1/* Hello, Emacs, this is -*-C-*- */ 2 3/* GNUPLOT -- mif.trm */ 4 5/*[ 6 * Copyright 1992, 1993, 1998, 2004 7 * 8 * Permission to use, copy, and distribute this software and its 9 * documentation for any purpose with or without fee is hereby granted, 10 * provided that the above copyright notice appear in all copies and 11 * that both that copyright notice and this permission notice appear 12 * in supporting documentation. 13 * 14 * Permission to modify the software is granted, but not the right to 15 * distribute the complete modified source code. Modifications are to 16 * be distributed as patches to the released version. Permission to 17 * distribute binaries produced by compiling modified sources is granted, 18 * provided you 19 * 1. distribute the corresponding source modifications from the 20 * released version in the form of a patch file along with the binaries, 21 * 2. add special version identification to distinguish your version 22 * in addition to the base release version number, 23 * 3. provide your name and address as the primary contact for the 24 * support of your modified version, and 25 * 4. retain our contact information in regard to use of the base 26 * software. 27 * Permission to distribute the released version of the source code along 28 * with corresponding source modifications in the form of a patch file is 29 * granted with same provisions 2 through 4 for binary distributions. 30 * 31 * This software is provided "as is" without express or implied warranty 32 * to the extent permitted by applicable law. 33]*/ 34 35/* 36 * This file is included by ../term.c. 37 * 38 * This terminal driver was developed for 39 * gnuplot for unix version 3.0 (patchlevel 1) 40 * gnuplot for unix version 3.2 (patchlevel 2) 41 * 42 * This terminal driver supports: 43 * Frame Maker MIF format version 3.00 44 * 45 * Options for this terminal driver (set terminal mif [options]): 46 * colour / Draw primitives with line types >= 0 in colour (sep. 2-7) 47 * monochrome Draw primitives in black (sep. 0) 48 * 49 * polyline / Draw lines as continuous curves 50 * vectors Draw lines as collections of vectors 51 * 52 * help / ? Print short usage description on stderr 53 * 54 * Properties for this terminal driver: 55 * -Gnuplot size of worksheet: MIF_XMAX * MIF_YMAX 56 * -Unit in MIF output: cm 57 * -Plot primitives with the same pen will 58 * be grouped in the same MIF group. 59 * -Plot primitives with line types >= 0 60 * will as default be drawn in colour. 61 * -Lines are plotted as collections of 62 * vectors, or as continuous lines (default) 63 * -Plot primitives in a plot will be in a 64 * Frame in MIF. Several plot Frames will 65 * be collected in one large Frame. 66 * -Point size of MIF output characters: MIF_PSIZE 67 * -Used font for MIF output characters: Times 68 * -Supports vertical text 69 * -points and dots as characters 70 * -character formats for TextLines 71 * 72 * AUTHORS: 73 * Olof Franksson, Physics IV, KTH, S-100 44 Stockholm, Sweden 74 * 75 * NEW TERMINAL FORMAT: David C. Schooley 76 77 * COMMENTS: 78 * Send comments and/or suggestions to olof@fysik4.kth.se 79 * 80 * CHANGES: 81 * Changed to new terminal format 9/29/95 schooley@ee.gatech.edu 82 * Changed order of routine declarations. olof@fysik4.kth.se 83 * Changed mechanism for pen pattern selection. kssingvo@immd4.informatik.uni-erlangen.de 84 * Support for vertical text. kssingvo@immd4.informatik.uni-erlangen.de 85 * Fixed plot bug for "set size XS,YS", XS/YS > 1. olof@fysik4.kth.se 86 * Support colored text merritt@u.washington.edu 87 * Support box fill and pattern fill merritt@u.washington.edu 88 * 89 */ 90 91#include "driver.h" 92 93#ifdef TERM_REGISTER 94register_term(mif) 95#endif 96 97 98 99#ifdef TERM_PROTO 100TERM_PUBLIC void MIF_init(void); 101TERM_PUBLIC void MIF_graphics(void); 102TERM_PUBLIC void MIF_text(void); 103TERM_PUBLIC void MIF_linetype(int linetype); 104TERM_PUBLIC void MIF_move(unsigned int x, unsigned int y); 105TERM_PUBLIC void MIF_vector(unsigned int x, unsigned int y); 106TERM_PUBLIC void MIF_put_text(unsigned int x, unsigned int y, const char *str); 107TERM_PUBLIC int MIF_text_angle(int ang); 108TERM_PUBLIC void MIF_reset(void); 109TERM_PUBLIC void MIF_options(void); 110TERM_PUBLIC int MIF_justify_text(enum JUSTIFY mode); 111TERM_PUBLIC void MIF_point(unsigned int x, unsigned int y, int number); 112TERM_PUBLIC void MIF_boxfill(int style, unsigned int x1, unsigned int y1, 113 unsigned int width, unsigned int height); 114TERM_PUBLIC void MIF_filled_polygon(int points, gpiPoint* corners); 115 116/** Coordinates **/ 117/* The cast to float is not necessary because we are dividing by a float */ 118/* On OSK the cast to a float is not allowed in a constant expression which */ 119/* is used by the declaration and initialization of mif_line */ 120/* Converts gnuplot units to MIF units */ 121#define GNP_TO_MIF(P) ((P) / 1000.0) 122/* Basic unit: 0.01 mm (15cm -> 15*10*100=15000) */ 123#define MIF_XMAX 15000 124/* Basic unit: 0.01 mm (10cm -> 10*10*100=10000) */ 125#define MIF_YMAX 10000 126 127#define MIF_XLAST (MIF_XMAX - 1) 128#define MIF_YLAST (MIF_YMAX - 1) 129 130static int insert_mif_line(double fx, double fy); 131static int proc_group_id(int group_id); 132static void free_mif_line(void); 133static void put_mif_line(void); 134static void MIF_set_font(const char *); 135static void mif_put_point(unsigned int x, unsigned int y, int np); 136 137#endif 138 139#ifndef TERM_PROTO_ONLY 140#ifdef TERM_BODY 141 142#ifndef cfree 143# define cfree free 144#endif 145 146static struct mif_line { /* Line point structure specification */ 147 float fpos_x; /* Line point X coordinate */ 148 float fpos_y; /* Y coordinate */ 149 struct mif_line *next; /* Pointer to next line point */ 150 struct mif_line *prev; /* Pointer to previous line point */ 151} mif_line = 152{ /* Current position structure. Adjust for origin. Local for this file. */ 153 GNP_TO_MIF(0), 154 GNP_TO_MIF(MIF_YLAST), 155 &mif_line, 156 &mif_line 157}; 158 159/** Characters **/ 160#define MIF_PSIZE 9 /* Point size of used characters */ 161 162#define MIF_VCHAR (MIF_YMAX/31) /* Distance between rows (a guess) */ 163#define MIF_HCHAR (MIF_XMAX/95) /* Distance between characters (a guess) */ 164 165/** Scale marks **/ 166#define MIF_VTIC (MIF_YMAX/150) /* Size of scale mark (vert) */ 167#define MIF_HTIC (MIF_XMAX/225) /* Size of scale mark (hor) */ 168 169/** Drawing properties **/ 170static char mif_justify[64]; /* How to justify the used text */ 171static char mif_pen[64], mif_pen_width[64], mif_separation[64]; /* How to plot */ 172static char mif_textcolor[64]; /* EAM parallels separation */ 173 174static int mif_text_ang = 0; /* Rotation angle of text */ 175 176static int mif_fill_patterns[] = {7,12,3,0,9,8,14,13}; 177#define MIF_FILL_SOLID 0 178#define MIF_FILL_NONE 15 179 180#define MIF_NPENS 16 /* Number of MIF pen types */ 181static int mif_pentype = 0; /* Pen type to use. Also used to create groups for graphics */ 182#define MIF_PEN_TO_GROUP(P) ( 1 + (P) ) /* Map pen type to group number. Must be >= 1 */ 183 184static int mif_pattern_table[MIF_NPENS] = 185{ /* Table, which pattern should be used for drawing */ 186 0, /* border */ 187 1, /* not used */ 188 2, 3, 4, 8, 12, 13, /* other lines: functions, data, ... (5 is used for grid; 6,7 is (nearly) invisible) */ 189 5, /* grid */ 190 9, 10, 11, 12, 13, 14, 15 /* not used */ 191}; 192 193/** MIF groups administration **/ 194#define MIF_NGROUP_ID 20 195static struct mif_group_id { 196 int group_existence; 197/* This group id should generate a MIF group */ 198#define MIF_GROUP_EXISTS 1 199/* This group id should not generate a MIF group */ 200#define MIF_GROUP_NOT_EXISTS 0 201 202 int group_id; 203#define MIF_INVALID_GROUP_ID 0 /* An invalid MIF group ID */ 204 205} mif_group_id[MIF_NGROUP_ID]; /* List of used group ID:s and corresponding MIF groups existence */ 206 207/** Semaphores **/ 208static int mif_initialized = 0; /* != 0 when output is active */ 209static int mif_in_frame = 0; /* != 0 when inside a plot frame */ 210static int mif_frameno = -1; /* Current frame number */ 211static int mif_colour = TRUE; /* == TRUE when colour should be used */ 212static int mif_polyline = TRUE; /* == TRUE when lines are drawn as continuous curves */ 213 214struct mpt { /* point definition structure */ 215 int chr; /* character for point */ 216 float x_offset, y_offset; /* offset for vertical positioning */ 217 char *font; /* font */ 218}; 219 220static char zgnuplot[] = "ZGnuplot"; /* character formats */ 221static char zgnuplotp[] = "ZGnuplotP"; 222static char zgnuplotd[] = "ZGnuplotD"; 223static const char *mif_font = NULL; /* actual character format */ 224 225static struct mpt mpt[POINT_TYPES + 1] = 226{ /* point definition data */ 227 {'.', 0.000, 0.005, zgnuplotd, /* dot */ }, 228 229 {'G', 0.002, 0.084, zgnuplotp, /* diamond */ }, 230 {';', 0.002, 0.084, zgnuplotp, /* plus */ }, 231 {'n', 0.002, 0.084, zgnuplotp, /* box */ }, 232 {'5', 0.002, 0.084, zgnuplotp, /* X */ }, 233 {'s', 0.002, 0.062, zgnuplotp, /* triangle */ }, 234 {'K', 0.005, 0.075, zgnuplotp, /* star */ }, 235}; 236 237/* diamond is offset 0, dot is offset -1 */ 238static struct mpt *mif_point = &(mpt[1]); 239 240 241/** Declaration of routine/s for internal use **/ 242static int insert_mif_line(double fx, double fy); 243static int proc_group_id(int group_id); 244 245enum MIF_id { 246 MIF_MONOCHROME, MIF_COLOR, MIF_VECTORS, MIF_POLYLINE, MIF_HELP, 247 MIF_OTHER 248}; 249 250static struct gen_table MIF_opts[] = 251{ 252 { "m$onochrome", MIF_MONOCHROME }, 253 { "c$olor", MIF_COLOR }, 254 { "c$olour", MIF_COLOR }, 255 { "v$ectors", MIF_VECTORS }, 256 { "p$olyline", MIF_POLYLINE }, 257 { "h$elp", MIF_HELP }, 258 { "?$", MIF_HELP }, 259 { NULL, MIF_OTHER } 260}; 261 262/** Routine/s **/ 263 264/* Called when this terminal type is set in order to parse options */ 265TERM_PUBLIC void 266MIF_options() 267{ 268 while (!END_OF_COMMAND) { 269 switch(lookup_table(&MIF_opts[0],c_token)) { 270 /* Colour options */ 271 case MIF_MONOCHROME: 272 mif_colour = FALSE; 273 c_token++; 274 break; 275 case MIF_COLOR: 276 mif_colour = TRUE; 277 c_token++; 278 break; 279 /* Curve options */ 280 case MIF_VECTORS: 281 mif_polyline = FALSE; 282 c_token++; 283 break; 284 case MIF_POLYLINE: 285 mif_polyline = TRUE; 286 c_token++; 287 break; 288 /* Short help */ 289 case MIF_HELP: 290 case MIF_OTHER: 291 default: 292 fprintf(stderr, "\ 293Usage: set terminal mif [options]\n\ 294\toptions:\n\ 295\t\tcolour / Draw primitives with line types >= 0 in colour (sep. 2-7)\n\ 296\t\tmonochrome Draw primitives in black (sep. 0)\n\n\ 297\t\tpolyline / Draw lines as continuous curves\n\ 298\t\tvectors Draw lines as collections of vectors\n\n\ 299\t\thelp / ? Print short usage description on stderr\n"); 300 c_token++; 301 break; 302 } 303 } 304 sprintf(term_options, "%s %s", 305 (mif_colour == TRUE) ? "colour" : "monochrome", 306 (mif_polyline == TRUE) ? "polyline" : "vectors"); 307} 308 309/* Deallocate the used line structure elements */ 310static void 311free_mif_line() 312{ 313 struct mif_line *tline; 314 315 while (mif_line.prev != &mif_line) { 316 /* Unlink */ 317 tline = mif_line.prev; 318 mif_line.prev = mif_line.prev->prev; 319 mif_line.prev->next = &mif_line; 320 321 /* Deallocate */ 322 free(tline); 323 } 324 325 /* Make sure that the list will be empty */ 326 mif_line.prev = &mif_line; 327 mif_line.next = &mif_line; 328} 329 330/* Draw the pending line. Change current position. */ 331static void 332put_mif_line() 333{ 334 int np, i; 335 struct mif_line *tline; 336 337 /* Process if inside a Frame */ 338 if (mif_initialized != 0 && mif_in_frame != 0) { 339 340 /* Count the number of available points */ 341 for (tline = mif_line.next, np = 1; tline != &mif_line; tline = tline->next, np++); 342 343 /* Draw line (at least two points) */ 344 if (np >= 2) { 345 346 /* Line preamble */ 347 fprintf(gpoutfile, "\t<PolyLine <GroupID %d> %s %s %s <Fill 15>\n", 348 MIF_PEN_TO_GROUP(mif_pentype), mif_pen, mif_pen_width, mif_separation); 349 350 /* Draw the line elements */ 351 fprintf(gpoutfile, "\t\t<NumPoints %d> ", np); 352 for (i = 0, tline = &mif_line; i < np; i++, tline = tline->next) { 353 if (i % 4 == 0) 354 fputs("\n\t\t", gpoutfile); 355 fprintf(gpoutfile, "<Point %.3f %.3f> ", 356 tline->fpos_x, tline->fpos_y); 357 } 358 359 /* Line post amble */ 360 fputs("\n\t>\n", gpoutfile); 361 362 /* Register the used group ID */ 363 proc_group_id(MIF_PEN_TO_GROUP(mif_pentype)); 364 365 /* Avoid to redraw this. The MIF system should remember it. */ 366 mif_pen[0] = '\0'; 367 mif_pen_width[0] = '\0'; 368 mif_separation[0] = '\0'; 369 370 /* Move current position to end of line */ 371 mif_line.fpos_x = mif_line.prev->fpos_x; 372 mif_line.fpos_y = mif_line.prev->fpos_y; 373 374 /* Restore the line */ 375 free_mif_line(); 376 } 377 } /* Line processed */ 378} 379 380/* Filled box support - Ethan Merritt <merritt@u.washington.edu> */ 381TERM_PUBLIC void 382MIF_boxfill(int style, unsigned int x1, unsigned int y1, 383 unsigned int width, unsigned int height) 384{ 385 int fill_pattern; 386 387 int fillpar = style >> 4; 388 style &= 0xf; 389 switch (style) { 390 default: 391 case FS_EMPTY: fill_pattern = 7; 392 break; 393 case FS_SOLID: fill_pattern = MIF_FILL_SOLID; 394 break; 395 case FS_PATTERN:fill_pattern = mif_fill_patterns[fillpar % 8]; 396 break; 397 } 398 399 /* Object preamble */ 400 fprintf(gpoutfile, "\t<Rectangle <GroupID %d> %s\n", 401 MIF_PEN_TO_GROUP(mif_pentype), mif_separation); 402 403 /* Set fill type */ 404 fprintf(gpoutfile, "\t\t<Fill %d>\n", fill_pattern); 405 406 /* Draw the box */ 407 fprintf(gpoutfile, "\t\t<ShapeRect %.3f %.3f %.3f %.3f>\n", 408 GNP_TO_MIF(x1), GNP_TO_MIF(MIF_YLAST - (y1+height)), 409 GNP_TO_MIF(width), GNP_TO_MIF(height)); 410 411 /* End of object */ 412 fputs("\n\t>\n", gpoutfile); 413 414 /* Register the used group ID */ 415 proc_group_id(MIF_PEN_TO_GROUP(mif_pentype)); 416 417} 418 419/* Filled polygon. Ethan Merritt <merritt@u.washington.edu> */ 420TERM_PUBLIC void 421MIF_filled_polygon(int points, gpiPoint* corners) 422{ 423 int i; 424 425 /* Object preamble */ 426 fprintf(gpoutfile, "\t<Polygon <GroupID %d>\n", 427 MIF_PEN_TO_GROUP(mif_pentype)); 428 429 /* Set fill type */ 430 fprintf(gpoutfile, "\t\t<Fill %d>\n", MIF_FILL_SOLID); 431 432 /* Draw the line elements */ 433 fprintf(gpoutfile, "\t\t<NumPoints %d> ", points); 434 for (i=0; i<points; i++) { 435 fprintf(gpoutfile, "<Point %.3f %.3f> ", 436 GNP_TO_MIF(corners[i].x), 437 GNP_TO_MIF(MIF_YLAST - corners[i].y)); 438 } 439 440 /* End of object */ 441 fputs("\n\t>\n", gpoutfile); 442 443 /* Register the used group ID */ 444 proc_group_id(MIF_PEN_TO_GROUP(mif_pentype)); 445 446} 447 448/* Draw a point */ 449static void 450mif_put_point(unsigned int x, unsigned int y, int np) 451{ 452 /* Process if inside a Frame */ 453 if (mif_initialized != 0 && mif_in_frame != 0) { 454 455 /* Draw pending line */ 456 if (mif_polyline == TRUE) 457 put_mif_line(); 458 459 /* Adjust current position for text-graphics alignment */ 460 MIF_move(x, y); 461 462 /* center text */ 463 MIF_justify_text(CENTRE); 464 465 /* Draw the point */ 466 fprintf(gpoutfile, "\t<TextLine <GroupID %d> %s\n", 467 MIF_PEN_TO_GROUP(mif_pentype), 468 mif_textcolor); 469 470 MIF_set_font(mif_point[np].font); 471 472 fprintf(gpoutfile, "\t\t<TLOrigin %.3f %.3f> %s <String `%c'>\n", 473 mif_line.fpos_x + mif_point[np].x_offset, 474 mif_line.fpos_y + mif_point[np].y_offset, 475 mif_justify, 476 mif_point[np].chr); 477 fputs("\t>\n", gpoutfile); 478 479 /* Register the used group ID */ 480 proc_group_id(MIF_PEN_TO_GROUP(mif_pentype)); 481 482 /* Avoid to redraw this. The MIF system should remember it. */ 483 mif_justify[0] = '\0'; 484 485 } /* Point processed */ 486} 487 488 489/* 490 * draw points 491 */ 492TERM_PUBLIC void 493MIF_point(unsigned int x, unsigned int y, int number) 494{ 495 if (number < 0) { /* dot */ 496 number = -1; 497 } else { /* point */ 498 number %= POINT_TYPES; 499 } 500 mif_put_point(x, y, number); 501} 502 503 504/* Set up a MIF output file */ 505TERM_PUBLIC void 506MIF_init() 507{ 508 int i; 509 510 /* Process if not inside a MIF file and Frame */ 511 if (mif_initialized == 0 && mif_in_frame == 0) { 512 /* Tell this terminal driver that the output is initialized and 513 * no current frames are processed */ 514 mif_initialized = 1; 515 mif_in_frame = 0; 516 517 /* Reset internal position */ 518 free_mif_line(); 519 mif_line.fpos_x = GNP_TO_MIF(0); 520 mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST); 521 522 /* Reset drawing properties strings */ 523 mif_pen[0] = '\0'; 524 mif_pen_width[0] = '\0'; 525 mif_separation[0] = '\0'; 526 527 MIF_justify_text(LEFT); 528 529 /* Reset group ID generator */ 530 for (i = 0; i < MIF_NGROUP_ID; i++) { 531 mif_group_id[i].group_id = MIF_INVALID_GROUP_ID; 532 mif_group_id[i].group_existence = MIF_GROUP_NOT_EXISTS; 533 } 534 535 /* Identify ourselves */ 536 /*bs show borders */ 537 /* Setup a default environment to use */ 538 fprintf(gpoutfile, "\ 539<MIFFile 3.00> # Generated by gnuplot version %s patchlevel %s; identifies this as a MIF file\n\ 540#\n\ 541# show borders\n\ 542<Document\n<DBordersOn Yes>\n>\n\ 543# Set a default pen pattern, pen width, unit and font for subsequent objects\n\ 544<Pen 0>\n\ 545<Fill 15>\n\ 546<PenWidth 0.5 pt>\n\ 547<Separation 0>\n\ 548<Units Ucm>\n\ 549<FontCatalog\n\ 550\t<Font <FTag `%s'><FFamily `Times'><FSize %d><FPlain Yes>>\n\ 551\t<Font <FTag `%s'><FFamily `ZapfDingbats'><FSize 7.0 pt><FPlain Yes>>\n\ 552\t<Font <FTag `%s'><FFamily `Symbol'><FSize 5.0 pt><FPlain Yes>>\n\ 553>\n\ 554#\n", 555 gnuplot_version, gnuplot_patchlevel, 556 zgnuplot, MIF_PSIZE, 557 zgnuplotp, 558 zgnuplotd); 559 } /* MIF file created */ 560} 561 562/* Finish of a MIF output file */ 563TERM_PUBLIC void 564MIF_reset() 565{ 566 /* Process if inside a MIF file and not inside a Frame */ 567 if (mif_initialized != 0 && mif_in_frame == 0) { 568 /* Finish off the MIF file */ 569 fputs("\ 570#\n\ 571# End of MIFFile\n", gpoutfile); 572 573 /* Tell this terminal driver that the output is finished */ 574 mif_initialized = 0; 575 576 /* bs: reset frame number */ 577 mif_frameno = -1; 578 579 } /* MIF file finished */ 580} 581 582/* Start plotting a Frame (-> graphics mode) */ 583TERM_PUBLIC void 584MIF_graphics() 585{ 586 int i; 587 588 /* Process if not inside a Frame */ 589 if (mif_initialized != 0 && mif_in_frame == 0) { 590 /* Tell that this terminal driver is working with a plot frame */ 591 mif_in_frame = 1; 592 593 /* Update frame number */ 594 mif_frameno++; 595 596 /* Set current position */ 597 free_mif_line(); 598 mif_line.fpos_x = GNP_TO_MIF(0); 599 mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST); 600 601 /* Set drawing properties */ 602 mif_pen[0] = '\0'; 603 mif_pen_width[0] = '\0'; 604 mif_separation[0] = '\0'; 605 606 MIF_justify_text(LEFT); 607 608 /* Reset group ID generator */ 609 for (i = 0; i < MIF_NGROUP_ID; i++) { 610 mif_group_id[i].group_id = MIF_INVALID_GROUP_ID; 611 mif_group_id[i].group_existence = MIF_GROUP_NOT_EXISTS; 612 } 613 614 /* Frame preamble */ 615 fprintf(gpoutfile, "\ 616#\n\ 617# Frame number %d with plot of graphics\n\ 618<Frame\n\ 619\t<Pen 15>\n\ 620\t<Fill 15>\n\ 621\t<PenWidth 0.5 pt>\n\ 622\t<Separation 0>\n\ 623\t<BRect 2.000 %.3f %.3f %.3f>\n\ 624\t<NSOffset 0.000>\n\ 625\t<BLOffset 0.000>\n", 626 mif_frameno, 627 ((float) mif_frameno) * GNP_TO_MIF(MIF_YMAX + 100), 628 GNP_TO_MIF(MIF_XMAX), GNP_TO_MIF(MIF_YMAX)); 629 } /* Frame created */ 630} 631 632/* Stop plotting a Frame (-> text mode) */ 633TERM_PUBLIC void 634MIF_text() 635{ 636 int i; 637 638 /* Process if inside a Frame */ 639 if (mif_initialized != 0 && mif_in_frame != 0) { 640 641 /* Draw pending line */ 642 if (mif_polyline == TRUE) 643 put_mif_line(); 644 645 /* Group the used plot primitives */ 646 fputs("\ 647\t#\n\ 648\t# Group the the objects in groups to make the chart easier to manipulate\n\ 649\t# after it's imported into FrameMaker.\n", gpoutfile); 650 651 for (i = 0; i < MIF_NGROUP_ID; i++) { 652 if (mif_group_id[i].group_id != MIF_INVALID_GROUP_ID && 653 mif_group_id[i].group_existence == MIF_GROUP_EXISTS) { 654 fprintf(gpoutfile, "\ 655\t<Group\n\ 656\t\t<ID %d>\n\ 657\t>\n", mif_group_id[i].group_id); 658 } 659 } 660 661 /* Frame post amble */ 662 fprintf(gpoutfile, "\ 663>\n\ 664# End of Frame number %d\n\ 665#\n", 666 mif_frameno); 667 668 /* Tell that this terminal driver is not working with a plot frame */ 669 mif_in_frame = 0; 670 } /* Frame finished */ 671} 672 673/* Select type of line in graphics */ 674/* NOTE: actually written to output the first time a primitive 675 * is drawn AFTER this call */ 676/* -2=border, -1=X/Y-axis, 0-13=lines, and 14-=mapped back */ 677TERM_PUBLIC void 678MIF_linetype(int linetype) 679{ 680 /* Process if inside a Frame */ 681 if (mif_initialized != 0 && mif_in_frame != 0) { 682 683 /* Draw pending line */ 684 if (mif_polyline == TRUE) 685 put_mif_line(); 686 687 /* Translate gnuplot pen types to MIF pen types */ 688 if (linetype < 0) { /* Special lines */ 689 if (linetype == LT_AXIS) { 690 mif_pentype = 8 + MIF_NPENS; /* -1 */ 691 if (mif_colour == TRUE) 692 sprintf(mif_separation, " <Separation 0> "); 693 } else { 694 mif_pentype = 0 + MIF_NPENS; /* -2 or less */ 695 if (mif_colour == TRUE) 696 sprintf(mif_separation, " <Separation 0> "); 697 } 698 sprintf(mif_pen_width, " <PenWidth 1.0 pt> "); 699 /* EAM - set text color to black */ 700 sprintf(mif_textcolor, " <Font <FSeparation 0>> "); 701 } else { /* Normal lines */ 702 mif_pentype = (linetype) % MIF_NPENS; /* 0-(MIF_NPENS-1) */ 703 sprintf(mif_pen_width, " <PenWidth 0.1 pt> "); 704 if (mif_colour == TRUE) 705 sprintf(mif_separation, " <Separation %d> ", 706 2 + (mif_pentype % 6)); /* 2-7 */ 707 /* EAM - set text color also */ 708 if (mif_colour == TRUE) 709 sprintf(mif_textcolor, " <Font <FSeparation %d>> ", 710 2 + (mif_pentype % 6)); /* 2-7 */ 711 } 712 713 /* Set pen type */ 714 sprintf(mif_pen, " <Pen %d> ", 715 mif_pattern_table[mif_pentype % MIF_NPENS]); 716 717 } /* Primitive processed */ 718} 719 720/* Allow arbitrary text rotation */ 721TERM_PUBLIC int 722MIF_text_angle(int ang) 723{ 724 mif_text_ang = ang; 725 return (TRUE); 726} 727 728/* Justify following text lines (MIF_put_text()) relative to the 729 * insertion point 730 * NOTE: actually written to output in text primitives which are 731 * drawn AFTER this call */ 732TERM_PUBLIC int 733MIF_justify_text(enum JUSTIFY mode) 734{ 735 int rval = TRUE; 736 737 /* Process if inside a Frame */ 738 if (mif_initialized != 0 && mif_in_frame != 0) { 739 switch (mode) { 740 case LEFT: 741 sprintf(mif_justify, " <TLAlignment Left> "); 742 break; 743 case CENTRE: 744 sprintf(mif_justify, " <TLAlignment Center> "); 745 break; 746 case RIGHT: 747 sprintf(mif_justify, " <TLAlignment Right> "); 748 break; 749 default: 750 rval = FALSE; 751 break; 752 } 753 754 } 755 /* Primitive processed */ 756 else { 757 rval = FALSE; 758 } 759 760 return (rval); 761} 762 763/* Draw a vector from current position to (x, y) and change current position. 764 * NOTE: actually written to output the first time another primitive 765 * is called AFTER this call */ 766TERM_PUBLIC void 767MIF_vector(unsigned int x, unsigned int y) 768{ 769 /* Process if inside a Frame */ 770 if (mif_initialized != 0 && mif_in_frame != 0) { 771 772 /* Setup the vector as a part of the line */ 773 insert_mif_line(GNP_TO_MIF(x), GNP_TO_MIF(MIF_YLAST - (int) y)); 774 775 /* Draw pending line -> vector */ 776 if (mif_polyline == FALSE) 777 put_mif_line(); 778 779 } /* Vector processed */ 780} 781 782/* Move current position */ 783TERM_PUBLIC void 784MIF_move(unsigned int x, unsigned int y) 785{ 786 /* Process if inside a Frame */ 787 if (mif_initialized != 0 && mif_in_frame != 0) { 788 789 /* Draw pending line */ 790 if (mif_polyline == TRUE) 791 put_mif_line(); 792 793 mif_line.fpos_x = GNP_TO_MIF(x); 794 mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST - (int) y); 795 } 796} 797 798 799/* set font */ 800static void 801MIF_set_font(const char *font) 802{ 803 if (font != mif_font) { 804 fprintf(gpoutfile, "\t\t<Font\n\t\t\t<FTag `%s'>\n\t\t>\n", font); 805 mif_font = font; 806 } 807} 808 809 810/* Draw the text string str at (x, y). Adjust according to MIF_justify_text(). 811 * Change current position. */ 812TERM_PUBLIC void 813MIF_put_text(unsigned int x, unsigned int y, const char str[]) 814{ 815 /* Process if inside a Frame */ 816 if (mif_initialized != 0 && mif_in_frame != 0) { 817 818 /* Draw pending line */ 819 if (mif_polyline == TRUE) 820 put_mif_line(); 821 822 /* Adjust current position for text-graphics alignment */ 823 MIF_move(x, y - MIF_VCHAR / 5); 824 825 if (strlen(str) > 0) { 826 827 /* Draw the text */ 828 fprintf(gpoutfile, "\t<TextLine <GroupID %d> %s %s %s %s\n", 829 MIF_PEN_TO_GROUP(mif_pentype), mif_pen, 830 mif_pen_width, mif_separation, mif_textcolor); 831 832 MIF_set_font(zgnuplot); 833 834 fprintf(gpoutfile, "\ 835\t\t<TLOrigin %.3f %.3f> %s <Angle %d> <String `%s'>\n\ 836\t>\n", 837 mif_line.fpos_x, mif_line.fpos_y, mif_justify, 838 mif_text_ang, str); 839 840 /* Register the used group ID */ 841 proc_group_id(MIF_PEN_TO_GROUP(mif_pentype)); 842 843 /* Avoid to redraw this. The MIF system should remember it. */ 844 mif_pen[0] = '\0'; 845 mif_pen_width[0] = '\0'; 846 mif_separation[0] = '\0'; 847 848 mif_justify[0] = '\0'; /* Independent of linetype */ 849 } 850 } /* Text processed */ 851} 852 853 854/* Insert one point in the line */ 855static int 856insert_mif_line(double fx, double fy) 857{ 858 int rval = TRUE; 859 860 if ((mif_line.prev->next = (struct mif_line *) gp_alloc(sizeof(struct mif_line), 861 "MIF driver")) != (struct mif_line *) NULL) { 862 /* Link */ 863 mif_line.prev->next->next = &mif_line; 864 mif_line.prev->next->prev = mif_line.prev; 865 mif_line.prev = mif_line.prev->next; 866 867 /* Fill */ 868 mif_line.prev->fpos_x = fx; 869 mif_line.prev->fpos_y = fy; 870 871 rval = TRUE; 872 } else { /* Failed to allocate */ 873 /* Relink */ 874 mif_line.prev->next = &mif_line; 875 876 rval = FALSE; 877 } 878 879 return (rval); 880} 881 882/* Register group ID. Update group ID existence. */ 883/* Returns: 1 group_id belongs to a MIF group 884 0 group_id does not belong to a MIF group 885 -1 not inside a Frame 886 -2 group ID list is full 887 */ 888static int 889proc_group_id(int group_id) 890{ 891 int i, rval = 0; 892 893 /* Process if inside a Frame */ 894 if (mif_initialized != 0 && mif_in_frame != 0) { 895 896 /* Find out the group ID, or a free group ID slot index. */ 897 for (i = 0; i < MIF_NGROUP_ID && 898 mif_group_id[i].group_id != MIF_INVALID_GROUP_ID && 899 mif_group_id[i].group_id != group_id; 900 i++) { 901 /* Don't check the group_existence variable */ 902 } 903 904 if (i < MIF_NGROUP_ID) { 905 if (mif_group_id[i].group_id == MIF_INVALID_GROUP_ID) { 906 /* Register as new group ID for eventual use as MIF group */ 907 mif_group_id[i].group_id = group_id; 908 mif_group_id[i].group_existence = MIF_GROUP_NOT_EXISTS; 909 } else { 910 /* If second use of this group ID -> create a new MIF group */ 911 if (mif_group_id[i].group_id == group_id) { 912 mif_group_id[i].group_existence = MIF_GROUP_EXISTS; 913 /* NOTE: a group MUST have at least two members. */ 914 rval = 1; 915 } 916 } 917 } else { 918 rval = -2; /* No place for this group ID in the list */ 919 } 920 921 } 922 /* Group ID processed */ 923 else { 924 rval = -1; /* Not inside a Frame */ 925 } 926 927 /* Return MIF group status */ 928 return (rval); 929} 930 931 932#endif 933 934 935#ifdef TERM_TABLE 936 937TERM_TABLE_START(mif_driver) 938 "mif", "Frame maker MIF 3.00 format", 939 MIF_XMAX, MIF_YMAX, MIF_VCHAR, MIF_HCHAR, 940 MIF_VTIC, MIF_HTIC, MIF_options, MIF_init, MIF_reset, 941 MIF_text, null_scale, MIF_graphics, MIF_move, MIF_vector, 942 MIF_linetype, MIF_put_text, MIF_text_angle, 943 MIF_justify_text, MIF_point, do_arrow, set_font_null, 944 0, /* pointsize */ 945 0, /* flags */ 946 0, 0, /* suspend, resume */ 947 MIF_boxfill, 948 0 /* linewidth */ 949#ifdef USE_MOUSE 950 , 0, 0, 0, 0, 0 951#endif 952 ,0 /* make_palette */ 953 ,0 /* previous_palette */ 954 ,0 /* set_color */ 955 ,MIF_filled_polygon /* filled_polygon */ 956TERM_TABLE_END(mif_driver) 957 958#undef LAST_TERM 959#define LAST_TERM mif_driver 960 961#endif 962#endif /* TERM_PROTO_ONLY */ 963 964#ifdef TERM_HELP 965START_HELP(mif) 966"1 mif", 967"?commands set terminal mif", 968"?set terminal mif", 969"?set term mif", 970"?terminal mif", 971"?term mif", 972"?mif", 973" Note: Legacy terminal.", 974" The `mif` terminal driver produces Frame Maker MIF format version 3.00. It", 975" plots in MIF Frames with the size 15*10 cm, and plot primitives with the same", 976" pen will be grouped in the same MIF group. Plot primitives in a `gnuplot`", 977" page will be plotted in a MIF Frame, and several MIF Frames are collected in", 978" one large MIF Frame. The MIF font used for text is \"Times\".", 979"", 980" Several options may be set in the MIF 3.00 driver.", 981"", 982" Syntax:", 983" set terminal mif {color | colour | monochrome} {polyline | vectors}", 984" {help | ?}", 985"", 986" `colour` plots lines with line types >= 0 in colour (MIF sep. 2--7) and", 987" `monochrome` plots all line types in black (MIF sep. 0).", 988" `polyline` plots curves as continuous curves and `vectors` plots curves as", 989" collections of vectors.", 990" `help` and `?` print online help on standard error output---both print a", 991" short description of the usage; `help` also lists the options.", 992"", 993" Examples:", 994" set term mif colour polylines # defaults", 995" set term mif # defaults", 996" set term mif vectors", 997" set term mif help" 998END_HELP(mif) 999#endif /* TERM_HELP */ 1000