%% options copyright owner = Dirk Krause copyright year = 2012-2014 license = bsd %% header #ifdef __cplusplus extern "C" { #endif /** Produce output. @param job Job structure. */ void f2lud_output(f2l_job_t *job); /** Issue "newpath" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ void f2lud_newpath( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ); /** Issue "moveto" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param x New point x in output space. @param y New point y in output space. */ void f2lud_moveto( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, double x, double y ); /** Issue "lineto" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param x New point x in output space. @param y New point y in output space. */ void f2lud_lineto( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, double x, double y ); /** Issue "curveto" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param xcs Control point at start x in output space. @param ycs Control point at start y in output space. @param xce Control point at end x in output space. @param yce Control point at end y in output space. @param xe End point x in output space. @param ye End point y in output space. */ void f2lud_curveto( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, double xcs, double ycs, double xce, double yce, double xe, double ye ); /** Issue "moveto" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param x New point x in Fig space. @param y New point y in Fig space. @param ec Pointer to error code variable, may be NULL. */ void f2lud_fig_moveto( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, double x, double y, int *ec ); /** Issue "lineto" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param x New point x in Fig space. @param y New point y in Fig space. @param ec Pointer to error code variable, may be NULL. */ void f2lud_fig_lineto( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, double x, double y, int *ec ); /** Issue "curveto" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param xcs Control point at start x in Fig space. @param ycs Control point at start y in Fig space. @param xce Control point at end x in Fig space. @param yce Control point at end y in Fig space. @param xe End point x in Fig space. @param ye End point y in Fig space. @param ec Pointer to error code variable, may be NULL. */ void f2lud_fig_curveto( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, double xcs, double ycs, double xce, double yce, double xe, double ye, int *ec ); /** Issue "closepath" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ void f2lud_closepath( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ); /** Issue "stroke" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ void f2lud_stroke( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ); /** Issue "fill" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ void f2lud_fill( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ); /** Check whether a spline object is an interpolated spline (only s=-1 and/or s=0 points). @param obj Object to check. @return 1 for pure interpolated spline, 0 otherwise. */ int f2lud_is_interpolated_spline(dk3_fig_obj_t *obj); #ifdef __cplusplus } #endif %% module #include "dk3all.h" #include "dk3bezcu.h" #include "fig2lat.h" #include "dk3xsp.h" #include "f2lud.h" #include "f2lsvg.h" #include "f2lpgf.h" #include "f2lpdf.h" #include "f2leps.h" #include "dk3figto.h" #include "dkt-version.h" #include "f2ludpat.h" #include "f2lpara.h" $!trace-include /** Keywords used by the module. */ static char const * const f2lud_c8_kw[] = { $!string-table # # 0: Debug message. # fig object begin %lu, line %lu, type %ld %ld, layer %d # # 1: Debug message. # fig object end %lu # # 2 # arrowhead forward begin, type=%d, fill=%d, length=%lg, width=%lg # # 3 # arrowhead forward end # # 4 # arrowhead backward begin, type=%d, fill=%d, length=%lg, width=%lg # # 5 # arrowhead backward end # # 6 # path object begin, type %ld %ld # # 7 # path object end $!end }; /** Write debug line to output file. @param job Job structure. @param msg Text line without newline at end. */ static void f2lud_debug( f2l_job_t *job, char const *msg ) { switch(job->dr) { case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_debug(job, msg); } break; case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_debug(job, msg); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_debug(job, msg); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_debug(job, msg); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_debug(job, msg); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_debug(job, msg); } break; } } /** Calculate factors for coordinates transformations. @param job Job structure. @param drw Drawing structure. @return 1 on success, 0 on error. */ static int f2lud_coordinates_transformation(f2l_job_t *job, dk3_fig_drawing_t *drw) { double xmin; /* Minimum x in output space. */ double xmax; /* Maximum x in output space. */ double ymin; /* Minimum y in output space. */ double ymax; /* Maximum y in output space. */ double xdelta; /* Used width in output space. */ double ydelta; /* Used height in output space. */ double width; /* Bounding box width in output space. */ double height; /* Bounding box height in output space. */ int mec = 0; /* Mathematical error code. */ int back = 1; $? "+ f2lud_coordinates_transformation" (job->ct2d).mx = dk3ma_d_div_ok( 72.0, drw->res, &mec); (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); ymax = dk3ma_d_mul_ok((job->ct2d).my, (drw->bb).ymin, &mec); ymin = dk3ma_d_mul_ok((job->ct2d).my, (drw->bb).ymax, &mec); xdelta = dk3ma_d_sub_ok(xmax, xmin, &mec); ydelta = dk3ma_d_sub_ok(ymax, ymin, &mec); job->width = width = ceil(xdelta); job->height = height = ceil(ydelta); job->lwidth = dk3ma_d_to_l_ok(width, &mec); job->lheight = dk3ma_d_to_l_ok(height, &mec); (job->ct2d).nx = 0.5 * dk3ma_d_sub_ok(width, xdelta, &mec); (job->ct2d).ny = 0.5 * dk3ma_d_sub_ok(height, ydelta, &mec); (job->ct2d).nx = dk3ma_d_sub_ok((job->ct2d).nx, xmin, &mec); (job->ct2d).ny = dk3ma_d_sub_ok((job->ct2d).ny, ymin, &mec); $? ". mx=%lg nx=%lg my=%lg ny=%lg", (job->ct2d).mx, (job->ct2d).nx, (job->ct2d).my, (job->ct2d).ny $? ". bb=%ld %ld (%lg %lg)", job->lwidth, job->lheight, (job->width) / 72.0, (job->height / 72.0) if(mec) { back = 0; /* ERROR: Math problem */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 35); f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH); $? ". exitcode" } $? "- f2lud_coordinates_transformation" return back; } /** Driver-specific initialization. @param job Job structure. @param drw Drawing structure. @return 1 on success, 0 on error. */ static int f2lud_driver_initialize(f2l_job_t *job, dk3_fig_drawing_t *drw) { int back; $? "+ f2lud_driver_initialize" back = f2lud_coordinates_transformation(job, drw); if(back) { switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { back = f2lpgf_tex_initialize(job, drw); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { back = f2lpdf_tex_with_pdf_initialize(job, drw); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { back = f2lpdf_pdf_with_tex_initialize(job, drw); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { back = f2leps_eps_with_tex_initialize(job, drw); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { back = f2leps_eps_pure_initialize(job, drw); } break; /* @DRIVER@ universal */ default: { /* PGF */ back = f2lpgf_pgf_initialize(job, drw); } break; } } $? "- f2lud_driver_initialize %d", back return back; } /** Release resources allocated by f2lud_driver_initialize(). @param job Job structure. @param drw Drawing structure. */ static void f2lud_driver_end(f2l_job_t *job, dk3_fig_drawing_t *drw) { $? "+ f2lud_driver_end" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_end(job, drw); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_end(job, drw); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_end(job, drw); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_end(job, drw); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_end(job, drw); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_end(job, drw); } break; } $? "- f2lud_driver_end" } /** Open output files. @param job Job structure. @return 1 on success, 0 on error. */ static int f2lud_open_output_files(f2l_job_t *job) { int back = 0; $? "+ f2lud_open_output_files" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { back = f2lpgf_tex_open_output_files(job); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { back = f2lpdf_tex_with_pdf_open_output_files(job); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { back = f2lpdf_pdf_with_tex_open_output_files(job); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { back = f2leps_eps_with_tex_open_output_files(job); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { back = f2leps_eps_pure_open_output_files(job); } break; /* @DRIVER@ universal */ default: { /* PGF */ back = f2lpgf_pgf_open_output_files(job); } break; } $? "- f2lud_open_output_files %d", back return back; } /** Close output files. @param job Job structure. */ static void f2lud_close_output_files(f2l_job_t *job) { $? "+ f2lud_close_output_files" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_close_output_files(job); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_close_output_files(job); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_close_output_files(job); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_close_output_files(job); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_close_output_files(job); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_close_output_files(job); } break; } $? "- f2lud_close_output_files" } /** Write start of output. @param job Job structure. @param drw Drawing structure. @return 1 on success, 0 on error. */ static int f2lud_start_processing(f2l_job_t *job, dk3_fig_drawing_t *drw) { int back = 0; $? "+ f2lud_start_processing" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { back = f2lpgf_tex_start_processing(job, drw); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { back = f2lpdf_tex_with_pdf_start_processing(job, drw); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { back = f2lpdf_pdf_with_tex_start_processing(job, drw); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { back = f2leps_eps_with_tex_start_processing(job, drw); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { back = f2leps_eps_pure_start_processing(job, drw); } break; /* @DRIVER@ universal */ default: { /* PGF */ back = f2lpgf_pgf_start_processing(job, drw); } break; } $? "- f2lud_start_processing %d", back return back; } /** Write end of output. @param job Job structure. @param drw Drawing structure. */ static void f2lud_end_processing(f2l_job_t *job, dk3_fig_drawing_t *drw) { $? "+ f2lud_end_processing" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_end_processing(job, drw); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_end_processing(job, drw); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_end_processing(job, drw); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_end_processing(job, drw); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_end_processing(job, drw); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_end_processing(job, drw); } break; } $? "- f2lud_end_processing" } /** Process one text object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ static void f2lud_text_object( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { double x; /* X position of text object. */ double y; /* Y position of text object. */ int ec = 0; /* Mathematical error code. */ $? "+ f2lud_text_object" if(!(DK3_FIG_FONT_FLAG_HIDDEN & ((obj->dt).txt.ff))) { x = dk3ct_2d_x(&(job->ct2d), (obj->dt).txt.x, &ec); y = dk3ct_2d_y(&(job->ct2d), (obj->dt).txt.y, &ec); switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_text_object(job, drw, obj, x, y); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_text_object(job, drw, obj, x, y); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_text_object(job, drw, obj, x, y); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_text_object(job, drw, obj, x, y); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_text_object(job, drw, obj, x, y); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_text_object(job, drw, obj, x, y); } break; } } if(ec) { /* ERROR: Math problem! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 35); f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH); $? ". exitcode" } $? "- f2lud_text_object" } /** Find bounding box for output coordinates. @param bb Bounding box to set up. @param job Job structure. @param drw Drawing structure. @param obj Polygon/polyline object. @param ec Pointer to error code variable. */ static void f2lud_find_bounding_box( dk3_bb_t *bb, f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int *ec ) { dk3_fig_poly_point_t *po; /* Current point. */ size_t np; /* Number of points. */ size_t i; /* Index of current point. */ $? "+ f2lud_find_bounding_box" po = (obj->dt).pol.po; np = (obj->dt).pol.np; dk3bb_reset(bb); for(i = 0; i < np; i++) { dk3bb_add_x(bb, dk3ct_2d_x(&(job->ct2d), po->x, ec)); dk3bb_add_y(bb, dk3ct_2d_y(&(job->ct2d), po->y, ec)); po++; } $? "- f2lud_find_bounding_box" } /** Process one image object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ static void f2lud_image_object( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { dk3_bb_t outbb; /* Image bounding box in output space. */ int ec = 0; /* Error code variable. */ int drawdir = 0; /* Drawing direction for embedded image. */ $? "+ f2lud_image_object" dk3bb_reset(&outbb); f2lud_find_bounding_box(&outbb, job, drw, obj, &ec); drawdir = f2lto_find_draw_direction(job, drw, obj, &ec); switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_image_object(job, drw, obj, &outbb, drawdir, &ec); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_image_object(job, drw, obj, &outbb, drawdir, &ec); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_image_object(job, drw, obj, &outbb, drawdir, &ec); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_image_object(job, drw, obj, &outbb, drawdir, &ec); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_image_object(job, drw, obj, &outbb, drawdir, &ec); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_image_object(job, drw, obj, &outbb, drawdir, &ec); } break; } if(ec) { /* ERROR: Math error! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 35); f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH); $? ". exitcode" } $? "- f2lud_image_object" } void f2lud_newpath( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { $? "+ f2lud_newpath" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_newpath(job, drw, obj); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_newpath(job, drw, obj); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_newpath(job, drw, obj); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_newpath(job, drw, obj); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_newpath(job, drw, obj); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_newpath(job, drw, obj); } break; } $? "- f2lud_newpath" } void f2lud_moveto( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, double x, double y ) { $? "+ f2lud_moveto %lg %lg", x, y switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_moveto(job, drw, obj, x, y); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_moveto(job, drw, obj, x, y); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_moveto(job, drw, obj, x, y); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_moveto(job, drw, obj, x, y); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_moveto(job, drw, obj, x, y); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_moveto(job, drw, obj, x, y); } break; } $? "- f2lud_moveto" } void f2lud_lineto( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, double x, double y ) { $? "+ f2lud_lineto %lg %lg", x, y switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_lineto(job, drw, obj, x, y); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_lineto(job, drw, obj, x, y); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_lineto(job, drw, obj, x, y); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_lineto(job, drw, obj, x, y); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_lineto(job, drw, obj, x, y); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_lineto(job, drw, obj, x, y); } break; } $? "- f2lud_lineto" } void f2lud_curveto( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, double xcs, double ycs, double xce, double yce, double xe, double ye ) { $? "+ f2lud_curveto %lg %lg %lg %lg %lg %lg", xcs, ycs, xce, yce, xe, ye switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_curveto(job, drw, obj, xcs, ycs, xce, yce, xe, ye); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_curveto(job, drw, obj, xcs, ycs, xce, yce, xe, ye); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_curveto(job, drw, obj, xcs, ycs, xce, yce, xe, ye); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_curveto(job, drw, obj, xcs, ycs, xce, yce, xe, ye); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_curveto(job, drw, obj, xcs, ycs, xce, yce, xe, ye); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_curveto(job, drw, obj, xcs, ycs, xce, yce, xe, ye); } break; } $? "- f2lud_curveto" } void f2lud_fig_moveto( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, double x, double y, int *ec ) { double nx; /* Destination x in output space. */ double ny; /* Destination y in output space. */ $? "+ f2lud_fig_moveto %lg %lg", x, y nx = dk3ct_2d_x(&(job->ct2d), x, ec); ny = dk3ct_2d_y(&(job->ct2d), y, ec); f2lud_moveto(job, drw, obj, nx, ny); $? "- f2lud_fig_moveto" } void f2lud_fig_lineto( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, double x, double y, int *ec ) { double nx; /* Destination x in output space. */ double ny; /* Destination y in output space. */ $? "+ f2lud_fig_lineto %lg %lg", x, y nx = dk3ct_2d_x(&(job->ct2d), x, ec); ny = dk3ct_2d_y(&(job->ct2d), y, ec); f2lud_lineto(job, drw, obj, nx, ny); $? "- f2lud_fig_lineto" } void f2lud_fig_curveto( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, double xcs, double ycs, double xce, double yce, double xe, double ye, int *ec ) { double nxcs; /* First control point x in output space. */ double nycs; /* First control point y in output space. */ double nxce; /* Second control point x in output space. */ double nyce; /* Second control point y in output space. */ double nxe; /* End point x in output space. */ double nye; /* End point y in output space. */ $? "+ f2lud_fig_curveto %lg %lg %lg %lg %lg %lg", xcs, ycs, xce, yce, xe, ye nxcs = dk3ct_2d_x(&(job->ct2d), xcs, ec); nycs = dk3ct_2d_y(&(job->ct2d), ycs, ec); nxce = dk3ct_2d_x(&(job->ct2d), xce, ec); nyce = dk3ct_2d_y(&(job->ct2d), yce, ec); nxe = dk3ct_2d_x(&(job->ct2d), xe, ec); nye = dk3ct_2d_y(&(job->ct2d), ye, ec); f2lud_curveto(job, drw, obj, nxcs, nycs, nxce, nyce, nxe, nye); $? "- f2lud_fig_curveto" } void f2lud_closepath( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { $? "+ f2lud_closepath" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_closepath(job, drw, obj); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_closepath(job, drw, obj); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_closepath(job, drw, obj); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_closepath(job, drw, obj); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_closepath(job, drw, obj); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_closepath(job, drw, obj); } break; } $? "- f2lud_closepath" } /** Issue "fill" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ void f2lud_fill( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { $? "+ f2lud_fill" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_fill(job, drw, obj); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_fill(job, drw, obj); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_fill(job, drw, obj); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_fill(job, drw, obj); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_fill(job, drw, obj); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_fill(job, drw, obj); } break; } $? "- f2lud_fill" } /** Issue combined "fill" and "clip" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ static void f2lud_fill_clip( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { $? "+ f2lud_fill_clip" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_fill_clip(job, drw, obj); } break; case FIG2LAT_DRIVER_PGF: { f2lpgf_pgf_fill_clip(job, drw, obj); } break; /* @DRIVER@ universal */ } $? "- f2lud_fill_clip" } /** Issue combined "fill", "stroke", and "clip" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ static void f2lud_fill_stroke_clip( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { $? "+ f2lud_fill_clip" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_fill_stroke_clip(job, drw, obj); } break; case FIG2LAT_DRIVER_PGF: { f2lpgf_pgf_fill_stroke_clip(job, drw, obj); } break; /* @DRIVER@ universal */ } $? "- f2lud_fill_clip" } /** Issue combined "fill" and "stroke" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ static void f2lud_fill_stroke( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { $? "+ f2lud_fill_stroke" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_fill_stroke(job, drw, obj); } break; case FIG2LAT_DRIVER_PGF: { f2lpgf_pgf_fill_stroke(job, drw, obj); } break; /* @DRIVER@ universal */ } $? "- f2lud_fill_stroke" } void f2lud_stroke( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { $? "+ f2lud_stroke" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_stroke(job, drw, obj); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_stroke(job, drw, obj); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_stroke(job, drw, obj); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_stroke(job, drw, obj); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_stroke(job, drw, obj); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_stroke(job, drw, obj); } break; } $? "- f2lud_stroke" } /** Issue "clip" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ static void f2lud_clip( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { $? "+ f2lud_clip" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_clip(job, drw, obj); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_clip(job, drw, obj); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_clip(job, drw, obj); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_clip(job, drw, obj); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_clip(job, drw, obj); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_clip(job, drw, obj); } break; } $? "- f2lud_clip" } /** Issue "gsave" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ static void f2lud_gsave( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { $? "+ f2lud_gsave" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_gsave(job, drw, obj); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_gsave(job, drw, obj); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_gsave(job, drw, obj); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_gsave(job, drw, obj); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_gsave(job, drw, obj); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_gsave(job, drw, obj); } break; } $? "- f2lud_gsave" } /** Issue "grestore" command. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ static void f2lud_grestore( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { $? "+ f2lud_grestore" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_grestore(job, drw, obj); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_grestore(job, drw, obj); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_grestore(job, drw, obj); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_grestore(job, drw, obj); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_grestore(job, drw, obj); } break; /* @DRIVER@ universal */ default: { /* PGF */ f2lpgf_pgf_grestore(job, drw, obj); } break; } $? "- f2lud_grestore" } /** Create path for ellipse object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param ec Pointe to error code variable, may be NULL. */ static void f2lud_create_ellipse_path( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int *ec ) { dk3_fig_poly_point_t po[12]; /* Points in Fig space. */ double myan; /* Rotation angle in Fig space. */ size_t i; /* Index of current point to modify. */ $? "+ f2lud_create_ellipse_path" po[0].x = (obj->dt).ell.rx; po[0].y = 0.0; po[1].x = (obj->dt).ell.rx; po[1].y = FIG2LAT_CIRCLE_QUADRANT_BEZIER * (obj->dt).ell.ry; po[2].x = FIG2LAT_CIRCLE_QUADRANT_BEZIER * (obj->dt).ell.rx; po[2].y = (obj->dt).ell.ry; po[3].x = 0.0; po[3].y = (obj->dt).ell.ry; po[4].x = 0.0 - po[2].x; po[4].y = po[2].y; po[5].x = 0.0 - po[1].x; po[5].y = po[1].y; po[6].x = 0.0 - po[0].x; po[6].y = 0.0; po[7].x = po[6].x; po[7].y = 0.0 - po[5].y; po[8].x = po[4].x; po[8].y = 0.0 - po[2].y; po[9].x = 0.0; po[9].y = 0.0 - po[3].y; po[10].x = po[2].x; po[10].y = po[9].y; po[11].x = po[1].x; po[11].y = po[7].y; switch(obj->st) { case 1: case 2: { if(1.0e-6 < fabs((obj->dt).ell.an)) { if(1.0e-6 < fabs(dk3ma_d_sub_ok((obj->dt).ell.rx,(obj->dt).ell.ry,ec))) { myan = -1.0 * (obj->dt).ell.an; for(i = 0; i < 12; i++) { dk3fig_tool_rotate_point(&(po[i]), myan, ec); } } } } break; } for(i = 0; i < 12; i++) { dk3fig_tool_shift_point(&(po[i]), (obj->dt).ell.cx, (obj->dt).ell.cy, ec); } f2lud_fig_moveto(job, drw, obj, po[0].x, po[0].y, ec); f2lud_fig_curveto( job, drw, obj, po[1].x, po[1].y, po[2].x, po[2].y, po[3].x, po[3].y, ec ); f2lud_fig_curveto( job, drw, obj, po[4].x, po[4].y, po[5].x, po[5].y, po[6].x, po[6].y, ec ); f2lud_fig_curveto( job, drw, obj, po[7].x, po[7].y, po[8].x, po[8].y, po[9].x, po[9].y, ec ); f2lud_fig_curveto( job, drw, obj, po[10].x, po[10].y, po[11].x, po[11].y, po[0].x, po[0].y, ec ); $? "- f2lud_create_ellipse_path" } /** Create path for polygon object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param ec Pointe to error code variable, may be NULL. */ static void f2lud_create_polygon_path( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int *ec ) { dk3_fig_poly_point_t *po; /* Current point to process. */ size_t np; /* Number of points. */ size_t i; /* Index of current point. */ $? "+ f2lud_create_polygon_path" po = (obj->dt).pol.po; np = (obj->dt).pol.np; for(i = 0; i < np; i++) { if(0 == i) { f2lud_fig_moveto(job, drw, obj, po->x, po->y, ec); } else { f2lud_fig_lineto(job, drw, obj, po->x, po->y, ec); } po++; } if(obj->cl) { po = (obj->dt).pol.po; f2lud_fig_lineto(job, drw, obj, po->x, po->y, ec); } $? "- f2lud_create_polygon_path" } /** Create path for box object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param ec Pointe to error code variable, may be NULL. */ static void f2lud_create_box_path( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int *ec ) { dk3_bb_t outbb; /* Box coordinates in output space. */ $? "+ f2lud_create_box_path" dk3bb_reset(&outbb); f2lud_find_bounding_box(&outbb, job, drw, obj, ec); f2lud_moveto(job, drw, obj, outbb.xmin, outbb.ymin); f2lud_lineto(job, drw, obj, outbb.xmax, outbb.ymin); f2lud_lineto(job, drw, obj, outbb.xmax, outbb.ymax); f2lud_lineto(job, drw, obj, outbb.xmin, outbb.ymax); f2lud_lineto(job, drw, obj, outbb.xmin, outbb.ymin); $? "- f2lud_create_box_path" } /** Create path for arc box object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param ec Pointe to error code variable, may be NULL. */ static void f2lud_create_arc_box_path( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int *ec ) { dk3_fig_poly_point_t po[16]; /* Box points in output space. */ dk3_bb_t outbb; /* Box coordinates in output space. */ double r; /* Corner radius in output space. */ double maxr; /* Maximum value for corner radius. */ double corner; /* Factor control to end. */ double rc; /* Dist of control to end in output space. */ $? "+ f2lud_create_arc_box_path" dk3bb_reset(&outbb); f2lud_find_bounding_box(&outbb, job, drw, obj, ec); #if VERSION_BEFORE_20140808 r = dk3ct_2d_r(&(job->ct2d), (obj->dt).pol.ra, ec); $? ". r=%lg", r #else r = 0.9 * (obj->dt).pol.ra; $? ". r=%lg", r #endif maxr = 0.49 * fabs(dk3ma_d_sub_ok(outbb.xmax, outbb.xmin, ec)); if(r > maxr) r = maxr; maxr = 0.49 * fabs(dk3ma_d_sub_ok(outbb.ymax, outbb.ymin, ec)); if(r > maxr) r = maxr; corner = 1.0 - FIG2LAT_CIRCLE_QUADRANT_BEZIER; rc = r * corner; /* Bottom line */ po[0].x = dk3ma_d_add_ok(outbb.xmin, r, ec); po[0].y = outbb.ymin; po[1].x = dk3ma_d_sub_ok(outbb.xmax, r, ec); po[1].y = po[0].y; /* Lower right corner control points */ po[2].x = dk3ma_d_sub_ok(outbb.xmax, rc, ec); po[2].y = po[0].y; po[3].x = outbb.xmax; po[3].y = dk3ma_d_add_ok(outbb.ymin, rc, ec); /* Right line */ po[4].x = outbb.xmax; po[4].y = dk3ma_d_add_ok(outbb.ymin, r, ec); po[5].x = outbb.xmax; po[5].y = dk3ma_d_sub_ok(outbb.ymax, r, ec); /* Upper right corner control points */ po[6].x = outbb.xmax; po[6].y = dk3ma_d_sub_ok(outbb.ymax, rc, ec); po[7].x = dk3ma_d_sub_ok(outbb.xmax, rc, ec); po[7].y = outbb.ymax; /* Top line */ po[8].x = dk3ma_d_sub_ok(outbb.xmax, r, ec); po[8].y = outbb.ymax; po[9].x = dk3ma_d_add_ok(outbb.xmin, r, ec); po[9].y = outbb.ymax; /* Upper left corner control points */ po[10].x = dk3ma_d_add_ok(outbb.xmin, rc, ec); po[10].y = outbb.ymax; po[11].x = outbb.xmin; po[11].y = dk3ma_d_sub_ok(outbb.ymax, rc, ec); /* Left line */ po[12].x = outbb.xmin; po[12].y = dk3ma_d_sub_ok(outbb.ymax, r, ec); po[13].x = outbb.xmin; po[13].y = dk3ma_d_add_ok(outbb.ymin, r, ec); /* Lower left corner control points */ po[14].x = outbb.xmin; po[14].y = dk3ma_d_add_ok(outbb.ymin, rc, ec); po[15].x = dk3ma_d_add_ok(outbb.xmin, rc, ec); po[15].y = outbb.ymin; f2lud_moveto(job, drw, obj, po[0].x, po[0].y); f2lud_lineto(job, drw, obj, po[1].x, po[1].y); f2lud_curveto( job, drw, obj, po[2].x, po[2].y, po[3].x, po[3].y, po[4].x, po[4].y ); f2lud_lineto(job, drw, obj, po[5].x, po[5].y); f2lud_curveto( job, drw, obj, po[6].x, po[6].y, po[7].x, po[7].y, po[8].x, po[8].y ); f2lud_lineto(job, drw, obj, po[9].x, po[9].y); f2lud_curveto( job, drw, obj, po[10].x, po[10].y, po[11].x, po[11].y, po[12].x, po[12].y ); f2lud_lineto(job, drw, obj, po[13].x, po[13].y); f2lud_curveto( job, drw, obj, po[14].x, po[14].y, po[15].x, po[15].y, po[0].x, po[0].y ); $? "- f2lud_create_arc_box_path" } /** 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 f2lud_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. */ $? "+ f2lud_final_spline_segment %lg", te myte = dk3ma_d_sub_ok(te, floor(te), ec); $? ". myte = %lg", myte dnumsegs = myte * dk3fig_tool_xssbs(drw, primary); dnumsegs = ceil(dnumsegs); $? ". dnumsegs = %lg", dnumsegs nsegs = dk3ma_d_to_sz_ok(dnumsegs, ec); $? ". nsegs = %u", (unsigned)nsegs 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; $? ". factor = %lg", factor 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) { f2lud_fig_moveto(job, drw, obj, lastx, lasty, ec); } /* Further curve only if te > 1.0e-6. For smaller te draw straight line. */ if(1.0e-6 < myte) { $? ". segments size ok" for(iseg = 0; iseg < nsegs; iseg++) { if(iseg < (nsegs - 1)) { $? ". not last sub-segment" t = (double)(iseg + 1) / (double)nsegs; t = t * myte; } else { $? ". last sub-segment" t = myte; } $? ". t = %lg", t 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; f2lud_fig_curveto( job, drw, obj, dk3ma_d_add_ok(lastx, lastdxdt, ec), dk3ma_d_add_ok(lasty, lastdydt, ec), dk3ma_d_sub_ok(x, dxdt, ec), dk3ma_d_sub_ok(y, dydt, ec), x, y, ec ); lastx = x; lasty = y; lastdxdt = dxdt; lastdydt = dydt; } } else { $? ". very small segment" 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); $? ". exitcode" } x = dk3xsp_get_x(&seg); y = dk3xsp_get_y(&seg); f2lud_fig_lineto(job, drw, obj, x, y, ec); } } else { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH); $? ". exitcode" } $? "- f2lud_final_spline_segment" } /** 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 f2lud_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. */ $? "+ f2lud_first_spline_segment ts=%lg", ts myts = dk3ma_d_sub_ok(ts, floor(ts), ec); $? ". myts = %lg", myts dnumsegs = (1.0 - myts) * dk3fig_tool_xssbs(drw, primary); dnumsegs = ceil(dnumsegs); $? ". dnumsegs = %lg", dnumsegs nsegs = dk3ma_d_to_sz_ok(dnumsegs, ec); $? ". nsegs = %u", (unsigned)nsegs 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; $? ". factor = %lg", factor 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) { f2lud_fig_moveto(job, drw, obj, lastx, 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; f2lud_fig_curveto( job, drw, obj, dk3ma_d_add_ok(lastx, lastdxdt, ec), dk3ma_d_add_ok(lasty, lastdydt, ec), dk3ma_d_sub_ok(x, dxdt, ec), dk3ma_d_sub_ok(y, dydt, ec), x, y, ec ); lastx = x; lasty = y; lastdxdt = dxdt; lastdydt = dydt; } } 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); $? ". exitcode" } x = dk3xsp_get_x(&seg); y = dk3xsp_get_y(&seg); f2lud_fig_lineto(job, drw, obj, x, y, ec); } } else { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH); $? ". exitcode" } $? "- f2lud_first_spline_segment" } /** 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 f2lud_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. */ $? "+ f2lud_single_spline_segment" 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); $? ". dnumsegs = %lg", dnumsegs nsegs = dk3ma_d_to_sz_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) { f2lud_fig_moveto(job, drw, obj, lastx, 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; f2lud_fig_curveto( job, drw, obj, dk3ma_d_add_ok(lastx, lastdxdt, ec), dk3ma_d_add_ok(lasty, lastdydt, ec), dk3ma_d_sub_ok(x, dxdt, ec), dk3ma_d_sub_ok(y, dydt, ec), x, y, ec ); lastx = x; lasty = y; lastdxdt = dxdt; lastdydt = dydt; } } 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); $? ". exitcode" } x = dk3xsp_get_x(&seg); y = dk3xsp_get_y(&seg); f2lud_fig_lineto(job, drw, obj, x, 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); $? ". exitcode" } $? "- f2lud_single_spline_segment" } /** Create path for one complete 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 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 f2lud_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 i, 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 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 xsss; /* Number of segments. */ size_t iseg; /* Current segment. */ size_t ic; size_t id; int res; /* Calculation result. */ $? "+ f2lud_full_spline_segment %u", (unsigned)i if(i < ((iscl) ? np : (np - 1))) { pb = &(sp[i]); ic = i + 1; while(ic >= np) { ic = ic - np; } pc = &(sp[ic]); if(i > 0) { pa = &(sp[i - 1]); } else { if(iscl) { pa = &(sp[np - 1]); } } if(i < (np - 2)) { pd = &(sp[i + 2]); } else { if(iscl) { id = i + 2; while(id >= np) { id = id - np; } pd = &(sp[id]); } } xsss = dk3fig_tool_xssbs(drw, primary); factor = 1.0 / (double)xsss; 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; if(isfirst) { f2lud_fig_moveto(job, drw, obj, lastx, lasty, ec); } for(iseg = 0; iseg < xsss; iseg++) { if(iseg < (xsss - 1)) { t = (double)(iseg + 1) / (double)xsss; } 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; f2lud_fig_curveto( job, drw, obj, dk3ma_d_add_ok(lastx, lastdxdt, ec), dk3ma_d_add_ok(lasty, lastdydt, ec), dk3ma_d_sub_ok(x, dxdt, ec), dk3ma_d_sub_ok(y, dydt, ec), x, y, ec ); lastx = x; lasty = y; lastdxdt = dxdt; lastdydt = dydt; } } else { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } } } else { /* ERROR: BUG: Wrong i */ } $? "- f2lud_full_spline_segment %u", (unsigned)i } /** Create path for open spline object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param primary Flag: Primary object (1=object, 0=arrowhead). @param ec Pointe to error code variable, may be NULL. */ static void f2lud_create_open_spline_path( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int primary, int *ec ) { dk3_fig_spline_point_t *sp; /* Spline points. */ size_t np; /* Number of points. */ size_t i; /* Current segment index. */ size_t min; /* Minimum t value. */ size_t max; /* Maximum t value. */ $? "+ f2lud_create_open_spline_path" sp = (obj->dt).spl.po; np = (obj->dt).spl.np; if(job->coah) { $? ". compatible arrowheads" for(i = 0; i < (np - 1); i++) { f2lud_full_spline_segment( job, drw, obj, sp, np, i, ((0 == i) ? 1 : 0), 0, primary, ec ); } } else { $? ". shorten spline if necessary" if(obj->ab) { $? ". have backward arrow" /* 2013-11-23 ROUNDING DOWNWARDS INTENDED. We want to find the start segment. */ min = dk3ma_d_to_sz_ok(floor((obj->dt).spl.ts), ec); if(obj->af) { $? ". have forward arrow" if((obj->dt).spl.te >= (obj->dt).spl.ts) { $? ". te/ts ok" /* 2013-11-23 ROUNDING DOWNWARDS INTENDED. We want to find the last full segment to draw. */ max = dk3ma_d_to_sz_ok(floor((obj->dt).spl.te), ec); if(max > min) { $? ". start and end in different segments" f2lud_first_spline_segment( job, drw, obj, sp, np, min, (obj->dt).spl.ts, 1, 0, primary, ec ); /* 2012-12-04 Bugfix: Only to max. */ #if VERSION_BEFORE_20121204 for(i = (min + 1); i < (np - 1); i++) { f2lud_full_spline_segment( job, drw, obj, sp, np, i, 0, 0, primary, ec ); } #else for(i = (min + 1); i < max; i++) { f2lud_full_spline_segment( job, drw, obj, sp, np, i, 0, 0, primary, ec ); } #endif f2lud_final_spline_segment( job, drw, obj, sp, np, max, (obj->dt).spl.te, 0, 0, primary, ec ); } else { $? ". start and end in same segment" f2lud_single_spline_segment( job, drw, obj, sp, np, min, (obj->dt).spl.ts, (obj->dt).spl.te, 1, 0, primary, ec ); } } else { $? "! te=%lg < ts=%lg",(obj->dt).spl.te,(obj->dt).spl.ts /* ERROR: Arrowheads 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); $? ". exitcode" } } else { $? ". no forward arrow" f2lud_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++) { f2lud_full_spline_segment( job, drw, obj, sp, np, i, 0, 0, primary, ec ); } } } else { $? ". no backward arrow" if(obj->af) { $? ". forward arrow" /* 2013-11-23 ROUNDING DOWNWARDS INTENDED. We want to find the last full segment. */ max = dk3ma_d_to_sz_ok(floor((obj->dt).spl.te), ec); if(max < (np - 1)) { $? ". max ok" if(max > 0) { $? ". max ok" for(i = 0; i < max; i++) { f2lud_full_spline_segment( job, drw, obj, sp, np, i, ((0 == i) ? 1 : 0), 0, primary, ec ); } f2lud_final_spline_segment( job, drw, obj, sp, np, max, (obj->dt).spl.te, 0, 0, primary, ec ); } else { $? "! max too small" f2lud_final_spline_segment( job, drw, obj, sp, np, max, (obj->dt).spl.te, 1, 0, primary, ec ); } } else { $? "! max too large" /* 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); $? ". exitcode" } } else { $? ". no forward arrow" for(i = 0; i < (np - 1); i++) { f2lud_full_spline_segment( job, drw, obj, sp, np, i, ((0 == i) ? 1 : 0), 0, primary, ec ); } } } } $? "- f2lud_create_open_spline_path" } /** Create path for open spline object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param primary Flag: Primary object (1=object, 0=arrowhead). @param ec Pointe to error code variable, may be NULL. */ static void f2lud_create_open_fast_spline_path( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int primary, int *ec ) { dk3_fig_spline_point_t *po; size_t np; size_t ib; size_t ic; double dxdtb; double dydtb; double dxdtc; double dydtc; $? "+ f2lud_create_open_fast_spline_path" po = (obj->dt).spl.po; np = (obj->dt).spl.np; if (np > 1) { for (ib = 0; ib < (np - 1); ib++) { ic = ib + 1; if (0 == ib) { /* MOVETO */ f2lud_fig_moveto(job, drw, obj, po[ib].x, po[ib].y, ec); } if ((fabs(po[ib].s) < 1.0e-6) && (fabs(po[ic].s) < 1.0e-6)) { /* LINETO */ f2lud_fig_lineto(job, drw, obj, po[ic].x, po[ic].y, ec); } else { dxdtb = dxdtc = dk3ma_d_sub_ok(po[ic].x, po[ib].x, ec); dydtb = dydtc = dk3ma_d_sub_ok(po[ic].y, po[ib].y, ec); if ((0 < ib) && (fabs(1.0 + po[ib].s) < 1.0e-6)) { dxdtb = f2lpara_derived_center(po[ib-1].x, po[ib].x, po[ic].x, ec); dydtb = f2lpara_derived_center(po[ib-1].y, po[ib].y, po[ic].y, ec); } else { if ((ic < (np - 1)) && (fabs(1.0 + po[ic].s) < 1.0e-6)) { dxdtb = f2lpara_derived_left(po[ib].x, po[ic].x, po[ic+1].x, ec); dydtb = f2lpara_derived_left(po[ib].y, po[ic].y, po[ic+1].y, ec); } } if ((ic < (np - 1)) && (1.0 + fabs(po[ic].s) < 1.0e-6)) { dxdtc = f2lpara_derived_center(po[ib].x, po[ic].x, po[ic+1].x, ec); dydtc = f2lpara_derived_center(po[ib].y, po[ic].y, po[ic+1].y, ec); } else { if ((0 < ib) && (fabs(1.0 + po[ib].s) < 1.0e-6)) { dxdtc = f2lpara_derived_right(po[ib-1].x, po[ib].x, po[ic].x, ec); dydtc = f2lpara_derived_right(po[ib-1].y, po[ib].y, po[ic].y, ec); } } /* CURVETO */ f2lud_fig_curveto( job, drw, obj, dk3ma_d_add_ok(po[ib].x, (dxdtb / 3.0), ec), dk3ma_d_add_ok(po[ib].y, (dydtb / 3.0), ec), dk3ma_d_sub_ok(po[ic].x, (dxdtc / 3.0), ec), dk3ma_d_sub_ok(po[ic].y, (dydtc / 3.0), ec), po[ic].x, po[ic].y, ec ); } } } $? "- f2lud_create_open_fast_spline_path" } /** Create path for closed spline object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param primary Flag: Primary object (1=object, 0=arrowhead). @param ec Pointe to error code variable, may be NULL. */ static void f2lud_create_closed_spline_path( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int primary, int *ec ) { dk3_fig_spline_point_t *sp; /* Spline points. */ size_t np; /* Number of points. */ size_t i; /* Current segment index. */ $? "+ f2lud_create_closed_spline_path" sp = (obj->dt).spl.po; np = (obj->dt).spl.np; for(i = 0; i < np; i++) { f2lud_full_spline_segment( job, drw, obj, sp, np, i, ((0 == i) ? 1 : 0), 1, primary, ec ); } $? "- f2lud_create_closed_spline_path" } /** Create path for closed spline object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param primary Flag: Primary object (1=object, 0=arrowhead). @param ec Pointe to error code variable, may be NULL. */ static void f2lud_create_closed_fast_spline_path( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int primary, int *ec ) { dk3_fig_spline_point_t *po; size_t np; size_t ib; size_t ic; size_t ia; size_t id; double dxdtb; double dydtb; double dxdtc; double dydtc; $? "+ f2lud_create_closed_fast_spline_path" po = (obj->dt).spl.po; np = (obj->dt).spl.np; if (2 < np) { for (ib = 0; ib < np; ib++) { ic = ib + 1; id = ib + 2; if (ic >= np) { ic = ic - np; } if (id >= np) { id = id - np; } if (0 < ib) { ia = ib - 1; } else { ia = np - 1; } if (0 == ib) { /* MOVETO */ f2lud_fig_moveto(job, drw, obj, po[ib].x, po[ib].y, ec); } if ((fabs(po[ib].s) < 1.0e-6) && (fabs(po[ic].s) < 1.0e-6)) { /* LINETO */ f2lud_fig_lineto(job, drw, obj, po[ic].x, po[ic].y, ec); } else { dxdtb = dxdtc = dk3ma_d_sub_ok(po[ic].x, po[ib].x, ec); dydtb = dydtc = dk3ma_d_sub_ok(po[ic].y, po[ib].y, ec); if (fabs(1.0 + po[ib].s) < 1.0e-6) { dxdtb = f2lpara_derived_center(po[ia].x, po[ib].x, po[ic].x, ec); dydtb = f2lpara_derived_center(po[ia].y, po[ib].y, po[ic].y, ec); } else { if (fabs(1.0 + po[ic].s) < 1.0e-6) { dxdtb = f2lpara_derived_left(po[ib].x, po[ic].x, po[id].x, ec); dydtb = f2lpara_derived_left(po[ib].y, po[ic].y, po[id].y, ec); } } if (fabs(1.0 + po[ic].s) < 1.0e-6) { dxdtc = f2lpara_derived_center(po[ib].x, po[ic].x, po[id].x, ec); dydtc = f2lpara_derived_center(po[ib].y, po[ic].y, po[id].y, ec); } else { if (fabs(1.0 + po[ib].s) < 1.0e-6) { dxdtc = f2lpara_derived_right(po[ia].x, po[ib].x, po[ic].x, ec); dydtc = f2lpara_derived_right(po[ia].y, po[ib].y, po[ic].y, ec); } } /* CURVETO */ f2lud_fig_curveto( job, drw, obj, dk3ma_d_add_ok(po[ib].x, (dxdtb / 3.0), ec), dk3ma_d_add_ok(po[ib].y, (dydtb / 3.0), ec), dk3ma_d_sub_ok(po[ic].x, (dxdtc / 3.0), ec), dk3ma_d_sub_ok(po[ic].y, (dydtc / 3.0), ec), po[ic].x, po[ic].y, ec ); } } } $? "+ f2lud_create_closed_fast_spline_path" } /** Create path for open arc object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param iscl Flag: Closed arc. @param ec Pointe to error code variable, may be NULL. */ static void f2lud_create_arc_path( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int iscl, 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. */ $? "+ f2lud_create_open_arc_path" 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)); $? ". dnumsegs = %lg", dnumsegs nsegs = dk3ma_d_to_sz_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); f2lud_fig_moveto(job, drw, obj, lastx, 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 ); f2lud_fig_curveto( job, drw, obj, dk3ma_d_add_ok(lastx, lastkdxdt, ec), dk3ma_d_add_ok(lasty, lastkdydt, ec), dk3ma_d_sub_ok(x, kdxdt, ec), dk3ma_d_sub_ok(y, kdydt, ec), x, y, ec ); lastx = x; lasty = y; lastkdxdt = kdxdt; lastkdydt = kdydt; } /* For closed arc draw the lines. */ if(iscl) { f2lud_fig_lineto(job, drw, obj, cx, cy, ec); f2lud_fig_lineto(job, drw, obj, sx, sy, ec); } $? "- f2lud_create_open_arc_path" } /** Create path for half circle object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param ec Pointe to error code variable, may be NULL. */ static void f2lud_create_half_circle_path( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int *ec ) { dk3_fig_poly_point_t po[7]; /* Points to construct path. */ size_t i; /* Current point index */ $? "+ f2lud_create_half_circle_path" 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, ec); } } for(i = 0; i < 7; i++) { dk3fig_tool_shift_point(&(po[i]), (obj->dt).hci.cx, (obj->dt).hci.cy, ec); } f2lud_fig_moveto(job, drw, obj, po[0].x, po[0].y, ec); f2lud_fig_curveto( job, drw, obj, po[1].x, po[1].y, po[2].x, po[2].y, po[3].x, po[3].y, ec ); f2lud_fig_curveto( job, drw, obj, po[4].x, po[4].y, po[5].x, po[5].y, po[6].x, po[6].y, ec ); if(obj->st) { f2lud_fig_lineto(job, drw, obj, po[0].x, po[0].y, ec); } $? "- f2lud_create_half_circle_path" } /** Create path for object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param ec Pointe to error code variable, may be NULL. @param primary Flag: Primary object (1=object, 0=arrowhead). */ static void f2lud_create_path( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int primary, int *ec ) { $? "+ f2lud_create_path" switch(obj->ot) { case DK3_FIG_OBJ_ELLIPSE: { f2lud_create_ellipse_path(job, drw, obj, ec); } break; case DK3_FIG_OBJ_POLYLINE: { switch(obj->st) { case 1: { /* Polyline */ f2lud_create_polygon_path(job, drw, obj, ec); } break; case 2: { /* Box */ f2lud_create_box_path(job, drw, obj, ec); } break; case 3: { /* Polygon */ f2lud_create_polygon_path(job, drw, obj, ec); } break; case 4: { /* Arc-box */ f2lud_create_arc_box_path(job, drw, obj, ec); } break; } } break; case DK3_FIG_OBJ_SPLINE: { switch(obj->st) { case 0: case 2: case 4: { /* open spline */ f2lud_create_open_spline_path(job, drw, obj, primary, ec); } break; case 1: case 3: case 5: { /* closed spline */ f2lud_create_closed_spline_path(job, drw, obj, primary, ec); } break; } } break; case DK3_FIG_OBJ_ARC: { switch(obj->st) { case 1: { /* open arc */ f2lud_create_arc_path(job, drw, obj, 0, ec); } break; default: { /* closed arc */ f2lud_create_arc_path(job, drw, obj, 1, ec); } break; } } break; case DK3_FIG_OBJ_PSEUDO_HALF_CIRCLE: { f2lud_create_half_circle_path(job, drw, obj, ec); } break; case DK3_FIG_OBJ_PSEUDO_FAST_SPLINE: { switch(obj->st) { case 0: case 2: case 4: { /* open spline */ f2lud_create_open_fast_spline_path(job, drw, obj, primary, ec); } break; case 1: case 3: case 5: { /* closed spline */ f2lud_create_closed_fast_spline_path(job, drw, obj, primary, ec); } break; } } break; } $? "- f2lud_create_path" } /** Set color (stroke color for pdf/pgf). If we already have a color 1 equal to the new color the operation is skipped. @param job Conversion job structure. @param drw Drawing structure. @param colno Color number. @param fillstyle Fill style used in the object. Depending on the fillstyle it might be necessary to create a shade of the color. */ static void f2lud_set_color_1( f2l_job_t *job, dk3_fig_drawing_t *drw, int colno, int fillstyle ) { dk3_rgb_color_t rgb; /* Color structure to fill. */ int muc = 1; /* Flag: Must configure. */ #if 0 int ec = 0; /* Error code variable. */ #endif $? "+ f2lud_set_color_1" dk3fig_tool_find_color(&rgb, drw, colno, fillstyle); #if 0 if((job->gs).hc1) { if(1.0e-6 > fabs(dk3ma_d_sub_ok(rgb.r, (job->gs).c1.r, &ec))) { if(1.0e-6 > fabs(dk3ma_d_sub_ok(rgb.g, (job->gs).c1.g, &ec))) { if(1.0e-6 > fabs(dk3ma_d_sub_ok(rgb.b, (job->gs).c1.b, &ec))) { if(0 == ec) { muc = 0; } } } } } #else muc = dk3fig_tool_must_set_color( (job->gs).hc1, (job->gs).c1.r, (job->gs).c1.g, (job->gs).c1.b, rgb.r, rgb.g, rgb.b ); #endif if(muc) { switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_set_color_1(job, drw, &rgb); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_set_color_1(job, drw, &rgb); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_set_color_1(job, drw, &rgb); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_set_color_1(job, drw, &rgb); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_set_color_1(job, drw, &rgb); } break; /* @DRIVER@ universal */ default: { f2lpgf_pgf_set_color_1(job, drw, &rgb); } break; } (job->gs).c1.r = rgb.r; (job->gs).c1.g = rgb.g; (job->gs).c1.b = rgb.b; (job->gs).hc1 = 1; } $? "- f2lud_set_color_1" } /** Set non-stroking color for pdf/pgf. If we already have a color 2 equal to the new color the operation is skipped. @param job Job structure. @param drw Drawing structure. @param colno Color number. @param fillstyle Fill style used in the object. Depending on the fillstyle it might be necessary to create a shade of the color. */ static void f2lud_set_color_2( f2l_job_t *job, dk3_fig_drawing_t *drw, int colno, int fillstyle ) { dk3_rgb_color_t rgb; /* Color structure to fill. */ #if 0 int ec = 0; /* Error code variable. */ #endif int muc = 1; /* Flag: Must configure. */ $? "+ f2lud_set_color_2" dk3fig_tool_find_color(&rgb, drw, colno, fillstyle); #if 0 if((job->gs).hc2) { if(1.0e-6 > fabs(dk3ma_d_sub_ok(rgb.r, (job->gs).c2.r, &ec))) { if(1.0e-6 > fabs(dk3ma_d_sub_ok(rgb.g, (job->gs).c2.g, &ec))) { if(1.0e-6 > fabs(dk3ma_d_sub_ok(rgb.b, (job->gs).c2.b, &ec))) { if(0 == ec) { muc = 0; } } } } } #else muc = dk3fig_tool_must_set_color( (job->gs).hc2, (job->gs).c2.r, (job->gs).c2.g, (job->gs).c2.b, rgb.r, rgb.g, rgb.b ); #endif if(muc) { switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_set_color_2(job, drw, &rgb); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_set_color_2(job, drw, &rgb); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_set_color_2(job, drw, &rgb); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_set_color_2(job, drw, &rgb); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_set_color_2(job, drw, &rgb); } break; /* @DRIVER@ universal */ default: { f2lpgf_pgf_set_color_2(job, drw, &rgb); } break; } (job->gs).c2.r = rgb.r; (job->gs).c2.g = rgb.g; (job->gs).c2.b = rgb.b; (job->gs).hc2 = 1; } $? "- f2lud_set_color_2" } /** Internal function to set line width. The line width is not set again if we already have a current line width equal to the new line width. @param job Job structure. @param drw Drawing structure. @param obj Current object. @param lw New line width in output coordinates. */ static void f2lud_internal_set_line_width( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, double lw ) { int mc = 1; /* Flag: Must configure. */ int ec = 0; /* Error code variable. */ $? "+ f2lud_internal_set_line_width %lg", lw if((job->gs).hlw) { if(1.0e-6 > fabs(dk3ma_d_sub_ok(lw, (job->gs).lw, &ec))) { if(0 == ec) { mc = 0; } } } if(mc) { switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_set_line_width(job, drw, obj, lw); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_set_line_width(job, drw, obj, lw); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_set_line_width(job, drw, obj, lw); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_set_line_width(job, drw, obj, lw); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_set_line_width(job, drw, obj, lw); } break; /* @DRIVER@ universal */ default: { f2lpgf_pgf_set_line_width(job, drw, obj, lw); } break; } (job->gs).lw = lw; (job->gs).hlw = 1; } $? "- f2lud_internal_set_line_width" } /** Set line dash (line style and dash/gap length). The operation is skipped if the current line style and style value is equal to the new one. @param job Job structure. @param drw Drawing structure. @param obj Fig object. @param ls Line style. @param sv Style value (dash/gap) length in output units. */ static void f2lud_internal_set_line_dash( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int ls, double sv ) { double mysv; /* Style value converted to output space. */ double mylw; /* Line width in Fig and output space. */ int mc = 1; /* Flag: Must configure. */ int ec = 0; /* Error code variable. */ $? "+ f2lud_internal_set_line_dash" mysv = 0.9 * sv; mylw = dk3fig_tool_get_lw(drw, obj, &ec); /* Convert line width to output space. */ mylw = dk3ct_2d_r(&(job->ct2d), mylw, &ec); if((job->gs).hls) { if((job->gs).ls == ls) { if(DK3_FIG_LS_SOLID == ls) { mc = 0; } else { if(1.0e-6 > fabs(dk3ma_d_sub_ok((job->gs).sv, mysv, &ec))) { if(0 == ec) { if(DK3_FIG_LS_DASHED == ls) { mc = 0; } else { if(1.0e-6 > fabs(dk3ma_d_sub_ok((job->gs).slw, mylw, &ec))) { if(0 == ec) { mc = 0; } } } } } } } } if(mc) { switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_set_line_style(job, drw, obj, ls, mysv, mylw); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_set_line_style(job, drw, obj, ls, mysv, mylw); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_set_line_style(job, drw, obj, ls, mysv, mylw); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_set_line_style(job, drw, obj, ls, mysv, mylw); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_set_line_style(job, drw, obj, ls, mysv, mylw); } break; /* @DRIVER@ universal */ default: { f2lpgf_pgf_set_line_style(job, drw, obj, ls, mysv, mylw); } break; } (job->gs).ls = ls; (job->gs).sv = mysv; (job->gs).slw = mylw; (job->gs).hls = 1; } $? "- f2lud_internal_set_line_dash" } /** Set line ends. The operation is skipped if the current line end is equal to the new one. @param job Job structure. @param drw Drawing structure. @param obj Current object. @param le Line end style. */ static void f2lud_set_line_end( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int le ) { int mc = 1; /* Flag: Must configure. */ $? "+ f2lud_set_line_end" if((job->gs).hlc) { if((job->gs).lc == le) { mc = 0; } } if(mc) { switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_set_line_end(job, drw, obj, le); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_set_line_end(job, drw, obj, le); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_set_line_end(job, drw, obj, le); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_set_line_end(job, drw, obj, le); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_set_line_end(job, drw, obj, le); } break; /* @DRIVER@ universal */ default: { f2lpgf_pgf_set_line_end(job, drw, obj, le); } break; } (job->gs).lc = le; (job->gs).hlc = 1; } $? "- f2lud_set_line_end" } /** Set line join. The operation is skipped if the current line join is equal to the new one. @param job Job structure. @param drw Drawing structure. @param obj Current object. @param lj Line end style. */ static void f2lud_set_line_join( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int lj ) { int mc = 1; /* Flag: Must configure. */ $? "+ f2lud_set_line_join" if((job->gs).hlj) { if((job->gs).lj == lj) { mc = 0; } } if(mc) { switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lpgf_tex_set_line_join(job, drw, obj, lj); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { f2lpdf_tex_with_pdf_set_line_join(job, drw, obj, lj); } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { f2leps_eps_with_tex_set_line_join(job, drw, obj, lj); } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lpdf_pdf_with_tex_set_line_join(job, drw, obj, lj); } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { f2leps_eps_pure_set_line_join(job, drw, obj, lj); } break; /* @DRIVER@ universal */ default: { f2lpgf_pgf_set_line_join(job, drw, obj, lj); } break; } (job->gs).lj = lj; (job->gs).hlj = 1; } $? "- f2lud_set_line_join" } /** Set up line style, line width, line ends and line join for pattern. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ static void f2lud_set_pattern_line_style( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { $? "+ f2lud_set_pattern_line_style" #if VERSION_BEFORE_20140330 f2lud_internal_set_line_width(job, drw, obj, ((job->lighten) ? 0.45 : 0.9)); #else f2lud_internal_set_line_width(job, drw, obj, job->lwbp); #endif f2lud_internal_set_line_dash(job, drw, obj, DK3_FIG_LS_SOLID, -1.0); f2lud_set_line_end(job, drw, obj, DK3_FIG_LC_BUTT); f2lud_set_line_join(job, drw, obj, DK3_FIG_LJ_MITER); #if 0 /* 2012/11/18 In fishscale patterns we draw arc by arc, not a sequence of arcs. So we do not need to care about line join of arcs. */ switch(obj->fi) { case 56: case 57: { f2lud_set_line_join(job, drw, obj, DK3_FIG_LJ_BEVEL); } break; default: { f2lud_set_line_join(job, drw, obj, DK3_FIG_LJ_MITER); } break; } #endif $? "- f2lud_set_pattern_line_style" } /** Set line width. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ static void f2lud_set_line_width( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { double lw; /* Line width in Fig space. */ int ec = 0; /* Error code variable. */ $? "+ f2lud_set_line_width" lw = dk3fig_tool_get_lw(drw, obj, &ec); lw = dk3ct_2d_r(&(job->ct2d), lw, &ec); if(0 == ec) { f2lud_internal_set_line_width(job, drw, obj, lw); } $? "- f2lud_set_line_width" } /** Set line dash (line style and dash/gap length). @param job Job structure. @param drw Drawing structure. @param obj Fig object. */ static void f2lud_set_line_dash( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { $? "+ f2lud_set_line_dash" f2lud_internal_set_line_dash(job, drw, obj, obj->ls, (0.9 * obj->sv)); $? "- f2lud_set_line_dash" } /** Draw operations for object: stroke. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param ec Pointe to error code variable, may be NULL. @param primary Flag: primary (1=primary object, 0=arrowhead). */ static void f2lud_path_stroke( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int primary, int *ec ) { $? "+ f2lud_path_stroke" f2lud_set_color_1(job, drw, obj->pc, 20); f2lud_set_line_width(job, drw, obj); f2lud_set_line_dash(job, drw, obj); f2lud_set_line_end(job, drw, obj, obj->cs); f2lud_set_line_join(job, drw, obj, obj->js); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); if(obj->cl) { f2lud_closepath(job, drw, obj); } f2lud_stroke(job, drw, obj); $? "- f2lud_path_stroke" } /** Draw operations for object: fill. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param ec Pointe to error code variable, may be NULL. @param primary Flag: primary (1=primary object, 0=arrowhead). */ static void f2lud_path_fill( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int primary, int *ec ) { $? "+ f2lud_path_fill" switch(job->dr) { case FIG2LAT_DRIVER_PGF: case FIG2LAT_DRIVER_TEX_FULL_PGF: case FIG2LAT_DRIVER_TEX_FULL_PDF: case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lud_set_color_2(job, drw, obj->fc, obj->fi); } break; default: { f2lud_set_color_1(job, drw, obj->fc, obj->fi); } break; } f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_fill(job, drw, obj); $? "- f2lud_path_fill" } /** Draw operations for object: fill and stroke. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param ec Pointe to error code variable, may be NULL. @param primary Flag: primary (1=primary object, 0=arrowhead). */ static void f2lud_path_fill_stroke( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int primary, int *ec ) { $? "+ f2lud_path_fill_stroke" switch(job->dr) { case FIG2LAT_DRIVER_PGF: case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lud_set_color_2(job, drw, obj->fc, obj->fi); f2lud_set_color_1(job, drw, obj->pc, 20); f2lud_set_line_width(job, drw, obj); f2lud_set_line_dash(job, drw, obj); f2lud_set_line_end(job, drw, obj, obj->cs); f2lud_set_line_join(job, drw, obj, obj->js); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_fill_stroke(job, drw, obj); } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lud_set_color_2(job, drw, obj->fc, obj->fi); f2lud_set_color_1(job, drw, obj->pc, 20); f2lud_set_line_width(job, drw, obj); f2lud_set_line_dash(job, drw, obj); f2lud_set_line_end(job, drw, obj, obj->cs); f2lud_set_line_join(job, drw, obj, obj->js); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_fill(job, drw, obj); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_stroke(job, drw, obj); } break; default: { f2lud_set_line_width(job, drw, obj); f2lud_set_line_dash(job, drw, obj); f2lud_set_line_end(job, drw, obj, obj->cs); f2lud_set_line_join(job, drw, obj, obj->js); f2lud_set_color_1(job, drw, obj->fc, obj->fi); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_fill(job, drw, obj); f2lud_set_color_1(job, drw, obj->pc, obj->fi); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_stroke(job, drw, obj); } break; } $? "- f2lud_path_fill_stroke" } /** Draw operations for object: pattern. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param ec Pointe to error code variable, may be NULL. @param primary Flag: primary (1=primary object, 0=arrowhead). */ static void f2lud_path_pattern( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int primary, int *ec ) { $? "+ f2lud_path_pattern" f2lud_set_pattern_line_style(job, drw, obj); f2lud_set_color_1(job, drw, obj->pc, 20); f2lud_gsave(job, drw, obj); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_clip(job, drw, obj); f2lud_pattern(job, drw, obj, ec); f2lud_grestore(job, drw, obj); $? "- f2lud_path_pattern" } /** Draw operations for object: pattern and stroke. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param ec Pointe to error code variable, may be NULL. @param primary Flag: primary (1=primary object, 0=arrowhead). */ static void f2lud_path_pattern_stroke( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int primary, int *ec ) { $? "+ f2lud_path_pattern_stroke" f2lud_set_color_1(job, drw, obj->pc, 20); f2lud_set_pattern_line_style(job, drw, obj); f2lud_gsave(job, drw, obj); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_clip(job, drw, obj); f2lud_pattern(job, drw, obj, ec); f2lud_grestore(job, drw, obj); f2lud_set_line_width(job, drw, obj); f2lud_set_line_dash(job, drw, obj); f2lud_set_line_end(job, drw, obj, obj->cs); f2lud_set_line_join(job, drw, obj, obj->js); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_stroke(job, drw, obj); $? "- f2lud_path_pattern_stroke" } /** Draw operations for object: fill and pattern. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param ec Pointe to error code variable, may be NULL. @param primary Flag: primary (1=primary object, 0=arrowhead). */ static void f2lud_path_fill_pattern( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int primary, int *ec ) { $? "+ f2lud_path_fill_pattern" switch(job->dr) { case FIG2LAT_DRIVER_PGF: case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lud_set_color_2(job, drw, obj->fc, obj->fi); f2lud_set_color_1(job, drw, obj->pc, 20); f2lud_set_pattern_line_style(job, drw, obj); f2lud_gsave(job, drw, obj); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_fill_clip(job, drw, obj); f2lud_pattern(job, drw, obj, ec); f2lud_grestore(job, drw, obj); } break; default: { switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PDF: case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lud_set_color_2(job, drw, obj->fc, obj->fi); f2lud_set_color_1(job, drw, obj->pc, 20); f2lud_set_pattern_line_style(job, drw, obj); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_fill(job, drw, obj); f2lud_gsave(job, drw, obj); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_clip(job, drw, obj); f2lud_pattern(job, drw, obj, ec); f2lud_grestore(job, drw, obj); } break; default: { f2lud_set_color_1(job, drw, obj->fc, obj->fi); f2lud_set_pattern_line_style(job, drw, obj); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_fill(job, drw, obj); f2lud_set_color_1(job, drw, obj->pc, 20); f2lud_gsave(job, drw, obj); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_clip(job, drw, obj); f2lud_pattern(job, drw, obj, ec); f2lud_grestore(job, drw, obj); } break; } } break; } $? "- f2lud_path_fill_pattern" } /** Check whether on object line style and line width matches style and width configured in a dk3_graphics_state_t. @param gs dk3_graphics_state_t to test. @param ct2d Coordinates transformation data. @param drw Drawing containing the Fig object. @param obj Fig object. @return 1 for equal line width and style, 0 otherwise. */ static int f2lud_style_equal( dk3_graphics_state_t *gs, dk3_ct_2d_t *ct2d, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { double lw; /* Line width in Fig space. */ int back = 0; int ec = 0; /* Error code variable. */ #if 0 if((gs->hlw) && (gs->hls) && (gs->hlc) && (gs->hlj)) { if((gs->ls = obj->ls) && (gs->lc == obj->cs) && (gs->lj == obj->js)) { lw = dk3fig_tool_get_lw(drw, obj, &ec); if(1.0e-6 > fabs(dk3ma_d_sub_ok(gs->lw, lw, &ec))) { if(0 == ec) { if(DK3_FIG_LS_SOLID == obj->ls) { back = 1; } else { sv = 0.9 * obj->sv; if(1.0e-6 > fabs(dk3ma_d_sub_ok(gs->sv, sv, &ec))) { if(0 == ec) { back = 1; } } } } } } } #else /* 2012/11/15 As this operation is applied to closed path objects only, there is no need to check line ends. As fill patterns are drawn as solid lines, we only have to check the object line style, whether it is solid. For solid lines the style value is ignored. */ if((gs->hlw) && (gs->hls) && (gs->hlj)) { if(DK3_FIG_LS_SOLID == obj->ls) { if(gs->lj == obj->js) { lw = dk3fig_tool_get_lw(drw, obj, &ec); lw = dk3ct_2d_r(ct2d, lw, &ec); if(1.0e-6 > fabs(dk3ma_d_sub_ok(gs->lw, lw, &ec))) { if(0 == ec) { back = 1; } } } } } #endif return back; } /** Draw operations for object: fill, pattern and stroke. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param ec Pointe to error code variable, may be NULL. @param primary Flag: primary (1=primary object, 0=arrowhead). */ static void f2lud_path_fill_pattern_stroke( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int primary, int *ec ) { $? "+ f2lud_path_fill_pattern_stroke" switch(job->dr) { case FIG2LAT_DRIVER_PGF: case FIG2LAT_DRIVER_TEX_FULL_PGF: { f2lud_set_color_2(job, drw, obj->fc, obj->fi); f2lud_set_color_1(job, drw, obj->pc, 20); f2lud_set_pattern_line_style(job, drw, obj); if(f2lud_style_equal(&(job->gs), &(job->ct2d), drw, obj)) { f2lud_gsave(job, drw, obj); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_fill_stroke_clip(job, drw, obj); f2lud_pattern(job, drw, obj, ec); f2lud_grestore(job, drw, obj); } else { f2lud_gsave(job, drw, obj); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_fill_clip(job, drw, obj); f2lud_pattern(job, drw, obj, ec); f2lud_grestore(job, drw, obj); f2lud_set_line_width(job, drw, obj); f2lud_set_line_dash(job, drw, obj); f2lud_set_line_end(job, drw, obj, obj->cs); f2lud_set_line_join(job, drw, obj, obj->js); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_stroke(job, drw, obj); } } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: case FIG2LAT_DRIVER_PDF_WITH_TEX: { f2lud_set_color_2(job, drw, obj->fc, obj->fi); f2lud_set_color_1(job, drw, obj->pc, 20); f2lud_set_pattern_line_style(job, drw, obj); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_fill(job, drw, obj); f2lud_gsave(job, drw, obj); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_clip(job, drw, obj); f2lud_pattern(job, drw, obj, ec); f2lud_grestore(job, drw, obj); f2lud_set_line_width(job, drw, obj); f2lud_set_line_dash(job, drw, obj); f2lud_set_line_end(job, drw, obj, obj->cs); f2lud_set_line_join(job, drw, obj, obj->js); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_stroke(job, drw, obj); } break; default: { f2lud_set_color_1(job, drw, obj->fc, obj->fi); f2lud_set_pattern_line_style(job, drw, obj); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_fill(job, drw, obj); f2lud_set_color_1(job, drw, obj->pc, 20); f2lud_gsave(job, drw, obj); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_clip(job, drw, obj); f2lud_pattern(job, drw, obj, ec); f2lud_grestore(job, drw, obj); f2lud_set_line_width(job, drw, obj); f2lud_set_line_dash(job, drw, obj); f2lud_set_line_end(job, drw, obj, obj->cs); f2lud_set_line_join(job, drw, obj, obj->js); f2lud_newpath(job, drw, obj); f2lud_create_path(job, drw, obj, primary, ec); f2lud_closepath(job, drw, obj); f2lud_stroke(job, drw, obj); } break; } $? "- f2lud_path_fill_pattern_stroke" } /** Process path object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param primary Flag: primary (1=primary object, 0=arrowhead). */ static void f2lud_path_object( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int primary ) { int drawop; /* Operations to perform. */ int ec = 0; /* Error code variable. */ $? "+ f2lud_path_object" drawop = dk3fig_tool_get_operation(drw, obj); if(obj->cl) { switch(drawop) { case DK3_FIG_OP_STROKE: { f2lud_path_stroke(job, drw, obj, primary, &ec); } break; case DK3_FIG_OP_FILL: { f2lud_path_fill(job, drw, obj, primary, &ec); } break; case (DK3_FIG_OP_FILL | DK3_FIG_OP_STROKE): { f2lud_path_fill_stroke(job, drw, obj, primary, &ec); } break; case DK3_FIG_OP_PATTERN: { f2lud_path_pattern(job, drw, obj, primary, &ec); } break; case (DK3_FIG_OP_PATTERN | DK3_FIG_OP_STROKE): { f2lud_path_pattern_stroke(job, drw, obj, primary, &ec); } break; case (DK3_FIG_OP_PATTERN | DK3_FIG_OP_FILL): { f2lud_path_fill_pattern(job, drw, obj, primary, &ec); } break; case (DK3_FIG_OP_PATTERN | DK3_FIG_OP_FILL | DK3_FIG_OP_STROKE): { f2lud_path_fill_pattern_stroke(job, drw, obj, primary, &ec); } break; } } else { if(DK3_FIG_OP_STROKE & drawop) { f2lud_path_stroke(job, drw, obj, primary, &ec); } } if(ec) { /* ERROR: Math error in object! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 38); f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH); $? ". exitcode" } $? "- f2lud_path_object" } /** Process one object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param primary Flag: primary (1=primary object, 0=arrowhead). */ static void f2lud_process_one( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, int primary ) { char debbuf[256]; /* Buffer for debug messages. */ $? "+ f2lud_process_one" if(job->debug) { sprintf(debbuf, f2lud_c8_kw[6], obj->ot, obj->st); f2lud_debug(job, debbuf); } switch(obj->ot) { case DK3_FIG_OBJ_TEXT: { f2lud_text_object(job, drw, obj); } break; case DK3_FIG_OBJ_ELLIPSE: case DK3_FIG_OBJ_SPLINE: case DK3_FIG_OBJ_ARC: case DK3_FIG_OBJ_PSEUDO_HALF_CIRCLE: case DK3_FIG_OBJ_PSEUDO_FAST_SPLINE: { f2lud_path_object(job, drw, obj, primary); } break; case DK3_FIG_OBJ_POLYLINE: { switch(obj->st) { case 5: { f2lud_image_object(job, drw, obj); } break; default: { f2lud_path_object(job, drw, obj, primary); } break; } } break; } if(job->debug) { f2lud_debug(job, f2lud_c8_kw[7]); } $? "- f2lud_process_one" } int f2lud_is_interpolated_spline(dk3_fig_obj_t *obj) { dk3_fig_spline_point_t *po; /* Points to test */ size_t np; /* Number of points */ size_t i; /* Traverse all points */ int back = 1; $? "+ f2lud_is_interpolated_spline closed=%u", (unsigned)(obj->cl) po = (obj->dt).spl.po; np = (obj->dt).spl.np; for (i = 0; ((i < np) && (1 == back)); i++) { $? ". point %u: x=%lg y=%lg s=%lg", (unsigned)i, po->x, po->y, po->s if (fabs(po->s) > 1.0e-6) { if (fabs(1.0 + po->s) > 1.0e-6) { back = 0; } } po++; } $? "- f2lud_is_interpolated_spline %d", back return back; } /** Process one arrowhead object. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. */ static void f2lud_process_ah_one( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj ) { switch (obj->ot) { case DK3_FIG_OBJ_SPLINE: { if ((!(job->xsah)) && (f2lud_is_interpolated_spline(obj))) { obj->ot = DK3_FIG_OBJ_PSEUDO_FAST_SPLINE; f2lud_process_one(job, drw, obj, 0); obj->ot = DK3_FIG_OBJ_SPLINE; } else { f2lud_process_one(job, drw, obj, 0); } } break; default: { f2lud_process_one(job, drw, obj, 0); } break; } } /** Process object and arrowheads. @param job Job structure. @param drw Drawing structure. @param obj Current object to process. @param objno Number of current object. */ static void f2lud_process_object( f2l_job_t *job, dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, unsigned long objno ) { char debbuf[256]; /* Buffer for debug messages. */ $? "+ f2lud_process_object" /* Process object itself. */ $? ". process main object" if(job->debug) { sprintf(debbuf, f2lud_c8_kw[0], objno, obj->li, obj->ot, obj->st, obj->la); f2lud_debug(job, debbuf); } f2lud_process_one(job, drw, obj, 1); $? ". main object finished" /* For primary objects process the arrowheads. */ if(obj->af) { $? ". process forward arrowhead" if(job->debug) { $? ". create debug messages" sprintf( debbuf, f2lud_c8_kw[2], (obj->af)->as, (obj->af)->af, (obj->af)->he, (obj->af)->wi ); f2lud_debug(job, debbuf); } if((obj->af)->o1) { $? ". use arrowhead object 1" #if VERSION_BEFORE_20140329 f2lud_process_one(job,drw,(dk3_fig_obj_t *)((obj->af)->o1),0); #else f2lud_process_ah_one(job, drw, (dk3_fig_obj_t *)((obj->af)->o1)); #endif } if((obj->af)->o2) { $? ". use arrowhead object 2" #if VERSION_BEFORE_20140329 f2lud_process_one(job,drw,(dk3_fig_obj_t *)((obj->af)->o2),0); #else f2lud_process_ah_one(job, drw, (dk3_fig_obj_t *)((obj->af)->o2)); #endif } if(job->debug) { $? ". create final debug message" f2lud_debug(job, f2lud_c8_kw[3]); } $? ". forward arrowhead finished" } if(obj->ab) { $? ". process backward arrowhead" if(job->debug) { $? ". create debug messages" sprintf( debbuf, f2lud_c8_kw[4], (obj->ab)->as, (obj->ab)->af, (obj->ab)->he, (obj->ab)->wi ); f2lud_debug(job, debbuf); } if((obj->ab)->o1) { $? ". use arrowhead object 1" #if VERSION_BEFORE_20140329 f2lud_process_one(job,drw,(dk3_fig_obj_t *)((obj->ab)->o1),0); #else f2lud_process_ah_one(job, drw, (dk3_fig_obj_t *)((obj->ab)->o1)); #endif } if((obj->ab)->o2) { $? ". use arrowhead object 2" #if VERSION_BEFORE_20140329 f2lud_process_one(job,drw,(dk3_fig_obj_t *)((obj->ab)->o2),0); #else f2lud_process_ah_one(job, drw, (dk3_fig_obj_t *)((obj->ab)->o2)); #endif } if(job->debug) { $? ". create final debug message" f2lud_debug(job, f2lud_c8_kw[5]); } $? ". backward arrowhead finished" } if(job->debug) { sprintf(debbuf, f2lud_c8_kw[1], objno); f2lud_debug(job, debbuf); } $? "- f2lud_process_object" } void f2lud_output(f2l_job_t *job) { dk3_fig_obj_t *obj; /* Current object to process. */ dk3_fig_drawing_t *drw; /* Drawing to process. */ unsigned long objno; /* Current object number. */ $? "+ f2lud_output" drw = job->drw; objno = 0UL; if(f2lud_driver_initialize(job, drw)) { if(f2lud_open_output_files(job)) { if(f2lud_start_processing(job, drw)) { dk3sto_it_reset(drw->iobj); while(NULL != (obj = (dk3_fig_obj_t *)dk3sto_it_next(drw->iobj))) { if(!dk3fig_tool_is_bgrect(obj, objno)) { f2lud_process_object(job, drw, obj, objno); } objno++; } } else { f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_UNKNOWN); $? ". exitcode" } f2lud_end_processing(job, drw); } else { f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_UNKNOWN); $? ". exitcode" } f2lud_close_output_files(job); } else { f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_UNKNOWN); $? ". exitcode" } f2lud_driver_end(job, drw); $? "- f2lud_output" }