/* Copyright (c) 2004-2010, Dirk Krause All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Dirk Krause nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file dkfigmp.c MP output driver module. */ /** Inside the dkfigmp module. */ #define DKFIGMP_C 1 #include "dkfig.h" $(trace-include) /** Restrict digits after decimal dot for double value. */ #define drd(v,o,w) dkfig_tool2_drd(v,o,w) $!trace-code #define TRACE_DEBUG 1 #if TRACE_DEBUG /** Issue debugging output about a Bezier point. @param bp Bezier point structure. */ static void trace_bezier_point DK_P1(dk_fig_bezier_point *,bp) { FILE *f; f = dktrace_file(); if(f) { fprintf(f, "value: x=%lg y=%lg\n", (bp->value).x, (bp->value).y); fprintf(f, "lcontrol: x=%lg y=%lg\n", (bp->lcontrol).x, (bp->lcontrol).y); fprintf(f, "rcontrol: x=%lg y=%lg\n", (bp->rcontrol).x, (bp->rcontrol).y); } } #endif #ifndef TR_PTR /** Trace output macro for pointer. */ #define TR_PTR(x) ((x) ? "PTR" : "(NULL)") #endif /** Flag: Linewidth known. */ #define HAVE_LINEWIDTH 1 /** Flag: Linecap known. */ #define HAVE_LINECAP 2 /** Flag: Linejoin known. */ #define HAVE_LINEJOIN 4 /** Flag: Arrowhead length known. */ #define HAVE_AHLENGTH 8 /** Flag: Arrowhead angle known. */ #define HAVE_AHANGLE 16 /** Pointer to characters. */ typedef char *PCHAR; /** Keywords for MetaPost output. */ static char *keywords[] = { /* 0 */ "\n", /* 1 */ " ", /* 2 */ "(", /* 3 */ ")", /* 4 */ ";", /* 5 */ ",", /* 6 */ "--", /* 7 */ "..", /* 8 */ "+", /* 9 */ "-", /* 10 */ "0", /* 11 */ "1", /* 12 */ "=", /* 13 */ "prologues", /* 14 */ ":", /* 15 */ "verbatimtex", /* 16 */ "%&latex", /* 17 */ "&tex", /* 18 */ "etex", /* 19 */ "%", /* 20 */ "line", /* 21 */ "\"", /* 22 */ "beginfig", /* 23 */ "endfig;", /* 24 */ "end", /* 25 */ "path", /* 26 */ "picture", /* 27 */ "p", /* 28 */ "q", /* 29 */ "btex", /* 30 */ "{", /* 31 */ "}", /* 32 */ "\\mbox", /* 33 */ "label", /* 34 */ ".", /* 35 */ "top", /* 36 */ "ulft", /* 37 */ "urt", /* 38 */ "rotated", /* 39 */ "r", /* 40 */ "*", /* 41 */ "10**", /* 42 */ "llcorner", /* 43 */ "withcolor", /* 44 */ "pair", /* 45 */ "s", /* 46 */ "xpart", /* 47 */ "lrcorner", /* 48 */ "infont", /* 49 */ "scaled", /* 50 */ "pt", /* 51 */ "/", /* 52 */ "fontsize", /* 53 */ "defaultfont", /* 54 */ "\\n", /* 55 */ "\\\"", /* 56 */ "yscaled", /* 57 */ "shifted", /* 58 */ "fullcircle", /* 59 */ "cycle", /* 60 */ "down", /* 61 */ "right", /* 62 */ "up", /* 63 */ "left", /* 64 */ "controls", /* 65 */ "and", /* 66 */ "cutafter", /* 67 */ "fill", /* 68 */ "color", /* 69 */ "c", /* 70 */ "draw", /* 71 */ "pickup", /* 72 */ "pencircle", /* 73 */ "bp", /* 74 */ "linecap", /* 75 */ ":=", /* 76 */ "2", /* 77 */ "linejoin", /* 78 */ "a", /* 79 */ "arrowhead", /* 80 */ "reverse", /* 81 */ "white", /* 82 */ "ahlength", /* 83 */ "ahangle", /* 84 */ "nullpicture", /* 85 */ "clip", /* 86 */ "to", /* 87 */ "addto", /* 88 */ "currentpicture", /* 89 */ "also", /* 90 */ "dashed", /* 91 */ "dashpattern", /* 92 */ "on", /* 93 */ "off", /* 94 */ "doublepath", /* 95 */ "withpen", /* 96 */ "o", /* 97 */ "pen", /* 98 */ "(0,0)", /* 99 */ "produced by fig2vect\0, see http://dktools.sourceforge.net/fig2vect.html", /* 100 */ "labeloffset:=0;bbmargin:=0;", /* 101 */ ".0", /* 102 */ "mp", /* 103 */ "% fill bounding box", /* 104 */ "% background rectangle removed", /* 105 */ "black", /* 106 */ "withgreyscale", NULL }; /** Number of keywods in the array (including final NULL pointer). */ static size_t number_of_keywords = sizeof(keywords)/sizeof(PCHAR); /** Write one keyword to output stream. @param strm Destination stream. @param index Keyword index. */ static void kw_to_stream DK_P2(dk_stream_t *,strm, size_t,index) { if(index < number_of_keywords) { dkstream_puts(strm, keywords[index]); } } /** Write double value to stream, convert for MetaPost representation if neccesary. (i.e. 3.5e8 -> (3.5*(10**8)) ) @param s Output stream. @param d Double value to write. @param iscoord Flag: Is coordinate. @param c Conversion job structure. */ static void stream_puts_double DK_P4(dk_stream_t *,s, double,d, int, iscoord, dk_fig_conversion *,c) { char buffer[32], *eptr, *dotptr; #if DK_HAVE_SNPRINTF snprintf(buffer, sizeof(buffer), "%lg", drd(d, c, iscoord)); buffer[sizeof(buffer)-1] = '\0'; #else sprintf(buffer, "%lg", drd(d, c, iscoord)); #endif eptr = strchr(buffer, 'e'); if(!eptr) { eptr = strchr(buffer, 'E'); } if(eptr) { dotptr = strchr(buffer, '.'); *(eptr++) = '\0'; kw_to_stream(s, 2); dkstream_puts(s, buffer); if(iscoord) { if(!dotptr) { kw_to_stream(s, 101); } } kw_to_stream(s, 40); kw_to_stream(s, 2); kw_to_stream(s, 41); if(*eptr == '-') { kw_to_stream(s, 2); } dkstream_puts(s, eptr); if(*eptr == '-') { kw_to_stream(s, 3); } kw_to_stream(s, 3); kw_to_stream(s, 3); } else { dotptr = strchr(buffer, '.'); dkstream_puts(s, buffer); if(iscoord) { if(!dotptr) { kw_to_stream(s, 101); } } } } /** Convert coordinate x (double value) from fig to MP. @param c Conversion job structure. @param x Value to convert. @return Converted x value. */ static double ccd_x DK_P2(dk_fig_conversion *,c, double,x) { double back = 0.0; dk_fig_output_mp *mpo; $? "+ ccd_x %lg", x mpo = (dk_fig_output_mp *)(c->outds); if(mpo) { back = mpo->mx * x + mpo->nx; } else { back = 0.06 * x; } $? "- ccd_x %lg", back return back; } /** Convert coordinate y (double value) from fig to MP. @param c Conversion job structure. @param y Value to convert. @return Converted y value. */ static double ccd_y DK_P2(dk_fig_conversion *,c, double,y) { double back = 0.0; dk_fig_output_mp *mpo; $? "+ ccd_y %lg", y mpo = (dk_fig_output_mp *)(c->outds); if(mpo) { back = mpo->my * y + mpo->ny; } else { back = -0.06 * y; } $? "- ccd_y %lg", back return back; } /** Convert coordinate x (long value) from fig to MP. @param c Conversion job structure. @param x Value to convert. @return Converted x value. */ static double cc_x DK_P2(dk_fig_conversion *,c, long,x) { double back = 0.0; dk_fig_output_mp *mpo; $? "+ cc_x %ld", x mpo = (dk_fig_output_mp *)(c->outds); if(mpo) { back = mpo->mx * dkma_l_to_double(x) + mpo->nx; } else { back = 0.06 * dkma_l_to_double(x); } $? "- cc_x %lg", back return back; } /** Convert coordinate y (long value) from fig to MP. @param c Conversion job structure. @param y Value to convert. @return Converted y value. */ static double cc_y DK_P2(dk_fig_conversion *,c, long,y) { double back = 0.0; dk_fig_output_mp *mpo; $? "+ cc_y %ld", y mpo = (dk_fig_output_mp *)(c->outds); if(mpo) { back = mpo->my * dkma_l_to_double(y) + mpo->ny; } else { back = -0.06 * dkma_l_to_double(y); } $? "- cc_y %lg", back return back; } /** Convert a distance (long value) from Fig to MetaPost. @param c Conversion job structure. @param x Distance to convert. @return Converted distance value. */ static double cc_radius DK_P2(dk_fig_conversion *,c, long,x) { double back = 0.0; dk_fig_output_mp *mpo; $? "+ cc_x %ld", x mpo = (dk_fig_output_mp *)(c->outds); if(mpo) { back = mpo->mx * dkma_l_to_double(x); } else { back = 0.06 * dkma_l_to_double(x); } $? "- cc_x %lg", back return back; } /** Convert a distance/radius (double value) from Fig to MetaPost. @param c Conversion job structure. @param r Radius to convert. @return Converted radius/distance. */ static double ccd_radius DK_P2(dk_fig_conversion *,c, double,r) { double back = 0.0; dk_fig_output_mp *mpo; mpo = (dk_fig_output_mp *)(c->outds); if(mpo) { back = mpo->mx * r; } else { back = 0.06 * r; } return back; } /** Convert a bounding box from Fig to MetaPost. @param c Conversion job structure. @param dst Destination bounding box structure. @param src Source bounding box structure. */ static void cc_bb DK_P3(dk_fig_conversion *,c, dk_fig_bb *,dst, dk_fig_bb *,src) { $? "+ cc_bb xmin=%lg xmax=%lg ymin=%lg ymax=%lg", src->xmin, src->xmax, src->ymin, src->ymax dkfig_tool_bb_reset(dst); dkfig_tool_bb_add_x(dst, ccd_x(c, src->xmin)); dkfig_tool_bb_add_x(dst, ccd_x(c, src->xmax)); dkfig_tool_bb_add_y(dst, ccd_y(c, src->ymin)); dkfig_tool_bb_add_y(dst, ccd_y(c, src->ymax)); $? "- cc_bb xmin=%lg xmax=%lg ymin=%lg ymax=%lg", dst->xmin, dst->xmax, dst->ymin, dst->ymax } /** Convert line width from Fig to MetaPost, ignore "lighten look" option. @param c Conversion job structure. @param l Linewidth in Fig linewidth units. @return Linewidth converted to MetaPost. */ static double cc_noenl_linewidth DK_P2(dk_fig_conversion *,c, long,l) { double back = 0.0; $? "+ cc_noenl_linewidth %ld", l back = dkma_l_to_double(l); /* back = (back / 10.0) * 9.0 */ back = 0.9 * back; $? "- cc_noenl_linewidth %lg", back return back; } /** Write point given in MetaPost co-ordinates to output stream. @param oi MetaPost output instruction structure. @param x X coordinate. @param y y coordinate. @param w Number of digits after decimal dot. */ static void write_noconv_double_point DK_P4(dkfig_mp_output_instruction *,oi, double,x, double,y, int,w) { $? "+ write_noconv_double_point" kw_to_stream(oi->s, 2); stream_puts_double(oi->s, x, w, oi->c); kw_to_stream(oi->s, 5); stream_puts_double(oi->s, y, w, oi->c); kw_to_stream(oi->s, 3); $? "- write_noconv_double_point" } /** Write point data given in Fig coordinates (long values). @param oi MetaPost output instruction structure. @param x x coordinate. @param y y coordinate. */ static void write_long_point DK_P3(dkfig_mp_output_instruction *,oi, long,x, long,y) { $? "+ write_long_point" write_noconv_double_point(oi, cc_x(oi->c, x), cc_y(oi->c, y), 1); $? "- write_long_point" } /** Write point data given in Fig coordinates (double values). @param oi MetaPost output instruction structure. @param x x coordinate. @param y y coordinate. @param w Number of digits after decimal dot. */ static void write_double_point DK_P4(dkfig_mp_output_instruction *,oi, double,x, double,y, int,w) { $? "+ write_double_point" write_noconv_double_point(oi, ccd_x(oi->c, x), ccd_y(oi->c, y), w); $? "- write_double_point" } /** Check whether to use colored or grayscaled output. @param c Conversion job structure. @return 1 for colored output, 0 for grayscaled output. */ static int can_use_color DK_P1(dk_fig_conversion *,c) { int back = 1; if(c) { if(!((c->opt2) & DKFIG_OPT_COLOR)) { back = 0; } } return back; } /** Write color cell RGB-triple to output stream. @param os Output stream. @param dcc Color cell. @param c Conversion job structure. */ static void write_dcc_data DK_P3(dk_stream_t *,os, dk_fig_dcc *,dcc, dk_fig_conversion *,c) { double g; if(can_use_color(c)) { kw_to_stream(os, 2); stream_puts_double(os, drd(dcc->red, c, 0), 0, c); kw_to_stream(os, 5); stream_puts_double(os, drd(dcc->green, c, 0), 0, c); kw_to_stream(os, 5); stream_puts_double(os, drd(dcc->blue, c, 0), 0, c); kw_to_stream(os, 3); } else { g = 0.3 * dcc->red + 0.59 * dcc->green + 0.11 * dcc->blue; g = drd(g, c, 0); if(g > 0.0) { if(g >= 1.0) { kw_to_stream(os, 81); } else { kw_to_stream(os, 2); stream_puts_double(os, g, 0, c); kw_to_stream(os, 40); kw_to_stream(os, 81); kw_to_stream(os, 3); } } else { kw_to_stream(os, 105); } } } /** Write gray value for color cell to output stream. @param os Output stream. @param dcc Color cell. @param c Conversion job structure. */ static void write_dcc_gray DK_P3(dk_stream_t *,os, dk_fig_dcc *,dcc, dk_fig_conversion *,c) { double g; g = 0.3 * dcc->red + 0.59 * dcc->green + 0.11 * dcc->blue; g = drd(g, c, 0); stream_puts_double(os, g, 0, c); } /** Output UTF-8 encoded text encoded for mp. @param c Conversion job structure. @param os Output stream. @param t Text to print. */ static void encode_utf8_to_mp DK_P3(dk_fig_conversion *,c, dk_stream_t *,os, char *,t) { dk_udword ucb; unsigned char uc; int cc; char buffer[2]; size_t max, used, avail, step; cc = 1; max = strlen(t); used = 0; avail = max; while(cc) { cc = 0; if(avail > 0) { step = 0; cc = dkenc_utf82uc(&ucb, (unsigned char *)(&(t[used])), avail, &step); if(cc) { used = used + step; if(avail > step) { avail = avail - step; } else { avail = 0; } if(ucb < 256UL) { uc = (unsigned char)ucb; if(uc == '\n') { kw_to_stream(os, 54); } else { if(uc == '"') { kw_to_stream(os, 55); } else { buffer[0] = uc; buffer[1] = '\0'; dkstream_puts(os, buffer); } } } else { $? "! ERROR: Character out of range" /* ERROR: Character out of range, use LaTeX text handling */ dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 119); } } } } /* char buffer[16]; char *ptr = NULL; ptr = t; buffer[1] = '\0'; while(*ptr) { switch(*ptr) { case '\n': { kw_to_stream(os, 54); } break; case '"': { kw_to_stream(os, 55); } break; default: { buffer[0] = *ptr; dkstream_puts(os, buffer); } break; } ptr++; } */ } /** Output text encoded for mp. @param os Output stream. @param t Text to print. */ static void encode_text_to_mp DK_P2(dk_stream_t *,os, char *,t) { char buffer[16]; char *ptr = NULL; ptr = t; buffer[1] = '\0'; while(*ptr) { switch(*ptr) { case '\n': { kw_to_stream(os, 54); } break; case '"': { kw_to_stream(os, 55); } break; default: { buffer[0] = *ptr; dkstream_puts(os, buffer); } break; } ptr++; } } /** Handle text object. @param oi MetaPost output instruction structure. @return 1 on success, 0 on error. */ static int print_text_object DK_P1(dkfig_mp_output_instruction *,oi) { int back = 1; int rotation = 0; int th; dk_fig_text *t; dk_fig_dcc dcc; dk_fig_fonth_t *fhptr = NULL; char *ptr; double dv; $? "+ print_text_object" t = (dk_fig_text *)((oi->o)->data); if((t) && (!(((oi->c)->opt2) & DKFIG_OPT_SKIP_ALL_TEXTS))) { th = (((t->font_flags) & 2) ? ((oi->c)->special_text) : ((oi->c)->normal_text)); fhptr = t->font_handling; if(fhptr) { if(fabs(t->angle) > DKFIG_EPSILON) { rotation = 1; } dkfig_tool_fill_dcc(oi->d, &dcc, ((oi->o)->fpd).pc); /* path q; path r; numeric s; */ kw_to_stream(oi->s, 26); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 28); kw_to_stream(oi->s, 4); if(rotation) { kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 26); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 39); kw_to_stream(oi->s, 4); switch(((oi->o)->fpd).st) { case 1: case 2: { kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 44); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 45); kw_to_stream(oi->s, 4); } break; } } kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 28); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 12); switch(fhptr->handling) { case 2: case 3: case 4: case 5: { /* text handling by TeX/LaTeX */ kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 29); kw_to_stream(oi->s, 1); if(th & DKFIG_TH_MBOX) { kw_to_stream(oi->s, 32); } kw_to_stream(oi->s, 30); if(fhptr->handling != 2) { dkfig_dt_write_fontname(oi->s, oi->d, fhptr); kw_to_stream(oi->s, 1); } if((t->font_flags) & 2) { /* Special text */ dkstream_puts(oi->s, t->text); } else { /* Non-special text */ if(((oi->c)->opt2) & DKFIG_OPT_UTF_8) { /* Handle UTF-8 encoded text */ dkfig_tool2_utf8_to_latex(oi->s, oi->c, t->text); } else { /* Handle normal text */ ptr = t->text; while(*ptr) { dkstream_puts(oi->s, dk_l2l_encoding(*ptr)); ptr++; } } } kw_to_stream(oi->s, 31); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 18); } break; default: { /* Text handling by MetaPost itself */ kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 21); if(((oi->c)->opt2) & DKFIG_OPT_UTF_8) { /* Handle UTF-8 encoded text */ encode_utf8_to_mp(oi->c, oi->s, t->text); } else { /* Handle normal text */ encode_text_to_mp(oi->s, t->text); } kw_to_stream(oi->s, 21), kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 48); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 21); dkstream_puts( oi->s, ( (fhptr->handling == 1) ? dkfont_get_ps_name((size_t)(fhptr->fontno)) : dkfont_get_tex_name((size_t)(fhptr->fontno)) ) ); kw_to_stream(oi->s, 21); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 49); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 2); stream_puts_double( oi->s, dkma_mul_double_ok(fhptr->fontsize,(oi->c)->fsf,&(oi->me)), 1 , oi->c); kw_to_stream(oi->s, 50); kw_to_stream(oi->s, 51); kw_to_stream(oi->s, 52); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 53); kw_to_stream(oi->s, 3); } break; } kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); if(rotation) { kw_to_stream(oi->s, 39); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 12); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 28); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 38); kw_to_stream(oi->s, 1); dv = (180.0 * t->angle) / M_PI; dv = drd(dv, oi->c, 1); stream_puts_double(oi->s, dv, 2, oi->c); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); switch(((oi->o)->fpd).st) { case 1: case 2: { kw_to_stream(oi->s, 45); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 12); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 46); kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 47); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 28); kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 9); kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 42); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 28); kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 40); kw_to_stream(oi->s, 2); dv = cos(t->angle); if(((oi->o)->fpd).st == 1) { dv = 0.5 * dv; } /* dv = dkma_double_restrict_digits(dv, 5); */ if(fabs(dv) < 1.4693e-5) { dv = 0.0; } stream_puts_double(oi->s, dv, 2, oi->c); kw_to_stream(oi->s, 5); dv = sin(t->angle); if(((oi->o)->fpd).st == 1) { dv = 0.5 * dv; } /* dv = dkma_double_restrict_digits(dv, 5); */ if(fabs(dv) < 1.4693e-5) { dv = 0.0; } stream_puts_double(oi->s, dv, 2, oi->c); kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); } break; } } kw_to_stream(oi->s, 33); kw_to_stream(oi->s, 34); if(rotation) { kw_to_stream(oi->s, 37); } else { switch(((oi->o)->fpd).st) { case 1: { kw_to_stream(oi->s, 35); } break; case 2: { kw_to_stream(oi->s, 36); } break; default: { kw_to_stream(oi->s, 37); } break; } } kw_to_stream(oi->s, 2); kw_to_stream(oi->s, (rotation ? 39 : 28)); kw_to_stream(oi->s, 5); kw_to_stream(oi->s, 2); write_long_point(oi, t->x, t->y); kw_to_stream(oi->s, 8); kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 42); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, (rotation ? 39 : 28)); kw_to_stream(oi->s, 3); if(rotation) { switch(((oi->o)->fpd).st) { case 1: case 2: { kw_to_stream(oi->s, 9); kw_to_stream(oi->s, 45); } break; } } kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 1); if(can_use_color(oi->c)) { kw_to_stream(oi->s, 43); kw_to_stream(oi->s, 1); write_dcc_data(oi->s, &dcc, oi->c); } else { kw_to_stream(oi->s, 106); kw_to_stream(oi->s, 1); write_dcc_gray(oi->s, &dcc, oi->c); } kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); } } $? "- print_text_object %d", back return back; } /** Check whether we have an ellipse or a circle. @param ellipse_sub_type Ellipse sub type. @return 1 for real ellipse, 0 for circle. */ static int is_ellipse DK_P1(int, ellipse_sub_type) { int back = 0; if((ellipse_sub_type < 3) || (ellipse_sub_type > 4)) { back = 1; } return back; } /** Write path for an ellipse. @param oi MetaPost output instruction structure. @return 1 on success, 0 on error. */ static int path_ellipse DK_P1(dkfig_mp_output_instruction *,oi) { int back = 0; int me = 0; dk_fig_ellipse *e = NULL; int iselli, rotation; $? "+ path_ellipse" e = (dk_fig_ellipse *)((oi->o)->data); if(e) { $? ". e ok" iselli = rotation = 0; back = 1; iselli = is_ellipse(((oi->o)->fpd).st); if(iselli) { if(fabs(e->angle) > DKFIG_EPSILON) { rotation = 1; } } if(iselli) { if(rotation) { kw_to_stream(oi->s, 2); } kw_to_stream(oi->s, 2); } $? ". iselli=%d rotation=%d", iselli, rotation /* (fullcircle scaled ...) */ kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 58); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 49); kw_to_stream(oi->s, 1); stream_puts_double( oi->s, dkma_mul_double_ok(2.0, fabs(cc_radius(oi->c, e->radiusx)), &me), 1 , oi->c); kw_to_stream(oi->s, 3); if(iselli) { kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 56); kw_to_stream(oi->s, 1); stream_puts_double( oi->s, dkma_div_double_ok( fabs(dkma_l_to_double(e->radiusy)), fabs(dkma_l_to_double(e->radiusx)), &me ), 1 , oi->c); kw_to_stream(oi->s, 3); if(rotation) { kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 38); kw_to_stream(oi->s, 1); stream_puts_double( oi->s, drd(dkma_mul_double_ok( 180.0, dkma_div_double_ok(e->angle, M_PI, &me), &me ), oi->c, 1), 1 , oi->c); kw_to_stream(oi->s, 3); } } /* shifted (...,...) */ kw_to_stream(oi->s, 1); if(rotation) { kw_to_stream(oi->s, 0); } kw_to_stream(oi->s, 57); kw_to_stream(oi->s, 1); write_long_point(oi, e->centerx, e->centery); } if(me) { back = 0; oi->me = me; } $? "- path_ellipse %d", back return back; } /** Write path for a polyline. @param oi MetaPost output instruction structure. @return 1 on success, 0 on error. */ static int path_polyline DK_P1(dkfig_mp_output_instruction *,oi) { int back = 0; int me = 0; dk_fig_polyline *p; dk_fig_bb bbdest; long *xptr, *yptr; size_t i; double deltax, deltay, radius; $? "+ path_polyline" p = (dk_fig_polyline *)((oi->o)->data); if(p) { back = 1; switch(((oi->o)->fpd).st) { case 5: { $? "! no image inclusions possible" /* WARNING: Skipping included image */ dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_WARNING, 53); } /* no break, fall-through wanted to draw empty frame */ case 2: case 4: { $? ". box / arc box" dkfig_tool_bb_reset(&bbdest); xptr = p->xvalues; yptr = p->yvalues; for(i = 0; i < p->npoints; i++) { dkfig_tool_bb_add_x(&bbdest, cc_x(oi->c, *xptr)); dkfig_tool_bb_add_y(&bbdest, cc_y(oi->c, *yptr)); xptr++; yptr++; } if(((oi->o)->fpd).st == 4) { deltax = dkma_sub_double_ok(bbdest.xmax, bbdest.xmin, &me); deltay = dkma_sub_double_ok(bbdest.ymax, bbdest.ymin, &me); radius = 0.9 * dkma_l_to_double(p->radius); if(radius > (0.5 * deltax)) { radius = 0.5 * deltax; } if(radius > (0.5 * deltay)) { radius = 0.5 * deltay; } write_noconv_double_point(oi, bbdest.xmin, (bbdest.ymin + radius), 1); kw_to_stream(oi->s, 30); kw_to_stream(oi->s, 60); kw_to_stream(oi->s, 31); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 7); kw_to_stream(oi->s, 30); kw_to_stream(oi->s, 61); kw_to_stream(oi->s, 31); write_noconv_double_point(oi, (bbdest.xmin + radius), bbdest.ymin, 1); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, (bbdest.xmax - radius), bbdest.ymin, 1); kw_to_stream(oi->s, 30); kw_to_stream(oi->s, 61); kw_to_stream(oi->s, 31); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 7); kw_to_stream(oi->s, 30); kw_to_stream(oi->s, 62); kw_to_stream(oi->s, 31); write_noconv_double_point(oi, bbdest.xmax, (bbdest.ymin + radius), 1); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, bbdest.xmax, (bbdest.ymax - radius), 1); kw_to_stream(oi->s, 30); kw_to_stream(oi->s, 62); kw_to_stream(oi->s, 31); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 7); kw_to_stream(oi->s, 30); kw_to_stream(oi->s, 63); kw_to_stream(oi->s, 31); write_noconv_double_point(oi, (bbdest.xmax - radius), bbdest.ymax, 1); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, (bbdest.xmin + radius), bbdest.ymax, 1); kw_to_stream(oi->s, 30); kw_to_stream(oi->s, 63); kw_to_stream(oi->s, 31); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 7); kw_to_stream(oi->s, 30); kw_to_stream(oi->s, 60); kw_to_stream(oi->s, 31); write_noconv_double_point(oi, bbdest.xmin, (bbdest.ymax - radius), 1); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 6); kw_to_stream(oi->s, 59); } else { write_noconv_double_point(oi, bbdest.xmin, bbdest.ymin, 1); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, bbdest.xmax, bbdest.ymin, 1); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, bbdest.xmax, bbdest.ymax, 1); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, bbdest.xmin, bbdest.ymax, 1); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 6); kw_to_stream(oi->s, 59); } } break; default: { $? ". polyline / polygon" xptr = p->xvalues; yptr = p->yvalues; if((!(((oi->o)->fpd).cl)) && (((oi->o)->fpd).ar & 2)) { $? ". backward arrowhead" write_double_point(oi, (p->pa).x, (p->pa).y, 2); $? ". decrease=%lg", ((oi->o)->fpd).ahb.decrease $? ". x=%lg y=%lg (x=%ld y=%ld)", (p->pa).x, (p->pa).y, *xptr, *yptr } else { $? ". no backward arrowhead" write_long_point(oi, *xptr, *yptr); } xptr++; yptr++; for(i = 1; i < p->npoints; i++) { kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 6); if(i == (p->npoints - 1)) { $? ". last point" if(((oi->o)->fpd).cl) { $? ". closed polygon" kw_to_stream(oi->s, 59); } else { $? ". open polyline" if(((oi->o)->fpd).ar & 1) { $? ". forward arrowhead" write_double_point(oi, (p->pe).x, (p->pe).y, 2); $? ". decrease=%lg", ((oi->o)->fpd).ahf.decrease $? ". x=%lg y=%lg (x=%ld y=%ld)", (p->pe).x, (p->pe).y, *xptr, *yptr } else { $? ". no forward arrowhead" write_long_point(oi, *xptr, *yptr); } } } else { $? ". not the last point" write_long_point(oi, *xptr, *yptr); } xptr++; yptr++; } } break; } } if(me) { back = 0; oi->me = me; } $? "- path_polyline %d", back return back; } /** Write path for a spline. @param oi MetaPost output instruction structure. @return 1 on success, 0 on error. */ static int path_spline DK_P1(dkfig_mp_output_instruction *,oi) { int back = 0; int me = 0; dk_fig_spline *s; size_t nsegs, li, ri, maxli; dk_fig_bezier_point *bpptr; $? "+ path_spline" s = (dk_fig_spline *)((oi->o)->data); if(s) { back = 1; nsegs = s->nbpoints - 1; if(((oi->o)->fpd).cl) { nsegs = s->nbpoints; } bpptr = s->bpoints; if((!(((oi->o)->fpd).cl)) && (((oi->o)->fpd).ar & 2)) { /* pa....pa2 */ $? ". pa" $!trace-code trace_bezier_point(&(s->pa)); $? ". pa2" $!trace-code trace_bezier_point(&(s->pa2)); write_double_point(oi, (s->pa).value.x, (s->pa).value.y, 2); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 7); kw_to_stream(oi->s, 64); write_double_point(oi, (s->pa).rcontrol.x, (s->pa).rcontrol.y, 2); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 65); write_double_point(oi, (s->pa2).lcontrol.x, (s->pa2).lcontrol.y, 2); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 7); write_double_point(oi, (s->pa2).value.x, (s->pa2).value.y, 2); li = s->normals; } else { write_double_point(oi, bpptr[0].value.x, bpptr[0].value.y, 2); li = 0; } if((s->normale > 0) || (((oi->o)->fpd).cl) || (!((((oi->o)->fpd).ar) & 1))) { maxli = s->nbpoints - 2; if(((oi->o)->fpd).cl) { maxli = s->nbpoints - 1; } if((!(((oi->o)->fpd).cl)) && (((oi->o)->fpd).ar & 1)) { maxli = s->normale - 1; } while(li <= maxli) { ri = li + 1; if(ri >= s->nbpoints) { ri = 0; } $? ". li" $!trace-code trace_bezier_point(&((s->bpoints)[li])); $? ". ri" $!trace-code trace_bezier_point(&((s->bpoints)[ri])); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 7); kw_to_stream(oi->s, 64); write_double_point(oi, bpptr[li].rcontrol.x, bpptr[li].rcontrol.y, 2); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 65); write_double_point(oi, bpptr[ri].lcontrol.x, bpptr[ri].lcontrol.y, 2); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 7); if(ri == 0) { kw_to_stream(oi->s, 59); } else { write_double_point(oi, bpptr[ri].value.x, bpptr[ri].value.y, 2); } li++; } } if((!(((oi->o)->fpd).cl)) && (((oi->o)->fpd).ar & 1)) { $? ". pe2" $!trace-code trace_bezier_point(&(s->pe2)); $? ". pe" $!trace-code trace_bezier_point(&(s->pe)); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 7); kw_to_stream(oi->s, 64); write_double_point(oi, (s->pe2).rcontrol.x, (s->pe2).rcontrol.y, 2); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 65); write_double_point(oi, (s->pe).lcontrol.x, (s->pe).lcontrol.y, 2); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 7); write_double_point(oi, (s->pe).value.x, (s->pe).value.y, 2); } } if(me) { back = 0; oi->me = me; } $? "- path_spline %d", back return back; } /** Write path for an arc. @param oi MetaPost output instruction structure. @return 1 on success, 0 on error. */ static int path_arc DK_P1(dkfig_mp_output_instruction *,oi) { int back = 0; int me = 0; double ahlgt, rl; dk_fig_arc *a; $? "+ path_arc" a = (dk_fig_arc *)((oi->o)->data); if(a) { back = 1; ahlgt = 0.0; if((!(((oi->o)->fpd).cl)) && ((((oi->o)->fpd).ar) & 1)) { /* ahlgt = a->lba; */ ahlgt = a->rba; } if((!(((oi->o)->fpd).cl)) && ((((oi->o)->fpd).ar) & 2)) { /* ahlgt = dkma_add_double_ok(ahlgt, a->rba, &me); */ ahlgt = dkma_add_double_ok(ahlgt, a->lba, &me); } $? ". ahlength=%lg ahlgt=%lg", (a->calc).alength, ahlgt if(ahlgt <= (a->calc).alength) { back = 1; rl = dkma_sub_double_ok((a->calc).alength, ahlgt, &me); $? ". rl=%lg", rl if(((oi->o)->fpd).st == 2) { kw_to_stream(oi->s, 2); } kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 58); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 66); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 2); write_noconv_double_point(oi, 0.0, 0.0, 1); kw_to_stream(oi->s, 6); write_noconv_double_point( oi, (1.1 * cos(rl)), (1.1 * sin(rl)) , 2); kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 38); kw_to_stream(oi->s, 1); rl = (a->calc).astart; if((!(((oi->o)->fpd).cl)) && ((((oi->o)->fpd).ar) & 2)) { rl = dkma_add_double_ok(rl, a->lba, &me); } rl = dkma_mul_double_ok( 180.0, dkma_div_double_ok(rl, M_PI, &me), &me ); rl = drd(rl, oi->c, 2); stream_puts_double(oi->s, rl, 2, oi->c); kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 49); kw_to_stream(oi->s, 1); stream_puts_double( oi->s, ccd_radius(oi->c, dkma_mul_double_ok(2.0, (a->calc).ra, &me) ), 1 , oi->c); kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 57); kw_to_stream(oi->s, 1); write_double_point(oi, (a->calc).xm, (a->calc).ym, 1); if(((oi->o)->fpd).st == 2) { kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 6); write_double_point(oi, (a->calc).xm, (a->calc).ym, 1); kw_to_stream(oi->s, 6); kw_to_stream(oi->s, 59); } } else { $? "! arrowhead removal larger than arrow" } } if(me) { back = 0; oi->me = me; } $? "- path_arc %d", back return back; } /** Write a color cell. @param oi MetaPost output instruction structure. @param dcc Color cell structure. */ static void write_color_c DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { if(can_use_color(oi->c)) { kw_to_stream(oi->s, 68); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 69); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 69); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 12); kw_to_stream(oi->s, 1); write_dcc_data(oi->s, dcc, oi->c); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); } } /** Set new line join (if it differs from the current line join). @param oi MetaPost output instruction structure. @param js Line join. */ static void set_line_join DK_P2(dkfig_mp_output_instruction *,oi, int,js) { int must_do_it = 1; if(((oi->m)->haveflags) & HAVE_LINEJOIN) { if((oi->m)->linejoin == js) { must_do_it = 0; } } if(must_do_it) { (oi->m)->haveflags = (oi->m)->haveflags | HAVE_LINEJOIN; (oi->m)->linejoin = js; kw_to_stream(oi->s, 77); kw_to_stream(oi->s, 75); switch(js) { case 1: kw_to_stream(oi->s, 11); break; case 2: kw_to_stream(oi->s, 76); break; default: kw_to_stream(oi->s, 10); break; } kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); } } /** Set new arrowhead length (only if it differs from the current arrowhead length). @param oi MetaPost output instruction structure. @param h New arrowhead length. */ static void set_ahlength DK_P2(dkfig_mp_output_instruction *,oi, double,h) { double newv, d, m; int me = 0; int must_do_it = 1; newv = dkma_mul_double_ok( 72.0, dkma_div_double_ok(fabs(h), (oi->d)->fres, &me), &me ); if(((oi->m)->haveflags) & HAVE_AHLENGTH) { d = fabs(newv - (oi->m)->ahlength); if(newv < (oi->m)->ahlength) { m = newv; } else { m = (oi->m)->ahlength; } if((d < DKFIG_EPSILON) && (d < m)) { must_do_it = 0; } } if(must_do_it && (!me)) { kw_to_stream(oi->s, 82); kw_to_stream(oi->s, 75); stream_puts_double(oi->s, newv, 1, oi->c); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); (oi->m)->haveflags = (oi->m)->haveflags | HAVE_AHLENGTH; (oi->m)->ahlength = newv; } } /** Set a new arrowhead angle (only if it differs from the current arrowhead angle). @param oi MetaPost output instruction structure. @param w Arrowhead width. @param h Arrowhead height. */ static void set_ahangle DK_P3(dkfig_mp_output_instruction *,oi, double,w, double,h) { double newv, d, m; int must_do_it = 1; newv = dkma_atan2((0.5*w), h); newv = 360.0 * newv / M_PI; newv = drd(newv, oi->c, 1); if(((oi->m)->haveflags) & HAVE_AHANGLE) { d = fabs(newv - (oi->m)->ahangle); if(fabs((oi->m)->ahangle) < fabs(newv)) { m = DKFIG_EPSILON * fabs((oi->m)->ahangle); } else { m = DKFIG_EPSILON * fabs(newv); } if((d < DKFIG_EPSILON) && (d < m)) { must_do_it = 0; } } if(must_do_it) { kw_to_stream(oi->s, 83); kw_to_stream(oi->s, 75); stream_puts_double(oi->s, newv, 1, oi->c); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); (oi->m)->haveflags = (oi->m)->haveflags | HAVE_AHANGLE; (oi->m)->ahangle = newv; } } /** Set a new line cap (only if it differs from the current line cap). @param oi MetaPost output instruction structure. @param cs Linecap style. */ static void set_line_cap DK_P2(dkfig_mp_output_instruction *,oi, int,cs) { int must_do_it = 1; if(((oi->m)->haveflags) & HAVE_LINECAP) { if((oi->m)->linecap == cs) { must_do_it = 0; } } if(must_do_it) { (oi->m)->haveflags = (oi->m)->haveflags | HAVE_LINECAP; (oi->m)->linecap = cs; kw_to_stream(oi->s, 74); kw_to_stream(oi->s, 75); switch(cs) { case 1: kw_to_stream(oi->s, 11); break; case 2: kw_to_stream(oi->s, 76); break; default: kw_to_stream(oi->s, 10); break; } kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); } } /** Set a new line width (only if the new line width differs from the current line width. @param oi MetaPost output instruction structure. @param lt Line width. */ static void set_line_width DK_P2(dkfig_mp_output_instruction *,oi, long,lt) { int me = 0; int must_do_it = 1; double newlw; double d, m; newlw = 0.9 * dkma_l_to_double(lt); if(((oi->c)->opt1) & DKFIG_OPT_ENLIGHTEN_LOOK) { newlw = 0.5 * newlw; } if(((oi->m)->haveflags) & HAVE_LINEWIDTH) { d = fabs((oi->m)->linewidth - newlw); if(fabs(newlw) < fabs((oi->m)->linewidth)) { m = DKFIG_EPSILON * fabs(newlw); } else { m = DKFIG_EPSILON * fabs((oi->m)->linewidth); } if((d < m) && (d < DKFIG_EPSILON)) { must_do_it = 0; } } if(must_do_it && (!me)) { kw_to_stream(oi->s, 71); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 72); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 49); kw_to_stream(oi->s, 1); stream_puts_double(oi->s, newlw, 1, oi->c); /* kw_to_stream(oi->s, 73); */ kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); (oi->m)->haveflags = (oi->m)->haveflags | HAVE_LINEWIDTH; (oi->m)->linewidth = newlw; } } /** Write path for arrowhead. @param oi MetaPost output instruction structure. @param rev Flag: Arrowhead reverse. */ static void arrowhead_path DK_P2(dkfig_mp_output_instruction *,oi, int,rev) { kw_to_stream(oi->s, 25); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 78); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); if(((oi->c)->opt1) & DKFIG_OPT_METAPOST_ARROWHEADS) { set_ahangle(oi, (oi->a)->w, (oi->a)->h); set_ahlength(oi, (oi->a)->h); kw_to_stream(oi->s, 78); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 12); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 79); kw_to_stream(oi->s, 1); if(rev) { kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 80); kw_to_stream(oi->s, 1); } kw_to_stream(oi->s, 27); if(rev) { kw_to_stream(oi->s, 3); } kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); } else { kw_to_stream(oi->s, 78); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 12); kw_to_stream(oi->s, 1); write_double_point(oi, ((oi->a)->p1).x, ((oi->a)->p1).y, 1); kw_to_stream(oi->s, 6); write_double_point(oi, ((oi->a)->p2).x, ((oi->a)->p2).y, 1); kw_to_stream(oi->s, 6); write_double_point(oi, ((oi->a)->p3).x, ((oi->a)->p3).y, 1); kw_to_stream(oi->s, 0); if((oi->a)->type > 0) { if((oi->a)->type > 1) { kw_to_stream(oi->s, 6); write_double_point(oi, ((oi->a)->p4).x, ((oi->a)->p4).y, 1); } kw_to_stream(oi->s, 6); kw_to_stream(oi->s, 59); } kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); } } /** Write instructions to draw arrowhead. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @param hc Flag: Color stored in variable c. */ static void arrowhead_fd DK_P3(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc, int,hc) { set_line_join(oi, (oi->d)->ahlj); if((oi->a)->type > 0) { kw_to_stream(oi->s, 67); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 78); kw_to_stream(oi->s, 1); if(can_use_color(oi->c)) { kw_to_stream(oi->s, 43); kw_to_stream(oi->s, 1); if((oi->a)->style > 0) { if(hc) { kw_to_stream(oi->s, 69); } else { write_dcc_data(oi->s, dcc, oi->c); } } else { kw_to_stream(oi->s, 81); } } else { kw_to_stream(oi->s, 106); kw_to_stream(oi->s, 1); if((oi->a)->style > 0) { write_dcc_gray(oi->s, dcc, oi->c); } else { kw_to_stream(oi->s, 11); } } kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); } kw_to_stream(oi->s, 70); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 78); kw_to_stream(oi->s, 1); if(can_use_color(oi->c)) { kw_to_stream(oi->s, 43); kw_to_stream(oi->s, 1); if(hc) { kw_to_stream(oi->s, 69); } else { write_dcc_data(oi->s, dcc, oi->c); } } else { kw_to_stream(oi->s, 106); kw_to_stream(oi->s, 1); write_dcc_gray(oi->s, dcc, oi->c); } kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); } /** Write start of addto ... instruction. @param oi MetaPost output instruction structure. */ static void start_addto DK_P1(dkfig_mp_output_instruction *,oi) { kw_to_stream(oi->s, 87); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 28); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 94); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 0); } /** Write end of addto instruction. @param oi MetaPost output instruction structure. @param dcc Color cell structure. */ static void end_addto DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 1); if(can_use_color(oi->c)) { kw_to_stream(oi->s, 43); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 69); } else { kw_to_stream(oi->s, 106); kw_to_stream(oi->s, 1); write_dcc_gray(oi->s, dcc, oi->c); } kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 95); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 96); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); } /** Fill pattern: 30 degree lines to the left. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int diagonal_left_30 DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; double xstart, xend, ystart, yend, y0, y1, deltay, y; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; deltay = fabs(oi->patrp); deltay = dkma_div_double_ok(deltay, sqrt(0.75), &me); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { y0 = dkma_add_double_ok( ystart, dkma_mul_double_ok(0.5, xstart, &me), &me ); y0 = dkma_div_double_ok(y0, deltay, &me); y1 = floor(y0); y0 = dkma_sub_double_ok(y0, y1, &me); y0 = dkma_mul_double_ok(y0, deltay, &me); ystart = dkma_sub_double_ok(ystart, y0, &me); } y1 = dkma_sub_double_ok(xend, xstart, &me); y1 = dkma_mul_double_ok(0.5, y1, &me); yend = dkma_add_double_ok(yend, y1, &me); y = ystart; while(y <= yend) { start_addto(oi); write_noconv_double_point(oi, xstart, y, 2); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, xend, dkma_sub_double_ok(y,y1,&me), 2); end_addto(oi, dcc); y = dkma_add_double_ok(y, deltay, &me); } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: 30 degree lines to the right. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int diagonal_right_30 DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; double xstart, xend, ystart, yend, y0, y1, deltay, y; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; deltay = fabs(oi->patrp); deltay = dkma_div_double_ok(deltay, sqrt(0.75), &me); y1 = dkma_sub_double_ok(xend, xstart, &me); y1 = dkma_mul_double_ok(0.5, y1, &me); ystart = dkma_sub_double_ok(ystart, y1, &me); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { y0 = dkma_sub_double_ok( ystart, dkma_mul_double_ok(0.5, xstart, &me), &me ); y0 = dkma_div_double_ok(y0, deltay, &me); y1 = floor(y0); y0 = dkma_sub_double_ok(y0, y1, &me); y0 = dkma_mul_double_ok(y0, deltay, &me); ystart = dkma_sub_double_ok(ystart, y0, &me); } y1 = dkma_sub_double_ok(xend, xstart, &me); y1 = dkma_mul_double_ok(0.5, y1, &me); y = ystart; while(y <= yend) { start_addto(oi); write_noconv_double_point(oi, xstart, y, 2); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, xend, dkma_add_double_ok(y,y1,&me), 2); end_addto(oi, dcc); y = dkma_add_double_ok(y, deltay, &me); } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: 30 degree crosshatch. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int crosshatch_30 DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; if(!diagonal_left_30(oi, dcc)) { back = 0; } if(!diagonal_right_30(oi, dcc)) { back = 0; } return back; } /** Fill pattern: 45 degree lines to the left. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int diagonal_left_45 DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; double xstart, xend, ystart, yend, y0, y1, deltay, y; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; deltay = fabs(oi->patrp); deltay = dkma_div_double_ok(deltay, sqrt(0.5), &me); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { y0 = dkma_add_double_ok( ystart, xstart, &me ); y0 = dkma_div_double_ok(y0, deltay, &me); y1 = floor(y0); y0 = dkma_sub_double_ok(y0, y1, &me); y0 = dkma_mul_double_ok(y0, deltay, &me); ystart = dkma_sub_double_ok(ystart, y0, &me); } y1 = dkma_sub_double_ok(xend, xstart, &me); /* y1 = dkma_mul_double_ok(sqrt(0.5), y1, &me); */ yend = dkma_add_double_ok(yend, y1, &me); y = ystart; while(y <= yend) { start_addto(oi); write_noconv_double_point(oi, xstart, y, 2); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, xend, dkma_sub_double_ok(y,y1,&me), 2); end_addto(oi, dcc); y = dkma_add_double_ok(y, deltay, &me); } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: 45 degree lines to the right. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int diagonal_right_45 DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; double xstart, xend, ystart, yend, y0, y1, deltay, y; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; deltay = fabs(oi->patrp); deltay = dkma_div_double_ok(deltay, sqrt(0.5), &me); y1 = dkma_sub_double_ok(xend, xstart, &me); /* y1 = dkma_mul_double_ok(0.5, y1, &me); */ ystart = dkma_sub_double_ok(ystart, y1, &me); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { y0 = dkma_sub_double_ok( ystart, xstart, &me ); y0 = dkma_div_double_ok(y0, deltay, &me); y1 = floor(y0); y0 = dkma_sub_double_ok(y0, y1, &me); y0 = dkma_mul_double_ok(y0, deltay, &me); ystart = dkma_sub_double_ok(ystart, y0, &me); } y1 = dkma_sub_double_ok(xend, xstart, &me); /* y1 = dkma_mul_double_ok(sqrt(0.5), y1, &me); */ y = ystart; while(y <= yend) { start_addto(oi); write_noconv_double_point(oi, xstart, y, 2); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, xend, dkma_add_double_ok(y,y1,&me), 2); end_addto(oi, dcc); y = dkma_add_double_ok(y, deltay, &me); } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: 45 degree crosshatch. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int crosshatch_45 DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; if(!diagonal_left_45(oi, dcc)) { back = 0; } if(!diagonal_right_45(oi, dcc)) { back = 0; } return back; } /** Fill pattern: horizontal bricks. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int horizontal_bricks DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; int inslevel = 0; double xstart, ystart, xend, yend, deltay, y, x; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; deltay = fabs(oi->patrp); deltay = dkma_mul_double_ok(2.0, deltay, &me); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { ystart = floor(dkma_div_double_ok(ystart, deltay, &me)); if((dkma_double_to_l(ystart)) % 2L) { inslevel = 1; } ystart = dkma_mul_double_ok(deltay, ystart, &me); xstart = dkma_sub_double_ok(xstart, deltay, &me); xstart = floor(dkma_div_double_ok(xstart,dkma_mul_double_ok(2.0,deltay,&me),&me)); xstart = dkma_mul_double_ok(xstart,dkma_mul_double_ok(2.0,deltay,&me),&me); } y = ystart; while(y <= yend) { start_addto(oi); write_noconv_double_point(oi, xstart, y, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, xend, y, 1); end_addto(oi, dcc); x = xstart; if(inslevel) { x = dkma_add_double_ok(x, deltay, &me); } while(x <= xend) { start_addto(oi); write_noconv_double_point(oi, x, y, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x, dkma_add_double_ok(y, deltay, &me), 1); end_addto(oi, dcc); x = dkma_add_double_ok(x,dkma_mul_double_ok(2.0,deltay,&me),&me); } y = dkma_add_double_ok(y, deltay, &me); inslevel = (inslevel ? 0: 1); } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: vertical bricks. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int vertical_bricks DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; int inslevel = 0; double xstart, ystart, xend, yend, deltax, x, y; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; deltax = fabs(dkma_mul_double_ok(2.0,oi->patrp,&me)); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { xstart = floor(dkma_div_double_ok(xstart, deltax, &me)); if(dkma_double_to_l(xstart) % 2L) { inslevel = 1; } xstart = dkma_mul_double_ok(deltax, xstart, &me); ystart = dkma_sub_double_ok(ystart, deltax, &me); ystart = floor(dkma_div_double_ok(ystart,dkma_mul_double_ok(2.0,deltax,&me),&me)); ystart = dkma_mul_double_ok(ystart,dkma_mul_double_ok(2.0,deltax,&me),&me); } x = xstart; while(x <= xend) { start_addto(oi); write_noconv_double_point(oi, x, ystart, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x, yend, 1); end_addto(oi, dcc); y = ystart; if(inslevel) { y = dkma_add_double_ok(y,deltax,&me); } while(y <= yend) { start_addto(oi); write_noconv_double_point(oi, x, y, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, dkma_add_double_ok(x,deltax,&me), y, 1); end_addto(oi, dcc); y = dkma_add_double_ok(y,dkma_mul_double_ok(2.0,deltax,&me),&me); } x = dkma_add_double_ok(x, deltax, &me); inslevel = (inslevel ? 0 : 1); } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: Horizontal lines. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int horizontal_lines DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; double xstart, ystart, xend, yend, deltay, y; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; deltay = fabs(oi->patrp); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { ystart = dkma_mul_double_ok( deltay, floor(dkma_div_double_ok(ystart, deltay, &me)), &me ); } y = ystart; while(y <= yend) { start_addto(oi); write_noconv_double_point(oi, xstart, y, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, xend, y, 1); end_addto(oi, dcc); y = dkma_add_double_ok(y, deltay, &me); } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: Vertical lines. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int vertical_lines DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; double xstart, ystart, xend, yend, deltax, x; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; deltax = fabs(oi->patrp); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { xstart = dkma_mul_double_ok( deltax, floor(dkma_div_double_ok(xstart, deltax, &me)), &me ); } x = xstart; while(x <= xend) { start_addto(oi); write_noconv_double_point(oi, x, ystart, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x, yend, 1); end_addto(oi, dcc); x = dkma_add_double_ok(x, deltax, &me); } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: Crosshatch. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int crosshatch DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; if(!horizontal_lines(oi, dcc)) { back = 0; } if(!vertical_lines(oi, dcc)) { back = 0; } return back; } /** Fill pattern: Horizontal shingles skewed to the right. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int horiz_shingles_right DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; int inslevel = 0; double xstart, ystart, xend, yend, deltay, y, x, deltax; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; deltax = deltay = fabs(oi->patrp); deltay = dkma_mul_double_ok(2.0, deltay, &me); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { ystart = floor(dkma_div_double_ok(ystart,deltay,&me)); inslevel = (int)(dkma_double_to_l(ystart) % 4L); ystart = dkma_mul_double_ok(deltay,ystart,&me); xstart = dkma_sub_double_ok(xstart, deltay, &me); xstart = floor(dkma_div_double_ok(xstart,dkma_mul_double_ok(2.0,deltay,&me),&me)); xstart = dkma_mul_double_ok(xstart,dkma_mul_double_ok(2.0,deltay,&me),&me); } y = ystart; while(y <= yend) { start_addto(oi); write_noconv_double_point(oi, xstart, y, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, xend, y, 1); end_addto(oi, dcc); /* x = xstart; if(inslevel) { x = dkma_add_double_ok(x, deltay, &me); } */ switch(inslevel) { case 3: { x = dkma_add_double_ok(xstart,deltax,&me); } break; case 2: { x = dkma_add_double_ok(xstart,deltay,&me); } break; case 1: { x = dkma_add_double_ok(xstart,dkma_mul_double_ok(1.5,deltay,&me),&me); } break; default: { x = xstart; } break; } while(x <= xend) { start_addto(oi); write_noconv_double_point(oi, x, y, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, dkma_add_double_ok(x,deltax,&me), dkma_add_double_ok(y, deltay, &me), 1); end_addto(oi, dcc); x = dkma_add_double_ok(x,dkma_mul_double_ok(2.0,deltay,&me),&me); } y = dkma_add_double_ok(y, deltay, &me); inslevel++; if(inslevel >= 4) { inslevel = 0; } } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: Horizontal shingles skewed to the left. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int horiz_shingles_left DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; int inslevel = 0; double xstart, ystart, xend, yend, deltay, y, x, deltax; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; deltax = deltay = fabs(oi->patrp); deltay = dkma_mul_double_ok(2.0, deltay, &me); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { ystart = floor(dkma_div_double_ok(ystart,deltay,&me)); inslevel = (int)(dkma_double_to_l(ystart) % 4L); ystart = dkma_mul_double_ok(deltay,ystart,&me); xstart = dkma_sub_double_ok(xstart, deltay, &me); xstart = floor(dkma_div_double_ok(xstart,dkma_mul_double_ok(2.0,deltay,&me),&me)); xstart = dkma_mul_double_ok(xstart,dkma_mul_double_ok(2.0,deltay,&me),&me); } y = ystart; while(y <= yend) { start_addto(oi); write_noconv_double_point(oi, xstart, y, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, xend, y, 1); end_addto(oi, dcc); /* x = xstart; if(inslevel) { x = dkma_add_double_ok(x, deltay, &me); } */ switch(inslevel) { case 3: { x = dkma_add_double_ok(xstart,dkma_add_double_ok(deltax,deltay,&me),&me); } break; case 2: { x = dkma_add_double_ok(xstart,deltay,&me); } break; case 1: { x = dkma_add_double_ok(xstart,deltax,&me); } break; default: { x = xstart; } break; } while(x <= xend) { start_addto(oi); write_noconv_double_point(oi, dkma_add_double_ok(x,deltax,&me), y, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x, dkma_add_double_ok(y, deltay, &me), 1); end_addto(oi, dcc); x = dkma_add_double_ok(x,dkma_mul_double_ok(2.0,deltay,&me),&me); } y = dkma_add_double_ok(y, deltay, &me); inslevel++; if(inslevel >= 4) { inslevel = 0; } } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: Vertical shingles 1. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int vert_shingles_one DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; int inslevel = 0; double xstart, ystart, xend, yend, deltay, deltax, x, y; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; deltay = deltax = fabs(oi->patrp); deltax = dkma_mul_double_ok(2.0, deltax, &me); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { xstart = floor(dkma_div_double_ok(xstart, deltax, &me)); inslevel = (int)(dkma_double_to_l(xstart) % 4L); xstart = dkma_mul_double_ok(deltax, xstart, &me); ystart = floor(dkma_div_double_ok(ystart,dkma_mul_double_ok(2.0,deltax,&me),&me)); ystart = dkma_mul_double_ok(ystart,dkma_mul_double_ok(2.0,deltax,&me),&me); } x = xstart; while(x <= xend) { start_addto(oi); write_noconv_double_point(oi, x, ystart, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x, yend, 1); end_addto(oi, dcc); switch(inslevel) { case 3: { y = dkma_add_double_ok(ystart,dkma_add_double_ok(deltax,deltay,&me),&me); } break; case 2: { y = dkma_add_double_ok(ystart,deltax,&me); } break; case 1: { y = dkma_add_double_ok(ystart,deltay,&me); } break; default: { y = ystart; } break; } while(y <= yend) { start_addto(oi); write_noconv_double_point(oi, x, dkma_add_double_ok(y,deltay,&me), 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, dkma_add_double_ok(x,deltax,&me), y, 1); end_addto(oi, dcc); y = dkma_add_double_ok(y,dkma_mul_double_ok(2.0,deltax,&me),&me); } x = dkma_add_double_ok(x, deltax, &me); inslevel++; if(inslevel >= 4) { inslevel = 0; } } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: Vertical shingles 2. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int vert_shingles_two DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; int inslevel = 0; double xstart, ystart, xend, yend, deltay, deltax, x, y; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; deltay = deltax = fabs(oi->patrp); deltax = dkma_mul_double_ok(2.0, deltax, &me); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { xstart = floor(dkma_div_double_ok(xstart, deltax, &me)); inslevel = (int)(dkma_double_to_l(xstart) % 4L); xstart = dkma_mul_double_ok(deltax, xstart, &me); ystart = floor(dkma_div_double_ok(ystart,dkma_mul_double_ok(2.0,deltax,&me),&me)); ystart = dkma_mul_double_ok(ystart,dkma_mul_double_ok(2.0,deltax,&me),&me); } x = xstart; while(x <= xend) { start_addto(oi); write_noconv_double_point(oi, x, ystart, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x, yend, 1); end_addto(oi, dcc); switch(inslevel) { case 3: { y = dkma_add_double_ok(ystart,deltay,&me); } break; case 2: { y = dkma_add_double_ok(ystart,deltax,&me); } break; case 1: { y = dkma_add_double_ok(ystart,dkma_add_double_ok(deltax,deltay,&me),&me); } break; default: { y = ystart; } break; } while(y <= yend) { start_addto(oi); write_noconv_double_point(oi, x, y, 1); kw_to_stream(oi->s, 6); write_noconv_double_point( oi, dkma_add_double_ok(x,deltax,&me), dkma_add_double_ok(y,deltay,&me) , 1); end_addto(oi, dcc); y = dkma_add_double_ok(y,dkma_mul_double_ok(2.0,deltax,&me),&me); } x = dkma_add_double_ok(x, deltax, &me); inslevel++; if(inslevel >= 4) { inslevel = 0; } } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: Fish scales. @param oi MetaPost output instruction structure. @param ar Arc start angle. @param phi Arc width angle. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int do_fish_scales DK_P4(dkfig_mp_output_instruction *,oi, double,ar, double,phi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; int inslevel = 0; double radius, xstart, ystart, xend, yend, deltax, dxh, deltay; double x, y, xm, ym; double cutx, cuty, rot, cuts; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; radius = dkma_mul_double_ok(2.0, fabs(oi->patrp), &me); radius = dkma_mul_double_ok(ar, radius, &me); deltax = dkma_mul_double_ok(2.0, dkma_mul_double_ok(radius, sin(phi/2.0), &me), &me); deltax = drd(deltax, oi->c, 2); dxh = 0.5 * deltax; deltay = dkma_mul_double_ok(radius,dkma_sub_double_ok(1.0,cos(phi/2.0),&me),&me); deltay = drd(deltay, oi->c, 2); rot = 1.5 * M_PI - 0.5 * phi; rot = dkma_sub_double_ok( dkma_mul_double_ok(1.5, M_PI, &me), dkma_mul_double_ok(0.5, phi, &me), &me ); rot = dkma_div_double_ok( dkma_mul_double_ok(180.0, rot, &me), M_PI, &me ); rot = drd(rot, oi->c, 2); xstart = dkma_sub_double_ok(xstart, dxh, &me); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { xstart = floor(dkma_div_double_ok(xstart, deltax, &me)); if(dkma_double_to_l(xstart) % 2L) { inslevel = 1; } xstart = dkma_mul_double_ok(deltax, xstart, &me); ystart = floor(dkma_div_double_ok(ystart, deltay, &me)); ystart = dkma_mul_double_ok(deltay, ystart, &me); } cutx = 1.25 * cos(phi); cuty = 1.25 * sin(phi); cuts = dkma_mul_double_ok(2.0, radius, &me); y = ystart; while(y <= yend) { ym = dkma_add_double_ok(y, radius, &me); x = xstart; if(inslevel) { x = dkma_add_double_ok(x, dxh, &me); } while(x <= xend) { xm = dkma_add_double_ok(x, dxh, &me); start_addto(oi); kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 58); /* fullcircle */ kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 66); /* cutafter */ kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 98); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, cutx, cuty, 2); kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 38); kw_to_stream(oi->s, 1); stream_puts_double(oi->s, rot, 2, oi->c); kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 49); kw_to_stream(oi->s, 1); stream_puts_double(oi->s, cuts, 2, oi->c); kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 57); kw_to_stream(oi->s, 1); write_noconv_double_point(oi, xm, ym, 2); end_addto(oi, dcc); x = dkma_add_double_ok(x, deltax, &me); } y = dkma_add_double_ok(y, deltay, &me); inslevel = (inslevel ? 0 : 1); } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: Large fish scales. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int large_fish_scales DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; back = do_fish_scales(oi, 1.25, 1.881618, dcc); return back; } /** Fill pattern: Small fish scales. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int small_fish_scales DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; back = do_fish_scales(oi, 0.5, M_PI, dcc); return back; } /** Fill pattern: Circles. @param oi MetaPost output instruction structure. @param dcc Color cell structure, @return 1 on success, 0 on error. */ static int circles DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; double xstart, ystart, xend, yend, deltay, deltax, x, y, r, xm; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; r = dkma_mul_double_ok(2.0, fabs(oi->patrp), &me); deltay = deltax = dkma_mul_double_ok(2.0, r, &me); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { xstart = floor(dkma_div_double_ok(xstart, deltax, &me)); xstart = dkma_mul_double_ok(deltax, xstart, &me); ystart = floor(dkma_div_double_ok(ystart, deltay, &me)); ystart = dkma_mul_double_ok(deltay, ystart, &me); } x = xstart; while(x <= xend) { y = ystart; xm = dkma_add_double_ok(x, r, &me); while(y <= yend) { start_addto(oi); kw_to_stream(oi->s, 2); kw_to_stream(oi->s, 58); /* fullcircle */ kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 49); /* scaled */ kw_to_stream(oi->s, 1); stream_puts_double(oi->s, deltay, 1, oi->c); kw_to_stream(oi->s, 73); /* bp */ kw_to_stream(oi->s, 3); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 57); kw_to_stream(oi->s, 1); write_noconv_double_point( oi, xm, dkma_add_double_ok(y, r, &me) , 1); end_addto(oi, dcc); y = dkma_add_double_ok(y, deltay, &me); } x = dkma_add_double_ok(x, deltax, &me); } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: Hexagons. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int hexagons DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; double xstart, ystart, xend, yend, deltay, deltax, x, y, r; double x1, x2, x3, x4, y1, y2; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; r = dkma_mul_double_ok(2.0, fabs(oi->patrp), &me); deltay = deltax = dkma_mul_double_ok(2.0, r, &me); r = dkma_div_double_ok(deltay, sqrt(3.0), &me); deltax = dkma_mul_double_ok(3.0, r, &me); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { xstart = floor(dkma_div_double_ok(xstart, deltax, &me)); xstart = dkma_mul_double_ok(deltax, xstart, &me); ystart = floor(dkma_div_double_ok(ystart, deltay, &me)); ystart = dkma_mul_double_ok(deltay, ystart, &me); } x = xstart; while(x <= xend) { x1 = dkma_add_double_ok(x, dkma_mul_double_ok(0.5, r, &me), &me); x2 = dkma_add_double_ok(x, dkma_mul_double_ok(1.5, r, &me), &me); x3 = dkma_add_double_ok(x, dkma_mul_double_ok(2.0, r, &me), &me); x4 = dkma_add_double_ok(x, dkma_mul_double_ok(3.0, r, &me), &me); y = ystart; while(y <= yend) { y1 = dkma_add_double_ok(y, dkma_mul_double_ok(0.5, deltay, &me), &me); y2 = dkma_add_double_ok(y, deltay, &me); start_addto(oi); write_noconv_double_point(oi, x, y1, 2); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x1, y, 2); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x2, y, 2); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x3, y1, 2); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x2, y2, 2); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x1, y2, 2); kw_to_stream(oi->s, 6); kw_to_stream(oi->s, 59); end_addto(oi, dcc); start_addto(oi); write_noconv_double_point(oi, x3, y1, 2); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x4, y1, 2); end_addto(oi, dcc); y = y2; } x = dkma_add_double_ok(x, deltax, &me); } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: Octagons. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int octagons DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; double xstart, ystart, xend, yend, deltay, deltax, x, y, r; double x1, x2, x3, y1, y2, y3; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; r = dkma_mul_double_ok(2.0, fabs(oi->patrp), &me); deltay = deltax = dkma_mul_double_ok(2.0, r, &me); r = dkma_div_double_ok( deltay, dkma_add_double_ok(2.0,sqrt(2.0),&me), &me ); r = drd(r, oi->c, 1); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { xstart = floor(dkma_div_double_ok(xstart, deltax, &me)); xstart = dkma_mul_double_ok(deltax, xstart, &me); ystart = floor(dkma_div_double_ok(ystart, deltay, &me)); ystart = dkma_mul_double_ok(deltay, ystart, &me); } x = xstart; while(x <= xend) { y = ystart; x1 = dkma_add_double_ok(x, r, &me); x3 = dkma_add_double_ok(x, deltax, &me); x2 = dkma_sub_double_ok(x3, r, &me); while(y <= yend) { y1 = dkma_add_double_ok(y, r, &me); y3 = dkma_add_double_ok(y, deltay, &me); y2 = dkma_sub_double_ok(y3, r, &me); start_addto(oi); write_noconv_double_point(oi, x1, y, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x2, y, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x3, y1, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x3, y2, 1); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x2, y3, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x1, y3, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x, y2, 1); kw_to_stream(oi->s, 6); write_noconv_double_point(oi, x, y1, 1); kw_to_stream(oi->s, 6); kw_to_stream(oi->s, 59); end_addto(oi, dcc); y = dkma_add_double_ok(y, deltay, &me); } x = dkma_add_double_ok(x, deltax, &me); } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: Horizontal tires. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int horiz_tires DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; double xstart, ystart, xend, yend, deltax, deltay, x, y, y1; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; deltax = fabs(oi->patrp); deltay = dkma_mul_double_ok(2.0, deltax, &me); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { ystart = dkma_mul_double_ok( deltay, floor(dkma_div_double_ok(ystart, deltay, &me)), &me ); xstart = dkma_mul_double_ok( deltay, floor(dkma_div_double_ok(xstart, deltay, &me)), &me ); } y = ystart; while(y <= yend) { y1 = dkma_add_double_ok(y, deltax, &me); start_addto(oi); x = xstart; write_noconv_double_point(oi,x,y, 1); while(x <= xend) { kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 6); x = dkma_add_double_ok(x, deltax, &me); write_noconv_double_point(oi,x,y1, 1); kw_to_stream(oi->s, 6); x = dkma_add_double_ok(x, deltax, &me); write_noconv_double_point(oi,x,y, 1); } end_addto(oi, dcc); y = dkma_add_double_ok(y, deltay, &me); } if(me) { oi->me = me; back = 0; } return back; } /** Fill pattern: Vertical tires. @param oi MetaPost output instruction structure. @param dcc Color cell structure. @return 1 on success, 0 on error. */ static int vert_tires DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_dcc *,dcc) { int back = 1; int me = 0; double xstart, ystart, xend, yend, deltax, deltay, x, y, x1; ystart = (oi->obb).ymin; yend = (oi->obb).ymax; xstart = (oi->obb).xmin; xend = (oi->obb).xmax; deltay = fabs(oi->patrp); deltax = dkma_mul_double_ok(2.0, deltay, &me); if(((oi->c)->opt1) & DKFIG_OPT_FILL_CONTIGOUS) { ystart = dkma_mul_double_ok( deltax, floor(dkma_div_double_ok(ystart, deltax, &me)), &me ); xstart = dkma_mul_double_ok( deltax, floor(dkma_div_double_ok(xstart, deltax, &me)), &me ); } x = xstart; while(x <= xend) { x1 = dkma_add_double_ok(x, deltay, &me); y = ystart; start_addto(oi); write_noconv_double_point(oi,x,y, 1); while(y <= yend) { y = dkma_add_double_ok(y, deltay, &me); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 6); write_noconv_double_point(oi,x1,y, 1); y = dkma_add_double_ok(y, deltay, &me); kw_to_stream(oi->s, 6); write_noconv_double_point(oi,x,y, 1); } end_addto(oi, dcc); x = dkma_add_double_ok(x, deltax, &me); } return back; } /** Write dash pattern for dashed lines. @param oi MetaPost output instruction structure. @return 1 on success, 0 on error. */ static int add_dash_pattern DK_P1(dkfig_mp_output_instruction *,oi) { int back = 1; double x; int i; if(((oi->o)->fpd).sv > DKFIG_EPSILON) { x = 0.9 * ((oi->o)->fpd).sv; } else { x = 0.9; } kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 90); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 91); kw_to_stream(oi->s, 2); switch(((oi->o)->fpd).ls) { case 1: case 3: case 4: case 5: { /* dashed or dash-x-dotted */ kw_to_stream(oi->s, 92); kw_to_stream(oi->s, 1); stream_puts_double(oi->s, (0.5*x), 1, oi->c); kw_to_stream(oi->s, 73); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 93); kw_to_stream(oi->s, 1); stream_puts_double(oi->s, x, 1, oi->c); kw_to_stream(oi->s, 73); kw_to_stream(oi->s, 1); if(((oi->o)->fpd).ls > 1) { i = ((oi->o)->fpd).ls - 2; while(i-- > 0) { kw_to_stream(oi->s, 92); kw_to_stream(oi->s, 1); if(((oi->c)->opt1) & DKFIG_OPT_DP_DOT_LW) { dkstream_puts_double(oi->s, (oi->m)->linewidth); } else { dkstream_puts_long(oi->s, 0L); } kw_to_stream(oi->s, 73); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 93); kw_to_stream(oi->s, 1); stream_puts_double(oi->s, x, 1, oi->c); kw_to_stream(oi->s, 73); kw_to_stream(oi->s, 0); } } kw_to_stream(oi->s, 92); kw_to_stream(oi->s, 1); stream_puts_double(oi->s, (0.5*x), 1, oi->c); kw_to_stream(oi->s, 73); } break; case 2: { /* dotted */ kw_to_stream(oi->s, 92); kw_to_stream(oi->s, 1); if(((oi->c)->opt1) & DKFIG_OPT_DP_DOT_LW) { dkstream_puts_double(oi->s, (oi->m)->linewidth); } else { dkstream_puts_long(oi->s, 0L); } kw_to_stream(oi->s, 73); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 93); kw_to_stream(oi->s, 1); stream_puts_double(oi->s, x, 1, oi->c); kw_to_stream(oi->s, 73); } break; } kw_to_stream(oi->s, 3); return back; } /** Print one non-text object. @param oi MetaPost output instruction structure. @return 1 on success, 0 on error. */ static int print_path_object DK_P1(dkfig_mp_output_instruction *,oi) { int back = 0; int have_color_c = 0; dk_fig_dcc dcc; int must_draw = 1; $? "+ print_path_object %ld", (oi->o)->layer oi->me = 0; /* path p */ kw_to_stream(oi->s, 25); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 27); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); /* p = */ kw_to_stream(oi->s, 27); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 12); kw_to_stream(oi->s, 1); /* create path variable contents */ switch((oi->o)->objtype) { case DK_FIG_OBJ_ELLIPSE: { back = path_ellipse(oi); } break; case DK_FIG_OBJ_POLYLINE: { back = path_polyline(oi); } break; case DK_FIG_OBJ_SPLINE: { back = path_spline(oi); } break; case DK_FIG_OBJ_ARC: { back = path_arc(oi); } break; } kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); if(((oi->o)->fpd).cl) { /* fill */ if(dkfig_tool_must_fill(((oi->o)->fpd).af, (oi->c)->opt1) || dkfig_tool_must_pattern(((oi->o)->fpd).af, (oi->c)->opt1)) { must_draw = 1; if((oi->o)->objtype == DK_FIG_OBJ_POLYLINE) { if((oi->o)->subtype == 5) { if(!(((oi->c)->opt1) & DKFIG_OPT_FILL_BITMAP_AREA)) { must_draw = 0; } } } if(must_draw) { if(((oi->o)->fpd).fc != (oi->d)->transparent) { dkfig_tool_fill_dcc(oi->d, &dcc, ((oi->o)->fpd).fc); dkfig_tool_correct_dcc(&dcc, ((oi->o)->fpd).fc, ((oi->o)->fpd).af); kw_to_stream(oi->s, 67); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 27); kw_to_stream(oi->s, 1); if(can_use_color(oi->c)) { kw_to_stream(oi->s, 43); kw_to_stream(oi->s, 1); write_dcc_data(oi->s, &dcc, oi->c); } else { kw_to_stream(oi->s, 106); kw_to_stream(oi->s, 1); write_dcc_gray(oi->s, &dcc, oi->c); } kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); } /* add pattern */ if(dkfig_tool_must_pattern(((oi->o)->fpd).af, (oi->c)->opt1)) { if(((oi->o)->fpd).pc != (oi->d)->transparent) { /* set_line_width(oi, ((((oi->o)->fpd).lt) ? ((oi->o)->fpd).lt : 1L)); */ cc_bb(oi->c, &(oi->obb), &((oi->o)->dbb)); oi->patrp = cc_noenl_linewidth( oi->c, (((oi->c)->patrp) ? ((oi->c)->patrp) : 4L) ); set_line_width(oi, 1L); kw_to_stream(oi->s, 97); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 96); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 96); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 12); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 72); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 49); kw_to_stream(oi->s, 1); if(((oi->c)->opt1) & DKFIG_OPT_ENLIGHTEN_LOOK) { stream_puts_double(oi->s, 0.45, 1, oi->c); } else { stream_puts_double(oi->s, 0.9, 1, oi->c); } kw_to_stream(oi->s, 73); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); set_line_cap(oi, 0); set_line_join(oi, 0); dkfig_tool_fill_dcc(oi->d, &dcc, ((oi->o)->fpd).pc); write_color_c(oi, &dcc); have_color_c = 1; kw_to_stream(oi->s, 26); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 28); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); kw_to_stream(oi->s, 28); kw_to_stream(oi->s, 75); kw_to_stream(oi->s, 84); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); switch(((oi->o)->fpd).af) { case 41: { if(!diagonal_left_30(oi, &dcc)) back = 0; } break; case 42: { if(!diagonal_right_30(oi, &dcc)) back = 0; } break; case 43: { if(!crosshatch_30(oi, &dcc)) back = 0; } break; case 44: { if(!diagonal_left_45(oi, &dcc)) back = 0;} break; case 45: { if(!diagonal_right_45(oi, &dcc)) back = 0; } break; case 46: { if(!crosshatch_45(oi, &dcc)) back = 0; } break; case 47: { if(!horizontal_bricks(oi, &dcc)) back = 0; } break; case 48: { if(!vertical_bricks(oi, &dcc)) back = 0; } break; case 49: { if(!horizontal_lines(oi, &dcc)) back = 0; } break; case 50: { if(!vertical_lines(oi, &dcc)) back = 0; } break; case 51: { if(!crosshatch(oi, &dcc)) back = 0; } break; case 52: { if(!horiz_shingles_right(oi, &dcc)) back = 0; } break; case 53: { if(!horiz_shingles_left(oi, &dcc)) back = 0; } break; case 54: { if(!vert_shingles_one(oi, &dcc)) back = 0; } break; case 55: { if(!vert_shingles_two(oi, &dcc)) back = 0; } break; case 56: { if(!large_fish_scales(oi, &dcc)) back = 0; } break; case 57: { if(!small_fish_scales(oi, &dcc)) back = 0; } break; case 58: { if(!circles(oi, &dcc)) back = 0; } break; case 59: { if(!hexagons(oi, &dcc)) back = 0; } break; case 60: { if(!octagons(oi, &dcc)) back = 0; } break; case 61: { if(!horiz_tires(oi, &dcc)) back = 0; } break; case 62: { if(!vert_tires(oi, &dcc)) back = 0; } break; } /* wieder einfuegen, nur zu Testzwecken draussen */ kw_to_stream(oi->s, 85); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 28); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 86); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 27); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); /* bis hierher zu Testzwecken geloescht */ kw_to_stream(oi->s, 87); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 88); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 89); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 28); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); } } } } } /* add stroke */ must_draw = 1; if((oi->o)->objtype == DK_FIG_OBJ_POLYLINE) { if((oi->o)->subtype == 5) { if(((oi->c)->opt1) & DKFIG_OPT_REMOVE_BITMAP_BORDER) { must_draw = 0; } } } if(((oi->c)->opt1) & DKFIG_OPT_REMOVE_THIN_BORDERS) { if(((oi->o)->fpd).lt == 0L) { if(((oi->o)->fpd).cl) { if(dkfig_tool_must_fill(((oi->o)->fpd).af, (oi->c)->opt1)) { must_draw = 0; } if(dkfig_tool_must_pattern(((oi->o)->fpd).af, (oi->c)->opt1)) { must_draw = 0; } if((oi->o)->objtype == DK_FIG_OBJ_POLYLINE) { if((oi->o)->subtype == 5) { must_draw = 0; } } } } } if(((oi->o)->fpd).pc == (oi->d)->transparent) { must_draw = 0; } if(must_draw) { dkfig_tool_fill_dcc(oi->d, &dcc, ((oi->o)->fpd).pc); if(!(((oi->o)->fpd).cl)) { if((((oi->o)->fpd).ar) & 3) { if(!have_color_c) { write_color_c(oi, &dcc); have_color_c = 1; } } } set_line_cap(oi, ((oi->o)->fpd).cs); set_line_join(oi, ((oi->o)->fpd).js); set_line_width(oi, ((oi->o)->fpd).lt); kw_to_stream(oi->s, 70); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 27); kw_to_stream(oi->s, 1); if(can_use_color(oi->c)) { kw_to_stream(oi->s, 43); kw_to_stream(oi->s, 1); if(have_color_c) { kw_to_stream(oi->s, 69); } else { write_dcc_data(oi->s, &dcc, oi->c); } } else { kw_to_stream(oi->s, 106); kw_to_stream(oi->s, 1); write_dcc_gray(oi->s, &dcc, oi->c); } if(((oi->o)->fpd).ls > 0) { add_dash_pattern(oi); } kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); /* add arrowheads */ if((((oi->o)->fpd).ar) & 1) { oi->a = &(((oi->o)->fpd).ahf); arrowhead_path(oi, 0); arrowhead_fd(oi, &dcc, have_color_c); } if((((oi->o)->fpd).ar) & 2) { oi->a = &(((oi->o)->fpd).ahb); arrowhead_path(oi, 1); arrowhead_fd(oi, &dcc, have_color_c); } } if(oi->me) { /* WARNING: math problem in object */ dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 13); back = 0; } $? "- print_path_object %d", back return back; } /** Draw one object. Use the functions above to do the real work. @param oi MetaPost output instruction structure. @return 1 on success, 0 on error. */ static int print_object DK_P1(dkfig_mp_output_instruction *,oi) { int back = 0; int must_draw = 1; int wbgr = 0; $? "+ print_object" if(((oi->c)->opt1) & DKFIG_OPT_VERBOSE_OUTPUT) { kw_to_stream(oi->s, 19); kw_to_stream(oi->s, 1); dkstream_puts_ul(oi->s, (oi->o)->lineno); kw_to_stream(oi->s, 0); } $? ". lineno=%lu type=%d", (oi->o)->lineno, (oi->o)->objtype switch((oi->o)->objtype) { case DK_FIG_OBJ_TEXT: { back = print_text_object(oi); } break; case DK_FIG_OBJ_ELLIPSE: case DK_FIG_OBJ_POLYLINE: case DK_FIG_OBJ_SPLINE: case DK_FIG_OBJ_ARC: { if(((oi->c)->opt1) & DKFIG_OPT_REMOVE_BG_RECTANGLE) { $? ". bg rectangle check" if(((oi->c)->opt2) & DKFIG_OPT_WHITE_BGRECT) { wbgr = 1; $? ". bg color is white" } if(dkfig_tool2_obj_is_bg_rect(oi->o, wbgr)) { must_draw = 0; $? ". this is a bg rectangle, do not draw" } } if(must_draw) { back = print_path_object(oi); } else { if(((oi->c)->opt1) & DKFIG_OPT_VERBOSE_OUTPUT) { kw_to_stream(oi->s, 104); kw_to_stream(oi->s, 0); } back = 1; } } break; default: { $? "! unknown object" } break; } $? "- print_object %d", back return back; } /** Write the MetaPost preamble (which includes the LaTeX preamble). @param oi MetaPost output instruction structure. @return 1 on success, 0 on error. */ static int do_preamble DK_P1(dkfig_mp_output_instruction *,oi) { int back = 1; int need_latex = 0; $? "+ do_preamble" need_latex = dkfig_dt_need_tex_file(oi->c); kw_to_stream(oi->s, 19); kw_to_stream(oi->s, 1); kw_to_stream(oi->s, 99); kw_to_stream(oi->s, 0); if(!(((oi->c)->opt2) & DKFIG_OPT_SKIP_ALL_TEXTS)) { kw_to_stream(oi->s, 13); kw_to_stream(oi->s, 14); kw_to_stream(oi->s, 12); kw_to_stream(oi->s, ((((oi->c)->opt1) & DKFIG_OPT_NO_EMBEDDED_FONTS) ? 10 : 11)); kw_to_stream(oi->s, 4); kw_to_stream(oi->s, 0); } kw_to_stream(oi->s, 100); kw_to_stream(oi->s, 0); if(need_latex && (!(((oi->c)->opt2) & DKFIG_OPT_SKIP_ALL_TEXTS))) { kw_to_stream(oi->s, 15); kw_to_stream(oi->s, 0); if(((oi->c)->opt1) & DKFIG_OPT_WR_TEX_COMMAND) { kw_to_stream(oi->s, ((((oi->c)->opt1) & DKFIG_OPT_OLD_TEX) ? 17 : 16)); kw_to_stream(oi->s, 0); } /* LaTeX preamble */ if(!dkfig_dt_tex_preamble(oi->c, oi->s)) { back = 0; } /* begin document */ dkfig_dt_begin_document(oi->c, oi->s); /* font setup */ if(!dkfig_dt_font_defs(oi->c, oi->s)) { back = 0; } kw_to_stream(oi->s, 18); kw_to_stream(oi->s, 0); } $? "- do_preamble" return back; } /** End mp output by writing the "end" line. @param os Output stream. */ static void end_file DK_P1(dk_stream_t *,os) { kw_to_stream(os, 24); kw_to_stream(os, 0); } /** End the current image. @param os Output stream. */ static void end_image DK_P1(dk_stream_t *,os) { kw_to_stream(os, 23); kw_to_stream(os, 0); } /** Set all settings empty at beginning of an image. @param mpo MetaPost output structure. */ static void do_not_have_anything DK_P1(dk_fig_output_mp *,mpo) { mpo->haveflags = 0 ; mpo->linewidth = 0L; mpo->linecap = 0 ; mpo->linejoin = 0 ; } /** Begin a new image. Write the beginfig line and increase the image number. @param c Conversion job structure. @param os Output stream. @param mpo MetaPost output structure. */ static void begin_image DK_P3(dk_fig_conversion *,c,dk_stream_t *,os,dk_fig_output_mp *,mpo) { kw_to_stream(os, 22); kw_to_stream(os, 2); dkstream_puts_ul(os, mpo->currentimage); kw_to_stream(os, 3); kw_to_stream(os, 0); mpo->currentimage += 1UL; do_not_have_anything(mpo); if((c->opt2) & DKFIG_OPT_FILL_BOUNDING_BOX) { if((c->opt1) & DKFIG_OPT_VERBOSE_OUTPUT) { kw_to_stream(os, 103); kw_to_stream(os, 0); } kw_to_stream(os, 67); kw_to_stream(os, 1); kw_to_stream(os, 2); kw_to_stream(os, 10); kw_to_stream(os, 5); kw_to_stream(os, 10); kw_to_stream(os, 3); kw_to_stream(os, 6); kw_to_stream(os, 2); dkstream_puts_double(os, mpo->bbx); kw_to_stream(os, 5); kw_to_stream(os, 10); kw_to_stream(os, 3); kw_to_stream(os, 6); kw_to_stream(os, 2); dkstream_puts_double(os, mpo->bbx); kw_to_stream(os, 5); dkstream_puts_double(os, mpo->bby); kw_to_stream(os, 3); kw_to_stream(os, 6); kw_to_stream(os, 2); kw_to_stream(os, 10); kw_to_stream(os, 5); dkstream_puts_double(os, mpo->bby); kw_to_stream(os, 3); kw_to_stream(os, 6); kw_to_stream(os, 59); kw_to_stream(os, 1); if(can_use_color(c)) { kw_to_stream(os, 43); kw_to_stream(os, 2); kw_to_stream(os, 11); kw_to_stream(os, 5); kw_to_stream(os, 11); kw_to_stream(os, 5); kw_to_stream(os, 11); kw_to_stream(os, 3); } else { kw_to_stream(os, 106); kw_to_stream(os, 1); kw_to_stream(os, 11); } kw_to_stream(os, 4); kw_to_stream(os, 0); } } /** For the mmp driver: End the current image and start a new one. @param c Conversion job structure. @param os Output stream. @param mpo MetaPost output structure. */ static void next_image DK_P3(dk_fig_conversion *,c,dk_stream_t *,os, dk_fig_output_mp *,mpo) { end_image(os); begin_image(c, os, mpo); } /** Handle special comments for an object. @param oi MetaPost output instruction structure. @param o Fig object structure. */ static void handle_special_comments DK_P2(dkfig_mp_output_instruction *,oi, dk_fig_object *,o) { int i; if((o->osc) && (o->osci)) { dk_fig_opt *speccom; $? ". processing special comments for object" dksto_it_reset(o->osci); while((speccom = (dk_fig_opt *)dksto_it_next(o->osci)) != NULL) { $? ". speccom = \"%s\"", speccom->name i = dkfig_opt_process_special_comment( oi->c, speccom->name, keywords[102], 0 ); dkfig_tool2_report_special_comment(oi->c, speccom, i); } } } /** Output pass. @param c Conversion job structure. @return 1 on success, 0 on error. */ static int output_pass DK_P1(dk_fig_conversion *,c) { int back = 0; int must_restart; dkfig_mp_output_instruction oi; dk_fig_object *o; int error_type; /* 0=internal, 1=handled */ unsigned long backupopt1; unsigned long backupopt2; int backupia; $? "+ output_pass" oi.c = c; error_type = 0; o = (dk_fig_object *)(c->drwng); if(c->app) { dkapp_set_source_lineno(c->app, 0UL); } if(o) { oi.d = (dk_fig_drawing *)(o->data); if(oi.d) { oi.m = (dk_fig_output_mp *)(c->outds); if(oi.m) { oi.o = NULL; oi.s = c->ostrm; if(oi.s) { dkstream_set_double_no_exponent(oi.s, 1); error_type = back = 1; if(!do_preamble(&oi)) { back = 0; /* message handled in do_pramble() */ } if(c->app) { dkapp_set_source_lineno(c->app, 0UL); } (oi.m)->currentdepth = 0L; (oi.m)->havecd = 0; begin_image(c, oi.s, oi.m); dksto_it_reset((oi.m)->it); while((o = (dk_fig_object *)dksto_it_next((oi.m)->it)) != NULL) { backupopt1 = c->opt1; backupopt2 = c->opt2; backupia = c->image_align; handle_special_comments(&oi,o); if(c->app) { dkapp_set_source_lineno(c->app, o->lineno); } oi.o = o; must_restart = 0; if((oi.m)->multi) { if((oi.m)->havecd) { if(o->layer < ((oi.m)->currentdepth - 1L)) { must_restart = 1; } } } if(must_restart) { /* DEBUG: Start of next output figure */ dkfig_tool2_msg1(oi.c, DK_LOG_LEVEL_DEBUG, 54); (oi.m)->currentdepth = o->layer; (oi.m)->havecd = 1; dksto_it_reset((oi.m)->it); next_image(c, oi.s, oi.m); } else { /* save current layer only if there is no layer saved yet or the current layer is smaller than the saved one */ if((oi.m)->havecd) { if(o->layer < (oi.m)->currentdepth) { (oi.m)->currentdepth = o->layer; } } else { (oi.m)->currentdepth = o->layer; } (oi.m)->havecd = 1; /* print the object */ if(!print_object(&oi)) { back = 0; /* message handled in print_object */ } } c->opt1 = backupopt1; c->opt2 = backupopt2; c->image_align = backupia; } end_image(oi.s); end_file(oi.s); } } } } if(!back) { switch(error_type) { case 0: { /* ERROR: internal setup error */ dkfig_tool2_msg1(oi.c, DK_LOG_LEVEL_ERROR, 44); } break; } } $? "- output_pass %d", back return back; } /** Initialize output data structure. @param o MetaPost output structure. */ static void null_outds DK_P1(dk_fig_output_mp *,o) { o->multi = 0; o->flatlist = NULL; o->it = NULL; o->currentimage = 0UL; o->sf = o->mx = 3.0 / 50.0; o->my = 0.0 - o->mx; o->nx = o->ny = 0.0; o->ahlength = 0.0; o->ahangle = 0.0; do_not_have_anything(o); } /** Cleaning up is necessary in all cases. @param c Conversion job structure. */ static void cleanup_pass DK_P1(dk_fig_conversion *,c) { dk_fig_output_mp *outds; $? "+ cleanup_pass" if(c->outds) { outds = (dk_fig_output_mp *)(c->outds); if(outds->it) { dksto_it_close(outds->it); } if(outds->flatlist) { dksto_close(outds->flatlist); } null_outds(outds); dk_delete(outds); c->outds = NULL; } $? "- cleanup_pass" } /** Set up co-ordinates transformation according to the bounding box. @param mpo MetaPost output structure. @param o Fig object. @return 1 on success, 0 on error. */ static int outds_coord_transform DK_P2(dk_fig_output_mp *,mpo, dk_fig_object *,o) { int back = 0, matherr = 0; dk_fig_drawing *d; double min, max, omin, omax; $? "+ outds_coord_transform" if(mpo && o) { d = (dk_fig_drawing *)(o->data); if(d) { if(d->fres > DKFIG_EPSILON) { if(dkfig_tool_invert_y(d)) { mpo->sf = dkma_div_double_ok(72.0, d->fres, &matherr); mpo->mx = mpo->sf; mpo->my = 0.0 - mpo->mx; mpo->nx = mpo->ny = 0.0; if( (d->dbb).flags & 0x01 ) { omin = dkma_mul_double_ok(mpo->mx, (d->dbb).xmin, &matherr); omax = dkma_mul_double_ok(mpo->mx, (d->dbb).xmax, &matherr); mpo->nx = 0.0 - omin; omax = dkma_sub_double_ok(omax, omin, &matherr); min = 0.0; max = ceil(omax); mpo->bbx = max; $? ". bbx = %lg", mpo->bbx mpo->nx = dkma_add_double_ok( mpo->nx, dkma_div_double_ok( dkma_sub_double_ok(max, omax, &matherr), 2.0, &matherr ), &matherr ); } if( (d->dbb).flags & 0x02 ) { omin = dkma_mul_double_ok(mpo->my, (d->dbb).ymax, &matherr); omax = dkma_mul_double_ok(mpo->my, (d->dbb).ymin, &matherr); mpo->ny = 0.0 - omin; omax = dkma_sub_double_ok(omax, omin, &matherr); min = 0.0; max = ceil(omax); mpo->bby = max; $? ". bby = %lg", mpo->bby mpo->ny = dkma_add_double_ok( mpo->ny, dkma_div_double_ok( dkma_sub_double_ok(max, omax, &matherr), 2.0, &matherr ), &matherr ); } if(!matherr) { back = 1; } } else { $? ". NO y MIRRORING" mpo->sf = dkma_div_double_ok(72.0, d->fres, &matherr); mpo->mx = mpo->sf; mpo->my = mpo->mx; mpo->nx = mpo->ny = 0.0; if( (d->dbb).flags & 0x01 ) { omin = dkma_mul_double_ok(mpo->mx, (d->dbb).xmin, &matherr); omax = dkma_mul_double_ok(mpo->mx, (d->dbb).xmax, &matherr); mpo->nx = 0.0 - omin; omax = dkma_sub_double_ok(omax, omin, &matherr); min = 0.0; max = ceil(omax); mpo->bbx = max; $? ". bbx = %lg", mpo->bbx mpo->nx = dkma_add_double_ok( mpo->nx, dkma_div_double_ok( dkma_sub_double_ok(max, omax, &matherr), 2.0, &matherr ), &matherr ); } if( (d->dbb).flags & 0x02 ) { omin = dkma_mul_double_ok(mpo->my, (d->dbb).ymin, &matherr); omax = dkma_mul_double_ok(mpo->my, (d->dbb).ymax, &matherr); mpo->ny = 0.0 - omin; omax = dkma_sub_double_ok(omax, omin, &matherr); min = 0.0; max = ceil(omax); mpo->bby = max; $? ". bby = %lg", mpo->bby mpo->ny = dkma_add_double_ok( mpo->ny, dkma_div_double_ok( dkma_sub_double_ok(max, omax, &matherr), 2.0, &matherr ), &matherr ); } if(!matherr) { back = 1; } } } } $? ". dbb xmin=%8.5lg xmax=%8.5lg ymin=%8.5lg ymax=%8.5lg", (d->dbb).xmin, (d->dbb).xmax, (d->dbb).ymin, (d->dbb).ymax $? ". sf xmin=%8.5lg xmax=%8.5lg ymin=%8.5lg ymax=%8.5lg", (mpo->mx * (d->dbb).xmin), (mpo->mx * (d->dbb).xmax), (mpo->my * (d->dbb).ymin), (mpo->my * (d->dbb).ymax) $? ". res mx=%8.5lg nx=%8.5lg my=%8.5lg ny=%8.5lg", mpo->mx, mpo->nx, mpo->my, mpo->ny } $? "- outds_coord_transform %d", back return back; } /** Prepare before writing. @param c Conversion job structure. @return 1 on success, 0 on error. */ static int preparation_pass DK_P1(dk_fig_conversion *,c) { int back = 0; dk_fig_output_mp *outds; $? "+ preparation_pass" if(c->app) { dkapp_set_source_lineno(c->app, 0UL); } outds = (dk_fig_output_mp *)dk_new(dk_fig_output_mp,1); if(outds) { c->outds = (void *)outds; null_outds(outds); outds_coord_transform(outds, c->drwng); outds->flatlist = dkfig_flat_list(c, c->drwng); if(outds->flatlist) { outds->it = dksto_it_open(outds->flatlist); if(outds->it) { back = 1; } else { if(c->app) { dkapp_err_memory(c->app, sizeof(dk_storage_iterator_t), 1); } } } } else { if(c->app) { dkapp_err_memory(c->app, sizeof(dk_fig_output_mp), 1); } } dkfig_tool2_report_unused_options(c); $? "- preparation_pass %d", back return back; } /** MMP (Multi-MetaPost) output driver function. @param c Conversion job structure. @return 1 on success, 0 on error. */ int dkfig_output_mmp DK_P1(dk_fig_conversion *,c) { int back = 0; $? "+ dkfig_output_mmp" if(c) { /* PROGRESS: Gathering font information */ dkfig_tool2_msg1(c, DK_LOG_LEVEL_PROGRESS, 55); if(preparation_pass(c)) { ((dk_fig_output_mp *)(c->outds))->multi = 1; /* enable mmp */ /* PROGRESS: Starting output */ dkfig_tool2_msg1(c, DK_LOG_LEVEL_PROGRESS, 56); back = output_pass(c); /* PROGRESS: Output finished */ dkfig_tool2_msg1(c, DK_LOG_LEVEL_PROGRESS, 57); } cleanup_pass(c); } $? "- dkfig_output_mmp %d", back return back; } /** MetaPost output driver function. @param c Conversion job structure. @return 1 on success, 0 on error. */ int dkfig_output_mp DK_P1(dk_fig_conversion *,c) { int back = 0; $? "+ dkfig_output_mp %s", TR_PTR(c) if(c) { /* PROGRESS: Gathering font information */ dkfig_tool2_msg1(c, DK_LOG_LEVEL_PROGRESS, 55); if(preparation_pass(c)) { ((dk_fig_output_mp *)(c->outds))->multi = 0; /* disable mmp */ /* PROGRESS: Starting output */ dkfig_tool2_msg1(c, DK_LOG_LEVEL_PROGRESS, 56); back = output_pass(c); /* PROGRESS: Output finished */ dkfig_tool2_msg1(c, DK_LOG_LEVEL_PROGRESS, 57); } cleanup_pass(c); } $? "- dkfig_output_mp %d", back return back; }