/* WARNING: This file was generated by dkct. Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: f2lsvg.ctr */ /* Copyright (C) 2012-2013, Dirk Krause 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 author 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 f2lsvg.c The f2lsvg module. */ #line 28 "f2lsvg.ctr" #include "dk3all.h" #include "dk3bezcu.h" #include "dk3font.h" #include "fig2lat.h" #include "f2lud.h" #include "f2lsvg.h" #include "f2lsvgst.h" #include "dk3figto.h" #include "dkt-version.h" #include "dk3xsp.h" #include "dk3font.h" #include "dk3bif.h" #line 45 "f2lsvg.ctr" /** Keywords used by the module. */ static char const * const f2lsvg_c8_kw[] = { /* 0 */ "\n", /* 1 */ " ", /* 2 */ "\n", /* 3 */ "\n", /* 6 */ "<", /* 7 */ "svg:", /* 8 */ "/", /* 9 */ ">", /* 10 */ "svg", /* 11 */ "width=\"%lgin\" height=\"%lgin\" viewBox=\"0 0 %ld %ld\"", /* 12 */ "xmlns=\"http://www.w3.org/2000/svg\"\n", /* 13 */ "xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n", /* 14 */ "title", /* 15 */ "desc", /* 16 */ "Fig file converted by fig2lat", /* 17 */ "http://dktools.sourceforge.net/fig2lat.html", /* 18 */ "defs", /* 19 */ "style", /* 20 */ "type=\"text/css\"", /* 21 */ "", /* 23 */ "@font-face {\n", /* 24 */ "}\n", /* 25 */ "font-family: \"", /* 26 */ "\";\n", /* 27 */ "font-style: oblique;\n", /* 28 */ "font-style: italic;\n", /* 29 */ "font-style: normal;\n", /* 30 */ "font-weight: %d;\n", /* 31 */ "src: url(\"", /* 32 */ ".ttf", /* 33 */ "\");\n", /* 34 */ "file://", /* 35 */ "g", /* 36 */ "/>\n", /* 37 */ "rect", /* 38 */ "x=\"%lg\" y=\"%lg\" width=\"%lg\" height=\"%lg\"", /* 39 */ " rx=\"%lg\" ry=\"%lg\"", /* 40 */ "polygon", /* 41 */ "points=\"", /* 42 */ "\"\n", /* 43 */ "%lg,%lg", /* 44 */ "polyline", /* 45 */ "circle", /* 46 */ "ellipse", /* 47 */ "\ncx=\"%lg\" cy=\"%lg\" r=\"%lg\"\n", /* 48 */ "\ntransform=\"translate(%lg %lg) rotate(%lg)\" rx=\"%lg\" ry=\"%lg\"\n", /* 49 */ "\ncx=\"%lg\" cy=\"%lg\" rx=\"%lg\" ry=\"%lg\"\n", /* 50 */ "text", /* 51 */ ">", /* 52 */ "\nx=\"%lg\" y=\"%lg\" ", /* 53 */ "\ntransform=\"translate(%lg %lg) rotate(%lg)\" x=\"0\" y=\"0\"\n", /* 54 */ "path", /* 55 */ "\nd=\"", /* 56 */ "M%lg,%lg\n", /* 57 */ "C%lg,%lg %lg,%lg %lg,%lg", /* 58 */ "L%lg,%lg\n", /* 59 */ "Z", /* 60 */ "\ntransform=\"translate(%lg %lg)", /* 61 */ " rotate(%d)", /* 62 */ " scale(", /* 63 */ "1", /* 64 */ "-1", /* 65 */ ")", /* 66 */ "image", /* 67 */ "\nx=\"0\" y=\"0\" width=\"%lg\" height=\"%lg\"\nxlink:href=\"", NULL #line 235 "f2lsvg.ctr" }; /* ************************************************************************ */ /* * * */ /* * Tool functions * */ /* * * */ /* ************************************************************************ */ #line 242 "f2lsvg.ctr" /** Write SVG tag name. For full SVG write the tag name directly, when producing an SVG fragment we prepend svg:. @param job Job structure. @param ind Index of tag name in f2lsvg_c8_kw. */ static void f2lsvg_tag_name(f2l_job_t *job, size_t ind) { if(job->fragment) { fputs(f2lsvg_c8_kw[7], job->of1); } fputs(f2lsvg_c8_kw[ind], job->of1); } /** Start opening tag. @param job Job structure. @param ind Index of tag name in f2lsvg_c8_kw. */ static void f2lsvg_tag_open_start(f2l_job_t *job, size_t ind) { fputs(f2lsvg_c8_kw[6], job->of1); if(job->fragment) { fputs(f2lsvg_c8_kw[7], job->of1); } fputs(f2lsvg_c8_kw[ind], job->of1); fputs(f2lsvg_c8_kw[1], job->of1); } /** End a tag. @param job Job structure. */ static void f2lsvg_tag_end(f2l_job_t *job) { fputs(f2lsvg_c8_kw[9], job->of1); } /** Opening tag. @param job Job structure. @param ind Index of tag name in f2lsvg_c8_kw. */ static void f2lsvg_tag_open(f2l_job_t *job, size_t ind) { fputs(f2lsvg_c8_kw[6], job->of1); if(job->fragment) { fputs(f2lsvg_c8_kw[7], job->of1); } fputs(f2lsvg_c8_kw[ind], job->of1); f2lsvg_tag_end(job); } /** Write a closing tag. @param job Job structure. @param ind Index of tag name in f2lsvg_c8_kw. */ static void f2lsvg_tag_close(f2l_job_t *job, size_t ind) { fputs(f2lsvg_c8_kw[6], job->of1); fputs(f2lsvg_c8_kw[8], job->of1); if(job->fragment) { fputs(f2lsvg_c8_kw[7], job->of1); } fputs(f2lsvg_c8_kw[ind], job->of1); fputs(f2lsvg_c8_kw[9], job->of1); fputs(f2lsvg_c8_kw[0], job->of1); } /** Calculate factors for coordinates transformations. @param job Job structure. @param drw Drawing structure. @return 1 on success, 0 on error. */ static int f2lsvg_coordinates_transformation(f2l_job_t *job, dk3_fig_drawing_t *drw) { double xmin; double xmax; double ymin; double ymax; int back = 1; int mec = 0; #line 348 "f2lsvg.ctr" (job->ct2d).mx = (job->ct2d).my = dk3ma_d_div_ok(72.0, drw->res, &mec); xmin = dk3ma_d_mul_ok((job->ct2d).mx, (drw->bb).xmin, &mec); xmax = dk3ma_d_mul_ok((job->ct2d).mx, (drw->bb).xmax, &mec); ymin = dk3ma_d_mul_ok((job->ct2d).my, (drw->bb).ymin, &mec); ymax = dk3ma_d_mul_ok((job->ct2d).my, (drw->bb).ymax, &mec); /* Align to 1/8 inch grid. */ xmin = xmin / 9.0; xmin = floor(xmin); xmin = dk3ma_d_mul_ok(9.0, xmin, &mec); xmax = xmax / 9.0; xmax = ceil(xmax); xmax = dk3ma_d_mul_ok(9.0, xmax, &mec); ymin = ymin / 9.0; ymin = floor(ymin); ymin = dk3ma_d_mul_ok(9.0, ymin, &mec); ymax = ymax / 9.0; ymax = ceil(ymax); ymax = dk3ma_d_mul_ok(9.0, ymax, &mec); (job->ct2d).nx = -1.0 * xmin; (job->ct2d).ny = -1.0 * ymin; job->width = dk3ma_d_sub_ok(xmax, xmin, &mec); job->height = dk3ma_d_sub_ok(ymax, ymin, &mec); job->lwidth = dk3ma_d_to_l_ok(job->width, &mec); job->lheight = dk3ma_d_to_l_ok(job->height, &mec); #line 370 "f2lsvg.ctr" #line 371 "f2lsvg.ctr" if(mec) { back = 0; /* ERROR: Math problem */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 38); f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH); #line 376 "f2lsvg.ctr" } #line 377 "f2lsvg.ctr" return back; } /** Collect style information for a text object, add to SVG style collection if necessary. @param job Job structure. @param drw Fig drawing. @param psvg SVG style collection. @param pobj Object to add. @return 1 on success, 0 on error. */ static int f2lsvg_text_object_style( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *pobj ) { f2l_svg_style_t sty; /* Style. */ dk3_fig_color_t fc; /* Fill color. */ int back = 1; #line 403 "f2lsvg.ctr" if(!(DK3_FIG_FONT_FLAG_HIDDEN & ((pobj->dt).txt.ff))) { f2lsvgst_style_initialize(&sty); /* Fill color. */ dk3fig_tool_find_int_color(&fc, drw, pobj->pc, 20); f2lsvgst_style_set_fill_color(&sty, fc.r, fc.g, fc.b); /* Text font. */ f2lsvgst_style_set_text( psvg, &sty, ((((pobj->dt).txt.ff) & DK3_FIG_FONT_FLAG_PS) ? 1 : 0), (pobj->dt).txt.fo, (pobj->dt).txt.fs ); /* Text alignment. */ f2lsvgst_style_set_text_align(&sty, pobj->st); pobj->dsd = (void *)f2lsvgst_style_add(psvg, &sty); if(!(pobj->dsd)) { back = 0; f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_SYSTEM); #line 424 "f2lsvg.ctr" } } #line 427 "f2lsvg.ctr" return back; } /** Collect style information for a non-text object, add to SVG style collection if necessary. @param job Job structure. @param drw Fig drawing. @param psvg SVG style collection. @param pobj Object to add. @return 1 on success, 0 on error. */ static int f2lsvg_path_object_style( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *pobj ) { f2l_svg_style_t sty; /* Style. */ f2l_svg_fill_pattern_t pat; /* Pattern. */ dk3_fig_color_t fc; /* Fill color. */ dk3_fig_color_t sc; /* Stroke color. */ double lw; /* Line width in SVG units. */ double lsv; /* Line style value in SVG units. */ int res; /* Operation result. */ int mec = 0; /* Mathematical error code. */ int any = 0; /* Flag: Any settings applied to style. */ int op = 0; /* Draw operation. */ int back = 1 ; #line 461 "f2lsvg.ctr" op = dk3fig_tool_get_operation(drw, pobj); f2lsvgst_style_initialize(&sty); if(op & DK3_FIG_OP_PATTERN) { /* Fill pattern. */ any = 1; dk3fig_tool_find_int_color(&fc, drw, pobj->fc, 20); dk3fig_tool_find_int_color(&sc, drw, pobj->pc, 20); pat.pn = 0UL; pat.fn = pobj->fi; pat.sr = sc.r; pat.sg = sc.g; pat.sb = sc.b; pat.fr = fc.r; pat.fg = fc.g; pat.fb = fc.b; res = f2lsvgst_style_set_pattern(psvg, &sty, &pat); if(!(res)) { back = 0; switch(psvg->ec) { case DK3_ERROR_MEMORY: { dk3app_log_i1(job->app, DK3_LL_ERROR, 9); f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_SYSTEM); #line 480 "f2lsvg.ctr" } break; default: { /* ERROR: Mathematical error. */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 38); f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH); #line 485 "f2lsvg.ctr" } break; } } } else { if(op & DK3_FIG_OP_FILL) { /* Fill color. */ dk3fig_tool_find_int_color(&fc, drw, pobj->fc, pobj->fi); f2lsvgst_style_set_fill_color(&sty, fc.r, fc.g, fc.b); any = 1; } } if(op & DK3_FIG_OP_STROKE) { any = 1; /* Line width. */ lw = dk3fig_tool_get_lw(drw, pobj, &mec); lw = dk3ct_2d_r(&(job->ct2d), lw, &mec); f2lsvgst_style_set_line_width(&sty, lw); if(mec) { back = 0; /* ERROR: Mathematical error. */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 38); mec = 0; f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH); #line 510 "f2lsvg.ctr" } /* Line style. */ /* lsv = dk3ct_2d_r(&(job->ct2d), pobj->sv, &mec); */ lsv = 0.9 * pobj->sv; f2lsvgst_style_set_line_style(&sty, pobj->ls, lsv); /* Stroke color. */ dk3fig_tool_find_int_color(&sc, drw, pobj->pc, 20); f2lsvgst_style_set_line_color(&sty, sc.r, sc.g, sc.b); if(!(pobj->cl)) { /* Line cap. */ f2lsvgst_style_set_text_line_cap(&sty, pobj->cs); } } if(op) { if(DK3_FIG_OBJ_ELLIPSE != pobj->ot) { if(!((DK3_FIG_OBJ_ARC == pobj->ot) && (1 == pobj->st))) { /* Line join. */ any = 1; f2lsvgst_style_set_text_line_join(&sty, pobj->js); } } } if(any) { pobj->dsd = (void *)f2lsvgst_style_add(psvg, &sty); if(!(pobj->dsd)) { back = 0; f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_SYSTEM); #line 541 "f2lsvg.ctr" } } #line 544 "f2lsvg.ctr" return back; } /** Collect style information for one object. @param job Job structure. @param drw Drawing structure. @param psvg SVG style collection. @param pobj Current object. @return 1 on success, 0 on error. */ static int f2lsvg_object_style_collection( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *pobj ) { int back = 1; switch(pobj->ot) { case DK3_FIG_OBJ_PSEUDO_HALF_CIRCLE: { if(!f2lsvg_path_object_style(job, drw, psvg, pobj)) { back = 0; } } break; case DK3_FIG_OBJ_ELLIPSE: { if(!f2lsvg_path_object_style(job, drw, psvg, pobj)) { back = 0; } } break; case DK3_FIG_OBJ_POLYLINE: { if(5 != pobj->st) { if(!f2lsvg_path_object_style(job, drw, psvg, pobj)) { back = 0; } } } break; case DK3_FIG_OBJ_SPLINE: { if(!f2lsvg_path_object_style(job, drw, psvg, pobj)) { back = 0; } } break; case DK3_FIG_OBJ_ARC: { if(!f2lsvg_path_object_style(job, drw, psvg, pobj)) { back = 0; } } break; case DK3_FIG_OBJ_TEXT: { if(!f2lsvg_text_object_style(job, drw, psvg, pobj)) { back = 0; } } break; } if(!(back)) { f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_UNKNOWN); #line 590 "f2lsvg.ctr" } return back; } /** Collect style information for all objects in drawing, add styles to style collection. @param job Job structure. @param drw Fig drawing. @param psvg SVG style collection. @return 1 on success, 0 on error. */ static int f2lsvg_collect_styles(f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg) { dk3_fig_obj_t *pobj; unsigned long objno = 0UL; unsigned long oldsourceline; int res; int back = 1; #line 613 "f2lsvg.ctr" oldsourceline = dk3app_get_source_line(job->app); dk3sto_it_reset(drw->iobj); while(NULL != (pobj = (dk3_fig_obj_t *)dk3sto_it_next(drw->iobj))) { if(!dk3fig_tool_is_bgrect(pobj, objno)) { dk3app_set_source_line(job->app, pobj->li); if(!f2lsvg_object_style_collection(job, drw, psvg, pobj)) { back = 0; } if(pobj->af) { if((pobj->af)->o1) { res = f2lsvg_object_style_collection( job, drw, psvg, (dk3_fig_obj_t *)((pobj->af)->o1) ); if(!(res)) { back = 0; } } if((pobj->af)->o2) { res = f2lsvg_object_style_collection( job, drw, psvg, (dk3_fig_obj_t *)((pobj->af)->o2) ); if(!(res)) { back = 0; } } } if(pobj->ab) { if((pobj->ab)->o1) { res = f2lsvg_object_style_collection( job, drw, psvg, (dk3_fig_obj_t *)((pobj->ab)->o1) ); if(!(res)) { back = 0; } } if((pobj->ab)->o2) { res = f2lsvg_object_style_collection( job, drw, psvg, (dk3_fig_obj_t *)((pobj->ab)->o2) ); if(!(res)) { back = 0; } } } } objno++; } dk3app_set_source_line(job->app, oldsourceline); #line 654 "f2lsvg.ctr" return back; } /** Check whether or not we must append a slash to the font base directory. @param bn Font base directory name. @return 1 to add a slash, 0 for no slash needed. */ static int f2lsvg_must_add_slash_to_font_base(char const *bn) { char const *ptr; int back = 1; ptr = bn; while(*ptr) { if('/' == *ptr) { back = 0; } else { back = 1; } ptr++; } return back; } /** Write font face definitions. @param job Job structure. @param drw Drawing structure. @param psvg SVG style collection. */ static void f2lsvg_write_font_faces( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg ) { dkChar dkb[DK3_MAX_PATH]; /* Font base (dkChars). */ char chb[DK3_MAX_PATH]; /* Font base (8-bit chars). */ size_t i; /* Walk through the 35 fonts. */ int fs; /* Font style. */ int res = 0; #line 703 "f2lsvg.ctr" if(0 < job->svgfontbase) { #line 704 "f2lsvg.ctr" switch(job->svgfontbase) { case 2: { res = dk3font_gs_base_web(job->app, dkb, DK3_SIZEOF(dkb,dkChar)); } break; default: { res = dk3font_gs_base_local(job->app, dkb, DK3_SIZEOF(dkb,dkChar)); } break; } if(res) { #line 713 "f2lsvg.ctr" res = dk3str_to_c8p_app( chb, sizeof(chb), dkb, dk3app_get_encoding(job->app), job->app ); #line 716 "f2lsvg.ctr" } for(i = 0; i < 35; i++) { #line 718 "f2lsvg.ctr" if((psvg->psFontsUsed)[i]) { fputs(f2lsvg_c8_kw[23], job->of1); /* Font family. */ fputs(f2lsvg_c8_kw[25], job->of1); fputs(dk3font_get_svg_family((int)i), job->of1); fputs(f2lsvg_c8_kw[26], job->of1); #line 725 "f2lsvg.ctr" /* Font style */ fs = dk3font_get_svg_features((int)i); if(fs & DK3_FONT_OBLIQUE) { fputs(f2lsvg_c8_kw[27], job->of1); } else { if(fs & DK3_FONT_ITALIC) { fputs(f2lsvg_c8_kw[28], job->of1); } else { fputs(f2lsvg_c8_kw[29], job->of1); } } #line 737 "f2lsvg.ctr" /* Font weight */ fprintf(job->of1,f2lsvg_c8_kw[30],dk3font_get_svg_font_weight((int)i)); #line 741 "f2lsvg.ctr" /* Source */ fputs(f2lsvg_c8_kw[31], job->of1); if(res) { #if 0 /* 2013-01-30 No file:// prefix */ if(1 == job->svgfontbase) { fputs(f2lsvg_c8_kw[34], job->of1); } #endif fputs(chb, job->of1); if(f2lsvg_must_add_slash_to_font_base(chb)) { fputs(f2lsvg_c8_kw[8], job->of1); } } #line 757 "f2lsvg.ctr" fputs(dk3font_get_gs_old_file((int)i), job->of1); #line 758 "f2lsvg.ctr" fputs(f2lsvg_c8_kw[32], job->of1); #if 0 /* 2013-01-30 No font id for TTF fonts */ fputs(dk3font_get_svg_fontid((int)i), job->of1); #line 763 "f2lsvg.ctr" #endif fputs(f2lsvg_c8_kw[33], job->of1); #line 765 "f2lsvg.ctr" fputs(f2lsvg_c8_kw[24], job->of1); #line 766 "f2lsvg.ctr" } #line 767 "f2lsvg.ctr" } #line 768 "f2lsvg.ctr" } #line 769 "f2lsvg.ctr" } /* ************************************************************************ */ /* * * */ /* * Driver functions * */ /* * * */ /* ************************************************************************ */ #line 776 "f2lsvg.ctr" /** Driver-specific initialization. @param job Job structure. @param drw Drawing structure. @return 1 on success, 0 on error. */ static int f2lsvg_driver_initialize(f2l_job_t *job, dk3_fig_drawing_t *drw) { f2l_svg_t *psvg; int back = 0; #line 790 "f2lsvg.ctr" if(f2lsvg_coordinates_transformation(job, drw)) { psvg = f2lsvgst_new_app(job->app); if(psvg) { drw->dsd = (void *)psvg; back = f2lsvg_collect_styles(job, drw, psvg); } } #line 797 "f2lsvg.ctr" return back; } /** Release resources allocated by f2lud_driver_initialize(). @param job Job structure. @param drw Drawing structure. */ static void f2lsvg_driver_end(f2l_job_t *job, dk3_fig_drawing_t *drw) { #line 811 "f2lsvg.ctr" if(drw->dsd) { f2lsvgst_delete((f2l_svg_t *)(drw->dsd)); } drw->dsd = NULL; #line 815 "f2lsvg.ctr" } /** Open output file. @param job Jobs structure. @return 1 on success, 0 on error. */ static int f2lsvg_open_output_files(f2l_job_t *job) { int back = 0; job->of1 = dk3sf_fopen_app(job->on1, dkT("w"), job->app); if(job->of1) { back = 1; } else { f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_SYSTEM); #line 833 "f2lsvg.ctr" } return back; } /** Close output file. @param job Job structure. */ static void f2lsvg_close_output_files(f2l_job_t *job) { if(job->of1) { dk3sf_fclose_app(job->of1, job->app); } job->of1 = NULL; } /** Check whether we must write a style tag for font faces or style definitions. @param job Job structure. @param psvg SVG style collection structure. @return 1 to write a style tag, 0 otherwise. */ static int f2lsvg_must_write_style(f2l_job_t *job, f2l_svg_t *psvg) { int back = 0; if(job->css) { if(psvg->nStyles) { back = 1; } } if(0 < job->svgfontbase) { if(f2lsvgst_any_ps_font_used(psvg)) { back = 1; } } return back; } /** Check whether we must write a defs tag for fill patterns, font faces, or style definitions. @param job Job structure. @param psvg SVG style collection structure. @return 1 to write a defs tag, 0 otherwise. */ static int f2lsvg_must_write_defs(f2l_job_t *job, f2l_svg_t *psvg) { int back; back = f2lsvg_must_write_style(job, psvg); if(0 == back) { if(psvg->nPatterns) { back = 1; } } return back; } /** Write start of output file. @param job Job strucure. @param drw Drawing structure. @return 1 on success, 0 on error. */ static int f2lsvg_start_processing(f2l_job_t *job, dk3_fig_drawing_t *drw) { f2l_svg_t *psvg; int back = 1; #line 913 "f2lsvg.ctr" psvg = (f2l_svg_t *)(drw->dsd); /* XML header and doctype. */ if(!(job->fragment)) { fputs(f2lsvg_c8_kw[2], job->of1); fputs(f2lsvg_c8_kw[3], job->of1); fputs(f2lsvg_c8_kw[4], job->of1); fputs(f2lsvg_c8_kw[5], job->of1); } /* Opening svg tag. */ f2lsvg_tag_open_start(job, 10); fprintf( job->of1, f2lsvg_c8_kw[11], (job->width / 72.0), (job->height / 72.0), job->lwidth, job->lheight ); if(!(job->fragment)) { fputs(f2lsvg_c8_kw[0], job->of1); fputs(f2lsvg_c8_kw[12], job->of1); fputs(f2lsvg_c8_kw[13], job->of1); } f2lsvg_tag_end(job); fputs(f2lsvg_c8_kw[0], job->of1); /* Title. */ f2lsvg_tag_open(job, 14); fputs(f2lsvg_c8_kw[16], job->of1); f2lsvg_tag_close(job, 14); /* Description. */ f2lsvg_tag_open(job, 15); fputs(f2lsvg_c8_kw[17], job->of1); f2lsvg_tag_close(job, 15); /* Definitions and style. */ if(f2lsvg_must_write_defs(job, psvg)) { f2lsvg_tag_open(job, 18); fputs(f2lsvg_c8_kw[0], job->of1); /* Pattern definitions. */ f2lsvgst_write_patterns(job, drw, psvg); if(f2lsvg_must_write_style(job, psvg)) { f2lsvg_tag_open_start(job, 19); fputs(f2lsvg_c8_kw[20], job->of1); f2lsvg_tag_end(job); fputs(f2lsvg_c8_kw[21], job->of1); fputs(f2lsvg_c8_kw[0], job->of1); /* Font face definitions if any. */ f2lsvg_write_font_faces(job, drw, psvg); /* Style definitions. */ if(job->css) { f2lsvgst_write_styles(job, drw, psvg); } fputs(f2lsvg_c8_kw[22], job->of1); f2lsvg_tag_close(job, 19); } f2lsvg_tag_close(job, 18); } #line 973 "f2lsvg.ctr" return back; } /** Write end of output file. @param job Job structure. @param drw Drawing structure. */ static void f2lsvg_end_processing(f2l_job_t *job, dk3_fig_drawing_t *drw) { f2lsvg_tag_close(job, 10); } /** Process ellipse object. @param job Job structure. @param drw Drawing structure. @param psvg SVG style collection. @param obj Current object to process. @param ec Pointer to error code variable. */ static void f2lsvg_process_ellipse( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *obj, int *ec ) { double rotation = 0.0; /* Rotation in degree. */ double irot; /* Rotation as integer. */ double x; /* Center X. */ double y; /* Center Y. */ double rx; /* Radius X. */ double ry; /* Radius Y. */ int isEllipse = 0; /* Flag: Is ellipse. */ int isRotated = 0; /* Flag: Is rotated. */ int mec = 0; /* Mathematical error code. */ switch(obj->st) { case 1: case 2: { if(fabs(dk3ma_d_sub_ok((obj->dt).ell.rx,(obj->dt).ell.ry,&mec)) > 1.0e-6) { isEllipse = 1; if(fabs((obj->dt).ell.an) > 1.0e-6) { isRotated = 1; rotation = dk3ma_d_mul_ok(180.0, ((obj->dt).ell.an / M_PI), &mec); irot = dk3ma_rint(rotation); if(1.0e-6 > fabs(dk3ma_d_sub_ok(rotation, irot, &mec))) { rotation = irot; } rotation = -1.0 * rotation; } } } break; } x = dk3ct_2d_x(&(job->ct2d), (obj->dt).ell.cx, &mec); y = dk3ct_2d_y(&(job->ct2d), (obj->dt).ell.cy, &mec); rx = ry = dk3ct_2d_r(&(job->ct2d), (obj->dt).ell.rx, &mec); fputs(f2lsvg_c8_kw[6], job->of1); if(isEllipse) { ry = dk3ct_2d_r(&(job->ct2d), (obj->dt).ell.ry, &mec); f2lsvg_tag_name(job, 46); if(isRotated) { fprintf(job->of1, f2lsvg_c8_kw[48], x, y, rotation, rx, ry); } else { fprintf(job->of1, f2lsvg_c8_kw[49], x, y, rx, ry); } } else { f2lsvg_tag_name(job, 45); fprintf(job->of1, f2lsvg_c8_kw[47], x, y, rx); } f2lsvgst_write_style_for_object(job, drw, psvg, obj); fputs(f2lsvg_c8_kw[36], job->of1); if(mec) { *ec = mec; } } /** Process box object. @param job Job structure. @param drw Drawing structure. @param psvg SVG style collection. @param obj Current object to process. @param arcbox Flag: Rounded corners. @param ec Pointer to error code variable. */ static void f2lsvg_process_box( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *obj, int arcbox, int *ec ) { dk3_bb_t outbb; dk3_fig_poly_point_t *po; double x; double y; double w; double h; double r; size_t i; int mec = 0; po = (obj->dt).pol.po; if(po) { dk3bb_reset(&outbb); for(i = 0; i < (obj->dt).pol.np; i++) { dk3bb_add_x(&outbb, dk3ct_2d_x(&(job->ct2d), po->x, &mec)); dk3bb_add_y(&outbb, dk3ct_2d_y(&(job->ct2d), po->y, &mec)); po++; } x = outbb.xmin; y = outbb.ymin; w = fabs(dk3ma_d_sub_ok(outbb.xmax, outbb.xmin, &mec)); h = fabs(dk3ma_d_sub_ok(outbb.ymax, outbb.ymin, &mec)); r = -1.0; if(arcbox) { #line 1100 "f2lsvg.ctr" r = fabs(0.9 * (obj->dt).pol.ra); #line 1101 "f2lsvg.ctr" if(r > (0.5 * w)) { r = 0.5 * w; } if(r > (0.5 * h)) { r = 0.5 * h; } #line 1103 "f2lsvg.ctr" } if(0 == mec) { fputs(f2lsvg_c8_kw[6], job->of1); f2lsvg_tag_name(job, 37); fputs(f2lsvg_c8_kw[0], job->of1); fprintf(job->of1, f2lsvg_c8_kw[38], x, y, w, h); if(arcbox) { fprintf(job->of1, f2lsvg_c8_kw[39], r, r); } fputs(f2lsvg_c8_kw[0], job->of1); f2lsvgst_write_style_for_object(job, drw, psvg, obj); fputs(f2lsvg_c8_kw[36], job->of1); } } dk3bb_reset(&outbb); if(mec) { *ec = mec; } } /** Process polygon object. @param job Job structure. @param drw Drawing structure. @param psvg SVG style collection. @param obj Current object to process. @param primary Flag: Primary object. @param ec Pointer to error code variable. */ static void f2lsvg_process_pl_polygon( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *obj, int primary, int *ec ) { dk3_fig_poly_point_t *po; size_t np; size_t i; int mec = 0; fputs(f2lsvg_c8_kw[6], job->of1); f2lsvg_tag_name(job, 40); fputs(f2lsvg_c8_kw[0], job->of1); fputs(f2lsvg_c8_kw[41], job->of1); po = (obj->dt).pol.po; np = (obj->dt).pol.np; if(primary) { if(1.0e-6 > fabs(dk3ma_d_sub_ok(po[0].x, po[np - 1].x, &mec))) { if(1.0e-6 > fabs(dk3ma_d_sub_ok(po[0].y, po[np - 1].y, &mec))) { np--; } } } for(i = 0; i < np; i++) { fprintf( job->of1, f2lsvg_c8_kw[43], dk3ct_2d_x(&(job->ct2d), po->x, &mec), dk3ct_2d_y(&(job->ct2d), po->y, &mec) ); if(i != (np - 1)) { fputs(f2lsvg_c8_kw[0], job->of1); } po++; } fputs(f2lsvg_c8_kw[42], job->of1); f2lsvgst_write_style_for_object(job, drw, psvg, obj); fputs(f2lsvg_c8_kw[36], job->of1); if(mec) { *ec = mec; } } /** Process polygon object. @param job Job structure. @param drw Drawing structure. @param psvg SVG style collection. @param obj Current object to process. @param ec Pointer to error code variable. */ static void f2lsvg_process_pl_polyline( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *obj, int *ec ) { dk3_fig_poly_point_t *po; size_t np; size_t i; int mec = 0; fputs(f2lsvg_c8_kw[6], job->of1); f2lsvg_tag_name(job, 44); fputs(f2lsvg_c8_kw[0], job->of1); fputs(f2lsvg_c8_kw[41], job->of1); po = (obj->dt).pol.po; np = (obj->dt).pol.np; for(i = 0; i < np; i++) { fprintf( job->of1, f2lsvg_c8_kw[43], dk3ct_2d_x(&(job->ct2d), po->x, &mec), dk3ct_2d_y(&(job->ct2d), po->y, &mec) ); if(i != (np - 1)) { fputs(f2lsvg_c8_kw[0], job->of1); } po++; } fputs(f2lsvg_c8_kw[42], job->of1); f2lsvgst_write_style_for_object(job, drw, psvg, obj); fputs(f2lsvg_c8_kw[36], job->of1); if(mec) { *ec = mec; } } /** Process image object. @param job Job structure. @param drw Drawing structure. @param psvg SVG style collection. @param obj Current object to process. @param ec Pointer to error code variable. */ static void f2lsvg_process_image( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *obj, int *ec ) { dk3_bb_t outbb; /* Output range. */ dk3_bif_t *bif; /* Image to process. */ dk3_fig_poly_point_t *po; /* Coordinates points. */ double tx; /* X translation. */ double ty; /* Y translation. */ double xres; /* Image resolution in x direction. */ double yres; /* Image resolution in y direction. */ double w; /* Image width (resolution used). */ double h; /* Image height (resolution used). */ double qx; /* Usable stretch factor for x. */ double qy; /* Usable stretch factor for y. */ double ow; /* Output width. */ double oh; /* Output height. */ double x1; /* Smallest x value. */ double x2; /* Largest x value. */ double y1; /* Smallest y value. */ double y2; /* Largest y value. */ dk3_bif_coord_t imw; /* Image width (number of pixels). */ dk3_bif_coord_t imh; /* Image height (number of pixels). */ size_t np; /* Number of coordinates points. */ size_t i; /* Traverse coordinates points. */ int drawdir; /* Drawing direction. */ int rotation = 0; /* Rotation in degree. */ int doScaleX = 0; /* Flag: Scale x=-1. */ int doScaleY = 0; /* Flag: Sclae y=-1. */ if((obj->dt).pol.fn) { bif = dk3bif_open_c8_filename_app( (obj->dt).pol.fn, DK3_BIF_IMAGE_TYPE_UNKNOWN, job->app ); if(bif) { /* Find image dimensions. */ imw = dk3bif_get_width(bif); imh = dk3bif_get_height(bif); xres = dk3bif_get_xres(bif); yres = dk3bif_get_yres(bif); dk3bif_close(bif); /* Find output area. */ dk3bb_reset(&outbb); po = (obj->dt).pol.po; np = (obj->dt).pol.np; for(i = 0; i < np; i++) { dk3bb_add_x(&outbb, dk3ct_2d_x(&(job->ct2d), po->x, ec)); dk3bb_add_y(&outbb, dk3ct_2d_y(&(job->ct2d), po->y, ec)); po++; } x1 = outbb.xmin; x2 = outbb.xmax; y1 = outbb.ymin; y2 = outbb.ymax; /* Find drawing direction. */ drawdir = f2lto_find_draw_direction(job, drw, obj, ec); /* Find real image width and height. */ if((xres > 0.0) && (yres > 0.0)) { switch(drawdir) { case DK3_IMAGE_ORIGIN_LEFT_BOTTOM: case DK3_IMAGE_ORIGIN_RIGHT_TOP: case DK3_IMAGE_ORIGIN_LEFT_TOP_FLIPPED: case DK3_IMAGE_ORIGIN_RIGHT_BOTTOM_FLIPPED: { w = dk3ma_d_div_ok((double)imh, yres, ec); h = dk3ma_d_div_ok((double)imw, xres, ec); } break; default: { w = dk3ma_d_div_ok((double)imw, xres, ec); h = dk3ma_d_div_ok((double)imh, yres, ec); } break; } } else { switch(drawdir) { case DK3_IMAGE_ORIGIN_LEFT_BOTTOM: case DK3_IMAGE_ORIGIN_RIGHT_TOP: case DK3_IMAGE_ORIGIN_LEFT_TOP_FLIPPED: case DK3_IMAGE_ORIGIN_RIGHT_BOTTOM_FLIPPED: { w = (double)imh; h = (double)imw; } break; default: { w = (double)imw; h = (double)imh; } break; } } /* Find the stretch factors and used regions. */ qx = dk3ma_d_div_ok(dk3ma_d_sub_ok(outbb.xmax, outbb.xmin, ec), w, ec); qy = dk3ma_d_div_ok(dk3ma_d_sub_ok(outbb.ymax, outbb.ymin, ec), h, ec); qx = fabs(qx); qy = fabs(qy); ow = oh = 0.0; if(qy >= qx) { /* Image too wide, can not use all height. */ ow = dk3ma_d_sub_ok(outbb.xmax, outbb.xmin, ec); oh = dk3ma_d_mul_ok(qx, h, ec); y1 = dk3ma_d_add_ok( outbb.ymin, ( 0.5 * dk3ma_d_sub_ok(dk3ma_d_sub_ok(outbb.ymax, outbb.ymin, ec), oh, ec) ), ec ); y2 = dk3ma_d_add_ok(y1, oh, ec); } else { /* Image too high, can not use all width. */ oh = dk3ma_d_sub_ok(outbb.ymax, outbb.ymin, ec); ow = dk3ma_d_mul_ok(qy, w, ec); x1 = dk3ma_d_add_ok( outbb.xmin, ( 0.5 * dk3ma_d_sub_ok(dk3ma_d_sub_ok(outbb.xmax, outbb.xmin, ec), ow, ec) ), ec ); x2 = dk3ma_d_add_ok(x1, ow, ec); } /* Find coordinates transformations. */ switch(drawdir) { case DK3_IMAGE_ORIGIN_RIGHT_BOTTOM_FLIPPED: { tx = x2; ty = y2; rotation = -90; doScaleY = 1; } break; case DK3_IMAGE_ORIGIN_RIGHT_TOP_FLIPPED: { tx = x2; ty = y1; doScaleX = 1; } break; case DK3_IMAGE_ORIGIN_LEFT_BOTTOM_FLIPPED: { tx = x1; ty = y2; doScaleY = 1; } break; case DK3_IMAGE_ORIGIN_LEFT_TOP_FLIPPED: { tx = x1; ty = y1; rotation = -90; doScaleX = 1; } break; case DK3_IMAGE_ORIGIN_RIGHT_BOTTOM: { tx = x2; ty = y2; rotation = 180; } break; case DK3_IMAGE_ORIGIN_RIGHT_TOP: { tx = x2; ty = y1; rotation = 90; } break; case DK3_IMAGE_ORIGIN_LEFT_BOTTOM: { tx = x1; ty = y2; rotation = -90; } break; default: { tx = x1; ty = y1; } break; } /* Write output. */ /* */ fputs(f2lsvg_c8_kw[6], job->of1); f2lsvg_tag_name(job, 35); fprintf(job->of1, f2lsvg_c8_kw[60], tx, ty); if(0 != rotation) { fprintf(job->of1, f2lsvg_c8_kw[61], rotation); } if((doScaleX) || (doScaleY)) { fputs(f2lsvg_c8_kw[62], job->of1); fputs(f2lsvg_c8_kw[(doScaleX) ? 64 : 63], job->of1); fputs(f2lsvg_c8_kw[1], job->of1); fputs(f2lsvg_c8_kw[(doScaleY) ? 64 : 63], job->of1); fputs(f2lsvg_c8_kw[65], job->of1); } fputs(f2lsvg_c8_kw[42], job->of1); fputs(f2lsvg_c8_kw[5], job->of1); /* */ fputs(f2lsvg_c8_kw[6], job->of1); f2lsvg_tag_name(job, 66); fprintf(job->of1, f2lsvg_c8_kw[67], ow, oh); fputs((obj->dt).pol.fn, job->of1); fputs(f2lsvg_c8_kw[42], job->of1); fputs(f2lsvg_c8_kw[36], job->of1); /* */ fputs(f2lsvg_c8_kw[6], job->of1); fputs(f2lsvg_c8_kw[8], job->of1); f2lsvg_tag_name(job, 35); fputs(f2lsvg_c8_kw[5], job->of1); } else { f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_SYSTEM); #line 1419 "f2lsvg.ctr" } } } /** Process polyline object. @param job Job structure. @param drw Drawing structure. @param psvg SVG style collection. @param obj Current object to process. @param primary Flag: Primary object. @param ec Pointer to error code variable. */ static void f2lsvg_process_polyline( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *obj, int primary, int *ec ) { switch(obj->st) { case 5: { /* imported image */ f2lsvg_process_image(job, drw, psvg, obj, ec); } break; case 4: { /* arc box */ f2lsvg_process_box(job, drw, psvg, obj, 1, ec); } break; case 3: { /* polygon */ f2lsvg_process_pl_polygon(job, drw, psvg, obj, primary, ec); } break; case 2: { /* box */ f2lsvg_process_box(job, drw, psvg, obj, 0, ec); } break; default: { /* polyline */ f2lsvg_process_pl_polyline(job, drw, psvg, obj, ec); } break; } } /** Process open spline object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param sp Spline points. @param np Total number of points @param cp Current point/segment. @param isfirst Flag: Moveto needed. @param iscl Flag: Closed (1) or open (0) spline. @param primary Flag: Primary object (1=object, 0=arrowhead). @param ec Pointer to error code variable. */ static void f2lsvg_process_full_spline_segment( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, dk3_fig_spline_point_t *sp, size_t np, size_t cp, int isfirst, int iscl, int primary, int *ec ) { dk3_xspline_segment_t seg; dk3_fig_spline_point_t *pa = NULL; dk3_fig_spline_point_t *pb = NULL; dk3_fig_spline_point_t *pc = NULL; dk3_fig_spline_point_t *pd = NULL; double factor; double t; double x; double y; double dxdt; double dydt; double lastx = 0.0; double lasty = 0.0; double lastdxdt = 0.0; double lastdydt = 0.0; size_t xsss; size_t iseg; size_t ic; size_t id; int res; int mec = 0; #line 1514 "f2lsvg.ctr" if(cp < ((iscl) ? (np) : (np - 1))) { pb = &(sp[cp]); #line 1516 "f2lsvg.ctr" ic = cp + 1; while(ic >= np) { ic = ic - np; } #line 1518 "f2lsvg.ctr" pc = &(sp[ic]); if(cp > 0) { #line 1520 "f2lsvg.ctr" pa = &(sp[cp - 1]); } else { if(iscl) { #line 1523 "f2lsvg.ctr" pa = &(sp[np - 1]); } } if(cp < (np - 2)) { #line 1527 "f2lsvg.ctr" pd = &(sp[cp + 2]); } else { if(iscl) { id = cp + 2; while(id >= np) { id = id - np; } #line 1532 "f2lsvg.ctr" pd = &(sp[id]); } } xsss = dk3fig_tool_xssbs(drw, primary); #line 1536 "f2lsvg.ctr" factor = 1.0 / (double)xsss; dk3xsp_reset(&seg); if(job->cosp) { dk3xsp_set_cb(&seg, 1); } dk3xsp_set(&seg, pa, pb, pc, pd); #line 1540 "f2lsvg.ctr" if(dk3xsp_calculate(&seg, 0.0, 1)) { #line 1541 "f2lsvg.ctr" lastx = dk3xsp_get_x(&seg); lasty = dk3xsp_get_y(&seg); lastdxdt = dk3xsp_get_dxdt(&seg); lastdydt = dk3xsp_get_dydt(&seg); lastdxdt = (factor * lastdxdt) / 3.0; lastdydt = (factor * lastdydt) / 3.0; if(isfirst) { #line 1548 "f2lsvg.ctr" /* MOVETO lastx lasty */ fprintf( job->of1, f2lsvg_c8_kw[56], dk3ct_2d_x(&(job->ct2d), lastx, &mec), dk3ct_2d_y(&(job->ct2d), lasty, &mec) ); } for(iseg = 0; iseg < xsss; iseg++) { #line 1556 "f2lsvg.ctr" if(iseg < (xsss - 1)) { t = (double)(iseg + 1) / (double)xsss; } else { t = 1.0; } #line 1561 "f2lsvg.ctr" res = dk3xsp_calculate(&seg, t, 1); #line 1562 "f2lsvg.ctr" if(!(res)) { mec = DK3_ERROR_MATH_OVERFLOW; } x = dk3xsp_get_x(&seg); y = dk3xsp_get_y(&seg); dxdt = dk3xsp_get_dxdt(&seg); dydt = dk3xsp_get_dydt(&seg); dxdt = (factor * dxdt) / 3.0; dydt = (factor * dydt) / 3.0; #line 1569 "f2lsvg.ctr" fprintf( job->of1, f2lsvg_c8_kw[57], dk3ct_2d_x(&(job->ct2d), dk3ma_d_add_ok(lastx, lastdxdt, &mec), &mec), dk3ct_2d_y(&(job->ct2d), dk3ma_d_add_ok(lasty, lastdydt, &mec), &mec), dk3ct_2d_x(&(job->ct2d), dk3ma_d_sub_ok(x, dxdt, &mec), &mec), dk3ct_2d_y(&(job->ct2d), dk3ma_d_sub_ok(y, dydt, &mec), &mec), dk3ct_2d_x(&(job->ct2d), x, &mec), dk3ct_2d_y(&(job->ct2d), y, &mec) ); lastx = x; lasty = y; lastdxdt = dxdt; lastdydt = dydt; if(iseg < (xsss - 1)) { fputs(f2lsvg_c8_kw[0], job->of1); } else { if(cp < (np - 1)) { fputs(f2lsvg_c8_kw[0], job->of1); } else { if(iscl) { fputs(f2lsvg_c8_kw[0], job->of1); } } } #line 1590 "f2lsvg.ctr" } } else { mec = DK3_ERROR_MATH_OVERFLOW; } } if(mec) { *ec = mec; } #line 1597 "f2lsvg.ctr" } /** Create path for the first partial X-spline segment from closed X-spline. @param job Job structure. @param drw Fig drawing. @param obj Fig object. @param sp Spline points array. @param np Number of spline points. @param i Current segment index. @param ts Parameter t for start point. @param isfirst Flag: First segment. @param iscl Flag: Closed spline. @param primary Flag: Primary (1=primary object, 0=arrowhead). @param ec Pointer to error code variable, may be NULL. */ static void f2lsvg_first_spline_segment( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, dk3_fig_spline_point_t *sp, size_t np, size_t i, double ts, int isfirst, int iscl, int primary, int *ec ) { dk3_xspline_segment_t seg; /* Segment for caluclation. */ dk3_fig_spline_point_t *pa = NULL; /* Left neighbour. */ dk3_fig_spline_point_t *pb = NULL; /* Start. */ dk3_fig_spline_point_t *pc = NULL; /* End. */ dk3_fig_spline_point_t *pd = NULL; /* Right neighbour. */ double myts; /* t for start. */ double dnumsegs; /* Number of segments. */ double factor; /* Scale factor for deriv. */ double t; /* Current t. */ double x; /* Bezier end x. */ double y; /* Bezier end y. */ double dxdt; /* Bezier dx/dt at end. */ double dydt; /* Bezier dy/dt at end. */ double lastx = 0.0; /* Bezier start x. */ double lasty = 0.0; /* Bezier start y. */ double lastdxdt = 0.0; /* dx/dt at start. */ double lastdydt = 0.0; /* dy/dt at end. */ size_t nsegs; /* Number of segments. */ size_t iseg; /* Current segment. */ int res; /* Calculation result. */ #line 1651 "f2lsvg.ctr" myts = dk3ma_d_sub_ok(ts, floor(ts), ec); #line 1652 "f2lsvg.ctr" dnumsegs = (1.0 - myts) * dk3fig_tool_xssbs(drw, primary); dnumsegs = ceil(dnumsegs); #line 1654 "f2lsvg.ctr" nsegs = dk3ma_d_to_size_ok(dnumsegs, ec); #line 1655 "f2lsvg.ctr" pb = &(sp[i]); pc = &(sp[i + 1]); if(0 < i) { pa = &(sp[i - 1]); } if(i < (np - 2)) { pd = &(sp[i + 2]); } factor = (1.0 - myts) / (double)nsegs; #line 1664 "f2lsvg.ctr" dk3xsp_reset(&seg); if(job->cosp) { dk3xsp_set_cb(&seg, 1); } dk3xsp_set(&seg, pa, pb, pc, pd); if(dk3xsp_calculate(&seg, myts, 1)) { /* If necessary move to the start point. */ lastx = dk3xsp_get_x(&seg); lasty = dk3xsp_get_y(&seg); lastdxdt = dk3xsp_get_dxdt(&seg); lastdydt = dk3xsp_get_dydt(&seg); lastdxdt = (factor * lastdxdt) / 3.0; lastdydt = (factor * lastdydt) / 3.0; if(isfirst) { fprintf( job->of1, f2lsvg_c8_kw[56], dk3ct_2d_x(&(job->ct2d), lastx, ec), dk3ct_2d_y(&(job->ct2d), lasty, ec) ); } if(1.0e-6 < (1.0 - myts)) { for(iseg = 0; iseg < nsegs; iseg++) { if(iseg < (nsegs - 1)) { t = myts + (((1.0 - myts) * ((double)(iseg + 1))) / ((double)nsegs)); } else { t = 1.0; } res = dk3xsp_calculate(&seg, t, 1); if(!(res)) { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } } x = dk3xsp_get_x(&seg); y = dk3xsp_get_y(&seg); dxdt = dk3xsp_get_dxdt(&seg); dydt = dk3xsp_get_dydt(&seg); dxdt = (factor * dxdt) / 3.0; dydt = (factor * dydt) / 3.0; fprintf( job->of1, f2lsvg_c8_kw[57], dk3ct_2d_x(&(job->ct2d), dk3ma_d_add_ok(lastx, lastdxdt, ec), ec), dk3ct_2d_y(&(job->ct2d), dk3ma_d_add_ok(lasty, lastdydt, ec), ec), dk3ct_2d_x(&(job->ct2d), dk3ma_d_sub_ok(x, dxdt, ec), ec), dk3ct_2d_y(&(job->ct2d), dk3ma_d_sub_ok(y, dydt, ec), ec), dk3ct_2d_x(&(job->ct2d), x, ec), dk3ct_2d_y(&(job->ct2d), y, ec) ); lastx = x; lasty = y; lastdxdt = dxdt; lastdydt = dydt; fputs(f2lsvg_c8_kw[0], job->of1); } } else { res = dk3xsp_calculate(&seg, 1.0, 0); if(!(res)) { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } /* ERROR: Math */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 36); f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH); #line 1719 "f2lsvg.ctr" } x = dk3xsp_get_x(&seg); y = dk3xsp_get_y(&seg); fprintf( job->of1, f2lsvg_c8_kw[58], dk3ct_2d_x(&(job->ct2d), x, ec), dk3ct_2d_y(&(job->ct2d), y, ec) ); } } else { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH); #line 1731 "f2lsvg.ctr" } #line 1733 "f2lsvg.ctr" } /** Create path for the last partial X-spline segment from closed X-spline. @param job Job structure. @param drw Fig drawing. @param obj Fig object. @param sp Spline points array. @param np Number of spline points. @param i Current segment index. @param te Parameter t for end point. @param isfirst Flag: First segment. @param iscl Flag: Closed spline. @param primary Flag: Primary (1=primary object, 0=arrowhead). @param ec Pointer to error code variable, may be NULL. */ static void f2lsvg_final_spline_segment( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, dk3_fig_spline_point_t *sp, size_t np, size_t i, double te, int isfirst, int iscl, int primary, int *ec ) { dk3_xspline_segment_t seg; /* Segment for caluclation. */ dk3_fig_spline_point_t *pa = NULL; /* Left neighbour. */ dk3_fig_spline_point_t *pb = NULL; /* Start. */ dk3_fig_spline_point_t *pc = NULL; /* End. */ dk3_fig_spline_point_t *pd = NULL; /* Right neighbour. */ double myte; /* t for end. */ double dnumsegs; /* Number of segments. */ double factor; /* Scale factor for deriv. */ double t; /* Current t. */ double x; /* Bezier end x. */ double y; /* Bezier end y. */ double dxdt; /* Bezier dx/dt at end. */ double dydt; /* Bezier dy/dt at end. */ double lastx = 0.0; /* Bezier start x. */ double lasty = 0.0; /* Bezier start y. */ double lastdxdt = 0.0; /* dx/dt at start. */ double lastdydt = 0.0; /* dy/dt at end. */ size_t nsegs; /* Number of segments. */ size_t iseg; /* Current segment. */ int res; /* Calculation result. */ #line 1787 "f2lsvg.ctr" myte = dk3ma_d_sub_ok(te, floor(te), ec); #line 1788 "f2lsvg.ctr" dnumsegs = myte * dk3fig_tool_xssbs(drw, primary); dnumsegs = ceil(dnumsegs); #line 1790 "f2lsvg.ctr" nsegs = dk3ma_d_to_size_ok(dnumsegs, ec); #line 1791 "f2lsvg.ctr" pb = &(sp[i]); pc = &(sp[i + 1]); if(0 < i) { pa = &(sp[i - 1]); } if(i < (np - 2)) { pd = &(sp[i + 2]); } factor = myte / (double)nsegs; #line 1800 "f2lsvg.ctr" dk3xsp_reset(&seg); if(job->cosp) { dk3xsp_set_cb(&seg, 1); } dk3xsp_set(&seg, pa, pb, pc, pd); if(dk3xsp_calculate(&seg, 0.0, 1)) { lastx = dk3xsp_get_x(&seg); lasty = dk3xsp_get_y(&seg); lastdxdt = dk3xsp_get_dxdt(&seg); lastdydt = dk3xsp_get_dydt(&seg); lastdxdt = (factor * lastdxdt) / 3.0; lastdydt = (factor * lastdydt) / 3.0; /* Move to start point. */ if(isfirst) { fprintf( job->of1, f2lsvg_c8_kw[56], dk3ct_2d_x(&(job->ct2d), lastx, ec), dk3ct_2d_y(&(job->ct2d), lasty, ec) ); } /* Further curve only if te > 1.0e-6. For smaller te draw straight line. */ if(1.0e-6 < myte) { #line 1823 "f2lsvg.ctr" for(iseg = 0; iseg < nsegs; iseg++) { if(iseg < (nsegs - 1)) { #line 1825 "f2lsvg.ctr" t = (double)(iseg + 1) / (double)nsegs; t = t * myte; } else { #line 1828 "f2lsvg.ctr" t = myte; } #line 1830 "f2lsvg.ctr" res = dk3xsp_calculate(&seg, t, 1); if(!(res)) { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } } x = dk3xsp_get_x(&seg); y = dk3xsp_get_y(&seg); dxdt = dk3xsp_get_dxdt(&seg); dydt = dk3xsp_get_dydt(&seg); dxdt = (factor * dxdt) / 3.0; dydt = (factor * dydt) / 3.0; fprintf( job->of1, f2lsvg_c8_kw[57], dk3ct_2d_x(&(job->ct2d), dk3ma_d_add_ok(lastx, lastdxdt, ec), ec), dk3ct_2d_y(&(job->ct2d), dk3ma_d_add_ok(lasty, lastdydt, ec), ec), dk3ct_2d_x(&(job->ct2d), dk3ma_d_sub_ok(x, dxdt, ec), ec), dk3ct_2d_y(&(job->ct2d), dk3ma_d_sub_ok(y, dydt, ec), ec), dk3ct_2d_x(&(job->ct2d), x, ec), dk3ct_2d_y(&(job->ct2d), y, ec) ); lastx = x; lasty = y; lastdxdt = dxdt; lastdydt = dydt; if(iseg < (nsegs - 1)) { fputs(f2lsvg_c8_kw[0], job->of1); } } } else { #line 1855 "f2lsvg.ctr" res = dk3xsp_calculate(&seg, myte, 0); if(!(res)) { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } /* ERROR: Math */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 36); f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH); #line 1861 "f2lsvg.ctr" } x = dk3xsp_get_x(&seg); y = dk3xsp_get_y(&seg); fprintf( job->of1, f2lsvg_c8_kw[58], dk3ct_2d_x(&(job->ct2d), x, ec), dk3ct_2d_y(&(job->ct2d), y, ec) ); } } else { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH); #line 1873 "f2lsvg.ctr" } #line 1875 "f2lsvg.ctr" } /** Create path for the single partial X-spline segment cutted on both ends from closed X-spline. @param job Job structure. @param drw Fig drawing. @param obj Fig object. @param sp Spline points array. @param np Number of spline points. @param i Current segment index. @param ts Parameter t for start point. @param te Parameter t for end point. @param isfirst Flag: First segment. @param iscl Flag: Closed spline. @param primary Flag: Primary (1=primary object, 0=arrowhead). @param ec Pointer to error code variable, may be NULL. */ static void f2lsvg_single_spline_segment( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, dk3_fig_spline_point_t *sp, size_t np, size_t i, double ts, double te, int isfirst, int iscl, int primary, int *ec ) { dk3_xspline_segment_t seg; /* Segment for caluclation. */ dk3_fig_spline_point_t *pa = NULL; /* Left neighbour. */ dk3_fig_spline_point_t *pb = NULL; /* Start. */ dk3_fig_spline_point_t *pc = NULL; /* End. */ dk3_fig_spline_point_t *pd = NULL; /* Right neighbour. */ double myte; /* t for end. */ double myts; /* t for start. */ double dnumsegs; /* Number of segments. */ double factor; /* Scale factor for deriv. */ double t; /* Current t. */ double x; /* Bezier end x. */ double y; /* Bezier end y. */ double dxdt; /* Bezier dx/dt at end. */ double dydt; /* Bezier dy/dt at end. */ double lastx = 0.0; /* Bezier start x. */ double lasty = 0.0; /* Bezier start y. */ double lastdxdt = 0.0; /* dx/dt at start. */ double lastdydt = 0.0; /* dy/dt at end. */ size_t nsegs; /* Number of segments. */ size_t iseg; /* Current segment. */ int res; /* Calculation result. */ #line 1933 "f2lsvg.ctr" myte = dk3ma_d_sub_ok(te, floor(te), ec); myts = dk3ma_d_sub_ok(ts, floor(ts), ec); dnumsegs = (myte - myts) * dk3fig_tool_xssbs(drw, primary); dnumsegs = ceil(dnumsegs); nsegs = dk3ma_d_to_size_ok(dnumsegs, ec); pb = &(sp[i]); pc = &(sp[i + 1]); if(0 < i) { pa = &(sp[i - 1]); } if(i < (np - 2)) { pd = &(sp[i + 2]); } factor = (myte - myts) / ((double)nsegs); dk3xsp_reset(&seg); if(job->cosp) { dk3xsp_set_cb(&seg, 1); } dk3xsp_set(&seg, pa, pb, pc, pd); if(dk3xsp_calculate(&seg, myts, 1)) { lastx = dk3xsp_get_x(&seg); lasty = dk3xsp_get_y(&seg); lastdxdt = dk3xsp_get_dxdt(&seg); lastdydt = dk3xsp_get_dydt(&seg); lastdxdt = (factor * lastdxdt) / 3.0; lastdydt = (factor * lastdydt) / 3.0; if(isfirst) { fprintf( job->of1, f2lsvg_c8_kw[56], dk3ct_2d_x(&(job->ct2d), lastx, ec), dk3ct_2d_y(&(job->ct2d), lasty, ec) ); } if(1.0e-6 < (myte - myts)) { for(iseg = 0; iseg < nsegs; iseg++) { if(iseg < (nsegs - 1)) { t = myts + (((myte - myts) * ((double)(iseg + 1))) / ((double)nsegs)); } else { t = myte; } res = dk3xsp_calculate(&seg, t, 1); if(!(res)) { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } } x = dk3xsp_get_x(&seg); y = dk3xsp_get_y(&seg); dxdt = dk3xsp_get_dxdt(&seg); dydt = dk3xsp_get_dydt(&seg); dxdt = (factor * dxdt) / 3.0; dydt = (factor * dydt) / 3.0; fprintf( job->of1, f2lsvg_c8_kw[57], dk3ct_2d_x(&(job->ct2d), dk3ma_d_add_ok(lastx, lastdxdt, ec), ec), dk3ct_2d_y(&(job->ct2d), dk3ma_d_add_ok(lasty, lastdydt, ec), ec), dk3ct_2d_x(&(job->ct2d), dk3ma_d_sub_ok(x, dxdt, ec), ec), dk3ct_2d_y(&(job->ct2d), dk3ma_d_sub_ok(y, dydt, ec), ec), dk3ct_2d_x(&(job->ct2d), x, ec), dk3ct_2d_y(&(job->ct2d), y, ec) ); lastx = x; lasty = y; lastdxdt = dxdt; lastdydt = dydt; if(iseg < (nsegs - 1)) { fputs(f2lsvg_c8_kw[0], job->of1); } } } else { res = dk3xsp_calculate(&seg, myte, 0); if(!(res)) { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } /* ERROR: Calculation failed! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 36); f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH); #line 2002 "f2lsvg.ctr" } x = dk3xsp_get_x(&seg); y = dk3xsp_get_y(&seg); fprintf( job->of1, f2lsvg_c8_kw[58], dk3ct_2d_x(&(job->ct2d), x, ec), dk3ct_2d_y(&(job->ct2d), y, ec) ); } } else { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } /* ERROR: Calculation failed! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 36); f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH); #line 2016 "f2lsvg.ctr" } #line 2018 "f2lsvg.ctr" } /** Process open spline object. @param job Job structure. @param drw Drawing structure. @param psvg SVG style collection. @param obj Current object to process. @param primary Flag: Primary object (1=object, 0=arrowhead). @param ec Pointer to error code variable. */ static void f2lsvg_process_open_spline( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *obj, int primary, int *ec ) { dk3_fig_spline_point_t *sp; size_t np; size_t i; size_t min; size_t max; sp = (obj->dt).spl.po; np = (obj->dt).spl.np; fputs(f2lsvg_c8_kw[6], job->of1); f2lsvg_tag_name(job, 54); fputs(f2lsvg_c8_kw[55], job->of1); if(job->coah) { for(i = 0; i < (np - 1); i++) { f2lsvg_process_full_spline_segment( job, drw, obj, sp, np, i, ((0 == i) ? 1 : 0), 0, primary, ec ); } } else { if(obj->ab) { #line 2060 "f2lsvg.ctr" min = dk3ma_d_to_size_ok((obj->dt).spl.ts, ec); if(obj->af) { #line 2062 "f2lsvg.ctr" if((obj->dt).spl.te >= (obj->dt).spl.ts) { max = dk3ma_d_to_size_ok((obj->dt).spl.te, ec); if(max > min) { f2lsvg_first_spline_segment( job, drw, obj, sp, np, min, (obj->dt).spl.ts, 1, 0, primary, ec ); for(i = (min + 1); i < max; i++) { f2lsvg_process_full_spline_segment( job, drw, obj, sp, np, i, 0, 0, primary, ec ); } f2lsvg_final_spline_segment( job, drw, obj, sp, np, max, (obj->dt).spl.te, 0, 0, primary, ec ); } else { f2lsvg_single_spline_segment( job, drw, obj, sp, np, min, (obj->dt).spl.ts, (obj->dt).spl.te, 1, 0, primary, ec ); } } else { /* ERROR: Arrowheads in summary too long for spline */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 37); f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_SYNTAX); #line 2086 "f2lsvg.ctr" } } else { #line 2088 "f2lsvg.ctr" f2lsvg_first_spline_segment( job, drw, obj, sp, np, min, (obj->dt).spl.ts, 1, 0, primary, ec ); for(i = (min + 1); i < (np - 1); i++) { f2lsvg_process_full_spline_segment( job, drw, obj, sp, np, i, 0, 0, primary, ec ); } } } else { #line 2098 "f2lsvg.ctr" if(obj->af) { #line 2099 "f2lsvg.ctr" max = dk3ma_d_to_size_ok((obj->dt).spl.te, ec); if(max < (np - 1)) { if(max > 0) { for(i = 0; i < max; i++) { f2lsvg_process_full_spline_segment( job, drw, obj, sp, np, i, ((0 == i) ? 1 : 0), 0, primary, ec ); } f2lsvg_final_spline_segment( job, drw, obj, sp, np, max, (obj->dt).spl.te, 0, 0, primary, ec ); } else { f2lsvg_final_spline_segment( job, drw, obj, sp, np, max, (obj->dt).spl.te, 1, 0, primary, ec ); } } else { /* ERROR: Illegal max value! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_UNKNOWN); #line 2119 "f2lsvg.ctr" } } else { #line 2121 "f2lsvg.ctr" for(i = 0; i < (np - 1); i++) { f2lsvg_process_full_spline_segment( job, drw, obj, sp, np, i, ((0 == i) ? 1 : 0), 0, primary, ec ); } } } } fputs(f2lsvg_c8_kw[42], job->of1); f2lsvgst_write_style_for_object(job, drw, psvg, obj); fputs(f2lsvg_c8_kw[36], job->of1); } /** Process closed spline object. @param job Job structure. @param drw Drawing structure. @param psvg SVG style collection. @param obj Current object to process. @param primary Flag: Primary object (1=object, 0=arrowhead). @param ec Pointer to error code variable. */ static void f2lsvg_process_closed_spline( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *obj, int primary, int *ec ) { dk3_fig_spline_point_t *sp; size_t np; size_t i; sp = (obj->dt).spl.po; np = (obj->dt).spl.np; fputs(f2lsvg_c8_kw[6], job->of1); f2lsvg_tag_name(job, 54); fputs(f2lsvg_c8_kw[55], job->of1); for(i = 0; i < np; i++) { f2lsvg_process_full_spline_segment( job, drw, obj, sp, np, i, ((0 == i) ? 1 : 0), 1, primary, ec ); } fputs(f2lsvg_c8_kw[59], job->of1); fputs(f2lsvg_c8_kw[42], job->of1); f2lsvgst_write_style_for_object(job, drw, psvg, obj); fputs(f2lsvg_c8_kw[36], job->of1); } /** Process spline object. @param job Job structure. @param drw Drawing structure. @param psvg SVG style collection. @param obj Current object to process. @param primary Flag: Primary object (1=object, 0=arrowhead). @param ec Pointer to error code variable. */ static void f2lsvg_process_spline( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *obj, int primary, int *ec ) { switch(obj->st) { case 1: case 3: case 5: { /* closed spline */ f2lsvg_process_closed_spline(job, drw, psvg, obj, primary, ec); } break; default: { /* open spline */ f2lsvg_process_open_spline(job, drw, psvg, obj, primary, ec); } break; } } /** Process text object. @param job Job structure. @param drw Drawing structure. @param psvg SVG style collection. @param obj Current object to process. @param ec Pointer to error code variable. */ static void f2lsvg_process_text( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *obj, int *ec ) { double rotation = 0.0; /* Rotation in degree. */ double irot = 0.0; /* Rotation as integer. */ double x; /* Text x position. */ double y; /* Text y position. */ int isRotated = 0; /* Flag: Text is rotated. */ int mec = 0; /* Mathematical error code. */ if(!(DK3_FIG_FONT_FLAG_HIDDEN & ((obj->dt).txt.ff))) { rotation = (obj->dt).txt.an; if(1.0e-6 < fabs(rotation)) { isRotated = 1; rotation = dk3ma_d_mul_ok(180.0, (rotation / M_PI), &mec); irot = dk3ma_rint(rotation); if(fabs(dk3ma_d_sub_ok(rotation, irot, &mec)) < 1.0e-3) { rotation = irot; } rotation = -1.0 * rotation; } fputs(f2lsvg_c8_kw[6], job->of1); f2lsvg_tag_name(job, 50); x = dk3ct_2d_x(&(job->ct2d), (obj->dt).txt.x, &mec); y = dk3ct_2d_y(&(job->ct2d), (obj->dt).txt.y, &mec); if(isRotated) { fprintf(job->of1, f2lsvg_c8_kw[53], x, y, rotation); } else { fprintf(job->of1, f2lsvg_c8_kw[52], x, y); } f2lsvgst_write_style_for_object(job, drw, psvg, obj); fputs(f2lsvg_c8_kw[51], job->of1); if((obj->dt).txt.st) { fputs((obj->dt).txt.st, job->of1); } fputs(f2lsvg_c8_kw[6], job->of1); fputs(f2lsvg_c8_kw[8], job->of1); f2lsvg_tag_name(job, 50); fputs(f2lsvg_c8_kw[5], job->of1); if(mec) { *ec = mec; } if(DK3_FIG_FONT_FLAG_SPECIAL & ((obj->dt).txt.ff)) { /* WARNING: Special text was found! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 44); } } } /** Process arc object. @param job Job structure. @param drw Drawing structure. @param psvg SVG style collection. @param obj Current object to process. @param ec Pointer to error code variable. */ static void f2lsvg_process_arc( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *obj, int *ec ) { double sx; /* Start x. */ double sy; /* Start y. */ double cx; /* Center x. */ double cy; /* Center y. */ double r; /* Radius. */ double as; /* Arc start angle in radians. */ double ae; /* Arc end angle in radians. */ double lastx; /* Segment start x. */ double lasty; /* Segment start y. */ double lastkdxdt; /* X difference to first control. */ double lastkdydt; /* Y difference to first control. */ double x; /* Segment end x. */ double y; /* Segment end y. */ double kdxdt; /* X difference to last control. */ double kdydt; /* Y difference to last control. */ double dnumsegs; /* Number of segments. */ double alpha; /* Arc angle in radians. */ double alphaseg; /* Segment angle in radians. */ double kappa; /* Factor for derivative. */ double alphaend; /* Segment end angle in radians. */ size_t nsegs; /* Number of segments. */ size_t i; /* Index of current segment. */ fputs(f2lsvg_c8_kw[6], job->of1); f2lsvg_tag_name(job, 54); fputs(f2lsvg_c8_kw[55], job->of1); cx = (obj->dt).arc.xc; cy = (obj->dt).arc.yc; r = (obj->dt).arc.ra; if((obj->dt).arc.as < (obj->dt).arc.ae) { as = (obj->dt).arc.as; ae = (obj->dt).arc.ae; } else { as = (obj->dt).arc.ae; ae = (obj->dt).arc.as; } alpha = dk3ma_d_sub_ok(ae, as, ec); dnumsegs = ceil(dk3ma_d_mul_ok(4.0, (alpha / M_PI), ec)); nsegs = dk3ma_d_to_size_ok(dnumsegs, ec); alphaseg = alpha / ((double)nsegs); kappa = dk3fig_tool_arc_kappa(alphaseg, ec); sx = lastx = dk3ma_d_add_ok(cx, (r * cos(as)), ec); sy = lasty = dk3ma_d_add_ok(cy, (r * sin(as)), ec); fprintf( job->of1, f2lsvg_c8_kw[56], dk3ct_2d_x(&(job->ct2d), lastx, ec), dk3ct_2d_y(&(job->ct2d), lasty, ec) ); lastkdxdt = dk3ma_d_mul_ok( kappa, (-1.0 * dk3ma_d_mul_ok(r, alphaseg, ec) * sin(as)), ec ); lastkdydt = dk3ma_d_mul_ok( kappa, (dk3ma_d_mul_ok(r, alphaseg, ec) * cos(as)), ec ); for(i = 0; i < nsegs; i++) { if(i < (nsegs - 1)) { alphaend = dk3ma_d_add_ok( as, dk3ma_d_mul_ok(dk3ma_d_add_ok(1.0, (double)i, ec), alphaseg, ec), ec ); } else { alphaend = ae; } x = dk3ma_d_add_ok(cx, (r * cos(alphaend)), ec); y = dk3ma_d_add_ok(cy, (r * sin(alphaend)), ec); kdxdt = dk3ma_d_mul_ok( kappa, (-1.0 * dk3ma_d_mul_ok(r, alphaseg, ec) * sin(alphaend)), ec ); kdydt = dk3ma_d_mul_ok( kappa, (dk3ma_d_mul_ok(r, alphaseg, ec) * cos(alphaend)), ec ); fprintf( job->of1, f2lsvg_c8_kw[57], dk3ct_2d_x(&(job->ct2d), dk3ma_d_add_ok(lastx, lastkdxdt, ec), ec), dk3ct_2d_y(&(job->ct2d), dk3ma_d_add_ok(lasty, lastkdydt, ec), ec), dk3ct_2d_x(&(job->ct2d), dk3ma_d_sub_ok(x, kdxdt, ec), ec), dk3ct_2d_y(&(job->ct2d), dk3ma_d_sub_ok(y, kdydt, ec), ec), dk3ct_2d_x(&(job->ct2d), x, ec), dk3ct_2d_y(&(job->ct2d), y, ec) ); fputs(f2lsvg_c8_kw[0], job->of1); lastx = x; lasty = y; lastkdxdt = kdxdt; lastkdydt = kdydt; } /* For closed arc draw the lines. */ if(1 != obj->st) { fprintf( job->of1, f2lsvg_c8_kw[58], dk3ct_2d_x(&(job->ct2d), cx, ec), dk3ct_2d_y(&(job->ct2d), cy, ec) ); fprintf( job->of1, f2lsvg_c8_kw[58], dk3ct_2d_x(&(job->ct2d), sx, ec), dk3ct_2d_y(&(job->ct2d), sy, ec) ); fputs(f2lsvg_c8_kw[59], job->of1); } fputs(f2lsvg_c8_kw[42], job->of1); f2lsvgst_write_style_for_object(job, drw, psvg, obj); fputs(f2lsvg_c8_kw[36], job->of1); } /** Process half-circle object. @param job Job structure. @param drw Drawing structure. @param psvg SVG style collection. @param obj Current object to process. @param ec Pointer to error code variable. */ static void f2lsvg_process_half_circle( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *obj, int *ec ) { dk3_fig_poly_point_t po[7]; size_t i; /* Traverse po. */ int mec = 0; /* Mathematical error code. */ #line 2424 "f2lsvg.ctr" po[0].x = 0.0; po[0].y = (obj->dt).hci.ra; po[1].x = -1.0 * FIG2LAT_CIRCLE_QUADRANT_BEZIER * (obj->dt).hci.ra; po[1].y = (obj->dt).hci.ra; po[2].x = -1.0 * (obj->dt).hci.ra; po[2].y = FIG2LAT_CIRCLE_QUADRANT_BEZIER * (obj->dt).hci.ra; po[3].x = -1.0 * (obj->dt).hci.ra; po[3].y = 0.0; po[4].x = -1.0 * (obj->dt).hci.ra; po[4].y = -1.0 * FIG2LAT_CIRCLE_QUADRANT_BEZIER * (obj->dt).hci.ra; po[5].x = -1.0 * FIG2LAT_CIRCLE_QUADRANT_BEZIER * (obj->dt).hci.ra; po[5].y = -1.0 * (obj->dt).hci.ra; po[6].x = 0.0; po[6].y = -1.0 * (obj->dt).hci.ra; if(1.0e-6 < fabs((obj->dt).hci.an)) { for(i = 0; i < 7; i++) { dk3fig_tool_rotate_point(&(po[i]), (obj->dt).hci.an, &mec); } } for(i = 0; i < 7; i++) { dk3fig_tool_shift_point(&(po[i]), (obj->dt).hci.cx, (obj->dt).hci.cy, &mec); } for(i = 0; i < 7; i++) { po[i].x = dk3ct_2d_x(&(job->ct2d), po[i].x, &mec); po[i].y = dk3ct_2d_y(&(job->ct2d), po[i].y, &mec); } fputs(f2lsvg_c8_kw[6], job->of1); f2lsvg_tag_name(job, 54); fputs(f2lsvg_c8_kw[55], job->of1); fprintf(job->of1, f2lsvg_c8_kw[56], po[0].x, po[0].y); fprintf( job->of1, f2lsvg_c8_kw[57], po[1].x, po[1].y, po[2].x, po[2].y, po[3].x, po[3].y ); fputs(f2lsvg_c8_kw[0], job->of1); fprintf( job->of1, f2lsvg_c8_kw[57], po[4].x, po[4].y, po[5].x, po[5].y, po[6].x, po[6].y ); if(obj->st) { fputs(f2lsvg_c8_kw[0], job->of1); fprintf(job->of1, f2lsvg_c8_kw[58], po[0].x, po[0].y); fputs(f2lsvg_c8_kw[59], job->of1); } fputs(f2lsvg_c8_kw[42], job->of1); f2lsvgst_write_style_for_object(job, drw, psvg, obj); fputs(f2lsvg_c8_kw[36], job->of1); if(mec) { *ec = mec; } #line 2473 "f2lsvg.ctr" } /** Process object and arrowheads. @param job Job structure. @param drw Drawing structure. @param psvg SVG style collection. @param obj Current object to process. @param primary Flag: primary (1=primary object, 0=arrowhead). @param ec Pointer to error code variable. */ static void f2lsvg_process_one( f2l_job_t *job, dk3_fig_drawing_t *drw, f2l_svg_t *psvg, dk3_fig_obj_t *obj, int primary, int *ec ) { int op; #line 2498 "f2lsvg.ctr" op = dk3fig_tool_get_operation(drw, obj); #line 2499 "f2lsvg.ctr" switch(obj->ot) { case DK3_FIG_OBJ_ELLIPSE: { if(op) { f2lsvg_process_ellipse(job, drw, psvg, obj, ec); } } break; case DK3_FIG_OBJ_POLYLINE: { if(op) {f2lsvg_process_polyline(job, drw, psvg, obj, primary, ec); } } break; case DK3_FIG_OBJ_SPLINE: { if(op) {f2lsvg_process_spline(job, drw, psvg, obj, primary, ec); } } break; case DK3_FIG_OBJ_TEXT: { f2lsvg_process_text(job, drw, psvg, obj, ec); } break; case DK3_FIG_OBJ_ARC: { if(op) {f2lsvg_process_arc(job, drw, psvg, obj, ec); } } break; case DK3_FIG_OBJ_PSEUDO_HALF_CIRCLE: { #line 2516 "f2lsvg.ctr" if(op) {f2lsvg_process_half_circle(job, drw, psvg, obj, ec); } } break; } #line 2520 "f2lsvg.ctr" } /** Check whether we must use a g instruction to group the object with its arrowheads. @param job Job structure. @param obj Current object to process. @return 1 to group, 0 for no group. */ static int f2lsvg_check_must_group(f2l_job_t *job, dk3_fig_obj_t *obj) { int back = 0; #line 2536 "f2lsvg.ctr" if(job->group) { #line 2537 "f2lsvg.ctr" if(obj->af) { #line 2538 "f2lsvg.ctr" if((obj->af)->o1) { #line 2539 "f2lsvg.ctr" back = 1; } if((obj->af)->o2) { #line 2542 "f2lsvg.ctr" back = 1; } } if(obj->ab) { #line 2546 "f2lsvg.ctr" if((obj->ab)->o1) { #line 2547 "f2lsvg.ctr" back = 1; } if((obj->ab)->o2) { #line 2550 "f2lsvg.ctr" back = 1; } } } #line 2554 "f2lsvg.ctr" return back; } /** Process object and arrowheads. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ static void f2lsvg_process_object( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { f2l_svg_t *psvg; /* SVG style collection. */ int mg; /* Flag: Must group */ int mec = 0; /* Mathematical error code. */ #line 2577 "f2lsvg.ctr" psvg = (f2l_svg_t *)(drw->dsd); mg = f2lsvg_check_must_group(job, obj); /* Process object itself. */ if(mg) { fputs(f2lsvg_c8_kw[6], job->of1); f2lsvg_tag_name(job, 35); fputs(f2lsvg_c8_kw[5], job->of1); } #line 2588 "f2lsvg.ctr" f2lsvg_process_one(job, drw, psvg, obj, 1, &mec); /* Process arrowheads. */ if(obj->af) { #line 2593 "f2lsvg.ctr" if((obj->af)->o1) { #line 2594 "f2lsvg.ctr" f2lsvg_process_one(job,drw,psvg,(dk3_fig_obj_t *)((obj->af)->o1),0,&mec); } if((obj->af)->o2) { #line 2597 "f2lsvg.ctr" f2lsvg_process_one(job,drw,psvg,(dk3_fig_obj_t *)((obj->af)->o2),0,&mec); } #line 2599 "f2lsvg.ctr" } if(obj->ab) { #line 2601 "f2lsvg.ctr" if((obj->ab)->o1) { #line 2602 "f2lsvg.ctr" f2lsvg_process_one(job,drw,psvg,(dk3_fig_obj_t *)((obj->ab)->o1),0,&mec); } if((obj->ab)->o2) { #line 2605 "f2lsvg.ctr" f2lsvg_process_one(job,drw,psvg,(dk3_fig_obj_t *)((obj->ab)->o2),0,&mec); } #line 2607 "f2lsvg.ctr" } #line 2609 "f2lsvg.ctr" if(mg) { fputs(f2lsvg_c8_kw[6], job->of1); fputs(f2lsvg_c8_kw[8], job->of1); f2lsvg_tag_name(job, 35); fputs(f2lsvg_c8_kw[5], job->of1); } if(mec) { /* ERROR: Mathematical error occured. */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 38); job->exval = FIG2LAT_EXIT_ERROR_MATH; #line 2619 "f2lsvg.ctr" } #line 2621 "f2lsvg.ctr" } void f2lsvg_output(f2l_job_t *job) { dk3_fig_drawing_t *drw; dk3_fig_obj_t *obj; unsigned long objno = 0UL; unsigned long oldsrcline = 0UL; #line 2633 "f2lsvg.ctr" oldsrcline = dk3app_get_source_line(job->app); dk3app_set_source_line(job->app, 0UL); drw = job->drw; objno = 0UL; if(f2lsvg_driver_initialize(job, drw)) { if(f2lsvg_open_output_files(job)) { if(f2lsvg_start_processing(job, drw)) { dk3sto_it_reset(drw->iobj); while(NULL != (obj = (dk3_fig_obj_t *)dk3sto_it_next(drw->iobj))) { dk3app_set_source_line(job->app, obj->li); if(!dk3fig_tool_is_bgrect(obj, objno)) { f2lsvg_process_object(job, drw, obj); } objno++; } } else { f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_UNKNOWN); #line 2649 "f2lsvg.ctr" } f2lsvg_end_processing(job, drw); } else { f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_UNKNOWN); #line 2653 "f2lsvg.ctr" } f2lsvg_close_output_files(job); } else { f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_UNKNOWN); #line 2657 "f2lsvg.ctr" } dk3app_set_source_line(job->app, oldsrcline); #line 2660 "f2lsvg.ctr" f2lsvg_driver_end(job, drw); }