diff options
Diffstat (limited to 'contrib/groff/src/devices/grolbp/lbp.cc')
-rw-r--r-- | contrib/groff/src/devices/grolbp/lbp.cc | 1038 |
1 files changed, 506 insertions, 532 deletions
diff --git a/contrib/groff/src/devices/grolbp/lbp.cc b/contrib/groff/src/devices/grolbp/lbp.cc index ec8c7b1..76db32a 100644 --- a/contrib/groff/src/devices/grolbp/lbp.cc +++ b/contrib/groff/src/devices/grolbp/lbp.cc @@ -1,5 +1,5 @@ // -*- C++ -*- -/* Copyright (C) 1994, 2000, 2001 Free Software Foundation, Inc. +/* Copyright (C) 1994, 2000, 2001, 2002 Free Software Foundation, Inc. Written by Francisco Andrés Verdú <pandres@dragonet.es> with many ideas taken from the other groff drivers. @@ -30,16 +30,22 @@ TODO #include "driver.h" #include "lbp.h" #include "charset.h" +#include "paper.h" #include "nonposix.h" extern "C" const char *Version_string; -static short int papersize = -1, // papersize - orientation = -1 , // orientation - paperlength = 0, // Custom Paper size - paperwidth = 0, - ncopies = 1; // Number of copies +static int user_papersize = -1; // papersize +static int orientation = -1; // orientation +static double user_paperlength = 0; // Custom Paper size +static double user_paperwidth = 0; +static int ncopies = 1; // Number of copies + +#define DEFAULT_LINEWIDTH_FACTOR 40 // 0.04em +static int linewidth_factor = DEFAULT_LINEWIDTH_FACTOR; + +static int set_papersize(const char *paperformat); class lbp_font : public font { public: @@ -55,7 +61,7 @@ private: class lbp_printer : public printer { public: - lbp_printer(); + lbp_printer(int, double, double); ~lbp_printer(); void set_char(int, font *, const environment *, int, const char *name); void draw(int code, int *p, int np, const environment *env); @@ -64,7 +70,7 @@ public: font *make_font(const char *); void end_of_line(); private: - void set_line_thickness(int size, int dot = 0); + void set_line_thickness(int size,const environment *env); void vdmstart(); void vdmflush(); // the name vdmend was already used in lbp.h void setfillmode(int mode); @@ -79,38 +85,27 @@ private: int cur_size; unsigned short cur_symbol_set; int line_thickness; + int req_linethickness; // requested line thickness + int papersize; + int paperlength; // custom paper size + int paperwidth; }; // Compatibility section. // -// Here we define some functions not present in some of the targets +// Here we define some functions not present in some of the targets // platforms #ifndef HAVE_STRSEP // Solaris 8 doesn't have the strsep function static char *strsep(char **pcadena, const char *delim) { char *p; - - p = strtok(*pcadena,delim); - *pcadena = strtok(NULL,delim); - return p; - -}; + p = strtok(*pcadena, delim); + *pcadena = strtok(NULL, delim); + return p; +} #endif -#ifndef HAVE_STRDUP -// Ditto with OS/390 and strdup -static char *strdup(const char *s) -{ - char *result; - - result = (char *)malloc(strlen(s)+1); - if (result != NULL) strcpy(result,s); - return result; - -}; // strdup - -#endif lbp_font::lbp_font(const char *nm) : font(nm) { @@ -124,12 +119,12 @@ lbp_font *lbp_font::load_lbp_font(const char *s) { lbp_font *f = new lbp_font(s); f->lbpname = NULL; - f->is_scalable = 1; // Default is that fonts are scalable + f->is_scalable = 1; // Default is that fonts are scalable if (!f->load()) { - delete f; - return 0; - } - return f; + delete f; + return 0; + } + return f; } @@ -138,64 +133,75 @@ void lbp_font::handle_unknown_font_command(const char *command, const char *filename, int lineno) { if (strcmp(command, "lbpname") == 0) { - if (arg == 0) - fatal_with_file_and_line(filename, lineno, - "`%1' command requires an argument", - command); - this->lbpname = new char[strlen(arg)+1]; - strcpy(this->lbpname,arg); - // We Recongnize bitmaped fonts by the first character of it's name - if (arg[0] == 'N') this->is_scalable = 0; - // fprintf(stderr,"Loading font \"%s\" \n",arg); - }; // if (strcmp(command, "lbpname") - // fprintf(stderr,"Loading font %s \"%s\" in %s at %d\n",command,arg,filename,lineno); -}; + if (arg == 0) + fatal_with_file_and_line(filename, lineno, + "`%1' command requires an argument", + command); + this->lbpname = new char[strlen(arg) + 1]; + strcpy(this->lbpname, arg); + // we recognize bitmapped fonts by the first character of its name + if (arg[0] == 'N') + this->is_scalable = 0; + // fprintf(stderr, "Loading font \"%s\" \n", arg); + } + // fprintf(stderr, "Loading font %s \"%s\" in %s at %d\n", + // command, arg, filename, lineno); +} static void wp54charset() { unsigned int i; - lbpputs("\033[714;100;29;0;32;120.}"); - for (i = 0; i < sizeof(symset) ; i++) lbpputc(symset[i]); + for (i = 0; i < sizeof(symset); i++) + lbpputc(symset[i]); lbpputs("\033[100;0 D"); - return ; -}; + return; +} -lbp_printer::lbp_printer() +lbp_printer::lbp_printer(int ps, double pw, double pl) : fill_pattern(1), fill_mode(0), cur_hpos(-1), cur_font(0), cur_size(0), cur_symbol_set(0), - line_thickness(-1) + req_linethickness(-1) { #ifdef SET_BINARY - SET_BINARY(fileno(stdout)); + SET_BINARY(fileno(stdout)); #endif - lbpinit(stdout); - lbpputs("\033c\033;\033[2&z\033[7 I\033[?32h\033[?33h\033[11h"); - wp54charset(); // Define the new symbol set - lbpputs("\033[7 I\033[?32h\033[?33h\033[11h"); - // Paper size handling - if (orientation < 0) orientation = 0;// Default orientation is portrait - if (papersize < 0) papersize = 14; // Default paper size is A4 - if (papersize < 80) // standard paper - lbpprintf("\033[%dp",(papersize | orientation)); - else // Custom paper - lbpprintf("\033[%d;%d;%dp",(papersize | orientation),\ - paperlength,paperwidth); - - // Number of copies - lbpprintf("\033[%dv\n",ncopies); - - lbpputs("\033[0u\033[1u\033P1y Grolbp\033\\"); - lbpmoveabs(0,0); - lbpputs("\033[0t\033[2t"); - lbpputs("\033('$2\033)' 1"); // Primary symbol set IBML - // Secondary symbol set IBMR1 - cur_symbol_set = 0; -}; + lbpinit(stdout); + lbpputs("\033c\033;\033[2&z\033[7 I\033[?32h\033[?33h\033[11h"); + wp54charset(); // Define the new symbol set + lbpputs("\033[7 I\033[?32h\033[?33h\033[11h"); + // Paper size handling + if (orientation < 0) + orientation = 0; // Default orientation is portrait + papersize = 14; // Default paper size is A4 + if (font::papersize) { + papersize = set_papersize(font::papersize); + paperlength = font::paperlength; + paperwidth = font::paperwidth; + } + if (ps >= 0) { + papersize = ps; + paperlength = int(pl * font::res + 0.5); + paperwidth = int(pw * font::res + 0.5); + } + if (papersize < 80) // standard paper + lbpprintf("\033[%dp", (papersize | orientation)); + else // Custom paper + lbpprintf("\033[%d;%d;%dp", (papersize | orientation), + paperlength, paperwidth); + // Number of copies + lbpprintf("\033[%dv\n", ncopies); + lbpputs("\033[0u\033[1u\033P1y Grolbp\033\\"); + lbpmoveabs(0, 0); + lbpputs("\033[0t\033[2t"); + lbpputs("\033('$2\033)' 1"); // Primary symbol set IBML + // Secondary symbol set IBMR1 + cur_symbol_set = 0; +} lbp_printer::~lbp_printer() { @@ -209,460 +215,415 @@ void lbp_printer::begin_page(int) void lbp_printer::end_page(int) { - if (vdminited()) vdmflush(); + if (vdminited()) + vdmflush(); lbpputc('\f'); cur_hpos = -1; } void lbp_printer::end_of_line() { - cur_hpos = -1; // force absolute motion + cur_hpos = -1; // force absolute motion } char *lbp_printer::font_name(const lbp_font *f, const int siz) { - static char bfont_name[255] ; // The resulting font name - char type, // Italic, Roman, Bold - ori, // Normal or Rotated - *nam; // The font name without other data. -// nam[strlen(f->lbpname)-2]; // The font name without other data. - int cpi; // The font size in characters per inch - // (Bitmaped fonts are monospaced). - - - /* Bitmap font selection is ugly in this printer, so don't expect - this function to be elegant. */ - + static char bfont_name[255]; // The resulting font name + char type, // Italic, Roman, Bold + ori, // Normal or Rotated + *nam; // The font name without other data. + int cpi; // The font size in characters per inch + // (bitmapped fonts are monospaced). + /* Bitmap font selection is ugly in this printer, so don't expect + this function to be elegant. */ bfont_name[0] = 0x00; - if (orientation) // Landscape - ori = 'R'; - else // Portrait - ori = 'N'; - type = f->lbpname[strlen(f->lbpname)-1]; - nam = new char[strlen(f->lbpname)-2]; - strncpy(nam,&(f->lbpname[1]),strlen(f->lbpname)-2); - nam[strlen(f->lbpname)-2] = 0x00; - // fprintf(stderr,"Bitmap font '%s' %d %c %c \n",nam,siz,type,ori); - /* Since these fonts are avaiable only at certain sizes, - 10 and 17 cpi for courier, 12 and 17 cpi for elite, - we adjust the resulting size. */ - cpi = 17; - // Fortunately there were only two bitmaped fonts shiped with the printer. - if (!strcasecmp(nam,"courier")) - { // Courier font - if (siz >= 12) cpi = 10; - else cpi = 17; - }; - if (!strcasecmp(nam,"elite")) - { // Elite font - if (siz >= 10) cpi = 12; - else cpi = 17; - }; - + if (orientation) // Landscape + ori = 'R'; + else // Portrait + ori = 'N'; + type = f->lbpname[strlen(f->lbpname) - 1]; + nam = new char[strlen(f->lbpname) - 2]; + strncpy(nam, &(f->lbpname[1]), strlen(f->lbpname) - 2); + nam[strlen(f->lbpname) - 2] = 0x00; + // fprintf(stderr, "Bitmap font '%s' %d %c %c \n", nam, siz, type, ori); + /* Since these fonts are available only at certain sizes, + 10 and 17 cpi for courier, 12 and 17 cpi for elite, + we adjust the resulting size. */ + cpi = 17; + // Fortunately there are only two bitmapped fonts shipped with the printer. + if (!strcasecmp(nam, "courier")) { + // Courier font + if (siz >= 12) + cpi = 10; + else cpi = 17; + } + if (!strcasecmp(nam, "elite")) { + if (siz >= 10) + cpi = 12; + else cpi = 17; + } // Now that we have all the data, let's generate the font name. if ((type != 'B') && (type != 'I')) // Roman font - sprintf(bfont_name,"%c%s%d",ori,nam,cpi); + sprintf(bfont_name, "%c%s%d", ori, nam, cpi); else - sprintf(bfont_name,"%c%s%d%c",ori,nam,cpi,type); - + sprintf(bfont_name, "%c%s%d%c", ori, nam, cpi, type); return bfont_name; - -}; // lbp_printer::font_name +} -void lbp_printer::set_char(int index, font *f, const environment *env, int w, const char *name) +void lbp_printer::set_char(int index, font *f, const environment *env, + int w, const char *name) { int code = f->get_code(index); - unsigned char ch = code & 0xff; unsigned short symbol_set = code >> 8; if (f != cur_font) { lbp_font *psf = (lbp_font *)f; - // fprintf(stderr,"Loading font %s \"%d\" \n",psf->lbpname,env->size); - if (psf->is_scalable) - { // Scalable font selection is different from bitmaped - lbpprintf("\033Pz%s.IBML\033\\\033[%d C",psf->lbpname,\ - (int)((env->size*300)/72)); - } else - { // Bitmaped font - lbpprintf("\033Pz%s.IBML\033\\\n",font_name(psf,env->size)); - }; - lbpputs("\033)' 1"); // Select IBML and IBMR1 symbol set - cur_size = env->size; + // fprintf(stderr, "Loading font %s \"%d\" \n", psf->lbpname, env->size); + if (psf->is_scalable) { + // Scalable font selection is different from bitmaped + lbpprintf("\033Pz%s.IBML\033\\\033[%d C", psf->lbpname, + (int)((env->size * font::res) / 72)); + } + else + // bitmapped font + lbpprintf("\033Pz%s.IBML\033\\\n", font_name(psf, env->size)); + lbpputs("\033)' 1"); // Select IBML and IBMR1 symbol set cur_font = psf; cur_symbol_set = 0; + // Update the line thickness if needed + if ((req_linethickness < 0 ) && (env->size != cur_size)) + set_line_thickness(req_linethickness,env); + cur_size = env->size; } if (symbol_set != cur_symbol_set) { - if ( cur_symbol_set == 3 ) { - // if current symbol set is Symbol we must restore the font - lbpprintf("\033Pz%s.IBML\033\\\033[%d C",cur_font->lbpname,\ - (int)((env->size*300)/72)); - }; // if ( cur_symbol_set == 3 ) + if (cur_symbol_set == 3) + // if current symbol set is Symbol we must restore the font + lbpprintf("\033Pz%s.IBML\033\\\033[%d C", cur_font->lbpname, + (int)((env->size * font::res) / 72)); switch (symbol_set) { - case 0: lbpputs("\033('$2\033)' 1"); // Select IBML and IBMR1 symbol sets - break; - case 1: lbpputs("\033(d\033)' 1"); // Select wp54 symbol set - break; - case 2: lbpputs("\033('$2\033)'!0"); // Select IBMP symbol set - break; - case 3: lbpprintf("\033PzSymbol.SYML\033\\\033[%d C",\ - (int)((env->size*300)/72)); - lbpputs("\033(\"!!0\033)\"!!1"); // Select symbol font - break; - case 4: lbpputs("\033)\"! 1\033(\"!$2"); // Select PS symbol set - break; - }; // switch (symbol_set) - -// if (symbol_set == 1) lbpputs("\033(d"); // Select wp54 symbol set -// else lbpputs("\033('$2\033)' 1"); // Select IBML and IBMR1 symbol sets + case 0: + lbpputs("\033('$2\033)' 1"); // Select IBML and IBMR1 symbol sets + break; + case 1: + lbpputs("\033(d\033)' 1"); // Select wp54 symbol set + break; + case 2: + lbpputs("\033('$2\033)'!0"); // Select IBMP symbol set + break; + case 3: + lbpprintf("\033PzSymbol.SYML\033\\\033[%d C", + (int)((env->size * font::res) / 72)); + lbpputs("\033(\"!!0\033)\"!!1"); // Select symbol font + break; + case 4: + lbpputs("\033)\"! 1\033(\"!$2"); // Select PS symbol set + break; + } cur_symbol_set = symbol_set; } if (env->size != cur_size) { - if (!cur_font->is_scalable) - lbpprintf("\033Pz%s.IBML\033\\\n",font_name(cur_font,env->size)); + lbpprintf("\033Pz%s.IBML\033\\\n", font_name(cur_font, env->size)); else - lbpprintf("\033[%d C",(int)((env->size*300)/72)); + lbpprintf("\033[%d C", (int)((env->size * font::res) / 72)); cur_size = env->size; + // Update the line thickness if needed + if (req_linethickness < 0 ) + set_line_thickness(req_linethickness,env); } - if ((env->hpos != cur_hpos) || (env->vpos != cur_vpos)) - { - // lbpmoveabs(env->hpos - ((5*300)/16),env->vpos ); - lbpmoveabs(env->hpos - 64,env->vpos - 64 ); - cur_vpos = env->vpos; - cur_hpos = env->hpos; - }; - if ((ch & 0x7F) < 32) lbpputs("\033[1.v"); + if ((env->hpos != cur_hpos) || (env->vpos != cur_vpos)) { + // lbpmoveabs(env->hpos - ((5 * 300) / 16), env->vpos); + lbpmoveabs(env->hpos - 64, env->vpos - 64); + cur_vpos = env->vpos; + cur_hpos = env->hpos; + } + if ((ch & 0x7F) < 32) + lbpputs("\033[1.v"); lbpputc(ch); cur_hpos += w; -}; +} -void -lbp_printer::vdmstart() +void lbp_printer::vdmstart() { FILE *f; static int changed_origin = 0; - - errno = 0; - f = tmpfile(); - // f = fopen("/tmp/gtmp","w+"); - if (f == NULL) perror("Openinig temp file"); - vdminit(f); - if (!changed_origin) { // we should change the origin only one time - changed_origin = 1; - vdmorigin(-63,0); - }; - vdmlinewidth(line_thickness); - -}; + errno = 0; + f = tmpfile(); + // f = fopen("/tmp/gtmp","w+"); + if (f == NULL) + perror("Opening temporary file"); + vdminit(f); + if (!changed_origin) { // we should change the origin only one time + changed_origin = 1; + vdmorigin(-63, 0); + } + vdmlinewidth(line_thickness); +} void lbp_printer::vdmflush() { char buffer[1024]; int bytes_read = 1; - vdmend(); fflush(lbpoutput); - /* lets copy the vdm code to the output */ + /* let's copy the vdm code to the output */ rewind(vdmoutput); - do - { - bytes_read = fread(buffer,1,sizeof(buffer),vdmoutput); - bytes_read = fwrite(buffer,1,bytes_read,lbpoutput); - } while ( bytes_read == sizeof(buffer)); - - fclose(vdmoutput); // This will also delete the file, - // since it is created by tmpfile() - vdmoutput = NULL; - -}; // lbp_printer::vdmflush - -inline void -lbp_printer::setfillmode(int mode) + do { + bytes_read = fread(buffer, 1, sizeof(buffer), vdmoutput); + bytes_read = fwrite(buffer, 1, bytes_read, lbpoutput); + } while (bytes_read == sizeof(buffer)); + fclose(vdmoutput); // This will also delete the file, + // since it is created by tmpfile() + vdmoutput = NULL; +} + +inline void lbp_printer::setfillmode(int mode) { if (mode != fill_mode) { - if (mode != 1) vdmsetfillmode(mode,1,0); - else vdmsetfillmode(mode,1,1); // To get black we must use white - // inverted - fill_mode = mode; - }; -}; // setfillmode + if (mode != 1) + vdmsetfillmode(mode, 1, 0); + else + vdmsetfillmode(mode, 1, 1); // To get black we must use white + // inverted + fill_mode = mode; + } +} -inline void -lbp_printer::polygon( int hpos,int vpos,int np,int *p) +inline void lbp_printer::polygon(int hpos, int vpos, int np, int *p) { - //int points[np+2],i; - int *points,i; - - points = new int[np+2]; - points[0] = hpos; - points[1] = vpos; -/* fprintf(stderr,"Poligon (%d,%d) ", points[0],points[1]);*/ - for (i = 0; i < np; i++) points[i+2] = p[i]; -/* for (i = 0; i < np; i++) fprintf(stderr," %d ",p[i]); - fprintf(stderr,"\n"); */ - vdmpolygon((np /2) + 1,points); -}; + int *points, i; + points = new int[np + 2]; + points[0] = hpos; + points[1] = vpos; + // fprintf(stderr, "Poligon (%d,%d) ", points[0], points[1]); + for (i = 0; i < np; i++) + points[i + 2] = p[i]; + // for (i = 0; i < np; i++) fprintf(stderr, " %d ", p[i]); + // fprintf(stderr, "\n"); + vdmpolygon((np /2) + 1, points); +} + +inline void lbp_printer::set_line_thickness(int size,const environment *env) +{ + if (size == 0) + line_thickness = 1; + else { + if (size < 0) + // line_thickness = + // (env->size * (font::res/72)) * (linewidth_factor/1000) + // we ought to check for overflow + line_thickness = + env->size * linewidth_factor * font::res / 72000; + else // size > 0 + line_thickness = size; + } // else from if (size == 0) + if (line_thickness < 1) + line_thickness = 1; + if (vdminited()) + vdmlinewidth(line_thickness); + req_linethickness = size; // an size requested + /* fprintf(stderr, "thickness: %d == %d, size %d, %d \n", + size, line_thickness, env->size,req_linethickness); */ + return; +}; // lbp_printer::set_line_thickness void lbp_printer::draw(int code, int *p, int np, const environment *env) { - switch (code) { - case 't': - if (np == 0) line_thickness = 1; - else { // troff gratuitously adds an extra 0 - if (np != 1 && np != 2) { - error("0 or 1 argument required for thickness"); - break; - } // if (np != ... - if (p[0] == 0) line_thickness = 1; - if (p[0] < 0) // Default = 1 point - line_thickness = (int)(env->size*30/72); - line_thickness = (int)((abs(p[0])*env->size)/10); - if ((line_thickness > 16 ) && (!vdminited())) - { /* for greater thickness we must use VDM */ - vdmstart(); - /* vdmlinewidth(line_thickness); already done in - * vdmstart() */ - }; - if (vdminited()) vdmlinewidth(line_thickness); - // fprintf(stderr,"\nthickness: %d == %d, size %d\n", - // p[0],line_thickness,env->size ); - } // else - break; - - case 'l': // Line - if (np != 2) { - error("2 arguments required for line"); - break; - }; - if (!vdminited()) vdmstart(); - vdmline(env->hpos,env->vpos,p[0],p[1]); - /*fprintf(stderr,"\nline: %d,%d - %d,%d thickness %d == %d\n",\ - env->hpos - 64,env->vpos -64, env->hpos - 64 + p[0],\ - env->vpos -64 + p[1],env->size, line_thickness);*/ - break; - case 'R': // Rule - if (np != 2) { - error("2 arguments required for Rule"); - break; - } - if (vdminited()) { - setfillmode(fill_pattern); // Solid Rule - vdmrectangle(env->hpos,env->vpos,p[0],p[1]); - } - else { - lbpruleabs(env->hpos - 64,env->vpos -64 , p[0], p[1]); - cur_vpos = p[1]; - cur_hpos = p[0]; - }; - fprintf(stderr,"\nrule: thickness %d == %d\n", env->size, line_thickness); - break; - case 'P': // Filled Polygon - if (!vdminited()) vdmstart(); - setfillmode(fill_pattern); - polygon(env->hpos,env->vpos,np,p); - break; - case 'p': // Empty Polygon - if (!vdminited()) vdmstart(); - setfillmode(0); - polygon(env->hpos,env->vpos,np,p); - break; - case 'C': // Filled Circle - if (!vdminited()) vdmstart(); - // fprintf(stderr,"Circle (%d,%d) Fill %d\n",env->hpos,env->vpos,fill_pattern); - setfillmode(fill_pattern); - vdmcircle(env->hpos + (p[0]/2),env->vpos,p[0]/2); - break; - case 'c': // Empty Circle - if (!vdminited()) vdmstart(); - setfillmode(0); - vdmcircle(env->hpos + (p[0]/2),env->vpos,p[0]/2); - break; - case 'E': // Filled Ellipse - if (!vdminited()) vdmstart(); - setfillmode(fill_pattern); - vdmellipse(env->hpos + (p[0]/2),env->vpos,p[0]/2,p[1]/2,0); - break; - case 'e': // Empty Ellipse - if (!vdminited()) vdmstart(); - setfillmode(0); - vdmellipse(env->hpos + (p[0]/2),env->vpos,p[0]/2,p[1]/2,0); - break; - case 'a': // Arc - if (!vdminited()) vdmstart(); - setfillmode(0); - // VDM draws arcs clockwise and pic counterclockwise - // We must compensate for that, exchanging the starting and - // ending points - vdmvarc(env->hpos + p[0],env->vpos+p[1],\ - int(sqrt( double((p[0]*p[0])+(p[1]*p[1])))),\ - p[2],p[3],\ - (-p[0]),(-p[1]),1,2); - break; - case '~': // Spline - if (!vdminited()) vdmstart(); - setfillmode(0); - vdmspline(np/2,env->hpos,env->vpos,p); - break; - case 'f': - if (np != 1 && np != 2) { - error("1 argument required for fill"); - break; - }; - // fprintf(stderr,"Fill %d\n",p[0]); - if ((p[0] == 1) || (p[0] >= 1000)) { // Black - fill_pattern = 1; - break; - }; // if (p[0] == 1) - if (p[0] == 0) { // White - fill_pattern = 0; - break; - }; - if ((p[0] > 1) && (p[0] < 1000)) - { - if (p[0] >= 990) fill_pattern = -23; - else if (p[0] >= 700) fill_pattern = -28; - else if (p[0] >= 500) fill_pattern = -27; - else if (p[0] >= 400) fill_pattern = -26; - else if (p[0] >= 300) fill_pattern = -25; - else if (p[0] >= 200) fill_pattern = -22; - else if (p[0] >= 100) fill_pattern = -24; - else fill_pattern = -21; - }; // if (p[0] >= 0 && p[0] <= 1000) - break; - default: - error("unrecognised drawing command `%1'", char(code)); - break; - }; // switch (code) - return ; -}; + if ((req_linethickness < 0 ) && (env->size != cur_size)) + set_line_thickness(req_linethickness,env); + + switch (code) { + case 't': + if (np == 0) + line_thickness = 1; + else { // troff gratuitously adds an extra 0 + if (np != 1 && np != 2) { + error("0 or 1 argument required for thickness"); + break; + }; + set_line_thickness(p[0],env); + }; + break; + case 'l': // Line + if (np != 2) { + error("2 arguments required for line"); + break; + } + if (!vdminited()) + vdmstart(); + vdmline(env->hpos, env->vpos, p[0], p[1]); +/* fprintf(stderr, "\nline: %d,%d - %d,%d thickness %d == %d\n", + env->hpos - 64,env->vpos -64, env->hpos - 64 + p[0], + env->vpos -64 + p[1], env->size, line_thickness);*/ + break; + case 'R': // Rule + if (np != 2) { + error("2 arguments required for Rule"); + break; + } + if (vdminited()) { + setfillmode(fill_pattern); // Solid Rule + vdmrectangle(env->hpos, env->vpos, p[0], p[1]); + } + else { + lbpruleabs(env->hpos - 64, env->vpos -64, p[0], p[1]); + cur_vpos = p[1]; + cur_hpos = p[0]; + } + // fprintf(stderr, "\nrule: thickness %d == %d\n", + // env->size, line_thickness); + break; + case 'P': // Filled Polygon + if (!vdminited()) + vdmstart(); + setfillmode(fill_pattern); + polygon(env->hpos, env->vpos, np, p); + break; + case 'p': // Empty Polygon + if (!vdminited()) + vdmstart(); + setfillmode(0); + polygon(env->hpos, env->vpos, np, p); + break; + case 'C': // Filled Circle + if (!vdminited()) + vdmstart(); + // fprintf(stderr, "Circle (%d,%d) Fill %d\n", + // env->hpos, env->vpos, fill_pattern); + setfillmode(fill_pattern); + vdmcircle(env->hpos + (p[0]/2), env->vpos, p[0]/2); + break; + case 'c': // Empty Circle + if (!vdminited()) + vdmstart(); + setfillmode(0); + vdmcircle(env->hpos + (p[0]/2), env->vpos, p[0]/2); + break; + case 'E': // Filled Ellipse + if (!vdminited()) + vdmstart(); + setfillmode(fill_pattern); + vdmellipse(env->hpos + (p[0]/2), env->vpos, p[0]/2, p[1]/2, 0); + break; + case 'e': // Empty Ellipse + if (!vdminited()) + vdmstart(); + setfillmode(0); + vdmellipse(env->hpos + (p[0]/2), env->vpos, p[0]/2, p[1]/2, 0); + break; + case 'a': // Arc + if (!vdminited()) + vdmstart(); + setfillmode(0); + // VDM draws arcs clockwise and pic counterclockwise + // We must compensate for that, exchanging the starting and + // ending points + vdmvarc(env->hpos + p[0], env->vpos+p[1], + int(sqrt(double((p[0]*p[0]) + (p[1]*p[1])))), + p[2], p[3], + (-p[0]), (-p[1]), 1, 2); + break; + case '~': // Spline + if (!vdminited()) + vdmstart(); + setfillmode(0); + vdmspline(np/2, env->hpos, env->vpos, p); + break; + case 'f': + if (np != 1 && np != 2) { + error("1 argument required for fill"); + break; + } + // fprintf(stderr, "Fill %d\n", p[0]); + if ((p[0] == 1) || (p[0] >= 1000)) { // Black + fill_pattern = 1; + break; + } + if (p[0] == 0) { // White + fill_pattern = 0; + break; + } + if ((p[0] > 1) && (p[0] < 1000)) + { + if (p[0] >= 990) fill_pattern = -23; + else if (p[0] >= 700) fill_pattern = -28; + else if (p[0] >= 500) fill_pattern = -27; + else if (p[0] >= 400) fill_pattern = -26; + else if (p[0] >= 300) fill_pattern = -25; + else if (p[0] >= 200) fill_pattern = -22; + else if (p[0] >= 100) fill_pattern = -24; + else fill_pattern = -21; + } + break; + case 'F': + // not implemented yet + break; + default: + error("unrecognised drawing command `%1'", char(code)); + break; + } + return; +} font *lbp_printer::make_font(const char *nm) { return lbp_font::load_lbp_font(nm); } - - printer *make_printer() { - return new lbp_printer; + return new lbp_printer(user_papersize, user_paperwidth, user_paperlength); } -static struct -{ - const char *name; - int code; -} papersizes[] = -{{ "A4", 14 }, -{ "letter", 30 }, -{ "legal", 32 }, -{ "executive", 40 }, -}; - +static struct { + const char *name; + int code; +} lbp_papersizes[] = + {{ "A4", 14 }, + { "letter", 30 }, + { "legal", 32 }, + { "executive", 40 }, + }; -static int set_papersize(const char *papersize) +static int set_papersize(const char *paperformat) { unsigned int i; - // First test for a standard (i.e. supported directly by the printer) - // papersize - for (i = 0 ; i < sizeof(papersizes)/sizeof(papersizes[0]); i++) + // paper size + for (i = 0 ; i < sizeof(lbp_papersizes) / sizeof(lbp_papersizes[0]); i++) { - if (strcasecmp(papersizes[i].name,papersize) == 0) - return papersizes[i].code; - }; - - // Now test for a custom papersize - if (strncasecmp("cust",papersize,4) == 0) - { - char *p , - *p1, - *papsize; - - p = papsize = strdup(&papersize[4]); - if (papsize == NULL) return -1; - p1 = strsep(&p,"x"); - if (p == NULL) - { // let's test for an uppercase x - p = papsize ; - p1 = strsep(&p,"X"); - if (p == NULL) { free(papsize); return -1;}; - }; // if (p1 == NULL) - paperlength = atoi(p1); - if (paperlength == 0) { free(papsize); return -1;}; - paperwidth = atoi(p); - if (paperwidth == 0) { free(papsize); return -1;}; - free(papsize); - return 82; - }; // if (strcnasecmp("cust",papersize,4) == 0) - - return -1; -}; - -static int handle_papersize_command(const char *arg) -{ - int n = set_papersize(arg); - - if (n < 0) - { // If is not a standard nor custom paper size - // let's see if it's a file (i.e /etc/papersize ) - FILE *f = fopen(arg,"r"); - if (f != NULL) - { // the file exists and is readable - char psize[255],*p; - fgets(psize,254,f); - fclose(f); - // set_papersize doesn't like the trailing \n - p = psize; while (*p) p++; - if (*(--p) == '\n') *p = 0x00; - - n = set_papersize(psize); - }; // if (f != NULL) - }; // if (n < 0) - - return n; -}; // handle_papersize_command - + if (strcasecmp(lbp_papersizes[i].name,paperformat) == 0) + return lbp_papersizes[i].code; + } + // Otherwise, we assume a custom paper size + return 82; +} static void handle_unknown_desc_command(const char *command, const char *arg, const char *filename, int lineno) { - // papersize command - if (strcasecmp(command, "papersize") == 0) { - // We give priority to command line options - if (papersize > 0) return; - if (arg == 0) - error_with_file_and_line(filename, lineno, - "`papersize' command requires an argument"); - else - { - int n = handle_papersize_command(arg); - if (n < 0) - error_with_file_and_line(filename, lineno, - "unknown paper size `%1'", arg); - else - papersize = n; - - }; // if (arg == 0) ... else ... - }; // if (strcasecmp(command, "papersize") - - // orientation command + // orientation command if (strcasecmp(command, "orientation") == 0) { // We give priority to command line options - if (orientation > 0) return; + if (orientation > 0) + return; if (arg == 0) error_with_file_and_line(filename, lineno, - "`papersize' command requires an argument"); + "`orientation' command requires an argument"); else { - if (strcasecmp(arg,"portrait") == 0) orientation = 0; - else { if (strcasecmp(arg,"landscape") == 0) orientation = 1; - else error_with_file_and_line(filename, lineno, - "`orientation' command requires an argument"); - }; - }; // if (arg == 0) ... else ... - }; // if (strcasecmp(command, "orientation") == 0) -}; + if (strcasecmp(arg, "portrait") == 0) + orientation = 0; + else { + if (strcasecmp(arg, "landscape") == 0) + orientation = 1; + else + error_with_file_and_line(filename, lineno, + "invalid argument to `orientation' command"); + } + } + } +} static struct option long_options[] = { { "orientation", required_argument, NULL, 'o' }, @@ -670,97 +631,110 @@ static struct option long_options[] = { { "copies", required_argument, NULL, 'c' }, { "landscape", no_argument, NULL, 'l' }, { "papersize", required_argument, NULL, 'p' }, + { "linewidth", required_argument, NULL, 'w' }, { "fontdir", required_argument, NULL, 'F' }, { "help", no_argument, NULL, 'h' }, { NULL, 0, 0, 0 } - }; +}; static void usage(FILE *stream) { fprintf(stream, - "usage: %s [-lvh] [-c n] [-p paper_size] [-F dir] [-o or] "\ - " [files ...]\n"\ - " -o --orientation=[portrait|landscape]\n"\ - " -v --version\n"\ - " -c --copies=numcopies\n"\ - " -l --landscape\n"\ - " -p --papersize=paper_size\n"\ - " -F --fontdir=dir\n"\ - " -h --help\n", + "usage: %s [-lvh] [-c n] [-p paper_size] [-F dir] [-o or]\n" + " [-w width] [files ...]\n" + "\n" + " -o --orientation=[portrait|landscape]\n" + " -v --version\n" + " -c --copies=numcopies\n" + " -l --landscape\n" + " -p --papersize=paper_size\n" + " -w --linewidth=width\n" + " -F --fontdir=dir\n" + " -h --help\n", program_name); -}; // usage +} int main(int argc, char **argv) { - if (program_name == NULL) program_name = strdup(argv[0]); - - font::set_unknown_desc_command_handler(handle_unknown_desc_command); - // command line parsing - int c = 0; - int option_index = 0; - - while (c >= 0 ) - { - c = getopt_long (argc, argv, "F:p:lvo:c:h",\ - long_options, &option_index); - switch (c) { - case 'F' : font::command_line_font_dir(optarg); - break; - case 'p' : { - int n = handle_papersize_command(optarg); - if (n < 0) - error("unknown paper size `%1'", optarg); - else - papersize = n; - break; - }; - case 'l' : orientation = 1; - break; - case 'v' : { - printf("GNU grolbp (groff) version %s\n", - Version_string); - exit(0); - break; - }; - case 'o' : { - if (strcasecmp(optarg,"portrait") == 0) - orientation = 0; - else { - if (strcasecmp(optarg,"landscape") == 0) - orientation = 1; - else - error("unknown orientation '%1'", optarg); - }; - break; - }; - case 'c' : { - char *ptr; - long n = strtol(optarg, &ptr, 10); - if ((n <= 0) && (ptr == optarg)) - error("argument for -c must be a positive integer"); - else if (n <= 0 || n > 32767) - error("out of range argument for -c"); - else - ncopies = unsigned(n); - break; - } - case 'h' : usage(stdout); - exit(0); - break; - case '?' : usage(stderr); - exit(1); - break; - - }; // switch (c) - }; // while (c > 0 ) - - if (optind >= argc) - do_file("-"); - - while (optind < argc) { - do_file(argv[optind++]); - }; - - lbpputs("\033c\033<"); - return 0; -}; + if (program_name == NULL) + program_name = strsave(argv[0]); + font::set_unknown_desc_command_handler(handle_unknown_desc_command); + // command line parsing + int c = 0; + int option_index = 0; + while (c >= 0) { + c = getopt_long (argc, argv, "F:p:lvo:c:hw:", + long_options, &option_index); + switch (c) { + case 'F': + font::command_line_font_dir(optarg); + break; + case 'p': + { + const char *s; + if (!font::scan_papersize(optarg, &s, + &user_paperlength, &user_paperwidth)) + error("invalid paper size `%1' ignored", optarg); + else + user_papersize = set_papersize(s); + break; + } + case 'l': + orientation = 1; + break; + case 'v': + printf("GNU grolbp (groff) version %s\n", Version_string); + exit(0); + break; + case 'o': + if (strcasecmp(optarg, "portrait") == 0) + orientation = 0; + else { + if (strcasecmp(optarg, "landscape") == 0) + orientation = 1; + else + error("unknown orientation '%1'", optarg); + }; + break; + case 'c': + { + char *ptr; + long n = strtol(optarg, &ptr, 10); + if ((n <= 0) && (ptr == optarg)) + error("argument for -c must be a positive integer"); + else if (n <= 0 || n > 32767) + error("out of range argument for -c"); + else + ncopies = unsigned(n); + break; + } + case 'w': + { + char *ptr; + long n = strtol(optarg, &ptr, 10); + if (n == 0 && ptr == optarg) + error("argument for -w must be a non-negative integer"); + else if (n < 0 || n > INT_MAX) + error("out of range argument for -w"); + else + linewidth_factor = int(n); + break; + } + case 'h': + usage(stdout); + exit(0); + break; + case '?': + usage(stderr); + exit(1); + break; + } + } + if (optind >= argc) + do_file("-"); + while (optind < argc) + do_file(argv[optind++]); + lbpputs("\033c\033<"); + delete pr; + return 0; +} |