%% options copyright owner = Dirk Krause copyright year = 2012-2014 license = bsd %% header #ifdef __cplusplus extern "C" { #endif /** Prepare drawing for printing. This includes (1) allocating memory for arrowhead Fig objects, (2) attaching arrowhead Fig objects for arrowheads, (3) shortening the paths for arrowheads, and (4) finding object and drawing bounding boxes. @param drw Drawing to prepare. @return 1 on success, 0 on error. */ int dk3fig_prepare(dk3_fig_drawing_t *drw); /** Add object bounding box to bounding box structure. @param dbb Destination bounding box. @param drw Drawing structure. @param obj Object to add. @param primobj Flag: Primary object (1=object, 0=arrowhead). @return 1 on success, 0 on error. */ int dk3fig_prepare_obj_bb( dk3_bb_t *dbb, dk3_fig_drawing_t *drw, dk3_fig_obj_t const *obj, int primobj ); #ifdef __cplusplus } #endif %% module #include "dk3all.h" #include "dk3fig.h" #include "dk3figto.h" #include "dk3figpr.h" #include "dk3figbb.h" #include "dk3figah.h" #include "fig2lat.h" $!trace-include /** If the first object is a background rectangle check whether it was created by jFig or XFig. @param drw Drawing. @param obj Object to check. @param objno Object number. */ static void dk3fig_prepare_check_bgrect( dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, unsigned long objno ) { $? "+ dk3fig_prepare_check_bgrect" if(dk3fig_tool_is_bgrect(obj, objno)) { if(DK3_FIG_SRCTYPE_UNKNOWN == drw->srctype) { switch(obj->pc) { case 7: { $? ". jFig file" drw->srctype = DK3_FIG_SRCTYPE_JFIG; } break; default: { $? ". XFig file" drw->srctype = DK3_FIG_SRCTYPE_XFIG; } break; } } } $? "- dk3fig_prepare_check_bgrect" } #if TRACE_DEBUG /** Calculate distance of 2 points, used to verify the correct radius calculation for args. @param x1 Point 1 x. @param x2 Point 2 x. @param y1 Point 1 y. @param y2 Point 2 y. @return Distance between points. */ static double dk3fig_prepare_point_distance( double x1, double x2, double y1, double y2 ) { double back; back = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); return back; } #endif /** Initialize arc object (calculate center and radius). @param drw Drawing. @param obj Object. @param objno Object number (0 for first object). @param primobj Flag: Primary object (1=object, 0=arrowhead). @return 1 on success, 0 on error. */ static int dk3fig_prepare_initialize_arc( dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, unsigned long objno, int primobj ) { dk3_fig_poly_point_t *points; dk3_fig_det_arc_t *arc; double tm; /* The t parameter of the M point. */ double n; /* Denominator in tm calculation. */ double xa; double ya; double xc; double yc; double r; double eps = DK3_FIG_EPSILON; int back = 1; int ec = 0; int divec = 0; $? "+ dk3fig_prepare_initialize_arc" arc = &((obj->dt).arc); n = dk3ma_d_sub_ok( dk3ma_d_mul_ok( dk3ma_d_sub_ok(arc->y2, arc->y1, &ec), dk3ma_d_sub_ok(arc->x2, arc->x3, &ec), &ec ), dk3ma_d_mul_ok( dk3ma_d_sub_ok(arc->y3, arc->y2, &ec), dk3ma_d_sub_ok(arc->x1, arc->x2, &ec), &ec ), &ec ); tm = 0.5 * dk3ma_d_div_ok( dk3ma_d_sub_ok( dk3ma_d_mul_ok( dk3ma_d_sub_ok(arc->x2, arc->x3, &ec), dk3ma_d_sub_ok(arc->x3, arc->x1, &ec), &ec ), dk3ma_d_mul_ok( dk3ma_d_sub_ok(arc->y3, arc->y2, &ec), dk3ma_d_sub_ok(arc->y3, arc->y1, &ec), &ec ), &ec ), n, &divec ); if(0 == divec) { arc->xc = dk3ma_d_add_ok( (0.5 * dk3ma_d_add_ok(arc->x1, arc->x2, &ec)), dk3ma_d_mul_ok( tm, dk3ma_d_sub_ok(arc->y2, arc->y1, &ec), &ec ), &ec ); arc->yc = dk3ma_d_add_ok( (0.5 * dk3ma_d_add_ok(arc->y1, arc->y2, &ec)), dk3ma_d_mul_ok( tm, dk3ma_d_sub_ok(arc->x1, arc->x2, &ec), &ec ), &ec ); arc->ra = sqrt( dk3ma_d_add_ok( dk3ma_d_mul_ok( dk3ma_d_sub_ok(arc->xc, arc->x1, &ec), dk3ma_d_sub_ok(arc->xc, arc->x1, &ec), &ec ), dk3ma_d_mul_ok( dk3ma_d_sub_ok(arc->yc, arc->y1, &ec), dk3ma_d_sub_ok(arc->yc, arc->y1, &ec), &ec ), &ec ) ); arc->as = dk3ma_d_atan2( dk3ma_d_sub_ok(arc->y1, arc->yc, &ec), dk3ma_d_sub_ok(arc->x1, arc->xc, &ec) ); arc->ae = dk3ma_d_atan2( dk3ma_d_sub_ok(arc->y3, arc->yc, &ec), dk3ma_d_sub_ok(arc->x3, arc->xc, &ec) ); if(n >= 0.0) { arc->di = 0x01; while(arc->ae < arc->as) { arc->ae = arc->ae + (2.0 * M_PI); } } else { arc->di = 0x00; while(arc->as < arc->ae) { arc->as = arc->as + (2.0 * M_PI); } } $? ". point 1:\t%lg\t%lg", arc->x1, arc->y1 $? ". point 2:\t%lg\t%lg", arc->x2, arc->y2 $? ". point 3:\t%lg\t%lg", arc->x3, arc->y3 $? ". point M:\t%lg\t%lg", arc->xc, arc->yc $? ". radius: \t%lg", arc->ra $? ". r 1 : \t%lg", dk3fig_prepare_point_distance(arc->x1, arc->xc, arc->y1, arc->yc) $? ". r 1 : \t%lg", dk3fig_prepare_point_distance(arc->x2, arc->xc, arc->y2, arc->yc) $? ". r 1 : \t%lg", dk3fig_prepare_point_distance(arc->x3, arc->xc, arc->y3, arc->yc) $? ". alphas: \t%lg", (180.0 * arc->as) / M_PI $? ". alphae: \t%lg", (180.0 * arc->ae) / M_PI $? ". dir: \t%s", ((arc->di) ? "pos" : "neg") } else { /* line */ back = 0; xa = arc->x1; ya = arc->y1; xc = arc->x3; yc = arc->y3; if(dk3ma_d_equal(xa, xc, eps) && dk3ma_d_equal(ya, yc, eps)) { r = 0.5 * dk3fig_tool_get_lw(drw, obj, &ec); switch(obj->cs) { case DK3_FIG_LC_ROUND: { back = 1; dk3mem_res( (void *)(&((obj->dt))), sizeof(dk3_fig_obj_det_t) ); obj->ot = DK3_FIG_OBJ_ELLIPSE; obj->st = 3; /* Circle defined by radius */ obj->lw = 0; obj->fc = obj->pc; obj->fi = 20; /* Full saturation of color. */ obj->cs = DK3_FIG_LC_BUTT; obj->js = DK3_FIG_LJ_MITER; obj->ls = DK3_FIG_LS_SOLID; obj->cl = 1; (obj->dt).ell.an = 0.0; (obj->dt).ell.cx = xa; (obj->dt).ell.cy = ya; (obj->dt).ell.rx = (obj->dt).ell.ry = r; } break; default: { points = dk3_new_app(dk3_fig_poly_point_t,4,drw->app); if(points) { back = 1; points[0].x = points[3].x = dk3ma_d_sub_ok(xa, r, &ec); points[1].x = points[2].x = dk3ma_d_add_ok(xa, r, &ec); points[0].y = points[1].y = dk3ma_d_sub_ok(ya, r, &ec); points[2].y = points[3].y = dk3ma_d_add_ok(ya, r, &ec); dk3mem_res( (void *)(&((obj->dt))), sizeof(dk3_fig_obj_det_t) ); obj->ot = DK3_FIG_OBJ_POLYLINE; obj->st = 3; /* Polygon */ obj->lw = 0; obj->fc = obj->pc; obj->fi = 20; /* Full saturation of color. */ obj->cs = DK3_FIG_LC_BUTT; obj->js = DK3_FIG_LJ_MITER; obj->ls = DK3_FIG_LS_SOLID; obj->cl = 1; (obj->dt).pol.fn = NULL; (obj->dt).pol.po = points; (obj->dt).pol.ra = 0.0; (obj->dt).pol.xs = 0.0; (obj->dt).pol.ys = 0.0; (obj->dt).pol.xe = 0.0; (obj->dt).pol.ye = 0.0; (obj->dt).pol.np = 4; (obj->dt).pol.flf = 0; } else { back = 0; dk3fig_set_ec(drw, DK3_ERROR_MEMORY); } } break; } } else { points = dk3_new_app(dk3_fig_poly_point_t,2,drw->app); if(points) { back = 1; points[0].x = xa; points[0].y = ya; points[1].x = xc; points[1].y = yc; (obj->dt).pol.fn = NULL; (obj->dt).pol.po = points; (obj->dt).pol.ra = 0.0; (obj->dt).pol.xs = xa; (obj->dt).pol.ys = ya; (obj->dt).pol.xe = xc; (obj->dt).pol.ye = yc; (obj->dt).pol.np = 2; (obj->dt).pol.flf = 0; obj->ot = DK3_FIG_OBJ_POLYLINE; obj->st = 1; } else { dk3fig_set_ec(drw, DK3_ERROR_MEMORY); /* memory allocation failed, reported by back == 0. */ } } } if(ec) { $? "! math problem in arc" back = 0; /* ERROR: Mathematical problem with arc! */ dk3fig_set_ec(drw, DK3_ERROR_MATH_OVERFLOW); dk3app_log_1(drw->app, DK3_LL_ERROR, drw->msg, 3); } $? "- dk3fig_prepare_initialize_arc %d", back return back; } /** Convert polyline to circle or squara if necessary. @param drw Drawing. @param obj Object. @param objno Object number (0 for first object). @param primobj Flag: Primary object (1=object, 0=arrowhead). @return 1 on success, 0 on error. */ static int dk3fig_prepare_initialize_polyline( dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, unsigned long objno, int primobj ) { dk3_fig_poly_point_t *newpoints; double cx; double cy; double r; double x1; double x2; double y1; double y2; double eps = DK3_FIG_EPSILON; int back = 1; int mc = 0; int ec = 0; $? "+ dk3fig_prepare_initialize_polyline" if(1 == (obj->dt).pol.np) { mc = 1; } else { if(2 == (obj->dt).pol.np) { if(dk3ma_d_equal(((obj->dt).pol.po)[0].x, ((obj->dt).pol.po)[1].x, eps)) { if(dk3ma_d_equal(((obj->dt).pol.po)[0].y, ((obj->dt).pol.po)[1].y, eps)) { mc = 1; } } } } if(mc) { switch(obj->cs) { case DK3_FIG_LC_ROUND: { $? ". convert polyline dot to circle" cx = ((obj->dt).pol.po)[0].x; cy = ((obj->dt).pol.po)[0].y; r = 0.5 * dk3fig_tool_get_lw(drw, obj, &ec); dk3_release((obj->dt).pol.fn); dk3_release((obj->dt).pol.po); dk3mem_res( (void *)(&((obj->dt))), sizeof(dk3_fig_obj_det_t) ); obj->ot = DK3_FIG_OBJ_ELLIPSE; obj->st = 3; /* Circle defined by radius */ obj->lw = 0; obj->fc = obj->pc; obj->fi = 20; /* Full saturation of color. */ obj->cs = DK3_FIG_LC_BUTT; obj->js = DK3_FIG_LJ_MITER; obj->ls = DK3_FIG_LS_SOLID; obj->cl = 1; (obj->dt).ell.an = 0.0; (obj->dt).ell.cx = cx; (obj->dt).ell.cy = cy; (obj->dt).ell.rx = (obj->dt).ell.ry = r; } break; default: { $? ". convert polyline dot to square" cx = ((obj->dt).pol.po)[0].x; cy = ((obj->dt).pol.po)[0].y; r = 0.5 * dk3fig_tool_get_lw(drw, obj, &ec); x1 = dk3ma_d_sub_ok(cx, r, &ec); x2 = dk3ma_d_add_ok(cx, r, &ec); y1 = dk3ma_d_sub_ok(cy, r, &ec); y2 = dk3ma_d_add_ok(cy, r, &ec); newpoints = dk3_new_app(dk3_fig_poly_point_t,4,drw->app); if(newpoints) { newpoints[0].x = x1; newpoints[0].y = y1; newpoints[1].x = x2; newpoints[1].y = y1; newpoints[2].x = x2; newpoints[2].y = y2; newpoints[3].x = x1; newpoints[3].y = y2; dk3_release((obj->dt).pol.fn); dk3_release((obj->dt).pol.po); dk3mem_res( (void *)(&((obj->dt))), sizeof(dk3_fig_obj_det_t) ); obj->ot = DK3_FIG_OBJ_POLYLINE; obj->st = 3; /* Polygon */ obj->lw = 0; obj->fc = obj->pc; obj->fi = 20; /* Full saturation of color. */ obj->cs = DK3_FIG_LC_BUTT; obj->js = DK3_FIG_LJ_MITER; obj->ls = DK3_FIG_LS_SOLID; obj->cl = 1; (obj->dt).pol.fn = NULL; (obj->dt).pol.po = newpoints; (obj->dt).pol.ra = 0.0; (obj->dt).pol.xs = 0.0; (obj->dt).pol.ys = 0.0; (obj->dt).pol.xe = 0.0; (obj->dt).pol.ye = 0.0; (obj->dt).pol.np = 4; (obj->dt).pol.flf = 0; } else { back = 0; dk3fig_set_ec(drw, DK3_ERROR_MEMORY); } } break; } } if(ec) { $? "! math error" /* ERROR: Math */ dk3fig_set_ec(drw, DK3_ERROR_MATH_OVERFLOW); back = 0; dk3app_log_i1(drw->app, DK3_LL_ERROR, 260); } $? "- dk3fig_prepare_initialize_polyline %d", back return back; } #if 0 /* Only polylines are allowed to have one point, not splines. */ /** Convert spline to circle or squara if necessary. @param drw Drawing. @param obj Object. @param objno Object number (0 for first object). @param primobj Flag: Primary object (1=object, 0=arrowhead). @return 1 on success, 0 on error. */ static int dk3fig_prepare_initialize_spline( dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, unsigned long objno, int primobj ) { dk3_fig_poly_point_t *newpoints; double cx; double cy; double r; double x1; double x2; double y1; double y2; double eps = DK3_FIG_EPSILON; int back = 1; int mc = 0; int ec = 0; $? "+ dk3fig_prepare_initialize_spline" if(1 == (obj->dt).spl.np) { mc = 1; } else { if(2 == (obj->dt).spl.np) { if(dk3ma_d_equal(((obj->dt).spl.po)[0].x, ((obj->dt).spl.po)[1].x, eps)) { if(dk3ma_d_equal(((obj->dt).spl.po)[0].y, ((obj->dt).spl.po)[1].y, eps)) { mc = 1; } } } } if(mc) { switch(obj->cs) { case DK3_FIG_LC_ROUND: { $? ". convert spline dot to circle" cx = ((obj->dt).spl.po)[0].x; cy = ((obj->dt).spl.po)[0].y; r = 0.5 * dk3fig_tool_get_lw(drw, obj, &ec); dk3_release((obj->dt).spl.po); dk3mem_res( (void *)(&((obj->dt))), sizeof(dk3_fig_obj_det_t) ); obj->ot = DK3_FIG_OBJ_ELLIPSE; obj->st = 3; /* Circle defined by radius */ obj->lw = 0; obj->fc = obj->pc; obj->fi = 20; /* Full saturation of color. */ obj->cs = DK3_FIG_LC_BUTT; obj->js = DK3_FIG_LJ_MITER; obj->ls = DK3_FIG_LS_SOLID; obj->cl = 1; (obj->dt).ell.an = 0.0; (obj->dt).ell.cx = cx; (obj->dt).ell.cy = cy; (obj->dt).ell.rx = (obj->dt).ell.ry = r; } break; default: { $? ". convert spline dot to square" cx = ((obj->dt).spl.po)[0].x; cy = ((obj->dt).spl.po)[0].y; r = 0.5 * dk3fig_tool_get_lw(drw, obj, &ec); x1 = dk3ma_d_sub_ok(cx, r, &ec); x2 = dk3ma_d_add_ok(cx, r, &ec); y1 = dk3ma_d_sub_ok(cy, r, &ec); y2 = dk3ma_d_add_ok(cy, r, &ec); newpoints = dk3_new_app(dk3_fig_poly_point_t,4,drw->app); if(newpoints) { newpoints[0].x = x1; newpoints[0].y = y1; newpoints[1].x = x2; newpoints[1].y = y1; newpoints[2].x = x2; newpoints[2].y = y2; newpoints[3].x = x1; newpoints[3].y = y2; dk3_release((obj->dt).spl.po); dk3mem_res( (void *)(&((obj->dt))), sizeof(dk3_fig_obj_det_t) ); obj->ot = DK3_FIG_OBJ_POLYLINE; obj->st = 3; /* Polygon */ obj->lw = 0; obj->fc = obj->pc; obj->fi = 20; /* Full saturation of color. */ obj->cs = DK3_FIG_LC_BUTT; obj->js = DK3_FIG_LJ_MITER; obj->ls = DK3_FIG_LS_SOLID; obj->cl = 1; (obj->dt).pol.fn = NULL; (obj->dt).pol.po = newpoints; (obj->dt).pol.ra = 0.0; (obj->dt).pol.xs = 0.0; (obj->dt).pol.ys = 0.0; (obj->dt).pol.xe = 0.0; (obj->dt).pol.ye = 0.0; (obj->dt).pol.np = 4; (obj->dt).pol.flf = 0; } else { back = 0; } } break; } } if(ec) { $? "! math error" dk3fig_set_ec(drw, DK3_ERROR_MATH_OVERFLOW); /* ERROR: Math */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 38); } $? "- dk3fig_prepare_initialize_spline %d", back return back; } #endif /** Object type specific initialization. @param drw Drawing. @param obj Object. @param objno Object number (0 for first object). @param primobj Flag: Primary object (1=object, 0=arrowhead). @return 1 on success, 0 on error. */ static int dk3fig_prepare_initialize_object( dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, unsigned long objno, int primobj ) { int back = 1; $? "+ dk3fig_prepare_initialize_object" switch(obj->ot) { case DK3_FIG_OBJ_POLYLINE: { back = dk3fig_prepare_initialize_polyline(drw, obj, objno, primobj); } break; #if 0 /* Only polylines are allowed to have one point, not splines. */ case DK3_FIG_OBJ_SPLINE: { back = dk3fig_prepare_initialize_spline(drw, obj, objno, primobj); } break; #endif case DK3_FIG_OBJ_ARC: { back = dk3fig_prepare_initialize_arc(drw, obj, objno, primobj); } break; } $? "- dk3fig_prepare_initialize_object %d", back return back; } /** Add object to drawing bounding box. @param drw Drawing to calculate the bounding box for. @param obj Object to add to bounding box. @param primobj Flag: Primary object (1=object, 0=arrowhead). @return 1 on success, 0 on error. */ static int dk3fig_prepare_add_to_bb( dk3_fig_drawing_t *drw, dk3_fig_obj_t const *obj, int primobj ); /** Add objects for one arrowhead to bounding box. @param drw @param obj @param ah @return 1 on success, 0 on error. */ static int dk3fig_prepare_arrowhead_object( dk3_fig_drawing_t *drw, dk3_fig_obj_t const *obj, dk3_fig_ah_t const *ah ) { int back = 1; $? "+ dk3fig_prepare_arrowhead_object" if(ah) { if(ah->o1) { if(!dk3fig_prepare_add_to_bb(drw, (dk3_fig_obj_t *)(ah->o1), 0)) { back = 0; } } if(ah->o2) { if(!dk3fig_prepare_add_to_bb(drw, (dk3_fig_obj_t *)(ah->o2), 0)) { back = 0; } } if(!(back)) { dk3fig_set_ec(drw, DK3_ERROR_MATH_OVERFLOW); /* ERROR: Math overflow */ } } $? "- dk3fig_prepare_arrowhead_object %d", back return back; } int dk3fig_prepare_obj_bb( dk3_bb_t *dbb, dk3_fig_drawing_t *drw, dk3_fig_obj_t const *obj, int primobj ) { int back = 0; int notfound = 0; switch(obj->ot) { case DK3_FIG_OBJ_ELLIPSE: { $? ". ellipse" back = dk3fig_bb_add_ellipse( dbb, &((obj->dt).ell), (0.5 * dk3fig_tool_get_lw(drw, obj, NULL)) ); } break; case DK3_FIG_OBJ_POLYLINE: { $? ". polyline %d lw=%d", obj->la, obj->lw back = dk3fig_bb_add_polyline( dbb, &((obj->dt).pol), (0.5 * dk3fig_tool_get_lw(drw, obj, NULL)) ); } break; case DK3_FIG_OBJ_SPLINE: { $? ". spline" back = dk3fig_bb_add_spline( drw, dbb, &((obj->dt).spl), (0.5 * dk3fig_tool_get_lw(drw, obj, NULL)), primobj, ((obj->cl) ? 1 : 0) ); } break; case DK3_FIG_OBJ_TEXT: { $? ". text" back = dk3fig_bb_add_text( dbb, &((obj->dt).txt), drw->res, drw->bbts ); } break; case DK3_FIG_OBJ_ARC: { $? ". arc" back = dk3fig_bb_add_arc( dbb, &((obj->dt).arc), ((1 != obj->st) ? 1 : 0), (0.5 * dk3fig_tool_get_lw(drw, obj, NULL)) ); } break; default: { $? "! unknown object" dk3fig_set_ec(drw, DK3_ERROR_SYNTAX); /* ERROR: Unknown object type! */ dk3app_log_1(drw->app, DK3_LL_ERROR, drw->msg, 8); notfound = 1; } break; } if(!(back)) { if(!(notfound)) { dk3fig_set_ec(drw, DK3_ERROR_MATH_OVERFLOW); /* ERROR: Math overflow */ } } return back; } static int dk3fig_prepare_add_to_bb( dk3_fig_drawing_t *drw, dk3_fig_obj_t const *obj, int primobj ) { #if TEST_SHOW_EACH_BB int back = 0; dk3_bb_t mybb; $? "+ dk3fig_prepare_add_to_bb" dk3bb_reset(&mybb); switch(obj->ot) { case DK3_FIG_OBJ_ELLIPSE: { $? ". ellipse" back = dk3fig_bb_add_ellipse( &mybb, &((obj->dt).ell), (0.5 * dk3fig_tool_get_lw(drw, obj, NULL)) ); } break; case DK3_FIG_OBJ_POLYLINE: { $? ". polyline %d lw=%d", obj->la, obj->lw back = dk3fig_bb_add_polyline( &mybb, &((obj->dt).pol), (0.5 * dk3fig_tool_get_lw(drw, obj, NULL)) ); } break; case DK3_FIG_OBJ_SPLINE: { $? ". spline" back = dk3fig_bb_add_spline( drw, &mybb, &((obj->dt).spl), (0.5 * dk3fig_tool_get_lw(drw, obj, NULL)), primobj, ((obj->cl) ? 1 : 0) ); } break; case DK3_FIG_OBJ_TEXT: { $? ". text" back = dk3fig_bb_add_text( &mybb, &((obj->dt).txt), drw->res, drw->bbts ); } break; case DK3_FIG_OBJ_ARC: { $? ". arc" back = dk3fig_bb_add_arc( &mybb, &((obj->dt).arc), ((1 != obj->st) ? 1 : 0), (0.5 * dk3fig_tool_get_lw(drw, obj, NULL)) ); } break; case DK3_FIG_OBJ_PSEUDO_HALF_CIRCLE: { back = dk3fig_bb_add_hci( &mybb, &(obj->dt).hci, (0.5 * dk3fig_tool_get_lw(drw, obj, NULL)) ); } break; default: { $? "! unknown object" } break; } $? ". bb x = %lg %lg y = %lg %lg",mybb.xmin,mybb.xmax,mybb.ymin,mybb.ymax dk3bb_merge(&(drw->bb), &mybb); if(primobj) { if(!dk3fig_prepare_arrowhead_object(drw, obj, obj->af)) { back = 0; } if(!dk3fig_prepare_arrowhead_object(drw, obj, obj->ab)) { back = 0; } } if(!(back)) { /* ERROR: Math overflow */ dk3fig_set_ec(drw, DK3_ERROR_MATH_OVERFLOW); dk3app_log_i1(drw->app, DK3_LL_ERROR, 260); } $? "- dk3fig_prepare_add_to_bb %d", back return back; #else int back = 0; $? "+ dk3fig_prepare_add_to_bb" switch(obj->ot) { case DK3_FIG_OBJ_ELLIPSE: { $? ". ellipse" back = dk3fig_bb_add_ellipse( &(drw->bb), &((obj->dt).ell), (0.5 * dk3fig_tool_get_lw(drw, obj, NULL)) ); } break; case DK3_FIG_OBJ_POLYLINE: { $? ". polyline %d lw=%d", obj->la, obj->lw back = dk3fig_bb_add_polyline( &(drw->bb), &((obj->dt).pol), (0.5 * dk3fig_tool_get_lw(drw, obj, NULL)) ); } break; case DK3_FIG_OBJ_SPLINE: { $? ". spline" back = dk3fig_bb_add_spline( drw, &(drw->bb), &((obj->dt).spl), (0.5 * dk3fig_tool_get_lw(drw, obj, NULL)), primobj, ((obj->cl) ? 1 : 0) ); } break; case DK3_FIG_OBJ_TEXT: { $? ". text" back = dk3fig_bb_add_text( &(drw->bb), &((obj->dt).txt), drw->res, drw->bbts ); } break; case DK3_FIG_OBJ_ARC: { $? ". arc" back = dk3fig_bb_add_arc( &(drw->bb), &((obj->dt).arc), ((1 != obj->st) ? 1 : 0), (0.5 * dk3fig_tool_get_lw(drw, obj, NULL)) ); } break; case DK3_FIG_OBJ_PSEUDO_HALF_CIRCLE: { back = dk3fig_bb_add_hci( &(drw->bb), &((obj->dt).hci), (0.5 * dk3fig_tool_get_lw(drw, obj, NULL)) ); } break; default: { $? "! unknown object" } break; } if(primobj) { if(!dk3fig_prepare_arrowhead_object(drw, obj, obj->af)) { back = 0; } if(!dk3fig_prepare_arrowhead_object(drw, obj, obj->ab)) { back = 0; } } if(!(back)) { /* ERROR: Math overflow */ dk3fig_set_ec(drw, DK3_ERROR_MATH_OVERFLOW); dk3app_log_i1(drw->app, DK3_LL_ERROR, 260); } $? "- dk3fig_prepare_add_to_bb %d", back return back; #endif } #if TRACE_DEBUG /** Report object to trace file. @param obj Object to report. @param primobj Flag: Primary object (1=object, 0=arrowhead). */ static void dk3fig_prepare_report_object(dk3_fig_obj_t *obj, int primobj); /** Report one arrowhead to trace file. @param ah Arrowhead to report. */ static void dk3fig_prepare_report_ah(dk3_fig_ah_t *ah) { if(ah) { $? "+ dk3fig_prepare_report_ah" if(ah->o1) { dk3fig_prepare_report_object((dk3_fig_obj_t *)(ah->o1), 0); } if(ah->o2) { dk3fig_prepare_report_object((dk3_fig_obj_t *)(ah->o2), 0); } $? "- dk3fig_prepare_report_ah" } } static void dk3fig_prepare_report_object(dk3_fig_obj_t *obj, int primobj) { FILE *fipo; dk3_fig_poly_point_t *pp; dk3_fig_spline_point_t *sp; size_t i; $? "+ dk3fig_prepare_report_object primary=%d", primobj fipo = dktrace_file(); if(fipo) { switch(obj->ot) { case DK3_FIG_OBJ_ELLIPSE: { fputs("Ellipse\n", fipo); switch(obj->st) { case 1: { fputs("Ellipse by radii\n", fipo); } break; case 2: { fputs("Ellipse by diameter\n", fipo); } break; case 3: { fputs("Circle by radius\n", fipo); } break; case 4: { fputs("Circle by diameter\n", fipo); } break; default: { fputs("UNKNOWN SUB-TYPE\n", fipo); } break; } } break; case DK3_FIG_OBJ_POLYLINE: { fputs("Polyline\n", fipo); switch(obj->st) { case 1: { fputs("Polyline\n", fipo); } break; case 2: { fputs("Box\n", fipo); } break; case 3: { fputs("Polygon\n", fipo); } break; case 4: { fputs("Arc-box\n", fipo); } break; case 5: { fputs("Imported image\n", fipo); } break; default: { fputs("UNKNOWN SUBTYPE\n", fipo); } break; } } break; case DK3_FIG_OBJ_SPLINE: { fputs("Spline\n", fipo); switch(obj->st) { case 0: { fputs("Open approximated\n", fipo); } break; case 1: { fputs("Closed approximated\n", fipo); } break; case 2: { fputs("Open interpolated\n", fipo); } break; case 3: { fputs("Closed interpolated\n", fipo); } break; case 4: { fputs("Open X-spline\n", fipo); } break; case 5: { fputs("Closed X-spline\n", fipo); } break; default: { fputs("UNKNOWN SUBTYPE\n", fipo); } break; } } break; case DK3_FIG_OBJ_TEXT: { fputs("Text\n", fipo); switch(obj->st) { case 0: { fputs("Left-aligned\n", fipo); } break; case 1: { fputs("Centered\n", fipo); } break; case 2: { fputs("Right-aligned\n", fipo); } break; default: { fputs("UNKNOWN SUB-TYPE\n", fipo); } break; } } break; case DK3_FIG_OBJ_ARC: { fputs("Arc\n", fipo); switch(obj->st) { case 1: { fputs("Open arc\n", fipo); } break; case 2: { fputs("Closed arc\n", fipo); } break; default: { fputs("UNKNOWN SUB-TYPE\n", fipo); } break; } } break; case DK3_FIG_OBJ_PSEUDO_HALF_CIRCLE: { fputs("Half-circle\n", fipo); if(obj->st) { fputs("Closed filled half-circle\n", fipo); } else { fputs("Open half-circle\n", fipo); } } break; default: { fputs("UNKNOWN OBJECT TYPE\n", fipo); } break; } fprintf(fipo, "Layer: %d\n", obj->la); fprintf(fipo, "Line number: %lu\n", obj->li); fprintf(fipo, "Closed: %d\n", obj->cl); fprintf(fipo, "Line width: %d\n", obj->lw); fprintf(fipo, "Pen color: %d\n", obj->pc); fprintf(fipo, "Fill color: %d\n", obj->fc); fprintf(fipo, "Fill type: %d\n", obj->fi); fprintf(fipo, "Line cap: %d\n", obj->cs); fprintf(fipo, "Line join: %d\n", obj->js); fprintf(fipo, "Line style: %d\n", obj->ls); fprintf(fipo, "Style value: %lg\n", obj->sv); switch(obj->ot) { case DK3_FIG_OBJ_ELLIPSE: { fprintf(fipo, "Center x: %lg\n", (obj->dt).ell.cx); fprintf(fipo, "Center y: %lg\n", (obj->dt).ell.cy); fprintf(fipo, "Radius x: %lg\n", (obj->dt).ell.rx); fprintf(fipo, "Radius y: %lg\n", (obj->dt).ell.ry); fprintf(fipo, "Angle: %lg\n", (180.0 * (obj->dt).ell.an / M_PI)); } break; case DK3_FIG_OBJ_POLYLINE: { fprintf(fipo, "Radius: %lg\n", (obj->dt).pol.ra); fprintf(fipo, "Start x: %lg\n", (obj->dt).pol.xs); fprintf(fipo, "Start y: %lg\n", (obj->dt).pol.ys); fprintf(fipo, "End x: %lg\n", (obj->dt).pol.xe); fprintf(fipo, "End y: %lg\n", (obj->dt).pol.ye); if(5 == obj->st) { fprintf(fipo, "Flip: %d\n", (obj->dt).pol.flf); fprintf(fipo, "Image: \"%s\"", TR_STR((obj->dt).pol.fn)); } fprintf(fipo, "Points: %lu\n", (unsigned long)((obj->dt).pol.np)); if((obj->dt).pol.po) { pp = (obj->dt).pol.po; i = (obj->dt).pol.np; while(i--) { fprintf(fipo, "%lg %lg\n", pp->x, pp->y); pp++; } } else { fprintf(fipo, "ERROR: NO POINTS!\n"); } } break; case DK3_FIG_OBJ_SPLINE: { fprintf(fipo, "Start t: %lg\n", (obj->dt).spl.ts); fprintf(fipo, "End t: %lg\n", (obj->dt).spl.te); fprintf(fipo, "Points: %lu\n", (unsigned long)((obj->dt).spl.np)); if((obj->dt).spl.po) { sp = (obj->dt).spl.po; i = (obj->dt).spl.np; while(i--) { fprintf(fipo, "%lg %lg %lg\n", sp->x, sp->y, sp->s); sp++; } } else { fprintf(fipo, "ERROR: NO POINTS!\n"); } } break; case DK3_FIG_OBJ_TEXT: { fprintf(fipo, "Position x: %lg\n", (obj->dt).txt.x); fprintf(fipo, "Position y: %lg\n", (obj->dt).txt.y); fprintf(fipo, "Angle: %lg\n", (obj->dt).txt.an); fprintf(fipo, "Text: \"%s\"\n", TR_STR((obj->dt).txt.st)); fprintf(fipo, "Font flags: %d\n", (obj->dt).txt.ff); fprintf(fipo, "Font: %d\n", (obj->dt).txt.fo); fprintf(fipo, "Font size: %lg\n", (obj->dt).txt.fs); } break; case DK3_FIG_OBJ_ARC: { fprintf(fipo, "Center x: %lg\n", (obj->dt).arc.xc); fprintf(fipo, "Center y: %lg\n", (obj->dt).arc.yc); fprintf(fipo, "Radius: %lg\n", (obj->dt).arc.ra); fprintf(fipo, "Start: %lg\n", (180.0 * (obj->dt).arc.as / M_PI)); fprintf(fipo, "End: %lg\n", (180.0 * (obj->dt).arc.ae / M_PI)); fprintf(fipo, "Direction: %d", (int)((obj->dt).arc.di)); fprintf(fipo, "Point 1 x: %lg\n", (obj->dt).arc.x1); fprintf(fipo, "Point 1 y: %lg\n", (obj->dt).arc.y1); fprintf(fipo, "Point 2 x: %lg\n", (obj->dt).arc.x2); fprintf(fipo, "Point 2 y: %lg\n", (obj->dt).arc.y2); fprintf(fipo, "Point 3 x: %lg\n", (obj->dt).arc.x3); fprintf(fipo, "Point 3 y: %lg\n", (obj->dt).arc.y3); } break; } if(primobj) { if(obj->af) { fprintf(fipo, "ARROWHEAD FORWARD\n"); dk3fig_prepare_report_ah(obj->af); } if(obj->ab) { fprintf(fipo, "ARROWHEAD BACKWARD\n"); dk3fig_prepare_report_ah(obj->ab); } } } $? "- dk3fig_prepare_report_object" } #endif /** Check whether the object is an open path and filling is required, change subtype to closed path if necessary. @param drw Drawing containing the object. @param obj Object to check. */ static void dk3fig_prepare_check_fill_open_path(dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj) { switch(obj->ot) { case DK3_FIG_OBJ_POLYLINE: { if((-1 != obj->fi) && (drw->transcol != obj->fc)) { switch(obj->st) { case 1: { if(drw->cofop) { obj->st = 3; obj->cl = 1; if((drw->app) && (drw->msg)) { dk3app_log_1(drw->app, DK3_LL_DEBUG, drw->msg, 10); } } else { if((drw->app) && (drw->msg)) { dk3app_log_1(drw->app, DK3_LL_WARNING, drw->msg, 9); } } } break; } } } break; case DK3_FIG_OBJ_SPLINE: { if((-1 != obj->fi) && (drw->transcol != obj->fc)) { switch(obj->st) { case 0: { if(drw->cofop) { obj->st = 1; obj->cl = 1; if((drw->app) && (drw->msg)) { dk3app_log_1(drw->app, DK3_LL_DEBUG, drw->msg, 10); } } else { if((drw->app) && (drw->msg)) { dk3app_log_1(drw->app, DK3_LL_WARNING, drw->msg, 9); } } } break; case 2: { if(drw->cofop) { obj->st = 3; obj->cl = 1; if((drw->app) && (drw->msg)) { dk3app_log_1(drw->app, DK3_LL_DEBUG, drw->msg, 10); } } else { if((drw->app) && (drw->msg)) { dk3app_log_1(drw->app, DK3_LL_WARNING, drw->msg, 9); } } } break; case 4: { if(drw->cofop) { obj->st = 5; obj->cl = 1; if((drw->app) && (drw->msg)) { dk3app_log_1(drw->app, DK3_LL_DEBUG, drw->msg, 10); } } else { if((drw->app) && (drw->msg)) { dk3app_log_1(drw->app, DK3_LL_WARNING, drw->msg, 9); } } } break; } } } break; } } /** Prepare one object. @param drw Drawing. @param obj Object to prepare. @param objno Object number (starting at 0). @return 1 on success, 0 on error. */ static int dk3fig_prepare_object( dk3_fig_drawing_t *drw, dk3_fig_obj_t *obj, unsigned long objno ) { int back = 1; $? "+ dk3fig_prepare_object" /* For object 0 check whether it is a background rectangle. Set srctype. */ dk3fig_prepare_check_bgrect(drw, obj, objno); /* Check for open path to fill. */ dk3fig_prepare_check_fill_open_path(drw, obj); /* Object type specific initialization. For arcs calculate center point and radius. */ if(!dk3fig_prepare_initialize_object(drw, obj, objno, 1)) { back = 0; $? "! initialization failed" } /* For open objects calculate arrowheads. */ if(back) { if(!dk3figah_calculate_arrowheads(drw, obj, objno)) { back = 0; $? "! arrowhead calculation failed" } } /* Add object to bounding box. For open objects add arrowheads to bounding box too. */ if(back) { $!trace-code dk3fig_prepare_report_object(obj, 1); if(!dk3fig_prepare_add_to_bb(drw, obj, 1)) { back = 0; $? "! add to bb failed" dk3app_log_1(drw->app, DK3_LL_ERROR, drw->msg, 4); } } $? "- dk3fig_prepare_object %d", back return back; } int dk3fig_prepare(dk3_fig_drawing_t *drw) { dk3_fig_obj_t *obj; unsigned long oldsourceline = 0UL; unsigned long objno = 0UL; int back = 1; $? "+ dk3fig_prepare" /* Reset bounding box. */ dk3bb_reset(&(drw->bb)); /* Prepare all drawing elements. */ oldsourceline = dk3app_get_source_line(drw->app); dk3sto_it_reset(drw->iobj); while(NULL != (obj = (dk3_fig_obj_t *)dk3sto_it_next(drw->iobj))) { dk3app_set_source_line(drw->app, obj->li); if(!dk3fig_prepare_object(drw, obj, objno++)) { back = 0; } } dk3app_set_source_line(drw->app, oldsourceline); $? ". x = %lg ... %lg y = %lg ... %lg", (drw->bb).xmin, (drw->bb).xmax, (drw->bb).ymin, (drw->bb).ymax $? "- dk3fig_prepare %d", back return back; }