/* 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 dkfigrd.c Fig file reader. */ /** Inside the dkfigrd module. */ #define DKFIGRD_C 1 #include "dkfig.h" #include "dkxsp.h" $(trace-include) #ifdef TRACE_DEBUG #undef TRACE_DEBUG #endif $!trace-code #define TRACE_DEBUG 1 /** RGB color definition. */ typedef struct _rgb_ { int r; /**< Red. */ int g; /**< Green. */ int b; /**< Blue. */ } rgb; /** Color palette for colors 0...31 as calculated from the floating point numbers. */ static rgb low_rgb[] = { /* 0: back */ { 0,0,0 }, /* 1: blue */ { 0, 0, 255 }, /* 2: green */ { 0, 255, 0 }, /* 3: cyan */ { 0, 255, 255 }, /* 4: red */ { 255, 0, 0 }, /* 5: magenta */ { 255, 0, 255 }, /* 6: yellow */ { 255, 255, 0 }, /* 7: white */ { 255, 255, 255 }, /* 8: dark blue */ { 0, 0, 143 }, /* 9: blue */ { 0, 0, 176 }, /* 10: blue */ { 0, 0, 209 }, /* 11: blue */ { 135, 207, 255 }, /* 12: dark green */ { 0, 143, 0 }, /* 13: green */ { 0, 176, 0 }, /* 14: green */ { 0, 209, 0 }, /* 15: dark cyan */ { 0, 143, 143 }, /* 16: cyan */ { 0, 176, 176 }, /* 17: cyan */ { 0, 209, 209 }, /* 18: dark red */ { 143, 0, 0 }, /* 19: red */ { 176, 0, 0 }, /* 20: red */ { 209, 0, 0 }, /* 21: dark magenta */ { 143, 0, 143 }, /* 22: magenta */ { 176, 0, 176 }, /* 23: magenta */ { 209, 0, 209 }, /* 24: dark brown */ { 127, 48, 0 }, /* 25: brown */ { 160, 63, 0 }, /* 26: brown */ { 191, 97, 0 }, /* 27: dark pink */ { 255, 127, 127 }, /* 28: pink */ { 255, 160, 160 }, /* 29: pink */ { 255, 191, 191 }, /* 30: pink */ { 255, 224, 224 }, /* 31: gold */ { 255, 214, 0 } }; /** Color palette for colors 0...31. We use the Web216 colors nearest to the calculation from the floating point numbers. */ static rgb web_rgb[] = { /* 0: back */ { 0,0,0 }, /* 1: blue */ { 0, 0, 255 }, /* 2: green */ { 0, 255, 0 }, /* 3: cyan */ { 0, 255, 255 }, /* 4: red */ { 255, 0, 0 }, /* 5: magenta */ { 255, 0, 255 }, /* 6: yellow */ { 255, 255, 0 }, /* 7: white */ { 255, 255, 255 }, /* 8: dark blue */ { 0, 0, 102 }, /* 9: blue */ { 0, 0, 153 }, /* 10: blue */ { 0, 0, 204 }, /* 11: blue */ { 153, 204, 255 }, /* 12: dark green */ { 0, 102, 0 }, /* 13: green */ { 0, 153, 0 }, /* 14: green */ { 0, 204, 0 }, /* 15: dark cyan */ { 0, 102, 102 }, /* 16: cyan */ { 0, 153, 153 }, /* 17: cyan */ { 0, 204, 204 }, /* 18: dark red */ { 102, 0, 0 }, /* 19: red */ { 153, 0, 0 }, /* 20: red */ { 204, 0, 0 }, /* 21: dark magenta */ { 102, 0, 102 }, /* 22: magenta */ { 153, 0, 153 }, /* 23: magenta */ { 204, 0, 204 }, /* 24: dark brown */ { 102, 51, 0 }, /* 25: brown */ { 153, 51, 0 }, /* 26: brown */ { 204, 102, 0 }, /* 27: dark pink */ { 255, 51, 51 }, /* 28: pink */ { 255, 102, 102 }, /* 29: pink */ { 255, 153, 153 }, /* 30: pink */ { 255, 204, 204 }, /* 31: gold */ { 255, 204, 0 } }; /** State: empty. */ #define STATE_EMPTY 0 /** State: Expect orientation. */ #define STATE_EXPECT_ORIENTATION 1 /** State: Expect justification. */ #define STATE_EXPECT_JUSTIFICATION 2 /** State: Expect units. */ #define STATE_EXPECT_UNITS 3 /** State: Expect papersize. */ #define STATE_EXPECT_PAPERSIZE 4 /** State: Expect magnification. */ #define STATE_EXPECT_MAGNIFICATION 5 /** State: Expect multiple page information. */ #define STATE_EXPECT_MULTIPLE_PAGE 6 /** State: Expect transparent color information. */ #define STATE_EXPECT_TRANSPARENT_COLOR 7 /** State: Expect resolution. */ #define STATE_EXPECT_RESOLUTION 8 /** State: Expect start of Fig objects list. */ #define STATE_START 9 /** State: Expect arc arrowhead 1. */ #define STATE_EXPECT_ARC_ARROW_1 10 /** State: Expect arc arrowhead 2. */ #define STATE_EXPECT_ARC_ARROW_2 11 /** State: Expect polyline arrowhead 1. */ #define STATE_EXPECT_PL_ARROW_1 12 /** State: Expect polyline arrowhead 2. */ #define STATE_EXPECT_PL_ARROW_2 13 /** State: Expect polyline points. */ #define STATE_EXPECT_PL_POINTS 14 /** State: Expect image file name. */ #define STATE_EXPECT_PL_IMAGENAME 15 /** State: Expect spline arrowhead 1. */ #define STATE_EXPECT_SPLINE_ARROW_1 16 /** State: Expect spline arrowhead 2. */ #define STATE_EXPECT_SPLINE_ARROW_2 17 /** State: Expect spline points. */ #define STATE_EXPECT_SPLINE_POINTS 18 /** State: Expect spline factors (-1 -- 1). */ #define STATE_EXPECT_SPLINE_FACTORS 19 /** FIG is a part of the file format string. */ static char str_fig[] = { "FIG" }; /** File format version is a part of the file format string. */ static char str_32[] = { "3.2" }; /** Orientation. */ static char *orientation_strings[] = { "Landscape", "Portrait", NULL }; /** Justification. */ static char *justification_strings[] = { "Center", "FlushLeft", "Flush Left", NULL }; /** Units. */ static char *unit_strings[] = { "Metric", "Inches", NULL }; /** Paper sizes. */ static char *paper_strings[] = { "Letter", "Legal", "Ledger", "Tabloid", "A", "B", "C", "D", "E", "A4", "A3", "A2", "A1", "A0", "B5", NULL }; /** Multipage or Single page. */ static char *multi_strings[] = { "Single", "Multiple", NULL }; /** Names of output drivers. */ static char *driver_names[] = { "mp", "mmp", "eps", "svg", "tex", "bb", "pdf", "java", "none", NULL }; /** Compare two Fig objects. Comparison by layer number (largest layer number is lowest layer), object type, line style and source file line number. @param l Left object. @param r Right object. @param cr Comparison criteria */ int dkfig_object_compare DK_P3(void *,l, void *,r,int,cr) { int back = 0; dk_fig_object *lo, *ro; $? "+ dkfig_object_compare %s %s %d", TR_PTR(l), TR_PTR(r), cr if(l) { if(r) { lo = (dk_fig_object *)l; ro = (dk_fig_object *)r; if(lo->layer > ro->layer) back = -1; if(lo->layer < ro->layer) back = 1; if(!back) { if((lo->fpd).ot > (ro->fpd).ot) back = 1; if((lo->fpd).ot < (ro->fpd).ot) back = -1; } if(!back) { if(((lo->fpd).ot == DK_FIG_OBJ_TEXT) && ((ro->fpd).ot == DK_FIG_OBJ_TEXT)) { } } if(!back) { if(((lo->fpd).ls) < ((ro->fpd).ls)) back = -1; if(((lo->fpd).ls) > ((ro->fpd).ls)) back = 1; } if(!back) { if(lo->lineno < ro->lineno) back = -1; if(lo->lineno > ro->lineno) back = 1; } } else { back = 1; } } else { if(r) { back = -1; } } $? "- dkfig_object_compare %d", back return back; } /** Compare two color cells. @param l Left color cell. @param r Right color cell or color number. @param cr Comparison criteria (1=color/number, default=color/color). @return The comparison result. */ int color_cell_compare DK_P3(void *,l, void *,r,int,cr) { int back = 0, *xr; dk_fig_colorcell *ccl, *ccr; $? "+ color_cell_compare %s %s %d", TR_PTR(l), TR_PTR(r), cr if(l && r) { ccl = (dk_fig_colorcell *)l; ccr = (dk_fig_colorcell *)r; xr = (int *)r; switch(cr) { case 1: { if((ccl->number) < (*xr)) { back = -1; } if((ccl->number) > (*xr)) { back = 1; } } break; default: { if((ccl->number) < (ccr->number)) { back = -1; } if((ccl->number) > (ccr->number)) { back = 1; } } break; } } $? "- color_cell_compare %d", back return back; } /** Check the first line for \#FIG 3.2. @param d Drawing structure. @param b Buffer containing the first line. @return 1 on success (line valid), 0 on error. */ static int is_first_line_ok DK_P2(dk_fig_drawing *,d,char *,b) { int back = 0; char *p1; $? "+ is_first_line_ok %s %s", TR_PTR(d), TR_STR(b) p1 = b; p1++; p1 = dkstr_start(p1, NULL); if(p1) { if(strlen(p1) >= 3) { if(strncmp(p1, str_fig, 3) == 0) { p1 = &(p1[3]); p1 = dkstr_start(p1, NULL); if(p1) { if(strlen(p1) >= 3) { if(strncmp(p1, str_32, 3) == 0) { back = 1; d->state = STATE_EXPECT_ORIENTATION; } } } } } } if(!back) { d->errc = DKFIG_ERROR_SYNTAX; } $? "- is_first_line_ok %d", back return back; } /** Store a special comment either belong to the entire drawing or belonging to a drawing primitive. @param d Drawing structure. @param b Buffer containing a special comment. @param s Array of storage pointers. @param i Array of storage iterator pointers. @return 1 on success, 0 on error. */ static int add_spec_comm_to DK_P4(dk_fig_drawing *,d,char *,b, dk_storage_t **,s,dk_storage_iterator_t **,i) { int back = 0; dk_fig_opt *fo; $? "+ add_spec_comm_to" if((!(*s)) && (!(*i))) { *s = dksto_open(0); if(*s) { *i = dksto_it_open(*s); if(*i) { dksto_set_comp(*s, dkfig_opt_compare, 0); } else { dksto_close(*s); *s = NULL; } } } if((*s) && (*i)) { fo = dkfig_opt_new(d->lineno, b); if(fo) { if(dksto_add(*s, (void *)fo)) { back = 1; } else { dkfig_opt_delete(fo); fo = NULL; d->errc = DKFIG_ERROR_MEMORY; } } else { $? "! memory" d->errc = DKFIG_ERROR_MEMORY; } } $? "- add_spec_comm_to %d", back return back; } /** Handle a special comment. May be either document level special comment or related to the next object. @param d Drawing structure. @param b Buffer containing the special comment. @return 1 on success, 0 on error. */ static int add_special_comment DK_P2(dk_fig_drawing *,d,char *,b) { int back = 0; $? "+ add_special_comment %s %s", TR_PTR(d), TR_STR(b) if(d->state < STATE_START) { back = add_spec_comm_to(d,b,&(d->dlsc),&(d->dlsci)); } else { back = add_spec_comm_to(d,b,&(d->nosc),&(d->nosci)); } $? "- add_special_comment %d", back return back; } /** Get orientation string (2nd line of file). @param d Drawing structure. @param b Buffer containing an input line. @return 1 on success, 0 on error. */ static int get_orientation DK_P2(dk_fig_drawing *,d,char *,b) { int back = 1; d->orientation = dkstr_array_index(orientation_strings, b, 0); if(d->orientation < 0) { back = 0; d->errc = DKFIG_ERROR_SYNTAX; } else { d->state = STATE_EXPECT_JUSTIFICATION; } return back; } /** The 3rd line contains the justification. @param d Drawing structure. @param b Buffer containing one line. @return 1 on success, 0 on error. */ static int get_justification DK_P2(dk_fig_drawing *,d,char *,b) { int back = 1; $? "+ get_justification" d->justification = dkstr_array_index(justification_strings,b,0); if(d->justification < 0) { back = 0; d->errc = DKFIG_ERROR_SYNTAX; } else { d->state = STATE_EXPECT_UNITS; } $? "- get_justification %d",back return back; } /** The 4th line contains the units used in the drawing. @param d Drawing structure. @param b Buffer containing one input line. @return 1 on success, 0 on error. */ static int get_units DK_P2(dk_fig_drawing *,d,char *,b) { int back = 1; $? "+ get_units" d->units = dkstr_array_index(unit_strings,b,0); if(d->units < 0) { back = 0; d->errc = DKFIG_ERROR_SYNTAX; } else { d->state = STATE_EXPECT_PAPERSIZE; } $? "- get_units %d", back return back; } /** The 5th line contains the paper size. @param d Drawing structure. @param b Buffer containing one input line. @return 1 on success, 0 on error. */ static int get_papersize DK_P2(dk_fig_drawing *,d,char *,b) { int back = 1; $? "+ get_papersize" d->paper = dkstr_array_index(paper_strings,b,0); if(d->paper < 0) { if(!((d->opt1) & DKFIG_OPT_IGNORE_UNKNOWN_PAPER)) { back = 0; d->errc = DKFIG_ERROR_SYNTAX; } else { d->state = STATE_EXPECT_MAGNIFICATION; } } else { d->state = STATE_EXPECT_MAGNIFICATION; } $? "- get_papersize %d", back return back; } /** The 6th line contains a magnification factor. @param d Drawing structure. @param b Buffer containing one input line. @return 1 on success, 0 on error. */ static int get_magnification DK_P2(dk_fig_drawing *,d,char *,b) { int back = 1; double f; $? "+ get_magnification" if(sscanf(b, "%lf", &f) == 1) { d->magnification = f; d->state = STATE_EXPECT_MULTIPLE_PAGE; } else { back = 0; d->errc = DKFIG_ERROR_SYNTAX; } $? "- get_magnification %d", back return back; } /** The 7th line tells whether we have a single page or multipage drawing. How to handle multipage drawings? I don't know. @param d Drawing structure. @param b Buffer containing one input line. @return 1 on success, 0 on error. */ static int get_multipage DK_P2(dk_fig_drawing *,d,char *,b) { int back = 1; $? "+ get_multipage" d->multi = dkstr_array_index(multi_strings, b, 0); if(d->multi < 0) { d->errc = DKFIG_ERROR_SYNTAX; back = 0; } else { d->state = STATE_EXPECT_TRANSPARENT_COLOR; } $? "- get_multipage %d", back return back; } /** The 8th line contains the number of the transparent color. @param d Drawing structure. @param b Buffer containing one input line. @return 1 on success, 0 on error. */ static int get_transparent_color DK_P2(dk_fig_drawing *,d,char *,b) { int back = 1; int i; $? "+ get_transparent_color" if(sscanf(b, "%d", &i) == 1) { d->transparent = i; d->state = STATE_EXPECT_RESOLUTION; } else { back = 0; d->errc = DKFIG_ERROR_SYNTAX; } $? "- get_transparent_color %d", back return back; } /** The 9th line contains the resolution in dots per unit (see line 4) and the co-ordinate system setting. The FIG format specification tells what the cs setting means in one place, in another place there is an advise to ignore this setting. This should be corrected in the file format specification to make things clear. @param d Drawing structure. @param b Buffer containing one input line. @return 1 on success, 0 on error. */ static int get_resolution DK_P2(dk_fig_drawing *,d,char *,b) { int back = 0; long l; int i; char *nxptr; $? "+ get_resolution" nxptr = dkstr_next(b, NULL); if(nxptr) { if(sscanf(b, "%ld", &l) == 1) { if(sscanf(nxptr, "%d", &i) == 1) { back = 1; d->state = STATE_START; d->resolution = l; d->cstype = i; d->fres = dkma_l_to_double(l); } } } if(!back) { d->errc = DKFIG_ERROR_SYNTAX; } $? "- get_resolution %d", back return back; } /** Delete color cell, release memory. @param cc Color cell. */ void dkfig_delete_color_cell DK_P1(dk_fig_colorcell *,cc) { $? "+ dkfig_delete_color_cell %s", TR_PTR(cc) if(cc) { $? ". %d %d %d %d", cc->number, cc->r, cc->g, cc->b cc->number = cc->r = cc->g = cc->b = 0; cc->drve = NULL; dk_delete(cc); } $? "- dkfig_delete_color_cell" } /** Initialize data structure for arc. @param a Arc structure. */ static void null_arc DK_P1(dk_fig_arc *,a) { $? "+ null_arc" DK_MEMRES(a,sizeof(dk_fig_arc)) ; a->centerx = a->centery = 0.0; a->lba = a->rba = 0.0; dkfig_tool_null_arc_calc(&(a->calc)); $? "- null_arc" } /** Destroy data structure for arc. @param a Arc structure. */ static void delete_arc_details DK_P1(dk_fig_arc *,a) { $? "+ delete_arc_details" null_arc(a); dk_delete(a); $? "- delete_arc_details" } /** Initialize data structure for ellipse. @param e Ellipse structure. */ static void null_ellipse DK_P1(dk_fig_ellipse *,e) { $? "+ null_ellipse" DK_MEMRES(e,sizeof(dk_fig_ellipse)) ; e->angle = 0.0; $? "- null_ellipse" } /** Destroy data structure for ellipse. @param e Ellipse structure. */ static void delete_ellipse_details DK_P1(dk_fig_ellipse *,e) { $? "+ delete_ellipse_details" null_ellipse(e); dk_delete(e); $? "- delete_ellipse_details" } /** Initialize data structure for polyline. @param p Polyline structure. */ static void null_polyline DK_P1(dk_fig_polyline *,p) { $? "+ null_polyline" DK_MEMRES(p,sizeof(dk_fig_polyline)) ; p->xvalues = p->yvalues = NULL; p->imagename = NULL; $? "- null_polyline" } /** Destroy data structure for polyline. @param p Polyline structure. */ static void delete_polyline_details DK_P1(dk_fig_polyline *,p) { void *ptr; $? "+ delete_polyline_details" if(p->xvalues) { ptr = p->xvalues; dk_delete(ptr); } if(p->yvalues) { ptr = p->yvalues; dk_delete(ptr); } if(p->imagename) { ptr = p->imagename; dk_delete(ptr); } null_polyline(p); dk_delete(p); $? "- delete_polyline_details" } /** Initialize data structure for spline. @param s Spline structure. */ static void null_spline DK_P1(dk_fig_spline *,s) { $? "+ null_spline" DK_MEMRES(s,sizeof(dk_fig_spline)) ; s->xvalues = s->yvalues = NULL; s->svalues = NULL; s->bpoints = NULL; $? "- null_spline" } /** Destroy data structure for spline. @param s Spline structure. */ static void delete_spline_details DK_P1(dk_fig_spline *,s) { void *ptr; $? "+ delete_spline_details" if(s->xvalues) { ptr = s->xvalues; dk_delete(ptr); } if(s->yvalues) { ptr = s->yvalues; dk_delete(ptr); } if(s->svalues) { ptr = s->svalues; dk_delete(ptr); } null_spline(s); dk_delete(s); $? "- delete_spline_details" } /** Initialize data structure for text. @param t Text object structure. */ static void null_text DK_P1(dk_fig_text *,t) { $? "+ null_text" DK_MEMRES(t,sizeof(dk_fig_text)) ; t->font_size = t->angle = t->height = t->length = 0.0; t->text = NULL; t->font_handling = NULL; $? "- null_text" } /** Destroy data structure for text. @param t Text object structure. */ static void delete_text_details DK_P1(dk_fig_text *,t) { void *ptr; $? "+ delete_text_details" if(t->text) { ptr = t->text; dk_delete(ptr); } null_text(t); dk_delete(t); $? "- delete_text_details" } /** Create data structure for a text. @return Pointer to new text details structure on success, NULL on error. */ static dk_fig_text * new_text_details DK_P0() { dk_fig_text *back = NULL; $? "+ new_text_details" back = dk_new(dk_fig_text,1); if(back) { null_text(back); } $? "- new_text_details %s", TR_PTR(back) return back; } /** Initialize compound data structure. @param c Compound structure. */ static void null_compound DK_P1(dk_fig_compound *,c) { c->objects = NULL; c->objit = NULL; c->ulx = c->uly = c->lrx = c->lry = 0L; } static void dkfig_object_delete DK_PR((dk_fig_object *o)); /** Destroy drawing details data structure. @param d Drawing structure. @return 1 on success, 0 on error. */ static int delete_drawing_details DK_P1(dk_fig_drawing *,d) { int back = 0; dk_fig_object *o; dk_fig_colorcell *c; dk_fig_opt *fo; char *cptr; $? "+ delete_drawing_details" if(d) { /* contents */ if((d->objit) && (d->objects)) { $? ". > delete objects" dksto_it_reset(d->objit); while((o = (dk_fig_object *)dksto_it_next(d->objit)) != NULL) { dkfig_object_delete(o); } dksto_it_close(d->objit); $? ". < delete object" } if(d->objects) { dksto_close(d->objects); } d->objit = NULL; d->objects = NULL; if((d->ccells) && (d->ccit)) { $? "> delete color cells" dksto_it_reset(d->ccit); while((c = (dk_fig_colorcell *)dksto_it_next(d->ccit)) != NULL) { dkfig_delete_color_cell(c); } dksto_it_close(d->ccit); $? "< delete color cells" } if(d->ccells) { dksto_close(d->ccells); } d->ccit = NULL; d->ccells = NULL; if((d->dlsc) && (d->dlsci)) { $? "> delete document level special comments" dksto_it_reset(d->dlsci); while((fo = (dk_fig_opt *)dksto_it_next(d->dlsci)) != NULL) { dkfig_opt_delete(fo); } dksto_it_close(d->dlsci); $? "< delete docment level special comments" } if(d->dlsc) { dksto_close(d->dlsc); } d->dlsc = NULL; d->dlsci = NULL; if((d->nosc) && (d->nosci)) { $? "> delete next objects special comments" dksto_it_reset(d->nosci); while((fo = (dk_fig_opt *)dksto_it_next(d->nosci)) != NULL) { dkfig_opt_delete(fo); } dksto_it_close(d->nosci); $? "< delete next objects special comments" } if(d->nosc) { dksto_close(d->nosc); } d->nosc = NULL; d->nosci = NULL; if((d->fonth) && (d->fonthi)) { dk_fig_fonth_t *fhptr; $? "> delete font handling information" dksto_it_reset(d->fonthi); while((fhptr = (dk_fig_fonth_t *)dksto_it_next(d->fonthi)) != NULL) { dkfig_fnt_del_fonth(fhptr); } dksto_it_close(d->fonthi); $? "< delete font handling information" } if(d->fonth) { dksto_close(d->fonth); } d->fonth = NULL; d->fonthi = NULL; /* input file name */ if(d->inputfilename) { $? ". delete input file name" cptr = d->inputfilename; dk_delete(cptr); } d->inputfilename = NULL; d->lineno = 0UL; d->currentcomp = NULL; d->state = 0; d->errc = 0; d->orientation = 0; d->justification = 0; d->orientation = 0; d->justification = 0; d->units = 0; d->paper = 0; d->multi = 0; d->transparent = 0; d->resolution = 0L; d->fres = 0.0; d->cstype = 0; d->magnification = 0.0; /* finally release the drawing itself */ dk_delete(d); } $? "- delete_drawing_details" return back; } static void delete_compound_details DK_PR((dk_fig_compound *c)); /** Destroy an object and all it's contents @param o Fig object structure. */ static void dkfig_object_delete DK_P1(dk_fig_object *,o) { dk_fig_opt *fo; $? "+ object_delete %s", TR_PTR(o) if(o) { $? ". object ok" if(o->data) { $? ". object has details" switch(o->objtype) { case DK_FIG_OBJ_DRAWING: { $? ". destroy drawing" delete_drawing_details((dk_fig_drawing *)(o->data)); } break; case DK_FIG_OBJ_COLOR: { $? "! should never happen" } break; case DK_FIG_OBJ_ARC: { $? ". destroy arc" delete_arc_details((dk_fig_arc *)(o->data)); } break; case DK_FIG_OBJ_ELLIPSE: { $? ". destroy ellipse" delete_ellipse_details((dk_fig_ellipse *)(o->data)); } break; case DK_FIG_OBJ_POLYLINE: { $? ". destroy polyline" delete_polyline_details((dk_fig_polyline *)(o->data)); } break; case DK_FIG_OBJ_SPLINE: { $? ". destroy spline" delete_spline_details((dk_fig_spline *)(o->data)); } break; case DK_FIG_OBJ_TEXT: { $? ". destroy text" delete_text_details((dk_fig_text *)(o->data)); } break; case DK_FIG_OBJ_COMPOUND: { $? ". destroy compound" delete_compound_details((dk_fig_compound *)(o->data)); } break; default: { $? "! no such object type" } break; } } else { $? "! no details" } if((o->osc) && (o->osci)) { $? "> delete objects special comments" dksto_it_reset(o->osci); while ((fo = (dk_fig_opt *)dksto_it_next(o->osci)) != NULL) { dkfig_opt_delete(fo); } dksto_it_close(o->osci); $? "< delete objects special comments" } if(o->osc) { dksto_close(o->osc); } o->osc = NULL; o->osci = NULL; o->lineno = 0UL; o->layer = 0L; o->objtype = -1; o->data = NULL; o->drve = NULL; o->parent = NULL; dk_delete(o); } else { $? "! no object" } $? "- object_delete" } /** Delete compound data structure. @param c Compound structure. */ static void delete_compound_details DK_P1(dk_fig_compound *,c) { dk_fig_object *o; $? "+ delete_compound_details" if((c->objects) && (c->objit)) { $? "> compound contents" dksto_it_reset(c->objit); while((o = (dk_fig_object *)dksto_it_next(c->objit)) != NULL) { dkfig_object_delete(o); } dksto_it_close(c->objit); $? "< compound contents" } if(c->objects) { dksto_close(c->objects); } null_compound(c); dk_delete(c); $? "- delete_compound_details" } /** Create Fig object structure. @param l Line number in source file. @param p Parent object (drawing or compound). @param st Storage for special comments. @param it Iterator for special comments storage. @return Pointer to new object on success, NULL on error. */ dk_fig_object * dkfig_object_new DK_P4(unsigned long,l,dk_fig_object *,p, dk_storage_t *,st,dk_storage_iterator_t *,it) { dk_fig_object *back = NULL; int ok = 0; $? "+ dkfig_object_new" back = dk_new(dk_fig_object,1); if(back) { ok = 1; /* initialize all pointers to NULL */ back->lineno = l; back->layer = 0L; back->objtype = -1; back->data = NULL; back->drve = NULL; back->osc = st; back->osci = it; back->parent = p; dkfig_tool_bb_reset(&(back->dbb)); if(!ok) { dkfig_object_delete(back); back = NULL; } } $? "- dkfig_object_new %s", TR_PTR(back) return back; } /** Convert hexadecimal character to int. @param c Character to convert. @return Conversion result. */ static int hex_to_int DK_P1(char,c) { int back = 0; switch(c) { case '0': { back = 0; } break; case '1': { back = 1; } break; case '2': { back = 2; } break; case '3': { back = 3; } break; case '4': { back = 4; } break; case '5': { back = 5; } break; case '6': { back = 6; } break; case '7': { back = 7; } break; case '8': { back = 8; } break; case '9': { back = 9; } break; case 'a': case 'A': { back = 10; } break; case 'b': case 'B': { back = 11; } break; case 'c': case 'C': { back = 12; } break; case 'd': case 'D': { back = 13; } break; case 'e': case 'E': { back = 14; } break; case 'f': case 'F': { back = 15; } break; } return back; } /** Create new color cell structure. @param n Color number. @param r Red component. @param g Green component. @param b Blue component. @return Pointer to new structure on success, NULL on error. */ dk_fig_colorcell * dkfig_new_color_cell DK_P4(int,n,int,r,int,g,int,b) { dk_fig_colorcell *back = NULL; $? "+ dk_fig_colorcell %d %d %d %d",n,r,g,b back = dk_new(dk_fig_colorcell,1); if(back) { back->number = n; back->r = r; back->g = g; back->b = b; back->drve = NULL; } $? "- dk_fig_colorcell %s", TR_PTR(back) return back; } /** Create a new color cell from the text line, save the color cell in the drawing. @param d Drawing structure. @param t Text line containing the color cell information. @return 1 on success, 0 on error. */ static int add_color_cell DK_P2(dk_fig_drawing *,d,char *,t) { int back = 0; int reason = 0; char *cnptr, *hexptr; int cellno, r, g, b; dk_fig_colorcell *ccptr; $? "+ add_color_cell" cellno = r = g = b = 0; cnptr = t; hexptr = dkstr_next(cnptr, NULL); reason = DKFIG_ERROR_SYNTAX; if(hexptr) { if(sscanf(cnptr, "%d", &cellno) == 1) { if((d->ccells) && (d->ccit)) { if(!dksto_it_find_like(d->ccit, &cellno, 1)) { if(*hexptr == '#') { hexptr++; if(*hexptr) { r = hex_to_int(*(hexptr++)); if(*hexptr) { r = 16 * r + hex_to_int(*(hexptr++)); if(*hexptr) { g = hex_to_int(*(hexptr++)); if(*hexptr) { g = 16 * g + hex_to_int(*(hexptr++)); if(*hexptr) { b = hex_to_int(*(hexptr++)); if(*hexptr) { b = 16 * b + hex_to_int(*(hexptr++)); ccptr = dkfig_new_color_cell(cellno,r,g,b); if(ccptr) { if(dksto_add(d->ccells, (void *)ccptr)) { back = 1; $? ". ok" } else { dkfig_delete_color_cell(ccptr); ccptr = NULL; reason = DKFIG_ERROR_MEMORY; } } else { reason = DKFIG_ERROR_MEMORY; } } } } } } } } } } } } if(!back) { d->errc = reason; } $? "- add_color_cell %d", back return back; } /** Save object data in the current compound object. @param d Drawing structure. @param data Object-type specific data. @param l Line number of object in source file. @param fpd Fill, pattern and draw structure. @param c Conversion job. @return 1 on success, 0 on error. */ static int register_object_data DK_P5(dk_fig_drawing *,d, void *,data,long,l,dk_fig_fpd *,fpd, dk_fig_conversion *,c) { int back = 0; dk_storage_t *st; dk_fig_drawing *dptr; dk_fig_compound *cptr; dk_fig_object *o; $? "+ register_object_data" st = NULL; if(d->currentcomp) { switch((d->currentcomp)->objtype) { case DK_FIG_OBJ_COMPOUND: { cptr = (dk_fig_compound *)((d->currentcomp)->data); st = cptr->objects; } break; case DK_FIG_OBJ_DRAWING: { dptr = (dk_fig_drawing *)((d->currentcomp)->data); st = dptr->objects; } break; } } if(st) { d->currentobj = NULL; o = dkfig_object_new(d->lineno, d->currentcomp, d->nosc, d->nosci); if(o) { o->layer = l; o->objtype = fpd->ot; o->subtype = fpd->st; o->data = data; if(!(fpd->cl)) { if(fpd->af != -1) { fpd->af = -1; if(c) { if(c->app) { unsigned long bckln; bckln = dkapp_get_source_lineno(c->app); dkapp_set_source_lineno(c->app, o->lineno); dkfig_tool2_msg1(c, DK_LOG_LEVEL_WARNING, 141); dkapp_set_source_lineno(c->app, bckln); } else { dkfig_tool2_msg1(c, DK_LOG_LEVEL_WARNING, 141); } } } } DK_MEMCPY(&(o->fpd), fpd, sizeof(dk_fig_fpd)) ; d->nosc = NULL; d->nosci = NULL; if(dksto_add(st, (void *)o)) { back = 1; if(fpd->ot == DK_FIG_OBJ_COMPOUND) { d->currentcomp = o; } d->currentobj = o; } else { o->layer = 0L; o->data = NULL; dkfig_object_delete(o); o = NULL; } } } else { $? "! current compound is not a compound" } $? "- register_object_data %d", back return back; } /** Destroy drawing object including all contents. @param o Drawing root object. */ void dkfig_delete DK_P1(dk_fig_object *,o) { $? "+ dkfig_delete %s", TR_PTR(o) if(o) { dkfig_object_delete(o); } $? "- dkfig_delete" } /** Create and initialize details for new drawing. @param uwp Flag: Use web color palette (1) or normal color palette (0). @param cc Current component. @return Pointer to new drawing details structure on success, NULL on error. */ static dk_fig_drawing * new_drawing_details DK_P2(int,uwp,dk_fig_object *,cc) { dk_fig_drawing *back = NULL; int ok = 0; int i; rgb *rgbptr; dk_fig_colorcell *ccptr; $? "+ new_drawing_details" back = dk_new(dk_fig_drawing,1); if(back) { /* initialize all pointers to zero */ back->spline_segs = 1; back->inputfilename = NULL; back->objects = NULL; back->objit = NULL; back->lineno = 0UL; back->state = 0; back->currentcomp = cc; back->currentobj = NULL; back->errc = 0; back->ccells = NULL; back->ccit = NULL; back->dlsc = NULL; back->dlsci = NULL; back->fonth = NULL; back->fonthi = NULL; back->orientation = 0; back->justification = 0; back->units = 0; back->paper = 0; back->multi = 0; back->transparent = 0; back->resolution = 0L; back->fres = 0.0; back->cstype = 0; back->magnification = 100.0; back->numlatfonts = 0UL; back->numlatalpha = 0; back->opt1 = 0UL; back->opt2 = 0UL; back->ahlj = 0; back->minitsteps = 8UL; back->maxitsteps = 2048UL; dkfig_tool_bb_reset(&(back->dbb)); /* real initialization */ back->objects = dksto_open(0); if(back->objects) { dksto_set_comp(back->objects, dkfig_object_compare, 0); back->objit = dksto_it_open(back->objects); if(back->objit) { back->dlsc = dksto_open(0); if(back->dlsc) { dksto_set_comp(back->dlsc, dkfig_opt_compare, 0); back->dlsci = dksto_it_open(back->dlsc); if(back->dlsci) { back->ccells = dksto_open(0); if(back->ccells) { dksto_set_comp(back->ccells, color_cell_compare, 0); back->ccit = dksto_it_open(back->ccells); if(back->ccit) { back->fonth = dksto_open(0); if(back->fonth) { dksto_set_comp(back->fonth, dkfig_fnt_comp_fonth, 0); back->fonthi = dksto_it_open(back->fonth); if(back->fonthi) { $? ". storages ok" ok = 1; rgbptr = (uwp ? web_rgb : low_rgb); for(i = 0; i < 32; i++) { ccptr = dkfig_new_color_cell( i, rgbptr->r, rgbptr->g, rgbptr->b ); if(ccptr) { if(!dksto_add(back->ccells, (void *)ccptr)) { ok = 0; dkfig_delete_color_cell(ccptr); } } else { ok = 0; } rgbptr++; } $? ". ok=%d", ok } } } } } } } } if(!ok) { delete_drawing_details(back); back = NULL; } } $? "- new_drawing_details %s", TR_PTR(back) return back; } /** Create Fig object for entire drawing. @param uwp Flag: Use web-optimized color palette. @return Pointer to new object on success, NULL on error. */ dk_fig_object * dkfig_new DK_P1(int,uwp) { dk_fig_object *back = NULL; $? "+ dkfig_new" back = dkfig_object_new(0UL, NULL, NULL, NULL); if(back) { back->objtype = DK_FIG_OBJ_DRAWING; back->data = new_drawing_details(uwp, back); if(!(back->data)) { dkfig_delete(back); back = NULL; } } $? "- dkfig_new %s", TR_PTR(back) return back; } /** Create data structure for an ellipse. @return Pointer to ellipse object structure on success, NULL on error. */ static dk_fig_ellipse * new_ellipse_details DK_P0() { dk_fig_ellipse *back = NULL; $? "+ new_ellipse_details" back = dk_new(dk_fig_ellipse,1); if(back) { null_ellipse(back); } $? "- new_ellipse_details %s", TR_PTR(back) return back; } /** Process a line starting a new ellipse. @param d Drawing structure. @param text Buffer containing the line to process. @param c Conversion job. @return 1 on success, 0 on error. */ static int add_ellipse DK_P3(dk_fig_drawing *,d,char *,text, dk_fig_conversion *,c) { int back = 0; int reason = 0; long layer = 100L; int di; double an; long cx, cy, rx, ry, sx, sy, ex, ey; char *ptr[21]; size_t sz; dk_fig_ellipse *e; dk_fig_fpd fpd; $? "+ add_ellipse" reason = DKFIG_ERROR_SYNTAX; dkfig_tool_null_fpd(&fpd); fpd.ot = DK_FIG_OBJ_ELLIPSE; sz = dkstr_explode(ptr, 21, text, NULL); if(sz >= 19) { if(sscanf(ptr[0], "%d", &(fpd.st)) == 1) { /* sub type */ if(sscanf(ptr[1], "%d", &(fpd.ls)) == 1) { if(sscanf(ptr[2], "%ld", &(fpd.lt)) == 1) { if(sscanf(ptr[3], "%d", &(fpd.pc)) == 1) { if(sscanf(ptr[4], "%d", &(fpd.fc)) == 1) { if(sscanf(ptr[5], "%ld", &layer) == 1) { if(sscanf(ptr[6], "%d", &(fpd.ps)) == 1) { if(sscanf(ptr[7], "%d", &(fpd.af)) == 1) { if(sscanf(ptr[8], "%lf", &(fpd.sv)) == 1) { if(sscanf(ptr[9], "%d", &di) == 1) { if(sscanf(ptr[10], "%lf", &an) == 1) { if(sscanf(ptr[11], "%ld", &cx) == 1) { if(sscanf(ptr[12], "%ld", &cy) == 1) { if(sscanf(ptr[13], "%ld", &rx) == 1) { if(sscanf(ptr[14], "%ld", &ry) == 1) { if(sscanf(ptr[15], "%ld", &sx) == 1) { if(sscanf(ptr[16], "%ld", &sy) == 1) { if(sscanf(ptr[17], "%ld", &ex) == 1) { if(sscanf(ptr[18], "%ld", &ey) == 1) { reason = DKFIG_ERROR_MEMORY; e = new_ellipse_details(); if(e) { fpd.cl = 1; e->direction = di; e->angle = an; e->centerx = cx; e->centery = cy; e->radiusx = rx; e->radiusy = ry; e->startx = sx; e->starty = sy; e->endx = ex; e->endy = ey; back = register_object_data(d, (void *)e, layer, &fpd, c); if(!back) { delete_ellipse_details(e); e = NULL; } } } } } } } } } } } } } } } } } } } } } } if(!back) { d->errc = reason; } $? "- add_ellipse %d", back return back; } /** Create data structure for polyline. @param np Number of points. @return Pointer to new polyline structure on success, NULL on error. */ static dk_fig_polyline * new_polyline_details DK_P1(int,np) { dk_fig_polyline *back = NULL; size_t sz; $? "+ new_polyline_details" back = dk_new(dk_fig_polyline,1); if(back) { null_polyline(back); sz = (size_t)np; back->npoints = sz; back->xvalues = dk_new(long,sz); back->yvalues = dk_new(long,sz); if(!((back->xvalues) && (back->yvalues))) { delete_polyline_details(back); back = NULL; } } $? "- new_polyline_details %s", TR_PTR(back) return back; } /** Process a line starting a new polyline. @param d Drawing structure. @param b Buffer containing the first text line for polyline. @param c Conversion job. @return 1 on success, 0 on error. */ static int start_polyline DK_P3(dk_fig_drawing *,d,char *,b, dk_fig_conversion *,c) { int back = 0; int reason; char *ptr[17]; size_t sz; dk_fig_polyline *p; dk_fig_fpd fpd; long layer; long radius; int ar1, ar2, np; $? "+ start_polyline" reason = DKFIG_ERROR_SYNTAX; dkfig_tool_null_fpd(&fpd); fpd.ot = DK_FIG_OBJ_POLYLINE; sz = dkstr_explode(ptr, 16, b, NULL); if(sz >= 15) { if(sscanf(ptr[0], "%d", &(fpd.st)) == 1) { /* sub type */ if(sscanf(ptr[1], "%d", &(fpd.ls)) == 1) { /* line style */ if(sscanf(ptr[2], "%ld", &(fpd.lt)) == 1) { /* thickness */ if(sscanf(ptr[3], "%d", &(fpd.pc)) == 1) { /* pen color */ if(sscanf(ptr[4], "%d", &(fpd.fc)) == 1) { /* fill color */ if(sscanf(ptr[5], "%ld", &layer) == 1) { /* layer */ if(sscanf(ptr[6], "%d", &(fpd.ps)) == 1) { /* pen style */ if(sscanf(ptr[7], "%d", &(fpd.af)) == 1) { /* area fill */ if(sscanf(ptr[8], "%lf", &(fpd.sv)) == 1) { /* style_val */ if(sscanf(ptr[9], "%d", &(fpd.js)) == 1) { /* join style */ if(sscanf(ptr[10], "%d", &(fpd.cs)) == 1) { /* cap style */ if(sscanf(ptr[11], "%ld", &radius) == 1) { /* radius for rounded edges */ if(sscanf(ptr[12], "%d", &ar1) == 1) { /* forward arrow */ if(sscanf(ptr[13], "%d", &ar2) == 1) { /* backward arrow */ if(sscanf(ptr[14], "%d", &np) == 1) { /* number of points */ switch(fpd.st) { case 2: case 3: case 4: case 5: fpd.cl = 1; break; } reason = DKFIG_ERROR_MEMORY; p = new_polyline_details(np); if(p) { p->radius = radius; fpd.ar = 0; if(ar1) { fpd.ar |= 1; $? ". arrow forward" } if(ar2) { fpd.ar |= 2; $? ". arrow backward" } p->npoints = np; back = register_object_data(d, (void *)p, layer, &fpd, c); if(back) { d->currentdet = p; d->currentpnt = 0; d->xory = 0; d->state = STATE_EXPECT_PL_POINTS; if(fpd.st == 5) { d->state = STATE_EXPECT_PL_IMAGENAME; } if(ar2) { $? ". expect backward arrow" d->state = STATE_EXPECT_PL_ARROW_2; } if(ar1) { $? ". expect forward arrow" d->state = STATE_EXPECT_PL_ARROW_1; } } else { delete_polyline_details(p); p = NULL; } } } } } } } } } } } } } } } } } } if(!back) { d->errc = reason; } $? "- start_polyline %d", back return back; } /** Create data structure for a spline. @param np Number of points, @param subsegs Number of Bezier segments per X-spline segment. @param cl Flag: Closed spline (1) or open spline (0). @param c Conversion job structure. @return Pointer to new spline details structure on success, NULL on error. */ static dk_fig_spline * new_spline_details DK_P4(int,np, size_t,subsegs, int,cl, dk_fig_conversion *,c) { dk_fig_spline *back = NULL; size_t sz = 0; int ok = 0, matherr = 0; unsigned long s, p, bp; $? "+ new_spline_details np=%d segs=%lu cl=%d", np, (unsigned long)subsegs, cl ok = 0; back = dk_new(dk_fig_spline,1); if(back) { $? ". memory allocated successfully" sz = (size_t)np; null_spline(back); $? ". trying to obtain memory %lu", (unsigned long)sz back->xvalues = dk_new(long,sz); $? ". xvalues" back->yvalues = dk_new(long,sz); $? ". yvalues" back->svalues = dk_new(double,sz); $? ". svalues" back->npoints = np; $? ". npoints" back->segs = subsegs; if(back->segs < 1) { back->segs = 1; } s = back->segs; p = back->npoints; matherr = 0; bp = dkma_mul_ulong_ok(s, p, &matherr); if(!cl) { bp = dkma_sub_ulong_ok( dkma_add_ulong_ok(bp, 1UL, &matherr), s, &matherr ); } $? ". number of bezier points = %lu", bp if(!matherr) { back->nbpoints = (size_t)bp; back->normals = 0; back->normale = (size_t)(bp - 1); if((unsigned long)(back->nbpoints) == bp) { back->bpoints = dk_new(dk_fig_bezier_point,(back->nbpoints)); } else { /* ERROR: Number of points too large */ if(c) { if(c->app) { dkapp_err_memory(c->app, sizeof(dk_fig_bezier_point), back->nbpoints); } } } } else { /* ERROR: Number of points too large */ if(c) { dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 43); } } if((back->xvalues) && (back->yvalues) && (back->svalues) && (back->nbpoints)) { ok = 1; } if(!ok) { delete_spline_details(back); back = NULL; } } $? "- new_spline_details %s", TR_PTR(back) return back; } /** Process a line starting a new spline object. @param d Drawing structure. @param b Buffer containing the line. @param c Conversion job structure. @return 1 on success, 0 on error. */ static int start_spline DK_P3(dk_fig_drawing *,d,char *,b, dk_fig_conversion *,c) { int back = 0; dk_fig_spline *s; dk_fig_fpd fpd; char *ptr[15]; size_t sz; int reason; long layer; int ar1, ar2, np; $? "+ start_spline" reason = DKFIG_ERROR_SYNTAX; dkfig_tool_null_fpd(&fpd); fpd.ot = DK_FIG_OBJ_SPLINE; sz = dkstr_explode(ptr, 14, b, NULL); if(sz >= 13) { if(sscanf(ptr[0], "%d", &(fpd.st)) == 1) { /* sub type */ if(sscanf(ptr[1], "%d", &(fpd.ls)) == 1) { /* line style */ if(sscanf(ptr[2], "%ld", &(fpd.lt)) == 1) { /* thickness */ if(sscanf(ptr[3], "%d", &(fpd.pc)) == 1) { /* pen color */ if(sscanf(ptr[4], "%d", &(fpd.fc)) == 1) { /* fill color */ if(sscanf(ptr[5], "%ld", &layer) == 1) { /* layer */ if(sscanf(ptr[6], "%d", &(fpd.ps)) == 1) { /* pen style */ if(sscanf(ptr[7], "%d", &(fpd.af)) == 1) { /* area fill */ if(sscanf(ptr[8], "%lf", &(fpd.sv)) == 1) { /* style_val */ if(sscanf(ptr[9], "%d", &(fpd.cs)) == 1) { /* cap style */ if(sscanf(ptr[10], "%d", &ar1) == 1) { /* forward arrow */ if(sscanf(ptr[11], "%d", &ar2) == 1) { /* backward arrow */ if(sscanf(ptr[12], "%d", &np) == 1) { /* npoints */ switch(fpd.st) { case 1: case 3: case 5: fpd.cl = 1; break; } reason = DKFIG_ERROR_MEMORY; s = new_spline_details(np,d->spline_segs,fpd.cl,c); if(s) { if(ar1) { fpd.ar |= 1; } if(ar2) { fpd.ar |= 2; } s->segs = d->spline_segs; /* s->flags = 0; */ back = register_object_data(d, (void *)s, layer, &fpd, c); if(back) { d->currentdet = s; d->currentpnt = 0; d->xory = 0; d->state = STATE_EXPECT_SPLINE_POINTS; if(ar2) { d->state = STATE_EXPECT_SPLINE_ARROW_2; } if(ar1) { d->state = STATE_EXPECT_SPLINE_ARROW_1; } } else { delete_spline_details(s); s = NULL; } } } } } } } } } } } } } } } } if(!back) { d->errc = reason; } $? "- start_spline %d", back return back; } /** Copy string contents "forward" (to the left) after processing an octal code. @param d Destination pointer. @param s Source pointer. */ static void copy_forward DK_P2(char *,d,char *,s) { char *dptr, *sptr; $? "+ copy_forward" dptr = d; sptr = s; while(*sptr) { *(dptr++) = *(sptr++); } /* 2004-06-15 bug fixed: forgot to finalize string */ *dptr = '\0'; /* 2004-06-15 end of bug fix */ $? "- copy_forward" } /** Correct octal codes in text. @param str String to correct. */ static void correct_octal_codes DK_P1(char *,str) { char *p; int i; $? "+ correct_octal_codes %s", TR_STR(str) p = str; while(*p) { $? ". p = %s", TR_STR(p) if(*p == '\\') { if((p[1] >= '0') && (p[1] <= '9')) { if((p[2] >= '0') && (p[1] <= '9')) { if((p[3] >= '0') && (p[1] <= '9')) { i = 64 * hex_to_int(p[1]) + 8 * hex_to_int(p[2]) + hex_to_int(p[3]); *p = (char) i; if(*p == 0x01) { *p = '\0'; } else { copy_forward(&(p[1]), &(p[4])); p++; } } else { i = 8 * hex_to_int(p[1]) + hex_to_int(p[2]); *p = (char)i; if(*p == 0x01) { *p = '\0'; } else { copy_forward(&(p[1]), &(p[3])); p++; } } } else { i = hex_to_int(p[1]); *p = (char)i; if(*p == 0x01) { *p = '\0'; } else { copy_forward(&(p[1]), &(p[2])); p++; } } } else { switch(p[1]) { case '\0' : { /* 2004-06-15 bug fixed: standalone backslash was unhandled */ *p = '\0'; /* 2004-06-15 end of bug fix */ } break; case '\\' : { *p = '\\'; copy_forward(&(p[1]), &(p[2])); p++; } break; case 'r': { *p = '\r'; copy_forward(&(p[1]), &(p[2])); p++; } break; case 'n': { *p = '\n'; copy_forward(&(p[1]), &(p[2])); p++; } break; case 't': { *p = '\t'; copy_forward(&(p[1]), &(p[2])); p++; } break; case 'a': { *p = '\a'; copy_forward(&(p[1]), &(p[2])); p++; } break; case 'b': { *p = '\b'; copy_forward(&(p[1]), &(p[2])); p++; } break; } } } else { p++; } } $? "- correct_octal_codes %s", TR_STR(str) } /** Create a number of small strings from one text line. @param array Array of pointers to receive the small strings. @param sz Size of array (Number of elements). @param l Line to process. @return Number of elements used in \arg array. */ static size_t my_explode DK_P3(char **,array, size_t,sz, char *,l) { size_t back = 0; char **ptr; size_t i; char *nxptr, *oldptr; $? "+ my_explode %lu", (unsigned long)sz ptr = array; i = sz; while(i--) { *(ptr++) = NULL; } ptr = array; i = sz; nxptr = dkstr_start(l, NULL); oldptr = NULL; if(nxptr) { *(ptr++) = nxptr; i--; oldptr = nxptr; back++; } while(i-- > 0) { nxptr = NULL; if(oldptr) { nxptr = dkstr_next(oldptr, NULL); if(nxptr) { *(ptr++) = nxptr; back++; } } oldptr = nxptr; } $? "- my_explode %lu", (unsigned long)back return back; } /** Process a line starting a text object. @param d Drawing structure. @param line Input line. @param c Conversion job. @return 1 on success, 0 on error. */ static int start_text DK_P3(dk_fig_drawing *,d,char *,line, dk_fig_conversion *,c) { int back = 0, ff = 0; int reason = DKFIG_ERROR_SYNTAX; char *str = NULL; long layer; char *ptr[16]; size_t sz; dk_fig_text *td; dk_fig_fpd fpd; int fo; double fs = 0.0, an = 0.0, h = 0.0, l = 0.0; long x = 0L, y = 0L; $? "+ start_text line=\"%s\"", TR_STR(line) dkfig_tool_null_fpd(&fpd); fpd.ot = DK_FIG_OBJ_TEXT; /* sz = dkstr_explode(ptr, 14, line, NULL); */ sz = my_explode(ptr, 13, line); $? ". %lu components found", (unsigned long)sz if(sz == 13) { if(sscanf(ptr[0], "%d", &(fpd.st)) == 1) { /* sub type */ if(sscanf(ptr[1], "%d", &(fpd.pc)) == 1) { /* color */ if(sscanf(ptr[2], "%ld", &layer) == 1) { /* layer */ if(sscanf(ptr[3], "%d", &(fpd.ps)) == 1) { /* pen style */ if(sscanf(ptr[4], "%d", &fo) == 1) { /* font */ if(sscanf(ptr[5], "%lf", &fs) == 1) { /* font size */ if(sscanf(ptr[6], "%lf", &an) == 1) { /* angle */ if(sscanf(ptr[7], "%d", &ff) == 1) { /* font flags */ if(sscanf(ptr[8], "%lf", &h) == 1) { /* height */ if(sscanf(ptr[9], "%lf", &l) == 1) { /* length */ if(sscanf(ptr[10], "%ld", &x) == 1) { /* x */ if(sscanf(ptr[11], "%ld", &y) == 1) { /* y */ $? ". scanned 13 components, string=\"%s\"", ptr[12] $? ". x=%ld y=%ld an=%lg", x, y, an reason = DKFIG_ERROR_MEMORY; str = dkstr_dup(ptr[12]); if(str) { $? ". string ok \"%s\"", str td = new_text_details(); if(td) { $? ". td ok" td->font = fo; td->font_size = fs; td->angle = an; td->font_flags = ff; td->height = h; td->length = l; td->x = x; td->y = y; td->text = str; $? "x=%ld/%ld y=%ld/%ld an=%lg/%lg", td->x,x, td->y,y, td->angle,an back = register_object_data( d, (void *)td, layer, &fpd, c ); if(back) { $? ". object registered" correct_octal_codes(str); } else { $? ". failed to register" delete_text_details(td); td = NULL; } } else { dk_delete(str); } } } } } } } } } } } } } } } if(!back) { d->errc = reason; } $? "- start_text %d \"%s\"", back, TR_STR(str) return back; } /** Create data structure for arc. @return Pointer to new arc structure on success, NULL on error. */ static dk_fig_arc * new_arc_details DK_P0() { dk_fig_arc *back = NULL; $? "+ new_arc_details" back = dk_new(dk_fig_arc,1); if(back) { null_arc(back); } $? "- new_arc_details" return back; } /** Process a line starting a new arc. @param d Drawing structure. @param line Input line. @param c Conversion job. @return 1 on success, 0 on error. */ static int start_arc DK_P3(dk_fig_drawing *,d,char *,line, dk_fig_conversion *,c) { int back = 0; int reason; long layer; int di, ar1, ar2; double cx, cy; long x1, y1, x2, y2, x3, y3; char *ptr[32]; size_t sz; dk_fig_arc *a; dk_fig_fpd fpd; $? "+ start_arc" dkfig_tool_null_fpd(&fpd); fpd.ot = DK_FIG_OBJ_ARC; reason = DKFIG_ERROR_SYNTAX; sz = dkstr_explode(ptr, 32, line, NULL); if(sz >= 21) { if(sscanf(ptr[0], "%d", &(fpd.st)) == 1) { /* sub type */ if(sscanf(ptr[1], "%d", &(fpd.ls)) == 1) { /* line style */ if(sscanf(ptr[2], "%ld", &(fpd.lt)) == 1) { /* line thickness */ if(sscanf(ptr[3], "%d", &(fpd.pc)) == 1) { /* pen color */ if(sscanf(ptr[4], "%d", &(fpd.fc)) == 1) { /* fill color */ if(sscanf(ptr[5], "%ld", &layer) == 1) { /* depth */ if(sscanf(ptr[6], "%d", &(fpd.ps)) == 1) { /* pen style */ if(sscanf(ptr[7], "%d", &(fpd.af)) == 1) { /* area fill */ if(sscanf(ptr[8], "%lf", &(fpd.sv)) == 1) { /* style val */ if(sscanf(ptr[9], "%d", &(fpd.cs)) == 1) { /* cap style */ if(sscanf(ptr[10], "%d", &di) == 1) { /* direction */ if(sscanf(ptr[11], "%d", &ar1) == 1) { /* arrow forward */ if(sscanf(ptr[12], "%d", &ar2) == 1) { /* arrow backward */ if(sscanf(ptr[13], "%lf", &cx) == 1) { /* center x */ if(sscanf(ptr[14], "%lf", &cy) == 1) { /* center y */ if(sscanf(ptr[15], "%ld", &x1) == 1) { /* x 1 */ if(sscanf(ptr[16], "%ld", &y1) == 1) { /* y 1 */ if(sscanf(ptr[17], "%ld", &x2) == 1) { /* x 2 */ if(sscanf(ptr[18], "%ld", &y2) == 1) { /* y 2 */ if(sscanf(ptr[19], "%ld", &x3) == 1) { /* x 3 */ if(sscanf(ptr[20], "%ld", &y3) == 1) { /* y 3 */ reason = DKFIG_ERROR_MEMORY; a = new_arc_details(); if(a) { a->direction = di; fpd.ar = 0; if(ar1) { fpd.ar |= 1; } if(ar2) { fpd.ar |= 2; } a->centerx = cx; a->centery = cy; a->x1 = x1; a->y1 = y1; a->x2 = x2; a->y2 = y2; a->x3 = x3; a->y3 = y3; switch(fpd.st) { case 2: { fpd.cl = 1; } break; } back = register_object_data( d, (void *)a, layer, &fpd, c ); if(back) { d->currentdet = (void *)a; if(ar2) { d->state = STATE_EXPECT_ARC_ARROW_2; } if(ar1) { d->state = STATE_EXPECT_ARC_ARROW_1; } } else { delete_arc_details(a); a = NULL; } } } } } } } } } } } } } } } } } } } } } } } } if(!back) { d->errc = reason; } $? "- start_arc %d", back return back; } /** This compound is finished, go back to parent compound. @param d Drawing structure. @return 1 on success, 0 on error. */ static int finish_compound DK_P1(dk_fig_drawing *,d) { int back = 0; $? "+ finish_compound" if(d->currentcomp) { d->currentcomp = (d->currentcomp)->parent; if(d->currentcomp) { back = 1; } else { $? "! no parent compound" } } $? "- finish_compound %d", back return back; } /** Create data structure for a new compound object. @param ulx Upper left x value. @param uly Upper left y value. @param lrx Lower right x value. @param lry Lower right y value. @return Pointer to new compound structure on success, NULL on error. */ static dk_fig_compound * new_compound_details DK_P4(long,ulx,long,uly,long,lrx,long,lry) { int ok; dk_fig_compound *back = NULL; $? "+ dk_fig_compound" ok = 0; back = dk_new(dk_fig_compound,1); if(back) { null_compound(back); back->objects = dksto_open(0); if(back->objects) { dksto_set_comp(back->objects, dkfig_object_compare, 0); back->objit = dksto_it_open(back->objects); if(back->objit) { ok = 1; back->ulx = ulx; back->uly = uly; back->lrx = lrx; back->lry = lry; } } if(!ok) { delete_compound_details(back); back = NULL; } } $? "- dk_fig_compound %s", TR_PTR(back) return back; } /** Process a line starting a new compound @param d Drawing structure. @param line Input line. @param c Conversion job. @return 1 on success, 0 on error. */ static int start_compound DK_P3(dk_fig_drawing *,d,char *,line, dk_fig_conversion *,c) { int back = 0, reason; char *p1, *p2, *p3, *p4; long ulx, uly, lrx, lry; dk_fig_compound *cptr; dk_fig_fpd fpd; $? "+ start_compound %s", TR_STR(line) reason = DKFIG_ERROR_SYNTAX; dkfig_tool_null_fpd(&fpd); fpd.ot = DK_FIG_OBJ_COMPOUND; p1 = dkstr_start(line, NULL); if(p1) { p2 = dkstr_next(p1, NULL); if(p2) { p3 = dkstr_next(p2, NULL); if(p3) { p4 = dkstr_next(p3, NULL); if(p4) { if(sscanf(p1, "%ld", &ulx) == 1) { if(sscanf(p2, "%ld", &uly) == 1) { if(sscanf(p3, "%ld", &lrx) == 1) { if(sscanf(p4, "%ld", &lry) == 1) { reason = DKFIG_ERROR_MEMORY; cptr = new_compound_details(ulx,uly,lrx,lry); if(cptr) { back = register_object_data( d, (void *)cptr, 0UL, &fpd, c ); if(!back) { delete_compound_details(cptr); cptr = NULL; } } } } } } } } } } if(!back) { d->errc = reason; } $? "- start_compound %d", back return back; } /** Beginning of a new object. @param d Drawing structure. @param b Input line buffer. @param c Conversion job structure. @return 1 on success, 0 on error. */ static int begin_object DK_P3(dk_fig_drawing *,d,char *,b, dk_fig_conversion *,c) { int back = 0; char *nxptr; int objtype; $? "+ begin_object %lu %s", d->lineno, TR_STR(b) nxptr = dkstr_next(b, NULL); if(sscanf(b, "%d", &objtype) == 1) { switch(objtype) { case 0: { /* color cell */ back = add_color_cell(d,nxptr); } break; case 1: { /* ellipse */ back = add_ellipse(d,nxptr, c); } break; case 2: { /* polyline */ back = start_polyline(d, nxptr, c); } break; case 3: { /* spline */ back = start_spline(d, nxptr, c); } break; case 4: { /* text */ back = start_text(d, nxptr, c); } break; case 5: { /* arc */ back = start_arc(d, nxptr, c); } break; case 6: { /* compound */ back = start_compound(d, nxptr, c); } break; case -6: { /* end of compound */ back = finish_compound(d); } break; } } else { d->errc = DKFIG_ERROR_SYNTAX; } $? "- begin_object %d", back return back; } /** Fill data structure for arrowhead. @param a Arrowhead structure. @param text Text line containing arrowhead information. @return 1 on success, 0 on error. */ static int add_arrow_info DK_P2(dk_fig_arrow *,a,char *,text) { int back = 0; char *ptr[10]; size_t sz; int i; double d; $? "+ add_arrow_info" sz = dkstr_explode(ptr, 9, text, NULL); if(sz >= 5) { if(sscanf(ptr[0], "%d", &i) == 1) { a->type = i; if(sscanf(ptr[1], "%d", &i) == 1) { a->style = i; if(sscanf(ptr[2], "%lf", &d) == 1) { a->thickness = d; if(sscanf(ptr[3], "%lf", &d) == 1) { a->w = d; if(sscanf(ptr[4], "%lf", &d) == 1) { a->h = d; back = 1; } } } } } } $? "- add_arrow_info %d", back return back; } /** Add forward arrow information to arc. @param d Drawing structure. @param b Text line buffer. @return 1 on success, 0 on error. */ static int add_arc_arrow_1 DK_P2(dk_fig_drawing *,d,char *,b) { int back = 0; $? "+ add_arc_arrow_1" if(d->currentobj) { back = add_arrow_info(&(((d->currentobj)->fpd).ahf), b); } if((((d->currentobj)->fpd).ar) & 2) { d->state = STATE_EXPECT_ARC_ARROW_2; } else { d->state = STATE_START; d->currentdet = NULL; d->currentobj = NULL; } if(!back) { d->errc = DKFIG_ERROR_SYNTAX; } $? "- add_arc_arrow_1 %d", back return back; } /** Add backward arrow information to arc. @param d Drawing structure. @param b Text line buffer, @return 1 on success, 0 on error. */ static int add_arc_arrow_2 DK_P2(dk_fig_drawing *,d,char *,b) { int back = 0; $? "+ add_arc_arrow_1" if(d->currentobj) { back = add_arrow_info(&(((d->currentobj)->fpd).ahb), b); } d->state = STATE_START; d->currentdet = NULL; d->currentobj = NULL; if(!back) { d->errc = DKFIG_ERROR_SYNTAX; } $? "- add_arc_arrow_1 %d", back return back; } /** Add forward arrow information to a polyline. @param d Drawing structure. @param b Text line buffer. @return 1 on success, 0 on error. */ static int add_pl_arrow_1 DK_P2(dk_fig_drawing *,d,char *,b) { int back = 0; $? "+ add_pl_arrow_1" if(d->currentobj) { back = add_arrow_info(&(((d->currentobj)->fpd).ahf), b); } d->state = STATE_EXPECT_PL_POINTS; if(((d->currentobj)->fpd).st == 5) { d->state = STATE_EXPECT_PL_IMAGENAME; } if((((d->currentobj)->fpd).ar) & 2) { $? ". expect backward arrow" d->state = STATE_EXPECT_PL_ARROW_2; } if(!back) { d->errc = DKFIG_ERROR_SYNTAX; } $? "- add_pl_arrow_1 %d", back return back; } /** Add backward arrow information to polyline. @param d Drawing structure. @param b Text line buffer. @return 1 on success, 0 on error. */ static int add_pl_arrow_2 DK_P2(dk_fig_drawing *,d,char *,b) { int back = 0; $? "+ add_pl_arrow_2" if(d->currentobj) { back = add_arrow_info(&(((d->currentobj)->fpd).ahb), b); } d->state = STATE_EXPECT_PL_POINTS; if(((d->currentobj)->fpd).st == 5) { d->state = STATE_EXPECT_PL_IMAGENAME; } if(!back) { d->errc = DKFIG_ERROR_SYNTAX; } $? "- add_pl_arrow_2 %d", back return back; } /** Add forward arrow information to a spline. @param d Drawing structure. @param b Text line buffer. @return 1 on success, 0 on error. */ static int add_sp_arrow_1 DK_P2(dk_fig_drawing *,d,char *,b) { int back = 0; $? "+ add_sp_arrow_1" if(d->currentobj) { back = add_arrow_info(&(((d->currentobj)->fpd).ahf), b); } if((((d->currentobj)->fpd).ar) & 2) { d->state = STATE_EXPECT_SPLINE_ARROW_2; } else { d->state = STATE_EXPECT_SPLINE_POINTS; } if(!back) { d->errc = DKFIG_ERROR_SYNTAX; } $? "- add_sp_arrow_1 %d", back return back; } /** Add backward arrow information to a spline. @param d Drawing structure. @param b Text line buffer. @return 1 on success, 0 on error. */ static int add_sp_arrow_2 DK_P2(dk_fig_drawing *,d,char *,b) { int back = 0; $? "+ add_sp_arrow_1" if(d->currentobj) { back = add_arrow_info(&(((d->currentobj)->fpd).ahb), b); } d->state = STATE_EXPECT_SPLINE_POINTS; if(!back) { d->errc = DKFIG_ERROR_SYNTAX; } $? "- add_sp_arrow_1 %d", back return back; } /** Add a line of polyline point co-ordinates. @param d Drawing structure. @param b Text line buffer. @return 1 on success, 0 on error. */ static int add_pl_points DK_P2(dk_fig_drawing *,d,char *,b) { int back = 1; long l; dk_fig_polyline *p; char *cptr, *nptr; int cc; $? "+ add_pl_points" if((d->currentdet) && (d->currentobj)) { p = (dk_fig_polyline *)(d->currentdet); cptr = dkstr_start(b, NULL); cc = 1; if(p->npoints == 0) cc = 0; while(cptr && (cc == 1)) { nptr = dkstr_next(cptr, NULL); if(sscanf(cptr, "%ld", &l) == 1) { if(d->currentpnt < p->npoints) { if(d->xory) { (p->yvalues)[d->currentpnt] = l; d->xory = 0; d->currentpnt += 1; if(d->currentpnt >= p->npoints) { cc = 0; d->state = STATE_START; d->currentdet = NULL; d->currentobj = NULL; } } else { (p->xvalues)[d->currentpnt] = l; d->xory = 1; } } else { cc = 0; d->state = STATE_START; d->currentdet = NULL; d->currentobj = NULL; } } else { cc = 0; back = 0; } cptr = nptr; } } else { back = 0; } $? "- add_pl_points %d", back return back; } /** Save the name of a bitmap image. @param d Drawing structure. @param b Text line buffer. @return 1 on success, 0 on error. */ static int add_pl_imagename DK_P2(dk_fig_drawing *,d,char *,b) { int back = 0; char *fn; int fl; int reason; dk_fig_polyline *p; $? "+ add_pl_imagename" reason = DKFIG_ERROR_SYNTAX; if(d->currentdet) { p = (dk_fig_polyline *)(d->currentdet); fn = dkstr_next(b, NULL); if(fn) { if(sscanf(b, "%d", &fl) == 1) { reason = DKFIG_ERROR_MEMORY; p->flipped = fl; fn = dkstr_dup(fn); if(fn) { if(p->imagename) { char *ptr; ptr = p->imagename; dk_delete(ptr); } p->imagename = fn; $? ". imagename=\"%s\"", p->imagename back = 1; d->state = STATE_EXPECT_PL_POINTS; } } } } if(!back) { d->errc = reason; } $? "- add_pl_imagename %d", back return back; } /** Add a line of point co-ordinates. @param d Drawing structure. @param b Text line buffer. @return 1 on success, 0 on error. */ static int add_sp_points DK_P2(dk_fig_drawing *,d,char *,b) { int back = 0; int cc; long l; dk_fig_spline *s; char *cptr, *nptr; $? "+ add_sp_points" s = (dk_fig_spline *)(d->currentdet); if(s) { back = 1; cptr = dkstr_start(b, NULL); cc = 1; if(s->npoints == 0) cc = 0; if(d->currentpnt < (size_t)(s->npoints)) { while(cc && cptr) { nptr = dkstr_next(cptr, NULL); if(sscanf(cptr, "%ld", &l) == 1) { if(d->xory) { (s->yvalues)[d->currentpnt] = l; d->xory = 0; d->currentpnt += 1; if(d->currentpnt >= (size_t)(s->npoints)) { cc = 0; d->state = STATE_EXPECT_SPLINE_FACTORS; d->currentpnt = 0; } } else { (s->xvalues)[d->currentpnt] = l; d->xory = 1; } } else { cc = 0; back = 0; } cptr = nptr; } } else { d->state = STATE_EXPECT_SPLINE_FACTORS; d->currentpnt = 0; } } $? "- add_sp_points %d", back return back; } /** Add a line of s_k blending coefficients. @param d Drawing structure. @param b Text line buffer. @return 1 on success, 0 on error. */ static int add_sp_factors DK_P2(dk_fig_drawing *,d,char *,b) { int back = 0; dk_fig_spline *s; char *cptr, *nptr; double dx; int cc; $? "+ add_sp_factors" s = (dk_fig_spline *)(d->currentdet); if(s) { if(d->currentpnt < (size_t)(s->npoints)) { back = 1; cc = 1; cptr = dkstr_start(b, NULL); while(cc && cptr) { nptr = dkstr_next(cptr, NULL); if(sscanf(cptr, "%lf", &dx) == 1) { (s->svalues)[d->currentpnt] = dx; d->currentpnt += 1; if(d->currentpnt >= (size_t)(s->npoints)) { cc = 0; d->state = STATE_START; d->currentdet = NULL; d->currentobj = NULL; d->currentpnt = 0; d->xory = 0; } } else { back = cc = 0; } cptr = nptr; } } else { d->state = STATE_START; d->currentdet = NULL; d->currentobj = NULL; d->currentpnt = 0; d->xory = 0; } } $? "- add_sp_factors %d",back return back; } /** Add a line (no comment line) to the drawing. @param d Drawing structure. @param b Text line buffer. @param c Conversion job structure. @return 1 on success, 0 on error. */ static int add_contents_line DK_P3(dk_fig_drawing *,d,char *,b, dk_fig_conversion *,c) { int back = 0; $? "+ add_contents_line %s %s", TR_PTR(d), TR_STR(b) switch(d->state) { case STATE_EXPECT_ORIENTATION: { back = get_orientation(d,b); } break; case STATE_EXPECT_JUSTIFICATION: { back = get_justification(d,b); } break; case STATE_EXPECT_UNITS: { back = get_units(d,b); } break; case STATE_EXPECT_PAPERSIZE: { back = get_papersize(d,b); } break; case STATE_EXPECT_MAGNIFICATION: { back = get_magnification(d,b); $? ". magnification added" } break; case STATE_EXPECT_MULTIPLE_PAGE: { back = get_multipage(d,b); } break; case STATE_EXPECT_TRANSPARENT_COLOR: { back = get_transparent_color(d,b); } break; case STATE_EXPECT_RESOLUTION: { back = get_resolution(d,b); } break; case STATE_START: { d->currentdet = NULL; d->currentobj = NULL; back = begin_object(d,b,c); } break; case STATE_EXPECT_ARC_ARROW_1: { back = add_arc_arrow_1(d,b); } break; case STATE_EXPECT_ARC_ARROW_2: { back = add_arc_arrow_2(d,b); } break; case STATE_EXPECT_PL_POINTS: { back = add_pl_points(d,b); } break; case STATE_EXPECT_PL_ARROW_1: { back = add_pl_arrow_1(d,b); } break; case STATE_EXPECT_PL_ARROW_2: { back = add_pl_arrow_2(d,b); } break; case STATE_EXPECT_PL_IMAGENAME: { back = add_pl_imagename(d,b); } break; case STATE_EXPECT_SPLINE_ARROW_1: { back = add_sp_arrow_1(d,b); } break; case STATE_EXPECT_SPLINE_ARROW_2: { back = add_sp_arrow_2(d,b); } break; case STATE_EXPECT_SPLINE_POINTS: { back = add_sp_points(d,b); } break; case STATE_EXPECT_SPLINE_FACTORS: { back = add_sp_factors(d,b); } break; } $? "- add_contents_line %d", back return back; } /** Add one line to drawing structure. @param o Fig drawing root object. @param b Buffer containing the line to add. @param c Conversion job structure. @return 1 on success, 0 on error. */ int dkfig_read_add_line DK_P3(dk_fig_object *,o,char *,b, dk_fig_conversion *,c) { int back = 0; dk_fig_drawing *d = NULL; char *p1; $? "+ dkfig_read_add_line %s %s", TR_PTR(o), TR_STR(b) if(o && b) { d = (dk_fig_drawing *)(o->data); if(d) { $? ". drawing ok" d->lineno += 1UL; d->errl = d->lineno; p1 = dkstr_start(b, NULL); if(p1) { if(*p1 == '#') { if(d->state == STATE_EMPTY) { $? ". expect first line" back = is_first_line_ok(d,b); } else { $? ". normal comment" p1++; p1 = dkstr_start(p1, NULL); if(p1) { if(*p1 == '#') { $? ". special comment" p1++; p1 = dkstr_start(p1, NULL); if(p1) { back = add_special_comment(d,p1); } else { $? ". empty, ignore" back = 1; } } else { $? ". simple comment, ignore" back = 1; } } else { $? ". simple comment, ignore" back = 1; } } } else { $? ". contents line" back = add_contents_line(d,p1,c); } } else { $? "! empty line" back = 1; } } else { $? "! internal problem" } } $? "- dkfig_read_add_line %d", back return back; } /** Build splines and collect font information. @param o Fig object structure. @param n Text handling flags for normal texts. @param s Text handling flags for special texts. @param c Conversion job structure. @return 1 on success, 0 on error. */ static int build_splines_and_fonth DK_P4(dk_fig_object *,o, int,n, int,s, dk_fig_conversion *,c) { int back = 1; dk_fig_object *objptr, *no; dk_fig_drawing *dptr; dk_fig_compound *cptr; dk_storage_iterator_t *it; int error_was_here; int error_type; $? "+ build_splines_and_fonth" objptr = o; dptr = (dk_fig_drawing *)(o->data); if(dptr) { it = dptr->objit; dksto_it_reset(it); while(objptr) { dptr->errl = objptr->lineno; error_was_here = 0; error_type = 0; /* 0=math, 1=mem, 2=setup */ no = (dk_fig_object *)dksto_it_next(it); if(no) { switch(no->objtype) { case DK_FIG_OBJ_ARC: { $? ". arc" if(!dkfig_tool_arc_complete(no, dptr,c)) { error_was_here = 1; back = 0; } dkfig_tool_bb_arc(no, dptr); dkfig_tool_bb_add(&(dptr->dbb), &(no->dbb)); } break; case DK_FIG_OBJ_POLYLINE: { $? ". polyline" if(!dkfig_tool_polyline_complete(no, dptr,c)) { error_was_here = 1; back = 0; } dkfig_tool_bb_polyline(no, dptr); dkfig_tool_bb_add(&(dptr->dbb), &(no->dbb)); } break; case DK_FIG_OBJ_ELLIPSE: { $? ". ellipse" dkfig_tool_bb_ellipse(no, dptr); dkfig_tool_bb_add(&(dptr->dbb), &(no->dbb)); } break; case DK_FIG_OBJ_DRAWING: { $? "! should never happen" } break; case DK_FIG_OBJ_COMPOUND: { cptr = (dk_fig_compound *)(no->data); if((cptr->objects) && (cptr->objit)) { objptr = no; it = cptr->objit; dksto_it_reset(it); } } break; case DK_FIG_OBJ_SPLINE: { $? ". spline" if(dkfig_tool_build_one_spline(no, dptr, c)) { dkfig_tool_bb_spline(no, dptr); dkfig_tool_bb_add(&(dptr->dbb), &(no->dbb)); } else { error_was_here = 1; back = 0; $? "! error while building spline" } } break; case DK_FIG_OBJ_TEXT: { dk_fig_fonth_t fh, *fhptr; $? ". text" dkfig_fnt_fonth_for_text(&fh, n, s, (dk_fig_text *)(no->data)); if((dptr->fonthi) && (dptr->fonth)) { fhptr = (dk_fig_fonth_t *)dksto_it_find_like( dptr->fonthi, (void *)(&fh), 0 ); if(fhptr) { ((dk_fig_text *)(no->data))->font_handling = fhptr; } else { fhptr = dkfig_fnt_copy_fonth(&fh); if(fhptr) { if(dksto_add(dptr->fonth, (void *)fhptr)) { ((dk_fig_text *)(no->data))->font_handling = fhptr; } else { error_was_here = 1; error_type = 1; back = 0; $? "! memory" dkfig_fnt_del_fonth(fhptr); } } else { error_was_here = 1; error_type = 1; back = 0; $? "! memory" } } } else { error_was_here = 1; error_type = 2; back = 0; $? "! no fonthandling storage or no iterator" } } break; } if(error_was_here) { /* ERROR message, use error_type and no->lineno */ if(c) { if(c->app && c->msg1) { /* char *msg[3]; */ switch(error_type) { case 0: { dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 13); } break; case 1: { dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 11); } break; default: { dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 44); } break; } } } } } else { objptr = (objptr->parent); it = NULL; if(objptr) { if(objptr->objtype == DK_FIG_OBJ_DRAWING) { dptr = (dk_fig_drawing *)(objptr->data); it = dptr->objit; } else { cptr = (dk_fig_compound *)(objptr->data); it = cptr->objit; } } } } } $? "- build_splines_and_fonth %d", back return back; } /** Process document level special comments. @param c Conversion job structure. @param dr Drawing structure. @return 1 on success, 0 on error. */ static int use_dlsc DK_P2(dk_fig_conversion *,c, dk_fig_drawing *,dr) { int back = 1; dk_fig_opt *fo; char *drname; int i; if(dr->dlsc) { if(dr->dlsci) { drname = driver_names[8]; if(c->bdnum >= 0) { if(c->bdnum < 8) { drname = driver_names[c->bdnum]; } } dksto_it_reset(dr->dlsci); while((fo = (dk_fig_opt *)dksto_it_next(dr->dlsci)) != NULL) { if(fo->name) { i = dkfig_opt_process_special_comment(c, fo->name, drname, 1); if(i != 1) { /* Problem */ switch(i) { case -1: case -2: case -3: case -4: { fo->used = 0x01; } break; } if(c->bdnum != 3) { dkfig_tool2_report_special_comment(c, fo, i); } } else { fo->used = 0x01; } } } } } return back; } /** Handle end of input. Check parser state (last object must be finished) and prepare some structures for text handling. @param o Fig drawing root object. @param n Text handling type for normal texts. @param s Text handling type for special texts. @param c Conversion job structure. @return 1 on success, 0 on error. */ int dkfig_read_input_finished DK_P4(dk_fig_object *,o, int,n, int,s, dk_fig_conversion *,c) { int back = 0; dk_fig_drawing *dr = NULL; dk_fig_fonth_t *fp = NULL; unsigned long numfonts = 0UL; $? "+ dkfig_read_input_finished %s", TR_PTR(o) if(o) { if((o->objtype) == DK_FIG_OBJ_DRAWING) { dr = (dk_fig_drawing *)(o->data); if(dr) { dr->errl = 0UL; if((dr->state == STATE_START) && (dr->errc == 0)) { if(use_dlsc(c,dr)) { back = build_splines_and_fonth(o, n, s, c); if(dr->fonthi) { dksto_it_reset(dr->fonthi); while((fp = (dk_fig_fonth_t *)dksto_it_next(dr->fonthi)) != NULL) { if(dkfig_dt_is_latex_text(fp)) { fp->fonthno = numfonts++; } } dr->numlatfonts = numfonts; dr->numlatalpha = dkfig_dt_needed_alpha(numfonts); } } else { } } else { if(dr->state != STATE_START) { /* ERROR: Syntax error! */ if(c) { dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 12); } } } } } } $? "- dkfig_read_input_finished %d", back return back; } /** Retrieve object line number (the line number in which the object was started). @param o Fig object structure. @return The line number. */ unsigned long dkfig_rd_get_lineno DK_P1(dk_fig_object *,o) { unsigned long back = 0UL; $? "+ dkfig_rd_get_lineno" if(o) { if(o->data) { back = ((dk_fig_drawing *)(o->data))->lineno; } } $? "- dkfig_rd_get_lineno %lu", back return back; } /** Retrieve line number of last error. @param o Drawing root object. @return The line number. */ unsigned long dkfig_rd_get_errl DK_P1(dk_fig_object *,o) { unsigned long back = 0UL; $? "+ dkfig_rd_get_lineno" if(o) { if(o->data) { back = ((dk_fig_drawing *)(o->data))->errl; } } $? "- dkfig_rd_get_lineno %lu", back return back; } /** Retrieve error code of last error. @param o Drawing root object. @return The error code. */ int dkfig_rd_get_errc DK_P1(dk_fig_object *,o) { int back = 0; $? "+ dkfig_rd_get_errc" if(o) { if(o->data) { back = ((dk_fig_drawing *)(o->data))->errc; } } $? "- dkfig_rd_get_errc %d", back return back; } /** Save input file name for later use. @param o Drawing root object. @param n File name. @return 1 on success, 0 on error. */ int dkfig_set_input_filename DK_P2(dk_fig_object *,o,char *,n) { int back = 0; dk_fig_drawing *d; char *newfn, *ofn; $? "+ dkfig_set_input_filename %s %s", TR_PTR(o), TR_STR(n) if(o && n) { d = (dk_fig_drawing *)(o->data); if(d) { newfn = dkstr_dup(n); if(newfn) { if(d->inputfilename) { ofn = d->inputfilename; dk_delete(ofn); } d->inputfilename = newfn; back = 1; } else { d->errc = DKFIG_ERROR_MEMORY; } } } $? "- dkfig_set_input_filename %d", back return back; } /** Initialize root object to parse input. @param o Drawing root object. @return 1 on success, 0 on error. */ int dkfig_read_prepare_for_input DK_P1(dk_fig_object *,o) { int back = 0; dk_fig_drawing *dr; $? "+ dkfig_read_prepare_for_input %s", TR_PTR(o) if(o) { if((o->objtype) == DK_FIG_OBJ_DRAWING) { dr = (dk_fig_drawing *)(o->data); if(dr) { dr->lineno = 0UL; dr->currentcomp = o; dr->state = 0; back = 1; } } } $? "- dkfig_read_prepare_for_input %d", back return back; } /** Set number of Bezier spline segments per X-spline segment. @param o Drawing root object. @param n Number of segments. @return 1 on success, 0 on error. */ int dkfig_set_spline_segments DK_P2(dk_fig_object *,o,size_t,n) { int back = 0; dk_fig_drawing *d; $? "+ dkfig_set_spline_segments %s %lu", TR_PTR(o), (unsigned long)n if(o) { d = (dk_fig_drawing *)(o->data); if(d) { back = 1; d->spline_segs = n; if(d->spline_segs < 1) { d->spline_segs = 1; } } } $? "- dkfig_set_spline_segments %d", back return back; } /** Set options to drawing. @param d Fig drawing structure. @param o Options as obtained from conversion job structure. */ void dkfig_rd_set_opts DK_P2(dk_fig_drawing *,d, unsigned long,o) { if(d) { d->opt1 = o; } } /** Set arrowhead line join. @param d Fig drawing structure. @param ahlj The arrowhead line join. */ void dkfig_rd_set_ahlj DK_P2(dk_fig_drawing *,d, int,ahlj) { if(d) { d->ahlj = ahlj; } } /** Create flattened container of Fig objects in order of drawing. @param c Conversion job structure. @param o Drawing root object. */ dk_storage_t * dkfig_flat_list DK_P2(dk_fig_conversion *,c, dk_fig_object *,o) { dk_storage_t *back = NULL; int ok = 0; dk_fig_object *optr, *no; dk_fig_compound *cptr; dk_fig_drawing *dptr; dk_storage_iterator_t *it; $? "+ dkfig_flat_list" if(c && o) { if(o->objtype == DK_FIG_OBJ_DRAWING) { back = dksto_open(0); if(back) { dksto_set_comp(back, dkfig_object_compare, 0); optr = o; if(optr->data) { dptr = (dk_fig_drawing *)(optr->data); if((dptr->objects) && (dptr->objit)) { dksto_it_reset(dptr->objit); it = dptr->objit; ok = 1; while(optr) { no = (dk_fig_object *)dksto_it_next(it); if(no) { if(c->app) { dkapp_set_source_lineno(c->app, no->lineno); } switch(no->objtype) { case DK_FIG_OBJ_DRAWING: { $? "! should never happen" } break; case DK_FIG_OBJ_COMPOUND: { $? ". go down" cptr = (dk_fig_compound *)(no->data); if(cptr) { if((cptr->objects) && (cptr->objit)) { dksto_it_reset(cptr->objit); optr = no; it = cptr->objit; } else { ok = 0; } } else { ok = 0; } } break; case DK_FIG_OBJ_ARC: case DK_FIG_OBJ_TEXT: case DK_FIG_OBJ_SPLINE: case DK_FIG_OBJ_POLYLINE: case DK_FIG_OBJ_ELLIPSE: { if(!dksto_add(back, (void *)no)) { ok = 0; if(c->app) { dkapp_err_memory(c->app, sizeof(dk_storage_node_t), 1); } } $? ". drw-primitive %d %ld %lu", no->objtype, no->layer, no->lineno } break; default: { $? "! should never happen" } break; } } else { $? ". go up" optr = optr->parent; if(optr) { if(optr->objtype == DK_FIG_OBJ_DRAWING) { dptr = (dk_fig_drawing *)(optr->data); it = dptr->objit; if(!it) { ok = 0; optr = NULL; /* ERROR: Setup problem */ dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 44); } } else { cptr = (dk_fig_compound *)(optr->data); it = cptr->objit; } } } } } else { /* ERROR: Setup problem */ dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 44); } } else { /* ERROR: Setup problem */ dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, 44); } if(!ok) { dksto_close(back); back = NULL; } } else { if(c->app) { dkapp_err_memory(c->app, sizeof(dk_storage_t), 1); } } } } $? "- dkfig_flat_list %s", TR_PTR(back) return back; } /** Set minimum and maximum number of iteration steps for arrowhead length on splines calculation. @param d Fig drawing structure. @param min Mininum number of steps. @param max Maximum number of steps. */ void dkfig_rd_set_it_steps DK_P3(dk_fig_drawing *,d, unsigned long,min, unsigned long,max) { if(d) { d->minitsteps = min; d->maxitsteps = max; } }