[BACK]Return to pdf.trm CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot / term

Annotation of OpenXM_contrib/gnuplot/term/pdf.trm, Revision 1.1

1.1     ! ohara       1: /*Hello, Emacs, this is -*-C-*- ! */
        !             2: /*------------------------------
        !             3:        GNUPLOT - pdf.trm
        !             4:
        !             5:        This file is included by ../term.c.
        !             6:
        !             7:        This driver uses PDFlib from www.pdflib.com
        !             8:
        !             9:        Author:
        !            10:
        !            11:                Hans-Bernhard Br"oker
        !            12:                broeker@physik.rwth-aachen.de
        !            13:
        !            14:        Licence: see the gnuplot copyright (to be merged into here...)
        !            15:
        !            16:        Options: can #define PDF_DONT_COMPRESS to avoid PDF output
        !            17:        generated being compressed (by the 'deflate' algorithm as used
        !            18:        in 'zip' or 'gzip'). That helps in debugging.
        !            19:
        !            20: ------------------------------*/
        !            21:
        !            22: /* CODEME: Add patterned lines (?). Implement the PM3D stuff.  */
        !            23:
        !            24: #include "driver.h"
        !            25:
        !            26: #ifdef TERM_REGISTER
        !            27: register_term (pdf)
        !            28: #endif
        !            29:
        !            30: #ifdef TERM_PROTO
        !            31: TERM_PUBLIC void PDF_options __PROTO ((void));
        !            32: TERM_PUBLIC void PDF_init __PROTO ((void));
        !            33: TERM_PUBLIC void PDF_graphics __PROTO ((void));
        !            34: TERM_PUBLIC void PDF_text __PROTO ((void));
        !            35: TERM_PUBLIC void PDF_linetype __PROTO ((int linetype));
        !            36: TERM_PUBLIC void PDF_move __PROTO ((unsigned int x, unsigned int y));
        !            37: TERM_PUBLIC void PDF_vector __PROTO ((unsigned int x, unsigned int y));
        !            38: TERM_PUBLIC void PDF_put_text __PROTO ((unsigned int x, unsigned int y, char *str));
        !            39: TERM_PUBLIC void PDF_reset __PROTO ((void));
        !            40: TERM_PUBLIC int PDF_justify_text __PROTO ((enum JUSTIFY mode));
        !            41: TERM_PUBLIC int PDF_text_angle __PROTO ((int ang));
        !            42: TERM_PUBLIC void PDF_point __PROTO ((unsigned int x, unsigned int y, int pointstyle));
        !            43: TERM_PUBLIC int PDF_set_font __PROTO ((char *font));
        !            44: TERM_PUBLIC void PDF_boxfill __PROTO((int style, unsigned int x1, unsigned int y1, unsigned int width, unsigned int height));
        !            45: TERM_PUBLIC void PDF_linewidth __PROTO ((double linewidth));
        !            46:
        !            47: #define PDF_NUM_POINTTYPES 75  /* number of point symbol types not counting the dot */
        !            48:
        !            49: #define PDF_RESOLUTION  (20)   /* number of terminal pixels per pt */
        !            50: #define PDF_XMAX       (5*72*PDF_RESOLUTION) /* 5 inches, 72 pt/inch */
        !            51: #define PDF_YMAX       (3*72*PDF_RESOLUTION) /* 3 inches, 72 pt/inch */
        !            52:
        !            53: #endif /* TERM_PROTO */
        !            54:
        !            55: #ifndef TERM_PROTO_ONLY
        !            56: #ifdef TERM_BODY
        !            57:
        !            58: #include <pdflib.h>
        !            59:
        !            60: PDF *myPDF = NULL;
        !            61:
        !            62: unsigned int PDF_xLast = UINT_MAX;     /* current pen horizontal position*/
        !            63: unsigned int PDF_yLast = UINT_MAX;     /* current pen vertical position*/
        !            64:
        !            65: int PDF_LineType = -3;         /* current line type*/
        !            66: double PDF_LineWidth = 1.0;    /* current line width*/
        !            67: int PDF_TextAngle = 0;         /* current text orientation*/
        !            68: enum JUSTIFY PDF_TextJust = LEFT; /* current text justification*/
        !            69:
        !            70: char PDF_fontNameDef[MAX_ID_LEN + 1] = "Helvetica"; /* default text font family*/
        !            71: double PDF_fontSizeDef = 6;    /* default text size*/
        !            72: char PDF_fontNameCur[MAX_ID_LEN + 1] = "Helvetica"; /* current text font family*/
        !            73: double PDF_fontSizeCur = 6;    /* current text size*/
        !            74:
        !            75: TBOOLEAN PDF_pageIsOpen = FALSE; /* already started a page ?? */
        !            76: TBOOLEAN PDF_pathIsOpen = FALSE; /* open path flag*/
        !            77:
        !            78: int PDF_fontAscent = 0;                /* estimated current font ascent*/
        !            79: int PDF_fontDescent = 0;       /* estimated current font descent*/
        !            80: int PDF_fontLeading = 0;       /* estimated current font leading*/
        !            81: int PDF_fontAvWidth = 0;       /* estimated current font char average width*/
        !            82:
        !            83: static short PDF_Pen_RealID __PROTO ((int));
        !            84: static void PDF_PathOpen __PROTO ((void));
        !            85: static void PDF_PathClose __PROTO ((void));
        !            86: static void PDF_SetFont __PROTO ((void));
        !            87:
        !            88: /*------------------------ helper functions -------------------*/
        !            89:
        !            90: static short
        !            91: PDF_Pen_RealID (inPenCode)
        !            92:     int inPenCode;
        !            93: {
        !            94:     if (inPenCode >= 13)
        !            95:        inPenCode %= 13;        /* normalize pen code*/
        !            96:     if (inPenCode < -2)
        !            97:        inPenCode = -2;
        !            98:
        !            99:     return (inPenCode + 2);
        !           100: }
        !           101:
        !           102: /* Functions to ensure that as many move() and vector() calls as
        !           103:  * possible get converted into a single long 'path', before closing it
        !           104:  * with a stroke or similar command. */
        !           105: static void
        !           106: PDF_PathOpen ()
        !           107: {
        !           108:     PDF_pathIsOpen = TRUE;
        !           109: }
        !           110:
        !           111: static void
        !           112: PDF_PathClose ()
        !           113: {
        !           114:     if (PDF_pathIsOpen) {
        !           115:        PDF_stroke(myPDF);
        !           116:
        !           117:        PDF_pathIsOpen = FALSE;
        !           118:     }
        !           119: }
        !           120:
        !           121: /* Helper function to deal with switching over to a newly selected
        !           122:  * font.  For now, this does not try to embed fonts into the PDF
        !           123:  * file. This relies on the user restricting herself to the 14
        !           124:  * 'classical' fonts built into every valid PDF reader application */
        !           125: static void
        !           126: PDF_SetFont ()
        !           127: {
        !           128:     int font_handle = PDF_findfont(myPDF, PDF_fontNameCur, "host", 0);
        !           129:
        !           130:     PDF_setfont(myPDF, font_handle, PDF_fontSizeCur * PDF_RESOLUTION);
        !           131:
        !           132:     /* Ask PDFlib for the actual numbers */
        !           133:     PDF_fontAscent = (int) (PDF_RESOLUTION * PDF_fontSizeCur * PDF_get_value(myPDF, "ascender", 0));
        !           134:     PDF_fontDescent = (int) (- PDF_RESOLUTION * PDF_fontSizeCur * PDF_get_value(myPDF, "descender", 0));
        !           135:     PDF_fontLeading = (int) (PDF_RESOLUTION * PDF_fontSizeCur * 0.25);
        !           136:
        !           137:     /* Assume this particular string is a somewhat reasonable typical
        !           138:      * output, for getting at the average character width */
        !           139:     PDF_fontAvWidth = (int)
        !           140:        (PDF_RESOLUTION * PDF_stringwidth(myPDF, "01234567890123456789",
        !           141:                                          font_handle, PDF_fontSizeCur)
        !           142:         / 20.0);
        !           143: }
        !           144:
        !           145: /*------------------- the terminal entry functions --------------------*/
        !           146:
        !           147:
        !           148: TERM_PUBLIC void
        !           149: PDF_options ()
        !           150: {
        !           151:     struct value a;
        !           152:
        !           153:     if (!END_OF_COMMAND) {     /* get default font family name*/
        !           154:        if (almost_equals (c_token, "fn$ame"))  {
        !           155:            c_token++;
        !           156:
        !           157:            if (!END_OF_COMMAND && isstring (c_token)) {
        !           158:                quote_str (PDF_fontNameDef, c_token, MAX_ID_LEN);
        !           159:                c_token++;
        !           160:            } else
        !           161:                int_error("fname: expecting font name", c_token);
        !           162:        }
        !           163:     }
        !           164:
        !           165:     if (!END_OF_COMMAND) {     /* get default font size*/
        !           166:        if (almost_equals (c_token, "fs$ize")) {
        !           167:            c_token++;
        !           168:
        !           169:            if (END_OF_COMMAND)
        !           170:                int_error("fsize: expecting font size", c_token);
        !           171:            PDF_fontSizeDef = real (const_express (&a));
        !           172:        }
        !           173:     }
        !           174:
        !           175:     if (!END_OF_COMMAND)
        !           176:         int_error("unexpected text at end of command", c_token);
        !           177:
        !           178:     /* Save options back into options string in normalized format */
        !           179:     sprintf(term_options, "fname '%s'  fsize %g",
        !           180:            PDF_fontNameDef, PDF_fontSizeDef);
        !           181: }
        !           182:
        !           183:
        !           184: TERM_PUBLIC void
        !           185: PDF_init ()
        !           186: {
        !           187:     static TBOOLEAN PDFlib_booted = FALSE;
        !           188:
        !           189:     if (!PDFlib_booted) {
        !           190:        PDF_boot();
        !           191:        PDFlib_booted = TRUE;
        !           192:     }
        !           193:
        !           194:     if (!myPDF)
        !           195:        myPDF = PDF_new();
        !           196:
        !           197:     /*open new PDF file */
        !           198:     if (PDF_open_fp(myPDF, gpoutfile) == -1)
        !           199:        int_error("Error:cannot open PDF file .\n", NO_CARET);
        !           200:
        !           201: #ifdef PDF_DONT_COMPRESS
        !           202:     /* for easier debugging of the output, turn off PDF stream
        !           203:      * compression */
        !           204:     PDF_set_value(myPDF, "compress", 0);
        !           205: #endif
        !           206:
        !           207:     PDF_set_info(myPDF,"Creator","gnuplot-3.8e");
        !           208:     PDF_set_info(myPDF,"Author","Hans-Bernhard Broeker"); /* FIXME: put in username? */
        !           209:     PDF_set_info(myPDF,"Title","gnuplot diagram"); /* FIXME: use 'set title', if any ? */
        !           210:
        !           211:     PDF_LineType = -3;
        !           212:
        !           213:     /* set current font to default */
        !           214:     strcpy(PDF_fontNameCur, PDF_fontNameDef);
        !           215:     PDF_fontSizeCur = PDF_fontSizeDef;
        !           216:
        !           217:     /* Have to start the first page now, in order to know the actual
        !           218:      * size of the selected font */
        !           219:     PDF_graphics();
        !           220:
        !           221:     /* set h_char, v_char*/
        !           222:     term->h_char = PDF_fontAvWidth;
        !           223:     term->v_char = (PDF_fontAscent + PDF_fontDescent + PDF_fontLeading);
        !           224:
        !           225:     /* set h_tic, v_tic*/
        !           226:     term->h_tic = term->v_tic = 3 * PDF_RESOLUTION;
        !           227:
        !           228:     /* initialize terminal's pointsize from "set pointsize" value */
        !           229:     term_pointsize = pointsize;
        !           230: }
        !           231:
        !           232:
        !           233: TERM_PUBLIC void
        !           234: PDF_graphics ()
        !           235: {
        !           236:     if (PDF_pageIsOpen)
        !           237:        return;                 /* already open --> nothing to do */
        !           238:
        !           239:     PDF_pathIsOpen = FALSE;
        !           240:     PDF_xLast = PDF_yLast = UINT_MAX;
        !           241:
        !           242:     /* set xmax, ymax*/
        !           243:     term->xmax = PDF_XMAX * xsize;
        !           244:     term->ymax = PDF_YMAX * ysize;
        !           245:
        !           246:     PDF_begin_page(myPDF, (double)term->xmax / PDF_RESOLUTION,
        !           247:                   (double)term->ymax / PDF_RESOLUTION);
        !           248:     PDF_scale(myPDF, 1.0/PDF_RESOLUTION, 1.0/PDF_RESOLUTION);
        !           249:     if (title.text && title.text[0])
        !           250:        /* a title has been set --> use it as the bookmark name, too */
        !           251:        PDF_add_bookmark(myPDF, title.text, 0, 1);
        !           252:     PDF_pageIsOpen = TRUE;
        !           253:
        !           254:     PDF_SetFont();
        !           255: }
        !           256:
        !           257:
        !           258: TERM_PUBLIC void
        !           259: PDF_text ()
        !           260: {
        !           261:     PDF_PathClose();
        !           262:     PDF_end_page(myPDF);
        !           263:     PDF_pageIsOpen = FALSE;
        !           264: }
        !           265:
        !           266:
        !           267: TERM_PUBLIC void
        !           268: PDF_reset ()
        !           269: {
        !           270:     assert(PDF_pageIsOpen == FALSE);
        !           271:     PDF_close(myPDF);
        !           272:     PDF_delete(myPDF);
        !           273:     myPDF = NULL;
        !           274: }
        !           275:
        !           276:
        !           277: TERM_PUBLIC void
        !           278: PDF_linetype (int linetype)
        !           279: {
        !           280:     if (linetype != PDF_LineType) {
        !           281:        int real_linetype = PDF_Pen_RealID(linetype);
        !           282:        struct rgb *this_color = web_color_rgbs + 1 + real_linetype;
        !           283:
        !           284:        PDF_PathClose ();
        !           285:        PDF_LineType = linetype;
        !           286:
        !           287:        PDF_setrgbcolor(myPDF, this_color->r / 255.0,
        !           288:                        this_color->g / 255.0, this_color->b / 255.0);
        !           289:     }
        !           290: }
        !           291:
        !           292:
        !           293: TERM_PUBLIC void
        !           294: PDF_linewidth (double linewidth)
        !           295: {
        !           296:     PDF_PathClose();
        !           297:     PDF_LineWidth = PDF_RESOLUTION * linewidth / 4.0;
        !           298:     PDF_setlinewidth(myPDF, PDF_LineWidth);
        !           299: }
        !           300:
        !           301:
        !           302: TERM_PUBLIC void
        !           303: PDF_move (unsigned int x, unsigned int y)
        !           304: {
        !           305:     if (PDF_pathIsOpen && x == PDF_xLast && y == PDF_yLast)
        !           306:        return;
        !           307:
        !           308:     PDF_PathOpen ();
        !           309:     PDF_moveto(myPDF, x, y);
        !           310:
        !           311:     PDF_xLast = x;
        !           312:     PDF_yLast = y;
        !           313: }
        !           314:
        !           315:
        !           316: TERM_PUBLIC void
        !           317: PDF_vector (unsigned int x, unsigned int y)
        !           318: {
        !           319:     if (PDF_pathIsOpen && x == PDF_xLast && y == PDF_yLast)
        !           320:        return;
        !           321:
        !           322:     PDF_PathOpen ();
        !           323:     PDF_lineto(myPDF, x, y);
        !           324:
        !           325:     PDF_xLast = x;
        !           326:     PDF_yLast = y;
        !           327: }
        !           328:
        !           329: /* Helper function. Many symbols have an additional dot in their
        !           330:  * center, so isolate its drawing into a separate function. */
        !           331: static GP_INLINE void
        !           332: PDF_dot (unsigned int x, unsigned int y)
        !           333: {
        !           334:     /* Imitate PS's way of creating a small dot by a zero-length line
        !           335:      * segment with rounded endpoints */
        !           336:     PDF_setlinecap(myPDF, 1); /* rounded ends */
        !           337:     PDF_moveto(myPDF, x, y);
        !           338:     PDF_lineto(myPDF, x, y);
        !           339:     PDF_stroke(myPDF);
        !           340: }
        !           341:
        !           342:
        !           343: TERM_PUBLIC void
        !           344: PDF_point (unsigned int x, unsigned int y, int number)
        !           345: {
        !           346:     PDF_PathClose ();
        !           347:     PDF_save(myPDF);
        !           348:
        !           349:     if (number < 0) {
        !           350:        /* Like the PostScript driver, treat all negative numbers as
        !           351:          * 'with dots'. */
        !           352:        PDF_dot(x, y);
        !           353:     } else {
        !           354:        /* Change coordinate system so the point symbols themselves
        !           355:         * can be drawn without depending on position or size (-->
        !           356:         * better compression and less coding for gnuplot) */
        !           357:        /* NB: I use the do_pointsize() default implementation, which
        !           358:         * just stores the last set pointsize into `term_pointsize',
        !           359:         * to avoid introducing another static driver-local variable
        !           360:         * */
        !           361:        PDF_translate(myPDF, x, y);
        !           362:        PDF_scale(myPDF, term->h_tic / 2.0 * term_pointsize,
        !           363:                  term->v_tic / 2.0 * term_pointsize);
        !           364:        /* Correct linewidth to counter the scaling effect --- assume
        !           365:         * h_tic is usable, to avoid having to average h_ and v_tic */
        !           366:        PDF_setlinewidth(myPDF,
        !           367:                         PDF_LineWidth / (term->h_tic / 2.0 * term_pointsize));
        !           368:        switch (number %= PDF_NUM_POINTTYPES) {
        !           369:        case 0:                 /* Plus */
        !           370:            PDF_moveto(myPDF, -1, 0);
        !           371:            PDF_lineto(myPDF, 1, 0);
        !           372:            PDF_moveto(myPDF, 0, -1);
        !           373:            PDF_lineto(myPDF, 0, 1);
        !           374:            PDF_stroke(myPDF);
        !           375:            break;
        !           376:        case 2:                 /* Star */
        !           377:            PDF_moveto(myPDF, -1, 0);
        !           378:            PDF_lineto(myPDF, 1, 0);
        !           379:            PDF_moveto(myPDF, 0, -1);
        !           380:            PDF_lineto(myPDF, 0, 1);
        !           381:            /* FALLTHROUGH */
        !           382:        case 1:                 /* Cross */
        !           383:            PDF_moveto(myPDF, -1, -1);
        !           384:            PDF_lineto(myPDF, 1, 1);
        !           385:            PDF_moveto(myPDF, 1, -1);
        !           386:            PDF_lineto(myPDF, -1, 1);
        !           387:            PDF_stroke(myPDF);
        !           388:            break;
        !           389:
        !           390: /* For each x = 0..5, 4 shapes are defined:
        !           391:  * 3 + 2*x --> hollow symbol with a dot at its center
        !           392:  * 4 + 2*x --> solid symbol filled in linetype's color
        !           393:  * 63 + x  --> hollow symbol without the center dot
        !           394:  * 69 + x  --> symbol filled with white --> opaque symbol */
        !           395:
        !           396:        case 63+0:              /* BoxEmpty */
        !           397:        case 3+2*0:             /* Box */
        !           398:            PDF_moveto(myPDF, -1, -1);
        !           399:            PDF_lineto(myPDF, 1, -1);
        !           400:            PDF_lineto(myPDF, 1, 1);
        !           401:            PDF_lineto(myPDF, -1, 1);
        !           402:            PDF_closepath_stroke(myPDF);
        !           403:            if (number == 3) PDF_dot(0,0);
        !           404:            break;
        !           405:        case 69+0:              /* BoxWhitefilled */
        !           406:            PDF_setgray_fill(myPDF, 1);
        !           407:            /* FALLTHROUGH */
        !           408:        case 4+2*0:             /* BoxFilled */
        !           409:            PDF_moveto(myPDF, -1, -1);
        !           410:            PDF_lineto(myPDF, 1, -1);
        !           411:            PDF_lineto(myPDF, 1, 1);
        !           412:            PDF_lineto(myPDF, -1, 1);
        !           413:            PDF_closepath_fill_stroke(myPDF);
        !           414:            break;
        !           415:
        !           416:        case 63+1:              /* CircleEmpty */
        !           417:        case 3+2*1:             /* Circle */
        !           418:            PDF_circle(myPDF, 0, 0, 1);
        !           419:            PDF_stroke(myPDF);
        !           420:            if (number == 5) PDF_dot(0,0);
        !           421:            break;
        !           422:        case 69+1:              /* CircleWhitefilled */
        !           423:            PDF_setgray_fill(myPDF, 1);
        !           424:            /* FALLTHROUGH */
        !           425:        case 4+2*1:             /* CircleFilled */
        !           426:            PDF_circle(myPDF, 0, 0, 1);
        !           427:            PDF_fill_stroke(myPDF);
        !           428:            break;
        !           429:
        !           430:        case 63+2:              /* TriangleUpEmpty */
        !           431:        case 3+2*2:             /* TriangleUp */
        !           432:            PDF_moveto(myPDF, 0, 1.12);
        !           433:            PDF_lineto(myPDF, -1, -0.5);
        !           434:            PDF_lineto(myPDF, 1, -0.5);
        !           435:            PDF_closepath_stroke(myPDF);
        !           436:            if (number == 7) PDF_dot(0,0);
        !           437:            break;
        !           438:        case 69+2:              /* TriangleUpWhitefilled */
        !           439:            PDF_setgray_fill(myPDF, 1);
        !           440:            /* FALLTHROUGH */
        !           441:        case 4+2*2:                     /* TriangleUpFilled */
        !           442:            PDF_moveto(myPDF, 0, 1.12);
        !           443:            PDF_lineto(myPDF, -1, -0.5);
        !           444:            PDF_lineto(myPDF, 1, -0.5);
        !           445:            PDF_closepath_fill_stroke(myPDF);
        !           446:            break;
        !           447:
        !           448:        case 63+3:              /* TriangleDownEmpty */
        !           449:        case 3+2*3:             /* TriangleDown */
        !           450:            PDF_moveto(myPDF, 0, -1.12);
        !           451:            PDF_lineto(myPDF, -1, 0.5);
        !           452:            PDF_lineto(myPDF, 1, 0.5);
        !           453:            PDF_closepath_stroke(myPDF);
        !           454:            if (number == 9) PDF_dot(0,0);
        !           455:            break;
        !           456:        case 69+3:              /* TriangleDownWhitefilled */
        !           457:            PDF_setgray_fill(myPDF, 1);
        !           458:            /* FALLTHROUGH */
        !           459:        case 4+2*3:             /* TriangleDownFilled */
        !           460:            PDF_moveto(myPDF, 0, -1.12);
        !           461:            PDF_lineto(myPDF, -1, 0.5);
        !           462:            PDF_lineto(myPDF, 1, 0.5);
        !           463:            PDF_closepath_fill_stroke(myPDF);
        !           464:            break;
        !           465:
        !           466:        case 63+4:              /* DiamondEmpty */
        !           467:        case 3+2*4:             /* Diamond */
        !           468:            PDF_moveto(myPDF, 0, -1);
        !           469:            PDF_lineto(myPDF, 1, 0);
        !           470:            PDF_lineto(myPDF, 0, 1);
        !           471:            PDF_lineto(myPDF, -1, 0);
        !           472:            PDF_closepath_stroke(myPDF);
        !           473:            if (number == 11) PDF_dot(0,0);
        !           474:            break;
        !           475:        case 69+4:              /* DiamondWhitefilled */
        !           476:            PDF_setgray_fill(myPDF, 1);
        !           477:            /* FALLTHROUGH */
        !           478:        case 4+2*4:             /* DiamondFilled */
        !           479:            PDF_moveto(myPDF, 0, -1);
        !           480:            PDF_lineto(myPDF, 1, 0);
        !           481:            PDF_lineto(myPDF, 0, 1);
        !           482:            PDF_lineto(myPDF, -1, 0);
        !           483:            PDF_closepath_fill_stroke(myPDF);
        !           484:            break;
        !           485:
        !           486:        case 63+5:              /* PentagonEmpty */
        !           487:        case 3+2*5:             /* Pentagon */
        !           488:            PDF_moveto(myPDF, 0, 1);
        !           489:            PDF_lineto(myPDF, -0.95, 0.31);
        !           490:            PDF_lineto(myPDF, -0.58, -0.81);
        !           491:            PDF_lineto(myPDF, +0.58, -0.81);
        !           492:            PDF_lineto(myPDF, +0.95, 0.31);
        !           493:            PDF_closepath_stroke(myPDF);
        !           494:            if (number == 13) PDF_dot(0,0);
        !           495:            break;
        !           496:        case 69+5:              /* PentagonWhitefilled */
        !           497:            PDF_setgray_fill(myPDF, 1);
        !           498:            /* FALLTHROUGH */
        !           499:        case 4+2*5:             /* PentagonFilled */
        !           500:            PDF_moveto(myPDF, 0, 1);
        !           501:            PDF_lineto(myPDF, -0.95, 0.31);
        !           502:            PDF_lineto(myPDF, -0.58, -0.81);
        !           503:            PDF_lineto(myPDF, +0.58, -0.81);
        !           504:            PDF_lineto(myPDF, +0.95, 0.31);
        !           505:            PDF_closepath_fill_stroke(myPDF);
        !           506:            break;
        !           507:
        !           508: /* 15 + (0..15): circles with varying parts of'em filled. The added
        !           509:  * number is a bit-pattern of the 4 quadrants: 1 signals a quadrant
        !           510:  * filled */
        !           511:        case 15+0:
        !           512:            PDF_moveto(myPDF, 0, 0);
        !           513:            PDF_lineto(myPDF, 0, 1);
        !           514:            PDF_arc(myPDF, 0, 0, 1, 90, 360+90);
        !           515:            PDF_closepath_stroke(myPDF);
        !           516:            break;
        !           517:
        !           518: /* Generalize common code into a macro... */
        !           519: #define CIRCLE_SINGLE_PIESLICE(x, y, angle1, angle2)           \
        !           520:            PDF_moveto(myPDF, 0, 0);                            \
        !           521:            PDF_lineto(myPDF, (x), (y));                        \
        !           522:            PDF_arc(myPDF, 0, 0, 1, (angle1), (angle2));        \
        !           523:            PDF_lineto(myPDF, 0, 0);                            \
        !           524:            PDF_closepath(myPDF);                               \
        !           525:            PDF_fill_stroke(myPDF);                             \
        !           526:            PDF_arc(myPDF, 0, 0, 1, (angle2), (angle1) + 360);  \
        !           527:            PDF_stroke(myPDF);                                  \
        !           528:            break;
        !           529:
        !           530: #define CIRCLE_SINGLE_QUADRANT(x, y, angle)                    \
        !           531:            CIRCLE_SINGLE_PIESLICE(x, y, angle, angle+90);
        !           532:        case 15+1:
        !           533:            CIRCLE_SINGLE_QUADRANT(1, 0, 0);
        !           534:        case 15+2:
        !           535:            CIRCLE_SINGLE_QUADRANT(0, 1, 90);
        !           536:        case 15+4:
        !           537:            CIRCLE_SINGLE_QUADRANT(-1, 0, 180);
        !           538:        case 15+8:
        !           539:            CIRCLE_SINGLE_QUADRANT(0, -1, 270);
        !           540: #undef CIRCLE_SINGLE_QUADRANT
        !           541:
        !           542: #define CIRCLE_TWO_NEIGHBOR_QUADRANTS(x, y, angle)             \
        !           543:            CIRCLE_SINGLE_PIESLICE(x, y, angle, angle+180)
        !           544:        case 15+3:
        !           545:            CIRCLE_TWO_NEIGHBOR_QUADRANTS(1, 0, 0);
        !           546:        case 15+6:
        !           547:            CIRCLE_TWO_NEIGHBOR_QUADRANTS(0, 1, 90);
        !           548:        case 15+12:
        !           549:            CIRCLE_TWO_NEIGHBOR_QUADRANTS(-1, 0, 180);
        !           550:        case 15+9:
        !           551:            CIRCLE_TWO_NEIGHBOR_QUADRANTS(0, -1, 270);
        !           552: #undef CIRCLE_TWO_NEIGHBOR_QUADRANTS
        !           553:
        !           554: #define CIRCLE_TWO_OPPOSING_QUADRANTS(x, y, angle)             \
        !           555:            PDF_moveto(myPDF, 0, 0);                            \
        !           556:            PDF_lineto(myPDF, x, y);                            \
        !           557:            PDF_arc(myPDF, 0, 0, 1, angle, angle + 90);         \
        !           558:            PDF_lineto(myPDF, 0, 0);                            \
        !           559:            PDF_fill_stroke(myPDF);                             \
        !           560:            PDF_moveto(myPDF, 0, 0);                            \
        !           561:            PDF_lineto(myPDF, -x, -y);                          \
        !           562:            PDF_arc(myPDF, 0, 0, 1, angle + 180, angle + 270);  \
        !           563:            PDF_lineto(myPDF, 0, 0);                            \
        !           564:            PDF_fill_stroke(myPDF);                             \
        !           565:            PDF_arc(myPDF, 0, 0, 1, angle + 90, angle + 360);   \
        !           566:            PDF_stroke(myPDF);                                  \
        !           567:            break;
        !           568:        case 15+5:
        !           569:            CIRCLE_TWO_OPPOSING_QUADRANTS(1, 0, 0);
        !           570:        case 15+10:
        !           571:            CIRCLE_TWO_OPPOSING_QUADRANTS(0, 1, 90);
        !           572: #undef CIRCLE_TWO_OPPOSING_QUADRANTS
        !           573:
        !           574: #define CIRCLE_THREE_QUADRANTS(x, y, angle)                    \
        !           575:            CIRCLE_SINGLE_PIESLICE(x, y, angle, angle+270)
        !           576:        case 15+7:
        !           577:            CIRCLE_THREE_QUADRANTS(1, 0, 0);
        !           578:        case 15+14:
        !           579:            CIRCLE_THREE_QUADRANTS(0, 1, 90);
        !           580:        case 15+13:
        !           581:            CIRCLE_THREE_QUADRANTS(-1, 0, 180);
        !           582:        case 15+11:
        !           583:            CIRCLE_THREE_QUADRANTS(0, -1, 270);
        !           584: #undef CIRCLE_THREE_QUADRANTS
        !           585: #undef CIRCLE_SINGLE_PIESLICE
        !           586:
        !           587:        case 15+15:
        !           588:            PDF_circle(myPDF, 0, 0, 1);
        !           589:            PDF_closepath_fill_stroke(myPDF);
        !           590:            break;
        !           591:
        !           592:
        !           593: /*************************************************************************/
        !           594: /* 31 + (0..15): squares with different quadrants of them filled in. */
        !           595: /*************************************************************************/
        !           596: /*************************************************************************/
        !           597: /* 47 + (0..15): diamonds with filled quadrants as given by bit pattern  */
        !           598: /*   Diamonds are drawn as squares rotated by 45 degrees, so can use
        !           599:  * fall-through from diamond to squares, and re-use some macros. */
        !           600: /*************************************************************************/
        !           601:        case 47+0:
        !           602:            PDF_rotate(myPDF, 45);
        !           603:            /* FALLTHROUGH */
        !           604:        case 31+0:
        !           605:            PDF_moveto(myPDF, 0, 0);
        !           606:            PDF_lineto(myPDF, 0, 1);
        !           607:            PDF_lineto(myPDF, -1, 1);
        !           608:            PDF_lineto(myPDF, -1, -1);
        !           609:            PDF_lineto(myPDF, 1, -1);
        !           610:            PDF_lineto(myPDF, 1, 1);
        !           611:            PDF_lineto(myPDF, 0, 1);
        !           612:            PDF_stroke(myPDF);
        !           613:            break;
        !           614:
        !           615:        case 47+15:
        !           616:            PDF_rotate(myPDF, 45);
        !           617:            /* FALLTHROUGH */
        !           618:        case 31+15:
        !           619:            PDF_moveto(myPDF, -1, 1);
        !           620:            PDF_lineto(myPDF, -1, -1);
        !           621:            PDF_lineto(myPDF, 1, -1);
        !           622:            PDF_lineto(myPDF, 1, 1);
        !           623:            PDF_closepath_fill_stroke(myPDF);
        !           624:            break;
        !           625:
        !           626: /* macros defining shapes of the partly filled symbols. Done by
        !           627:  * rotating the starting point (x0, y0) by 90 degrees or 45 degrees
        !           628:  * (with length adjustment).  The rotations can be done without
        !           629:  * trigonometric function calls, since their values are known:
        !           630:  * cos(90)=0, sin(90)=1, cos(45)=sin(45)=1/sqrt(2).  A good compiler
        !           631:  * should be able to optimize away all the local variables and
        !           632:  * loops...  */
        !           633:
        !           634: #define SQUARE_SINGLE_PIESLICE(x0, y0, quadrants)                      \
        !           635:            {                                                           \
        !           636:                int quadrant = 0;                                       \
        !           637:                int x= x0, y=y0;                                        \
        !           638:                PDF_moveto(myPDF, 0, 0);                                \
        !           639:                PDF_lineto(myPDF, x, y);                                \
        !           640:                /* poor man's rotation by 45 and 90 degrees around the  \
        !           641:                 * square's outline. */                                 \
        !           642:                while (quadrant++ < quadrants) {                        \
        !           643:                    int dummy;                                          \
        !           644:                    PDF_lineto(myPDF, x-y, x+y);                        \
        !           645:                    dummy = x; x = -y; y = dummy;                       \
        !           646:                }                                                       \
        !           647:                PDF_lineto(myPDF, x, y);                                \
        !           648:                PDF_closepath_fill_stroke(myPDF);                       \
        !           649:                PDF_moveto(myPDF, x, y);                                \
        !           650:                while (quadrant++ <= 4) {                               \
        !           651:                    int dummy;                                          \
        !           652:                    PDF_lineto(myPDF, x-y, x+y);                        \
        !           653:                    dummy = x; x = -y; y = dummy;                       \
        !           654:                }                                                       \
        !           655:                PDF_lineto(myPDF, x, y);                                \
        !           656:                PDF_stroke(myPDF);                                      \
        !           657:            }                                                           \
        !           658:            break;
        !           659:
        !           660: #define SQUARE_TWO_OPPOSING_QUADRANTS(x0, y0, angle)   \
        !           661:            {                                           \
        !           662:                int x = x0, y = y0, dummy;              \
        !           663:                int counter = 0;                        \
        !           664:                                                        \
        !           665:                while (counter++ < 2) {                 \
        !           666:                    PDF_moveto(myPDF, 0, 0);            \
        !           667:                    PDF_lineto(myPDF, x, y);            \
        !           668:                    PDF_lineto(myPDF, x-y, x+y);        \
        !           669:                    dummy = x; x = -y; y = dummy;       \
        !           670:                    PDF_lineto(myPDF, x, y);            \
        !           671:                    PDF_closepath_fill_stroke(myPDF);   \
        !           672:                                                        \
        !           673:                    PDF_moveto(myPDF, x, y);            \
        !           674:                    PDF_lineto(myPDF, x-y, x+y);        \
        !           675:                    dummy = x; x = -y; y = dummy;       \
        !           676:                    PDF_lineto(myPDF, x, y);            \
        !           677:                    PDF_stroke(myPDF);                  \
        !           678:                }                                       \
        !           679:                break;                                  \
        !           680:            }
        !           681:
        !           682: /* Macros for diamonds just prepend the rotation and then call those
        !           683:  * for squares: */
        !           684: #define DIAMOND_SINGLE_PIESLICE(x, y, quadrants)       \
        !           685:            PDF_rotate(myPDF, 45);                      \
        !           686:            SQUARE_SINGLE_PIESLICE(x, y, quadrants);
        !           687: #define DIAMOND_TWO_OPPOSING_QUADRANTS(x, y, angle)    \
        !           688:            PDF_rotate(myPDF, 45);                      \
        !           689:            SQUARE_TWO_OPPOSING_QUADRANTS(x, y, angle);
        !           690:
        !           691: /* ... and now all the individual cases. The 'angle' arguments' are
        !           692:  * purely for the sake of easing cut'n'paste with the circle case */
        !           693: #define SQUARE_SINGLE_QUADRANT(x, y, angle)                    \
        !           694:            SQUARE_SINGLE_PIESLICE(x, y, 1);
        !           695:        case 31+1:
        !           696:            SQUARE_SINGLE_QUADRANT(1, 0, 0);
        !           697:        case 31+2:
        !           698:            SQUARE_SINGLE_QUADRANT(0, 1, 90);
        !           699:        case 31+4:
        !           700:            SQUARE_SINGLE_QUADRANT(-1, 0, 180);
        !           701:        case 31+8:
        !           702:            SQUARE_SINGLE_QUADRANT(0, -1, 270);
        !           703: #undef SQUARE_SINGLE_QUADRANT
        !           704:
        !           705: #define SQUARE_TWO_NEIGHBOR_QUADRANTS(x, y, angle)             \
        !           706:            SQUARE_SINGLE_PIESLICE(x, y, 2)
        !           707:        case 31+3:
        !           708:            SQUARE_TWO_NEIGHBOR_QUADRANTS(1, 0, 0);
        !           709:        case 31+6:
        !           710:            SQUARE_TWO_NEIGHBOR_QUADRANTS(0, 1, 90);
        !           711:        case 31+12:
        !           712:            SQUARE_TWO_NEIGHBOR_QUADRANTS(-1, 0, 180);
        !           713:        case 31+9:
        !           714:            SQUARE_TWO_NEIGHBOR_QUADRANTS(0, -1, 270);
        !           715: #undef SQUARE_TWO_NEIGHBOR_QUADRANTS
        !           716:
        !           717:        case 31+5:
        !           718:            SQUARE_TWO_OPPOSING_QUADRANTS(1, 0, 0);
        !           719:        case 31+10:
        !           720:            SQUARE_TWO_OPPOSING_QUADRANTS(0, 1, 90);
        !           721:
        !           722: #define SQUARE_THREE_QUADRANTS(x, y, angle)                    \
        !           723:            SQUARE_SINGLE_PIESLICE(x, y, 3)
        !           724:        case 31+7:
        !           725:            SQUARE_THREE_QUADRANTS(1, 0, 0);
        !           726:        case 31+14:
        !           727:            SQUARE_THREE_QUADRANTS(0, 1, 90);
        !           728:        case 31+13:
        !           729:            SQUARE_THREE_QUADRANTS(-1, 0, 180);
        !           730:        case 31+11:
        !           731:            SQUARE_THREE_QUADRANTS(0, -1, 270);
        !           732: #undef SQUARE_THREE_QUADRANTS
        !           733:
        !           734: #define DIAMOND_SINGLE_QUADRANT(x, y, angle)                   \
        !           735:            DIAMOND_SINGLE_PIESLICE(x, y, 1)
        !           736:        case 47+1:
        !           737:            DIAMOND_SINGLE_QUADRANT(1, 0, 0);
        !           738:        case 47+2:
        !           739:            DIAMOND_SINGLE_QUADRANT(0, 1, 90);
        !           740:        case 47+4:
        !           741:            DIAMOND_SINGLE_QUADRANT(-1, 0, 180);
        !           742:        case 47+8:
        !           743:            DIAMOND_SINGLE_QUADRANT(0, -1, 270);
        !           744: #undef DIAMOND_SINGLE_QUADRANT
        !           745:
        !           746: #define DIAMOND_TWO_NEIGHBOR_QUADRANTS(x, y, angle)            \
        !           747:            DIAMOND_SINGLE_PIESLICE(x, y, 2)
        !           748:        case 47+3:
        !           749:            DIAMOND_TWO_NEIGHBOR_QUADRANTS(1, 0, 0);
        !           750:        case 47+6:
        !           751:            DIAMOND_TWO_NEIGHBOR_QUADRANTS(0, 1, 90);
        !           752:        case 47+12:
        !           753:            DIAMOND_TWO_NEIGHBOR_QUADRANTS(-1, 0, 180);
        !           754:        case 47+9:
        !           755:            DIAMOND_TWO_NEIGHBOR_QUADRANTS(0, -1, 270);
        !           756: #undef DIAMOND_TWO_NEIGHBOR_QUADRANTS
        !           757:
        !           758:
        !           759:        case 47+5:
        !           760:            DIAMOND_TWO_OPPOSING_QUADRANTS(1, 0, 0);
        !           761:        case 47+10:
        !           762:            DIAMOND_TWO_OPPOSING_QUADRANTS(0, 1, 90);
        !           763: #undef DIAMOND_TWO_OPPOSING_QUADRANTS
        !           764: #undef SQUARE_TWO_OPPOSING_QUADRANTS
        !           765:
        !           766: #define DIAMOND_THREE_QUADRANTS(x, y, angle)                   \
        !           767:            DIAMOND_SINGLE_PIESLICE(x, y, 3)
        !           768:        case 47+7:
        !           769:            DIAMOND_THREE_QUADRANTS(1, 0, 0);
        !           770:        case 47+14:
        !           771:            DIAMOND_THREE_QUADRANTS(0, 1, 90);
        !           772:        case 47+13:
        !           773:            DIAMOND_THREE_QUADRANTS(-1, 0, 180);
        !           774:        case 47+11:
        !           775:            DIAMOND_THREE_QUADRANTS(0, -1, 270);
        !           776: #undef DIAMOND_THREE_QUADRANTS
        !           777: #undef DIAMOND_SINGLE_PIESLICE
        !           778: #undef SQUARE_SINGLE_PIESLICE
        !           779:
        !           780:        default:
        !           781:            {
        !           782:            char temp[64];
        !           783:            sprintf(temp, "PDF: unknown point type number %d", number);
        !           784:            int_warn(temp,NO_CARET);
        !           785:            }
        !           786:        }
        !           787:     }
        !           788:
        !           789:     PDF_restore(myPDF);
        !           790:     PDF_xLast = x;
        !           791:     PDF_yLast = y;
        !           792: }
        !           793:
        !           794:
        !           795: TERM_PUBLIC int
        !           796: PDF_justify_text (enum JUSTIFY mode)
        !           797: {
        !           798:     PDF_TextJust = mode;
        !           799:     return (TRUE);
        !           800: }
        !           801:
        !           802:
        !           803: TERM_PUBLIC int
        !           804: PDF_text_angle (int ang)
        !           805: {
        !           806:     if (ang == 0 || ang == 1) {
        !           807:        /* FIXME: need to do this in a different way? */
        !           808:        PDF_TextAngle = ang;
        !           809:        return (TRUE);
        !           810:     }
        !           811:
        !           812:     return (FALSE);
        !           813: }
        !           814:
        !           815:
        !           816: TERM_PUBLIC void
        !           817: PDF_put_text (unsigned int x, unsigned int y, char *str)
        !           818: {
        !           819:     char *alignment = NULL;
        !           820:     double h = x, v = y;
        !           821:
        !           822:     PDF_PathClose ();
        !           823:
        !           824:     /* horizontal justification*/
        !           825:     switch (PDF_TextJust) {
        !           826:     case LEFT:
        !           827:        alignment = "left";
        !           828:        break;
        !           829:     case CENTRE:
        !           830:        alignment = "center";
        !           831:        break;
        !           832:     case RIGHT:
        !           833:        alignment = "right";
        !           834:        break;
        !           835:     }
        !           836:
        !           837:     /* vertical justification*/
        !           838:     switch (PDF_TextAngle) {
        !           839:     case 1:
        !           840:        h += (PDF_fontAscent - PDF_fontDescent) / 2;
        !           841:        break;          /* vertical text*/
        !           842:     default:
        !           843:        v -= (PDF_fontAscent - PDF_fontDescent) / 2;
        !           844:        break;          /* horizontal text*/
        !           845:     }
        !           846:
        !           847:     if (PDF_TextAngle) {
        !           848:        PDF_save(myPDF);
        !           849:        PDF_rotate(myPDF, 90);
        !           850:        PDF_show_boxed(myPDF, str, v , -h, 0, 0, alignment, NULL);
        !           851:        PDF_restore(myPDF);
        !           852:     } else {
        !           853:        PDF_show_boxed(myPDF, str, h , v, 0, 0, alignment, NULL);
        !           854:     }
        !           855:
        !           856: }
        !           857:
        !           858:
        !           859: TERM_PUBLIC int
        !           860: PDF_set_font (char *font)
        !           861: {
        !           862:     if (strlen (font) > 0) {   /* if available, parse the font specification ("fontname,fontsize")*/
        !           863:        short index;
        !           864:        char *token,
        !           865:            seps[] = ",", *buffer = (char *) malloc (strlen (font) + 1);
        !           866:
        !           867:        if (buffer == NULL)
        !           868:            return (FALSE);
        !           869:        strcpy (buffer, font);
        !           870:
        !           871:        for (token = strtok (buffer, seps), index = 1;
        !           872:             token != NULL; token = strtok (NULL, seps), index++
        !           873:            ) {
        !           874:            switch (index) {
        !           875:            case 1:
        !           876:                strcpy (PDF_fontNameCur, token);
        !           877:                break;  /* font name*/
        !           878:            case 2:
        !           879:                PDF_fontSizeCur = atoi (token);
        !           880:                break;  /* font size*/
        !           881:            default:
        !           882:                break;
        !           883:            }
        !           884:        }
        !           885:
        !           886:        free (buffer);
        !           887:     } else {                   /* otherwise simply reset the default font*/
        !           888:        strcpy (PDF_fontNameCur, PDF_fontNameDef);
        !           889:        PDF_fontSizeCur = PDF_fontSizeDef;
        !           890:     }
        !           891:
        !           892:
        !           893:     PDF_PathClose();
        !           894:     PDF_SetFont();
        !           895:     return (TRUE);
        !           896: }
        !           897:
        !           898: TERM_PUBLIC void
        !           899: PDF_boxfill(int style, unsigned int x1, unsigned int y1,
        !           900:            unsigned int width, unsigned int height)
        !           901: {
        !           902:     (void) style;              /* unused */
        !           903:     PDF_PathClose();
        !           904:     PDF_save(myPDF);
        !           905:     PDF_setgray(myPDF, 1);
        !           906:     PDF_moveto(myPDF, x1, y1);
        !           907:     PDF_lineto(myPDF, x1+width, y1);
        !           908:     PDF_lineto(myPDF, x1+width, y1+height);
        !           909:     PDF_lineto(myPDF, x1, y1+height);
        !           910:     PDF_fill(myPDF);
        !           911:     PDF_restore(myPDF);
        !           912: }
        !           913:
        !           914: #endif /* TERM_BODY */
        !           915:
        !           916: #ifdef TERM_TABLE
        !           917: TERM_TABLE_START (pdf_driver)
        !           918:     "pdf", "PDF (Portable Document File) file driver",
        !           919:     0 /* xmax */ , 0 /* ymax */ , 0 /* vchar */ , 0 /* hchar */ ,
        !           920:     0 /* vtic */ , 0 /* htic */ ,
        !           921:     PDF_options, PDF_init, PDF_reset, PDF_text, null_scale, PDF_graphics,
        !           922:     PDF_move, PDF_vector, PDF_linetype, PDF_put_text, PDF_text_angle,
        !           923:     PDF_justify_text, PDF_point, do_arrow, PDF_set_font, do_pointsize,
        !           924:     TERM_BINARY,
        !           925:     0 /* suspend */, 0 /* resume */ , PDF_boxfill, PDF_linewidth
        !           926: TERM_TABLE_END (pdf_driver)
        !           927: #undef LAST_TERM
        !           928: #define LAST_TERM pdf_driver
        !           929: #endif /* TERM_TABLE */
        !           930:
        !           931: #endif /* TERM_PROTO_ONLY */
        !           932:
        !           933: #ifdef TERM_HELP
        !           934:     START_HELP (pdf)
        !           935:     "1 pdf",
        !           936:     "?commands set terminal pdf",
        !           937:     "?set terminal pdf",
        !           938:     "?set term pdf",
        !           939:     "?terminal pdf",
        !           940:     "?term pdf",
        !           941:     "?pdf",
        !           942:     " This terminal produces files in the Adobe Portable Document Format",
        !           943:     " (PDF), useable for printing or display with tools like Acrobat Reader",
        !           944:     "",
        !           945:     " Syntax:",
        !           946:     "       set terminal pdf {fname \"<font>\"} {fsize <fontsize>}",
        !           947:     "",
        !           948:     " where <font> is the name of the default font to use (default Helvetica)",
        !           949:     " and <fontsize> is the font size (in points, default 12)"
        !           950:     END_HELP (pdf)
        !           951: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>