/* GIMP - The GNU Image Manipulation Program * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * gimpvectors-compat.c * Copyright (C) 2003 Michael Natterer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include #include #include "vectors-types.h" #include "core/gimpimage.h" #include "gimpanchor.h" #include "gimpbezierstroke.h" #include "gimpvectors.h" #include "gimpvectors-compat.h" enum { GIMP_VECTORS_COMPAT_ANCHOR = 1, GIMP_VECTORS_COMPAT_CONTROL = 2, GIMP_VECTORS_COMPAT_NEW_STROKE = 3 }; static const GimpCoords default_coords = GIMP_COORDS_DEFAULT_VALUES; GimpVectors * gimp_vectors_compat_new (GimpImage *image, const gchar *name, GimpVectorsCompatPoint *points, gint n_points, gboolean closed) { GimpVectors *vectors; GimpStroke *stroke; GimpCoords *coords; GimpCoords *curr_stroke; GimpCoords *curr_coord; gint i; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (name != NULL, NULL); g_return_val_if_fail (points != NULL || n_points == 0, NULL); g_return_val_if_fail (n_points >= 0, NULL); vectors = gimp_vectors_new (image, name); coords = g_new0 (GimpCoords, n_points + 1); curr_stroke = curr_coord = coords; /* skip the first control point, will set it later */ curr_coord++; for (i = 0; i < n_points; i++) { *curr_coord = default_coords; curr_coord->x = points[i].x; curr_coord->y = points[i].y; /* copy the first anchor to be the first control point */ if (curr_coord == curr_stroke + 1) *curr_stroke = *curr_coord; /* found new stroke start */ if (points[i].type == GIMP_VECTORS_COMPAT_NEW_STROKE) { /* copy the last control point to the beginning of the stroke */ *curr_stroke = *(curr_coord - 1); stroke = gimp_bezier_stroke_new_from_coords (curr_stroke, curr_coord - curr_stroke - 1, TRUE); gimp_vectors_stroke_add (vectors, stroke); g_object_unref (stroke); /* start a new stroke */ curr_stroke = curr_coord - 1; /* copy the first anchor to be the first control point */ *curr_stroke = *curr_coord; } curr_coord++; } if (closed) { /* copy the last control point to the beginning of the stroke */ curr_coord--; *curr_stroke = *curr_coord; } stroke = gimp_bezier_stroke_new_from_coords (curr_stroke, curr_coord - curr_stroke, closed); gimp_vectors_stroke_add (vectors, stroke); g_object_unref (stroke); g_free (coords); return vectors; } gboolean gimp_vectors_compat_is_compatible (GimpImage *image) { GList *list; g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); for (list = gimp_image_get_vectors_iter (image); list; list = g_list_next (list)) { GimpVectors *vectors = GIMP_VECTORS (list->data); GList *strokes; gint open_count = 0; if (gimp_item_get_visible (GIMP_ITEM (vectors))) return FALSE; for (strokes = vectors->strokes->head; strokes; strokes = g_list_next (strokes)) { GimpStroke *stroke = GIMP_STROKE (strokes->data); if (! GIMP_IS_BEZIER_STROKE (stroke)) return FALSE; if (!stroke->closed) open_count++; } if (open_count >= 2) return FALSE; } return TRUE; } GimpVectorsCompatPoint * gimp_vectors_compat_get_points (GimpVectors *vectors, gint32 *n_points, gint32 *closed) { GimpVectorsCompatPoint *points; GList *strokes; gint i; GList *postponed = NULL; /* for the one open stroke... */ gint open_count; gboolean first_stroke = TRUE; g_return_val_if_fail (GIMP_IS_VECTORS (vectors), NULL); g_return_val_if_fail (n_points != NULL, NULL); g_return_val_if_fail (closed != NULL, NULL); *n_points = 0; *closed = TRUE; open_count = 0; for (strokes = vectors->strokes->head; strokes; strokes = g_list_next (strokes)) { GimpStroke *stroke = strokes->data; gint n_anchors; if (! stroke->closed) { open_count++; postponed = strokes; *closed = FALSE; if (open_count >= 2) { g_warning ("gimp_vectors_compat_get_points(): convert failed"); *n_points = 0; return NULL; } } n_anchors = g_queue_get_length (stroke->anchors); if (! stroke->closed) n_anchors--; *n_points += n_anchors; } points = g_new0 (GimpVectorsCompatPoint, *n_points); i = 0; for (strokes = vectors->strokes->head; strokes || postponed; strokes = g_list_next (strokes)) { GimpStroke *stroke; GList *anchors; if (strokes) { if (postponed && strokes == postponed) /* we need to visit the open stroke last... */ continue; else stroke = GIMP_STROKE (strokes->data); } else { stroke = GIMP_STROKE (postponed->data); postponed = NULL; } for (anchors = stroke->anchors->head; anchors; anchors = g_list_next (anchors)) { GimpAnchor *anchor = anchors->data; /* skip the first anchor, will add it at the end if needed */ if (! anchors->prev) continue; switch (anchor->type) { case GIMP_ANCHOR_ANCHOR: if (anchors->prev == stroke->anchors->head && ! first_stroke) points[i].type = GIMP_VECTORS_COMPAT_NEW_STROKE; else points[i].type = GIMP_VECTORS_COMPAT_ANCHOR; break; case GIMP_ANCHOR_CONTROL: points[i].type = GIMP_VECTORS_COMPAT_CONTROL; break; } points[i].x = anchor->position.x; points[i].y = anchor->position.y; i++; /* write the skipped control point */ if (! anchors->next && stroke->closed) { anchor = g_queue_peek_head (stroke->anchors); points[i].type = GIMP_VECTORS_COMPAT_CONTROL; points[i].x = anchor->position.x; points[i].y = anchor->position.y; i++; } } first_stroke = FALSE; } return points; }