diff --git a/app/core/Makefile.am b/app/core/Makefile.am index 7b8b413f58..0fddeacb19 100644 --- a/app/core/Makefile.am +++ b/app/core/Makefile.am @@ -141,6 +141,8 @@ libappcore_a_sources = \ gimpdrawable-combine.h \ gimpdrawable-equalize.c \ gimpdrawable-equalize.h \ + gimpdrawable-fill.c \ + gimpdrawable-fill.h \ gimpdrawable-filter.c \ gimpdrawable-filter.h \ gimpdrawable-foreground-extract.c \ diff --git a/app/core/gimpdrawable-fill.c b/app/core/gimpdrawable-fill.c new file mode 100644 index 0000000000..cb9c8b256b --- /dev/null +++ b/app/core/gimpdrawable-fill.c @@ -0,0 +1,214 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * 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 + +#include "core-types.h" + +#include "gegl/gimp-gegl-apply-operation.h" +#include "gegl/gimp-gegl-utils.h" + +#include "gimpbezierdesc.h" +#include "gimpchannel.h" +#include "gimpdrawable-fill.h" +#include "gimperror.h" +#include "gimpfilloptions.h" +#include "gimpimage.h" +#include "gimppattern.h" +#include "gimpscanconvert.h" + +#include "vectors/gimpvectors.h" + +#include "gimp-intl.h" + + +/* public functions */ + +void +gimp_drawable_fill_boundary (GimpDrawable *drawable, + GimpFillOptions *options, + const GimpBoundSeg *bound_segs, + gint n_bound_segs, + gint offset_x, + gint offset_y, + gboolean push_undo) +{ + GimpScanConvert *scan_convert; + + 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_FILL_OPTIONS (options)); + g_return_if_fail (bound_segs == NULL || n_bound_segs != 0); + g_return_if_fail (gimp_fill_options_get_style (options) != + GIMP_FILL_STYLE_PATTERN || + gimp_context_get_pattern (GIMP_CONTEXT (options)) != NULL); + + scan_convert = gimp_scan_convert_new_from_boundary (bound_segs, n_bound_segs, + offset_x, offset_y); + + if (scan_convert) + { + gimp_drawable_fill_scan_convert (drawable, options, + scan_convert, push_undo); + gimp_scan_convert_free (scan_convert); + } +} + +gboolean +gimp_drawable_fill_vectors (GimpDrawable *drawable, + GimpFillOptions *options, + GimpVectors *vectors, + gboolean push_undo, + GError **error) +{ + const GimpBezierDesc *bezier; + + g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE); + g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE); + g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), FALSE); + g_return_val_if_fail (GIMP_IS_VECTORS (vectors), FALSE); + g_return_val_if_fail (gimp_fill_options_get_style (options) != + GIMP_FILL_STYLE_PATTERN || + gimp_context_get_pattern (GIMP_CONTEXT (options)) != NULL, + FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + bezier = gimp_vectors_get_bezier (vectors); + + if (bezier && bezier->num_data > 4) + { + GimpScanConvert *scan_convert = gimp_scan_convert_new (); + + gimp_scan_convert_add_bezier (scan_convert, bezier); + gimp_drawable_fill_scan_convert (drawable, options, + scan_convert, push_undo); + + gimp_scan_convert_free (scan_convert); + + return TRUE; + } + + g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED, + _("Not enough points to fill")); + + return FALSE; +} + +void +gimp_drawable_fill_scan_convert (GimpDrawable *drawable, + GimpFillOptions *options, + GimpScanConvert *scan_convert, + gboolean push_undo) +{ + GimpContext *context; + GimpImage *image; + GeglBuffer *base_buffer; + GeglBuffer *mask_buffer; + gint x, y, w, h; + gint off_x; + gint off_y; + + 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_FILL_OPTIONS (options)); + g_return_if_fail (scan_convert != NULL); + g_return_if_fail (gimp_fill_options_get_style (options) != + GIMP_FILL_STYLE_PATTERN || + gimp_context_get_pattern (GIMP_CONTEXT (options)) != NULL); + + context = GIMP_CONTEXT (options); + image = gimp_item_get_image (GIMP_ITEM (drawable)); + + /* must call gimp_channel_is_empty() instead of relying on + * gimp_item_mask_intersect() because the selection pretends to + * be empty while it is being stroked, to prevent masking itself. + */ + if (gimp_channel_is_empty (gimp_image_get_mask (image))) + { + x = 0; + y = 0; + w = gimp_item_get_width (GIMP_ITEM (drawable)); + h = gimp_item_get_height (GIMP_ITEM (drawable)); + } + else if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &w, &h)) + { + return; + } + + /* fill a 1-bpp GeglBuffer with black, this will describe the shape + * of the stroke. + */ + mask_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, w, h), + babl_format ("Y u8")); + + /* render the stroke into it */ + gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); + + gimp_scan_convert_render (scan_convert, mask_buffer, + x + off_x, y + off_y, + gimp_fill_options_get_antialias (options)); + + base_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, w, h), + gimp_drawable_get_format_with_alpha (drawable)); + + switch (gimp_fill_options_get_style (options)) + { + case GIMP_FILL_STYLE_SOLID: + { + GimpRGB fg; + GeglColor *color; + + gimp_context_get_foreground (context, &fg); + + color = gimp_gegl_color_new (&fg); + gegl_buffer_set_color (base_buffer, NULL, color); + g_object_unref (color); + } + break; + + case GIMP_FILL_STYLE_PATTERN: + { + GimpPattern *pattern = gimp_context_get_pattern (context); + GeglBuffer *pattern_buffer; + + pattern_buffer = gimp_pattern_create_buffer (pattern); + gegl_buffer_set_pattern (base_buffer, NULL, pattern_buffer, 0, 0); + g_object_unref (pattern_buffer); + } + break; + } + + gimp_gegl_apply_opacity (base_buffer, NULL, NULL, base_buffer, + mask_buffer, 0, 0, 1.0); + g_object_unref (mask_buffer); + + /* Apply to drawable */ + gimp_drawable_apply_buffer (drawable, base_buffer, + GEGL_RECTANGLE (0, 0, w, h), + push_undo, C_("undo-type", "Render Stroke"), + gimp_context_get_opacity (context), + gimp_context_get_paint_mode (context), + NULL, x, y); + + g_object_unref (base_buffer); + + gimp_drawable_update (drawable, x, y, w, h); +} diff --git a/app/core/gimpdrawable-fill.h b/app/core/gimpdrawable-fill.h new file mode 100644 index 0000000000..c3364ba9c6 --- /dev/null +++ b/app/core/gimpdrawable-fill.h @@ -0,0 +1,42 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * 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 . + */ + +#ifndef __GIMP_DRAWABLE_FILL_H__ +#define __GIMP_DRAWABLE_FILL_H__ + + +void gimp_drawable_fill_boundary (GimpDrawable *drawable, + GimpFillOptions *options, + const GimpBoundSeg *bound_segs, + gint n_bound_segs, + gint offset_x, + gint offset_y, + gboolean push_undo); + +gboolean gimp_drawable_fill_vectors (GimpDrawable *drawable, + GimpFillOptions *options, + GimpVectors *vectors, + gboolean push_undo, + GError **error); + +void gimp_drawable_fill_scan_convert (GimpDrawable *drawable, + GimpFillOptions *options, + GimpScanConvert *scan_convert, + gboolean push_undo); + + +#endif /* __GIMP_DRAWABLE_FILL_H__ */ diff --git a/app/core/gimpdrawable-stroke.c b/app/core/gimpdrawable-stroke.c index 6757125805..3e7dd7f15f 100644 --- a/app/core/gimpdrawable-stroke.c +++ b/app/core/gimpdrawable-stroke.c @@ -21,87 +21,28 @@ #include "config.h" #include -#include #include +#include #include "libgimpbase/gimpbase.h" -#include "libgimpmath/gimpmath.h" -#include "libgimpcolor/gimpcolor.h" #include "core-types.h" -#include "gegl/gimp-gegl-apply-operation.h" -#include "gegl/gimp-gegl-utils.h" - -#include "gimp.h" -#include "gimpbezierdesc.h" -#include "gimpboundary.h" #include "gimpchannel.h" -#include "gimpcontext.h" +#include "gimpdrawable-fill.h" #include "gimpdrawable-stroke.h" #include "gimperror.h" #include "gimpimage.h" -#include "gimppattern.h" #include "gimpscanconvert.h" #include "gimpstrokeoptions.h" -#include "vectors/gimpstroke.h" #include "vectors/gimpvectors.h" #include "gimp-intl.h" -/* local function prototypes */ - -static GimpScanConvert * gimp_drawable_render_boundary (GimpDrawable *drawable, - const GimpBoundSeg *bound_segs, - gint n_bound_segs, - gint offset_x, - gint offset_y); -static GimpScanConvert * gimp_drawable_render_vectors (GimpDrawable *drawable, - GimpVectors *vectors, - gboolean do_stroke, - GError **error); -static void gimp_drawable_stroke_scan_convert (GimpDrawable *drawable, - GimpFillOptions *options, - GimpScanConvert *scan_convert, - gboolean do_stroke, - gboolean push_undo); - - /* public functions */ -void -gimp_drawable_fill_boundary (GimpDrawable *drawable, - GimpFillOptions *options, - const GimpBoundSeg *bound_segs, - gint n_bound_segs, - gint offset_x, - gint offset_y, - gboolean push_undo) -{ - GimpScanConvert *scan_convert; - - 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 (bound_segs == NULL || n_bound_segs != 0); - g_return_if_fail (gimp_fill_options_get_style (options) != - GIMP_FILL_STYLE_PATTERN || - gimp_context_get_pattern (GIMP_CONTEXT (options)) != NULL); - - scan_convert = gimp_drawable_render_boundary (drawable, - bound_segs, n_bound_segs, - offset_x, offset_y); - - if (scan_convert) - { - gimp_drawable_stroke_scan_convert (drawable, options, - scan_convert, FALSE, push_undo); - gimp_scan_convert_free (scan_convert); - } -} - void gimp_drawable_stroke_boundary (GimpDrawable *drawable, GimpStrokeOptions *options, @@ -121,49 +62,15 @@ gimp_drawable_stroke_boundary (GimpDrawable *drawable, GIMP_FILL_STYLE_PATTERN || gimp_context_get_pattern (GIMP_CONTEXT (options)) != NULL); - scan_convert = gimp_drawable_render_boundary (drawable, - bound_segs, n_bound_segs, - offset_x, offset_y); - - if (scan_convert) - { - gimp_drawable_stroke_scan_convert (drawable, GIMP_FILL_OPTIONS (options), - scan_convert, TRUE, push_undo); - gimp_scan_convert_free (scan_convert); - } -} - -gboolean -gimp_drawable_fill_vectors (GimpDrawable *drawable, - GimpFillOptions *options, - GimpVectors *vectors, - gboolean push_undo, - GError **error) -{ - GimpScanConvert *scan_convert; - - g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE); - g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE); - g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), FALSE); - g_return_val_if_fail (GIMP_IS_VECTORS (vectors), FALSE); - g_return_val_if_fail (gimp_fill_options_get_style (options) != - GIMP_FILL_STYLE_PATTERN || - gimp_context_get_pattern (GIMP_CONTEXT (options)) != NULL, - FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - scan_convert = gimp_drawable_render_vectors (drawable, vectors, FALSE, error); + scan_convert = gimp_scan_convert_new_from_boundary (bound_segs, n_bound_segs, + offset_x, offset_y); if (scan_convert) { gimp_drawable_stroke_scan_convert (drawable, options, - scan_convert, FALSE, push_undo); + scan_convert, push_undo); gimp_scan_convert_free (scan_convert); - - return TRUE; } - - return FALSE; } gboolean @@ -173,7 +80,7 @@ gimp_drawable_stroke_vectors (GimpDrawable *drawable, gboolean push_undo, GError **error) { - GimpScanConvert *scan_convert; + const GimpBezierDesc *bezier; g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE); g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE); @@ -185,211 +92,79 @@ gimp_drawable_stroke_vectors (GimpDrawable *drawable, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - scan_convert = gimp_drawable_render_vectors (drawable, vectors, TRUE, error); + bezier = gimp_vectors_get_bezier (vectors); - if (scan_convert) + if (bezier && bezier->num_data >= 2) { - gimp_drawable_stroke_scan_convert (drawable, GIMP_FILL_OPTIONS (options), - scan_convert, TRUE, push_undo); + GimpScanConvert *scan_convert = gimp_scan_convert_new (); + + gimp_scan_convert_add_bezier (scan_convert, bezier); + gimp_drawable_stroke_scan_convert (drawable, options, + scan_convert, push_undo); + gimp_scan_convert_free (scan_convert); return TRUE; } + g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED, + _("Not enough points to stroke")); + return FALSE; } - -/* private functions */ - -static GimpScanConvert * -gimp_drawable_render_boundary (GimpDrawable *drawable, - const GimpBoundSeg *bound_segs, - gint n_bound_segs, - gint offset_x, - gint offset_y) +void +gimp_drawable_stroke_scan_convert (GimpDrawable *drawable, + GimpStrokeOptions *options, + GimpScanConvert *scan_convert, + gboolean push_undo) { - if (bound_segs) - { - GimpBoundSeg *stroke_segs; - gint n_stroke_segs; + GimpImage *image; + gdouble width; + GimpUnit unit; - stroke_segs = gimp_boundary_sort (bound_segs, n_bound_segs, - &n_stroke_segs); + 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 (scan_convert != NULL); + g_return_if_fail (gimp_fill_options_get_style (GIMP_FILL_OPTIONS (options)) != + GIMP_FILL_STYLE_PATTERN || + gimp_context_get_pattern (GIMP_CONTEXT (options)) != NULL); - if (stroke_segs) - { - GimpBezierDesc *bezier; - - bezier = gimp_bezier_desc_new_from_bound_segs (stroke_segs, - n_bound_segs, - n_stroke_segs); - - g_free (stroke_segs); - - if (bezier) - { - GimpScanConvert *scan_convert; - - scan_convert = gimp_scan_convert_new (); - - gimp_bezier_desc_translate (bezier, offset_x, offset_y); - gimp_scan_convert_add_bezier (scan_convert, bezier); - - gimp_bezier_desc_free (bezier); - - return scan_convert; - } - } - } - - return NULL; -} - -static GimpScanConvert * -gimp_drawable_render_vectors (GimpDrawable *drawable, - GimpVectors *vectors, - gboolean do_stroke, - GError **error) -{ - const GimpBezierDesc *bezier; - - bezier = gimp_vectors_get_bezier (vectors); - - if (bezier && (do_stroke ? bezier->num_data >= 2 : bezier->num_data > 4)) - { - GimpScanConvert *scan_convert; - - scan_convert = gimp_scan_convert_new (); - gimp_scan_convert_add_bezier (scan_convert, bezier); - - return scan_convert; - } - - g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED, - do_stroke ? - _("Not enough points to stroke") : - _("Not enough points to fill")); - - return NULL; -} - -static void -gimp_drawable_stroke_scan_convert (GimpDrawable *drawable, - GimpFillOptions *options, - GimpScanConvert *scan_convert, - gboolean do_stroke, - gboolean push_undo) -{ - GimpContext *context = GIMP_CONTEXT (options); - GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); - GeglBuffer *base_buffer; - GeglBuffer *mask_buffer; - gint x, y, w, h; - gint off_x; - gint off_y; + image = gimp_item_get_image (GIMP_ITEM (drawable)); /* must call gimp_channel_is_empty() instead of relying on * gimp_item_mask_intersect() because the selection pretends to * be empty while it is being stroked, to prevent masking itself. */ - if (gimp_channel_is_empty (gimp_image_get_mask (image))) - { - x = 0; - y = 0; - w = gimp_item_get_width (GIMP_ITEM (drawable)); - h = gimp_item_get_height (GIMP_ITEM (drawable)); - } - else if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &w, &h)) + if (! gimp_channel_is_empty (gimp_image_get_mask (image)) && + ! gimp_item_mask_intersect (GIMP_ITEM (drawable), NULL, NULL, NULL, NULL)) { return; } - if (do_stroke) + width = gimp_stroke_options_get_width (options); + unit = gimp_stroke_options_get_unit (options); + + if (unit != GIMP_UNIT_PIXEL) { - GimpStrokeOptions *stroke_options = GIMP_STROKE_OPTIONS (options); - gdouble width; - GimpUnit unit; + gdouble xres; + gdouble yres; - width = gimp_stroke_options_get_width (stroke_options); - unit = gimp_stroke_options_get_unit (stroke_options); + gimp_image_get_resolution (image, &xres, &yres); - if (unit != GIMP_UNIT_PIXEL) - { - gdouble xres; - gdouble yres; + gimp_scan_convert_set_pixel_ratio (scan_convert, yres / xres); - gimp_image_get_resolution (image, &xres, &yres); - - gimp_scan_convert_set_pixel_ratio (scan_convert, yres / xres); - - width = gimp_units_to_pixels (width, unit, yres); - } - - gimp_scan_convert_stroke (scan_convert, width, - gimp_stroke_options_get_join_style (stroke_options), - gimp_stroke_options_get_cap_style (stroke_options), - gimp_stroke_options_get_miter_limit (stroke_options), - gimp_stroke_options_get_dash_offset (stroke_options), - gimp_stroke_options_get_dash_info (stroke_options)); + width = gimp_units_to_pixels (width, unit, yres); } - /* fill a 1-bpp GeglBuffer with black, this will describe the shape - * of the stroke. - */ - mask_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, w, h), - babl_format ("Y u8")); + gimp_scan_convert_stroke (scan_convert, width, + gimp_stroke_options_get_join_style (options), + gimp_stroke_options_get_cap_style (options), + gimp_stroke_options_get_miter_limit (options), + gimp_stroke_options_get_dash_offset (options), + gimp_stroke_options_get_dash_info (options)); - /* render the stroke into it */ - gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); - - gimp_scan_convert_render (scan_convert, mask_buffer, - x + off_x, y + off_y, - gimp_fill_options_get_antialias (options)); - - base_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, w, h), - gimp_drawable_get_format_with_alpha (drawable)); - - switch (gimp_fill_options_get_style (options)) - { - case GIMP_FILL_STYLE_SOLID: - { - GimpRGB fg; - GeglColor *color; - - gimp_context_get_foreground (context, &fg); - - color = gimp_gegl_color_new (&fg); - gegl_buffer_set_color (base_buffer, NULL, color); - g_object_unref (color); - } - break; - - case GIMP_FILL_STYLE_PATTERN: - { - GimpPattern *pattern = gimp_context_get_pattern (context); - GeglBuffer *pattern_buffer; - - pattern_buffer = gimp_pattern_create_buffer (pattern); - gegl_buffer_set_pattern (base_buffer, NULL, pattern_buffer, 0, 0); - g_object_unref (pattern_buffer); - } - break; - } - - gimp_gegl_apply_opacity (base_buffer, NULL, NULL, base_buffer, - mask_buffer, 0, 0, 1.0); - g_object_unref (mask_buffer); - - /* Apply to drawable */ - gimp_drawable_apply_buffer (drawable, base_buffer, - GEGL_RECTANGLE (0, 0, w, h), - push_undo, C_("undo-type", "Render Stroke"), - gimp_context_get_opacity (context), - gimp_context_get_paint_mode (context), - NULL, x, y); - - g_object_unref (base_buffer); - - gimp_drawable_update (drawable, x, y, w, h); + gimp_drawable_fill_scan_convert (drawable, GIMP_FILL_OPTIONS (options), + scan_convert, push_undo); } diff --git a/app/core/gimpdrawable-stroke.h b/app/core/gimpdrawable-stroke.h index 11a26ef353..2d15e3ff45 100644 --- a/app/core/gimpdrawable-stroke.h +++ b/app/core/gimpdrawable-stroke.h @@ -22,31 +22,24 @@ #define __GIMP_DRAWABLE_STROKE_H__ -void gimp_drawable_fill_boundary (GimpDrawable *drawable, - GimpFillOptions *options, - const GimpBoundSeg *bound_segs, - gint n_bound_segs, - gint offset_x, - gint offset_y, - gboolean push_undo); -void gimp_drawable_stroke_boundary (GimpDrawable *drawable, - GimpStrokeOptions *options, - const GimpBoundSeg *bound_segs, - gint n_bound_segs, - gint offset_x, - gint offset_y, - gboolean push_undo); +void gimp_drawable_stroke_boundary (GimpDrawable *drawable, + GimpStrokeOptions *options, + const GimpBoundSeg *bound_segs, + gint n_bound_segs, + gint offset_x, + gint offset_y, + gboolean push_undo); -gboolean gimp_drawable_fill_vectors (GimpDrawable *drawable, - GimpFillOptions *options, - GimpVectors *vectors, - gboolean push_undo, - GError **error); -gboolean gimp_drawable_stroke_vectors (GimpDrawable *drawable, - GimpStrokeOptions *options, - GimpVectors *vectors, - gboolean push_undo, - GError **error); +gboolean gimp_drawable_stroke_vectors (GimpDrawable *drawable, + GimpStrokeOptions *options, + GimpVectors *vectors, + gboolean push_undo, + GError **error); + +void gimp_drawable_stroke_scan_convert (GimpDrawable *drawable, + GimpStrokeOptions *options, + GimpScanConvert *scan_convert, + gboolean push_undo); #endif /* __GIMP_DRAWABLE_STROKE_H__ */ diff --git a/app/core/gimpscanconvert.c b/app/core/gimpscanconvert.c index f37bd0c36e..d287532ff5 100644 --- a/app/core/gimpscanconvert.c +++ b/app/core/gimpscanconvert.c @@ -19,7 +19,7 @@ #include -#include +#include #include #include @@ -29,6 +29,7 @@ #include "core-types.h" +#include "gimpboundary.h" #include "gimpbezierdesc.h" #include "gimpscanconvert.h" @@ -76,6 +77,51 @@ gimp_scan_convert_new (void) return sc; } +GimpScanConvert * +gimp_scan_convert_new_from_boundary (const GimpBoundSeg *bound_segs, + gint n_bound_segs, + gint offset_x, + gint offset_y) +{ + g_return_val_if_fail (bound_segs == NULL || n_bound_segs != 0, NULL); + + if (bound_segs) + { + GimpBoundSeg *stroke_segs; + gint n_stroke_segs; + + stroke_segs = gimp_boundary_sort (bound_segs, n_bound_segs, + &n_stroke_segs); + + if (stroke_segs) + { + GimpBezierDesc *bezier; + + bezier = gimp_bezier_desc_new_from_bound_segs (stroke_segs, + n_bound_segs, + n_stroke_segs); + + g_free (stroke_segs); + + if (bezier) + { + GimpScanConvert *scan_convert; + + scan_convert = gimp_scan_convert_new (); + + gimp_bezier_desc_translate (bezier, offset_x, offset_y); + gimp_scan_convert_add_bezier (scan_convert, bezier); + + gimp_bezier_desc_free (bezier); + + return scan_convert; + } + } + } + + return NULL; +} + /** * gimp_scan_convert_free: * @sc: a #GimpScanConvert context diff --git a/app/core/gimpscanconvert.h b/app/core/gimpscanconvert.h index 53fc94e0ce..f43c169e3c 100644 --- a/app/core/gimpscanconvert.h +++ b/app/core/gimpscanconvert.h @@ -19,7 +19,14 @@ #define __GIMP_SCAN_CONVERT_H__ -GimpScanConvert * gimp_scan_convert_new (void); +GimpScanConvert * + gimp_scan_convert_new (void); + +GimpScanConvert * + gimp_scan_convert_new_from_boundary (const GimpBoundSeg *bound_segs, + gint n_bound_segs, + gint offset_x, + gint offset_y); void gimp_scan_convert_free (GimpScanConvert *sc); void gimp_scan_convert_set_pixel_ratio (GimpScanConvert *sc,