/*! * \brief Convert _StdPath to one or more _BezierLine/BezierGon */ static ObjectChange * _convert_to_beziers_callback (DiaObject *obj, Point *clicked, gpointer data) { StdPath *stdpath = (StdPath *)obj; BezPoint *bezier = stdpath->points; GList *list = NULL; int i, n = 0; ObjectChange *change; for (i = 1; i < stdpath->num_points; ++i) { if (bezier[i].type == BEZ_MOVE_TO || i+1 == stdpath->num_points) { DiaObject *rep; int num = bezier[i].type == BEZ_MOVE_TO ? i - n : i - n + 1; if (stdpath->stroke_or_fill & PDO_FILL) rep = create_standard_beziergon (num, &bezier[n]); else rep = create_standard_bezierline (num, &bezier[n], NULL, NULL); if (!rep) /* no Standard objects? */ break; list = g_list_append (list, rep); n = i; } } if (!list) { change = change_list_create (); } else if (g_list_length (list) == 1) { change = object_substitute (obj, (DiaObject *)list->data); g_list_free (list); } else { change = object_substitute (obj, create_standard_group (list)); } return change; }
/*! * \brief Upgrade the _Zigzagline to a _Bezierline * * Accessible through the object's context menu this function substitutes * the _Zigzagline with a _Bezierline. The function creates a favorable * representation of the original _OrthConn data of the given object. * * @param obj explicit this pointer * @param clicked last clicked point on the canvas or NULL * @param data a pointer to extra data, unused here * @return undo/redo information as _ObjectChange * * \memberof _Zigzagline */ static ObjectChange * _convert_to_bezierline_callback (DiaObject *obj, Point *clicked, gpointer data) { DiaObject *poly; Zigzagline *zigzagline = (Zigzagline *)obj; OrthConn *orth = &zigzagline->orth; BezPoint *bp; int i, j, num_points; DiaObject *bezier; num_points = (orth->numpoints + 1) / 2; bp = g_new(BezPoint, num_points); bp[0].type = BEZ_MOVE_TO; bp[0].p1 = orth->points[0]; for (i = 1, j = 1; i < num_points && j < orth->numpoints; ++i) { bp[i].type = BEZ_CURVE_TO; bp[i].p1 = orth->points[j++]; bp[i].p2 = orth->points[j++]; if (j + 2 < orth->numpoints) { /* if we have more than two points left, use the middle of the segment */ Point p = { (orth->points[j-1].x + orth->points[j].x) / 2.0, (orth->points[j-1].y + orth->points[j].y) / 2.0 }; bp[i].p3 = p; } else if (j + 2 == orth->numpoints) { /* if we one extra point left, use the middle of two segments */ Point p1 = { (orth->points[j-2].x + orth->points[j-1].x) / 2.0, (orth->points[j-2].y + orth->points[j-1].y) / 2.0 }; Point p2 = { (orth->points[j-1].x + orth->points[j].x) / 2.0, (orth->points[j-1].y + orth->points[j].y) / 2.0 }; Point p = { (p1.x + p2.x) / 2.0, (p1.y + p2.y) / 2.0 }; bp[i].p3 = p; /* also adapt the previous control point */ bp[i].p2 = p1; /* and do the final bezpoint */ bp[i+1].type = BEZ_CURVE_TO; bp[i+1].p1 = p2; bp[i+1].p2 = orth->points[j]; bp[i+1].p3 = orth->points[j+1]; break; } else { bp[i].p3 = orth->points[j++]; } } bezier = create_standard_bezierline(num_points, bp, &zigzagline->end_arrow, &zigzagline->start_arrow); g_free(bp); return object_substitute (obj, bezier); }
/*! * \brief create a _Bezierline or _StdPath from the graphics state */ void DiaOutputDev::stroke (GfxState *state) { GArray *points = g_array_new (FALSE, FALSE, sizeof(BezPoint)); DiaObject *obj = NULL; GfxPath *path = state->getPath(); bool haveClose = false; if (doPath (points, state, path, haveClose) && points->len > 1) { if (path->getNumSubpaths() == 1) { if (!haveClose) obj = create_standard_bezierline (points->len, &g_array_index (points, BezPoint, 0), NULL, NULL); else obj = create_standard_beziergon (points->len, &g_array_index (points, BezPoint, 0)); } else { obj = create_standard_path (points->len, &g_array_index (points, BezPoint, 0)); } applyStyle (obj, false); } g_array_free (points, TRUE); if (obj) addObject (obj); }
static DiaObject * fig_read_spline(FILE *file, DiaContext *ctx) { int sub_type; int line_style; int thickness; int pen_color; int fill_color; int depth; int pen_style; int area_fill; real style_val; int cap_style; int forward_arrow, backward_arrow; Arrow *forward_arrow_info = NULL, *backward_arrow_info = NULL; int npoints; Point *points = NULL; GPtrArray *props = g_ptr_array_new(); DiaObject *newobj = NULL; BezPoint *bezpoints; int i; char* old_locale; old_locale = setlocale(LC_NUMERIC, "C"); if (fscanf(file, "%d %d %d %d %d %d %d %d %lf %d %d %d %d\n", &sub_type, &line_style, &thickness, &pen_color, &fill_color, &depth, &pen_style, &area_fill, &style_val, &cap_style, &forward_arrow, &backward_arrow, &npoints) != 13) { dia_context_add_message_with_errno(ctx, errno, _("Couldn't read spline info.")); goto exit; } if (forward_arrow == 1) { forward_arrow_info = fig_read_arrow(file, ctx); } if (backward_arrow == 1) { backward_arrow_info = fig_read_arrow(file, ctx); } if (!fig_read_n_points(file, npoints, &points, ctx)) { goto exit; } switch (sub_type) { case 0: /* Open approximated spline */ case 1: /* Closed approximated spline */ dia_context_add_message(ctx, _("Cannot convert approximated spline yet.")); goto exit; case 2: /* Open interpolated spline */ case 3: /* Closed interpolated spline */ /* Despite what the Fig description says, interpolated splines now also have the line with spline info from the X-spline */ case 4: /* Open X-spline */ case 5: /* Closed X-spline */ { double f; gboolean interpolated = TRUE; for (i = 0; i < npoints; i++) { if (fscanf(file, " %lf ", &f) != 1) { dia_context_add_message_with_errno(ctx, errno,_("Couldn't read spline info.")); goto exit; } if (f != -1.0 && f != 0.0) { dia_context_add_message(ctx, _("Cannot convert approximated spline yet.")); interpolated = FALSE; } } if (!interpolated) goto exit; /* Matrix-based conversion not ready yet. */ #if 0 if (sub_type%2 == 0) { bezpoints = fig_transform_spline(npoints, points, FALSE, f); newobj = create_standard_bezierline(npoints, bezpoints, forward_arrow_info, backward_arrow_info); } else { points = g_renew(Point, points, npoints+1); points[npoints] = points[0]; npoints++; bezpoints = fig_transform_spline(npoints, points, TRUE, f); newobj = create_standard_beziergon(npoints, bezpoints); } #else if (sub_type%2 == 0) { bezpoints = transform_spline(npoints, points, FALSE); newobj = create_standard_bezierline(npoints, bezpoints, forward_arrow_info, backward_arrow_info); } else { points = g_renew(Point, points, npoints+1); points[npoints] = points[0]; npoints++; bezpoints = transform_spline(npoints, points, TRUE); newobj = create_standard_beziergon(npoints, bezpoints); } #endif } if (newobj == NULL) goto exit; break; default: dia_context_add_message(ctx, _("Unknown spline subtype: %d\n"), sub_type); goto exit; } fig_simple_properties(newobj, line_style, style_val, thickness, pen_color, fill_color, area_fill, ctx); /* Pen style field (not used) */ /* Style_val (size of dots and dashes) in 1/80 inch*/ /* Cap style */ /* Depth field */ add_at_depth(newobj, depth, ctx); exit: setlocale(LC_NUMERIC, old_locale); prop_list_free(props); g_free(forward_arrow_info); g_free(backward_arrow_info); g_free(points); return newobj; }