Annotation of OpenXM_contrib/gnuplot/term/emf.trm, Revision 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>