Graphviz  2.29.20120524.0446
lib/common/hpglgen.c
Go to the documentation of this file.
00001 /* $Id$ $Revision$ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /*************************************************************************
00005  * Copyright (c) 2011 AT&T Intellectual Property 
00006  * All rights reserved. This program and the accompanying materials
00007  * are made available under the terms of the Eclipse Public License v1.0
00008  * which accompanies this distribution, and is available at
00009  * http://www.eclipse.org/legal/epl-v10.html
00010  *
00011  * Contributors: See CVS logs. Details at http://www.graphviz.org/
00012  *************************************************************************/
00013 
00014 
00015 /* TODO:
00016  *  Use encoded form for polyline and polygon
00017  */
00018 #include <ctype.h>
00019 #include "render.h"
00020 
00021 #define SOLID  0
00022 #define DOTTED 1
00023 #define DASHED 2
00024 #define INVIS  3
00025   /* Convert point (1/72 inch) to hpgl units (0.025 mm) */
00026 #define PT2UNIT(p)  ((p)*(double)14.111)
00027 #define PENW 0.0138
00028 #define NPENS  32
00029 #define CX(_x)   ((int)(_x))
00030 #define CY(_y)   ((int)(_y))
00031 
00032     /* Origin of HP plotter from lower left corner, in points
00033      * This varies from plotter to plotter. We assume 1/4" and 
00034      * hope for the best.
00035      */
00036 #define HP_OX     18
00037 #define HP_OY     18
00038 
00039 static char *raw_prefix = "";
00040 static char *raw_suffix = "";
00041 #ifdef NOTUSED_ERG_MUST_KNOW_WHY
00042 static char *clr_prefix = "\033%-12345X@PJL ENTER LANGUAGE = HPGL2\n";
00043 static char *clr_suffix = "\033%-12345X\n";
00044 #endif
00045 static char *pcl_prefix = "\033E\n\033%%0B\n";
00046 static char *pcl_suffix = "\033%%0A\n";
00047 
00048 static int N_pages;
00049 /* static       point   Pages; */
00050 static double Scale;
00051 static point Origin;
00052 static box PB;
00053 static int CurrentPen;
00054 static int ColorsUsed;
00055 static char *Sep = ";";
00056 static int PageWidth;           /* Width of page, in points. */
00057 static char *prefix;            /* Machine-dependent prefix and suffix */
00058 static char *suffix;
00059 /* static boolean       onetime = TRUE; */
00060 
00061 #define MAXLINELEN   80
00062 static int bufcnt;              /* Number of characters output on current line */
00063 static char *text_hdr = "LB";
00064 static void output(char *str)
00065 {
00066     char *ptr = str;
00067     int len;
00068 
00069     while (*ptr != '\0')
00070         ptr++;
00071     len = ptr - str;
00072     if (bufcnt + len > MAXLINELEN) {
00073         fputs("\n", Output_file);
00074         bufcnt = 0;
00075     }
00076     fputs(str, Output_file);
00077     if ((len > 0) && (*(ptr - 1) == '\n'))
00078         bufcnt = 0;
00079     else
00080         bufcnt += len;
00081 }
00082 
00083 static void output_text(char *str)
00084 {
00085     char *ptr = str;
00086     int len;
00087     char text_tail[32];
00088 
00089     sprintf(text_tail, "\03%s\n", Sep);
00090     while (*ptr != '\0')
00091         ptr++;
00092     len = (ptr - str) + strlen(text_tail) + strlen(text_hdr);
00093     if (bufcnt + len > MAXLINELEN) {
00094         fputs("\n", Output_file);
00095     }
00096     fputs(text_hdr, Output_file);
00097     fputs(str, Output_file);
00098     fputs(text_tail, Output_file);
00099     bufcnt = 0;
00100 }
00101 
00102 #ifdef SMILE
00103 void doSmile(void)
00104 {
00105     fprintf(Output_file,
00106             "SP1SD1,341,2,1,4,14,5,0,6,0,7,5SSLO7PA%d,0LB\001\003IN\n",
00107             (int) PT2UNIT(PageWid - 2 * HP_OX));
00108 
00109 }
00110 #endif
00111 
00112 static void setPen(int p)
00113 {
00114     char buffer[32];
00115     sprintf(buffer, "SP%d%s", p, Sep);
00116     output(buffer);
00117 #ifdef HPDEBUG
00118     fprintf(stderr, "set pen %d\n", p);
00119 #endif
00120     CurrentPen = p;
00121 }
00122 
00123 typedef struct {
00124     int symbol;
00125     int spacing;
00126     int face;
00127     int bold;
00128     int italic;
00129     double size;
00130 } FontInfo;
00131 static FontInfo dfltFont = { 277, 1, 5, 0, 0, 14.0 };
00132 static FontInfo coordFont = { 277, 1, 5, 0, 0, 8.0 };
00133 static FontInfo nullFont = { 0, 0, 0, 0, 0, 0.0 };
00134 
00135   /* Font 0 is the stdfont; font 1 is the alt font */
00136 typedef struct {
00137     FontInfo fonts[2];
00138     int curfont;
00139 } FontState;
00140 static FontState fontState;
00141 
00142 static int eqFontInfo(FontInfo * fi1, FontInfo * fi2)
00143 {
00144     return ((fi1->face == fi2->face) &&
00145             (fi1->spacing == fi2->spacing) &&
00146             (fi1->bold == fi2->bold) &&
00147             (fi1->italic == fi2->italic) &&
00148             (fi1->size == fi2->size) && (fi1->symbol == fi2->symbol));
00149 }
00150 
00151 typedef struct {
00152     unsigned char r, g, b;
00153 } Color;
00154 
00155 static int eqColor(Color * c1, Color * c2)
00156 {
00157     return ((c1->r == c2->r) && (c1->g == c2->g) && (c1->b == c2->b));
00158 }
00159 
00160 static Color black = { 0, 0, 0 };
00161 static Color white = { 255, 255, 255 };
00162 static Color *colorlist;
00163 
00164 typedef struct GC_s {
00165     int bold;
00166     int style;
00167     Color color;
00168     FontInfo font;
00169     struct GC_s *prev;
00170 } GC_t;
00171 static GC_t *curGC;
00172 
00173 static void set_color(Color * cp)
00174 {
00175     int i;
00176     char buffer[32];
00177 
00178     if (eqColor(cp, &curGC->color))
00179         return;
00180     for (i = 0; i < ColorsUsed; i++) {
00181         if (eqColor(cp, &colorlist[i]))
00182             break;
00183     }
00184     if (i == ColorsUsed) {
00185         if (ColorsUsed == NPENS)
00186             i--;
00187         else
00188             ColorsUsed++;
00189         sprintf(buffer, "PC%d,%d,%d,%d%s", i, cp->r, cp->g, cp->b, Sep);
00190         colorlist[i] = *cp;
00191         output(buffer);
00192 #ifdef HPDEBUG
00193         fprintf(stderr, "set pen %d color %d %d %d\n", i, cp->r, cp->g,
00194                 cp->b);
00195 #endif
00196     }
00197     setPen(i);
00198     curGC->color = *cp;
00199 }
00200 
00201 static void initColors(void)
00202 {
00203     colorlist = N_GNEW(NPENS, Color);
00204     colorlist[0] = white;
00205     colorlist[1] = black;
00206     ColorsUsed = 2;
00207 }
00208 
00209 static void destroyColors(void)
00210 {
00211     free(colorlist);
00212     ColorsUsed = 0;
00213 }
00214 
00215 static void setFont(FontInfo * fi)
00216 {
00217     int otherfont;
00218     char buffer[128];
00219 
00220     if (eqFontInfo(fi, &fontState.fonts[fontState.curfont]))
00221         return;
00222     otherfont = (fontState.curfont ? 0 : 1);
00223 
00224     if (!eqFontInfo(fi, &fontState.fonts[otherfont])) {
00225         if (fi->spacing)
00226             sprintf(buffer, "%s1,%d,2,1,4,%.1f,5,%d,6,%d,7,%d%s",
00227                     (otherfont ? "AD" : "SD"), fi->symbol,
00228                     Scale * (fi->size), fi->italic, fi->bold, fi->face,
00229                     Sep);
00230         else
00231             sprintf(buffer, "%s1,%d,2,0,3,%.1f,5,%d,6,%d,7,%d%s",
00232                     (otherfont ? "AD" : "SD"), fi->symbol,
00233                     (fi->size) / Scale, fi->italic, fi->bold, fi->face,
00234                     Sep);
00235         output(buffer);
00236     }
00237     sprintf(buffer, "%s%s\n", (otherfont ? "SA" : "SS"), Sep);
00238     output(buffer);
00239     fontState.curfont = otherfont;
00240     fontState.fonts[otherfont] = *fi;
00241     curGC->font = *fi;
00242 }
00243 
00244 static void set_line_bold(int on)
00245 {
00246     char buffer[32];
00247 
00248     if (on) {
00249         sprintf(buffer, "PW%.3f%s\n", 2 * PENW, Sep);
00250         curGC->bold = TRUE;
00251     } else {
00252         sprintf(buffer, "PW%.3f%s\n", PENW, Sep);
00253         curGC->bold = FALSE;
00254     }
00255     output(buffer);
00256 }
00257 
00258 static void set_line_style(int sty)
00259 {
00260     char buffer[8];
00261     char *opt = NULL;
00262 
00263     curGC->style = sty;
00264     switch (sty) {
00265     case SOLID:
00266         opt = "LT";
00267         break;
00268     case DOTTED:
00269         opt = "LT1";
00270         break;
00271     case DASHED:
00272         opt = "LT2";
00273         break;
00274     case INVIS:
00275     default:
00276         return;
00277     }
00278     sprintf(buffer, "%s%s", opt, Sep);
00279     output(buffer);
00280 }
00281 
00282 static GC_t *makeGC(GC_t * old)
00283 {
00284     GC_t *newGC;
00285     newGC = GNEW(GC_t);
00286     if (old)
00287         *newGC = *old;
00288     else {
00289         newGC->bold = FALSE, newGC->style = SOLID, newGC->color = black;
00290         newGC->font = dfltFont;
00291     }
00292     newGC->prev = 0;
00293     return newGC;
00294 }
00295 
00296 static void initGC(void)
00297 {
00298     char buffer[32];
00299 
00300     curGC = makeGC(0);
00301     /* Pick pen 1; set default pen width; set colors
00302      */
00303     sprintf(buffer, "SP1%sPW%.3f%s\n", Sep, PENW, Sep);
00304     output(buffer);
00305     fontState.curfont = 1;
00306     setFont(&dfltFont);
00307     CurrentPen = 1;
00308     initColors();
00309 }
00310 
00311 static void destroyGC(void)
00312 {
00313     GC_t *gc, *gc1;
00314     for (gc = curGC; gc; gc = gc1) {
00315         gc1 = gc->prev;
00316         free(gc);
00317     }
00318     curGC = 0;
00319     fontState.fonts[0] = nullFont;
00320     fontState.fonts[1] = nullFont;
00321     fontState.curfont = 1;
00322     destroyColors();
00323 }
00324 
00325 static void saveGC(void)
00326 {
00327     GC_t *newGC;
00328     newGC = makeGC(curGC);
00329     newGC->prev = curGC;
00330     curGC = newGC;
00331 }
00332 
00333 static void restoreGC(void)
00334 {
00335     GC_t *gc, *newGC;
00336     gc = curGC;
00337     newGC = gc->prev;
00338     if (gc->bold != newGC->bold)
00339         set_line_bold(newGC->bold);
00340     if (gc->style != newGC->style)
00341         set_line_style(newGC->style);
00342     if (!eqColor(&gc->color, &newGC->color)) {
00343 #ifdef HPDEBUG
00344         fprintf(stderr, "restore color\n");
00345 #endif
00346         set_color(&newGC->color);
00347     }
00348     if (!eqFontInfo(&gc->font, &newGC->font))
00349         setFont(&newGC->font);
00350     free(gc);
00351     curGC = newGC;
00352 }
00353 
00354 static int isInvis(void)
00355 {
00356     return (curGC->style == INVIS);
00357 }
00358 
00359 #if 0                           /* not used */
00360 static double _Xalign;
00361 #define getTextAlign() (_Xalign)
00362 static void initTextAlign(void)
00363 {
00364     char buffer[20];
00365     _Xalign = -0.5;
00366     sprintf(buffer, "LO4%s", Sep);
00367     output(buffer);
00368 }
00369 
00370 static int setTextAlign(double al)
00371 {
00372     char buffer[20];
00373     char opt;
00374 
00375     if (al == 0.0)
00376         opt = '1';
00377     else if (al == -1.0)
00378         opt = '7';
00379     else if (al == -0.5)
00380         opt = '4';
00381     else
00382         return 0;
00383 
00384     sprintf(buffer, "LO%c%s", opt, Sep);
00385     output(buffer);
00386     _Xalign = al;
00387     return 1;
00388 }
00389 #endif
00390 
00391 static void hpgl_reset(void)
00392 {
00393     /* onetime = TRUE; */
00394 }
00395 
00396 static void
00397 hpgl_begin_job(FILE * ofp, graph_t * g, const char **lib, char *info[], point pages)
00398 {
00399     /* Pages = pages; */
00400     N_pages = pages.x * pages.y;
00401 }
00402 
00403 static void hpgl_begin_graph(GVC_t * gvc, graph_t * g, box bb, point pb)
00404 {
00405     PB = bb;
00406     PageWidth = pb.x;
00407     if (Output_lang == PCL) {
00408         prefix = pcl_prefix;
00409         suffix = pcl_suffix;
00410     } else {
00411         prefix = raw_prefix;
00412         suffix = raw_suffix;
00413     }
00414 }
00415 
00416 static void hpgl_set_scale(double scx, double scy)
00417 {
00418     char buffer[64];
00419     sprintf(buffer, "SC%.4f,%.4f,%.4f,%.4f,2%s\n",
00420             -Origin.x / scx, PT2UNIT(scx), -Origin.y / scy, PT2UNIT(scy),
00421             Sep);
00422     output(buffer);
00423 }
00424 
00425 static void hpgl_begin_page(graph_t * g, point page, double scale, int rot,
00426                             point offset)
00427 {
00428     char buffer[64];
00429     box clipWin;
00430 
00431     bufcnt = 0;
00432     Scale = scale;
00433 
00434     /* Initialize output */
00435     output(prefix);
00436     sprintf(buffer, "BP%sIN%s", Sep, Sep);
00437     output(buffer);
00438 #ifdef SMILE
00439     doSmile();
00440 #endif
00441 #if 0                           /* not used */
00442     initTextAlign();
00443 #endif
00444     initGC();
00445 
00446     if (N_pages > 1) {
00447         saveGC();
00448         setFont(&coordFont);
00449         if (rot == 90) {
00450             sprintf(buffer, "RO90IP%s", Sep);
00451             output(buffer);
00452         }
00453         sprintf(buffer, "PA0,0%sLB(%d,%d)\03%s\n", Sep, page.x, page.y,
00454                 Sep);
00455         output(buffer);
00456         if (rot == 90) {
00457             sprintf(buffer, "ROIP%s", Sep);
00458             output(buffer);
00459         }
00460         restoreGC();
00461     }
00462 
00463     if (rot == 90) {
00464         /* Rotate layout. HPGL/2 automatically shifts
00465          * origin to bottom right corner, so we have to
00466          * use the page width to set the new origin.
00467          */
00468         sprintf(buffer, "RO90IP%s", Sep);
00469         output(buffer);
00470 
00471         clipWin.LL.x = PB.LL.y - HP_OY - 1;
00472         clipWin.LL.y = PageWidth - PB.UR.x - HP_OX - 1;
00473         clipWin.UR.x = PB.UR.y - HP_OY + 1;
00474         clipWin.UR.y = PageWidth - PB.LL.x - HP_OX + 1;
00475         Origin.x = PB.LL.y + scale * offset.y - HP_OY;
00476         Origin.y = PageWidth - PB.LL.x - scale * offset.x - HP_OX;
00477     } else {
00478         clipWin.LL.x = PB.LL.x - HP_OX - 1;
00479         clipWin.LL.y = PB.LL.y - HP_OY - 1;
00480         clipWin.UR.x = PB.UR.x - HP_OX + 1;
00481         clipWin.UR.y = PB.UR.y - HP_OY + 1;
00482         Origin.x = PB.LL.x + scale * offset.x - HP_OX;
00483         Origin.y = PB.LL.y + scale * offset.y - HP_OY;
00484     }
00485     /* Set clipping window */
00486     sprintf(buffer, "IW%d,%d,%d,%d%s\n",
00487             (int) PT2UNIT(clipWin.LL.x), (int) PT2UNIT(clipWin.LL.y),
00488             (int) PT2UNIT(clipWin.UR.x), (int) PT2UNIT(clipWin.UR.y), Sep);
00489     /* output(buffer); *//* Turn off clipping. */
00490     hpgl_set_scale(scale, scale);
00491 
00492 }
00493 
00494 static void hpgl_end_page(void)
00495 {
00496     char buffer[32];
00497 
00498     sprintf(buffer, "PU%sSP0%sPG;\n", Sep, Sep);        /* pen up; advance page */
00499     output(buffer);
00500     output(suffix);
00501     destroyGC();
00502 }
00503 
00504 static void hpgl_begin_context(void)
00505 {
00506     saveGC();
00507 }
00508 
00509 static void hpgl_end_context(void)
00510 {
00511     restoreGC();
00512 }
00513 
00514 static void mkFontCanon(unsigned char *old, unsigned char *new)
00515 {
00516     unsigned char c;
00517     while ((c = *old++)) {
00518         if (isalnum(c) == FALSE)
00519             continue;
00520         if (isupper(c))
00521             c = tolower(c);
00522         *new++ = c;
00523     }
00524     *new = c;
00525 }
00526 
00527   /* factors for turning font size, in points,
00528    * to pitches, in chars per inch, for fixed pitch fonts.
00529    */
00530 static double courierPitch = 110.76923;
00531 static double stickPitch = 102.85714;
00532 
00533 typedef struct {
00534     char *name;
00535     int symbol;
00536     double *spacing;
00537     int face;
00538     int italic;
00539     int bold;
00540 } FontIndex;
00541 static FontIndex fontIndex[] = {
00542     {"timesroman", 277, 0, 5, 0, 0},
00543     {"timesbold", 277, 0, 5, 0, 3},
00544     {"timesitalic", 277, 0, 5, 1, 0},
00545     {"timesbolditalic", 277, 0, 5, 1, 3},
00546     {"helvetica", 277, 0, 4, 0, 0},
00547     {"helveticabold", 277, 0, 4, 0, 3},
00548     {"helveticaoblique", 277, 0, 4, 1, 0},
00549     {"helveticaboldoblique", 277, 0, 4, 1, 3},
00550     {"courier", 277, &courierPitch, 3, 0, 0},
00551     {"courierbold", 277, &courierPitch, 3, 0, 3},
00552     {"courieroblique", 277, &courierPitch, 3, 1, 0},
00553     {"courierboldoblique", 277, &courierPitch, 3, 1, 3},
00554     {"palatinoroman", 277, 0, 15, 0, 0},
00555     {"palatinobold", 277, 0, 15, 0, 3},
00556     {"palatinoitalic", 277, 0, 15, 1, 0},
00557     {"palatinobolditalic", 277, 0, 15, 1, 3},
00558     {"stickcw", 277, &stickPitch, 48, 0, 0},
00559     {"stick", 277, 0, 48, 0, 0},
00560     {"zapfdingbats", 332, 0, 45, 0, 0},
00561     {"symbol", 173, 0, 5, 0, 0}
00562 };
00563 
00564 static void mkFontInfo(char *name, double size, FontInfo * fip)
00565 {
00566     int i;
00567     char buf[128];
00568     FontIndex *fi;
00569 
00570     mkFontCanon((unsigned char *) name, (unsigned char *) buf);
00571     fi = fontIndex;
00572     for (i = 0; i < sizeof(fontIndex) / sizeof(FontIndex) - 1; i++) {
00573         if (streq(buf, fi->name))
00574             break;
00575         fi++;
00576     }
00577     fip->symbol = fi->symbol;
00578     fip->italic = fi->italic;
00579     fip->bold = fi->bold;
00580     fip->face = fi->face;
00581     if (fi->spacing) {          /* fixed spacing */
00582         fip->spacing = 0;
00583         fip->size = (*(fi->spacing)) / size;
00584     } else {                    /* proportional spacing */
00585         fip->spacing = 1;
00586         fip->size = size;
00587     }
00588 }
00589 
00590 static void hpgl_set_font(char *name, double size)
00591 {
00592     static FontInfo fi;
00593 
00594     mkFontInfo(name, size, &fi);
00595     setFont(&fi);
00596 }
00597 
00598 static void hpgl_set_color(char *name)
00599 {
00600     gvcolor_t color;
00601 
00602 #ifdef HPDEBUG
00603     fprintf(stderr, "set color %s\n", name);
00604 #endif
00605     colorxlate(name, &color, RGBA_BYTE);
00606     set_color((Color *) color.u.rgba);
00607 }
00608 
00609 static void hpgl_set_style(char **s)
00610 {
00611     char *line;
00612 
00613     while ((line = *s++)) {
00614         if (streq(line, "solid"))
00615             set_line_style(SOLID);
00616         else if (streq(line, "dashed"))
00617             set_line_style(DASHED);
00618         else if (streq(line, "dotted"))
00619             set_line_style(DOTTED);
00620         else if (streq(line, "invis"))
00621             set_line_style(INVIS);
00622         else if (streq(line, "bold"))
00623             set_line_bold(TRUE);
00624         else if (streq(line, "filled")) {       /* no-op */
00625         } else if (streq(line, "unfilled")) {   /* no-op */
00626         } else {
00627             agerr(AGERR,
00628                   "hpgl_set_style: unsupported style %s - ignoring\n",
00629                   line);
00630         }
00631     }
00632 }
00633 
00634 static void hpgl_textpara(point p, textpara_t * para)
00635 {
00636     char buffer[128];
00637 
00638     if (isInvis())
00639         return;
00640 
00641     switch (para->just) {
00642     case 'l':
00643         break;
00644     case 'r':
00645         p.x -= para->width;
00646         break;
00647     default:
00648     case 'n':
00649         p.x -= para->width / 2;
00650         break;
00651     }
00652 
00653     sprintf(buffer, "PA%d,%d%s", CX(p.x), CY(p.y), Sep);
00654     output(buffer);
00655     output_text(para->str);
00656 
00657 #ifdef HPDEBUG
00658     fprintf(stderr, "text =%s=\n", para->str);
00659 #endif
00660 }
00661 
00662 static int firstSeg;
00663 #define FLATNESS  1.0
00664 static int isFlat(double x0, double y0, double x1, double y1, double x2,
00665                   double y2, double x3, double y3)
00666 {
00667     double sa, ca, y, O = y3 - y0, A = x3 - x0, H = sqrt(O * O + A * A);
00668 
00669     if (H == 0)
00670         return TRUE;
00671 
00672     sa = O / H, ca = A / H;
00673     y = -sa * (x1 - x0) + ca * (y1 - y0);
00674     if (y > FLATNESS || y < -FLATNESS)
00675         return FALSE;
00676     y = -sa * (x2 - x0) + ca * (y2 - y0);
00677     return y <= FLATNESS && y >= -FLATNESS;
00678 }
00679 
00680 static void Bzier(double x0, double y0, double x1, double y1, double x2,
00681                   double y2, double x3, double y3)
00682 {
00683     char buffer[64];
00684     if (isFlat(x0, y0, x1, y1, x2, y2, x3, y3)) {
00685         if (firstSeg) {
00686             sprintf(buffer, "%d,%d", CX(x3), CY(y3));
00687             firstSeg = 0;
00688         } else {
00689             sprintf(buffer, ",%d,%d", CX(x3), CY(y3));
00690         }
00691         output(buffer);
00692         return;
00693     }
00694     Bzier(x0, y0,
00695           (x0 + x1) / 2, (y0 + y1) / 2,
00696           (x0 + x2) / 4 + x1 / 2, (y0 + y2) / 4 + y1 / 2,
00697           (x0 + x3) / 8 + 3 * (x1 + x2) / 8,
00698           (y0 + y3) / 8 + 3 * (y1 + y2) / 8);
00699     Bzier((x0 + x3) / 8 + 3 * (x1 + x2) / 8,
00700           (y0 + y3) / 8 + 3 * (y1 + y2) / 8, (x1 + x3) / 4 + x2 / 2,
00701           (y1 + y3) / 4 + y2 / 2, (x2 + x3) / 2, (y2 + y3) / 2, x3, y3);
00702 
00703 }
00704 
00705 static void hpgl_bezier(point * A, int n, int arrow_at_start,
00706                         int arrow_at_end, int filled)
00707 {
00708     char buffer[32];
00709     int j;
00710 
00711     if (arrow_at_start || arrow_at_end)
00712         agerr(AGERR, "hpgl_bezier illegal arrow args\n");
00713     if (isInvis())
00714         return;
00715     sprintf(buffer, "PA%d,%d%sPD", CX(A[0].x), CY(A[0].y), Sep);
00716     output(buffer);
00717     firstSeg = 1;
00718     for (j = 1; j < n; j += 3)
00719         Bzier((double) A[j - 1].x, (double) A[j - 1].y,
00720               (double) A[j].x, (double) A[j].y,
00721               (double) A[j + 1].x, (double) A[j + 1].y,
00722               (double) A[j + 2].x, (double) A[j + 2].y);
00723     sprintf(buffer, "%sPU%s\n", Sep, Sep);
00724     output(buffer);
00725 }
00726 
00727 static void hpgl_polygon(point * A, int n, int filled)
00728 {
00729     int j;
00730     char buffer[64];
00731 
00732     if (isInvis())
00733         return;
00734     sprintf(buffer, "PA%d,%d%sPM0%sPD", CX(A[0].x), CY(A[0].y), Sep, Sep);
00735     output(buffer);
00736     for (j = 1; j < n - 1; j++) {
00737         sprintf(buffer, "%d,%d,", CX(A[j].x), CY(A[j].y));
00738         output(buffer);
00739     }
00740     sprintf(buffer, "%d,%d%sPM2%sPU%s", CY(A[n - 1].x), CY(A[n - 1].y),
00741             Sep, Sep, Sep);
00742     output(buffer);
00743     if (filled) {
00744 #ifdef HPDEBUG
00745         fprintf(stderr, "fill pen %d\n", CurrentPen);
00746 #endif
00747         if (CurrentPen == 1) {
00748             sprintf(buffer, "FP%sLT%sEP%sLT99%s\n", Sep, Sep, Sep, Sep);
00749         } else {
00750             sprintf(buffer, "FP%sSP1%sLT%sEP%sSP%d%sLT99%s\n",
00751                     Sep, Sep, Sep, Sep, CurrentPen, Sep, Sep);
00752         }
00753     } else {
00754         sprintf(buffer, "EP%s\n", Sep);
00755     }
00756     output(buffer);
00757 }
00758 
00759 /***** Arrowheads now centralized in emit.c
00760 static void hpgl_arrowhead(point p,double theta,double scale,int flag)
00761 {
00762     point   sp,ep;
00763     double  costh, sinth,arroww2,arrowl;
00764     char    buffer[128];
00765 
00766     if (isInvis()) return;
00767     costh = cos(RADIANS(theta));
00768     sinth = sin(RADIANS(theta));
00769         arrowl = ARROW_LENGTH * scale;
00770         arroww2 = ARROW_WIDTH * scale / 2.0;
00771     sp.x = p.x + arrowl*costh + arroww2*sinth;
00772     sp.y = p.y + arrowl*sinth - arroww2*costh;
00773     ep.x = p.x + arrowl*costh - arroww2*sinth;
00774     ep.y = p.y + arrowl*sinth + arroww2*costh;
00775         sprintf(buffer,"PA%d,%d%sPM0%sPD%d,%d,%d,%d%sPM2%sPU%sFP%s\n",
00776       CX(sp.x),CY(sp.y),Sep,Sep,
00777       CX(p.x),CY(p.y),CX(ep.x),CY(ep.y), Sep, Sep, Sep, Sep);
00778     output(buffer);
00779 }
00780 **********/
00781 
00782 static void hpgl_ellipse(point p, int rx, int ry, int filled)
00783 {
00784     char buffer[128];
00785 
00786     if (isInvis())
00787         return;
00788     sprintf(buffer, "PA%d,%d%s", p.x, p.y, Sep);
00789     output(buffer);
00790     hpgl_set_scale(Scale * rx, Scale * ry);
00791     if (filled) {
00792         if (CurrentPen == 1)
00793             sprintf(buffer, "WG1,0,360%sLT%sEW1,0,360%sLT99%s", Sep, Sep,
00794                     Sep, Sep);
00795         else
00796             sprintf(buffer, "WG1,0,360%sSP1%sLT%sEW1,0,360%sSP%d%sLT99%s",
00797                     Sep, Sep, Sep, Sep, CurrentPen, Sep, Sep);
00798     } else
00799         sprintf(buffer, "EW1,0,360%s", Sep);
00800     output(buffer);
00801     hpgl_set_scale(Scale, Scale);
00802 }
00803 
00804 /* Use encoded form */
00805 static void hpgl_polyline(point * A, int n)
00806 {
00807     int j;
00808     char buffer[64];
00809 
00810     if (isInvis())
00811         return;
00812     sprintf(buffer, "PA%d,%d%sPD", CX(A[0].x), CY(A[0].y), Sep);
00813     output(buffer);
00814     for (j = 1; j < n - 1; j++) {
00815         sprintf(buffer, "%d,%d,", CX(A[j].x), CY(A[j].y));
00816         output(buffer);
00817     }
00818     sprintf(buffer, "%d,%d%sPU%s\n", CX(A[n - 1].x), CY(A[n - 1].y), Sep,
00819             Sep);
00820     output(buffer);
00821 }
00822 
00823 static void hpgl_usershape(usershape_t *us, boxf p, point *A, int n, boolean filled)
00824 {
00825     static boolean onetime = TRUE;
00826     if (onetime) {
00827         agerr(AGERR, "custom shapes not available with this driver\n");
00828         onetime = FALSE;
00829     }
00830 }
00831 
00832 codegen_t HPGL_CodeGen = {
00833     hpgl_reset,
00834     hpgl_begin_job, 0,          /* hpgl_end_job */
00835     hpgl_begin_graph, 0,        /* hpgl_end_graph */
00836     hpgl_begin_page, hpgl_end_page,
00837     0, /* hpgl_begin_layer */ 0,        /* hpgl_end_layer */
00838     0, /* hpgl_begin_cluster */ 0,      /* hpgl_end_cluster */
00839     0, /* hpgl_begin_nodes */ 0,        /* hpgl_end_nodes */
00840     0, /* hpgl_begin_edges */ 0,        /* hpgl_end_edges */
00841     0, /* hpgl_begin_node */ 0, /* hpgl_end_node */
00842     0, /* hpgl_begin_edge */ 0, /* hpgl_end_edge */
00843     hpgl_begin_context, hpgl_end_context,
00844     0, /* hpgl_begin_anchor */ 0,       /* hpgl_end_anchor */
00845     hpgl_set_font, hpgl_textpara,
00846     hpgl_set_color, hpgl_set_color, hpgl_set_style,
00847     hpgl_ellipse, hpgl_polygon,
00848     hpgl_bezier, hpgl_polyline,
00849     0,                          /* bezier_has_arrows */
00850     0,                          /* hpgl_comment */
00851     hpgl_usershape
00852 };