static GimpBezierDesc * gimp_vectors_real_make_bezier (const GimpVectors *vectors) { GimpStroke *stroke; GArray *cmd_array; GimpBezierDesc *ret_bezdesc = NULL; cmd_array = g_array_new (FALSE, FALSE, sizeof (cairo_path_data_t)); for (stroke = gimp_vectors_stroke_get_next (vectors, NULL); stroke; stroke = gimp_vectors_stroke_get_next (vectors, stroke)) { GimpBezierDesc *bezdesc = gimp_stroke_make_bezier (stroke); if (bezdesc) { cmd_array = g_array_append_vals (cmd_array, bezdesc->data, bezdesc->num_data); gimp_bezier_desc_free (bezdesc); } } if (cmd_array->len > 0) ret_bezdesc = gimp_bezier_desc_new ((cairo_path_data_t *) cmd_array->data, cmd_array->len); g_array_free (cmd_array, FALSE); return ret_bezdesc; }
void gimp_drawable_stroke_vectors (GimpDrawable *drawable, GimpStrokeOptions *options, GimpVectors *vectors) { GimpScanConvert *scan_convert; GimpStroke *stroke; gint num_coords = 0; g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); g_return_if_fail (GIMP_IS_STROKE_OPTIONS (options)); g_return_if_fail (GIMP_IS_VECTORS (vectors)); scan_convert = gimp_scan_convert_new (); /* For each Stroke in the vector, interpolate it, and add it to the * ScanConvert */ for (stroke = gimp_vectors_stroke_get_next (vectors, NULL); stroke; stroke = gimp_vectors_stroke_get_next (vectors, stroke)) { GArray *coords; gboolean closed; /* Get the interpolated version of this stroke, and add it to our * scanconvert. */ coords = gimp_stroke_interpolate (stroke, 0.2, &closed); if (coords && coords->len) { GimpVector2 *points = g_new0 (GimpVector2, coords->len); gint i; for (i = 0; i < coords->len; i++) { points[i].x = g_array_index (coords, GimpCoords, i).x; points[i].y = g_array_index (coords, GimpCoords, i).y; num_coords++; } gimp_scan_convert_add_polyline (scan_convert, coords->len, points, closed); g_free (points); } if (coords) g_array_free (coords, TRUE); } if (num_coords > 0) gimp_drawable_stroke_scan_convert (drawable, options, scan_convert); gimp_scan_convert_free (scan_convert); }
TempBuf * gimp_vectors_get_new_preview (GimpViewable *viewable, GimpContext *context, gint width, gint height) { GimpVectors *vectors; GimpItem *item; GimpStroke *cur_stroke; gdouble xscale, yscale; guchar *data; TempBuf *temp_buf; guchar white[1] = { 255 }; vectors = GIMP_VECTORS (viewable); item = GIMP_ITEM (viewable); xscale = ((gdouble) width) / gimp_image_get_width (item->image); yscale = ((gdouble) height) / gimp_image_get_height (item->image); temp_buf = temp_buf_new (width, height, 1, 0, 0, white); data = temp_buf_data (temp_buf); for (cur_stroke = gimp_vectors_stroke_get_next (vectors, NULL); cur_stroke; cur_stroke = gimp_vectors_stroke_get_next (vectors, cur_stroke)) { GArray *coords; gboolean closed; gint i; coords = gimp_stroke_interpolate (cur_stroke, 0.5, &closed); if (coords) { for (i = 0; i < coords->len; i++) { GimpCoords point; gint x, y; point = g_array_index (coords, GimpCoords, i); x = ROUND (point.x * xscale); y = ROUND (point.y * yscale); if (x >= 0 && y >= 0 && x < width && y < height) data[y * width + x] = 0; } g_array_free (coords, TRUE); } } return temp_buf; }
gboolean gimp_draw_tool_on_vectors_curve (GimpDrawTool *draw_tool, GimpDisplay *display, GimpVectors *vectors, const GimpCoords *coord, gint width, gint height, GimpCoords *ret_coords, gdouble *ret_pos, GimpAnchor **ret_segment_start, GimpAnchor **ret_segment_end, GimpStroke **ret_stroke) { GimpStroke *stroke = NULL; GimpAnchor *segment_start; GimpAnchor *segment_end; GimpCoords min_coords = GIMP_COORDS_DEFAULT_VALUES; GimpCoords cur_coords; gdouble min_dist, cur_dist, cur_pos; g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), FALSE); g_return_val_if_fail (GIMP_IS_DISPLAY (display), FALSE); g_return_val_if_fail (GIMP_IS_VECTORS (vectors), FALSE); g_return_val_if_fail (coord != NULL, FALSE); if (ret_coords) *ret_coords = *coord; if (ret_pos) *ret_pos = -1.0; if (ret_segment_start) *ret_segment_start = NULL; if (ret_segment_start) *ret_segment_end = NULL; if (ret_stroke) *ret_stroke = NULL; min_dist = -1.0; while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke))) { cur_dist = gimp_stroke_nearest_point_get (stroke, coord, 1.0, &cur_coords, &segment_start, &segment_end, &cur_pos); if (cur_dist >= 0 && (min_dist < 0 || cur_dist < min_dist)) { min_dist = cur_dist; min_coords = cur_coords; if (ret_coords) *ret_coords = cur_coords; if (ret_pos) *ret_pos = cur_pos; if (ret_segment_start) *ret_segment_start = segment_start; if (ret_segment_end) *ret_segment_end = segment_end; if (ret_stroke) *ret_stroke = stroke; } } if (min_dist >= 0 && gimp_draw_tool_on_handle (draw_tool, display, coord->x, coord->y, GIMP_HANDLE_CIRCLE, min_coords.x, min_coords.y, width, height, GIMP_HANDLE_ANCHOR_CENTER)) { return TRUE; } return FALSE; }
gboolean gimp_draw_tool_on_vectors_handle (GimpDrawTool *draw_tool, GimpDisplay *display, GimpVectors *vectors, const GimpCoords *coord, gint width, gint height, GimpAnchorType preferred, gboolean exclusive, GimpAnchor **ret_anchor, GimpStroke **ret_stroke) { GimpStroke *stroke = NULL; GimpStroke *pref_stroke = NULL; GimpAnchor *anchor = NULL; GimpAnchor *pref_anchor = NULL; gdouble dx, dy; gdouble pref_mindist = -1; gdouble mindist = -1; g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), FALSE); g_return_val_if_fail (GIMP_IS_DISPLAY (display), FALSE); g_return_val_if_fail (GIMP_IS_VECTORS (vectors), FALSE); g_return_val_if_fail (coord != NULL, FALSE); if (ret_anchor) *ret_anchor = NULL; if (ret_stroke) *ret_stroke = NULL; while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke))) { GList *anchor_list; GList *list; anchor_list = g_list_concat (gimp_stroke_get_draw_anchors (stroke), gimp_stroke_get_draw_controls (stroke)); for (list = anchor_list; list; list = g_list_next (list)) { dx = coord->x - GIMP_ANCHOR (list->data)->position.x; dy = coord->y - GIMP_ANCHOR (list->data)->position.y; if (mindist < 0 || mindist > dx * dx + dy * dy) { mindist = dx * dx + dy * dy; anchor = GIMP_ANCHOR (list->data); if (ret_stroke) *ret_stroke = stroke; } if ((pref_mindist < 0 || pref_mindist > dx * dx + dy * dy) && GIMP_ANCHOR (list->data)->type == preferred) { pref_mindist = dx * dx + dy * dy; pref_anchor = GIMP_ANCHOR (list->data); pref_stroke = stroke; } } g_list_free (anchor_list); } /* If the data passed into ret_anchor is a preferred anchor, return it. */ if (ret_anchor && *ret_anchor && gimp_draw_tool_on_handle (draw_tool, display, coord->x, coord->y, GIMP_HANDLE_CIRCLE, (*ret_anchor)->position.x, (*ret_anchor)->position.y, width, height, GIMP_HANDLE_ANCHOR_CENTER) && (*ret_anchor)->type == preferred) { if (ret_stroke) *ret_stroke = pref_stroke; return TRUE; } if (pref_anchor && gimp_draw_tool_on_handle (draw_tool, display, coord->x, coord->y, GIMP_HANDLE_CIRCLE, pref_anchor->position.x, pref_anchor->position.y, width, height, GIMP_HANDLE_ANCHOR_CENTER)) { if (ret_anchor) *ret_anchor = pref_anchor; if (ret_stroke) *ret_stroke = pref_stroke; return TRUE; } else if (!exclusive && anchor && gimp_draw_tool_on_handle (draw_tool, display, coord->x, coord->y, GIMP_HANDLE_CIRCLE, anchor->position.x, anchor->position.y, width, height, GIMP_HANDLE_ANCHOR_CENTER)) { if (ret_anchor) *ret_anchor = anchor; /* *ret_stroke already set correctly. */ return TRUE; } if (ret_anchor) *ret_anchor = NULL; if (ret_stroke) *ret_stroke = NULL; return FALSE; }
gboolean gimp_image_snap_rectangle (GimpImage *image, gdouble x1, gdouble y1, gdouble x2, gdouble y2, gdouble *tx1, gdouble *ty1, gdouble epsilon_x, gdouble epsilon_y, gboolean snap_to_guides, gboolean snap_to_grid, gboolean snap_to_canvas, gboolean snap_to_vectors) { gdouble nx, ny; gdouble mindist_x = G_MAXDOUBLE; gdouble mindist_y = G_MAXDOUBLE; gdouble x_center = (x1 + x2) / 2.0; gdouble y_center = (y1 + y2) / 2.0; gboolean snapped = FALSE; g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); g_return_val_if_fail (tx1 != NULL, FALSE); g_return_val_if_fail (ty1 != NULL, FALSE); *tx1 = x1; *ty1 = y1; if (! gimp_image_get_guides (image)) snap_to_guides = FALSE; if (! gimp_image_get_grid (image)) snap_to_grid = FALSE; if (! gimp_image_get_active_vectors (image)) snap_to_vectors = FALSE; if (! (snap_to_guides || snap_to_grid || snap_to_canvas || snap_to_vectors)) return FALSE; /* left edge */ if (gimp_image_snap_x (image, x1, &nx, MIN (epsilon_x, mindist_x), snap_to_guides, snap_to_grid, snap_to_canvas)) { mindist_x = ABS (nx - x1); *tx1 = nx; snapped = TRUE; } /* right edge */ if (gimp_image_snap_x (image, x2, &nx, MIN (epsilon_x, mindist_x), snap_to_guides, snap_to_grid, snap_to_canvas)) { mindist_x = ABS (nx - x2); *tx1 = RINT (x1 + (nx - x2)); snapped = TRUE; } /* center, vertical */ if (gimp_image_snap_x (image, x_center, &nx, MIN (epsilon_x, mindist_x), snap_to_guides, snap_to_grid, snap_to_canvas)) { mindist_x = ABS (nx - x_center); *tx1 = RINT (x1 + (nx - x_center)); snapped = TRUE; } /* top edge */ if (gimp_image_snap_y (image, y1, &ny, MIN (epsilon_y, mindist_y), snap_to_guides, snap_to_grid, snap_to_canvas)) { mindist_y = ABS (ny - y1); *ty1 = ny; snapped = TRUE; } /* bottom edge */ if (gimp_image_snap_y (image, y2, &ny, MIN (epsilon_y, mindist_y), snap_to_guides, snap_to_grid, snap_to_canvas)) { mindist_y = ABS (ny - y2); *ty1 = RINT (y1 + (ny - y2)); snapped = TRUE; } /* center, horizontal */ if (gimp_image_snap_y (image, y_center, &ny, MIN (epsilon_y, mindist_y), snap_to_guides, snap_to_grid, snap_to_canvas)) { mindist_y = ABS (ny - y_center); *ty1 = RINT (y1 + (ny - y_center)); snapped = TRUE; } if (snap_to_vectors) { GimpVectors *vectors = gimp_image_get_active_vectors (image); GimpStroke *stroke = NULL; GimpCoords coords1 = GIMP_COORDS_DEFAULT_VALUES; GimpCoords coords2 = GIMP_COORDS_DEFAULT_VALUES; while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke))) { GimpCoords nearest; gdouble dist; /* top edge */ coords1.x = x1; coords1.y = y1; coords2.x = x2; coords2.y = y1; if (gimp_stroke_nearest_tangent_get (stroke, &coords1, &coords2, 1.0, &nearest, NULL, NULL, NULL) >= 0) { snapped |= gimp_image_snap_distance (y1, nearest.y, epsilon_y, &mindist_y, ty1); } if (gimp_stroke_nearest_intersection_get (stroke, &coords1, &coords2, 1.0, &nearest, NULL, NULL, NULL) >= 0) { snapped |= gimp_image_snap_distance (x1, nearest.x, epsilon_x, &mindist_x, tx1); } if (gimp_stroke_nearest_intersection_get (stroke, &coords2, &coords1, 1.0, &nearest, NULL, NULL, NULL) >= 0) { dist = ABS (nearest.x - x2); if (dist < MIN (epsilon_x, mindist_x)) { mindist_x = dist; *tx1 = RINT (x1 + (nearest.x - x2)); snapped = TRUE; } } /* bottom edge */ coords1.x = x1; coords1.y = y2; coords2.x = x2; coords2.y = y2; if (gimp_stroke_nearest_tangent_get (stroke, &coords1, &coords2, 1.0, &nearest, NULL, NULL, NULL) >= 0) { dist = ABS (nearest.y - y2); if (dist < MIN (epsilon_y, mindist_y)) { mindist_y = dist; *ty1 = RINT (y1 + (nearest.y - y2)); snapped = TRUE; } } if (gimp_stroke_nearest_intersection_get (stroke, &coords1, &coords2, 1.0, &nearest, NULL, NULL, NULL) >= 0) { snapped |= gimp_image_snap_distance (x1, nearest.x, epsilon_x, &mindist_x, tx1); } if (gimp_stroke_nearest_intersection_get (stroke, &coords2, &coords1, 1.0, &nearest, NULL, NULL, NULL) >= 0) { dist = ABS (nearest.x - x2); if (dist < MIN (epsilon_x, mindist_x)) { mindist_x = dist; *tx1 = RINT (x1 + (nearest.x - x2)); snapped = TRUE; } } /* left edge */ coords1.x = x1; coords1.y = y1; coords2.x = x1; coords2.y = y2; if (gimp_stroke_nearest_tangent_get (stroke, &coords1, &coords2, 1.0, &nearest, NULL, NULL, NULL) >= 0) { snapped |= gimp_image_snap_distance (x1, nearest.x, epsilon_x, &mindist_x, tx1); } if (gimp_stroke_nearest_intersection_get (stroke, &coords1, &coords2, 1.0, &nearest, NULL, NULL, NULL) >= 0) { snapped |= gimp_image_snap_distance (y1, nearest.y, epsilon_y, &mindist_y, ty1); } if (gimp_stroke_nearest_intersection_get (stroke, &coords2, &coords1, 1.0, &nearest, NULL, NULL, NULL) >= 0) { dist = ABS (nearest.y - y2); if (dist < MIN (epsilon_y, mindist_y)) { mindist_y = dist; *ty1 = RINT (y1 + (nearest.y - y2)); snapped = TRUE; } } /* right edge */ coords1.x = x2; coords1.y = y1; coords2.x = x2; coords2.y = y2; if (gimp_stroke_nearest_tangent_get (stroke, &coords1, &coords2, 1.0, &nearest, NULL, NULL, NULL) >= 0) { dist = ABS (nearest.x - x2); if (dist < MIN (epsilon_x, mindist_x)) { mindist_x = dist; *tx1 = RINT (x1 + (nearest.x - x2)); snapped = TRUE; } } if (gimp_stroke_nearest_intersection_get (stroke, &coords1, &coords2, 1.0, &nearest, NULL, NULL, NULL) >= 0) { snapped |= gimp_image_snap_distance (y1, nearest.y, epsilon_y, &mindist_y, ty1); } if (gimp_stroke_nearest_intersection_get (stroke, &coords2, &coords1, 1.0, &nearest, NULL, NULL, NULL) >= 0) { dist = ABS (nearest.y - y2); if (dist < MIN (epsilon_y, mindist_y)) { mindist_y = dist; *ty1 = RINT (y1 + (nearest.y - y2)); snapped = TRUE; } } /* center */ coords1.x = x_center; coords1.y = y_center; if (gimp_stroke_nearest_point_get (stroke, &coords1, 1.0, &nearest, NULL, NULL, NULL) >= 0) { if (gimp_image_snap_distance (x_center, nearest.x, epsilon_x, &mindist_x, &nx)) { mindist_x = ABS (nx - x_center); *tx1 = RINT (x1 + (nx - x_center)); snapped = TRUE; } if (gimp_image_snap_distance (y_center, nearest.y, epsilon_y, &mindist_y, &ny)) { mindist_y = ABS (ny - y_center); *ty1 = RINT (y1 + (ny - y_center)); snapped = TRUE; } } } } return snapped; }
gboolean gimp_image_snap_point (GimpImage *image, gdouble x, gdouble y, gdouble *tx, gdouble *ty, gdouble epsilon_x, gdouble epsilon_y, gboolean snap_to_guides, gboolean snap_to_grid, gboolean snap_to_canvas, gboolean snap_to_vectors) { gdouble mindist_x = G_MAXDOUBLE; gdouble mindist_y = G_MAXDOUBLE; gboolean snapped = FALSE; g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); g_return_val_if_fail (tx != NULL, FALSE); g_return_val_if_fail (ty != NULL, FALSE); *tx = x; *ty = y; if (! gimp_image_get_guides (image)) snap_to_guides = FALSE; if (! gimp_image_get_grid (image)) snap_to_grid = FALSE; if (! gimp_image_get_active_vectors (image)) snap_to_vectors = FALSE; if (! (snap_to_guides || snap_to_grid || snap_to_canvas || snap_to_vectors)) return FALSE; if (x < -epsilon_x || x >= (gimp_image_get_width (image) + epsilon_x) || y < -epsilon_y || y >= (gimp_image_get_height (image) + epsilon_y)) { return FALSE; } if (snap_to_guides) { GList *list; for (list = gimp_image_get_guides (image); list; list = g_list_next (list)) { GimpGuide *guide = list->data; gint position = gimp_guide_get_position (guide); switch (gimp_guide_get_orientation (guide)) { case GIMP_ORIENTATION_HORIZONTAL: snapped |= gimp_image_snap_distance (y, position, epsilon_y, &mindist_y, ty); break; case GIMP_ORIENTATION_VERTICAL: snapped |= gimp_image_snap_distance (x, position, epsilon_x, &mindist_x, tx); break; default: break; } } } if (snap_to_grid) { GimpGrid *grid = gimp_image_get_grid (image); gdouble xspacing, yspacing; gdouble xoffset, yoffset; gdouble i; gimp_grid_get_spacing (grid, &xspacing, &yspacing); gimp_grid_get_offset (grid, &xoffset, &yoffset); while (xoffset > xspacing) xoffset -= xspacing; while (yoffset > yspacing) yoffset -= yspacing; for (i = xoffset; i <= gimp_image_get_width (image); i += xspacing) { if (i < 0) continue; snapped |= gimp_image_snap_distance (x, i, epsilon_x, &mindist_x, tx); } for (i = yoffset; i <= gimp_image_get_height (image); i += yspacing) { if (i < 0) continue; snapped |= gimp_image_snap_distance (y, i, epsilon_y, &mindist_y, ty); } } if (snap_to_canvas) { snapped |= gimp_image_snap_distance (x, 0, epsilon_x, &mindist_x, tx); snapped |= gimp_image_snap_distance (x, gimp_image_get_width (image), epsilon_x, &mindist_x, tx); snapped |= gimp_image_snap_distance (y, 0, epsilon_y, &mindist_y, ty); snapped |= gimp_image_snap_distance (y, gimp_image_get_height (image), epsilon_y, &mindist_y, ty); } if (snap_to_vectors) { GimpVectors *vectors = gimp_image_get_active_vectors (image); GimpStroke *stroke = NULL; GimpCoords coords = { 0, 0, 0, 0, 0 }; coords.x = x; coords.y = y; while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke))) { GimpCoords nearest; if (gimp_stroke_nearest_point_get (stroke, &coords, 1.0, &nearest, NULL, NULL, NULL) >= 0) { snapped |= gimp_image_snap_distance (x, nearest.x, epsilon_x, &mindist_x, tx); snapped |= gimp_image_snap_distance (y, nearest.y, epsilon_y, &mindist_y, ty); } } } return snapped; }
gboolean gimp_image_snap_point (GimpImage *image, gdouble x, gdouble y, gdouble *tx, gdouble *ty, gdouble epsilon_x, gdouble epsilon_y, gboolean snap_to_guides, gboolean snap_to_grid, gboolean snap_to_canvas, gboolean snap_to_vectors) { gdouble mindist_x = G_MAXDOUBLE; gdouble mindist_y = G_MAXDOUBLE; gdouble dist; gboolean snapped = FALSE; g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); g_return_val_if_fail (tx != NULL, FALSE); g_return_val_if_fail (ty != NULL, FALSE); *tx = x; *ty = y; if (! gimp_image_get_guides (image)) snap_to_guides = FALSE; if (! gimp_image_get_grid (image)) snap_to_grid = FALSE; if (! gimp_image_get_active_vectors (image)) snap_to_vectors = FALSE; if (! (snap_to_guides || snap_to_grid || snap_to_canvas || snap_to_vectors)) return FALSE; if (x < -epsilon_x || x >= (gimp_image_get_width (image) + epsilon_x) || y < -epsilon_y || y >= (gimp_image_get_height (image) + epsilon_y)) { return FALSE; } if (snap_to_guides) { GList *list; for (list = gimp_image_get_guides (image); list; list = g_list_next (list)) { GimpGuide *guide = list->data; gint position = gimp_guide_get_position (guide); if (position < 0) continue; switch (gimp_guide_get_orientation (guide)) { case GIMP_ORIENTATION_HORIZONTAL: dist = ABS (position - y); if (dist < MIN (epsilon_y, mindist_y)) { mindist_y = dist; *ty = position; snapped = TRUE; } break; case GIMP_ORIENTATION_VERTICAL: dist = ABS (position - x); if (dist < MIN (epsilon_x, mindist_x)) { mindist_x = dist; *tx = position; snapped = TRUE; } break; default: break; } } } if (snap_to_grid) { GimpGrid *grid = gimp_image_get_grid (image); gdouble xspacing, yspacing; gdouble xoffset, yoffset; gdouble i; g_object_get (grid, "xspacing", &xspacing, "yspacing", &yspacing, "xoffset", &xoffset, "yoffset", &yoffset, NULL); while (xoffset > xspacing) xoffset -= xspacing; while (yoffset > yspacing) yoffset -= yspacing; for (i = xoffset; i <= gimp_image_get_width (image); i += xspacing) { if (i < 0) continue; dist = ABS (i - x); if (dist < MIN (epsilon_x, mindist_x)) { mindist_x = dist; *tx = i; snapped = TRUE; } } for (i = yoffset; i <= gimp_image_get_height (image); i += yspacing) { if (i < 0) continue; dist = ABS (i - y); if (dist < MIN (epsilon_y, mindist_y)) { mindist_y = dist; *ty = i; snapped = TRUE; } } } if (snap_to_canvas) { dist = ABS (x); if (dist < MIN (epsilon_x, mindist_x)) { mindist_x = dist; *tx = 0; snapped = TRUE; } dist = ABS (gimp_image_get_width (image) - x); if (dist < MIN (epsilon_x, mindist_x)) { mindist_x = dist; *tx = gimp_image_get_width (image); snapped = TRUE; } dist = ABS (y); if (dist < MIN (epsilon_y, mindist_y)) { mindist_y = dist; *ty = 0; snapped = TRUE; } dist = ABS (gimp_image_get_height (image) - y); if (dist < MIN (epsilon_y, mindist_y)) { mindist_y = dist; *ty = gimp_image_get_height (image); snapped = TRUE; } } if (snap_to_vectors) { GimpVectors *vectors = gimp_image_get_active_vectors (image); GimpStroke *stroke = NULL; GimpCoords coords = { 0, 0, 0, 0, 0 }; coords.x = x; coords.y = y; while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke))) { GimpCoords nearest; if (gimp_stroke_nearest_point_get (stroke, &coords, 1.0, &nearest, NULL, NULL, NULL) >= 0) { dist = ABS (nearest.x - x); if (dist < MIN (epsilon_x, mindist_x)) { mindist_x = dist; *tx = nearest.x; snapped = TRUE; } dist = ABS (nearest.y - y); if (dist < MIN (epsilon_y, mindist_y)) { mindist_y = dist; *ty = nearest.y; snapped = TRUE; } } } } return snapped; }
static gboolean gimp_vectors_bounds (GimpItem *item, gdouble *x, gdouble *y, gdouble *width, gdouble *height) { GimpVectors *vectors = GIMP_VECTORS (item); if (! vectors->bounds_valid) { GimpStroke *stroke; vectors->bounds_empty = TRUE; vectors->bounds_x1 = vectors->bounds_x2 = 0.0; vectors->bounds_y1 = vectors->bounds_y2 = 0.0; for (stroke = gimp_vectors_stroke_get_next (vectors, NULL); stroke; stroke = gimp_vectors_stroke_get_next (vectors, stroke)) { GArray *stroke_coords; gboolean closed; stroke_coords = gimp_stroke_interpolate (stroke, 1.0, &closed); if (stroke_coords) { GimpCoords point; gint i; if (vectors->bounds_empty && stroke_coords->len > 0) { point = g_array_index (stroke_coords, GimpCoords, 0); vectors->bounds_x1 = vectors->bounds_x2 = point.x; vectors->bounds_y1 = vectors->bounds_y2 = point.y; vectors->bounds_empty = FALSE; } for (i = 0; i < stroke_coords->len; i++) { point = g_array_index (stroke_coords, GimpCoords, i); vectors->bounds_x1 = MIN (vectors->bounds_x1, point.x); vectors->bounds_y1 = MIN (vectors->bounds_y1, point.y); vectors->bounds_x2 = MAX (vectors->bounds_x2, point.x); vectors->bounds_y2 = MAX (vectors->bounds_y2, point.y); } g_array_free (stroke_coords, TRUE); } } vectors->bounds_valid = TRUE; } *x = vectors->bounds_x1; *y = vectors->bounds_y1; *width = vectors->bounds_x2 - vectors->bounds_x1; *height = vectors->bounds_y2 - vectors->bounds_y1; return ! vectors->bounds_empty; }