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

Annotation of OpenXM_contrib/gnuplot/term/emf.trm, Revision 1.1.1.1

1.1       ohara       1: /*
                      2:  * $Id: emf.trm,v 1.1.6.4 2002/01/26 19:05:34 lhecking Exp $
                      3:  */
                      4:
                      5: /* GNUPLOT - emf.trm */
                      6:
                      7: /*[
                      8:  * Copyright 1998
                      9:  *
                     10:  * Permission to use, copy, and distribute this software and its
                     11:  * documentation for any purpose with or without fee is hereby granted,
                     12:  * provided that the above copyright notice appear in all copies and
                     13:  * that both that copyright notice and this permission notice appear
                     14:  * in supporting documentation.
                     15:  *
                     16:  * Permission to modify the software is granted, but not the right to
                     17:  * distribute the complete modified source code.  Modifications are to
                     18:  * be distributed as patches to the released version.  Permission to
                     19:  * distribute binaries produced by compiling modified sources is granted,
                     20:  * provided you
                     21:  *   1. distribute the corresponding source modifications from the
                     22:  *    released version in the form of a patch file along with the binaries,
                     23:  *   2. add special version identification to distinguish your version
                     24:  *    in addition to the base release version number,
                     25:  *   3. provide your name and address as the primary contact for the
                     26:  *    support of your modified version, and
                     27:  *   4. retain our contact information in regard to use of the base
                     28:  *    software.
                     29:  * Permission to distribute the released version of the source code along
                     30:  * with corresponding source modifications in the form of a patch file is
                     31:  * granted with same provisions 2 through 4 for binary distributions.
                     32:  *
                     33:  * This software is provided "as is" without express or implied warranty
                     34:  * to the extent permitted by applicable law.
                     35: ]*/
                     36:
                     37: /*
                     38:  * This file is included by ../term.c and ../docs/termdoc.c.
                     39:  *
                     40:  * This terminal driver supports:
                     41:  *   Enhanced Metafile Format
                     42:  *
                     43:  * TODO
                     44:  *
                     45:  * HISTORY
                     46:  *
                     47:  * 1.0.5 2000/07/20
                     48:  * - Handles were not freed at all, resulting to resource leaks when viewing on Windows 9x (not on NT4/W2000!!!)
                     49:  * 1.0.4 2000/06/28
                     50:  * - Emulated dashed vectors are now looking better
                     51:  * - 15 colors * 8 pointstyles = 120 pointtypes
                     52:  * 1.0.3 2000/03/29
                     53:  * - default font is now Arial 12
                     54:  * - implemented options (color/mono,dashed/solid,font)
                     55:  * - 15 colors * 5 dashtypes = 75 linetypes
                     56:  * 1.0.2 2000/03/22
                     57:  * - Polygon and Polyline structures are not working for Windows 9X, I
                     58:  *   really don't know why, replaced with lineto/moveto couples...
                     59:  * - Texts are now displayed in GM_Compatible mode because GM_Advanced is
                     60:  *   displaying correctly but it does not print correctly with Word97!
                     61:  * - Text centering now works best according to escapement/orientation
                     62:  * - Now there is 8 colors * 5 dashtypes = 40 linetypes
                     63:  * - Successfully Working on Linux Suse 6.1 (x86)
                     64:  *
                     65:  * 1.0.1 2000/03/16
                     66:  * - Unicode text have be to long aligned in EMF files (exttextoutw)
                     67:  * - Problems with text transparence (SetBkMode was not called)
                     68:  * - Null brush created for *not* filling polygon
                     69:  *
                     70:  * 1.0.0 2000/03/15
                     71:  * - Only tested on x86 Win32
                     72:  *
                     73:  * AUTHOR
                     74:  *   Stephane Barbaray <stephane.barbaray@compodata.com>
                     75:  *   Some code based on cgm.trm
                     76:  *
                     77:  * send your comments or suggestions to (info-gnuplot@dartmouth.edu).
                     78:  */
                     79:
                     80: #include "driver.h"
                     81:
                     82: #ifdef TERM_REGISTER
                     83: register_term(emf)
                     84: #endif
                     85:
                     86: #ifdef TERM_PROTO
                     87: TERM_PUBLIC void EMF_options __PROTO((void));
                     88: TERM_PUBLIC void EMF_init __PROTO((void));
                     89: TERM_PUBLIC void EMF_reset __PROTO((void));
                     90: TERM_PUBLIC void EMF_text __PROTO((void));
                     91: TERM_PUBLIC void EMF_graphics __PROTO((void));
                     92: TERM_PUBLIC void EMF_move __PROTO((unsigned int x, unsigned int y));
                     93: TERM_PUBLIC void EMF_dashed_vector __PROTO((unsigned int ux, unsigned int uy));
                     94: TERM_PUBLIC void EMF_solid_vector __PROTO((unsigned int ux, unsigned int uy));
                     95: TERM_PUBLIC void EMF_linetype __PROTO((int linetype));
                     96: TERM_PUBLIC void EMF_linecolor __PROTO((int color));
                     97: TERM_PUBLIC void EMF_dashtype __PROTO((int dashtype));
                     98: TERM_PUBLIC void EMF_linewidth __PROTO((double width));
                     99: TERM_PUBLIC void EMF_put_text __PROTO((unsigned int x, unsigned int y, char *str));
                    100: TERM_PUBLIC int EMF_text_angle __PROTO((int ang));
                    101: TERM_PUBLIC int EMF_justify_text __PROTO((enum JUSTIFY mode));
                    102: TERM_PUBLIC void EMF_point __PROTO((unsigned int x, unsigned int y, int number));
                    103: TERM_PUBLIC void EMF_set_pointsize __PROTO((double size));
                    104: TERM_PUBLIC int EMF_set_font __PROTO((char *));
                    105:
                    106: #ifdef RGB
                    107: #undef RGB
                    108: #endif
                    109: #define RGB(r,g,b) ((long)(((unsigned char)(r)|((short)((unsigned char)(g))<<8))|(((long)(unsigned char)(b))<<16)))
                    110:
                    111: #ifndef min
                    112: #define min(a,b) (a<b?a:b)
                    113: #endif
                    114:
                    115: #ifndef max
                    116: #define max(a,b) (a>b?a:b)
                    117: #endif
                    118:
                    119: #define EMF_PX2HM 20
                    120: #define EMF_PT2HM 35.28
                    121: #define EMF_10THDEG2RAD (3.14159265359/1800)
                    122: #define EMF_XMAX (1024*EMF_PX2HM)
                    123: #define EMF_YMAX (768*EMF_PX2HM)
                    124: #define EMF_HTIC (EMF_XMAX/160)
                    125: #define EMF_VTIC EMF_HTIC
                    126: #define EMF_FONTNAME "Arial"
                    127: #define EMF_FONTSIZE 12
                    128: #define EMF_HCHAR (EMF_FONTSIZE*EMF_PT2HM)
                    129: #define EMF_VCHAR (EMF_FONTSIZE*EMF_PT2HM)
                    130: #define EMF_LINE_TYPES 5       /* number of line types we support */
                    131: #define EMF_COLORS 15          /* number of colors we support */
                    132: #define EMF_POINTS 8           /* number of markers we support */
                    133: #define EMF_MAX_SEGMENTS 104   /* maximum # polyline coordinates */
                    134:
                    135: #define EMF_HANDLE_PEN         1
                    136: #define EMF_HANDLE_FONT                2
                    137: #define EMF_HANDLE_BRUSH       3
                    138: #define EMF_HANDLE_MAX         4
                    139:
                    140: #define EMF_STOCK_OBJECT_FLAG  ((unsigned long)0x1 << 31)
                    141: #define EMF_STOCK_OBJECT_WHITE_BRUSH   (EMF_STOCK_OBJECT_FLAG + 0x00)
                    142: #define EMF_STOCK_OBJECT_BLACK_PEN     (EMF_STOCK_OBJECT_FLAG + 0x07)
                    143: #define EMF_STOCK_OBJECT_DEFAULT_FONT  (EMF_STOCK_OBJECT_FLAG + 0x0A)
                    144:
                    145: #define EMF_write_emr(type,size) {EMF_write_long(type);EMF_write_long(size);emf_record_count++;}
                    146: #define EMF_write_sizel(width,height) {EMF_write_long(width);EMF_write_long(height);}
                    147: #define EMF_write_points(x,y) {EMF_write_short(x);EMF_write_short(y);}
                    148: #define EMF_write_pointl(x,y) {EMF_write_long(x);EMF_write_long(y);}
                    149: #define EMF_write_rectl(left,top,right,bottom) {EMF_write_long(left);EMF_write_long(top);EMF_write_long(right);EMF_write_long(bottom);}
                    150:
                    151: #define EMF_EOF() {EMF_write_emr(14,20);EMF_write_long(0);EMF_write_long(0x10);EMF_write_long(20);}
                    152: #define EMF_SetMapMode(mode) {EMF_write_emr(17,0xc);EMF_write_long(mode);}
                    153: #define EMF_SetWindowExtEx(width,height) {EMF_write_emr(9,0x10);EMF_write_sizel(width,height);}
                    154: #define EMF_SetWindowOrgEx(width,height) {EMF_write_emr(10,0x10);EMF_write_sizel(width,height);}
                    155: #define EMF_SetViewportExtEx(width,height) {EMF_write_emr(11,0x10);EMF_write_sizel(width,height);}
                    156: #define EMF_SetViewportOrgEx(width,height) {EMF_write_emr(12,0x10);EMF_write_sizel(width,height);}
                    157: #define EMF_SetTextColor(color) {EMF_write_emr(24,0xc);EMF_write_long(color);}
                    158: #define EMF_MoveToEx(x,y) {EMF_write_emr(27,0x10);EMF_write_pointl(x,y);}
                    159: #define EMF_LineTo(x,y) {EMF_write_emr(54,0x10);EMF_write_pointl(x,y);}
                    160: #define EMF_CreatePen(handle,type,width,color) {EMF_write_emr(38,0x1C);EMF_write_long(handle);EMF_write_long(type);EMF_write_long(width);EMF_write_long(0);EMF_write_long(color);}
                    161: #define EMF_CreateBrush(handle,type,color,hatch) {EMF_write_emr(39,0x18);EMF_write_long(handle);EMF_write_long(type);EMF_write_long(color);EMF_write_long(hatch);}
                    162: #define EMF_SelectObject(handle) {EMF_write_emr(37,0x0C);EMF_write_long(handle);}
                    163: #define EMF_DeleteObject(handle) {EMF_write_emr(40,0x0C);EMF_write_long(handle);}
                    164: #define EMF_SetTextAlign(align) {EMF_write_emr(22,0x0C);EMF_write_long(align);}
                    165: #define EMF_SetBkMode(mode) {EMF_write_emr(18,0x0C);EMF_write_long(mode);}
                    166:
                    167: #endif /* TERM_PROTO */
                    168:
                    169: #ifndef TERM_PROTO_ONLY
                    170: #ifdef TERM_BODY
                    171:
                    172: /*
                    173:  * on NeXTstep, id is an identifier (in ObjC) and causes a parse error
                    174:  * since some asserts below are mistaken as casts. datum is a type
                    175:  * defined in ndbm.h which also causes a parse error (ndbm.h is
                    176:  * included as part of appkit.h, I think).  Strangely enough, both
                    177:  * errors only happen with cpp-precomp -smart, not with the regular
                    178:  * cpp. (AL)
                    179:  */
                    180:
                    181: #ifdef NEXT
                    182: #define id id_
                    183: #define datum datum_
                    184: #endif
                    185:
                    186: #include <ctype.h>             /* for isspace() */
                    187:
                    188: #ifndef assert
                    189: #define assert(x) 0            /* defeat assertions */
                    190: #endif
                    191:
                    192: /* uncomment the following to enable assertions for this module only,
                    193:    regardless of compiler switches */
                    194: #ifdef NDEBUG
                    195: #define DEFEAT_ASSERTIONS
                    196: #endif
                    197: #undef NDEBUG
                    198: #include <assert.h>
                    199:
                    200: static unsigned int emf_posx;
                    201: static unsigned int emf_posy;
                    202: static unsigned int emf_record_count = 0;
                    203: static unsigned int emf_linetype = 1;
                    204: static unsigned int emf_linewidth;     /* line width in plot units */
                    205: static unsigned int emf_dashtype = 0;
                    206: static unsigned long emf_color = 0L;
                    207: static unsigned int emf_polyline[EMF_MAX_SEGMENTS];    /* stored polyline coordinates */
                    208: static unsigned int emf_graphics = FALSE;
                    209: static unsigned int emf_dashed = TRUE;
                    210: static unsigned int emf_monochrome = FALSE;
                    211: static int emf_coords = 0;     /* # polyline coordinates saved */
                    212: static char emf_fontname[255] = EMF_FONTNAME;
                    213: static int emf_fontsize = EMF_FONTSIZE;
                    214: static char emf_defaultfontname[255] = EMF_FONTNAME;
                    215: static int emf_defaultfontsize = EMF_FONTSIZE;
                    216: enum JUSTIFY emf_justify = LEFT;
                    217: static int emf_vert_text = 0;  /* text orientation -- nonzero for vertical */
                    218: static int emf_step_sizes[8];  /* array of currently used dash lengths in plot units */
                    219: static int emf_step_index = 0; /* index into emf_step_sizes[] */
                    220: static int emf_step = 0;       /* amount of current dash not yet drawn, in plot units */
                    221: static int emf_tic, emf_tic707, emf_tic866, emf_tic500, emf_tic1241, emf_tic1077, emf_tic621;  /* marker dimensions */
                    222:
                    223: static void EMF_flush_polyline __PROTO((void));
                    224: static void EMF_flush_polygon __PROTO((void));
                    225: static void EMF_write_byte __PROTO((int)); /* HBB 20001102: was 'char'... */
                    226: static void EMF_write_short __PROTO((int)); /* HBB 20001102: was 'short' */
                    227: static void EMF_write_long __PROTO((unsigned long));
                    228: static void EMF_write_float __PROTO((double)); /* HBB 20001102: was 'float' */
                    229: static void EMF_setfont __PROTO((void));
                    230:
                    231: static void
                    232: EMF_setfont()
                    233: {
                    234:     int i, count;
                    235:     int bold = 400;
                    236:     char italic = 0, underline = 0, strikeout = 0;
                    237:     char font[32];
                    238:     char *sub;
                    239:
                    240:     if (!emf_graphics)
                    241:        return;
                    242:
                    243:     count = min (strlen(emf_fontname), 31);
                    244:     if (((sub = strstr(emf_fontname, " bold")) != NULL)
                    245:        || ((sub = strstr(emf_fontname, " Bold")) != NULL)) {
                    246:        bold = 700;
                    247:        count = min(sub - emf_fontname, count);
                    248:     }
                    249:     if (((sub = strstr(emf_fontname, " italic")) != NULL)
                    250:        || ((sub = strstr(emf_fontname, " Italic")) != NULL)) {
                    251:        italic = 1;
                    252:        count = min(sub - emf_fontname, count);
                    253:     }
                    254:     if (((sub = strstr(emf_fontname, " underline")) != NULL)
                    255:        || ((sub = strstr(emf_fontname, " Underline")) != NULL)) {
                    256:        underline = 1;
                    257:        count = min(sub - emf_fontname, count);
                    258:     }
                    259:     if (((sub = strstr(emf_fontname, " strikeout")) != NULL)
                    260:        || ((sub = strstr(emf_fontname, " Strikeout")) != NULL)
                    261:        || ((sub = strstr(emf_fontname, " StrikeOut")) != NULL)
                    262:        ) {
                    263:        strikeout = 1;
                    264:        count = min(sub - emf_fontname, count);
                    265:     }
                    266:
                    267:     safe_strncpy(font, emf_fontname, count + 1);
                    268:
                    269:     EMF_SelectObject(EMF_STOCK_OBJECT_DEFAULT_FONT);
                    270:     EMF_DeleteObject(EMF_HANDLE_FONT);
                    271:
                    272:     EMF_write_emr(82, 104);
                    273:     EMF_write_long(EMF_HANDLE_FONT);
                    274:     EMF_write_long((long) (emf_fontsize * EMF_PT2HM)); /* height */
                    275:     EMF_write_long(0);         /* width */
                    276:     EMF_write_long(emf_vert_text);     /* escapement */
                    277:     EMF_write_long(emf_vert_text);     /* orientation */
                    278:     EMF_write_long(bold);      /* weight */
                    279:     EMF_write_byte(italic);    /* italic */
                    280:     EMF_write_byte(underline); /* underline */
                    281:     EMF_write_byte(strikeout); /* strikeout */
                    282:     EMF_write_byte(1);         /* charset */
                    283:     EMF_write_byte(0);         /* out precision */
                    284:     EMF_write_byte(0);         /* clip precision */
                    285:     EMF_write_byte(0);         /* quality */
                    286:     EMF_write_byte(0);         /* pitch and family */
                    287:     for (i = 0; i < 32; i++) { /* face name (max 32) */
                    288:        EMF_write_byte((char) (i < strlen(font) ? font[i] : 0));
                    289:        EMF_write_byte(0);
                    290:     }
                    291:     EMF_SelectObject(EMF_HANDLE_FONT);
                    292: }
                    293:
                    294: static void
                    295: EMF_flush_polygon()
                    296: {
                    297:     if (emf_coords == 0)
                    298:        return;
                    299:     else {
                    300:        int i = 0;
                    301:        /* Polygon works for NT4 but not on W9x */
                    302: /*              EMF_write_emr(3,(7+emf_coords*2)*4);
                    303:    EMF_write_rectl(0,0,0,0);
                    304:    EMF_write_long(emf_coords);
                    305:    while(i < emf_coords*2)
                    306:    EMF_write_pointl(emf_polyline[i++],term->ymax-emf_polyline[i++]);
                    307:  */
                    308:        EMF_MoveToEx(emf_polyline[i++], term->ymax - emf_polyline[i++]);
                    309:        while (i < emf_coords * 2)
                    310:            EMF_LineTo(emf_polyline[i++], term->ymax - emf_polyline[i++]);
                    311:        EMF_LineTo(emf_polyline[0], term->ymax - emf_polyline[1]);
                    312:     }
                    313:     emf_coords = 0;
                    314: }
                    315:
                    316: static void
                    317: EMF_flush_polyline()
                    318: {
                    319:     if (emf_coords == 0)
                    320:        return;
                    321:     else if (emf_coords <= 2) {
                    322:        EMF_MoveToEx(emf_polyline[0], term->ymax - emf_polyline[1]);
                    323:        EMF_LineTo(emf_polyline[2], term->ymax - emf_polyline[3]);
                    324:     } else {
                    325:        int i = 0;
                    326:        /* Polyline works for NT4 but not on W9x */
                    327: /*              EMF_write_emr(4,(7+emf_coords*2)*4);
                    328:    EMF_write_rectl(0,0,0,0);
                    329:    EMF_write_long(emf_coords);
                    330:    while(i < emf_coords*2)
                    331:    EMF_write_pointl(emf_polyline[i++],term->ymax-emf_polyline[i++]);
                    332:  */
                    333:        EMF_MoveToEx(emf_polyline[i++], term->ymax - emf_polyline[i++]);
                    334:        while (i < emf_coords * 2)
                    335:            EMF_LineTo(emf_polyline[i++], term->ymax - emf_polyline[i++]);
                    336:     }
                    337:     emf_coords = 0;
                    338: }
                    339:
                    340: /* HBB 20001103: K&R'ized these 4 functions a bit better. */
                    341: static void
                    342: EMF_write_byte(value)
                    343:     int value;
                    344: {
                    345:     char c = value;
                    346:     fwrite(&c, 1, 1, gpoutfile);
                    347: }
                    348:
                    349: static void
                    350: EMF_write_short(value)
                    351:     int value;
                    352: {
                    353:     short int actual_value = value;
                    354:     char c[2];
                    355:
                    356:     c[1] = (actual_value >> 8) & 255;  /* convert to x86 order */
                    357:     c[0] = actual_value & 255;
                    358:
                    359:     fwrite(c, 1, 2, gpoutfile);
                    360: }
                    361:
                    362: static void
                    363: EMF_write_long(value)
                    364:     unsigned long value;
                    365: {
                    366:     char c[4];
                    367:
                    368:     c[3] = (value >> 24) & 0xFFL;      /* convert to x86 order */
                    369:     c[2] = (value >> 16) & 0xFFL;
                    370:     c[1] = (value >> 8) & 0xFFL;
                    371:     c[0] = value & 0xFFL;
                    372:
                    373:     fwrite(c, 1, 4, gpoutfile);
                    374: }
                    375:
                    376: /* FIXME HBB 20001103: this only works as given iff 'float' is the
                    377:  * same format as on x86's, i.e. IEEE 4-byte floating point format */
                    378: static void
                    379: EMF_write_float(value)
                    380:     double value;
                    381: {
                    382:     char c[4];
                    383:
                    384:     union {
                    385:        long l;
                    386:        float f;
                    387:     } u;
                    388:
                    389:     u.f = value;
                    390:
                    391:     c[3] = (u.l >> 24) & 0xFFL;        /* convert to x86 order */
                    392:     c[2] = (u.l >> 16) & 0xFFL;
                    393:     c[1] = (u.l >> 8) & 0xFFL;
                    394:     c[0] = u.l & 0xFFL;
                    395:
                    396:     fwrite(c, 1, 4, gpoutfile);
                    397: }
                    398:
                    399: TERM_PUBLIC void
                    400: EMF_options()
                    401: {
                    402:     term->xmax = EMF_XMAX;
                    403:     term->ymax = EMF_YMAX;
                    404:     emf_dashed = TRUE;
                    405:     emf_monochrome = FALSE;
                    406:     while (!END_OF_COMMAND) {
                    407:        if (almost_equals(c_token, "de$fault")) {
                    408:            strcpy(emf_defaultfontname, EMF_FONTNAME);
                    409:            emf_defaultfontsize = EMF_FONTSIZE;
                    410:            emf_monochrome = FALSE;
                    411:            emf_dashed = TRUE;
                    412:            c_token++;
                    413:            continue;
                    414:        }
                    415:        if (almost_equals(c_token, "m$onochrome")) {
                    416:            emf_monochrome = TRUE;
                    417:            c_token++;
                    418:            continue;
                    419:        }
                    420:        if (almost_equals(c_token, "c$olor") || almost_equals(c_token, "c$olour")) {
                    421:            emf_monochrome = FALSE;
                    422:            c_token++;
                    423:            continue;
                    424:        }
                    425:        if (almost_equals(c_token, "da$shed")) {
                    426:            emf_dashed = TRUE;
                    427:            c_token++;
                    428:            continue;
                    429:        }
                    430:        if (almost_equals(c_token, "s$olid")) {
                    431:            emf_dashed = FALSE;
                    432:            c_token++;
                    433:            continue;
                    434:        }
                    435:        break;
                    436:     }
                    437:     if (!END_OF_COMMAND && isstring(c_token)) {
                    438:        quote_str(emf_defaultfontname, c_token, MAX_ID_LEN);
                    439:        c_token++;
                    440:     }
                    441:     if (!END_OF_COMMAND) {
                    442:        /* We have font size specified */
                    443:        struct value a;
                    444:        emf_defaultfontsize = (int) real(const_express(&a));
                    445:     }
                    446:     EMF_set_font(NULL);                /* set default font */
                    447:
                    448:     sprintf(term_options, "%s %s \"%s\" %d",
                    449:            emf_monochrome ? "monochrome" : "color",
                    450:            emf_dashed ? "dashed" : "solid",
                    451:            emf_defaultfontname, emf_defaultfontsize);
                    452: }
                    453:
                    454: TERM_PUBLIC void
                    455: EMF_init()
                    456: {
                    457:     emf_posx = emf_posy = 0;
                    458:     emf_linetype = 0;
                    459:     emf_vert_text = 0;
                    460:     emf_graphics = FALSE;
                    461: }
                    462:
                    463: TERM_PUBLIC void
                    464: EMF_graphics()
                    465: {
                    466:     /* header start */
                    467:     emf_record_count = 0;
                    468:     EMF_write_emr(1, 100);
                    469:     EMF_write_long(0);         /* rclBounds */
                    470:     EMF_write_long(0);
                    471:     EMF_write_long(term->xmax / 20);
                    472:     EMF_write_long(term->ymax / 20);
                    473:     EMF_write_long(0);         /* rclFrame */
                    474:     EMF_write_long(0);
                    475:     EMF_write_long(term->xmax);
                    476:     EMF_write_long(term->ymax);
                    477:     EMF_write_long(0x464D4520);        /* signature */
                    478:     EMF_write_long(0x00010000);        /* version */
                    479:     EMF_write_long(0);         /* nBytes */
                    480:     EMF_write_long(0);         /* nRecords */
                    481:     EMF_write_short(EMF_HANDLE_MAX);   /* nHandles */
                    482:     EMF_write_short(0);                /* reserved */
                    483:     EMF_write_long(0);         /* descSize */
                    484:     EMF_write_long(0);         /* descOff */
                    485:     EMF_write_long(0);         /* nPalEntries */
                    486:     EMF_write_long(1600);      /* ref dev pixwidth */
                    487:     EMF_write_long(1200);      /* ref dev pixheight */
                    488:     EMF_write_long(320);       /* ref dev mwidth */
                    489:     EMF_write_long(240);       /* ref dev mheight */
                    490:     EMF_write_long(0);         /* cbPixelFormat  */
                    491:     EMF_write_long(0);         /* offPixelFormat  */
                    492:     EMF_write_long(0);         /* bOpenGL */
                    493:     emf_graphics = TRUE;
                    494:     /* header end */
                    495:
                    496:     EMF_SetMapMode(8);         /* forcing anisotropic mode */
                    497:     EMF_SetWindowExtEx(term->xmax, term->ymax);                /* setting logical (himetric) size      */
                    498:     EMF_SetViewportExtEx(term->xmax / 20, term->ymax / 20);    /* setting device (pixel) size */
                    499:     EMF_CreatePen(EMF_HANDLE_PEN, 0, 1, 0x000000);     /* init default pen */
                    500:     EMF_SelectObject(EMF_HANDLE_PEN);
                    501:     EMF_SetBkMode(1);          /* transparent background for text */
                    502:     EMF_CreateBrush(EMF_HANDLE_BRUSH, 1, 0, 0);                /* transparent brush for polygons */
                    503:     EMF_SelectObject(EMF_HANDLE_BRUSH);
                    504:     EMF_set_font(NULL);                /* init default font */
                    505: }
                    506:
                    507: TERM_PUBLIC int
                    508: EMF_set_font(char *font)
                    509: {
                    510:     int sep;                   /* hope this function exist everywhere... */
                    511:
                    512:     if (font && *font) {
                    513:        char *comma = strchr(font, ',');
                    514:        if (comma == NULL)
                    515:            return FALSE;       /* bad format */
                    516:        sep = comma - font;
                    517:        safe_strncpy(emf_fontname, font, min(sep + 1, 32));
                    518:        emf_fontsize = atoi(&font[sep + 1]);
                    519:     } else {
                    520:        strcpy(emf_fontname, emf_defaultfontname);
                    521:        emf_fontsize = emf_defaultfontsize;
                    522:     }
                    523:     term->h_char = (emf_fontsize * EMF_PT2HM);
                    524:     term->v_char = (emf_fontsize * EMF_PT2HM);
                    525:     EMF_setfont();
                    526:     return TRUE;
                    527: }
                    528:
                    529: TERM_PUBLIC void
                    530: EMF_text()
                    531: {
                    532:     long pos;
                    533:     EMF_flush_polyline();
                    534:
                    535:     /* writing end of metafile */
                    536:     EMF_SelectObject(EMF_STOCK_OBJECT_DEFAULT_FONT);
                    537:     EMF_DeleteObject(EMF_HANDLE_FONT);
                    538:     EMF_SelectObject(EMF_STOCK_OBJECT_BLACK_PEN);
                    539:     EMF_DeleteObject(EMF_HANDLE_PEN);
                    540:     EMF_SelectObject(EMF_STOCK_OBJECT_WHITE_BRUSH);
                    541:     EMF_DeleteObject(EMF_HANDLE_BRUSH);
                    542:     EMF_EOF();
                    543:
                    544:     /* updating header */
                    545:     pos = ftell(gpoutfile);
                    546:     fseek(gpoutfile, 48, SEEK_SET);
                    547:     EMF_write_long(pos);
                    548:     EMF_write_long(emf_record_count);
                    549:     /* HBB 20010228: have to make known that we're no longer in graphics
                    550:      * status. */
                    551:     emf_graphics = FALSE;
                    552: }
                    553:
                    554: TERM_PUBLIC void
                    555: EMF_linetype(linetype)
                    556: int linetype;
                    557: {
                    558:     /* Note : separating linetype and color would have not been futile, but anyway... */
                    559:
                    560:     assert(linetype >= -2);
                    561:     if (linetype == emf_linetype)
                    562:        return;
                    563:     emf_linetype = linetype;
                    564:
                    565:     EMF_linecolor(linetype);
                    566:     EMF_dashtype(linetype);
                    567: }
                    568:
                    569: TERM_PUBLIC void
                    570: EMF_linecolor(linecolor)
                    571: int linecolor;
                    572: {
                    573:     static long GPFAR color_table_data[] =
                    574:     {
                    575:        RGB(255, 0, 0),         /* red */
                    576:        RGB(0, 255, 0),         /* green */
                    577:        RGB(0, 0, 255),         /* blue */
                    578:        RGB(255, 0, 255),       /* magenta */
                    579:        RGB(0, 0, 128),         /* dark blue */
                    580:        RGB(128, 0, 0),         /* dark red */
                    581:        RGB(0, 128, 128),       /* dark cyan */
                    582:        RGB(0, 0, 0),           /* black */
                    583:        RGB(128, 128, 128),     /* grey */
                    584:        RGB(0, 128, 64),        /* very dark cyan */
                    585:        RGB(128, 128, 0),       /* dark yellow */
                    586:        RGB(128, 0, 128),       /* dark magenta */
                    587:        RGB(192, 192, 192),     /* light grey */
                    588:        RGB(0, 255, 255),       /* cyan */
                    589:        RGB(255, 255, 0),       /* yellow */
                    590:     };
                    591:
                    592:     assert(linecolor >= -2);
                    593:     linecolor = (linecolor < 0 || emf_monochrome) ? 7 : (linecolor % EMF_COLORS);
                    594:     if (color_table_data[linecolor] == emf_color)
                    595:        return;
                    596:     emf_color = color_table_data[linecolor];
                    597:
                    598:     EMF_flush_polyline();
                    599: }
                    600:
                    601: TERM_PUBLIC void
                    602: EMF_linewidth(width)
                    603: double width;
                    604: {
                    605:     assert(width >= 0);
                    606:     if (width == emf_linewidth)
                    607:        return;
                    608:     emf_linewidth = width;
                    609:
                    610:     EMF_dashtype(emf_dashtype);        /* have dash lengths recalculated */
                    611: }
                    612:
                    613: TERM_PUBLIC void
                    614: EMF_dashtype(dashtype)
                    615:     int dashtype;
                    616: {
                    617:     int i, j;
                    618:     /* Each group of 8 entries in dot_length[] defines a dash
                    619:        pattern.  Entries in each group are alternately length of
                    620:        whitespace and length of line, in units of 2/3 of the
                    621:        linewidth. */
                    622:     static int dot_length[EMF_LINE_TYPES * 8] =
                    623:     {                          /* 0 - solid             */
                    624:        5, 8, 5, 8, 5, 8, 5, 8, /* 1 - dashes            */
                    625:        4, 2, 4, 2, 4, 2, 4, 2, /* 2 - dotted            */
                    626:        4, 8, 4, 2, 4, 8, 4, 2, /* 3 - dash-dot          */
                    627:        4, 9, 4, 2, 4, 2, 0, 0, /* 4 - dash-dot-dot      */
                    628:     };
                    629:
                    630:
                    631:     assert(dashtype >= -2);
                    632:     if (dashtype == emf_dashtype)
                    633:        return;
                    634:
                    635:     emf_dashtype = dashtype;
                    636:
                    637:     EMF_flush_polyline();
                    638:
                    639:     if (dashtype >= 0)
                    640:        dashtype = (dashtype / EMF_COLORS) % EMF_LINE_TYPES;
                    641:
                    642:     if (dashtype < 1 || !emf_dashed) { /* solid mode */
                    643:        EMF_SelectObject(EMF_STOCK_OBJECT_BLACK_PEN);
                    644:        EMF_DeleteObject(EMF_HANDLE_PEN);
                    645:        EMF_CreatePen(EMF_HANDLE_PEN, 0, emf_linewidth * EMF_PX2HM, emf_color);
                    646:        EMF_SelectObject(EMF_HANDLE_PEN);
                    647:
                    648:        term->vector = EMF_solid_vector;
                    649:     } else {                   /* Since win32 dashed lines works only with 1 pixel linewith we must emulate */
                    650:        EMF_SelectObject(EMF_STOCK_OBJECT_BLACK_PEN);
                    651:        EMF_DeleteObject(EMF_HANDLE_PEN);
                    652:        EMF_CreatePen(EMF_HANDLE_PEN, 0, emf_linewidth * EMF_PX2HM, emf_color);
                    653:        EMF_SelectObject(EMF_HANDLE_PEN);
                    654:
                    655:        term->vector = EMF_dashed_vector;
                    656:
                    657:        /* set up dash dimensions */
                    658:        j = (dashtype - 1) * 8;
                    659:        for (i = 0; i < 8; i++, j++) {
                    660:            if (dot_length[j])
                    661:                emf_step_sizes[i] = (dot_length[j] * emf_linewidth * EMF_PX2HM) * 3 / 3;
                    662:            else
                    663:                emf_step_sizes[i] = 0;
                    664:        }
                    665:        /* first thing drawn will be a line */
                    666:        emf_step = emf_step_sizes[1];
                    667:        emf_step_index = 1;
                    668:     }
                    669: }
                    670:
                    671: TERM_PUBLIC void
                    672: EMF_move(x, y)
                    673: unsigned int x, y;
                    674: {
                    675:     assert(x < term->xmax && y < term->ymax);
                    676:     if (x == emf_posx && y == emf_posy)
                    677:        return;
                    678:     EMF_flush_polyline();
                    679:     emf_posx = x;
                    680:     emf_posy = y;
                    681: }
                    682:
                    683: TERM_PUBLIC void
                    684: EMF_dashed_vector(ux, uy)
                    685: unsigned int ux, uy;
                    686: {
                    687:     int xa, ya;
                    688:     int dx, dy, adx, ady;
                    689:     int dist;                  /* approximate distance in plot units from starting point to specified end point. */
                    690:     long remain;               /* approximate distance in plot units remaining to specified end point. */
                    691:
                    692:     assert(ux < term->xmax && uy < term->ymax);
                    693:
                    694:     dx = (ux - emf_posx);
                    695:     dy = (uy - emf_posy);
                    696:     adx = abs(dx);
                    697:     ady = abs(dy * 10);
                    698:
                    699:     /* using the approximation sqrt(x**2 + y**2)  ~  x + (5*x*x)/(12*y)   when x > y.
                    700:        Note ordering of calculations to avoid overflow on 16 bit architectures */
                    701:     if (10 * adx < ady)
                    702:        dist = (ady / 2 + 25 * adx / ady * adx / 6 * 5) / 5;
                    703:     else {
                    704:        if (adx == 0)
                    705:            return;
                    706:        dist = (adx * 10 + (ady / 24) * (ady / adx)) / 10;
                    707:     }
                    708:     remain = dist;
                    709:     xa = emf_posx;
                    710:     ya = emf_posy;
                    711:     while (remain > emf_step) {
                    712:        remain -= emf_step;
                    713:        if (emf_step_index & 1)
                    714:            EMF_solid_vector((int) (ux - (remain * dx) / dist), (int) (uy - (remain * dy) / dist));
                    715:        else {
                    716:            xa = (int) (ux - (remain * dx) / dist);
                    717:            ya = (int) (uy - (remain * dy) / dist);
                    718:            EMF_move(xa, ya);
                    719:        }
                    720:        if (++emf_step_index >= 8)
                    721:            emf_step_index = 0;
                    722:        emf_step = emf_step_sizes[emf_step_index];
                    723:     }
                    724:     if (emf_step_index & 1)
                    725:        EMF_solid_vector(ux, uy);
                    726:     else
                    727:        EMF_move(ux, uy);
                    728:     emf_step -= (int) remain;
                    729: }
                    730:
                    731: TERM_PUBLIC void
                    732: EMF_solid_vector(ux, uy)
                    733: unsigned int ux, uy;
                    734: {
                    735:     assert(ux < term->xmax && uy < term->ymax);
                    736:     if (ux == emf_posx && uy == emf_posy)
                    737:        return;
                    738:     if (emf_coords * 2 > EMF_MAX_SEGMENTS - 2)
                    739:        EMF_flush_polyline();
                    740:     if (emf_coords == 0) {
                    741:        emf_polyline[0] = emf_posx;
                    742:        emf_polyline[1] = emf_posy;
                    743:        emf_coords++;
                    744:     }
                    745:     emf_posx = emf_polyline[emf_coords * 2] = ux;
                    746:     emf_posy = emf_polyline[emf_coords * 2 + 1] = uy;
                    747:     emf_coords++;
                    748: }
                    749:
                    750: TERM_PUBLIC void
                    751: EMF_put_text(x, y, str)
                    752: unsigned int x, y;
                    753: char str[];
                    754: {
                    755:     int i, len = strlen(str);
                    756:     if (len % 2)               /* Must be long aligned! */
                    757:        len++;
                    758:     EMF_flush_polyline();
                    759:     EMF_SetTextColor(emf_color);       /* since text doesn't use pens, we must initialize with this */
                    760:     EMF_write_emr(84, 76 + len * 2);   /* exttextoutw, yes it's the 16bits char version! */
                    761:     EMF_write_rectl(0, 0, 0, 0);       /* bounding, never used */
                    762:     EMF_write_long(1);         /* GM_Compatible mode for advanced scaling */
                    763:     EMF_write_float(EMF_PX2HM);        /* x scale */
                    764:     EMF_write_float(EMF_PX2HM);        /* y scale */
                    765:     EMF_write_pointl(x + (long) ((EMF_VCHAR / 2) * sin(emf_vert_text * EMF_10THDEG2RAD)), term->ymax - y + (long) ((EMF_VCHAR / 2) * cos(emf_vert_text * EMF_10THDEG2RAD)));   /* positioning... y is recentered from bottom reference set in text align */
                    766:     EMF_write_long(strlen(str));       /* real char size */
                    767:     EMF_write_long(76);                /* offset to text */
                    768:     EMF_write_long(0);         /* options, none */
                    769:     EMF_write_rectl(0, 0, 0, 0);       /* rectangle clipping not used */
                    770:     EMF_write_long(0);         /* offset to dx, can't be used since really we don't know anything about the face properties used */
                    771:
                    772:     for (i = 0; i < len; i++) {        /* it is safe to go up to strlen+1 for aligning to long */
                    773:        char pad = 0;
                    774:        fwrite(&str[i], 1, 1, gpoutfile);
                    775:        fwrite(&pad, 1, 1, gpoutfile);
                    776:     }
                    777:     emf_posx = emf_posy = -2000;
                    778: }
                    779:
                    780: TERM_PUBLIC int
                    781: EMF_text_angle(ang)
                    782: int ang;
                    783: {
                    784:     /* Note : why did they use choose only 0 and 1? That's stupid! */
                    785:     /* Win GDI rotation is scaled in tenth of degrees, so... */
                    786:     switch (ang) {
                    787:     case 0:                    /* left right */
                    788:        if (emf_vert_text != 0) {
                    789:            emf_vert_text = 0;
                    790:            EMF_setfont();
                    791:        }
                    792:        break;
                    793:     case 1:                    /* bottom up */
                    794:        if (emf_vert_text != 900) {
                    795:            emf_vert_text = 900;
                    796:            EMF_setfont();
                    797:        }
                    798:        break;
                    799:     }
                    800:     return TRUE;
                    801: }
                    802:
                    803: TERM_PUBLIC int
                    804: EMF_justify_text(mode)
                    805: enum JUSTIFY mode;
                    806: {
                    807:     int align = 8;             /* y referenced to bottom */
                    808:     switch (mode) {
                    809:     case LEFT:
                    810:        align |= 0;
                    811:        break;
                    812:     case RIGHT:
                    813:        align |= 2;
                    814:        break;
                    815:     case CENTRE:
                    816:        align |= 6;
                    817:        break;
                    818:     }
                    819:     EMF_SetTextAlign(align);
                    820:     return (TRUE);
                    821: }
                    822:
                    823: TERM_PUBLIC void
                    824: EMF_reset()
                    825: {
                    826:     emf_posx = emf_posy = 0;
                    827:     emf_graphics = FALSE;
                    828: }
                    829:
                    830: TERM_PUBLIC void
                    831: EMF_point(x, y, number)
                    832: unsigned int x, y;
                    833: int number;
                    834: {
                    835:     int old_dashtype;
                    836:     unsigned long old_linecolor;
                    837:
                    838:     EMF_flush_polyline();
                    839:     old_dashtype = emf_dashtype;
                    840:     old_linecolor = emf_color;
                    841:     EMF_linecolor(number);
                    842:     EMF_dashtype(number % EMF_COLORS);
                    843:
                    844:     if (number < 0) {          /* draw dot */
                    845:        EMF_move(x, y);
                    846:        EMF_solid_vector(x + 1, y);
                    847:        goto end_points;
                    848:     }
                    849:     number = (number / EMF_COLORS) % EMF_POINTS;
                    850:
                    851:     switch (number) {
                    852:     case 0:                    /* draw diamond */
                    853:        EMF_move(x - emf_tic, y);
                    854:        EMF_solid_vector(x, y - emf_tic);
                    855:        EMF_solid_vector(x + emf_tic, y);
                    856:        EMF_solid_vector(x, y + emf_tic);
                    857:        EMF_flush_polygon();
                    858:        break;
                    859:     case 1:                    /* draw plus */
                    860:        EMF_move(x - emf_tic, y);
                    861:        EMF_solid_vector(x + emf_tic, y);
                    862:        EMF_move(x, y - emf_tic);
                    863:        EMF_solid_vector(x, y + emf_tic);
                    864:        break;
                    865:     case 2:                    /* draw box */
                    866:        EMF_move(x - emf_tic707, y - emf_tic707);
                    867:        EMF_solid_vector(x + emf_tic707, y - emf_tic707);
                    868:        EMF_solid_vector(x + emf_tic707, y + emf_tic707);
                    869:        EMF_solid_vector(x - emf_tic707, y + emf_tic707);
                    870:        EMF_flush_polygon();
                    871:        break;
                    872:     case 3:                    /* draw X */
                    873:        EMF_move(x - emf_tic707, y - emf_tic707);
                    874:        EMF_solid_vector(x + emf_tic707, y + emf_tic707);
                    875:        EMF_move(x - emf_tic707, y + emf_tic707);
                    876:        EMF_solid_vector(x + emf_tic707, y - emf_tic707);
                    877:        break;
                    878:     case 4:                    /* draw triangle (point up) */
                    879:        EMF_move(x, y + emf_tic1241);
                    880:        EMF_solid_vector(x - emf_tic1077, y - emf_tic621);
                    881:        EMF_solid_vector(x + emf_tic1077, y - emf_tic621);
                    882:        EMF_flush_polygon();
                    883:        break;
                    884:     case 5:                    /* draw star (asterisk) */
                    885:        EMF_move(x, y - emf_tic);
                    886:        EMF_solid_vector(x, y + emf_tic);
                    887:        EMF_move(x + emf_tic866, y - emf_tic500);
                    888:        EMF_solid_vector(x - emf_tic866, y + emf_tic500);
                    889:        EMF_move(x + emf_tic866, y + emf_tic500);
                    890:        EMF_solid_vector(x - emf_tic866, y - emf_tic500);
                    891:        break;
                    892:     case 6:                    /* draw triangle (point down) */
                    893:        EMF_move(x, y - emf_tic1241);
                    894:        EMF_solid_vector(x - emf_tic1077, y + emf_tic621);
                    895:        EMF_solid_vector(x + emf_tic1077, y + emf_tic621);
                    896:        EMF_flush_polygon();
                    897:        break;
                    898:     case 7:                    /* draw circle (actually, dodecagon)
                    899:                                   (WinWord 6 accepts the CGM "circle"
                    900:                                   element, but the resulting circle
                    901:                                   is not correctly centered!) */
                    902:        EMF_move(x, y - emf_tic);
                    903:        EMF_solid_vector(x + emf_tic500, y - emf_tic866);
                    904:        EMF_solid_vector(x + emf_tic866, y - emf_tic500);
                    905:        EMF_solid_vector(x + emf_tic, y);
                    906:        EMF_solid_vector(x + emf_tic866, y + emf_tic500);
                    907:        EMF_solid_vector(x + emf_tic500, y + emf_tic866);
                    908:        EMF_solid_vector(x, y + emf_tic);
                    909:        EMF_solid_vector(x - emf_tic500, y + emf_tic866);
                    910:        EMF_solid_vector(x - emf_tic866, y + emf_tic500);
                    911:        EMF_solid_vector(x - emf_tic, y);
                    912:        EMF_solid_vector(x - emf_tic866, y - emf_tic500);
                    913:        EMF_solid_vector(x - emf_tic500, y - emf_tic866);
                    914:        EMF_flush_polygon();
                    915:        break;
                    916:     }
                    917:   end_points:
                    918:     emf_color = old_linecolor;
                    919:     EMF_dashtype(old_dashtype);
                    920: }
                    921:
                    922:
                    923: TERM_PUBLIC void
                    924: EMF_set_pointsize(size)
                    925: double size;
                    926: {
                    927:     emf_tic = (size * term->h_tic / 2);
                    928:     emf_tic707 = emf_tic * 12 / 17;
                    929:     emf_tic866 = emf_tic * 13 / 15;
                    930:     emf_tic500 = emf_tic / 2;
                    931:     emf_tic1241 = emf_tic * 36 / 29;
                    932:     emf_tic1077 = emf_tic * 14 / 13;
                    933:     emf_tic621 = emf_tic * 18 / 29;
                    934: }
                    935:
                    936: #ifdef DEFEAT_ASSERTIONS
                    937: #define NDEBUG
                    938: #include <assert.h>
                    939: #undef DEFEAT_ASSERTIONS
                    940: #endif /* DEFEAT_ASSERTIONS */
                    941:
                    942: #ifdef NEXT
                    943: #undef id
                    944: #undef datum
                    945: #endif
                    946:
                    947: #endif /* TERM_BODY */
                    948:
                    949: #ifdef TERM_TABLE
                    950: TERM_TABLE_START(emf_driver)
                    951: "emf", "Enhanced Metafile format",
                    952: EMF_XMAX, EMF_YMAX, EMF_VCHAR, EMF_HCHAR,
                    953: EMF_VTIC, EMF_HTIC, EMF_options, EMF_init, EMF_reset,
                    954: EMF_text, null_scale, EMF_graphics, EMF_move, EMF_solid_vector,
                    955: EMF_linetype, EMF_put_text, EMF_text_angle,
                    956: EMF_justify_text, EMF_point, do_arrow, EMF_set_font,
                    957: EMF_set_pointsize,
                    958: TERM_BINARY,                   /* various flags */
                    959: NULL,                          /* after one plot of multiplot */
                    960: NULL,                          /* before subsequent plot of multiplot */
                    961: NULL,                          /* clear part of multiplot */
                    962: EMF_linewidth
                    963: TERM_TABLE_END(emf_driver)
                    964: #undef LAST_TERM
                    965: #define LAST_TERM emf_driver
                    966:
                    967: #endif /* TERM_TABLE */
                    968: #endif /* TERM_PROTO_ONLY */
                    969:
                    970: #ifdef TERM_HELP
                    971: START_HELP(emf)
                    972: "1 emf",
                    973: "?commands set terminal emf",
                    974: "?set terminal emf",
                    975: "?set term emf",
                    976: "?terminal emf",
                    977: "?term emf",
                    978: "?emf",
                    979: " The `emf` terminal generates an Enhanced Metafile Format file.  This file format",
                    980: " is the metafile standard on MS Win32 Systems"
                    981: "",
                    982: " Syntax:",
                    983: "       set terminal emf {<color>} {solid | dashed}",
                    984: "                        {\"<font>\"} {<fontsize>}",
                    985: "",
                    986: " <color> is either `color` or `monochrome`; ",
                    987: " `solid` draws all curves with solid lines, overriding any dashed patterns;",
                    988: " <font> is the name of a font; and ",
                    989: " `<fontsize>` is the size of the font in points.",
                    990: "",
                    991: " The first two options can be in any order.  Selecting `default` sets all",
                    992: " options to their default values.",
                    993: "",
                    994: " Examples:",
                    995: "       set terminal emf 'Times Roman Italic' 12",
                    996: "       set terminal emf color solid    # no pesky dashes!"
                    997: END_HELP(emf)
                    998: #endif /* TERM_HELP */

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