diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:23:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:23:22 +0000 |
commit | e42129241681dde7adae7d20697e7b421682fbb4 (patch) | |
tree | af1fe815a5e639e68e59fabd8395ec69458b3e5e /app/core/gimpbezierdesc.c | |
parent | Initial commit. (diff) | |
download | gimp-ea37a4141e911d96afe705183d5bf292fb1941af.tar.xz gimp-ea37a4141e911d96afe705183d5bf292fb1941af.zip |
Adding upstream version 2.10.22.upstream/2.10.22upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'app/core/gimpbezierdesc.c')
-rw-r--r-- | app/core/gimpbezierdesc.c | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/app/core/gimpbezierdesc.c b/app/core/gimpbezierdesc.c new file mode 100644 index 0000000..6047544 --- /dev/null +++ b/app/core/gimpbezierdesc.c @@ -0,0 +1,202 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpbezierdesc.c + * Copyright (C) 2010 Michael Natterer <mitch@gimp.org> + * + * 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 <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <gegl.h> +#include <cairo.h> + +#include "core-types.h" + +#include "gimpbezierdesc.h" +#include "gimpboundary.h" + + +GType +gimp_bezier_desc_get_type (void) +{ + static GType type = 0; + + if (! type) + type = g_boxed_type_register_static ("GimpBezierDesc", + (GBoxedCopyFunc) gimp_bezier_desc_copy, + (GBoxedFreeFunc) gimp_bezier_desc_free); + + return type; +} + +GimpBezierDesc * +gimp_bezier_desc_new (cairo_path_data_t *data, + gint n_data) +{ + GimpBezierDesc *desc; + + g_return_val_if_fail (n_data == 0 || data != NULL, NULL); + + desc = g_slice_new (GimpBezierDesc); + + desc->status = CAIRO_STATUS_SUCCESS; + desc->num_data = n_data; + desc->data = data; + + return desc; +} + +static void +add_polyline (GArray *path_data, + const GimpVector2 *points, + gint n_points, + gboolean closed) +{ + GimpVector2 prev = { 0.0, 0.0, }; + cairo_path_data_t pd; + gint i; + + for (i = 0; i < n_points; i++) + { + /* compress multiple identical coordinates */ + if (i == 0 || + prev.x != points[i].x || + prev.y != points[i].y) + { + pd.header.type = (i == 0) ? CAIRO_PATH_MOVE_TO : CAIRO_PATH_LINE_TO; + pd.header.length = 2; + + g_array_append_val (path_data, pd); + + pd.point.x = points[i].x; + pd.point.y = points[i].y; + + g_array_append_val (path_data, pd); + + prev = points[i]; + } + } + + /* close the polyline when needed */ + if (closed) + { + pd.header.type = CAIRO_PATH_CLOSE_PATH; + pd.header.length = 1; + + g_array_append_val (path_data, pd); + } +} + +GimpBezierDesc * +gimp_bezier_desc_new_from_bound_segs (GimpBoundSeg *bound_segs, + gint n_bound_segs, + gint n_bound_groups) +{ + GArray *path_data; + GimpVector2 *points; + gint n_points; + gint seg; + gint i; + guint path_data_len; + + g_return_val_if_fail (bound_segs != NULL, NULL); + g_return_val_if_fail (n_bound_segs > 0, NULL); + + path_data = g_array_new (FALSE, FALSE, sizeof (cairo_path_data_t)); + + points = g_new0 (GimpVector2, n_bound_segs + 4); + + seg = 0; + n_points = 0; + + points[n_points].x = (gdouble) (bound_segs[0].x1); + points[n_points].y = (gdouble) (bound_segs[0].y1); + + n_points++; + + for (i = 0; i < n_bound_groups; i++) + { + while (bound_segs[seg].x1 != -1 || + bound_segs[seg].x2 != -1 || + bound_segs[seg].y1 != -1 || + bound_segs[seg].y2 != -1) + { + points[n_points].x = (gdouble) (bound_segs[seg].x1); + points[n_points].y = (gdouble) (bound_segs[seg].y1); + + n_points++; + seg++; + } + + /* Close the stroke points up */ + points[n_points] = points[0]; + + n_points++; + + add_polyline (path_data, points, n_points, TRUE); + + n_points = 0; + seg++; + + points[n_points].x = (gdouble) (bound_segs[seg].x1); + points[n_points].y = (gdouble) (bound_segs[seg].y1); + + n_points++; + } + + g_free (points); + + path_data_len = path_data->len; + + return gimp_bezier_desc_new ((cairo_path_data_t *) g_array_free (path_data, FALSE), + path_data_len); +} + +void +gimp_bezier_desc_translate (GimpBezierDesc *desc, + gdouble offset_x, + gdouble offset_y) +{ + gint i, j; + + g_return_if_fail (desc != NULL); + + for (i = 0; i < desc->num_data; i += desc->data[i].header.length) + for (j = 1; j < desc->data[i].header.length; ++j) + { + desc->data[i+j].point.x += offset_x; + desc->data[i+j].point.y += offset_y; + } +} + +GimpBezierDesc * +gimp_bezier_desc_copy (const GimpBezierDesc *desc) +{ + g_return_val_if_fail (desc != NULL, NULL); + + return gimp_bezier_desc_new (g_memdup (desc->data, + desc->num_data * sizeof (cairo_path_data_t)), + desc->num_data); +} + +void +gimp_bezier_desc_free (GimpBezierDesc *desc) +{ + g_return_if_fail (desc != NULL); + + g_free (desc->data); + g_slice_free (GimpBezierDesc, desc); +} |