%% options copyright owner = Dirk Krause copyright year = 2019-xxxx SPDX-License-Identifier: BSD-3-Clause %% header /** @file WxdkdrawObj.h Graphics elements handling. */ #ifndef WXDKDRAWTYPES_H_INCLUDED #include "WxdkdrawTypes.h" #endif #ifndef WXDENUM_H_INCLUDED #include "wxdenum.h" #endif /* PROTOTYPES (start) */ /* Create and destroy drawing -------------------------- */ /** Open a new empty drawing. @return Valid pointer on success, NULL on error (not enough memory). */ Wxd_drawing_t * wxdobj_drw_new(void); /** Delete drawing including all contents. @param pdrw Drawing to delete. */ void wxdobj_drw_delete(Wxd_drawing_t *pdrw); /** Set required redraw level. During handling one event this function may be called multiple times. The maximum of the required redraw levels is saved in the drawing. @param pdrw Drawing to update. @param level Required minimum redraw level. */ void wxdobj_drw_require_redraw(Wxd_drawing_t *pdrw, int level); /** Retrieve required redraw level. This function should be called at the end of event handlers to check whether or not to refresh and update the control and from within the repaint handler to check which caches to update. @param pdrw Drawing to check. @param level Required redraw level already found. @return Required redraw level. */ int wxdobj_drw_get_required_redraw_level( Wxd_drawing_t *pdrw, int level = WXD_REFRESH_NONE ); /** Reset required redraw level. This function should be called from the repaint handler when redrawing is done. @param pdrw Drawing to modify. */ void wxdobj_drw_reset_required_redraw_level(Wxd_drawing_t *pdrw); /* Create and destroy elements without registration and unregistration to drawing ------------------------------------------------ */ /** Initialize bounding box structure. @param pdst Structure to initialize. */ void wxdobj_det_init_bb(Wxd_bb_t *pdst); /** Initialize text details structure. @param pdst Structure to initialize. */ void wxdobj_det_init_text(Wxd_det_text_t *pdst); /** Initialize polyline or polygon details structure. @param pdst Structure to initialize. */ void wxdobj_det_init_poly(Wxd_det_pl_t *pdst); /** Initialize spline details structure. @param pdst Structure to initialize. */ void wxdobj_det_init_spline(Wxd_det_xs_t *pdst); /** Initialize arc details structure. @param pdst Structure to initialize. */ void wxdobj_det_init_arc(Wxd_det_arc_t *pdst); /** Initialize details structure for ellipse or circle. @param pdst Structure to initialize. */ void wxdobj_det_init_ellipse(Wxd_det_ellipse_t *pdst); /** Initialize box details structure. @param pdst Structure to initialize. */ void wxdobj_det_init_box(Wxd_det_box_t *pdst); /** Initialize image details structure. @param pdst Structure to initialize. */ void wxdobj_det_init_image(Wxd_det_image_t *pdst); /** Initialize dot details structure. @param pdst Structure to initialize. */ void wxdobj_det_init_dot(Wxd_det_dot_t *pdst); /** Initialize object, use template if specified. @param pdst Object to initialize. @param ot Object type. @param ptpl Template object, may be NULL. */ void wxdobj_obj_init(Wxd_object_t *pdst, int ot, Wxd_object_t const *ptpl = NULL); /** Delete group structure recursively. Only group structural information is deleted, graphics objects remain intact. The parent information of all graphics objects is set to NULL. */ void wxdobj_grp_delete_recursive(Wxd_object_t *pgrp); /** Create polyline object. @param np Number of points. @param ptpl Style template. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_obj_new_polyline(uint16_t np, Wxd_object_t const *ptpl); /** Create polygon object. @param np Number of points. @param ptpl Style template. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_obj_new_polygon(uint16_t np, Wxd_object_t const *ptpl); /** Create spline object. @param np Number of points. @param cl Flag: Closed spline. @param ptpl Style template. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_obj_new_spline(uint16_t np, int cl, Wxd_object_t const *ptpl); /** Create arc object. @param cl Flag: Closed arc. @param ptpl Style template. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_obj_new_arc(int cl, Wxd_object_t const *ptpl); /** Create circle object. @param ptpl Style template. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_obj_new_circle(Wxd_object_t const *ptpl); /** Create ellipse object. @param ptpl Style template. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_obj_new_ellipse(Wxd_object_t const *ptpl); /** Create box object. @param ptpl Style template. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_obj_new_box(Wxd_object_t const *ptpl); /** Create image object. @param fn Image file name. @param ptpl Style template. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_obj_new_image(wxChar const *fn, Wxd_object_t const *ptpl); /** Create dot object. @param wh Flag: White filled dot. @param ptpl Style template. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_obj_new_dot(int wh, Wxd_object_t const *ptpl); /** Create new text label. @param te Export text. @param ptpl Style template. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_obj_new_textlabel(wxChar const *te, Wxd_object_t const *ptpl); /** Delete object, release memory. The object is not unregistered from the drawing. For a group object the storage and iterator are just closed, no recursive processing. @param pobj Object to delete. */ void wxdobj_obj_delete(Wxd_object_t *pobj); /* Create new elements in a drawing (create element and register it in the drawings storages) ---------------------------------------------------------------- */ /** Register an object in drawing and group structure. @param pdrw Drawing to register object. @param pgrp Objects parent group or NULL for a top-level element. @param pobj Object to register in drawing. */ int wxdobj_drw_register_object( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, Wxd_object_t *pobj ); /** Add a new group to a drawing, register it in structered storage. @param pdrw Drawing to add group to. @param pgrp Parent group, NULL for a new top-level group. @return Valid pointer to new group on success, NULL on error. */ Wxd_object_t * wxdobj_drw_add_group( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp ); /** Add a new polyline to drawing and register it in the storages. @param pdrw Drawing to add to. @param pgrp Parent group, NULL for top-level object. @param np Number of points. @param cl Flag: Closed polyline (polygon). @param ptpl Style template, may be NULL. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_add_polyline( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, uint16_t np, int cl, Wxd_object_t const *ptpl ); /** Add point to polygon or polyline. @param pobj Polygon or polyline to modify. @param pind Index of new point. @param erp Error report, may be NULL. @return True on success, false on error (memory). */ bool wxdobj_add_polypoint( Wxd_object_t *pobj, uint16_t pind, dk4_er_t *erp ); /** Delete one polyline or polygon point. @param pobj Polyline or polygon object to modify. @param pind Index of point to delete. @param erp Error report, may be NULL. @return True on success, false on error (memory). */ bool wxdobj_del_polypoint( Wxd_object_t *pobj, uint16_t pind, dk4_er_t *erp ); /** Add a new spline to drawing and register it in the storages. @param pdrw Drawing to add to. @param pgrp Parent group, NULL for top-level object. @param np Number of points. @param cl Flag: Closed spline. @param ptpl Style template, may be NULL. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_add_spline( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, uint16_t np, int cl, Wxd_object_t const *ptpl ); /** Add point to spline. @param pobj Spline to modify. @param pind Index of new point. @param erp Error report, may be NULL. @return True on success, false on error (memory). */ bool wxdobj_add_splinepoint( Wxd_object_t *pobj, uint16_t pind, dk4_er_t *erp ); /** Delete one spline point. @param pobj Open or closed spline object to modify. @param pind Index of point to delete. @param erp Error report, may be NULL. @return True on success, false on error (memory). */ bool wxdobj_del_splinepoint( Wxd_object_t *pobj, uint16_t pind, dk4_er_t *erp ); /** Add a new arc to drawing and register it in the storages. @param pdrw Drawing to add to. @param pgrp Parent group, NULL for top-level object. @param cl Flag: Closed polyline (polygon). @param ptpl Style template, may be NULL. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_add_arc( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, int cl, Wxd_object_t const *ptpl ); /** Add a new circle to drawing and register it in the storages. @param pdrw Drawing to add to. @param pgrp Parent group, NULL for top-level object. @param ptpl Style template, may be NULL. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_add_circle( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, Wxd_object_t const *ptpl ); /** Add a new ellipse to drawing and register it in the storages. @param pdrw Drawing to add to. @param pgrp Parent group, NULL for top-level object. @param ptpl Style template, may be NULL. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_add_ellipse( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, Wxd_object_t const *ptpl ); /** Add a new box to drawing and register it in the storages. @param pdrw Drawing to add to. @param pgrp Parent group, NULL for top-level object. @param ptpl Style template, may be NULL. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_add_box( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, Wxd_object_t const *ptpl ); /** Add a new polyline to drawing and register it in the storages. @param pdrw Drawing to add to. @param pgrp Parent group, NULL for top-level object. @param fn File name of image file. @param ptpl Style template, may be NULL. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_add_image( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, wxChar const *fn, Wxd_object_t const *ptpl ); /** Add a new dot to drawing and register it in the storages. @param pdrw Drawing to add to. @param pgrp Parent group, NULL for top-level object. @param wh Flag: White filled dot. @param ptpl Style template, may be NULL. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_add_dot( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, int wh, Wxd_object_t const *ptpl ); /** Add a new text label to the drawing and register it to the storages. @param pdrw Drawing to add to. @param pgrp Parent group, NULL for top-level object. @param te Export text. @param ptpl Style template, may be NULL. @return Valid pointer on success, NULL on error. */ Wxd_object_t * wxdobj_add_textlabel( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, wxChar const *te, Wxd_object_t const *ptpl ); /* Modify elements within a drawing, update registration if necessary ----------------------------------------------------- */ /** Check whether or not object is active. @param pobj Object to check. @return True normally, false for objects on inactive layers. */ bool wxdobj_is_active(Wxd_object_t *pobj); /** Increase point number of polyline or polygon by one (after clicking on a new point to add). @param pobj Object to modify. @return 1 on success, 0 on error. */ int wxdobj_mod_poly_add_point( Wxd_object_t *pobj ); /** Decrease point number of polyline or polygon by one (after right-clicking for finalizing). @param pobj Object to modify. @return 1 on success, 0 on error. */ int wxdobj_mod_poly_del_point( Wxd_object_t *pobj ); /** Increase point number of spline by one (after clicking on a new point to add). @param pobj Object to modify. @return 1 on success, 0 on error. */ int wxdobj_mod_spline_add_point( Wxd_object_t *pobj ); /** Decrease point number of spline by one (after right-clicking for finalizing). @param pobj Object to modify. @return 1 on success, 0 on error. */ int wxdobj_mod_spline_del_point( Wxd_object_t *pobj ); /** Find group containing an object. @param pdrw Drawing containing the object. @param pobj Object to search for. @return Valid pointer to group on success, NULL on error. */ Wxd_object_t * wxdobj_find_group_for(Wxd_drawing_t *pdrw, Wxd_object_t *pobj); /** Ensure object has layer structure pointer. @param pdrw Drawing. @param pobj Object to check. @return 1 on success, 0 on error. */ int wxdobj_find_layer_structure(Wxd_drawing_t *pdrw, Wxd_object_t *pobj); /** Check whether an object needs a stipple structure. @param pobj Object to check. @return 1 for true, 0 for false. */ int wxdobj_needs_stipple( Wxd_object_t *pobj ); /** Modify layer of an object. This includes reorganization of sorted storages. @param pdrw Drawing to modify. @param pobj Object for layer change. @param nl New layer number. @return 1 on success, 0 on error. */ int wxdobj_modify_layer( Wxd_drawing_t *pdrw, Wxd_object_t *pobj, int16_t nl ); /** Correct bounding box and/or generic rectangle. @param bbptr Rectangle to correct. */ void wxdobj_bb_correct(Wxd_bb_t *bbptr, uint16_t *ppoint = NULL); /** Check for incorrect rectangle (width or height 0 or negative). @param bbptr Rectangle to check. @return True for incorrect rectangle. */ bool wxdobj_bb_is_null_area(Wxd_bb_t *bbptr); /** Check two rectangles for intersection, find intersection area if any. The intersection area is saved to res only if the function returns true. @param res Address of result rectangle variable. @param a One rectangle to check. @param b Other rectangle to check. @return True if there is any intersection, false otherwise. */ bool wxdobj_bb_intersection( Wxd_bb_t *res, Wxd_bb_t const *a, Wxd_bb_t const *b ); /** Find bitmap type for file name. @param fn File name to check. @return Bitmap image type on success, wxBITMAP_TYPE_INVALID on error (file name has no suffix or suffix not in the list of supported types). */ wxBitmapType wxdobj_image_type(wxChar const *fn); /** Load image from file. @param pobj Image object, must be type WXD_OT_IMAGE. @param dkenc Encoding used for dkChar strings. @param wxenc Encoding used for wxChar strings. */ void wxdobj_load_image( Wxd_object_t *pobj, int dkenc, int wxenc ); /** Calculate image placement, save in pl component. @param pobj Image object, must be type WXD_OT_IMAGE. */ void wxdobj_image_placement( Wxd_object_t *pobj ); /** Calculate distance from point to object. @param pobj Object to check. @param ppt Point to check. @return Distance from point to object if found, negative value otherwise. */ double wxdobj_distance_to_point( Wxd_object_t *pobj, Wxd_point_t const *ppt, bool bCtrlPt = false, uint16_t *pIndex = NULL ); /** Unmark all objects in drawing. @param pdrw Drawing to modify. @param marker Marker bit to delete from all objects. */ void wxdobj_unmark_all(Wxd_drawing_t *pdrw, uint8_t marker); /** Mark one object recursively. @param pobj Object to mark. @param marker Marker to set on object. */ void wxdobj_mark_recursively(Wxd_object_t *pobj, uint8_t marker); /** Unmark one object recursively. @param pobj Object to modify. @param marker Marker to remove from object. */ void wxdobj_unmark_recursively(Wxd_object_t *pobj, uint8_t marker); /** Find stipple structure for object. @param pdrw Drawing the object belongs to. @param pobj Object needing stipple. @return Valid pointer on success, NULL on error. */ Wxd_stipple_t * wxdobj_find_stipple_structure( Wxd_drawing_t *pdrw, Wxd_object_t *pobj ); /** Find font structure for object. @param pdrw Drawing the object belongs to. @param pobj Object needing font. @return Valid pointer on success, NULL on error. */ Wxd_font_t * wxdobj_find_font_structure( Wxd_drawing_t *pdrw, Wxd_object_t *pobj ); /** Remove unused stipple data from drawing. @param pdrw Drawing to clean up. */ void wxdobj_remove_unused_stipples( Wxd_drawing_t *pdrw ); /** Remove unused font data from drawing. @param pdrw Drawing to clean up. */ void wxdobj_remove_unused_fonts( Wxd_drawing_t *pdrw ); /** Get number of used layers in drawing. @param pdrw Drawing to check. @return Number of used layers, may be 0 for empty drawing. */ size_t wxdobj_get_number_of_layers( Wxd_drawing_t *pdrw ); /** Remove object from drawing. The object can be a simple object or a group object. When removing a group object all contents objects are removed too. @param pdrw Drawing containing the object. @param pobj Object to remove. */ void wxdobj_obj_delete_from_drawing( Wxd_drawing_t *pdrw, Wxd_object_t *pobj ); /** Shift drawing object for a difference. Call this function on members of the flat storage only. @param pobj Object to shift. @param ppt Point containing vector for shifting. @param doit Flag: Really do it (1=yes, 0=simulation/check only). @return 1 on success, 0 on error (mathematical overflow). */ int wxdobj_shift(Wxd_object_t *pobj, Wxd_point_t *ppt, int doit); /** Shift drawing objects marked by OBJ_MARKER_1 in a drawing. @param pdrw Drawing containing the objects to shift. @param ppt Point containing vector for shifting. @param doit Flag: Really do it (1=yes, 0=simulation/check only). @return 1 on success, 0 on error (mathematical overflow). */ int wxdobj_shift_marked(Wxd_drawing_t *pdrw, Wxd_point_t *ppt, int doit); /** Check whether a given marker is set on object. @param pobj Object to test. @param marker Marker to check for. @return Test result. */ bool wxdobj_is_marked(Wxd_object_t const *pobj, uint8_t marker); /** Create copy of an object. The copy is not registered to a drawing. @param psrc Object to copy, must not be a group. @return Valid pointer to new object on success, NULL on error. */ Wxd_object_t * wxdobj_copy(Wxd_object_t *psrc); /** Copy drawing object (recursively if object is a group). @param pdrw Drawing containing the object. @param pobj Drawing object, may be a group. @param psh Shift vector for the copy. @return 1 on success, 0 on error. */ int wxdobj_copy_recursive( Wxd_drawing_t *pdrw, Wxd_object_t *obj, Wxd_point_t *psh ); /** Report one object. @param pobj Object to report. */ void wxdobj_report_object( Wxd_object_t *pobj ); /** Find object and point index for point move operation. @param pdrw Drawing to search. @param ppt Mouse position. @param pindex Address of index variable to set on success. @param dlim Distance limit. @return Found object on success, NULL if no object found. */ Wxd_object_t * wxdobj_point_move_find_object( Wxd_drawing_t *pdrw, Wxd_point_t const *ppt, uint16_t *pindex, double dlim ); /** Find object and point index for spline value modification. @param pdrw Drawing to search. @param ppt Mouse position. @param pindex Address of index variable to set on success. @param dlim Distance limit. @return Found object on success, NULL if no object found. */ Wxd_object_t * wxdobj_modify_spline_find_object( Wxd_drawing_t *pdrw, Wxd_point_t const *ppt, uint16_t *pindex, double dlim ); /** Find object and point index for object rotation. @param pdrw Drawing to search. @param ppt Mouse position. @param pindex Address of index variable to set on success. @param dlim Distance limit. @return Found object on success, NULL if no object found. */ Wxd_object_t * wxdobj_rotate_find_object( Wxd_drawing_t *pdrw, Wxd_point_t const *ppt, uint16_t *pindex, double dlim ); /** Find object and point index for adding a further point. @param pdrw Drawing to search. @param ppt Mouse position. @param pindex Address of index variable to set on success. @param pbins Address of flag, whether to append after or insert before. @param dlim Distance limit. @return Found object on success, NULL if no object found. */ Wxd_object_t * wxdobj_point_add_find_object( Wxd_drawing_t *pdrw, Wxd_point_t const *ppt, uint16_t *pindex, bool *pbapp, double dlim ); /** Find object and point index for point delete operation. @param pdrw Drawing to search. @param ppt Mouse position. @param pindex Address of index variable to set on success. @param dlim Distance limit. @return Found object on success, NULL if no object found. */ Wxd_object_t * wxdobj_point_del_find_object( Wxd_drawing_t *pdrw, Wxd_point_t const *ppt, uint16_t *pindex, double dlim ); /** Retrieve control point coordinates. @param pdst Destination variable to save point coordinates. @param psrc Object to retrieve control point from. @param pind Control point index. @return True on success, false on error. */ bool wxdobj_get_control_point( Wxd_point_t *pdst, Wxd_object_t const *psrc, uint16_t pind ); /** Modify control point coordinates. @param pdst Destination object to modify control point. @param psrc New control point coordinates. @param pind Control point index. @return True on success, false on error. */ bool wxdobj_set_control_point( Wxd_object_t *pdst, Wxd_point_t const *psrc, uint16_t pind ); /** Delete one control point of polygon, polyline or spline. @param pdst Destination object to modify control points. @param pind Control point index. */ void wxdobj_delete_control_point( Wxd_object_t *pdst, uint16_t pind ); /** Add one control point to polygon, polyline or spline. @param pdst Destination object to modify control points. @param pind Control point index. @return True on success, false on error. */ bool wxdobj_add_control_point( Wxd_object_t *pdst, uint16_t pind, Wxd_point_t const *ppt ); /** Calculate distance from point to box. @param pbox Box coordinates. @param r Radius for rounded corners. @param ppt Point coordinates. @param bCtrlPt Find distance to control points, not lines. @param pIndex Address of index variable for control points. @return Distance from point ppt to box. */ double wxdobj_dist_box( Wxd_bb_t *pbox, uint32_t r, dk4_gra_point_t *ppt, bool bCtrlPt, uint16_t *pIndex ); /** Calculate distance from point to box. @param pbox Box coordinates. @param ppt Point coordinates. @param pIndex Address of index variable for control points. @param dlim Distance limit. @return True if point is near enough to control point, false otherwise. */ bool wxdobj_ctrlpt_dist_box( Wxd_bb_t *pbox, dk4_gra_point_t *ppt, uint16_t *pIndex, double dlim ); /** Set a bounding box structure with control points from an object. @param pbox Bounding box to set up. @param pobj Object to use, must be simple object (not a group). */ bool wxdobj_control_pt_to_bb( Wxd_bb_t *pbox, Wxd_object_t const *pobj ); /** Add object bounding box to another bounding box. @param pbox Accumulated bounding box information for all objects. @param psrc Bounding box information to add for one object. */ bool wxdobj_bb_add_bb( Wxd_bb_t *pbox, Wxd_bb_t const *psrc ); /** Flip one object, use collected bounding box information. @param pobj Object to flip. @param pbox Bounding box information to use. @param bVert Flip vertically (true) or horizontally (false). @param bRealRun Really flip object (false: test only). */ bool wxdobj_flip_object( Wxd_object_t *pobj, Wxd_bb_t const *pbox, bool bVert = false, bool bRealRun = true ); /** Find number of objects in structured storage marked by marker 2. @param pdrw Drawing to check. @return 0, 1 or 2 (for 2 and more). */ int wxdobj_num_marked_2(Wxd_drawing_t *pdrw); /** Find bounding box for a simple graphics element. @param pdrw Drawing containing the graphics element. @param pobj Graphics element to find bounding box for. @return True on success, false on error. */ bool wxdobj_bb_simple_object( Wxd_drawing_t const *pdrw, Wxd_object_t *pobj ); /** Rebuild bounding box for structural nodes in a group. Bounding boxes for simple objects are not renewed. @param pdrw Drawing containing the graphics element. @param pobj Graphics element to find bounding box for. @return True on success, false on error. */ bool wxdobj_bb_group_structural( Wxd_drawing_t const *pdrw, Wxd_object_t *pobj ); /** Rebuild bounding box for a group completely (both for structural nodes and simple objects. @param pdrw Drawing containing the graphics element. @param pobj Graphics element to find bounding box for. @return True on success, false on error. */ bool wxdobj_bb_group_and_contents( Wxd_drawing_t const *pdrw, Wxd_object_t *pobj ); /** Rebuild bounding box for a modified object. If the modified (moved) object is a group, rebuild the bounding box completely. If a simple object was modified, rebuild the bounding box for that object; if the object is member of a group, rebuild the groups structural bounding boxes. @param pdrw Drawing containing the graphics element. @param pobj Graphics element to find bounding box for. @return True on success, false on error. */ bool wxdobj_bb_modified_object( Wxd_drawing_t const *pdrw, Wxd_object_t *pobj ); /** (Re)build bounding box information for all drawing elements. @param pdrw Drawing to build bounding box information for. @return True on success, false on error. */ bool wxdobj_bb_for_drawing( Wxd_drawing_t *pdrw ); /** Set number of sub segments per X-spline segment. @param pdrw Drawing to set up. @param xs Number of sub segments per X-spline segment. */ void wxdobj_drw_set_xsubs(Wxd_drawing_t *pdrw, size_t xs); /** Check whether a text label object is a LaTeX text label. @param pobj Object to check. @rturn True for LaTeX text labels, false otherwise. */ bool wxdobj_text_is_latex(Wxd_object_t const *pobj); /** Check whether an object can be converted to another object type. @param destot Destination object type. @param pobj Object to check. @return True if the conversion is possible, false otherwise. */ bool wxdobj_can_convert( int destot, const Wxd_object_t *pobj ); /** Rotate an object by 90 degree. @param pobj Object to rotate. @param x0 Center point x coordinate. @param y0 Center point y coordinate. @param neg Flag: Negative direction (false=positive). @param doit Flag: Really do it (false=test only). @return True on success, false on error. */ bool wxdobj_rotate_object( Wxd_object_t *pobj, int32_t x0, int32_t y0, bool neg, bool doit ); /** Check two bounding boxes for equality. @param pa One bounding box. @param pb Other bounding box. @return True if both boxes are equal, false otherwise. */ bool wxdobj_bb_equal(Wxd_bb_t const *pa, Wxd_bb_t const *pb); /* PROTOTYPES (end) */ /* vim: set ai sw=4 ts=4 : */ %% module #include "wxdkdraw.h" #if DK4_HAVE_MATH_H #ifndef MATH_H_INCLUDED #include #define MATH_H_INCLUDED 1 #endif #endif #ifndef DK4MATH_H_INCLUDED #include #endif #ifndef DK4BIF_H_INCLUDED #include #endif #ifndef DK4MAAU16_H_INCLUDED #include "dk4maau16.h" #endif #ifndef DK4MAAI16_H_INCLUDED #include "dk4maai16.h" #endif #ifndef DK4MAAI32_H_INCLUDED #include "dk4maai32.h" #endif $!trace-include /** Image types handled by wxdkdraw. */ static const Wxd_suffix_and_type_t image_type_suffixes[] = { { wxT(".png") , wxBITMAP_TYPE_PNG } , { wxT(".jpg") , wxBITMAP_TYPE_JPEG } , { wxT(".jpeg") , wxBITMAP_TYPE_JPEG } , { wxT(".pbm") , wxBITMAP_TYPE_PNM } , { wxT(".pgm") , wxBITMAP_TYPE_PNM } , { wxT(".ppm") , wxBITMAP_TYPE_PNM } , { wxT(".pnm") , wxBITMAP_TYPE_PNM } , { wxT(".pam") , wxBITMAP_TYPE_PNM } , { wxT(".tif") , wxBITMAP_TYPE_TIF } , { wxT(".tiff") , wxBITMAP_TYPE_TIFF } , { NULL , wxBITMAP_TYPE_INVALID } }; /** Angles to check when calculating arc bounding box. */ static double arc_angles[] = { (-4.0 * M_PI), (-3.0 * M_PI - M_PI_2), (-3.0 * M_PI), (-2.0 * M_PI - M_PI_2), (-2.0 * M_PI), (-1.0 * M_PI - M_PI_2), (-1.0 * M_PI), (-1.0 * M_PI_2), 0.0, M_PI_2, M_PI, (M_PI + M_PI_2), (2.0 * M_PI), (2.0 * M_PI + M_PI_2), (3.0 * M_PI), (3.0 * M_PI + M_PI_2) }; /** Number of elements in arc_angles array. */ static const size_t sz_arc_angles = sizeof(arc_angles)/sizeof(double); /** Flip coordinate value. @param min Bounding box minimum. @param max Bounding box maximum. @param v Value to flip. @param erp Error report, may be NULL. @return Flip result. */ static int32_t wxdobj_flip_coordinate(int32_t min, int32_t max, int32_t v, dk4_er_t *erp) { dk4_er_t er; int32_t back = (int32_t)0L; dk4error_init(&er); back = dk4ma_int32_t_sub(dk4ma_int32_t_add(min, max, &er), v, &er); if (DK4_E_NONE != er.ec) { dk4error_init(&er); back = dk4ma_int32_t_add(min, dk4ma_int32_t_sub(max, v, &er), &er); if (DK4_E_NONE != er.ec) { dk4error_init(&er); back = dk4ma_int32_t_add(max, dk4ma_int32_t_sub(min, v, &er), &er); if (DK4_E_NONE != er.ec) { dk4error_init(&er); back = dk4ma_int32_from_double( ((double)min + (double)max - (double)v), &er ); if (DK4_E_NONE != er.ec) { dk4error_copy(erp, &er); } } } } return back; } /** Set bounding box x and y value. Use this function to add the first point. @param pbox Bounding box to set. @param x X coordinate. @param y Y coordinate. */ static void wxdobj_bb_set_point( Wxd_bb_t *pbox, int32_t x, int32_t y ) { if (NULL != pbox) { pbox->xl = pbox->xr = x; pbox->yb = pbox->yt = y; } } /** Add bounding box x and y value. Use this function to add further points. @param pbox Bounding box to set. @param x X coordinate. @param y Y coordinate. */ static void wxdobj_bb_add_point( Wxd_bb_t *pbox, int32_t x, int32_t y ) { if (NULL != pbox) { if (x < pbox->xl) { pbox->xl = x; } if (x > pbox->xr) { pbox->xr = x; } if (y < pbox->yb) { pbox->yb = y; } if (y > pbox->yt) { pbox->yt = y; } } } bool wxdobj_bb_add_bb( Wxd_bb_t *pbox, Wxd_bb_t const *psrc ) { bool back = false; if ((NULL != pbox) && (NULL != psrc)) { wxdobj_bb_add_point(pbox, psrc->xl, psrc->yb); wxdobj_bb_add_point(pbox, psrc->xr, psrc->yt); back = true; } return back; } void wxdobj_report_object( #if TRACE_DEBUG Wxd_object_t *pobj #else Wxd_object_t * DK4_ARG_UNUSED(pobj) #endif ) { #if TRACE_DEBUG double s; uint16_t i; int32_t x; int32_t y; $? "+ wxdobj_report_object" if (NULL != pobj) { switch (pobj->ot) { case WXD_OT_GROUP_BEGIN : { $? ". group object" } break; case WXD_OT_TEXT : { $? ". text object" } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { if (WXD_OT_POLYLINE == pobj->ot) { $? ". polyline" } else { $? ". polygon" } $? ". points: %u", (unsigned)((pobj->det).p.n) if (NULL != (pobj->det).p.p) { for (i = 0; i < (pobj->det).p.n; i++) { x = ((pobj->det).p.p)[i].x; y = ((pobj->det).p.p)[i].y; $? ". [%u] x = %ld y = %ld",(unsigned)i,(long)x,(long)y } } else { $? "! no point data available" } } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { if (WXD_OT_O_SPLINE == pobj->ot) { $? ". open spline" } else { $? ". closed spline" } $? ". points: %u", (unsigned)((pobj->det).s.n) if (NULL != (pobj->det).p.p) { for (i = 0; i < (pobj->det).s.n; i++) { x = ((pobj->det).s.p)[i].x; y = ((pobj->det).s.p)[i].y; s = ((pobj->det).s.p)[i].s; $? ". [%u] x = %ld y = %ld s = %g",(unsigned)i,(long)x,(long)y,s } } else { $? "! no point data available" } } break; case WXD_OT_O_ARC : case WXD_OT_C_ARC : { if (WXD_OT_O_ARC == pobj->ot) { $? ". open arc" } else { $? ". closed arc" } } break; case WXD_OT_CIRCLE : case WXD_OT_ELLIPSE : { if (WXD_OT_CIRCLE == pobj->ot) { $? ". circle" } else { $? ". ellipse" } $? ". x = %ld", (long)((pobj->det).e.x) $? ". y = %ld", (long)((pobj->det).e.y) $? ". rx = %lu", (unsigned long)((pobj->det).e.rx) $? ". ry = %lu", (unsigned long)((pobj->det).e.ry) $? ". a = %d", (int)((pobj->det).e.a) } break; case WXD_OT_BOX : { $? ". box" } break; case WXD_OT_IMAGE : { $? ". image" } break; case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : { if (WXD_OT_DOT_FILLED == pobj->ot) { $? ". colour filled dot" } else { $? ". white dot" } } break; default : { } break; } } else { $? "! NULL pointer" } $? "- wxdobj_report_object" #else DK4_UNUSED_ARG(pobj) #endif } bool wxdobj_is_active(Wxd_object_t *pobj) { bool back = false; $? "+ wxdobj_is_active" if (NULL != pobj) { back = true; if (NULL != pobj->play) { if ((uint8_t)0x00 == pobj->play->active) { back = false; } } } $? "- wxdobj_is_active %d", (back ? 1 : 0) return back; } wxBitmapType wxdobj_image_type(wxChar const *fn) { wxChar const *suffix; Wxd_suffix_and_type_t const *tptr; wxBitmapType back = wxBITMAP_TYPE_INVALID; $? "+ wxdobj_image_type" suffix = dk4strx_get_path_suffix(fn, NULL); if (NULL != suffix) { tptr = image_type_suffixes; while ((NULL != tptr->suffix) && (wxBITMAP_TYPE_INVALID == back)) { if (0 == dk4strx_casecmp(tptr->suffix, suffix)) { back = tptr->t; } else { tptr++; } } } $? "- wxdobj_image_type %d", (int)back return back; } void wxdobj_det_init_bb(Wxd_bb_t *pdst) { $? "+ wxdobj_det_init_bb %d", TR_IPTR(pdst) if (NULL != pdst) { DK4_MEMRES(pdst,sizeof(Wxd_bb_t)); pdst->xl = (int32_t)0L; pdst->xr = (int32_t)0L; pdst->yb = (int32_t)0L; pdst->yt = (int32_t)0L; } $? "- wxdobj_det_init_bb" } void wxdobj_det_init_text(Wxd_det_text_t *pdst) { $? "+ wxdobj_det_init_text %d", TR_IPTR(pdst) if (NULL != pdst) { DK4_MEMRES(pdst,sizeof(Wxd_det_text_t)); pdst->t = NULL; pdst->tsc = NULL; pdst->font = NULL; pdst->x = (int32_t)0L; pdst->y = (int32_t)0L; pdst->fsz = (uint16_t)12U; pdst->a = (int16_t)0; pdst->find = (uint8_t)0U; pdst->al = WXD_TA_LEFT; pdst->fl = 0x01; pdst->font = NULL; } $? "- wxdobj_det_init_text" } void wxdobj_det_init_poly(Wxd_det_pl_t *pdst) { $? "+ wxdobj_det_init_poly %d", TR_IPTR(pdst) if (NULL != pdst) { DK4_MEMRES(pdst,sizeof(Wxd_det_pl_t)); pdst->p = NULL; pdst->n = (uint16_t)0U; } $? "- wxdobj_det_init_poly" } void wxdobj_det_init_spline(Wxd_det_xs_t *pdst) { $? "+ wxdobj_det_init_spline %d", TR_IPTR(pdst) if (NULL != pdst) { DK4_MEMRES(pdst,sizeof(Wxd_det_xs_t)); pdst->p = NULL; pdst->n = (uint16_t)0U; } $? "- wxdobj_det_init_spline" } void wxdobj_det_init_arc(Wxd_det_arc_t *pdst) { $? "+ wxdobj_det_init_arc %d", TR_IPTR(pdst) if (NULL != pdst) { DK4_MEMRES(pdst,sizeof(Wxd_det_arc_t)); pdst->a = 0.0; pdst->b = 360.0; pdst->x = 0.0; pdst->y = 0.0; pdst->r = 0.0; pdst->x1 = (int32_t)0L; pdst->y1 = (int32_t)0L; pdst->x2 = (int32_t)0L; pdst->y2 = (int32_t)0L; pdst->x3 = (int32_t)0L; pdst->y3 = (int32_t)0L; pdst->d = (int8_t)0; } $? "- wxdobj_det_init_arc" } void wxdobj_det_init_ellipse(Wxd_det_ellipse_t *pdst) { $? "+ wxdobj_det_init_ellipse %d", TR_IPTR(pdst) if (NULL != pdst) { DK4_MEMRES(pdst,sizeof(Wxd_det_ellipse_t)); pdst->x = (int32_t)0L; pdst->y = (int32_t)0L; pdst->rx = (uint32_t)0UL; pdst->ry = (uint32_t)0UL; pdst->a = (int16_t)0; } $? "- wxdobj_det_init_ellipse" } void wxdobj_det_init_box(Wxd_det_box_t *pdst) { $? "+ wxdobj_det_init_box %d", TR_IPTR(pdst) if (NULL != pdst) { DK4_MEMRES(pdst,sizeof(Wxd_det_box_t)); wxdobj_det_init_bb(&(pdst->b)); pdst->r = (uint32_t)0UL; } $? "- wxdobj_det_init_box" } void wxdobj_det_init_image(Wxd_det_image_t *pdst) { $? "+ wxdobj_det_init_image %d", TR_IPTR(pdst) if (NULL != pdst) { DK4_MEMRES(pdst,sizeof(Wxd_det_image_t)); pdst->fn = NULL; pdst->bm = NULL; dk4bb_init(&(pdst->pl)); wxdobj_det_init_bb(&(pdst->br)); pdst->xres = -1.0; pdst->yres = -1.0; pdst->fl = WXD_IMFL_ASPECT | WXD_IMFL_USE_ALPHA | WXD_IMFL_IMG_INT | WXD_IMFL_USE_DCT; pdst->r2g = (int8_t)(-1); pdst->r2c = (int8_t)(-1); pdst->t = wxBITMAP_TYPE_INVALID; } $? "- wxdobj_det_init_image" } void wxdobj_det_init_dot(Wxd_det_dot_t *pdst) { $? "+ wxdobj_det_init_dot %d", TR_IPTR(pdst) if (NULL != pdst) { DK4_MEMRES(pdst,sizeof(Wxd_det_dot_t)); pdst->x = (int32_t)0L; pdst->y = (int32_t)0L; pdst->d = (uint16_t)0U; } $? "- wxdobj_det_init_dot" } /** Initialize object, use template if specified. @param pdst Object to initialize. @param ot Object type. @param ptpl Template object, may be NULL. */ void wxdobj_obj_init(Wxd_object_t *pdst, int ot, Wxd_object_t const *ptpl) { $? "+ wxdobj_obj_init" if (NULL != ptpl) { $? ". from template" /* Apply template settings */ DK4_MEMCPY(pdst,ptpl,sizeof(Wxd_object_t)); } else { $? ". no template" /* Apply default settings */ DK4_MEMRES(pdst,sizeof(Wxd_object_t)); pdst->lay = 0; pdst->lw = 2; pdst->fc[0] = (uint8_t)255U; pdst->fc[1] = (uint8_t)255U; pdst->fc[2] = (uint8_t)255U; pdst->sc[0] = (uint8_t)0U; pdst->sc[1] = (uint8_t)0U; pdst->sc[2] = (uint8_t)0U; pdst->cs = (uint8_t)(WXD_LC_BUTTED); pdst->fs = (uint8_t)(WXD_FS_NONE); pdst->ls = (uint8_t)(WXD_LS_SOLID); pdst->sl = (uint8_t)4U; pdst->js = (uint8_t)(WXD_LJ_MITERED); pdst->ml = (uint8_t)8U; pdst->aft = (uint8_t)0U; pdst->afl = (uint8_t)16U; pdst->afw = (uint8_t)8U; pdst->abt = (uint8_t)0U; pdst->abl = (uint8_t)16U; pdst->abw = (uint8_t)8U; pdst->mark = (uint8_t)0U; } pdst->pa = NULL; pdst->psti = NULL; pdst->play = NULL; pdst->ot = ot; dk4bb_init(&(pdst->bb)); /* Use default values for details if no template was specified or template object type does not match */ if ((NULL == ptpl) || ((NULL != ptpl) && (ot != ptpl->ot))) { switch (ot) { case WXD_OT_GROUP_BEGIN : { } break; case WXD_OT_TEXT : { wxdobj_det_init_text(&((pdst->det).t)); } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { wxdobj_det_init_poly(&((pdst->det).p)); } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { wxdobj_det_init_spline(&((pdst->det).s)); } break; case WXD_OT_O_ARC : case WXD_OT_C_ARC : { wxdobj_det_init_arc(&((pdst->det).a)); } break; case WXD_OT_CIRCLE : case WXD_OT_ELLIPSE : { wxdobj_det_init_ellipse(&((pdst->det).e)); } break; case WXD_OT_BOX : { wxdobj_det_init_box(&((pdst->det).b)); } break; case WXD_OT_IMAGE : { wxdobj_det_init_image(&((pdst->det).i)); } break; case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : { wxdobj_det_init_dot(&((pdst->det).d)); } break; } } /* Make sure not to re-use dynamic objects from template. */ switch (ot) { case WXD_OT_GROUP_BEGIN : { (pdst->det).g.s_e = NULL; (pdst->det).g.i_e = NULL; } break; case WXD_OT_TEXT : { (pdst->det).t.t = NULL; (pdst->det).t.tsc = NULL; /* 2020-01-05 Set font to NULL too. */ (pdst->det).t.font = NULL; } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { (pdst->det).p.n = (uint16_t)0U; (pdst->det).p.p = NULL; } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { (pdst->det).s.n = (uint16_t)0U; (pdst->det).s.p = NULL; } break; case WXD_OT_O_ARC : case WXD_OT_C_ARC : { } break; case WXD_OT_CIRCLE : case WXD_OT_ELLIPSE : { } break; case WXD_OT_BOX : { } break; case WXD_OT_IMAGE : { (pdst->det).i.fn = NULL; (pdst->det).i.bm = NULL; } break; case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : { } break; } $? "- wxdobj_obj_init" } /** Check whether a layer is used in a drawing, remove layer if unused. @param pdrw Drawing to check and modify. @param play Layer to check and probably remove. */ static void i_check_layer_structure_removal(Wxd_drawing_t *pdrw, Wxd_layer_t *play) { Wxd_object_t *pobj; $? "+ i_check_layer_structure_removal %d", (int)(play->lay) play->used = 0x00; dk4sto_it_reset(pdrw->i_flat); do { pobj = (Wxd_object_t *)dk4sto_it_next(pdrw->i_flat); if (NULL != pobj) { if (NULL != pobj->play) { pobj->play->used = 0x01; } } } while (NULL != pobj); if (0x00 == play->used) { $? ". delete layer" dk4sto_remove(pdrw->s_layers, play, NULL); dk4sto_it_reset(pdrw->i_layers); dk4mem_free(play); } $? "- i_check_layer_structure_removal" } /** Find group for object. @param pdrw Drawing containing the object. @param pobj Object to search for. @return Valid pointer on success, NULL if not found. */ static Wxd_object_t * i_find_group_for(Wxd_drawing_t *pdrw, Wxd_object_t *pobj) { Wxd_object_t *back = NULL; /* Result */ Wxd_object_t *pgrc = NULL; /* Group candidate */ Wxd_object_t *pgrp = NULL; /* Current (sub)group tested */ Wxd_object_t *pno = NULL; /* Next object */ void *pt = NULL; /* Test whether object contained */ $? "+ i_find_group_for" dk4sto_it_reset(pdrw->i_stru); do { pgrc = (Wxd_object_t *)dk4sto_it_next(pdrw->i_stru); if (NULL != pgrc) { if (WXD_OT_GROUP_BEGIN == pgrc->ot) { if (NULL != dk4sto_it_find_exact((pgrc->det).g.i_e, pobj)) { /* Object found in top-level group */ back = pgrc; } else { /* Must search group structure recursively */ pgrp = pgrc; dk4sto_it_reset((pgrp->det).g.i_e); while ((NULL != pgrp) && (NULL == back)) { pno = (Wxd_object_t *)dk4sto_it_next((pgrp->det).g.i_e); if (NULL != pno) { if (WXD_OT_GROUP_BEGIN == pno->ot) { pt = dk4sto_it_find_exact((pno->det).g.i_e, pobj); if (NULL != pt) { back = pno; } else { pgrp = pno; dk4sto_it_reset((pgrp->det).g.i_e); } } } else { /* No more objects in group, go up 1 level */ pgrp = pgrp->pa; } } } } } } while ((NULL != pgrc) && (NULL == back)); #if TRACE_DEBUG if (NULL == back) { $? "! not found" } #endif $? "- i_find_group_for %d", TR_IPTR(back) return back; } void wxdobj_obj_delete(Wxd_object_t *pobj) { $? "+ wxdobj_obj_delete" if (NULL != pobj) { switch ( (int)(pobj->ot) ) { case WXD_OT_GROUP_BEGIN : { $? ". group" if (NULL != (pobj->det).g.i_e) { dk4sto_it_close((pobj->det).g.i_e); } if (NULL != (pobj->det).g.s_e) { dk4sto_close((pobj->det).g.s_e); } (pobj->det).g.s_e = NULL; (pobj->det).g.i_e = NULL; } break; case WXD_OT_TEXT : { $? ". text label" dk4mem_release((pobj->det).t.t); dk4mem_release((pobj->det).t.tsc); } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { $? ". polygon" dk4mem_release((pobj->det).p.p); } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { $? ". spline" dk4mem_release((pobj->det).s.p); } break; case WXD_OT_IMAGE : { $? ". image" dk4mem_release((pobj->det).i.fn); if (NULL != (pobj->det).i.bm) { $? ". have bitmap" delete (pobj->det).i.bm; (pobj->det).i.bm = NULL; } #if TRACE_DEBUG else { $? "! no bitmap" } #endif } break; #if TRACE_DEBUG case WXD_OT_O_ARC : { $? ". open arc" } break; case WXD_OT_C_ARC : { $? ". closed arc" } break; case WXD_OT_CIRCLE : { $? ". circle" } break; case WXD_OT_ELLIPSE : { $? ". ellipse" } break; case WXD_OT_BOX : { $? ". box" } break; case WXD_OT_DOT_FILLED : { $? ". dot" } break; case WXD_OT_DOT_WHITE : { $? ". white dot" } break; default : { $? ". other object" } break; #endif } dk4mem_free(pobj); } #if TRACE_DEBUG else { $? "! pobj" } #endif $? "- wxdobj_obj_delete" } /** Internally delete a group structure recursively. @param pgrp Group structure object to delete (must not be NULL, must be WXD_OT_GROUP_BEGIN type, s_e and i_e must not be NULL). */ static void grp_delete_recursive(Wxd_object_t *pgrp) { Wxd_object_t *no; /* Next object */ Wxd_object_t *ng; /* Next group */ $? "+ grp_delete_recursive" dk4sto_it_reset((pgrp->det).g.i_e); while (NULL != pgrp) { no = (Wxd_object_t *)dk4sto_it_next((pgrp->det).g.i_e); if (NULL != no) { if (WXD_OT_GROUP_BEGIN == no->ot) { if ((NULL != (no->det).g.s_e) && (NULL != (no->det).g.i_e)) { dk4sto_it_reset((no->det).g.i_e); pgrp = no; } else { dk4sto_remove((pgrp->det).g.s_e, no, NULL); dk4sto_it_reset((pgrp->det).g.i_e); #if 0 if (NULL != (no->det).g.s_e) { dk4sto_close((no->det).g.s_e); (no->det).g.s_e = NULL; } dk4mem_free(no); #endif wxdobj_obj_delete(no); } } else { no->pa = NULL; dk4sto_remove((pgrp->det).g.s_e, no, NULL); dk4sto_it_reset((pgrp->det).g.i_e); } } else { ng = pgrp->pa; if (NULL != ng) { dk4sto_remove((ng->det).g.s_e, pgrp, NULL); dk4sto_it_reset((ng->det).g.i_e); } #if 0 dk4sto_it_close((pgrp->det).g.i_e); (pgrp->det).g.i_e = NULL; dk4sto_close((pgrp->det).g.s_e); (pgrp->det).g.s_e = NULL; dk4mem_free(pgrp); #endif wxdobj_obj_delete(pgrp); pgrp = ng; } } $? "- grp_delete_recursive" } void wxdobj_grp_delete_recursive(Wxd_object_t *pgrp) { $? "+ wxdobj_grp_delete_recursive" if (NULL != pgrp) { if (WXD_OT_GROUP_BEGIN == pgrp->ot) { if ((NULL != (pgrp->det).g.s_e) && (NULL != (pgrp->det).g.i_e)) { grp_delete_recursive(pgrp); } else { if (NULL != (pgrp->det).g.s_e) { dk4sto_close((pgrp->det).g.s_e); (pgrp->det).g.s_e = NULL; } dk4mem_free(pgrp); } } } else { } $? "- wxdobj_grp_delete_recursive" } void wxdobj_drw_delete(Wxd_drawing_t *pdrw) { Wxd_object_t *pgrp; /* Current group to delete */ Wxd_stipple_t *pstip; /* Current stipple to delete */ Wxd_layer_t *play; /* Current layer to delete */ Wxd_font_t *pfont; /* Current font to delete */ $? "+ wxdobj_drw_delete" if (NULL != pdrw) { /* Delete structured information */ $? ". delete structured information" if (NULL != pdrw->s_stru) { if (NULL != pdrw->i_stru) { dk4sto_it_reset(pdrw->i_stru); do { pgrp = (Wxd_object_t *)dk4sto_it_next(pdrw->i_stru); if (NULL != pgrp) { if (WXD_OT_GROUP_BEGIN == pgrp->ot) { wxdobj_grp_delete_recursive(pgrp); } else { pgrp->pa = NULL; } } } while (NULL != pgrp); dk4sto_it_close(pdrw->i_stru); pdrw->i_stru = NULL; } dk4sto_close(pdrw->s_stru); pdrw->s_stru = NULL; } $? ". structured information deleted" /* Delete stipples */ $? ". delete stipples" if (NULL != pdrw->s_stip) { $? ". s_stip" if (NULL != pdrw->i_stip) { $? ". i_stip" dk4sto_it_reset(pdrw->i_stip); do { $? ". do" pstip = (Wxd_stipple_t *)dk4sto_it_next(pdrw->i_stip); if (NULL != pstip) { $? ". delete stipple %u (%u,%u,%u) (%u,%u,%u)", (unsigned)(pstip->cd[0]), (unsigned)(pstip->cd[1]),(unsigned)(pstip->cd[2]),(unsigned)(pstip->cd[3]),(unsigned)(pstip->cd[4]),(unsigned)(pstip->cd[5]),(unsigned)(pstip->cd[6]) if (NULL != pstip->bm) { $? ". have bitmap" delete (pstip->bm); pstip->bm = NULL; } else { $? "! no bitmap" } dk4mem_free(pstip); } } while (NULL != pstip); dk4sto_it_close(pdrw->i_stip); pdrw->i_stip = NULL; } #if TRACE_DEBUG else { $? "! i_stip" } #endif dk4sto_close(pdrw->s_stip); pdrw->s_stip = NULL; } #if TRACE_DEBUG else { $? "! s_stip" } #endif $? ". stipples deleted" /* Delete layers */ $? ". delete layers" if (NULL != pdrw->s_layers) { if (NULL != pdrw->i_layers) { dk4sto_it_reset(pdrw->i_layers); do { play = (Wxd_layer_t *)dk4sto_it_next(pdrw->i_layers); if (NULL != play) { $? ". delete layer %d", (int)(play->lay) dk4mem_free(play); } } while (NULL != play); dk4sto_it_close(pdrw->i_layers); pdrw->i_layers = NULL; } dk4sto_close(pdrw->s_layers); pdrw->s_layers = NULL; } $? ". layers deleted" /* Delete flat list and objects */ $? ". delete flat list" if (NULL != pdrw->s_flat) { if (NULL != pdrw->i_flat) { dk4sto_it_reset(pdrw->i_flat); do { pgrp = (Wxd_object_t *)dk4sto_it_next(pdrw->i_flat); if (NULL != pgrp) { $? ". delete one object from flat list" wxdobj_obj_delete(pgrp); } } while (NULL != pgrp); dk4sto_it_close(pdrw->i_flat); pdrw->i_flat = NULL; } dk4sto_close(pdrw->s_flat); pdrw->s_flat = NULL; } $? ". flat list deleted" $? ". delete fonts" /* Delete font structures */ if (NULL != pdrw->s_fonts) { if (NULL != pdrw->i_fonts) { dk4sto_it_reset(pdrw->i_fonts); do { pfont = (Wxd_font_t *)dk4sto_it_next(pdrw->i_fonts); if (NULL != pfont) { $? ". one font structure to delete" wxdfont_delete(pfont); } } while (NULL != pfont); dk4sto_it_close(pdrw->i_fonts); pdrw->i_fonts = NULL; } dk4sto_close(pdrw->s_fonts); pdrw->s_fonts = NULL; } $? ". fonts deleted" dk4mem_free(pdrw); $? ". finished" } #if TRACE_DEBUG else { $? "! pdrw" } #endif $? "- wxdobj_drw_delete" } void wxdobj_drw_set_xsubs(Wxd_drawing_t *pdrw, size_t xs) { if (NULL != pdrw) { if ((size_t)2U > xs) { xs = (size_t)2U; } pdrw->xsubs = xs; } } void wxdobj_drw_require_redraw(Wxd_drawing_t *pdrw, int level) { $? "+ wxdobj_drw_require_redraw %d", level if (NULL != pdrw) { if (level > pdrw->redraw) { pdrw->redraw = level; } } $? "- wxdobj_drw_require_redraw" } int wxdobj_drw_get_required_redraw_level(Wxd_drawing_t *pdrw, int level) { $? "+ wxdobj_drw_get_required_redraw_level %d", level if (NULL != pdrw) { if (pdrw->redraw > level) { level = pdrw->redraw; } } $? "- wxdobj_drw_get_required_redraw_level %d", level return level; } void wxdobj_drw_reset_required_redraw_level(Wxd_drawing_t *pdrw) { $? "+ wxdobj_drw_reset_required_redraw_level" if (NULL != pdrw) { pdrw->redraw = WXD_REFRESH_NONE; } $? "- wxdobj_drw_reset_required_redraw_level" } Wxd_drawing_t * wxdobj_drw_new(void) { Wxd_drawing_t *back = NULL; bool ok = false; $? "+ wxdobj_drw_new" back = dk4mem_new(Wxd_drawing_t,1,NULL); if (NULL != back) { /* Initialize drawing members */ back->s_stru = back->s_flat = back->s_stip = back->s_layers = back->s_fonts = NULL; back->i_stru = back->i_flat = back->i_stip = back->i_layers = back->i_fonts = NULL; (back->bb).xl = 0L; (back->bb).yb = 0L; (back->bb).xr = 130048000L; (back->bb).yt = 73152000L; back->xsubs = (size_t)8U; back->cx = 65024000L; back->cy = 36576000L; back->baselw = 101600L; back->bleft = 16256000L; back->bright = 16256000L; back->bbottom = 16256000L; back->btop = 16256000L; back->fv_maj = 1U; back->fv_min = 0U; back->zl = 0; back->gridunit = 0U; back->gridbase = 0U; back->s_stru = dk4sto_open(NULL); back->s_flat = dk4sto_open(NULL); back->s_stip = dk4sto_open(NULL); back->s_layers = dk4sto_open(NULL); back->s_fonts = dk4sto_open(NULL); /* After loading a drawing the first repaint must do a complete redraw. */ back->redraw = WXD_REFRESH_GRID; /* Allocate storages and iterators. */ if ( (NULL != back->s_stru) && (NULL != back->s_flat) && (NULL != back->s_stip) && (NULL != back->s_layers) && (NULL != back->s_fonts) ) { dk4sto_set_comp(back->s_stru, drawobj_compare_object, 0); dk4sto_set_comp(back->s_flat, drawobj_compare_object, 0); dk4sto_set_comp(back->s_stip, drawobj_compare_stipples, 0); dk4sto_set_comp(back->s_layers, drawobj_compare_layers, 0); dk4sto_set_comp(back->s_fonts, wxdfont_compare, 0); back->i_stru = dk4sto_it_open(back->s_stru, NULL); back->i_flat = dk4sto_it_open(back->s_flat, NULL); back->i_stip = dk4sto_it_open(back->s_stip, NULL); back->i_layers = dk4sto_it_open(back->s_layers, NULL); back->i_fonts = dk4sto_it_open(back->s_fonts, NULL); if ( (NULL != back->i_stru) && (NULL != back->i_flat) && (NULL != back->i_stip) && (NULL != back->i_layers) && (NULL != back->i_fonts) ) { ok = true; } } /* Check whether initialization completed successfully */ if(!(ok)) { $? "! memory" wxdobj_drw_delete(back); back = NULL; } } $? "- wxdobj_drw_new %d", TR_IPTR(back) return back; } #if 0 static Wxd_object_t * wxdobj_obj_new_text( wxChar const *t, wxChar const *tsc, Wxd_object_t const *ptpl ) { Wxd_object_t *back = NULL; $? "+ wxdobj_obj_new_text" if (NULL != t) { back = dk4mem_new(Wxd_object_t,1,NULL); if (NULL != back) { wxdobj_obj_init(back, WXD_OT_TEXT, ptpl); (back->det).t.t = dk4strx_dup(t, NULL); if (NULL == (back->det).t.t) { $? "! memory" dk4mem_free(back); back = NULL; } else { if (NULL != tsc) { (back->det).t.tsc = dk4strx_dup(tsc, NULL); if (NULL == (back->det).t.tsc) { $? "! memory" wxdobj_obj_delete(back); back = NULL; } } } } #if TRACE_DEBUG else { $? "! memory" } #endif } $? "- wxdobj_obj_new_text %d", TR_IPTR(back) return back; } #endif static Wxd_object_t * wxdobj_obj_new_polyany(uint16_t np, int ot, Wxd_object_t const *ptpl) { Wxd_object_t *back = NULL; $? "+ wxdobj_obj_new_polyany" back = dk4mem_new(Wxd_object_t,1,NULL); if (NULL != back) { wxdobj_obj_init(back, ot, ptpl); (back->det).p.n = np; (back->det).p.p = NULL; (back->det).p.p = dk4mem_new(Wxd_point_t,((size_t)np),NULL); if (NULL == (back->det).p.p) { $? "! memory" dk4mem_free(back); back = NULL; } } $? "- wxdobj_obj_new_polyany %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_obj_new_polyline(uint16_t np, Wxd_object_t const *ptpl) { Wxd_object_t *back = NULL; $? "+ wxdobj_obj_new_polyline" if ((uint16_t)1U < np) { back = wxdobj_obj_new_polyany(np, WXD_OT_POLYLINE, ptpl); } $? "- wxdobj_obj_new_polyline %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_obj_new_polygon(uint16_t np, Wxd_object_t const *ptpl) { Wxd_object_t *back = NULL; $? "+ wxdobj_obj_new_polygon" if ((uint16_t)1U < np) { back = wxdobj_obj_new_polyany(np, WXD_OT_POLYGON, ptpl); } $? "- wxdobj_obj_new_polygon %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_obj_new_spline(uint16_t np, int cl, Wxd_object_t const *ptpl) { Wxd_object_t *back = NULL; $? "+ wxdobj_obj_new_spline" if ((uint16_t)1U < np) { back = dk4mem_new(Wxd_object_t,1,NULL); if (NULL != back) { wxdobj_obj_init( back, ((0 != cl) ? (WXD_OT_C_SPLINE) : (WXD_OT_O_SPLINE)), ptpl ); (back->det).s.n = np; (back->det).s.p = dk4mem_new(Wxd_spline_point_t,((size_t)np),NULL); if (NULL == (back->det).s.p) { $? "! memory" dk4mem_free(back); back = NULL; } } #if TRACE_DEBUG else { $? "! memory" } #endif } $? "- wxdobj_obj_new_spline %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_obj_new_arc(int cl, Wxd_object_t const *ptpl) { Wxd_object_t *back = NULL; $? "+ wxdobj_obj_new_arc" back = dk4mem_new(Wxd_object_t,1,NULL); if (NULL != back) { wxdobj_obj_init( back, ((0 != cl) ? (WXD_OT_C_ARC) : (WXD_OT_O_ARC)), ptpl ); } #if TRACE_DEBUG else { $? "! memory" } #endif $? "- wxdobj_obj_new_arc %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_obj_new_circle(Wxd_object_t const *ptpl) { Wxd_object_t *back = NULL; $? "+ wxdobj_obj_new_circle" back = dk4mem_new(Wxd_object_t,1,NULL); if (NULL != back) { wxdobj_obj_init(back, WXD_OT_CIRCLE, ptpl); } #if TRACE_DEBUG else { $? "! memory" } #endif $? "- wxdobj_obj_new_circle %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_obj_new_ellipse(Wxd_object_t const *ptpl) { Wxd_object_t *back = NULL; $? "+ wxdobj_obj_new_ellipse" back = dk4mem_new(Wxd_object_t,1,NULL); if (NULL != back) { wxdobj_obj_init(back, WXD_OT_ELLIPSE, ptpl); } #if TRACE_DEBUG else { $? "! memory" } #endif $? "- wxdobj_obj_new_ellipse %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_obj_new_box(Wxd_object_t const *ptpl) { Wxd_object_t *back = NULL; $? "+ wxdobj_obj_new_box" back = dk4mem_new(Wxd_object_t,1,NULL); if (NULL != back) { wxdobj_obj_init(back, WXD_OT_BOX, ptpl); } #if TRACE_DEBUG else { $? "! memory" } #endif $? "- wxdobj_obj_new_box %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_obj_new_image(wxChar const *fn, Wxd_object_t const *ptpl) { Wxd_object_t *back = NULL; $? "+ wxdobj_obj_new_image" if (NULL != fn) { back = dk4mem_new(Wxd_object_t,1,NULL); if (NULL != back) { wxdobj_obj_init(back, WXD_OT_IMAGE, ptpl); (back->det).i.fn = dk4strx_dup(fn, NULL); if (NULL == (back->det).i.fn) { $? "! memory" wxdobj_obj_delete(back); back = NULL; } } } #if TRACE_DEBUG else { $? "! memory" } #endif $? "- wxdobj_obj_new_image %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_obj_new_dot(int wh, Wxd_object_t const *ptpl) { Wxd_object_t *back = NULL; $? "+ wxdobj_obj_new_dot" back = dk4mem_new(Wxd_object_t,1,NULL); if (NULL != back) { wxdobj_obj_init( back, ((0 != wh) ? (WXD_OT_DOT_WHITE) : (WXD_OT_DOT_FILLED)), ptpl ); } #if TRACE_DEBUG else { $? "! memory" } #endif $? "- wxdobj_obj_new_dot %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_obj_new_textlabel(wxChar const *te, Wxd_object_t const *ptpl) { Wxd_object_t *back = NULL; $? "+ wxdobj_obj_new_textlabel \"%!xs\"", TR_WXSTR(te) if (NULL != te) { back = dk4mem_new(Wxd_object_t,1,NULL); if (NULL != back) { wxdobj_obj_init(back, WXD_OT_TEXT, ptpl); if (NULL != ptpl) { back->fc[0] = ptpl->sc[0]; back->fc[1] = ptpl->sc[1]; back->fc[2] = ptpl->sc[2]; } (back->det).t.t = dk4strx_dup(te, NULL); if (NULL == (back->det).t.t) { $? "! memory" wxdobj_obj_delete(back); back = NULL; } } #if TRACE_DEBUG else { $? "! memory" } #endif } #if TRACE_DEBUG else { $? "! arg te" } #endif $? "- wxdobj_obj_new_textlabel %d", TR_IPTR(back) return back; } int wxdobj_needs_stipple( Wxd_object_t *pobj ) { int back = 0; $? "+ wxdobj_needs_stipple" switch ( (int)(pobj->ot) ) { case WXD_OT_POLYGON : case WXD_OT_C_SPLINE : case WXD_OT_C_ARC : case WXD_OT_CIRCLE : case WXD_OT_ELLIPSE : case WXD_OT_BOX : { $? ". object type allows filling" $? ". fs = %u", (unsigned)(pobj->fs) if (WXD_FS_PURE < pobj->fs) { back = 1; } } break; } $? "- wxdobj_needs_stipple %d", back return back; } /** Find existing stipple structure for object or create a new one. @param pdrw Drawing. @param pobj Object. @return Address of stipple on success, NULL on error. */ static Wxd_stipple_t * i_find_stipple_structure( Wxd_drawing_t *pdrw, Wxd_object_t *pobj ) { Wxd_stipple_t teststip; Wxd_stipple_t *back; $? "+ i_find_stipple_structure" teststip.cd[0] = pobj->fs; teststip.cd[1] = pobj->fc[0]; teststip.cd[2] = pobj->fc[1]; teststip.cd[3] = pobj->fc[2]; teststip.cd[4] = pobj->sc[0]; teststip.cd[5] = pobj->sc[1]; teststip.cd[6] = pobj->sc[2]; teststip.cd[7] = 0x01; teststip.bm = NULL; back = (Wxd_stipple_t *)dk4sto_it_find_like( pdrw->i_stip, (const void *)(&teststip), 0 ); if (NULL == back) { $? ". no matching stipple found" back = dk4mem_new(Wxd_stipple_t,1,NULL); if (NULL != back) { $? ". allocated" DK4_MEMCPY(back,&teststip,sizeof(Wxd_stipple_t)); back->bm = NULL; if (0 == dk4sto_add(pdrw->s_stip, (void *)back, NULL)) { dk4mem_free(back); $? "! add" back = NULL; } #if TRACE_DEBUG else { $? ". added to storage" } #endif } #if TRACE_DEBUG else { $? "! memory" } #endif } $? "- i_find_stipple_structure %d", TR_IPTR(back) return back; } static int i_find_layer_structure(Wxd_drawing_t *pdrw, Wxd_object_t *pobj) { Wxd_layer_t *ptest; int back = 0; $? "+ i_find_layer_structure" if (NULL == pobj->play) { ptest = (Wxd_layer_t *)dk4sto_it_find_like( pdrw->i_layers, &(pobj->lay), 1 ); if (NULL != ptest) { pobj->play = ptest; back = 1; } else { ptest = dk4mem_new(Wxd_layer_t,1,NULL); if (NULL != ptest) { ptest->lay = pobj->lay; ptest->active = 0x01; ptest->used = 0x01; if (0 != dk4sto_add(pdrw->s_layers, ptest, NULL)) { pobj->play = ptest; back = 1; } else { $? "! memory" dk4mem_free(ptest); } } #if TRACE_DEBUG else { $? "! memory" } #endif } } else { back = 1; } $? "- i_find_layer_structure %d", back return back; } static int wxdobj_drw_layer_and_stipple( Wxd_drawing_t *pdrw, Wxd_object_t *pobj ) { int back = 1; $? "+ wxdobj_drw_layer_and_stipple" if (NULL == pobj->play) { if (0 == i_find_layer_structure(pdrw, pobj)) { back = 0; } } if (0 != wxdobj_needs_stipple(pobj)) { $? ". need stipple" if (NULL == pobj->psti) { $? ". no stipple yet" pobj->psti = i_find_stipple_structure(pdrw, pobj); if (NULL == pobj->psti) { $? ". still NULL" back = 0; } #if TRACE_DEBUG else { $? ". stipple found" $? ". fs = %u", (unsigned)((pobj->psti)->cd[0]) } #endif } } $? "- wxdobj_drw_layer_and_stipple %d", back return back; } int wxdobj_drw_register_object( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, Wxd_object_t *pobj ) { int back = 0; $? "+ wxdobj_drw_register_object %d %d %d", TR_IPTR(pdrw), TR_IPTR(pgrp), TR_IPTR(pobj) if ((NULL != pdrw) && (NULL != pobj)) { if (WXD_OT_GROUP_BEGIN == pobj->ot) { /* Group objects go to structured storage only, no layer structure */ if (NULL != pgrp) { if (0 != dk4sto_add((pgrp->det).g.s_e, pobj, NULL)) { pobj->pa = pgrp; back = 1; } #if TRACE_DEBUG else { $? "! memory" } #endif } else { if (0 != dk4sto_add(pdrw->s_stru, pobj, NULL)) { back = 1; } #if TRACE_DEBUG else { $? "! memory" } #endif } } else { if (0 != wxdobj_drw_layer_and_stipple(pdrw, pobj)) { /* Non-group elements are added to flat and structured storage */ if (0 != dk4sto_add(pdrw->s_flat, pobj, NULL)) { /* Add to structured storage, either group or top-level storage. */ if (NULL != pgrp) { if (0 != dk4sto_add((pgrp->det).g.s_e, pobj, NULL)) { back = 1; pobj->pa = pgrp; } else { $? "! memory" dk4sto_remove(pdrw->s_flat, pobj, NULL); } } else { if (0 != dk4sto_add(pdrw->s_stru, pobj, NULL)) { back = 1; } else { $? "! memory" dk4sto_remove(pdrw->s_flat, pobj, NULL); } } } #if TRACE_DEBUG else { $? "! memory" } #endif } } } #if TRACE_DEBUG else { $? "! args" } #endif $? "- wxdobj_drw_register_object %d", back return back; } Wxd_object_t * wxdobj_drw_add_group( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp ) { Wxd_object_t *back = NULL; $? "+ wxdobj_drw_add_group %d %d", TR_IPTR(pdrw), TR_IPTR(pgrp) if (NULL != pdrw) { back = dk4mem_new(Wxd_object_t,1,NULL); if (NULL != back) { wxdobj_obj_init(back, WXD_OT_GROUP_BEGIN, NULL); (back->det).g.s_e = dk4sto_open(NULL); if (NULL != (back->det).g.s_e) { dk4sto_set_comp( (back->det).g.s_e, drawobj_compare_object, WXD2LAT_OBJ_COMPARE_CR_PROPERTIES ); (back->det).g.i_e = dk4sto_it_open((back->det).g.s_e, NULL); if (NULL != (back->det).g.i_e) { if (0 == wxdobj_drw_register_object(pdrw, pgrp, back)) { wxdobj_obj_delete(back); back = NULL; $? "! memory" } } else { $? "! memory" wxdobj_obj_delete(back); back = NULL; } } else { $? "! memory" wxdobj_obj_delete(back); back = NULL; } } #if TRACE_DEBUG else { $? "! memory" } #endif } #if TRACE_DEBUG else { $? "! args" } #endif $? "- wxdobj_drw_add_group %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_add_polyline( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, uint16_t np, int cl, Wxd_object_t const *ptpl ) { Wxd_object_t *back = NULL; $? "+ wxdobj_add_polyline" if (NULL != pdrw) { if (0 != cl) { back = wxdobj_obj_new_polygon(np, ptpl); } else { back = wxdobj_obj_new_polyline(np, ptpl); } if (NULL != back) { if (0 == wxdobj_drw_register_object(pdrw, pgrp, back)) { wxdobj_obj_delete(back); back = NULL; } } } $? "- wxdobj_add_polyline %d", TR_IPTR(back) return back; } bool wxdobj_add_polypoint( Wxd_object_t *pobj, uint16_t pind, dk4_er_t *erp ) { dk4_er_t er; /* Error report */ Wxd_point_t *pnew; /* New allocated points array */ size_t btc; /* Bytes to copy */ uint16_t nn; /* New array size */ uint16_t num; /* Number of elements to move */ uint16_t i; /* Index of element to copy */ bool back = false; $? "+ wxdobj_add_polypoint %u", (unsigned)pind if ( (NULL != pobj) && ( (WXD_OT_POLYLINE == pobj->ot) || (WXD_OT_POLYGON == pobj->ot) ) && (NULL != (pobj->det).p.p) ) { dk4error_init(&er); nn = dk4ma_uint16_t_add((pobj->det).p.n, 1U, &er); if (DK4_E_NONE == er.ec) { pnew = dk4mem_new(Wxd_point_t,((size_t)nn),&er); if (NULL != pnew) { back = true; btc = sizeof(Wxd_point_t) * (size_t)((pobj->det).p.n); DK4_MEMCPY(pnew,(pobj->det).p.p,btc); dk4mem_free((pobj->det).p.p); (pobj->det).p.p = pnew; if (pind < (pobj->det).p.n) { num = (pobj->det).p.n - pind; for (i = 0; i < num; i++) { ((pobj->det).p.p)[(pobj->det).p.n - i].x = ((pobj->det).p.p)[(pobj->det).p.n - i - 1].x; ((pobj->det).p.p)[(pobj->det).p.n - i].y = ((pobj->det).p.p)[(pobj->det).p.n - i - 1].y; } } else { ((pobj->det).p.p)[(pobj->det).p.n].x = ((pobj->det).p.p)[(pobj->det).p.n - 1].x; ((pobj->det).p.p)[(pobj->det).p.n].y = ((pobj->det).p.p)[(pobj->det).p.n - 1].y; } (pobj->det).p.n = nn; } else { /* ERROR: Memory (already reported) */ } } else { dk4error_copy(erp, &er); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } $? "- wxdobj_add_polypoint %d", (back ? 1 : 0) return back; } bool wxdobj_del_polypoint( Wxd_object_t *pobj, uint16_t pind, dk4_er_t *erp ) { Wxd_point_t *pnew; size_t btc; uint16_t num; uint16_t i; uint16_t nn; bool back = false; $? "+ wxdobj_del_polypoint" $!trace-code wxdobj_report_object(pobj); if ( (NULL != pobj) && ( (WXD_OT_POLYLINE == pobj->ot) || (WXD_OT_POLYGON == pobj->ot) ) ) { $? ". obj ok" $? ". number of points %u", (unsigned)((pobj->det).p.n) back = true; if (pind < ((pobj->det).p.n - 1U)) { $? ". must squeeze" num = (pobj->det).p.n - 1U - pind; for (i = 0U; i < num; i++) { ((pobj->det).p.p)[pind + i].x = ((pobj->det).p.p)[pind + i + 1U].x; ((pobj->det).p.p)[pind + i].y = ((pobj->det).p.p)[pind + i + 1U].y; } } #if TRACE_DEBUG else { $? ". no need to squeeze" } #endif nn = (pobj->det).p.n - 1U; pnew = dk4mem_new(Wxd_point_t,((size_t)nn),erp); if (NULL != pnew) { $? ". mem for smaller array" btc = sizeof(Wxd_point_t) * ((size_t)nn); DK4_MEMCPY(pnew,(pobj->det).p.p,btc); dk4mem_free((pobj->det).p.p); (pobj->det).p.p = pnew; } #if TRACE_DEBUG else { $? "! memory" } #endif (pobj->det).p.n = (pobj->det).p.n - 1U; $? ". number of points %u", (unsigned)((pobj->det).p.n) } else { $? "! args" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } $!trace-code wxdobj_report_object(pobj); $? "- wxdobj_del_polypoint %d", (back ? 1 : 0) return back; } Wxd_object_t * wxdobj_add_spline( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, uint16_t np, int cl, Wxd_object_t const *ptpl ) { Wxd_object_t *back = NULL; $? "+ wxdobj_add_spline" if (NULL != pdrw) { back = wxdobj_obj_new_spline(np, cl, ptpl); if (NULL != back) { if (0 == wxdobj_drw_register_object(pdrw, pgrp, back)) { wxdobj_obj_delete(back); back = NULL; } } } $? "- wxdobj_add_spline %d", TR_IPTR(back) return back; } bool wxdobj_add_splinepoint( Wxd_object_t *pobj, uint16_t pind, dk4_er_t *erp ) { dk4_er_t er; /* Error report */ Wxd_spline_point_t *pnew; /* New allocated points array */ size_t btc; /* Bytes to copy */ uint16_t nn; /* New array size */ uint16_t num; /* Number of elements to move */ uint16_t i; /* Index of element to copy */ bool back = false; $? "+ wxdobj_add_splinepoint %u", (unsigned)pind if ( (NULL != pobj) && ( (WXD_OT_O_SPLINE == pobj->ot) || (WXD_OT_C_SPLINE == pobj->ot) ) && (NULL != (pobj->det).s.p) ) { dk4error_init(&er); nn = dk4ma_uint16_t_add((pobj->det).s.n, 1U, &er); if (DK4_E_NONE == er.ec) { pnew = dk4mem_new(Wxd_spline_point_t,((size_t)nn),&er); if (NULL != pnew) { back = true; btc = sizeof(Wxd_spline_point_t) * (size_t)((pobj->det).s.n); DK4_MEMCPY(pnew,(pobj->det).s.p,btc); dk4mem_free((pobj->det).s.p); (pobj->det).s.p = pnew; if (pind < (pobj->det).s.n) { num = (pobj->det).s.n - pind; for (i = 0; i < num; i++) { ((pobj->det).s.p)[(pobj->det).s.n - i].x = ((pobj->det).s.p)[(pobj->det).s.n - i - 1].x; ((pobj->det).s.p)[(pobj->det).s.n - i].y = ((pobj->det).s.p)[(pobj->det).s.n - i - 1].y; ((pobj->det).s.p)[(pobj->det).s.n - i].s = ((pobj->det).s.p)[(pobj->det).s.n - i - 1].s; } } else { ((pobj->det).s.p)[(pobj->det).s.n].x = ((pobj->det).s.p)[(pobj->det).s.n - 1].x; ((pobj->det).s.p)[(pobj->det).s.n].y = ((pobj->det).s.p)[(pobj->det).s.n - 1].y; ((pobj->det).s.p)[(pobj->det).s.n].s = ((pobj->det).s.p)[(pobj->det).s.n - 1].s; } (pobj->det).s.n = nn; } else { /* ERROR: Memory (already reported) */ } } else { dk4error_copy(erp, &er); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } $? "- wxdobj_add_splinepoint %d", (back ? 1 : 0) return back; } bool wxdobj_del_splinepoint( Wxd_object_t *pobj, uint16_t pind, dk4_er_t *erp ) { Wxd_spline_point_t *pnew; size_t btc; uint16_t num; uint16_t i; uint16_t nn; bool back = false; $? "+ wxdobj_del_splinepoint" $!trace-code wxdobj_report_object(pobj); if ( (NULL != pobj) && ( (WXD_OT_O_SPLINE == pobj->ot) || (WXD_OT_C_SPLINE == pobj->ot) ) ) { $? ". obj ok" $? ". number of points %u", (unsigned)((pobj->det).s.n) back = true; if (pind < ((pobj->det).s.n - 1U)) { $? ". must squeeze" num = (pobj->det).s.n - 1U - pind; for (i = 0U; i < num; i++) { ((pobj->det).s.p)[pind + i].x = ((pobj->det).s.p)[pind + i + 1U].x; ((pobj->det).s.p)[pind + i].y = ((pobj->det).s.p)[pind + i + 1U].y; ((pobj->det).s.p)[pind + i].s = ((pobj->det).s.p)[pind + i + 1U].s; } } #if TRACE_DEBUG else { $? ". no need to squeeze" } #endif nn = (pobj->det).s.n - 1U; pnew = dk4mem_new(Wxd_spline_point_t,((size_t)nn),erp); if (NULL != pnew) { $? ". mem for smaller array" btc = sizeof(Wxd_spline_point_t) * ((size_t)nn); DK4_MEMCPY(pnew,(pobj->det).s.p,btc); dk4mem_free((pobj->det).s.p); (pobj->det).s.p = pnew; } #if TRACE_DEBUG else { $? "! memory" } #endif (pobj->det).s.n = (pobj->det).s.n - 1U; $? ". number of points %u", (unsigned)((pobj->det).s.n) } else { $? "! args" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } $!trace-code wxdobj_report_object(pobj); $? "- wxdobj_del_splinepoint %d", (back ? 1 : 0) return back; } Wxd_object_t * wxdobj_add_arc( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, int cl, Wxd_object_t const *ptpl ) { Wxd_object_t *back = NULL; $? "+ wxdobj_add_arc" if (NULL != pdrw) { back = wxdobj_obj_new_arc(cl, ptpl); if (NULL != back) { if (0 == wxdobj_drw_register_object(pdrw, pgrp, back)) { wxdobj_obj_delete(back); back = NULL; } } } $? "- wxdobj_add_arc %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_add_circle( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, Wxd_object_t const *ptpl ) { Wxd_object_t *back = NULL; $? "+ wxdobj_add_circle" if (NULL != pdrw) { back = wxdobj_obj_new_circle(ptpl); if (NULL != back) { if (0 == wxdobj_drw_register_object(pdrw, pgrp, back)) { wxdobj_obj_delete(back); back = NULL; } } } $? "- wxdobj_add_circle %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_add_ellipse( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, Wxd_object_t const *ptpl ) { Wxd_object_t *back = NULL; $? "+ wxdobj_add_ellipse" if (NULL != pdrw) { back = wxdobj_obj_new_ellipse(ptpl); if (NULL != back) { if (0 == wxdobj_drw_register_object(pdrw, pgrp, back)) { wxdobj_obj_delete(back); back = NULL; } } } $? "- wxdobj_add_ellipse %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_add_box( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, Wxd_object_t const *ptpl ) { Wxd_object_t *back = NULL; $? "+ wxdobj_add_box" if (NULL != pdrw) { back = wxdobj_obj_new_box(ptpl); if (NULL != back) { if (0 == wxdobj_drw_register_object(pdrw, pgrp, back)) { wxdobj_obj_delete(back); back = NULL; } } } $? "- wxdobj_add_box %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_add_image( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, wxChar const *fn, Wxd_object_t const *ptpl ) { Wxd_object_t *back = NULL; $? "+ wxdobj_add_image" if (NULL != pdrw) { back = wxdobj_obj_new_image(fn, ptpl); if (NULL != back) { if (0 == wxdobj_drw_register_object(pdrw, pgrp, back)) { wxdobj_obj_delete(back); back = NULL; } } } $? "- wxdobj_add_image %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_add_dot( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, int wh, Wxd_object_t const *ptpl ) { Wxd_object_t *back = NULL; $? "+ wxdobj_add_dot" if (NULL != pdrw) { back = wxdobj_obj_new_dot(wh, ptpl); if (NULL != back) { if (0 == wxdobj_drw_register_object(pdrw, pgrp, back)) { wxdobj_obj_delete(back); back = NULL; } } } $? "- wxdobj_add_dot %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_add_textlabel( Wxd_drawing_t *pdrw, Wxd_object_t *pgrp, wxChar const *te, Wxd_object_t const *ptpl ) { Wxd_object_t *back = NULL; $? "+ wxdobj_add_textlabel" if ((NULL != pdrw) && (NULL != te)) { back = wxdobj_obj_new_textlabel(te, ptpl); if (NULL != back) { if (0 == wxdobj_drw_register_object(pdrw, pgrp, back)) { wxdobj_obj_delete(back); back= NULL; } } } $? "- wxdobj_add_textlabel %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_find_group_for(Wxd_drawing_t *pdrw, Wxd_object_t *pobj) { Wxd_object_t *back = NULL; $? "+ wxdobj_find_group_for" if ((NULL != pdrw) && (NULL != pobj)) { back = i_find_group_for(pdrw, pobj); } $? "- wxdobj_find_group_for %d", TR_IPTR(back) return back; } int wxdobj_find_layer_structure(Wxd_drawing_t *pdrw, Wxd_object_t *pobj) { int back = 0; $? "+ wxdobj_find_layer_structure" if ((NULL != pdrw) && (NULL != pobj)) { back = i_find_layer_structure(pdrw, pobj); } $? "- wxdobj_find_layer_structure %d", back return back; } /** Modify object layer internally. @param pdrw Drawing to modify. @param pobj Object to modify. @param nl New layer differing from objects current layer. @return 1 on success, 0 on error. */ static int i_modify_layer( Wxd_drawing_t *pdrw, Wxd_object_t *pobj, int16_t nl ) { Wxd_layer_t *playold; /* Old layer structure */ Wxd_object_t *pgrp; /* Group containing the object */ int back = 0; /* Result */ $? "+ i_modify_layer" playold = pobj->play; pobj->play = NULL; if (NULL != dk4sto_it_find_exact(pdrw->i_flat, pobj)) { /* In flat list */ if (NULL != dk4sto_it_find_exact(pdrw->i_stru, pobj)) { /* Top-level element */ dk4sto_remove(pdrw->s_stru, pobj, NULL); dk4sto_remove(pdrw->s_flat, pobj, NULL); pobj->lay = nl; back = wxdobj_drw_register_object(pdrw, NULL, pobj); if (0 == back) { $? "! registration failed" wxdobj_obj_delete(pobj); } wxdobj_drw_require_redraw(pdrw, WXD_REFRESH_DRAWING); } else { /* Member of a group */ pgrp = i_find_group_for(pdrw, pobj); if (NULL != pgrp) { /* Group found */ dk4sto_remove((pgrp->det).g.s_e, pobj, NULL); dk4sto_remove(pdrw->s_flat, pobj, NULL); pobj->lay = nl; back = wxdobj_drw_register_object(pdrw, pgrp, pobj); if (0 == back) { $? "! registration failed" wxdobj_obj_delete(pobj); } wxdobj_drw_require_redraw(pdrw, WXD_REFRESH_DRAWING); } else { $? "! group not found" /* Group not found */ } } } else { $? "! not in flat list" /* Not in flat list */ } /* Find layer structure */ if (0 != back) { back = i_find_layer_structure(pdrw, pobj); } /* Remove playold from drawing if not used by other objects */ if (NULL != playold) { i_check_layer_structure_removal(pdrw, playold); } $? "- i_modify_layer %d", back return back; } int wxdobj_modify_layer( Wxd_drawing_t *pdrw, Wxd_object_t *pobj, int16_t nl ) { int back = 0; $? "+ wxdobj_modify_layer" if ((NULL != pdrw) && (NULL != pobj)) { if (pobj->lay != nl) { back = i_modify_layer(pdrw, pobj, nl); } else { back = 1; } } #if TRACE_DEBUG else { $? "! args" } #endif $? "- wxdobj_modify_layer %d", back return back; } void wxdobj_bb_correct(Wxd_bb_t *bbptr, uint16_t *ppoint) { int32_t x; $? "+ wxdobj_bb_correct" if (NULL != bbptr) { if (bbptr->xl > bbptr->xr) { if (bbptr->yb > bbptr->yt) { x = bbptr->xl; bbptr->xl = bbptr->xr; bbptr->xr = x; x = bbptr->yb; bbptr->yb = bbptr->yt; bbptr->yt = x; if (NULL != ppoint) { switch ( (int)(*ppoint) ) { case 3 : { *ppoint = (uint16_t)0U; } break; case 2 : { *ppoint = (uint16_t)0U; } break; case 1 : { *ppoint = (uint16_t)3U; } break; default : { *ppoint = (uint16_t)2U; } break; } } } else { x = bbptr->xl; bbptr->xl = bbptr->xr; bbptr->xr = x; if (NULL != ppoint) { switch ( (int)(*ppoint) ) { case 3 : { *ppoint = (uint16_t)2U; } break; case 2 : { *ppoint = (uint16_t)3U; } break; case 1 : { *ppoint = (uint16_t)0U; } break; default : { *ppoint = (uint16_t)1U; } break; } } } } else { if (bbptr->yb > bbptr->yt) { x = bbptr->yb; bbptr->yb = bbptr->yt; bbptr->yt = x; if (NULL != ppoint) { switch ( (int)(*ppoint) ) { case 3 : { *ppoint = (uint16_t)0U; } break; case 2 : { *ppoint = (uint16_t)1U; } break; case 1 : { *ppoint = (uint16_t)2U; } break; default : { *ppoint = (uint16_t)3U; } break; } } } } } $? "- wxdobj_bb_correct" } bool wxdobj_bb_is_null_area(Wxd_bb_t *bbptr) { bool back = false; $? "+ wxdobj_bb_is_null_area" if (NULL != bbptr) { if (bbptr->xl >= bbptr->xr) { back = true; } if (bbptr->yb >= bbptr->yt) { back = true; } } $? "- wxdobj_bb_is_null_area %d", (back ? 1 : 0) return back; } static int32_t wxdobj_i32_max(int32_t a, int32_t b) { return ((a >= b) ? (a) : (b)); } static int32_t wxdobj_i32_min(int32_t a, int32_t b) { return ((a <= b) ? (a) : (b)); } bool wxdobj_bb_intersection( Wxd_bb_t *res, Wxd_bb_t const *a, Wxd_bb_t const *b ) { if ((NULL == res) || (NULL == a) || (NULL == b)) { return false; } if (a->xr < b->xl) return false; if (b->xr < a->xl) return false; if (a->yt < b->yb) return false; if (b->yt < a->yb) return false; res->xl = wxdobj_i32_max(a->xl, b->xl); res->xr = wxdobj_i32_min(a->xr, b->xr); res->yb = wxdobj_i32_max(a->yb, b->yb); res->yt = wxdobj_i32_min(a->yt, b->yt); return true; } static dk4_bif_t * wxdobj_image_bif_open( Wxd_object_t *pobj, int dkenc, int wxenc ) { dkChar fnb[DK4_MAX_PATH]; dk4_bif_t *back = NULL; const size_t szfnb = DK4_SIZEOF(fnb,dkChar); int res; $? "+ wxdobj_image_bif_open" res = dk4recwx_wxchar_to_dkchar( fnb, szfnb, dkenc, (pobj->det).i.fn, wxenc, NULL ); if (0 != res) { back = dk4bif_open(fnb, 1, NULL, NULL); } #if TRACE_DEBUG else { $? "! file name conversion failed" } #endif $? "- wxdobj_image_bif_open %d", TR_IPTR(back) return back; } void wxdobj_image_placement( Wxd_object_t *pobj ) { double iw; /* Image width */ double ih; /* Image height */ double sw; /* Scale factor for width */ double sh; /* Scale factor for height */ double l; /* Length */ double b; /* Border */ $? "+ wxdobj_image_placement" $? ". br.xl = %ld", (long)((pobj->det).i.br.xl) $? ". br.xr = %ld", (long)((pobj->det).i.br.xr) $? ". br.yb = %ld", (long)((pobj->det).i.br.yb) $? ". br.yt = %ld", (long)((pobj->det).i.br.yt) if (0 != ((uint16_t)(WXD_IMFL_ASPECT) & (pobj->det).i.fl)) { $? ". keep aspect ratio" wxSize wxsz = ((pobj->det).i.bm)->GetSize(); iw = (double)(wxsz.GetWidth()); ih = (double)(wxsz.GetHeight()); if ( (0.0 < (pobj->det).i.xres) && (0.0 < (pobj->det).i.yres) && ((pobj->det).i.xres != (pobj->det).i.yres) ) { $? ". use resolution" iw = iw / (pobj->det).i.xres; ih = ih / (pobj->det).i.yres; } sw = ( (double)((pobj->det).i.br.xr) - (double)((pobj->det).i.br.xl) ) / iw; sh = ( (double)((pobj->det).i.br.yt) - (double)((pobj->det).i.br.yb) ) / ih; if (sw <= sh) { $? ". more height available" (pobj->det).i.pl.xmin = (pobj->det).i.br.xl; (pobj->det).i.pl.xmax = (pobj->det).i.br.xr; l = sw * ih; b = (double)((pobj->det).i.br.yt) - (double)((pobj->det).i.br.yb); b = (b - l) / 2.0; (pobj->det).i.pl.ymin = (pobj->det).i.br.yb + b; (pobj->det).i.pl.ymax = (pobj->det).i.br.yt - b; } else { $? ". more width available" (pobj->det).i.pl.ymin = (pobj->det).i.br.yb; (pobj->det).i.pl.ymax = (pobj->det).i.br.yt; l = sh * iw; b = (double)((pobj->det).i.br.xr) - (double)((pobj->det).i.br.xl); b = (b - l) / 2.0; (pobj->det).i.pl.xmin = (pobj->det).i.br.xl + b; (pobj->det).i.pl.xmax = (pobj->det).i.br.xr - b; } } else { $? ". fill available space" (pobj->det).i.pl.xmin = (pobj->det).i.br.xl; (pobj->det).i.pl.xmax = (pobj->det).i.br.xr; (pobj->det).i.pl.ymin = (pobj->det).i.br.yb; (pobj->det).i.pl.ymax = (pobj->det).i.br.yt; } $? ". pl.xmin = %g", (pobj->det).i.pl.xmin $? ". pl.xmax = %g", (pobj->det).i.pl.xmax $? ". pl.ymin = %g", (pobj->det).i.pl.ymin $? ". pl.ymax = %g", (pobj->det).i.pl.ymax $? "- wxdobj_image_placement" } void wxdobj_load_image( Wxd_object_t *pobj, int dkenc, int wxenc ) { dk4_bif_t *bifptr; wxString strfn((pobj->det).i.fn); $? "+ wxdobj_load_image" if (NULL == (pobj->det).i.bm) { $? ". no img yet" (pobj->det).i.xres = -1.0; (pobj->det).i.yres = -1.0; (pobj->det).i.t = wxdobj_image_type((pobj->det).i.fn); if (wxBITMAP_TYPE_INVALID != (pobj->det).i.t) { (pobj->det).i.bm = new wxBitmap( strfn, (pobj->det).i.t ); if (NULL != (pobj->det).i.bm) { $? ". have bitmap" if (!(((pobj->det).i.bm)->IsOk())) { $? "! not ok" delete ((pobj->det).i.bm); (pobj->det).i.bm = NULL; } } if (NULL != (pobj->det).i.bm) { $? ". have bitmap" if (0 != ((uint16_t)(WXD_IMFL_ASPECT) & (pobj->det).i.fl)) { $? ". keep aspect ratio" bifptr = wxdobj_image_bif_open(pobj, dkenc, wxenc); if (NULL != bifptr) { (pobj->det).i.xres = dk4bif_get_xres(bifptr); (pobj->det).i.yres = dk4bif_get_yres(bifptr); $? ". x resolution = %g", (pobj->det).i.xres $? ". y resolution = %g", (pobj->det).i.yres dk4bif_close(bifptr); } } #if TRACE_DEBUG else { $? ". fill region" } #endif wxdobj_image_placement(pobj); } #if TRACE_DEBUG else { $? "! no bitmap" } #endif } #if TRACE_DEBUG else { $? "! image type" } #endif } #if TRACE_DEBUG else { $? ". have image" } #endif $? "- wxdobj_load_image %d", ((NULL != (pobj->det).i.bm) ? 1 : 0) } void wxdobj_unmark_recursively(Wxd_object_t *pobj, uint8_t marker) { Wxd_object_t *po; $? "+ wxdobj_unmark_recursively" if (NULL != pobj) { pobj->mark &= (~(marker)); if (WXD_OT_GROUP_BEGIN == pobj->ot) { dk4sto_it_reset((pobj->det).g.i_e); do { po = (Wxd_object_t *)dk4sto_it_next((pobj->det).g.i_e); if (NULL != po) { wxdobj_unmark_recursively(po, marker); } } while (NULL != po); } } $? "- wxdobj_unmark_recursively" } void wxdobj_unmark_all(Wxd_drawing_t *pdrw, uint8_t marker) { Wxd_object_t *pobj; $? "+ wxdobj_unmark_all" uint8_t mask; mask = (~(marker)); dk4sto_it_reset(pdrw->i_flat); do { pobj = (Wxd_object_t *)dk4sto_it_next(pdrw->i_flat); if (NULL != pobj) { pobj->mark &= mask; } } while (NULL != pobj); dk4sto_it_reset(pdrw->i_stru); do { pobj = (Wxd_object_t *)dk4sto_it_next(pdrw->i_stru); if (NULL != pobj) { pobj->mark &= mask; } } while (NULL != pobj); $? "- wxdobj_unmark_all" } void wxdobj_mark_recursively(Wxd_object_t *pobj, uint8_t marker) { Wxd_object_t *po; $? "+ wxdobj_mark_recursively" if (NULL != pobj) { pobj->mark |= marker; if (WXD_OT_GROUP_BEGIN == pobj->ot) { dk4sto_it_reset((pobj->det).g.i_e); do { po = (Wxd_object_t *)dk4sto_it_next((pobj->det).g.i_e); if (NULL != po) { wxdobj_mark_recursively(po, marker); } } while (NULL != po); } } $? "- wxdobj_mark_recursively" } /** Find sector for point relative to box. @param pbox Box. @param r Rounded corners radius. @param ppt Point. @return Sector number, one from: - 0: Point is lower left than box center. - 1: Point is centered below box. - 2: Point is lower right than box center. - 3: Point is left from box center. - 4: Point is in box center. - 5: Point is right from box center. - 6: Point is upper left from box center. - 7: Point is centered over box. - 8: Point is upper right from box center. */ static int wxdobj_box_sector(Wxd_bb_t *pbox, uint32_t r, dk4_gra_point_t *ppt) { int back = 4; $? "+ wxdobj_box_sector" if (ppt->x < (double)(pbox->xl) + (double)r) { /* X: left */ if (ppt->y < (double)(pbox->yb) + (double)r) { back = 0; } else { if (ppt->y > (double)(pbox->yt) - (double)r) { back = 6; } else { back = 3; } } } else { if (ppt->x > (double)(pbox->xr) - (double)r) { /* X: right */ if (ppt->y < (double)(pbox->yb) + (double)r) { back = 2; } else { if (ppt->y > (double)(pbox->yt) - (double)r) { back = 8; } else { back = 5; } } } else { /* X: centered */ if (ppt->y < (double)(pbox->yb) + (double)r) { back = 1; } else { if (ppt->y > (double)(pbox->yt) - (double)r) { back = 7; } } } } $? "- wxdobj_box_sector %d", back return back; } double wxdobj_dist_box( Wxd_bb_t *pbox, uint32_t r, dk4_gra_point_t *ppt, bool bCtrlPt, uint16_t *pIndex ) { dk4_gra_point_t pta; dk4_gra_point_t ptb; double d; double back = -1.0; uint16_t n; $? "+ wxdobj_dist_box" if (bCtrlPt) { pta.x = (double)(pbox->xl); pta.y = (double)(pbox->yb); back = dk4gratool_dist_point_point(&pta, ppt, NULL); n = 0; pta.x = (double)(pbox->xr); pta.y = (double)(pbox->yb); d = dk4gratool_dist_point_point(&pta, ppt, NULL); if (d < back) { back = d; n = 1; } pta.x = (double)(pbox->xr); pta.y = (double)(pbox->yt); d = dk4gratool_dist_point_point(&pta, ppt, NULL); if (d < back) { back = d; n = 2; } pta.x = (double)(pbox->xl); pta.y = (double)(pbox->yt); d = dk4gratool_dist_point_point(&pta, ppt, NULL); if (d < back) { back = d; n = 3; } if (NULL != pIndex) { *pIndex = n; } } else { if ((uint32_t)0UL == r) { pta.x = (double)(pbox->xl); pta.y = (double)(pbox->yb); ptb.x = (double)(pbox->xr); ptb.y = (double)(pbox->yb); back = dk4gratool_dist_point_track(&pta, &ptb, ppt, NULL); pta.x = (double)(pbox->xr); pta.y = (double)(pbox->yt); d = dk4gratool_dist_point_track(&pta, &ptb, ppt, NULL); if ((0.0 <= d) && (d < back)) { back = d; } ptb.x = (double)(pbox->xl); ptb.y = (double)(pbox->yt); d = dk4gratool_dist_point_track(&pta, &ptb, ppt, NULL); if ((0.0 <= d) && (d < back)) { back = d; } pta.x = (double)(pbox->xl); pta.y = (double)(pbox->yb); d = dk4gratool_dist_point_track(&pta, &ptb, ppt, NULL); if ((0.0 <= d) && (d < back)) { back = d; } } else { switch (wxdobj_box_sector(pbox, r, ppt)) { case 0: { pta.x = (double)(pbox->xl); pta.y = (double)(pbox->yb); back = dk4gratool_dist_point_point(&pta, ppt, NULL); back = fabs(back - (double)r); } break; case 1: { pta.x = (double)(pbox->xl); pta.y = (double)(pbox->yb); ptb.x = (double)(pbox->xr); ptb.y = (double)(pbox->yb); back = dk4gratool_dist_point_track(&pta, &ptb, ppt, NULL); } break; case 2: { pta.x = (double)(pbox->xr); pta.y = (double)(pbox->yb); back = dk4gratool_dist_point_point(&pta, ppt, NULL); back = fabs(back - (double)r); } break; case 3: { pta.x = (double)(pbox->xl); pta.y = (double)(pbox->yb); ptb.x = (double)(pbox->xl); ptb.y = (double)(pbox->yt); back = dk4gratool_dist_point_track(&pta, &ptb, ppt, NULL); } break; case 5: { pta.x = (double)(pbox->xr); pta.y = (double)(pbox->yb); ptb.x = (double)(pbox->xr); ptb.y = (double)(pbox->yt); back = dk4gratool_dist_point_track(&pta, &ptb, ppt, NULL); } break; case 6: { pta.x = (double)(pbox->xl); pta.y = (double)(pbox->yt); back = dk4gratool_dist_point_point(&pta, ppt, NULL); back = fabs(back - (double)r); } break; case 7: { pta.x = (double)(pbox->xl); pta.y = (double)(pbox->yt); ptb.x = (double)(pbox->xr); ptb.y = (double)(pbox->yt); back = dk4gratool_dist_point_track(&pta, &ptb, ppt, NULL); } break; case 8: { pta.x = (double)(pbox->xr); pta.y = (double)(pbox->yt); back = dk4gratool_dist_point_point(&pta, ppt, NULL); back = fabs(back - (double)r); } break; default : { pta.x = (double)(pbox->xl); pta.y = (double)(pbox->yb); ptb.x = (double)(pbox->xr); ptb.y = (double)(pbox->yb); back = dk4gratool_dist_point_track(&pta, &ptb, ppt, NULL); pta.x = (double)(pbox->xr); pta.y = (double)(pbox->yt); d = dk4gratool_dist_point_track(&pta, &ptb, ppt, NULL); if ((0.0 <= d) && (d < back)) { back = d; } ptb.x = (double)(pbox->xl); ptb.y = (double)(pbox->yt); d = dk4gratool_dist_point_track(&pta, &ptb, ppt, NULL); if ((0.0 <= d) && (d < back)) { back = d; } pta.x = (double)(pbox->xl); pta.y = (double)(pbox->yb); d = dk4gratool_dist_point_track(&pta, &ptb, ppt, NULL); if ((0.0 <= d) && (d < back)) { back = d; } } break; } } } $? "- wxdobj_dist_box %g", back return back; } bool wxdobj_ctrlpt_dist_box( Wxd_bb_t *pbox, dk4_gra_point_t *ppt, uint16_t *pIndex, double dlim ) { double d; uint16_t ind = (uint16_t)0U; bool back = false; d = wxdobj_dist_box(pbox, (uint32_t)0UL, ppt, true, &ind); if (dlim >= d) { *pIndex = ind; back = true; } return back; } static double wxdobj_dist_dot( Wxd_object_t *pobj, dk4_gra_point_t *grapt ) { dk4_gra_point_t pta; double back = 0.0; double r; $? "+ wxdobj_dist_dot" pta.x = (double)((pobj->det).d.x); pta.y = (double)((pobj->det).d.y); back = dk4gratool_dist_point_point(grapt, &pta, NULL); /* (d / 2) * (16256000 / 160) */ r = 50800.0 * (double)((pobj->det).d.d); if (WXD_OT_DOT_WHITE == pobj->ot) { r += 101600.0; } if (back > r) { back = back - r; } $? "- wxdobj_dist_dot %g", back return back; } double wxdobj_distance_to_point( Wxd_object_t *pobj, Wxd_point_t const *ppt, bool bCtrlPt, uint16_t *pIndex ) { dk4_gra_point_t grapt; /* Point to test in double coords */ dk4_gra_point_t pta; /* Section start point */ dk4_gra_point_t ptb; /* Section end point */ double back = -1.0; /* Result distance */ double d; /* Distance in current test */ double alpha; /* Ellipse rotation in degree */ uint16_t i; /* Traverse point array */ $? "+ wxdobj_distance_to_point" grapt.x = (double)(ppt->x); grapt.y = (double)(ppt->y); switch ( pobj->ot ) { case WXD_OT_TEXT : { pta.x = (double)((pobj->det).t.x); pta.y = (double)((pobj->det).t.y); back = dk4gratool_dist_point_point(&grapt, &pta, NULL); if (bCtrlPt && (NULL != pIndex)) { *pIndex = (uint16_t)0U; } } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { if ((NULL != (pobj->det).p.p) && (1 < (pobj->det).p.n)) { if (bCtrlPt) { for (i = 0; i < (pobj->det).p.n; i++) { pta.x = (double)(((pobj->det).p.p)[i].x); pta.y = (double)(((pobj->det).p.p)[i].y); d = dk4gratool_dist_point_point(&pta, &grapt, NULL); if (0 == i) { back = d; if (NULL != pIndex) { *pIndex = (uint16_t)0U; } } else { if (d < back) { back = d; if (NULL != pIndex) { *pIndex = (uint16_t)i; } } } } } else { pta.x = (double)(((pobj->det).p.p)[0].x); pta.y = (double)(((pobj->det).p.p)[0].y); for (i = 0; i < ((pobj->det).p.n - (uint16_t)1U); i++) { ptb.x = (double)(((pobj->det).p.p)[i + (uint16_t)1U].x); ptb.y = (double)(((pobj->det).p.p)[i + (uint16_t)1U].y); d = dk4gratool_dist_point_track(&pta,&ptb,&grapt,NULL); if (0.0 < d) { if ((0.0 > back) || (d < back)) { back = d; } } DK4_MEMCPY(&pta,&ptb,sizeof(dk4_gra_point_t)); } if (WXD_OT_POLYGON == pobj->ot) { ptb.x = (double)(((pobj->det).p.p)[0].x); ptb.y = (double)(((pobj->det).p.p)[0].y); d = dk4gratool_dist_point_track(&pta,&ptb,&grapt,NULL); if (0.0 < d) { if ((0.0 > back) || (d < back)) { back = d; } } } } } } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { if ((NULL != (pobj->det).s.p) && (1 < (pobj->det).s.n)) { if (bCtrlPt) { for (i = 0; i < (pobj->det).s.n; i++) { pta.x = (double)(((pobj->det).s.p)[i].x); pta.y = (double)(((pobj->det).s.p)[i].y); d = dk4gratool_dist_point_point(&pta, &grapt, NULL); if (0 == i) { back = d; if (NULL != pIndex) { *pIndex = (uint16_t)0U; } } else { if (d < back) { back = d; if (NULL != pIndex) { *pIndex = (uint16_t)i; } } } } } else { pta.x = (double)(((pobj->det).s.p)[0].x); pta.y = (double)(((pobj->det).s.p)[0].y); for (i = 0; i < ((pobj->det).s.n - (uint16_t)1U); i++) { ptb.x = (double)(((pobj->det).s.p)[i + (uint16_t)1U].x); ptb.y = (double)(((pobj->det).s.p)[i + (uint16_t)1U].y); d = dk4gratool_dist_point_track(&pta,&ptb,&grapt,NULL); if (0.0 < d) { if ((0.0 > back) || (d < back)) { back = d; } } DK4_MEMCPY(&pta,&ptb,sizeof(dk4_gra_point_t)); } if (WXD_OT_C_SPLINE == pobj->ot) { ptb.x = (double)(((pobj->det).s.p)[0].x); ptb.y = (double)(((pobj->det).s.p)[0].y); d = dk4gratool_dist_point_track(&pta,&ptb,&grapt,NULL); if (0.0 < d) { if ((0.0 > back) || (d < back)) { back = d; } } } } } } break; case WXD_OT_O_ARC : case WXD_OT_C_ARC : { pta.x = (double)((pobj->det).a.x1); pta.y = (double)((pobj->det).a.y1); back = dk4gratool_dist_point_point(&grapt, &pta, NULL); if (NULL != pIndex) { *pIndex = (uint16_t)0U; } pta.x = (double)((pobj->det).a.x2); pta.y = (double)((pobj->det).a.y2); d = dk4gratool_dist_point_point(&grapt, &pta, NULL); if ((0.0 <= d) && (d < back)) { back = d; if (NULL != pIndex) { *pIndex = (uint16_t)1U; } } pta.x = (double)((pobj->det).a.x3); pta.y = (double)((pobj->det).a.y3); d = dk4gratool_dist_point_point(&grapt, &pta, NULL); if ((0.0 <= d) && (d < back)) { back = d; if (NULL != pIndex) { *pIndex = (uint16_t)2U; } } if ((WXD_OT_C_ARC == pobj->ot) && (!(bCtrlPt))) { if (0 != (pobj->det).a.d) { pta.x = (double)((pobj->det).a.x1); pta.y = (double)((pobj->det).a.y1); ptb.x = (pobj->det).a.x; ptb.y = (pobj->det).a.y; d = dk4gratool_dist_point_track(&pta, &ptb, &grapt, NULL); if ((0.0 <= d) && (d < back)) { back = d; } pta.x = (double)((pobj->det).a.x3); pta.y = (double)((pobj->det).a.y3); d = dk4gratool_dist_point_track(&pta, &ptb, &grapt, NULL); if ((0.0 <= d) && (d < back)) { back = d; } } } } break; case WXD_OT_CIRCLE : { if (bCtrlPt) { for (i = 0; i < 4; i++) { switch (i) { case 0 : { pta.x = (double)((pobj->det).e.rx); pta.y = 0.0; } break; case 1 : { pta.x = 0.0; pta.y = (double)((pobj->det).e.rx); } break; case 2 : { pta.x = 0.0 - (double)((pobj->det).e.rx); pta.y = 0.0; } break; case 3 : { pta.x = 0.0; pta.y = 0.0 - (double)((pobj->det).e.rx); } break; } pta.x += (double)((pobj->det).e.x); pta.y += (double)((pobj->det).e.y); d = dk4gratool_dist_point_point(&grapt, &pta, NULL); if (0 == i) { back = d; if (NULL != pIndex) { *pIndex = i; } } else { if (d < back) { back = d; if (NULL != pIndex) { *pIndex = i; } } } } if (NULL != pIndex) { $? ". control point %u", (unsigned)(*pIndex) } } else { pta.x = (double)((pobj->det).e.x); pta.y = (double)((pobj->det).e.y); d = dk4gratool_dist_point_point(&grapt, &pta, NULL); d = d - (double)((pobj->det).e.rx); back = fabs(d); if (NULL != pIndex) { *pIndex = (uint16_t)0U; } } } break; case WXD_OT_ELLIPSE : { if (bCtrlPt) { $? ". ellipse control points" alpha = (M_PI * (double)((pobj->det).e.a)) / 180.0; for (i = 0; i < 4; i++) { switch (i) { case 0 : { pta.x = (double)((pobj->det).e.rx); pta.y = 0.0; } break; case 1 : { pta.x = 0.0; pta.y = (double)((pobj->det).e.ry); } break; case 2 : { pta.x = 0.0 - (double)((pobj->det).e.rx); pta.y = 0.0; } break; case 3 : { pta.x = 0.0; pta.y = 0.0 - (double)((pobj->det).e.ry); } break; } dk4gratool_rotate_point(&pta, alpha); pta.x += (double)((pobj->det).e.x); pta.y += (double)((pobj->det).e.y); d = dk4gratool_dist_point_point(&grapt, &pta, NULL); if (0 == i) { back = d; if (NULL != pIndex) { *pIndex = i; } } else { if (d < back) { back = d; if (NULL != pIndex) { *pIndex = i; } } } } if (NULL != pIndex) { $? ". control point %u", (unsigned)(*pIndex) } } else { pta.x = (double)((pobj->det).e.x); pta.y = (double)((pobj->det).e.y); back = dk4gratool_dist_point_ellipse( &pta,(double)((pobj->det).e.rx),(double)((pobj->det).e.ry), ((M_PI * (double)((pobj->det).e.a)) / 180.0), &grapt, NULL ); } } break; case WXD_OT_BOX : { back = wxdobj_dist_box( &((pobj->det).b.b), (pobj->det).b.r, &grapt, bCtrlPt, pIndex ); } break; case WXD_OT_IMAGE : { back = wxdobj_dist_box( &((pobj->det).i.br), 0UL, &grapt, bCtrlPt, pIndex ); } break; case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : { back = wxdobj_dist_dot(pobj, &grapt); if (NULL != pIndex) { *pIndex = (uint16_t)0U; } } break; } $? "- wxdobj_distance_to_point %g", back return back; } Wxd_stipple_t * wxdobj_find_stipple_structure( Wxd_drawing_t *pdrw, Wxd_object_t *pobj ) { if ((NULL != pdrw) && (NULL != pobj)) { return (i_find_stipple_structure(pdrw,pobj)); } return NULL; } void wxdobj_remove_unused_stipples( Wxd_drawing_t *pdrw ) { Wxd_stipple_t *pstip; Wxd_object_t *pobj; bool changed; $? "+ wxdobj_remove_unused_stipples" /* Mark all stipples as unused */ dk4sto_it_reset(pdrw->i_stip); do { pstip = (Wxd_stipple_t *)dk4sto_it_next(pdrw->i_stip); if (NULL != pstip) { pstip->cd[7] = 0x00; } } while (NULL != pstip); /* Mark used stipples */ dk4sto_it_reset(pdrw->i_flat); do { pobj = (Wxd_object_t *)dk4sto_it_next(pdrw->i_flat); if (NULL != pobj) { if (NULL != pobj->psti) { pobj->psti->cd[7] = 0x01; } } } while (NULL != pobj); /* Remove stipples not marked as used */ do { changed = false; dk4sto_it_reset(pdrw->i_stip); do { pstip = (Wxd_stipple_t *)dk4sto_it_next(pdrw->i_stip); if (NULL != pstip) { if (0x00 == pstip->cd[7]) { $? ". unused stipple found" #if TRACE_DEBUG for (size_t i = 0; i < 8; i++) { $? ". [%u] = %u", (unsigned)i, (unsigned)(pstip->cd[i]) } $? ". bm = %d", TR_IPTR(pstip->bm) #endif changed = true; dk4sto_remove(pdrw->s_stip, pstip, NULL); if (NULL != pstip->bm) { delete (pstip->bm); } dk4mem_free(pstip); } } } while ((NULL != pstip) && (!(changed))); } while (changed); $? "- wxdobj_remove_unused_stipples" } void wxdobj_remove_unused_fonts( Wxd_drawing_t *pdrw ) { Wxd_font_t *pfont; Wxd_object_t *pobj; bool changed; $? "+ wxdobj_remove_unused_fonts" /* Mark all fonts as unused */ dk4sto_it_reset(pdrw->i_fonts); do { pfont = (Wxd_font_t *)dk4sto_it_next(pdrw->i_fonts); if (NULL != pfont) { pfont->used = false; } } while (NULL != pfont); /* Mark used fonts */ dk4sto_it_reset(pdrw->i_flat); do { pobj = (Wxd_object_t *)dk4sto_it_next(pdrw->i_flat); if (NULL != pobj) { if (WXD_OT_TEXT == pobj->ot) { if (NULL != (pobj->det).t.font) { ((pobj->det).t.font)->used = true; } } } } while (NULL != pobj); /* Remove fonts not marked as used */ do { changed = false; dk4sto_it_reset(pdrw->i_fonts); do { pfont = (Wxd_font_t *)dk4sto_it_next(pdrw->i_fonts); if (NULL != pfont) { if (!(pfont->used)) { changed = true; dk4sto_remove(pdrw->s_fonts, pfont, NULL); if (NULL != pfont->font) { delete (pfont->font); pfont->font = NULL; } dk4mem_free(pfont); } } } while ((NULL != pfont) && (!(changed))); } while (changed); $? "- wxdobj_remove_unused_fonts" } size_t wxdobj_get_number_of_layers( Wxd_drawing_t *pdrw ) { size_t back = 0U; $? "+ wxdobj_get_number_of_layers" if (NULL != pdrw) { if (NULL != pdrw->i_layers) { dk4sto_it_reset(pdrw->i_layers); while (NULL != dk4sto_it_next(pdrw->i_layers)) { back++; } } } $? "- wxdobj_get_number_of_layers %u", (unsigned)back return back; } void wxdobj_obj_delete_from_drawing( Wxd_drawing_t *pdrw, Wxd_object_t *pobj ) { Wxd_object_t *po; Wxd_object_t *pn; $? "+ wxdobj_obj_delete_from_drawing" if ((NULL != pdrw) && (NULL != pobj)) { if (WXD_OT_GROUP_BEGIN == pobj->ot) { $? ". group" dk4sto_remove(pdrw->s_stru, (void *)pobj, NULL); pobj->pa = NULL; dk4sto_it_reset((pobj->det).g.i_e); while (NULL != pobj) { $? ". start of loop" po = (Wxd_object_t *)dk4sto_it_next((pobj->det).g.i_e); if (NULL != po) { $? ". yet another object" if (WXD_OT_GROUP_BEGIN == po->ot) { $? ". group object" if ( (NULL != (po->det).g.s_e) && (NULL != (po->det).g.i_e) ) { $? ". complete group" dk4sto_it_reset((po->det).g.i_e); po->pa = pobj; pobj = po; } else { $? ". incomplete group" wxdobj_obj_delete(po); } } else { $? ". normal object" dk4sto_remove(pdrw->s_flat, (void *)po, NULL); wxdobj_obj_delete(po); } } else { $? ". no more contents objects" pn = pobj->pa; wxdobj_obj_delete(pobj); pobj = pn; } $? ". end of loop %d", TR_IPTR(pobj) } } else { $? ". simple object" dk4sto_remove(pdrw->s_stru, (void *)pobj, NULL); dk4sto_remove(pdrw->s_flat, (void *)pobj, NULL); wxdobj_obj_delete(pobj); } } else { $? "! pdrw, pobj" if (NULL != pobj) { wxdobj_obj_delete(pobj); } } $? "- wxdobj_obj_delete_from_drawing" } int wxdobj_shift(Wxd_object_t *pobj, Wxd_point_t *ppt, int doit) { dk4_er_t er; int32_t xdiff = (int32_t)0L; int32_t ydiff = (int32_t)0L; int back = 0; uint16_t i = 0; $? "+ wxdobj_shift" if (NULL != pobj) { if (NULL != ppt) { xdiff = ppt->x; ydiff = ppt->y; if (((int32_t)0L != xdiff) || ((int32_t)0L != ydiff)) { dk4error_init(&er); back = 1; switch (pobj->ot) { case WXD_OT_TEXT : { $? ". text" if (0 != doit) { (pobj->det).t.x = dk4ma_int32_t_add( (pobj->det).t.x, xdiff, &er ); (pobj->det).t.y = dk4ma_int32_t_add( (pobj->det).t.y, ydiff, &er ); } else { (void)dk4ma_int32_t_add( (pobj->det).t.x, xdiff, &er ); (void)dk4ma_int32_t_add( (pobj->det).t.y, ydiff, &er ); } } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { $? ". polyline/polygon" if ( (NULL != (pobj->det).p.p) && ((uint16_t)0U < (pobj->det).p.n) ) { for (i = 0; i < (pobj->det).p.n; i++) { if (0 != doit) { ((pobj->det).p.p)[i].x = dk4ma_int32_t_add( ((pobj->det).p.p)[i].x, xdiff, &er ); ((pobj->det).p.p)[i].y = dk4ma_int32_t_add( ((pobj->det).p.p)[i].y, ydiff, &er ); } else { (void)dk4ma_int32_t_add( ((pobj->det).p.p)[i].x, xdiff, &er ); (void)dk4ma_int32_t_add( ((pobj->det).p.p)[i].y, ydiff, &er ); } } } } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { $? ". spline" if ( (NULL != (pobj->det).s.p) && ((uint16_t)0U < (pobj->det).s.n) ) { for (i = 0; i < (pobj->det).s.n; i++) { if (0 != doit) { ((pobj->det).s.p)[i].x = dk4ma_int32_t_add( ((pobj->det).s.p)[i].x, xdiff, &er ); ((pobj->det).s.p)[i].y = dk4ma_int32_t_add( ((pobj->det).s.p)[i].y, ydiff, &er ); } else { (void)dk4ma_int32_t_add( ((pobj->det).s.p)[i].x, xdiff, &er ); (void)dk4ma_int32_t_add( ((pobj->det).s.p)[i].y, ydiff, &er ); } } } } break; case WXD_OT_O_ARC : case WXD_OT_C_ARC : { $? ". arc" if (0 != doit) { (pobj->det).a.x1 = dk4ma_int32_t_add( (pobj->det).a.x1, xdiff, &er ); (pobj->det).a.y1 = dk4ma_int32_t_add( (pobj->det).a.y1, ydiff, &er ); (pobj->det).a.x2 = dk4ma_int32_t_add( (pobj->det).a.x2, xdiff, &er ); (pobj->det).a.y2 = dk4ma_int32_t_add( (pobj->det).a.y2, ydiff, &er ); (pobj->det).a.x3 = dk4ma_int32_t_add( (pobj->det).a.x3, xdiff, &er ); (pobj->det).a.y3 = dk4ma_int32_t_add( (pobj->det).a.y3, ydiff, &er ); (pobj->det).a.x += (double)xdiff; (pobj->det).a.y += (double)ydiff; } else { (void)dk4ma_int32_t_add((pobj->det).a.x1,xdiff,&er); (void)dk4ma_int32_t_add((pobj->det).a.y1,ydiff,&er); (void)dk4ma_int32_t_add((pobj->det).a.x2,xdiff,&er); (void)dk4ma_int32_t_add((pobj->det).a.y2,ydiff,&er); (void)dk4ma_int32_t_add((pobj->det).a.x3,xdiff,&er); (void)dk4ma_int32_t_add((pobj->det).a.y3,ydiff,&er); } } break; case WXD_OT_CIRCLE : case WXD_OT_ELLIPSE : { $? ". circle/ellipse" if (0 != doit) { (pobj->det).e.x = dk4ma_int32_t_add( (pobj->det).e.x, xdiff, &er ); (pobj->det).e.y = dk4ma_int32_t_add( (pobj->det).e.y, ydiff, &er ); } else { (void)dk4ma_int32_t_add((pobj->det).e.x,xdiff,&er); (void)dk4ma_int32_t_add((pobj->det).e.y,ydiff,&er); } } break; case WXD_OT_BOX : { $? ". box" if (0 != doit) { (pobj->det).b.b.xl = dk4ma_int32_t_add( (pobj->det).b.b.xl, xdiff, &er ); (pobj->det).b.b.xr = dk4ma_int32_t_add( (pobj->det).b.b.xr, xdiff, &er ); (pobj->det).b.b.yb = dk4ma_int32_t_add( (pobj->det).b.b.yb, ydiff, &er ); (pobj->det).b.b.yt = dk4ma_int32_t_add( (pobj->det).b.b.yt, ydiff, &er ); } else { (void)dk4ma_int32_t_add( (pobj->det).b.b.xl, xdiff, &er ); (void)dk4ma_int32_t_add( (pobj->det).b.b.xr, xdiff, &er ); (void)dk4ma_int32_t_add( (pobj->det).b.b.yb, ydiff, &er ); (void)dk4ma_int32_t_add( (pobj->det).b.b.yt, ydiff, &er ); } } break; case WXD_OT_IMAGE : { $? ". image" if (0 != doit) { (pobj->det).i.br.xl = dk4ma_int32_t_add( (pobj->det).i.br.xl, xdiff, &er ); (pobj->det).i.br.xr = dk4ma_int32_t_add( (pobj->det).i.br.xr, xdiff, &er ); (pobj->det).i.br.yb = dk4ma_int32_t_add( (pobj->det).i.br.yb, ydiff, &er ); (pobj->det).i.br.yt = dk4ma_int32_t_add( (pobj->det).i.br.yt, ydiff, &er ); /* Re-calculate image placement */ wxdobj_image_placement(pobj); } else { (void)dk4ma_int32_t_add( (pobj->det).i.br.xl, xdiff, &er ); (void)dk4ma_int32_t_add( (pobj->det).i.br.xr, xdiff, &er ); (void)dk4ma_int32_t_add( (pobj->det).i.br.yb, ydiff, &er ); (void)dk4ma_int32_t_add( (pobj->det).i.br.yt, ydiff, &er ); } } break; case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : { $? ". dot" if (0 != doit) { (pobj->det).d.x = dk4ma_int32_t_add( (pobj->det).d.x, xdiff, &er ); (pobj->det).d.y = dk4ma_int32_t_add( (pobj->det).d.y, ydiff, &er ); } else { (void)dk4ma_int32_t_add((pobj->det).d.x,xdiff,&er); (void)dk4ma_int32_t_add((pobj->det).d.y,ydiff,&er); } } break; } if (DK4_E_NONE != er.ec) { back = 0; $? "! overflow" } } else { back = 1; } } else { back = 1; } } $? "- wxdobj_shift %d", back return back; } int wxdobj_shift_marked(Wxd_drawing_t *pdrw, Wxd_point_t *ppt, int doit) { Wxd_object_t *pobj; int back = 0; $? "+ wxdobj_shift_marked" if (NULL != pdrw) { back = 1; dk4sto_it_reset(pdrw->i_flat); do { pobj = (Wxd_object_t *)dk4sto_it_next(pdrw->i_flat); if (NULL != pobj) { if ((uint8_t)0U != (OBJ_MARKER_1 & (pobj->mark))) { if (0 == wxdobj_shift(pobj, ppt, doit)) { back = 0; } } } } while (NULL != pobj); } $? "- wxdobj_shift_marked %d", back return back; } Wxd_object_t * wxdobj_copy(Wxd_object_t *psrc) { Wxd_object_t *back = NULL; wxBitmap *obm = NULL; size_t npt; $? "+ wxdobj_copy %d", TR_IPTR(psrc) if (NULL != psrc) { if (WXD_OT_GROUP_BEGIN != psrc->ot) { back = dk4mem_new(Wxd_object_t,1,NULL); if (NULL != back) { DK4_MEMCPY(back,psrc,sizeof(Wxd_object_t)); back->pa = NULL; switch (psrc->ot) { case WXD_OT_TEXT : { /* t.t, t.tsc */ (back->det).t.t = NULL; (back->det).t.tsc = NULL; (back->det).t.t = dk4strx_dup((psrc->det).t.t, NULL); if (NULL != (back->det).t.t) { if (NULL != (psrc->det).t.tsc) { (back->det).t.tsc = dk4strx_dup((psrc->det).t.tsc, NULL); if (NULL == (back->det).t.tsc) { wxdobj_obj_delete(back); back = NULL; } } } else { wxdobj_obj_delete(back); back = NULL; } } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { /* p.p */ npt = (size_t)((psrc->det).p.n); (back->det).p.p = dk4mem_new(Wxd_point_t, npt, NULL); if (NULL != (back->det).p.p) { npt *= sizeof(Wxd_point_t); DK4_MEMCPY((back->det).p.p,(psrc->det).p.p,npt); } else { wxdobj_obj_delete(back); back = NULL; } } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { /* s.p */ npt = (size_t)((psrc->det).s.n); (back->det).s.p = dk4mem_new(Wxd_spline_point_t,npt,NULL); if (NULL != (back->det).s.p) { npt *= sizeof(Wxd_spline_point_t); DK4_MEMCPY((back->det).s.p,(psrc->det).s.p,npt); } else { wxdobj_obj_delete(back); back = NULL; } } break; case WXD_OT_IMAGE : { /* i.fn, i.bm */ (back->det).i.fn = NULL; (back->det).i.bm = NULL; obm = (psrc->det).i.bm; (back->det).i.fn = dk4strx_dup((psrc->det).i.fn, NULL); if (NULL != (back->det).i.fn) { (back->det).i.bm = new wxBitmap( obm->GetSubBitmap( wxRect(0, 0, obm->GetWidth(), obm->GetHeight()) ) ); if (NULL == (back->det).i.bm) { wxdobj_obj_delete(back); back = NULL; } else { if (!(((back->det).i.bm)->IsOk())) { wxdobj_obj_delete(back); back = NULL; } } } else { wxdobj_obj_delete(back); back = NULL; } } break; } } } } $? "- wxdobj_copy %d", TR_IPTR(back) return back; } /** Test whether the entire group contents can be shifted by given vector. @param pgrsrc Group containing objects to shift. @param psh Shift vector. @param doit Flag: Really do shift operation, 0=test only. @return 1 on success, 0 on error (numeric overflow). */ static int wxdobj_i_group_shift( Wxd_object_t *pgrsrc, Wxd_point_t *psh, int doit ) { Wxd_object_t *pno; int back = 1; $? "+ wxdobj_i_group_shift" pgrsrc->pa = NULL; dk4sto_it_reset((pgrsrc->det).g.i_e); while ((1 == back) && (NULL != pgrsrc)) { pno = (Wxd_object_t *)dk4sto_it_next((pgrsrc->det).g.i_e); if (NULL != pno) { if (WXD_OT_GROUP_BEGIN == pno->ot) { if ( (NULL != (pgrsrc->det).g.s_e) && (NULL != (pgrsrc->det).g.i_e) ) { pno->pa = pgrsrc; pgrsrc = pno; dk4sto_it_reset((pgrsrc->det).g.i_e); } } else { if (0 == wxdobj_shift(pno, psh, doit)) { back = 0; } } } else { pgrsrc = pgrsrc->pa; } } $? "- wxdobj_i_group_shift %d", back return back; } /** Test whether the entire group contents can be shifted by given vector. @param pgrsrc Group containing objects to shift. @param psh Shift vector. @return 1 on success, 0 on error (numeric overflow). */ static int wxdobj_group_test_shift( Wxd_object_t *pgrsrc, Wxd_point_t *psh ) { int back = 0; $? "+ wxdobj_group_test_shift" if (NULL != pgrsrc) { if (NULL != psh) { if (((int32_t)0L != psh->x) || ((int32_t)0L != psh->y)) { back = wxdobj_i_group_shift(pgrsrc, psh, 0); } else { $? ". 0 vector" back = 1; } } else { $? ". no vector" back = 1; } } $? "- wxdobj_group_test_shift %d", back return back; } /** Copy group contents recursively. Both source and destination group object must be root group objects having no parent. @param pdrw Drawing containing both groups. @param pgrdst Destination group. @param pgrsrc Source group. @param psh Shift vector for the copy. @return 1 on success, 0 on error. */ static int wxdobj_i_group_copy( Wxd_drawing_t *pdrw, Wxd_object_t *pgrdst, Wxd_object_t *pgrsrc, Wxd_point_t *psh ) { Wxd_object_t *pso; Wxd_object_t *pdo; int back = 1; $? "+ wxdobj_i_group_copy" dk4sto_it_reset((pgrsrc->det).g.i_e); while ((NULL != pgrsrc) && (NULL != pgrdst) && (1 == back)) { pso = (Wxd_object_t *)dk4sto_it_next((pgrsrc->det).g.i_e); if (NULL != pso) { if (WXD_OT_GROUP_BEGIN == pso->ot) { if ( (NULL != (pso->det).g.s_e) && (NULL != (pso->det).g.i_e) ) { pdo = wxdobj_drw_add_group(pdrw, pgrdst); if (NULL != pdo) { dk4sto_it_reset((pso->det).g.i_e); pgrsrc = pso; pgrdst = pdo; } else { back = 0; } } } else { pdo = wxdobj_copy(pso); if (NULL != pdo) { if (0 != wxdobj_drw_register_object(pdrw, pgrdst, pdo)) { wxdobj_shift(pdo, psh, 1); } else { wxdobj_obj_delete(pdo); back = 0; } } else { back = 0; } } } else { pgrsrc = pgrsrc->pa; pgrdst = pgrdst->pa; } } $? "- wxdobj_i_group_copy %d", back return back; } int wxdobj_copy_recursive( Wxd_drawing_t *pdrw, Wxd_object_t *pobj, Wxd_point_t *psh ) { Wxd_object_t *pno; Wxd_object_t *png; int back = 0; $? "+ wxdobj_copy_recursive" if ((NULL != pdrw) && (NULL != pobj)) { if (WXD_OT_GROUP_BEGIN != pobj->ot) { /* Copy simple object */ if (0 != wxdobj_shift(pobj, psh, 0)) { pno = wxdobj_copy(pobj); if (NULL != pno) { wxdobj_shift(pno, psh, 1); if (0 != wxdobj_drw_register_object(pdrw, NULL, pno)) { back = 1; wxdobj_bb_simple_object(pdrw, pno); } else { wxdobj_obj_delete(pno); /* ERROR: Memory */ #if 0 dk4error_set_simple_error_code( &m_oErrorReport, DK4_E_MEMORY_ALLOCATION_FAILED ); #endif back = 0; } } else { /* ERROR: Memory */ #if 0 dk4error_set_simple_error_code( &m_oErrorReport, DK4_E_MEMORY_ALLOCATION_FAILED ); #endif back = 0; } } else { $? "! shift" /* ERROR: Failed to shift */ #if 0 dk4error_set_simple_error_code( &m_oErrorReport, WXD_E_OVERFLOW_COORDINATES ); #endif back = 0; } } else { /* Copy a group of objects, probably including subgroups... */ if (0 != wxdobj_group_test_shift(pobj, psh)) { png = wxdobj_drw_add_group(pdrw, NULL); if (NULL != png) { back = wxdobj_i_group_copy(pdrw, png, pobj, psh); wxdobj_bb_modified_object(pdrw, png); } else { /* ERROR: Memory */ #if 0 dk4error_set_simple_error_code( &m_oErrorReport, DK4_E_MEMORY_ALLOCATION_FAILED ); #endif back = false; } } else { $? "! shift" /* ERROR: Failed to shift */ #if 0 dk4error_set_simple_error_code( &m_oErrorReport, WXD_E_OVERFLOW_COORDINATES ); #endif back = false; } } } $? "- wxdobj_copy_recursive %d", back return back; } Wxd_object_t * wxdobj_point_move_find_object( Wxd_drawing_t *pdrw, Wxd_point_t const *ppt, uint16_t *pindex, double dlim ) { Wxd_object_t *back = NULL; /* Object to modify */ Wxd_object_t *pcand = NULL; /* Current object to test */ double backd; /* Distance to back */ double candd; /* Distance to cand */ double backx; /* Distance to back */ double candx; /* Distance to cand */ uint16_t backi; /* Point index on back */ uint16_t candi; /* Point index on cand */ $? "+ wxdobj_point_move_find_object dlim=%g", dlim if ((NULL != pdrw) && (NULL != ppt) && (NULL != pindex)) { dk4sto_it_reset(pdrw->i_flat); do { pcand = (Wxd_object_t *)dk4sto_it_next(pdrw->i_flat); if (NULL != pcand) { $? ". yet another object to test" if (wxdobj_is_active(pcand)) { switch ( (int)(pcand->ot) ) { case WXD_OT_TEXT : case WXD_OT_POLYLINE : case WXD_OT_O_SPLINE : case WXD_OT_O_ARC : case WXD_OT_POLYGON : case WXD_OT_C_SPLINE : case WXD_OT_C_ARC : case WXD_OT_CIRCLE : case WXD_OT_ELLIPSE : case WXD_OT_BOX : case WXD_OT_IMAGE : case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : { candd = wxdobj_distance_to_point(pcand,ppt,true,&candi); candx = wxdobj_distance_to_point(pcand, ppt); $? ". candd=%g candx=%g", candd, candx if (dlim >= candd) { $? ". within limit" if (NULL == back) { $? ". first object" back = pcand; backd = candd; backx = candx; backi = candi; } else { $? ". already have obj" if (backd > candd) { $? ". smaller distance" back = pcand; backd = candd; backx = candx; backi = candi; } else { if ((!(backd < candd)) && (backx > candx)) { $? ". equal distance, better" back = pcand; backd = candd; backx = candx; backi = candi; } #if TRACE_DEBUG else { $? ". distances larger" } #endif } } } #if TRACE_DEBUG else { $? ". distance larger than limit" } #endif } break; } } } } while (NULL != pcand); if (NULL != back) { *pindex = backi; } } $? "- wxdobj_point_move_find_object %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_modify_spline_find_object( Wxd_drawing_t *pdrw, Wxd_point_t const *ppt, uint16_t *pindex, double dlim ) { Wxd_object_t *back = NULL; /* Object to modify */ Wxd_object_t *pcand = NULL; /* Current object to test */ double backd; /* Distance to back */ double candd; /* Distance to cand */ double backx; /* Distance to back */ double candx; /* Distance to cand */ uint16_t backi; /* Point index on back */ uint16_t candi; /* Point index on cand */ $? "+ wxdobj_point_move_find_object dlim=%g", dlim if ((NULL != pdrw) && (NULL != ppt) && (NULL != pindex)) { dk4sto_it_reset(pdrw->i_flat); do { pcand = (Wxd_object_t *)dk4sto_it_next(pdrw->i_flat); if (NULL != pcand) { $? ". yet another object to test" if (wxdobj_is_active(pcand)) { switch ( (int)(pcand->ot) ) { case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { candd = wxdobj_distance_to_point(pcand,ppt,true,&candi); candx = wxdobj_distance_to_point(pcand, ppt); $? ". candd=%g candx=%g", candd, candx if (dlim >= candd) { $? ". within limit" if (NULL == back) { $? ". first object" back = pcand; backd = candd; backx = candx; backi = candi; } else { $? ". already have obj" if (backd > candd) { $? ". smaller distance" back = pcand; backd = candd; backx = candx; backi = candi; } else { if ((!(backd < candd)) && (backx > candx)) { $? ". equal distance, better" back = pcand; backd = candd; backx = candx; backi = candi; } #if TRACE_DEBUG else { $? ". distances larger" } #endif } } } #if TRACE_DEBUG else { $? ". distance larger than limit" } #endif } break; } } } } while (NULL != pcand); if (NULL != back) { *pindex = backi; } } $? "- wxdobj_point_move_find_object %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_rotate_find_object( Wxd_drawing_t *pdrw, Wxd_point_t const *ppt, uint16_t *pindex, double dlim ) { Wxd_object_t *back = NULL; /* Object to modify */ Wxd_object_t *pcand = NULL; /* Current object to test */ double backd; /* Distance to back */ double candd; /* Distance to cand */ double backx; /* Distance to back */ double candx; /* Distance to cand */ uint16_t backi; /* Point index on back */ uint16_t candi; /* Point index on cand */ bool is_rotatable; /* Object is rotatable */ $? "+ wxdobj_rotate_find_object dlim=%g", dlim if ((NULL != pdrw) && (NULL != ppt) && (NULL != pindex)) { dk4sto_it_reset(pdrw->i_flat); do { pcand = (Wxd_object_t *)dk4sto_it_next(pdrw->i_flat); if (NULL != pcand) { $? ". yet another object to test" if (wxdobj_is_active(pcand)) { is_rotatable = false; switch ( (int)(pcand->ot) ) { case WXD_OT_TEXT : case WXD_OT_POLYLINE : case WXD_OT_O_SPLINE : case WXD_OT_O_ARC : case WXD_OT_POLYGON : case WXD_OT_C_SPLINE : case WXD_OT_C_ARC : case WXD_OT_CIRCLE : case WXD_OT_ELLIPSE : case WXD_OT_BOX : case WXD_OT_IMAGE : { is_rotatable = true; } break; case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : { if (NULL != pcand->pa) { is_rotatable = true; } } break; } if (is_rotatable) { candd = wxdobj_distance_to_point(pcand,ppt,true,&candi); candx = wxdobj_distance_to_point(pcand, ppt); $? ". candd=%g candx=%g", candd, candx if (dlim >= candd) { $? ". within limit" if (NULL == back) { $? ". first object" back = pcand; backd = candd; backx = candx; backi = candi; } else { $? ". already have obj" if (backd > candd) { $? ". smaller distance" back = pcand; backd = candd; backx = candx; backi = candi; } else { if ((!(backd < candd)) && (backx > candx)) { $? ". equal distance, better" back = pcand; backd = candd; backx = candx; backi = candi; } #if TRACE_DEBUG else { $? ". distances larger" } #endif } } } #if TRACE_DEBUG else { $? ". distance larger than limit" } #endif } } } } while (NULL != pcand); if (NULL != back) { *pindex = backi; } } $? "- wxdobj_rotate_find_object %d", TR_IPTR(back) return back; } /** Check whether to insert the new point before the selected point or append after the selected point. @param pobj Object to modify. @param ppt Mouse position, not grid-aligned. @param ileft Index of "left side" point. @param ipoint Index of selected point. @param iright Index of "right side" point. @param pbapp Address of flag to set for appending (true) or inserting (false). */ static void wxdobj_point_add_find_poly_point( Wxd_object_t *pobj, Wxd_point_t const *ppt, uint16_t ileft, uint16_t ipoint, uint16_t iright, bool *pbapp ) { dk4_gra_point_t pta; dk4_gra_point_t ptb; dk4_gra_point_t ptc; dk4_gra_point_t ptt; double da; double db; $? "+ wxdobj_point_add_find_poly_point" pta.x = (double)(((pobj->det).p.p)[ileft].x); pta.y = (double)(((pobj->det).p.p)[ileft].y); ptb.x = (double)(((pobj->det).p.p)[iright].x); ptb.y = (double)(((pobj->det).p.p)[iright].y); ptc.x = (double)(((pobj->det).p.p)[ipoint].x); ptc.y = (double)(((pobj->det).p.p)[ipoint].y); ptt.x = (double)(ppt->x); ptt.y = (double)(ppt->y); da = dk4gratool_dist_point_track(&pta, &ptc, &ptt, NULL); db = dk4gratool_dist_point_track(&ptb, &ptc, &ptt, NULL); *pbapp = (db < da); $? "- wxdobj_point_add_find_poly_point" } /** Check whether to insert the new point before the selected point or append after the selected point. @param pobj Object to modify. @param ppt Mouse position, not grid-aligned. @param ileft Index of "left side" point. @param ipoint Index of selected point. @param iright Index of "right side" point. @param pbapp Address of flag to set for appending (true) or inserting (false). */ static void wxdobj_point_add_find_spline_point( Wxd_object_t *pobj, Wxd_point_t const *ppt, uint16_t ileft, uint16_t ipoint, uint16_t iright, bool *pbapp ) { dk4_gra_point_t pta; dk4_gra_point_t ptb; dk4_gra_point_t ptc; dk4_gra_point_t ptt; double da; double db; $? "+ wxdobj_point_add_find_spline_point" pta.x = (double)(((pobj->det).s.p)[ileft].x); pta.y = (double)(((pobj->det).s.p)[ileft].y); ptb.x = (double)(((pobj->det).s.p)[iright].x); ptb.y = (double)(((pobj->det).s.p)[iright].y); ptc.x = (double)(((pobj->det).s.p)[ipoint].x); ptc.y = (double)(((pobj->det).s.p)[ipoint].y); ptt.x = (double)(ppt->x); ptt.y = (double)(ppt->y); da = dk4gratool_dist_point_track(&pta, &ptc, &ptt, NULL); db = dk4gratool_dist_point_track(&ptb, &ptc, &ptt, NULL); *pbapp = (db < da); $? "- wxdobj_point_add_find_spline_point" } /** Find object to add points to or delete points from. @param pdrw Drawing to search. @param ppt Mouse position. @param pindex Address of index variable to set on success. @param dlim Distance limit. @param doadd Flag: Find object to add points to. @return Object found. */ static Wxd_object_t * wxdobj_point_del_find_object_internal( Wxd_drawing_t *pdrw, Wxd_point_t const *ppt, uint16_t *pindex, double dlim, int doadd ) { Wxd_object_t *back = NULL; /* Object to modify */ Wxd_object_t *pcand = NULL; /* Current object to test */ double backd; /* Distance to back */ double candd; /* Distance to cand */ double backx; /* Distance to back */ double candx; /* Distance to cand */ uint16_t backi; /* Point index on back */ uint16_t candi; /* Point index on cand */ bool btest; if ((NULL != pdrw) && (NULL != ppt) && (NULL != pindex)) { backi = (uint16_t)0U; dk4sto_it_reset(pdrw->i_flat); do { pcand = (Wxd_object_t *)dk4sto_it_next(pdrw->i_flat); if (NULL != pcand) { btest = false; /* For open splines and polylines we need at least 2 points remaining after deleting a point. For closed splines and polygons we need at least 3 points remaining after deleting a point. 2020-08-28 When adding point there must be less than UINT16_MAX existing points. */ switch ( (int)(pcand->ot) ) { case WXD_OT_POLYLINE : { if (0 != doadd) { if (UINT16_MAX > (pcand->det).p.n) { btest = true; } } else { if ((uint16_t)2U < (pcand->det).p.n) { btest = true; } } } break; case WXD_OT_POLYGON : { if (0 != doadd) { if (UINT16_MAX > (pcand->det).p.n) { btest = true; } } else { if ((uint16_t)3U < (pcand->det).p.n) { btest = true; } } } break; case WXD_OT_O_SPLINE : { if (0 != doadd) { if (UINT16_MAX > (pcand->det).s.n) { btest = true; } } else { if ((uint16_t)2U < (pcand->det).s.n) { btest = true; } } } break; case WXD_OT_C_SPLINE : { if (0 != doadd) { if (UINT16_MAX > (pcand->det).s.n) { btest = true; } } else { if ((uint16_t)3U < (pcand->det).s.n) { btest = true; } } } break; } if (btest) { if (!wxdobj_is_active(pcand)) { btest = false; } } if (btest) { candd = wxdobj_distance_to_point(pcand, ppt, true, &candi); candx = wxdobj_distance_to_point(pcand, ppt); if (dlim >= candd) { if (NULL == back) { back = pcand; backd = candd; backx = candx; backi = candi; } else { if (backd > candd) { back = pcand; backd = candd; backx = candx; backi = candi; } else { if ((!(backd < candd)) && (backx > candx)) { back = pcand; backd = candd; backx = candx; backi = candi; } #if TRACE_DEBUG else { $? ". distances larger" } #endif } } } #if TRACE_DEBUG else { $? ". distance larger than limit" } #endif } } } while (NULL != pcand); if (NULL != back) { *pindex = backi; } } return back; } Wxd_object_t * wxdobj_point_add_find_object( Wxd_drawing_t *pdrw, Wxd_point_t const *ppt, uint16_t *pindex, bool *pbapp, double dlim ) { dk4_gra_point_t pta; dk4_gra_point_t ptb; dk4_gra_point_t ptt; Wxd_object_t *back = NULL; double da; double db; uint16_t ileft = (uint16_t)0U; uint16_t iright = (uint16_t)0U; bool bAppend = false; $? "+ wxdobj_point_add_find_object" back = wxdobj_point_del_find_object_internal(pdrw, ppt, pindex, dlim, 1); if (NULL != back) { ileft = *pindex - (uint16_t)1U; iright = *pindex + (uint16_t)1U; switch ( (int)(back->ot) ) { case WXD_OT_POLYLINE : { $? ". polyline" if ((uint16_t)0U < *pindex) { if ( ((back->det).p.n - (uint16_t)1U) > *pindex) { $? ". inner point" wxdobj_point_add_find_poly_point( back, ppt, ileft, *pindex, iright, &bAppend ); } else { $? ". end point" pta.x = (double)(((back->det).p.p)[ileft].x); pta.y = (double)(((back->det).p.p)[ileft].y); ptb.x = (double)(((back->det).p.p)[*pindex].x); ptb.y = (double)(((back->det).p.p)[*pindex].y); ptt.x = (double)(ppt->x); ptt.y = (double)(ppt->y); da = dk4gratool_dist_point_point(&ptb, &pta, NULL); db = dk4gratool_dist_point_point(&ptt, &pta, NULL); bAppend = (db > da); } } else { $? ". start point" pta.x = (double)(((back->det).p.p)[0].x); pta.y = (double)(((back->det).p.p)[0].y); ptb.x = (double)(((back->det).p.p)[1].x); ptb.y = (double)(((back->det).p.p)[1].y); ptt.x = (double)(ppt->x); ptt.y = (double)(ppt->y); da = dk4gratool_dist_point_point(&pta, &ptb, NULL); db = dk4gratool_dist_point_point(&ptt, &ptb, NULL); bAppend = (db <= da); } } break; case WXD_OT_O_SPLINE : { $? ". open spline" if ((uint16_t)0U < *pindex) { if ( ((back->det).s.n - (uint16_t)1U) > *pindex) { $? ". inner point" wxdobj_point_add_find_spline_point( back, ppt, ileft, *pindex, iright, &bAppend ); } else { $? ". end point" pta.x = (double)(((back->det).s.p)[ileft].x); pta.y = (double)(((back->det).s.p)[ileft].y); ptb.x = (double)(((back->det).s.p)[*pindex].x); ptb.y = (double)(((back->det).s.p)[*pindex].y); ptt.x = (double)(ppt->x); ptt.y = (double)(ppt->y); da = dk4gratool_dist_point_point(&ptb, &pta, NULL); db = dk4gratool_dist_point_point(&ptt, &pta, NULL); bAppend = (db > da); } } else { $? ". start point" pta.x = (double)(((back->det).s.p)[0].x); pta.y = (double)(((back->det).s.p)[0].y); ptb.x = (double)(((back->det).s.p)[1].x); ptb.y = (double)(((back->det).s.p)[1].y); ptt.x = (double)(ppt->x); ptt.y = (double)(ppt->y); da = dk4gratool_dist_point_point(&pta, &ptb, NULL); db = dk4gratool_dist_point_point(&ptt, &ptb, NULL); bAppend = (db <= da); } } break; case WXD_OT_POLYGON : { $? ". polygon" if ((uint16_t)0U < *pindex) { if ( ((back->det).p.n - (uint16_t)1U) <= *pindex) { $? ". last point" iright = (uint16_t)0U; } } else { $? ". first point" ileft = (back->det).p.n - (uint16_t)1U; } wxdobj_point_add_find_poly_point( back, ppt, ileft, *pindex, iright, &bAppend ); } break; case WXD_OT_C_SPLINE : { $? ". closed spline" if ((uint16_t)0U < *pindex) { if ( ((back->det).s.n - (uint16_t)1U) <= *pindex) { iright = (uint16_t)0U; } } else { $? ". start point" ileft = (back->det).s.n - (uint16_t)1U; } wxdobj_point_add_find_spline_point( back, ppt, ileft, *pindex, iright, &bAppend ); } break; } *pbapp = bAppend; } $? "- wxdobj_point_add_find_object %d", TR_IPTR(back) return back; } Wxd_object_t * wxdobj_point_del_find_object( Wxd_drawing_t *pdrw, Wxd_point_t const *ppt, uint16_t *pindex, double dlim ) { return (wxdobj_point_del_find_object_internal(pdrw, ppt, pindex, dlim, 0)); } static void wxdobj_get_box_control_point( Wxd_point_t *pdst, Wxd_bb_t const *psrc, uint16_t pind ) { switch ( (int)pind ) { case 3 : { pdst->x = psrc->xl; pdst->y = psrc->yt; } break; case 2 : { pdst->x = psrc->xr; pdst->y = psrc->yt; } break; case 1 : { pdst->x = psrc->xr; pdst->y = psrc->yb; } break; default : { pdst->x = psrc->xl; pdst->y = psrc->yb; } break; } } static void wxdobj_set_box_control_point( Wxd_bb_t *pdst, Wxd_point_t const *psrc, uint16_t pind ) { switch ( (int)pind ) { case 3 : { pdst->xl = psrc->x; pdst->yt = psrc->y; } break; case 2 : { pdst->xr = psrc->x; pdst->yt = psrc->y; } break; case 1 : { pdst->xr = psrc->x; pdst->yb = psrc->y; } break; default : { pdst->xl = psrc->x; pdst->yb = psrc->y; } break; } } static void wxdobj_set_ellipse_control_point( Wxd_object_t *pdst, Wxd_point_t const *psrc, uint16_t pind, dk4_er_t *erp ) { int32_t r; int16_t rot; double dx; double dy; double a; $? "+ wxdobj_set_ellipse_control_point %u", (unsigned)pind $? ". psrc.x = %ld", (long)(psrc->x) $? ". psrc.y = %ld", (long)(psrc->y) dx = (double)(psrc->x) - (double)((pdst->det).e.x); dy = (double)(psrc->y) - (double)((pdst->det).e.y); $? ". dx = %g", dx $? ". dy = %g", dy r = dk4ma_int32_from_double( dk4ma_rint(sqrt(dx * dx + dy * dy)), erp ); $? ". r = %ld", (long)r a = atan2(dy, dx); $? ". a = %g", a if (dk4ma_is_finite(a)) { rot = dk4ma_int16_from_double( dk4ma_rint((180.0 * a) / M_PI), erp ); $? ". rot = %d", (int)rot while (-360 > rot) { rot += (int16_t)360; } while ( 360 < rot) { rot -= (int16_t)360; } $? ". rot = %d", (int)rot switch ( (int)pind ) { case 3 : { $? ". control point 3" (pdst->det).e.ry = r; $? ". ry = %ld", (long)r rot -= 270; while (-360 > rot) { rot += (int16_t)360; } } break; case 2 : { $? ". control point 2" (pdst->det).e.rx = r; $? ". rx = %ld", (long)r rot -= 180; while (-360 > rot) { rot += (int16_t)360; } } break; case 1 : { $? ". control point 1" (pdst->det).e.ry = r; $? ". ry = %ld", (long)r rot -= 90; while (-360 > rot) { rot += (int16_t)360; } } break; default : { $? ". control point 0" (pdst->det).e.rx = r; $? ". rx = %ld", (long)r } break; } (pdst->det).e.a = rot; $? ". r=%d rot=%d", (int)r, (int)rot } else { $? "! failed to calculate rotation" dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); } $? "- wxdobj_set_ellipse_control_point" } bool wxdobj_get_control_point( Wxd_point_t *pdst, Wxd_object_t const *psrc, uint16_t pind ) { dk4_er_t er; /* Error report */ dk4_gra_point_t pta; /* Graphics point */ bool back = false; /* Function result */ $? "+ wxdobj_get_control_point" if ((NULL != pdst) && (NULL != psrc)) { switch ( (int)(psrc->ot) ) { case WXD_OT_TEXT : { pdst->x = (psrc->det).t.x; pdst->y = (psrc->det).t.y; back = true; } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { if ((NULL != (psrc->det).p.p) && (pind < (psrc->det).p.n)) { pdst->x = ((psrc->det).p.p)[pind].x; pdst->y = ((psrc->det).p.p)[pind].y; back = true; } } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { if ((NULL != (psrc->det).s.p) && (pind < (psrc->det).s.n)) { pdst->x = ((psrc->det).s.p)[pind].x; pdst->y = ((psrc->det).s.p)[pind].y; back = true; } } break; case WXD_OT_O_ARC : case WXD_OT_C_ARC : { if (2U == pind) { pdst->x = (psrc->det).a.x3; pdst->y = (psrc->det).a.y3; back = true; } else { if (1U == pind) { pdst->x = (psrc->det).a.x2; pdst->y = (psrc->det).a.y2; back = true; } else { pdst->x = (psrc->det).a.x1; pdst->y = (psrc->det).a.y1; back = true; } } } break; case WXD_OT_CIRCLE : { if ((uint32_t)(DK4_I32_MAX) >= (psrc->det).e.rx) { dk4error_init(&er); switch ( (int)pind ) { case 3 : { pdst->x = (psrc->det).e.x; pdst->y = dk4ma_int32_t_sub( (psrc->det).e.y,(int32_t)((psrc->det).e.rx),&er ); } break; case 2 : { pdst->x = dk4ma_int32_t_sub( (psrc->det).e.x,(int32_t)((psrc->det).e.rx),&er ); pdst->y = (psrc->det).e.y; } break; case 1 : { pdst->x = (psrc->det).e.x; pdst->y = dk4ma_int32_t_add( (psrc->det).e.y,(int32_t)((psrc->det).e.rx),&er ); } break; default : { pdst->x = dk4ma_int32_t_add( (psrc->det).e.x,(int32_t)((psrc->det).e.rx),&er ); pdst->y = (psrc->det).e.y; } break; } if (DK4_E_NONE == er.ec) { back = true; } } } break; case WXD_OT_ELLIPSE : { dk4error_init(&er); if ((int16_t)0 == (psrc->det).e.a) { /* Not rotated */ if ( ((uint32_t)(DK4_I32_MAX) >= (psrc->det).e.rx) && ((uint32_t)(DK4_I32_MAX) >= (psrc->det).e.ry) ) { switch ( (int)pind ) { case 3 : { pdst->x = (psrc->det).e.x; pdst->y = dk4ma_int32_t_sub( (psrc->det).e.y, (int32_t)((psrc->det).e.ry), &er ); } break; case 2 : { pdst->x = dk4ma_int32_t_sub( (psrc->det).e.x, (int32_t)((psrc->det).e.rx), &er ); pdst->y = (psrc->det).e.y; } break; case 1 : { pdst->x = (psrc->det).e.x; pdst->y = dk4ma_int32_t_add( (psrc->det).e.y, (int32_t)((psrc->det).e.ry), &er ); } break; default : { pdst->x = dk4ma_int32_t_add( (psrc->det).e.x, (int32_t)((psrc->det).e.rx), &er ); pdst->y = (psrc->det).e.y; } break; } } if (DK4_E_NONE == er.ec) { back = true; } } else { /* Rotated */ switch ( (int)pind ) { case 3 : { pta.x = 0.0; pta.y = 0.0 - (double)((psrc->det).e.ry); } break; case 2 : { pta.x = 0.0 - (double)((psrc->det).e.rx); pta.y = 0.0; } break; case 1 : { pta.x = 0.0; pta.y = (double)((psrc->det).e.ry); } break; default : { pta.x = (double)((psrc->det).e.rx); pta.y = 0.0; } break; } dk4gratool_rotate_point( &pta, ((M_PI * (double)((psrc->det).e.a)) / 180.0) ); pta.x += (double)((psrc->det).e.x); pta.y += (double)((psrc->det).e.y); pdst->x = dk4ma_int32_from_double(dk4ma_rint(pta.x), &er); pdst->y = dk4ma_int32_from_double(dk4ma_rint(pta.y), &er); if (DK4_E_NONE == er.ec) { back = true; } } } break; case WXD_OT_BOX : { wxdobj_get_box_control_point(pdst, &((psrc->det).b.b), pind); back = true; } break; case WXD_OT_IMAGE : { wxdobj_get_box_control_point(pdst, &((psrc->det).i.br), pind); back = true; } break; case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : { pdst->x = (psrc->det).d.x; pdst->y = (psrc->det).d.y; back = true; } break; } } $? "- wxdobj_get_control_point %d", (back ? 1 : 0) return back; } bool wxdobj_set_control_point( Wxd_object_t *pdst, Wxd_point_t const *psrc, uint16_t pind ) { dk4_er_t er; /* Error report */ double dx; /* X difference control point, center */ double dy; /* Y difference control point, center */ int32_t newr; /* New radius */ bool back = false; /* Function result */ $? "+ wxdobj_set_control_point" if ((NULL != pdst) && (NULL != psrc)) { $? ". psrc.x = %ld", (long)(psrc->x) $? ". psrc.y = %ld", (long)(psrc->y) switch ( (int)(pdst->ot) ) { case WXD_OT_TEXT : { (pdst->det).t.x = psrc->x; (pdst->det).t.y = psrc->y; back = true; } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { if ((NULL != (pdst->det).p.p) && (pind < (pdst->det).p.n)) { ((pdst->det).p.p)[pind].x = psrc->x; ((pdst->det).p.p)[pind].y = psrc->y; back = true; } } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { if ((NULL != (pdst->det).s.p) && (pind < (pdst->det).s.n)) { ((pdst->det).s.p)[pind].x = psrc->x; ((pdst->det).s.p)[pind].y = psrc->y; back = true; } } break; case WXD_OT_O_ARC : case WXD_OT_C_ARC : { if (2U == pind) { (pdst->det).a.x3 = psrc->x; (pdst->det).a.y3 = psrc->y; back = true; } else { if (1U == pind) { (pdst->det).a.x2 = psrc->x; (pdst->det).a.y2 = psrc->y; back = true; } else { (pdst->det).a.x1 = psrc->x; (pdst->det).a.y1 = psrc->y; back = true; } } wxdarc_calculation( &((pdst->det).a.x), &((pdst->det).a.y), &((pdst->det).a.r), &((pdst->det).a.a), &((pdst->det).a.b), &((pdst->det).a.d), (pdst->det).a.x1, (pdst->det).a.y1, (pdst->det).a.x2, (pdst->det).a.y2, (pdst->det).a.x3, (pdst->det).a.y3 ); } break; case WXD_OT_CIRCLE : { dk4error_init(&er); #if 0 /* 2020-03-24 Modification Clang static analyzer complains about this line because newr is overwritten in all the if/else branches below. */ newr = (int32_t)0L; #endif if ((pdst->det).e.x == psrc->x) { newr = dk4ma_int32_t_abs( dk4ma_int32_t_sub((pdst->det).e.y, psrc->y, &er), &er ); } else { if ((pdst->det).e.y == psrc->y) { newr = dk4ma_int32_t_abs( dk4ma_int32_t_sub((pdst->det).e.x,psrc->x,&er), &er ); } else { dx = (double)((pdst->det).e.x) - (double)(psrc->x); dy = (double)((pdst->det).e.y) - (double)(psrc->y); newr = dk4ma_int32_from_double( sqrt(dx * dx + dy * dy), &er ); } } if (DK4_E_NONE == er.ec) { (pdst->det).e.rx = newr; back = true; } } break; case WXD_OT_ELLIPSE : { $? ". set ellipse control point %u", (unsigned)pind dk4error_init(&er); switch ( (int)pind ) { case 3 : { $? ". 3" if ((pdst->det).e.x == psrc->x) { if (psrc->y <= (pdst->det).e.y) { (pdst->det).e.a = 0; (pdst->det).e.ry = dk4ma_int32_t_sub( (pdst->det).e.y, psrc->y, &er ); } else { (pdst->det).e.a = 180; (pdst->det).e.ry = dk4ma_int32_t_sub( psrc->y, (pdst->det).e.y, &er ); } } else { if ((pdst->det).e.y == psrc->y) { if (psrc->x >= (pdst->det).e.x) { (pdst->det).e.a = 90; (pdst->det).e.ry = dk4ma_int32_t_sub( psrc->x, (pdst->det).e.x, &er ); } else { (pdst->det).e.a = -90; (pdst->det).e.ry = dk4ma_int32_t_sub( (pdst->det).e.x, psrc->x, &er ); } } else { wxdobj_set_ellipse_control_point( pdst, psrc, pind, &er ); } } } break; case 2 : { $? ". 2" if ((pdst->det).e.y == psrc->y) { if (psrc->x <= (pdst->det).e.x) { (pdst->det).e.a = 0; (pdst->det).e.rx = dk4ma_int32_t_sub( (pdst->det).e.x, psrc->x, &er ); } else { (pdst->det).e.a = 180; (pdst->det).e.rx = dk4ma_int32_t_sub( psrc->x, (pdst->det).e.x, &er ); } } else { if ((pdst->det).e.x == psrc->x) { if (psrc->y <= (pdst->det).e.y) { (pdst->det).e.a = 90; (pdst->det).e.rx = dk4ma_int32_t_sub( (pdst->det).e.y, psrc->y, &er ); } else { (pdst->det).e.a = -90; (pdst->det).e.rx = dk4ma_int32_t_sub( psrc->y, (pdst->det).e.y, &er ); } } else { wxdobj_set_ellipse_control_point( pdst, psrc, pind, &er ); } } } break; case 1 : { $? ". 1" if ((pdst->det).e.x == psrc->x) { if (psrc->y >= (pdst->det).e.y) { (pdst->det).e.a = 0; (pdst->det).e.ry = dk4ma_int32_t_sub( psrc->y, (pdst->det).e.y, &er ); } else { (pdst->det).e.a = 180; (pdst->det).e.ry = dk4ma_int32_t_sub( (pdst->det).e.y, psrc->y, &er ); } } else { if ((pdst->det).e.y == psrc->y) { if (psrc->x <= (pdst->det).e.x) { (pdst->det).e.a = 90; (pdst->det).e.ry = dk4ma_int32_t_sub( (pdst->det).e.x, psrc->x, &er ); } else { (pdst->det).e.a = -90; (pdst->det).e.ry = dk4ma_int32_t_sub( psrc->x, (pdst->det).e.x, &er ); } } else { wxdobj_set_ellipse_control_point( pdst, psrc, pind, &er ); } } } break; default : { $? ". 0" if ((pdst->det).e.y == psrc->y) { $? ". same y" if (psrc->x >= (pdst->det).e.x) { (pdst->det).e.a = 0; (pdst->det).e.rx = dk4ma_int32_t_sub( psrc->x, (pdst->det).e.x, &er ); } else { (pdst->det).e.a = 180; (pdst->det).e.rx = dk4ma_int32_t_sub( (pdst->det).e.x, psrc->x, &er ); } } else { if ((pdst->det).e.x == psrc->x) { $? ". same x" if (psrc->y >= (pdst->det).e.y) { (pdst->det).e.a = 90; (pdst->det).e.rx = dk4ma_int32_t_sub( psrc->y, (pdst->det).e.y, &er ); } else { (pdst->det).e.a = -90; (pdst->det).e.rx = dk4ma_int32_t_sub( (pdst->det).e.y, psrc->y, &er ); } } else { $? ". rotated" wxdobj_set_ellipse_control_point( pdst, psrc, pind, &er ); } } } break; } if (DK4_E_NONE == er.ec) { back = true; } } break; case WXD_OT_BOX : { wxdobj_set_box_control_point(&((pdst->det).b.b), psrc, pind); back = true; } break; case WXD_OT_IMAGE : { wxdobj_set_box_control_point(&((pdst->det).i.br), psrc, pind); back = true; } break; case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : { (pdst->det).d.x = psrc->x; (pdst->det).d.y = psrc->y; back = true; } break; } } $? "- wxdobj_set_control_point %d", (back ? 1 : 0) return back; } void wxdobj_delete_control_point( Wxd_object_t *pdst, uint16_t pind ) { Wxd_point_t *ptrppt; /* New poly points array */ Wxd_spline_point_t *ptrspl; /* New spline points array */ double olds; /* Old s value */ size_t sz; /* Number of points to allocate */ uint16_t i; /* Traverse control points */ bool bCanDo; /* Can delete point from this object */ bool bBorder; /* Deleted point was border point */ $? "+ wxdobj_delete_control_point" if (NULL != pdst) { bCanDo = false; switch ( (int)(pdst->ot) ) { case WXD_OT_POLYLINE : { if ((uint16_t)2U < (pdst->det).p.n) { bCanDo = true; } } break; case WXD_OT_POLYGON : { if ((uint16_t)3U < (pdst->det).p.n) { bCanDo = true; } } break; case WXD_OT_O_SPLINE : { if ((uint16_t)2U < (pdst->det).s.n) { bCanDo = true; } } break; case WXD_OT_C_SPLINE : { if ((uint16_t)3U < (pdst->det).s.n) { bCanDo = true; } } break; } if (bCanDo) { switch ( (int)(pdst->ot) ) { case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { ptrppt = NULL; sz = (size_t)((pdst->det).p.n); sz--; ptrppt = dk4mem_new(Wxd_point_t, sz, NULL); if (NULL != ptrppt) { DK4_MEMCPY(\ ptrppt, (pdst->det).p.p,\ (sz * sizeof(Wxd_point_t))\ ); if ((size_t)pind < sz) { DK4_MEMCPY(\ &(ptrppt[pind]),\ &(((pdst->det).p.p)[pind + (uint16_t)1U]),\ (\ sizeof(Wxd_point_t) * (sz - (size_t)pind)\ )\ ); } dk4mem_free((pdst->det).p.p); (pdst->det).p.p = ptrppt; (pdst->det).p.n = sz; } else { if ((size_t)pind < sz) { /* Can not do one large memcpy as source and destination range would overlap. */ for (i = pind; (size_t)i < sz; i++) { DK4_MEMCPY(\ &(((pdst->det).p.p)[i]),\ &(((pdst->det).p.p)[i + (uint16_t)1U]),\ sizeof(Wxd_point_t)\ ); } } (pdst->det).p.n = sz; } } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { ptrspl = NULL; sz = (size_t)((pdst->det).s.n); sz--; olds = ((pdst->det).s.p)[pind].s; bBorder = false; if ( (((pdst->det).s.n - (uint16_t)1U) == pind) || ((uint16_t)0U == pind) ) { bBorder = true; } ptrspl = dk4mem_new(Wxd_spline_point_t, sz, NULL); if (NULL != ptrspl) { DK4_MEMCPY(\ ptrspl, (pdst->det).s.p,\ (sz * sizeof(Wxd_spline_point_t))\ ); if ((size_t)pind < sz) { DK4_MEMCPY(\ &(ptrspl[pind]),\ &(((pdst->det).s.p)[pind + (uint16_t)1U]),\ (\ sizeof(Wxd_spline_point_t)\ * (sz - (size_t)pind)\ )\ ); } dk4mem_free((pdst->det).s.p); (pdst->det).s.p = ptrspl; (pdst->det).s.n = sz; } else { if ((size_t)pind < sz) { /* Can not do one large memcpy as source and destination range would overlap. */ for (i = pind; (size_t)i < sz; i++) { DK4_MEMCPY(\ &(((pdst->det).s.p)[i]),\ &(((pdst->det).s.p)[i + (uint16_t)1U]),\ sizeof(Wxd_spline_point_t)\ ); } } (pdst->det).s.n = sz; } if (bBorder) { if ((uint16_t)0U == pind) { ((pdst->det).s.p)[0].s = olds; } else { ((pdst->det).s.p)[sz - (size_t)1U].s = olds; } } } break; } } } $? "- wxdobj_delete_control_point" } bool wxdobj_add_control_point( Wxd_object_t *pdst, uint16_t pind, Wxd_point_t const *ppt ) { Wxd_spline_point_t *ptrspl; Wxd_point_t *ptrppt; size_t oldsz; size_t newsz; bool back = false; bool bCanDo = false; $? "+ wxdobj_add_control_point" if (NULL != pdst) { switch ( (int)(pdst->ot) ) { case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { $? ". polyline/polygon" if ((uint16_t)0xFFFFU > (pdst->det).p.n) { if (pind <= (pdst->det).p.n) { $? ". pind ok" oldsz = (size_t)((pdst->det).p.n); newsz = oldsz + (size_t)1U; ptrppt = dk4mem_new(Wxd_point_t,newsz,NULL); if (NULL != ptrppt) { $? ". allocation ok" DK4_MEMCPY(\ ptrppt, (pdst->det).p.p,\ (oldsz * sizeof(Wxd_point_t))\ ); if ((size_t)pind < oldsz) { DK4_MEMCPY(\ &(ptrppt[pind + (uint16_t)1U]),\ &(((pdst->det).p.p)[pind]),\ (\ (oldsz - (size_t)pind)\ * sizeof(Wxd_point_t)\ )\ ); } dk4mem_free((pdst->det).p.p); (pdst->det).p.p = ptrppt; (pdst->det).p.n = (uint16_t)newsz; ((pdst->det).p.p)[pind].x = ppt->x; ((pdst->det).p.p)[pind].y = ppt->y; back = true; } else { $? "! memory" /* ERROR: Memory */ #if 0 dk4error_set_simple_error_code( &m_oErrorReport, DK4_E_MEMORY_ALLOCATION_FAILED ); #endif back = false; } } else { $? "! pind" /* ERROR: New point index out of range (bug) */ #if 0 dk4error_set_simple_error_code( &m_oErrorReport, WXD_E_BUG_POINT_OOR ); #endif back = false; } } else { $? "! too many points" /* ERROR: Too many points */ #if 0 dk4error_set_simple_error_code( &m_oErrorReport, WXD_E_TOO_MANY_POINTS ); #endif back = false; } } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { $? ". spline" if ((uint16_t)0xFFFFU > (pdst->det).s.n) { if (pind <= (pdst->det).s.n) { oldsz = (size_t)((pdst->det).s.n); newsz = oldsz + (size_t)1U; ptrspl = dk4mem_new(Wxd_spline_point_t,newsz,NULL); if (NULL != ptrspl) { DK4_MEMCPY(\ ptrspl, (pdst->det).s.p,\ (oldsz * sizeof(Wxd_spline_point_t))\ ); if ((size_t)pind < oldsz) { DK4_MEMCPY(\ &(ptrspl[pind + (uint16_t)1U]),\ &(((pdst->det).s.p)[pind]),\ (\ (oldsz - (size_t)pind)\ * sizeof(Wxd_spline_point_t)\ )\ ); } dk4mem_free((pdst->det).s.p); (pdst->det).s.p = ptrspl; (pdst->det).s.n = (uint16_t)newsz; ((pdst->det).s.p)[pind].x = ppt->x; ((pdst->det).s.p)[pind].y = ppt->y; back = true; if ((uint16_t)0U == pind) { ((pdst->det).s.p)[0].s = 0.0; ((pdst->det).s.p)[1].s = ((pdst->det).s.p)[2].s; } else { if (((pdst->det).s.n - (uint16_t)1U) == pind) { ((pdst->det).s.p)[pind].s = 0.0; ((pdst->det).s.p)[pind - (uint16_t)1U].s = ((pdst->det).s.p)[pind - (uint16_t)2U].s; } } } else { $? "! memory" /* ERROR: Memory */ #if 0 dk4error_set_simple_error_code( &m_oErrorReport, DK4_E_MEMORY_ALLOCATION_FAILED ); #endif back = false; } } else { $? "! pind" /* ERROR: New point index out of range (bug) */ #if 0 dk4error_set_simple_error_code( &m_oErrorReport, WXD_E_BUG_POINT_OOR ); #endif back = false; } } else { $? "! too many points" /* ERROR: Too many points */ #if 0 dk4error_set_simple_error_code( &m_oErrorReport, WXD_E_TOO_MANY_POINTS ); #endif back = false; } } break; } if (bCanDo) { } } $? "- wxdobj_add_control_point %d", (back ? 1 : 0) return back; } bool wxdobj_control_pt_to_bb( Wxd_bb_t *pbox, Wxd_object_t const *pobj ) { bool back = false; uint16_t i; if (NULL != pbox) { wxdobj_det_init_bb(pbox); if (NULL != pobj) { switch ( (int)(pobj->ot) ) { case WXD_OT_TEXT : { wxdobj_bb_set_point( pbox, (pobj->det).t.x, (pobj->det).t.y ); back = true; } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { if ((0U < (pobj->det).p.n) && (NULL != (pobj->det).p.p)) { for (i = (uint16_t)0U; i < (pobj->det).p.n; i++) { if ((uint16_t)0U != i) { wxdobj_bb_add_point( pbox, ((pobj->det).p.p)[i].x, ((pobj->det).p.p)[i].y ); } else { wxdobj_bb_set_point( pbox, ((pobj->det).p.p)[i].x, ((pobj->det).p.p)[i].y ); } } back = true; } } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { if ((0U < (pobj->det).s.n) && (NULL != (pobj->det).s.p)) { for (i = (uint16_t)0U; i < (pobj->det).s.n; i++) { if ((uint16_t)0U != i) { wxdobj_bb_add_point( pbox, ((pobj->det).s.p)[i].x, ((pobj->det).s.p)[i].y ); } else { wxdobj_bb_set_point( pbox, ((pobj->det).s.p)[i].x, ((pobj->det).s.p)[i].y ); } } back = true; } } break; case WXD_OT_O_ARC : case WXD_OT_C_ARC : { wxdobj_bb_set_point( pbox, (pobj->det).a.x1, (pobj->det).a.y1 ); wxdobj_bb_add_point( pbox, (pobj->det).a.x2, (pobj->det).a.y2 ); wxdobj_bb_add_point( pbox, (pobj->det).a.x3, (pobj->det).a.y3 ); back = true; } break; case WXD_OT_CIRCLE : case WXD_OT_ELLIPSE : { wxdobj_bb_set_point( pbox, (pobj->det).e.x, (pobj->det).e.y ); back = true; } break; case WXD_OT_BOX : { DK4_MEMCPY(pbox,&((pobj->det).b.b),sizeof(Wxd_bb_t)); back = true; } break; case WXD_OT_IMAGE : { DK4_MEMCPY(pbox,&((pobj->det).i.br),sizeof(Wxd_bb_t)); back = true; } break; case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : { wxdobj_bb_set_point( pbox, (pobj->det).d.x, (pobj->det).d.y ); back = true; } break; } } } return back; } bool wxdobj_flip_object( Wxd_object_t *pobj, Wxd_bb_t const *pbox, bool bVert, bool bRealRun ) { dk4_er_t er; uint16_t i; bool back = false; $? "+ wxdobj_flip_object" if ((NULL != pobj) && (NULL != pbox)) { dk4error_init(&er); switch ( (int)(pobj->ot) ) { case WXD_OT_TEXT : { if (bRealRun) { if (bVert) { (pobj->det).t.y = wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).t.y, &er ); (pobj->det).t.a = (int16_t)0 - (pobj->det).t.a; } else { (pobj->det).t.x = wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).t.x, &er ); (pobj->det).t.a = (int16_t)180 - (pobj->det).t.a; switch ( (int)((pobj->det).t.al) ) { case WXD_TA_RIGHT : { (pobj->det).t.al = (uint8_t)(WXD_TA_LEFT); } break; case WXD_TA_CENTERED : { (pobj->det).t.al = (uint8_t)(WXD_TA_CENTERED); } break; default : { (pobj->det).t.al = (uint8_t)(WXD_TA_RIGHT); } break; } } while ((int16_t)(-360) >= (pobj->det).t.a) { (pobj->det).t.a += (int16_t)360; } while ((int16_t)360 <= (pobj->det).t.a) { (pobj->det).t.a -= (int16_t)360; } } else { if (bVert) { (void)wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).t.y, &er ); } else { (void)wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).t.x, &er ); } } if (DK4_E_NONE == er.ec) { back = true; } } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { if ((NULL != (pobj->det).p.p) && (0U < (pobj->det).p.n)) { if (bRealRun) { if (bVert) { for (i = (uint16_t)0U; i < (pobj->det).p.n; i++) { ((pobj->det).p.p)[i].y = wxdobj_flip_coordinate( pbox->yb, pbox->yt, ((pobj->det).p.p)[i].y, &er ); } } else { for (i = (uint16_t)0U; i < (pobj->det).p.n; i++) { ((pobj->det).p.p)[i].x = wxdobj_flip_coordinate( pbox->xl, pbox->xr, ((pobj->det).p.p)[i].x, &er ); } } } else { if (bVert) { for (i = (uint16_t)0U; i < (pobj->det).p.n; i++) { (void)wxdobj_flip_coordinate( pbox->yb, pbox->yt, ((pobj->det).p.p)[i].y, &er ); } } else { for (i = (uint16_t)0U; i < (pobj->det).p.n; i++) { (void)wxdobj_flip_coordinate( pbox->xl, pbox->xr, ((pobj->det).p.p)[i].x, &er ); } } } if (DK4_E_NONE == er.ec) { back = true; } } } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { if ((NULL != (pobj->det).s.p) && (0U < (pobj->det).s.n)) { if (bRealRun) { if (bVert) { for (i = (uint16_t)0U; i < (pobj->det).s.n; i++) { ((pobj->det).s.p)[i].y = wxdobj_flip_coordinate( pbox->yb, pbox->yt, ((pobj->det).s.p)[i].y, &er ); } } else { for (i = (uint16_t)0U; i < (pobj->det).s.n; i++) { ((pobj->det).s.p)[i].x = wxdobj_flip_coordinate( pbox->xl, pbox->xr, ((pobj->det).s.p)[i].x, &er ); } } } else { if (bVert) { for (i = (uint16_t)0U; i < (pobj->det).s.n; i++) { (void)wxdobj_flip_coordinate( pbox->yb, pbox->yt, ((pobj->det).s.p)[i].y, &er ); } } else { for (i = (uint16_t)0U; i < (pobj->det).s.n; i++) { (void)wxdobj_flip_coordinate( pbox->xl, pbox->xr, ((pobj->det).s.p)[i].x, &er ); } } } if (DK4_E_NONE == er.ec) { back = true; } } } break; case WXD_OT_O_ARC : case WXD_OT_C_ARC : { if (bRealRun) { if (bVert) { (pobj->det).a.y1 = wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).a.y1, &er ); (pobj->det).a.y2 = wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).a.y2, &er ); (pobj->det).a.y3 = wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).a.y3, &er ); } else { (pobj->det).a.x1 = wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).a.x1, &er ); (pobj->det).a.x2 = wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).a.x2, &er ); (pobj->det).a.x3 = wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).a.x3, &er ); } wxdarc_calculation( &((pobj->det).a.x), &((pobj->det).a.y), &((pobj->det).a.r), &((pobj->det).a.a), &((pobj->det).a.b), &((pobj->det).a.d), (pobj->det).a.x1, (pobj->det).a.y1, (pobj->det).a.x2, (pobj->det).a.y2, (pobj->det).a.x3, (pobj->det).a.y3 ); } else { if (bVert) { (void)wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).a.y1, &er ); (void)wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).a.y2, &er ); (void)wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).a.y3, &er ); } else { (void)wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).a.x1, &er ); (void)wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).a.x2, &er ); (void)wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).a.x3, &er ); } } if (DK4_E_NONE == er.ec) { back = true; } } break; case WXD_OT_CIRCLE : case WXD_OT_ELLIPSE : { if (bRealRun) { if (bVert) { (pobj->det).e.y = wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).e.y, &er ); } else { (pobj->det).e.x = wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).e.x, &er ); } if ( (WXD_OT_ELLIPSE == pobj->ot) && ((int16_t)0 != (pobj->det).e.a) ) { if (bVert) { (pobj->det).e.a = (int16_t)0 - (pobj->det).e.a; } else { (pobj->det).e.a = (int16_t)180 - (pobj->det).e.a; } while ((int16_t)(-360) >= (pobj->det).t.a) { (pobj->det).t.a += (int16_t)360; } while ((int16_t)360 <= (pobj->det).t.a) { (pobj->det).t.a -= (int16_t)360; } } } else { if (bVert) { (void)wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).e.y, &er ); } else { (void)wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).e.x, &er ); } } if (DK4_E_NONE == er.ec) { back = true; } } break; case WXD_OT_BOX : { if (bRealRun) { if (bVert) { (pobj->det).b.b.yb = wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).b.b.yb, &er ); (pobj->det).b.b.yt = wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).b.b.yt, &er ); } else { (pobj->det).b.b.xl = wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).b.b.xl, &er ); (pobj->det).b.b.xr = wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).b.b.xr, &er ); } wxdobj_bb_correct(&((pobj->det).b.b)); } else { if (bVert) { (void)wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).b.b.yb, &er ); (void)wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).b.b.yt, &er ); } else { (void)wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).b.b.xl, &er ); (void)wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).b.b.xr, &er ); } } if (DK4_E_NONE == er.ec) { back = true; } } break; case WXD_OT_IMAGE : { if (bRealRun) { if (bVert) { (pobj->det).i.br.yb = wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).i.br.yb, &er ); (pobj->det).i.br.yt = wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).i.br.yt, &er ); } else { (pobj->det).i.br.xl = wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).i.br.xl, &er ); (pobj->det).i.br.xr = wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).i.br.xr, &er ); } wxdobj_bb_correct(&((pobj->det).i.br)); } else { if (bVert) { (void)wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).i.br.yb, &er ); (void)wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).i.br.yt, &er ); } else { (void)wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).i.br.xl, &er ); (void)wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).i.br.xr, &er ); } } if (DK4_E_NONE == er.ec) { back = true; } } break; case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : { if (bRealRun) { if (bVert) { (pobj->det).d.y = wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).d.y, &er ); } else { (pobj->det).d.x = wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).d.x, &er ); } } else { if (bVert) { (void)wxdobj_flip_coordinate( pbox->yb, pbox->yt, (pobj->det).d.y, &er ); } else { (void)wxdobj_flip_coordinate( pbox->xl, pbox->xr, (pobj->det).d.x, &er ); } } if (DK4_E_NONE == er.ec) { back = true; } } break; } } $? "- wxdobj_flip_object %d", (back ? 1 : 0) return back; } bool wxdobj_is_marked(Wxd_object_t const *pobj, uint8_t marker) { bool back = false; $? "+ wxdobj_is_marked" if (NULL != pobj) { if ((uint8_t)0U != (marker & (pobj->mark))) { back = true; } } $? "- wxdobj_is_marked %d", (back ? (1) : (0)) return back; } int wxdobj_num_marked_2(Wxd_drawing_t *pdrw) { Wxd_object_t *pobj; int back = 0; $? "+ wxdobj_num_marked_2" if (NULL != pdrw) { dk4sto_it_reset(pdrw->i_stru); do { pobj = (Wxd_object_t *)dk4sto_it_next(pdrw->i_stru); if (NULL != pobj) { if (wxdobj_is_marked(pobj, OBJ_MARKER_2)) { back++; } } } while ((NULL != pobj) && (2 > back)); } $? "- wxdobj_num_marked_2 %d", back return back; } #if TRACE_DEBUG static void wxdobj_report_bb(dk4_bb_t const *pbb) { #if TRACE_DEBUG $? "+ wxdobj_report_bb" if (0 != dk4bb_have_x(pbb)) { $? ". xmin=%lg xmax=%lg", pbb->xmin, pbb->xmax } else { $? "! no x information" } if (0 != dk4bb_have_y(pbb)) { $? ". ymin=%lg ymax=%lg", pbb->ymin, pbb->ymax } else { $? "! no y information" } $? "- wxdobj_report_bb" #endif } #endif static bool wxdobj_bb_simple_text(Wxd_object_t *pobj) { $? "+ wxdobj_bb_simple_text" dk4bb_init(&(pobj->bb)); dk4bb_add_point( &(pobj->bb), (double)((pobj->det).t.x), (double)((pobj->det).t.y) ); $!trace-code wxdobj_report_bb(&(pobj->bb)); $? "- wxdobj_bb_simple_text" return true; } static bool wxdobj_bb_simple_polyline(Wxd_object_t *pobj) { uint16_t u; bool back = false; $? "+ wxdobj_bb_simple_polyline" dk4bb_init(&(pobj->bb)); if ((NULL != (pobj->det).p.p) && ((uint16_t)0U < (pobj->det).p.n)) { back = true; for (u = (uint16_t)0U; u < (pobj->det).p.n; u++) { dk4bb_add_point( &(pobj->bb), (double)(((pobj->det).p.p)[u].x), (double)(((pobj->det).p.p)[u].y) ); } } $!trace-code wxdobj_report_bb(&(pobj->bb)); $? "- wxdobj_bb_simple_polyline %d", (back ? 1 : 0) return back; } static bool wxdobj_bb_simple_spline( Wxd_object_t *pobj, size_t subsegs ) { double aa[4]; /* Subsegment start */ double ab[4]; /* Subsegment end */ dk4_xsp_2d_t xsp; /* X-spline structure for calculations */ double divisor; /* Divisor for derivatives */ double t; /* Current "time" */ size_t ssegno; /* Current subsegment */ uint16_t nsegs; /* Number of segments in spline */ uint16_t a; /* Point A index */ uint16_t b; /* Point B index */ uint16_t c; /* Point C index */ uint16_t d; /* Point D index */ bool back = false; $? "+ wxdobj_bb_simple_spline" divisor = 3.0 * ((double)subsegs); dk4bb_init(&(pobj->bb)); if ((NULL != (pobj->det).s.p) && ((uint16_t)1U < (pobj->det).s.n)) { back = true; $? ". enough points" nsegs = (pobj->det).s.n; if (WXD_OT_C_SPLINE != pobj->ot) { nsegs--; } $? ". nsegs=%u", (unsigned)nsegs dk4xsp2d_reset(&xsp); for (b = (uint16_t)0U; b < nsegs; b++) { $? ". b=%u", (unsigned)b if (b < ((pobj->det).s.n - (uint16_t)1U)) { c = b + (uint16_t)1U; } else { c = 0; } $? ". c=%u", (unsigned)c if ( (1.0e-7 > fabs(((pobj->det).s.p)[b].s)) && (1.0e-7 > fabs(((pobj->det).s.p)[c].s)) ) { $? ". straight line" dk4bb_add_point( &(pobj->bb), ((pobj->det).s.p)[b].x, ((pobj->det).s.p)[b].y ); dk4bb_add_point( &(pobj->bb), ((pobj->det).s.p)[c].x, ((pobj->det).s.p)[c].y ); } else { $? ". spline segment" dk4xsp2d_reset_points(&xsp); dk4xsp2d_set_point( &xsp, (double)(((pobj->det).s.p)[b].x), (double)(((pobj->det).s.p)[b].y), ((pobj->det).s.p)[b].s, 1 ); dk4xsp2d_set_point( &xsp, (double)(((pobj->det).s.p)[c].x), (double)(((pobj->det).s.p)[c].y), ((pobj->det).s.p)[c].s, 2 ); if (b < ((pobj->det).s.n - (uint16_t)2U)) { d = b + (uint16_t)2U; $? ". d=%u", (unsigned)d dk4xsp2d_set_point( &xsp, (double)(((pobj->det).s.p)[d].x), (double)(((pobj->det).s.p)[d].y), ((pobj->det).s.p)[d].s, 3 ); } else { if (WXD_OT_C_SPLINE == pobj->ot) { d = b - ((pobj->det).s.n - (uint16_t)2U); $? ". d=%u", (unsigned)d dk4xsp2d_set_point( &xsp, (double)(((pobj->det).s.p)[d].x), (double)(((pobj->det).s.p)[d].y), ((pobj->det).s.p)[d].s, 3 ); } } if ((uint16_t)0U < b) { a = b - (uint16_t)1U; $? ". a=%u", (unsigned)a dk4xsp2d_set_point( &xsp, (double)(((pobj->det).s.p)[a].x), (double)(((pobj->det).s.p)[a].y), ((pobj->det).s.p)[a].s, 0 ); } else { if (WXD_OT_C_SPLINE == pobj->ot) { a = (pobj->det).s.n - (uint16_t)1U; $? ". a=%u", (unsigned)a dk4xsp2d_set_point( &xsp, (double)(((pobj->det).s.p)[a].x), (double)(((pobj->det).s.p)[a].y), ((pobj->det).s.p)[a].s, 0 ); } } /* Minimum number of sub segments is 2 */ if ((size_t)2U > subsegs) { subsegs = (size_t)2U; } /* Start point of segment */ dk4xsp2d_calculate_value_derivative(aa, &xsp, 0.0, NULL); aa[1] = aa[1] / divisor; aa[3] = aa[3] / divisor; for (ssegno = (size_t)0U; ssegno < subsegs; ssegno++) { if ((subsegs - (size_t)1U) == ssegno) { t = 1.0; } else { t = ((double)(ssegno + (size_t)1U)) / ((double)subsegs); } dk4xsp2d_calculate_value_derivative(ab, &xsp, t, NULL); ab[1] = ab[1] / divisor; ab[3] = ab[3] / divisor; dk4bb_add_bezier( &(pobj->bb), aa[0], aa[2], (aa[0] + aa[1]), (aa[2] + aa[3]), (ab[0] - ab[1]), (ab[2] - ab[3]), ab[0], ab[2] ); DK4_MEMCPY(aa,ab,sizeof(aa)); } } } } $!trace-code wxdobj_report_bb(&(pobj->bb)); $? "- wxdobj_bb_simple_spline %d", (back ? 1 : 0) return back; } static bool wxdobj_bb_simple_arc(Wxd_object_t *pobj) { double a; double b; size_t i; int c; $? "+ wxdobj_bb_simple_arc" dk4bb_init(&(pobj->bb)); dk4bb_add_point( &(pobj->bb), (double)((pobj->det).a.x1), (double)((pobj->det).a.y1) ); dk4bb_add_point( &(pobj->bb), (double)((pobj->det).a.x2), (double)((pobj->det).a.y2) ); dk4bb_add_point( &(pobj->bb), (double)((pobj->det).a.x3), (double)((pobj->det).a.y3) ); if ((int8_t)0 != (pobj->det).a.d) { if ((pobj->det).a.a <= (pobj->det).a.b) { a = (pobj->det).a.a; b = (pobj->det).a.b; } else { a = (pobj->det).a.b; b = (pobj->det).a.a; } c = 0; for (i = (size_t)0U; i < sz_arc_angles; i++) { if (a <= arc_angles[i]) { if (arc_angles[i] <= b) { switch (c) { case 3 : { dk4bb_add_y( &(pobj->bb), ((pobj->det).a.y - (pobj->det).a.r) ); } break; case 2 : { dk4bb_add_x( &(pobj->bb), ((pobj->det).a.x - (pobj->det).a.r) ); } break; case 1 : { dk4bb_add_y( &(pobj->bb), ((pobj->det).a.y + (pobj->det).a.r) ); } break; default : { dk4bb_add_x( &(pobj->bb), ((pobj->det).a.x + (pobj->det).a.r) ); } break; } } } if (4 <= ++c) { c = 0; } } if (WXD_OT_C_ARC == pobj->ot) { dk4bb_add_point(&(pobj->bb), (pobj->det).a.x, (pobj->det).a.y); } } $!trace-code wxdobj_report_bb(&(pobj->bb)); $? "- wxdobj_bb_simple_arc" return true; } static bool wxdobj_bb_simple_circle(Wxd_object_t *pobj) { $? "+ wxdobj_bb_simple_circle" dk4bb_init(&(pobj->bb)); dk4bb_add_point( &(pobj->bb), ((double)((pobj->det).e.x) - (double)((pobj->det).e.rx)), ((double)((pobj->det).e.y) - (double)((pobj->det).e.rx)) ); dk4bb_add_point( &(pobj->bb), ((double)((pobj->det).e.x) + (double)((pobj->det).e.rx)), ((double)((pobj->det).e.y) + (double)((pobj->det).e.rx)) ); $!trace-code wxdobj_report_bb(&(pobj->bb)); $? "- wxdobj_bb_simple_circle" return true; } static bool wxdobj_bb_simple_ellipse(Wxd_object_t *pobj) { $? "+ wxdobj_bb_simple_ellipse" dk4bb_init(&(pobj->bb)); dk4bb_add_rotated_ellipse( &(pobj->bb), (double)((pobj->det).e.x), (double)((pobj->det).e.y), (double)((pobj->det).e.rx), (double)((pobj->det).e.ry), ((M_PI * ((double)((pobj->det).e.a))) / 180.0) ); $!trace-code wxdobj_report_bb(&(pobj->bb)); $? "- wxdobj_bb_simple_ellipse" return true; } static bool wxdobj_bb_simple_box(Wxd_object_t *pobj) { $? "+ wxdobj_bb_simple_box" dk4bb_init(&(pobj->bb)); dk4bb_add_point( &(pobj->bb), (double)((pobj->det).b.b.xl), (double)((pobj->det).b.b.yb) ); dk4bb_add_point( &(pobj->bb), (double)((pobj->det).b.b.xr), (double)((pobj->det).b.b.yt) ); $!trace-code wxdobj_report_bb(&(pobj->bb)); $? "- wxdobj_bb_simple_box" return true; } static bool wxdobj_bb_simple_image(Wxd_object_t *pobj) { $? "+ wxdobj_bb_simple_image" dk4bb_init(&(pobj->bb)); dk4bb_add_point( &(pobj->bb), (double)((pobj->det).i.br.xl), (double)((pobj->det).i.br.yb) ); dk4bb_add_point( &(pobj->bb), (double)((pobj->det).i.br.xr), (double)((pobj->det).i.br.yt) ); $!trace-code wxdobj_report_bb(&(pobj->bb)); $? "- wxdobj_bb_simple_image" return true; } static bool wxdobj_bb_simple_dot(Wxd_drawing_t const *pdrw, Wxd_object_t *pobj) { #if 1 double r; #endif $? "+ wxdobj_bb_simple_dot" dk4bb_init(&(pobj->bb)); #if 1 r = (((double)((pobj->det).d.d) * (double)(pdrw->baselw)) / 2.0); dk4bb_add_point( &(pobj->bb), ((double)((pobj->det).d.x) - r), ((double)((pobj->det).d.y) - r) ); dk4bb_add_point( &(pobj->bb), ((double)((pobj->det).d.x) + r), ((double)((pobj->det).d.y) + r) ); #else dk4bb_add_point(&(pobj->bb), (pobj->det).d.x, (pobj->det).d.y); #endif $!trace-code wxdobj_report_bb(&(pobj->bb)); $? "- wxdobj_bb_simple_dot" return true; } bool wxdobj_bb_simple_object( Wxd_drawing_t const *pdrw, Wxd_object_t *pobj ) { bool back = false; $? "+ wxdobj_bb_simple_object pdrw=%d pobj=%d", TR_IPTR(pdrw), TR_IPTR(pobj) if (NULL != pobj) { switch ( (int)(pobj->ot) ) { case WXD_OT_TEXT : { back = wxdobj_bb_simple_text(pobj); } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { back = wxdobj_bb_simple_polyline(pobj); } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { back = wxdobj_bb_simple_spline(pobj, pdrw->xsubs); } break; case WXD_OT_O_ARC : case WXD_OT_C_ARC : { back = wxdobj_bb_simple_arc(pobj); } break; case WXD_OT_CIRCLE : { back = wxdobj_bb_simple_circle(pobj); } break; case WXD_OT_ELLIPSE : { back = wxdobj_bb_simple_ellipse(pobj); } break; case WXD_OT_BOX : { back = wxdobj_bb_simple_box(pobj); } break; case WXD_OT_IMAGE : { back = wxdobj_bb_simple_image(pobj); } break; case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : { back = wxdobj_bb_simple_dot(pdrw, pobj); } break; } } $? "- wxdobj_bb_simple_object %d", (back ? 1 : 0) return back; } bool wxdobj_bb_group_structural( Wxd_drawing_t const *pdrw, Wxd_object_t *pobj ) { Wxd_object_t *po; bool back = false; $? "+ wxdobj_bb_group_structural" if (NULL != pobj) { dk4bb_init(&(pobj->bb)); } if ((NULL != pdrw) && (NULL != pobj)) { if (WXD_OT_GROUP_BEGIN == pobj->ot) { back = true; dk4sto_it_reset((pobj->det).g.i_e); do { po = (Wxd_object_t *)dk4sto_it_next((pobj->det).g.i_e); if (NULL != po) { $? ". yet another member" if (WXD_OT_GROUP_BEGIN == po->ot) { if (!wxdobj_bb_group_structural(pdrw, po)) { back = false; } } $!trace-code wxdobj_report_bb(&(po->bb)); dk4bb_add_bb(&(pobj->bb), &(po->bb)); } } while (NULL != po); } $!trace-code wxdobj_report_bb(&(pobj->bb)); } $? "- wxdobj_bb_group_structural %d", (back ? 1 : 0) return back; } bool wxdobj_bb_group_and_contents( Wxd_drawing_t const *pdrw, Wxd_object_t *pobj ) { Wxd_object_t *po; bool back = false; $? "+ wxdobj_bb_group_and_contents" if (NULL != pobj) { dk4bb_init(&(pobj->bb)); } if ((NULL != pdrw) && (NULL != pobj)) { if (WXD_OT_GROUP_BEGIN == pobj->ot) { back = true; dk4sto_it_reset((pobj->det).g.i_e); do { po = (Wxd_object_t *)dk4sto_it_next((pobj->det).g.i_e); if (NULL != po) { $? ". yet another member" if (WXD_OT_GROUP_BEGIN == po->ot) { if (!wxdobj_bb_group_and_contents(pdrw, po)) { back = false; } } else { if (!wxdobj_bb_simple_object(pdrw, po)) { back = false; } } $!trace-code wxdobj_report_bb(&(po->bb)); dk4bb_add_bb(&(pobj->bb), &(po->bb)); } } while (NULL != po); } $!trace-code wxdobj_report_bb(&(pobj->bb)); } $? "- wxdobj_bb_group_and_contents %d", (back ? 1 : 0) return back; } bool wxdobj_bb_modified_object( Wxd_drawing_t const *pdrw, Wxd_object_t *pobj ) { bool back = false; $? "+ wxdobj_bb_modified_object" if (NULL != pobj) { dk4bb_init(&(pobj->bb)); } if ((NULL != pdrw) && (NULL != pobj)) { if (WXD_OT_GROUP_BEGIN == pobj->ot) { /* If a group was modified (i.e. moved) rebuild bounding box information completely */ back = wxdobj_bb_group_and_contents(pdrw, pobj); } else { /* Rebuild bounding box information for simple object */ back = wxdobj_bb_simple_object(pdrw, pobj); if (NULL != pobj->pa) { /* If object is member of a group rebuild bounding box information in structural nodes */ while (NULL != pobj->pa) { pobj = pobj->pa; } if (!wxdobj_bb_group_structural(pdrw, pobj)) { back = false; } } } } $? "- wxdobj_bb_modified_object %d", (back ? 1 : 0) return back; } bool wxdobj_bb_for_drawing( Wxd_drawing_t *pdrw ) { Wxd_object_t *pobj; bool back = false; $? "+ wxdobj_bb_for_drawing pdrw=%d", TR_IPTR(pdrw) if (NULL != pdrw) { back = true; dk4sto_it_reset(pdrw->i_flat); do { pobj = (Wxd_object_t *)dk4sto_it_next(pdrw->i_flat); if (NULL != pobj) { $? ". yet another simple object" if (!wxdobj_bb_simple_object(pdrw, pobj)) { back = false; } } } while (NULL != pobj); dk4sto_it_reset(pdrw->i_stru); do { pobj = (Wxd_object_t *)dk4sto_it_next(pdrw->i_stru); if (NULL != pobj) { if (WXD_OT_GROUP_BEGIN == pobj->ot) { $? ". yet another group" if (!wxdobj_bb_group_structural(pdrw, pobj)) { back = false; } } } } while (NULL != pobj); } $? "- wxdobj_bb_for_drawing %d", (back ? 1 : 0) return back; } bool wxdobj_text_is_latex(Wxd_object_t const *pobj) { bool back = false; if (NULL != pobj) { if (WXD_OT_TEXT == pobj->ot) { if ( WXD_TEXT_FLAG_NONE != (WXD_TEXT_FLAG_LATEX & ((pobj->det).t.fl)) ) { back = true; } } } return back; } bool wxdobj_can_convert( int destot, const Wxd_object_t *pobj ) { bool back = false; $? "+ wxdobj_can_convert new=%d old=%d", destot, (int)(pobj->ot) if (NULL != pobj) { switch (destot) { case WXD_OT_POLYLINE : { switch ( (int)(pobj->ot) ) { case WXD_OT_BOX : case WXD_OT_POLYLINE : case WXD_OT_O_SPLINE : case WXD_OT_O_ARC : case WXD_OT_POLYGON : case WXD_OT_C_SPLINE : case WXD_OT_C_ARC : { back = true; } break; } } break; case WXD_OT_O_SPLINE : { switch ( (int)(pobj->ot) ) { case WXD_OT_BOX : case WXD_OT_POLYLINE : case WXD_OT_O_SPLINE : case WXD_OT_O_ARC : case WXD_OT_POLYGON : case WXD_OT_C_SPLINE : case WXD_OT_C_ARC : { back = true; } break; } } break; case WXD_OT_O_ARC : { switch ( (int)(pobj->ot) ) { case WXD_OT_C_ARC : case WXD_OT_O_ARC : { back = true; } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { if ((uint16_t)3U == (pobj->det).p.n) { back = true; } } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { if ((uint16_t)3U == (pobj->det).s.n) { back = true; } } break; } } break; case WXD_OT_POLYGON : { switch ( (int)(pobj->ot) ) { case WXD_OT_BOX : case WXD_OT_POLYLINE : case WXD_OT_O_SPLINE : case WXD_OT_O_ARC : case WXD_OT_POLYGON : case WXD_OT_C_SPLINE : case WXD_OT_C_ARC : { back = true; } break; } } break; case WXD_OT_C_SPLINE : { switch ( (int)(pobj->ot) ) { case WXD_OT_BOX : case WXD_OT_POLYLINE : case WXD_OT_O_SPLINE : case WXD_OT_O_ARC : case WXD_OT_POLYGON : case WXD_OT_C_SPLINE : case WXD_OT_C_ARC : { back = true; } break; } } break; case WXD_OT_C_ARC : { switch ( (int)(pobj->ot) ) { case WXD_OT_C_ARC : case WXD_OT_O_ARC : { back = true; } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { if ((uint16_t)3U == (pobj->det).p.n) { back = true; } } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { if ((uint16_t)3U == (pobj->det).s.n) { back = true; } } break; } } break; case WXD_OT_DOT_FILLED : { switch ( (int)(pobj->ot) ) { case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : case WXD_OT_CIRCLE : { back = true; } break; } } break; case WXD_OT_DOT_WHITE : { switch ( (int)(pobj->ot) ) { case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : case WXD_OT_CIRCLE : { back = true; } break; } } break; } } $? "- wxdobj_can_convert %d", (back ? 1 : 0) return back; } /** Rotate one point relatively to a center point by 90 degree. @param x Point x coordinate (in and out). @paam y Point y coordinate (in and out). @param x0 Center point x coordinate. @param y0 Center point y coordinate. @param neg Negative direction (false=positive direction). @param doit Really modify point (false=test only). @return True on success, false on error. */ static bool wxdobj_rotate_point( int32_t & x, int32_t & y, int32_t x0, int32_t y0, bool neg, bool doit ) { dk4_er_t er; int32_t dx; int32_t dy; int32_t nx; int32_t ny; bool back = false; if ((x == x0) && (y == y0)) { back = true; } else { dk4error_init(&er); dx = dk4ma_int32_t_sub(x, x0, &er); dy = dk4ma_int32_t_sub(y, y0, &er); if (neg) { nx = dk4ma_int32_t_add(x0, dy, &er); ny = dk4ma_int32_t_sub(y0, dx, &er); } else { nx = dk4ma_int32_t_sub(x0, dy, &er); ny = dk4ma_int32_t_add(y0, dx, &er); } if (DK4_E_NONE == er.ec) { back = true; if (doit) { x = nx; y = ny; } } } return back; } static bool wxdobj_rotate_text( Wxd_object_t *pobj, int32_t x0, int32_t y0, bool neg, bool doit ) { bool back; back = wxdobj_rotate_point( (pobj->det).t.x, (pobj->det).t.y, x0, y0, neg, doit ); if (doit) { if (neg) { (pobj->det).t.a -= (int16_t)90; if ((int16_t)0 > (pobj->det).t.a) { (pobj->det).t.a += (int16_t)360; } } else { (pobj->det).t.a += (int16_t)90; if ((int16_t)360 < (pobj->det).t.a) { (pobj->det).t.a -= (int16_t)360; } } } return back; } static bool wxdobj_rotate_polyline( Wxd_object_t *pobj, int32_t x0, int32_t y0, bool neg, bool doit ) { uint16_t i; bool back = false; bool res; if ((NULL != (pobj->det).p.p) && ((uint16_t)0U < (pobj->det).p.n)) { back = true; for (i = (uint16_t)0U; i < (pobj->det).p.n; i++) { res = wxdobj_rotate_point( ((pobj->det).p.p)[i].x,((pobj->det).p.p)[i].y,x0,y0,neg,doit ); if (!(res)) { back = false; } } } return back; } static bool wxdobj_rotate_spline( Wxd_object_t *pobj, int32_t x0, int32_t y0, bool neg, bool doit ) { uint16_t i; bool back = false; bool res; if ((NULL != (pobj->det).s.p) && ((uint16_t)0U < (pobj->det).s.n)) { back = true; for (i = (uint16_t)0U; i < (pobj->det).s.n; i++) { res = wxdobj_rotate_point( ((pobj->det).s.p)[i].x,((pobj->det).s.p)[i].y,x0,y0,neg,doit ); if (!(res)) { back = false; } } } return back; } static bool wxdobj_rotate_arc( Wxd_object_t *pobj, int32_t x0, int32_t y0, bool neg, bool doit ) { bool back = true; bool res; res = wxdobj_rotate_point((pobj->det).a.x1,(pobj->det).a.y1,x0,y0,neg,doit); if (!(res)) { back = false; } res = wxdobj_rotate_point((pobj->det).a.x2,(pobj->det).a.y2,x0,y0,neg,doit); if (!(res)) { back = false; } res = wxdobj_rotate_point((pobj->det).a.x3,(pobj->det).a.y3,x0,y0,neg,doit); if (!(res)) { back = false; } if (doit) { wxdarc_calculation( &((pobj->det).a.x), &((pobj->det).a.y), &((pobj->det).a.r), &((pobj->det).a.a), &((pobj->det).a.b), &((pobj->det).a.d), (pobj->det).a.x1, (pobj->det).a.y1, (pobj->det).a.x2, (pobj->det).a.y2, (pobj->det).a.x3, (pobj->det).a.y3 ); } return back; } static bool wxdobj_rotate_ellipse( Wxd_object_t *pobj, int32_t x0, int32_t y0, bool neg, bool doit ) { bool back = false; back = wxdobj_rotate_point( (pobj->det).e.x, (pobj->det).e.y, x0, y0, neg, doit ); if (doit && (WXD_OT_ELLIPSE == pobj->ot)) { if (neg) { (pobj->det).e.a -= (int16_t)90; if ((int16_t)0 > (pobj->det).e.a) { (pobj->det).e.a += (int16_t)360; } } else { (pobj->det).e.a += (int16_t)90; if ((int16_t)360 < (pobj->det).e.a) { (pobj->det).e.a -= (int16_t)360; } } } return back; } static bool wxdobj_rotate_bb( Wxd_bb_t *pbb, int32_t x0, int32_t y0, bool neg, bool doit ) { bool back = true; bool res; res = wxdobj_rotate_point(pbb->xl, pbb->yb, x0, y0, neg, doit); if (!(res)) { back = false; } res = wxdobj_rotate_point(pbb->xr, pbb->yt, x0, y0, neg, doit); if (!(res)) { back = false; } if (doit) { wxdobj_bb_correct(pbb); } return back; } static bool wxdobj_rotate_simple_object( Wxd_object_t *pobj, int32_t x0, int32_t y0, bool neg, bool doit ) { bool back = false; if (NULL != pobj) { switch ( (int)(pobj->ot) ) { case WXD_OT_TEXT : { back = wxdobj_rotate_text(pobj, x0, y0, neg, doit); } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { back = wxdobj_rotate_polyline(pobj, x0, y0, neg, doit); } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { back = wxdobj_rotate_spline(pobj, x0, y0, neg, doit); } break; case WXD_OT_O_ARC : case WXD_OT_C_ARC : { back = wxdobj_rotate_arc(pobj, x0, y0, neg, doit); } break; case WXD_OT_CIRCLE : case WXD_OT_ELLIPSE : { back = wxdobj_rotate_ellipse(pobj, x0, y0, neg, doit); } break; case WXD_OT_BOX : { back = wxdobj_rotate_bb(&((pobj->det).b.b), x0, y0, neg, doit); } break; case WXD_OT_IMAGE : { back = wxdobj_rotate_bb(&((pobj->det).i.br), x0, y0, neg, doit); if (doit) { wxdobj_image_placement(pobj); } } break; case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : { back = wxdobj_rotate_point( (pobj->det).d.x, (pobj->det).d.y, x0, y0, neg, doit ); } break; } } return back; } static bool wxdobj_rotate_structural_object( Wxd_object_t *pobj, int32_t x0, int32_t y0, bool neg, bool doit ) { Wxd_object_t *o; bool back = false; bool res; if (WXD_OT_GROUP_BEGIN == pobj->ot) { back = true; dk4sto_it_reset((pobj->det).g.i_e); do { o = (Wxd_object_t *)dk4sto_it_next((pobj->det).g.i_e); if (NULL != o) { switch ( (int)(o->ot) ) { case WXD_OT_GROUP_BEGIN : { res = wxdobj_rotate_structural_object( o, x0, y0, neg, doit ); } break; default : { res = wxdobj_rotate_simple_object( o, x0, y0, neg, doit ); } break; } if (!(res)) { back = false; } } } while (NULL != o); } return back; } bool wxdobj_rotate_object( Wxd_object_t *pobj, int32_t x0, int32_t y0, bool neg, bool doit ) { bool back = false; if (NULL != pobj) { switch ( (int)(pobj->ot) ) { case WXD_OT_GROUP_BEGIN : { back = wxdobj_rotate_structural_object( pobj, x0, y0, neg, doit ); } break; default : { back = wxdobj_rotate_simple_object( pobj, x0, y0, neg, doit ); } break; } } return back; } bool wxdobj_bb_equal(Wxd_bb_t const *pa, Wxd_bb_t const *pb) { bool back = false; $? "+ wxdobj_bb_equal" if ((NULL != pa) && (NULL != pb)) { $? ". pa = %ld %ld %ld %ld", (long)(pa->xl), (long)(pa->xr), (long)(pa->yb), (long)(pa->yt) $? ". pb = %ld %ld %ld %ld", (long)(pb->xl), (long)(pb->xr), (long)(pb->yb), (long)(pb->yt) if ( (pa->xl == pb->xl) && (pa->xr == pb->xr) && (pa->yb == pb->yb) && (pa->yt == pb->yt) ) { back = true; } } $? "- wxdobj_bb_equal %d", (back ? 1 : 0) return back; } /* vim: set ai sw=4 ts=4 : */