diff options
Diffstat (limited to 'app/core/gimpfilloptions.c')
-rw-r--r-- | app/core/gimpfilloptions.c | 548 |
1 files changed, 548 insertions, 0 deletions
diff --git a/app/core/gimpfilloptions.c b/app/core/gimpfilloptions.c new file mode 100644 index 0000000..d10b6e4 --- /dev/null +++ b/app/core/gimpfilloptions.c @@ -0,0 +1,548 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis + * + * gimpfilloptions.c + * Copyright (C) 2003 Simon Budig + * + * 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 <cairo.h> +#include <gdk-pixbuf/gdk-pixbuf.h> +#include <gegl.h> + +#include "libgimpcolor/gimpcolor.h" +#include "libgimpconfig/gimpconfig.h" + +#include "core-types.h" + +#include "operations/layer-modes/gimp-layer-modes.h" + +#include "gimp.h" +#include "gimp-palettes.h" +#include "gimpdrawable.h" +#include "gimpdrawable-fill.h" +#include "gimperror.h" +#include "gimpfilloptions.h" +#include "gimppattern.h" + +#include "gimp-intl.h" + + +enum +{ + PROP_0, + PROP_STYLE, + PROP_ANTIALIAS, + PROP_FEATHER, + PROP_FEATHER_RADIUS, + PROP_PATTERN_VIEW_TYPE, + PROP_PATTERN_VIEW_SIZE +}; + + +typedef struct _GimpFillOptionsPrivate GimpFillOptionsPrivate; + +struct _GimpFillOptionsPrivate +{ + GimpFillStyle style; + gboolean antialias; + gboolean feather; + gdouble feather_radius; + + GimpViewType pattern_view_type; + GimpViewSize pattern_view_size; + + const gchar *undo_desc; +}; + +#define GET_PRIVATE(options) \ + ((GimpFillOptionsPrivate *) gimp_fill_options_get_instance_private ((GimpFillOptions *) (options))) + + +static void gimp_fill_options_config_init (GimpConfigInterface *iface); + +static void gimp_fill_options_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_fill_options_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static gboolean gimp_fill_options_serialize (GimpConfig *config, + GimpConfigWriter *writer, + gpointer data); + + +G_DEFINE_TYPE_WITH_CODE (GimpFillOptions, gimp_fill_options, GIMP_TYPE_CONTEXT, + G_ADD_PRIVATE (GimpFillOptions) + G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG, + gimp_fill_options_config_init)) + + +static void +gimp_fill_options_class_init (GimpFillOptionsClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = gimp_fill_options_set_property; + object_class->get_property = gimp_fill_options_get_property; + + GIMP_CONFIG_PROP_ENUM (object_class, PROP_STYLE, + "style", + _("Style"), + NULL, + GIMP_TYPE_FILL_STYLE, + GIMP_FILL_STYLE_SOLID, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ANTIALIAS, + "antialias", + _("Antialiasing"), + NULL, + TRUE, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_FEATHER, + "feather", + _("Feather edges"), + _("Enable feathering of fill edges"), + FALSE, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_FEATHER_RADIUS, + "feather-radius", + _("Radius"), + _("Radius of feathering"), + 0.0, 100.0, 10.0, + GIMP_PARAM_STATIC_STRINGS); + + g_object_class_install_property (object_class, PROP_PATTERN_VIEW_TYPE, + g_param_spec_enum ("pattern-view-type", + NULL, NULL, + GIMP_TYPE_VIEW_TYPE, + GIMP_VIEW_TYPE_GRID, + G_PARAM_CONSTRUCT | + GIMP_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_PATTERN_VIEW_SIZE, + g_param_spec_int ("pattern-view-size", + NULL, NULL, + GIMP_VIEW_SIZE_TINY, + GIMP_VIEWABLE_MAX_BUTTON_SIZE, + GIMP_VIEW_SIZE_SMALL, + G_PARAM_CONSTRUCT | + GIMP_PARAM_READWRITE)); +} + +static void +gimp_fill_options_config_init (GimpConfigInterface *iface) +{ + iface->serialize = gimp_fill_options_serialize; +} + +static void +gimp_fill_options_init (GimpFillOptions *options) +{ +} + +static void +gimp_fill_options_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpFillOptionsPrivate *private = GET_PRIVATE (object); + + switch (property_id) + { + case PROP_STYLE: + private->style = g_value_get_enum (value); + private->undo_desc = NULL; + break; + case PROP_ANTIALIAS: + private->antialias = g_value_get_boolean (value); + break; + case PROP_FEATHER: + private->feather = g_value_get_boolean (value); + break; + case PROP_FEATHER_RADIUS: + private->feather_radius = g_value_get_double (value); + break; + + case PROP_PATTERN_VIEW_TYPE: + private->pattern_view_type = g_value_get_enum (value); + break; + case PROP_PATTERN_VIEW_SIZE: + private->pattern_view_size = g_value_get_int (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_fill_options_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpFillOptionsPrivate *private = GET_PRIVATE (object); + + switch (property_id) + { + case PROP_STYLE: + g_value_set_enum (value, private->style); + break; + case PROP_ANTIALIAS: + g_value_set_boolean (value, private->antialias); + break; + case PROP_FEATHER: + g_value_set_boolean (value, private->feather); + break; + case PROP_FEATHER_RADIUS: + g_value_set_double (value, private->feather_radius); + break; + + case PROP_PATTERN_VIEW_TYPE: + g_value_set_enum (value, private->pattern_view_type); + break; + case PROP_PATTERN_VIEW_SIZE: + g_value_set_int (value, private->pattern_view_size); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static gboolean +gimp_fill_options_serialize (GimpConfig *config, + GimpConfigWriter *writer, + gpointer data) +{ + return gimp_config_serialize_properties (config, writer); +} + + +/* public functions */ + +GimpFillOptions * +gimp_fill_options_new (Gimp *gimp, + GimpContext *context, + gboolean use_context_color) +{ + GimpFillOptions *options; + + g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); + g_return_val_if_fail (context == NULL || GIMP_IS_CONTEXT (context), NULL); + g_return_val_if_fail (use_context_color == FALSE || context != NULL, NULL); + + options = g_object_new (GIMP_TYPE_FILL_OPTIONS, + "gimp", gimp, + NULL); + + if (use_context_color) + { + gimp_context_define_properties (GIMP_CONTEXT (options), + GIMP_CONTEXT_PROP_MASK_FOREGROUND | + GIMP_CONTEXT_PROP_MASK_PATTERN, + FALSE); + + gimp_context_set_parent (GIMP_CONTEXT (options), context); + } + + return options; +} + +GimpFillStyle +gimp_fill_options_get_style (GimpFillOptions *options) +{ + g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), GIMP_FILL_STYLE_SOLID); + + return GET_PRIVATE (options)->style; +} + +void +gimp_fill_options_set_style (GimpFillOptions *options, + GimpFillStyle style) +{ + g_return_if_fail (GIMP_IS_FILL_OPTIONS (options)); + + g_object_set (options, "style", style, NULL); +} + +gboolean +gimp_fill_options_get_antialias (GimpFillOptions *options) +{ + g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), FALSE); + + return GET_PRIVATE (options)->antialias; +} + +void +gimp_fill_options_set_antialias (GimpFillOptions *options, + gboolean antialias) +{ + g_return_if_fail (GIMP_IS_FILL_OPTIONS (options)); + + g_object_set (options, "antialias", antialias, NULL); +} + +gboolean +gimp_fill_options_get_feather (GimpFillOptions *options, + gdouble *radius) +{ + g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), FALSE); + + if (radius) + *radius = GET_PRIVATE (options)->feather_radius; + + return GET_PRIVATE (options)->feather; +} + +void +gimp_fill_options_set_feather (GimpFillOptions *options, + gboolean feather, + gdouble radius) +{ + g_return_if_fail (GIMP_IS_FILL_OPTIONS (options)); + + g_object_set (options, "feather", feather, NULL); + g_object_set (options, "feather-radius", radius, NULL); +} + +gboolean +gimp_fill_options_set_by_fill_type (GimpFillOptions *options, + GimpContext *context, + GimpFillType fill_type, + GError **error) +{ + GimpFillOptionsPrivate *private; + GimpRGB color; + const gchar *undo_desc; + + g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), FALSE); + g_return_val_if_fail (GIMP_IS_CONTEXT (context), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + private = GET_PRIVATE (options); + + private->undo_desc = NULL; + + switch (fill_type) + { + case GIMP_FILL_FOREGROUND: + gimp_context_get_foreground (context, &color); + undo_desc = C_("undo-type", "Fill with Foreground Color"); + break; + + case GIMP_FILL_BACKGROUND: + gimp_context_get_background (context, &color); + undo_desc = C_("undo-type", "Fill with Background Color"); + break; + + case GIMP_FILL_WHITE: + gimp_rgba_set (&color, 1.0, 1.0, 1.0, GIMP_OPACITY_OPAQUE); + undo_desc = C_("undo-type", "Fill with White"); + break; + + case GIMP_FILL_TRANSPARENT: + gimp_context_get_background (context, &color); + gimp_context_set_paint_mode (GIMP_CONTEXT (options), + GIMP_LAYER_MODE_ERASE); + undo_desc = C_("undo-type", "Fill with Transparency"); + break; + + case GIMP_FILL_PATTERN: + { + GimpPattern *pattern = gimp_context_get_pattern (context); + + if (! pattern) + { + g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED, + _("No patterns available for this operation.")); + return FALSE; + } + + gimp_fill_options_set_style (options, GIMP_FILL_STYLE_PATTERN); + gimp_context_set_pattern (GIMP_CONTEXT (options), pattern); + private->undo_desc = C_("undo-type", "Fill with Pattern"); + + return TRUE; + } + break; + + default: + g_warning ("%s: invalid fill_type %d", G_STRFUNC, fill_type); + return FALSE; + } + + gimp_fill_options_set_style (options, GIMP_FILL_STYLE_SOLID); + gimp_context_set_foreground (GIMP_CONTEXT (options), &color); + private->undo_desc = undo_desc; + + return TRUE; +} + +gboolean +gimp_fill_options_set_by_fill_mode (GimpFillOptions *options, + GimpContext *context, + GimpBucketFillMode fill_mode, + GError **error) +{ + GimpFillType fill_type; + + g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), FALSE); + g_return_val_if_fail (GIMP_IS_CONTEXT (context), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + switch (fill_mode) + { + default: + case GIMP_BUCKET_FILL_FG: + fill_type = GIMP_FILL_FOREGROUND; + break; + + case GIMP_BUCKET_FILL_BG: + fill_type = GIMP_FILL_BACKGROUND; + break; + + case GIMP_BUCKET_FILL_PATTERN: + fill_type = GIMP_FILL_PATTERN; + break; + } + + return gimp_fill_options_set_by_fill_type (options, context, + fill_type, error); +} + +const gchar * +gimp_fill_options_get_undo_desc (GimpFillOptions *options) +{ + GimpFillOptionsPrivate *private; + + g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), NULL); + + private = GET_PRIVATE (options); + + if (private->undo_desc) + return private->undo_desc; + + switch (private->style) + { + case GIMP_FILL_STYLE_SOLID: + return C_("undo-type", "Fill with Solid Color"); + + case GIMP_FILL_STYLE_PATTERN: + return C_("undo-type", "Fill with Pattern"); + } + + g_return_val_if_reached (NULL); +} + +const Babl * +gimp_fill_options_get_format (GimpFillOptions *options, + GimpDrawable *drawable) +{ + GimpContext *context; + + g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), NULL); + g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); + + context = GIMP_CONTEXT (options); + + return gimp_layer_mode_get_format (gimp_context_get_paint_mode (context), + GIMP_LAYER_COLOR_SPACE_AUTO, + GIMP_LAYER_COLOR_SPACE_AUTO, + gimp_layer_mode_get_paint_composite_mode ( + gimp_context_get_paint_mode (context)), + gimp_drawable_get_format (drawable)); +} + +GeglBuffer * +gimp_fill_options_create_buffer (GimpFillOptions *options, + GimpDrawable *drawable, + const GeglRectangle *rect, + gint pattern_offset_x, + gint pattern_offset_y) +{ + GeglBuffer *buffer; + + g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), NULL); + g_return_val_if_fail (gimp_fill_options_get_style (options) != + GIMP_FILL_STYLE_PATTERN || + gimp_context_get_pattern (GIMP_CONTEXT (options)) != NULL, + NULL); + g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); + g_return_val_if_fail (rect != NULL, NULL); + + buffer = gegl_buffer_new (rect, + gimp_fill_options_get_format (options, drawable)); + + gimp_fill_options_fill_buffer (options, drawable, buffer, + pattern_offset_x, pattern_offset_y); + + return buffer; +} + +void +gimp_fill_options_fill_buffer (GimpFillOptions *options, + GimpDrawable *drawable, + GeglBuffer *buffer, + gint pattern_offset_x, + gint pattern_offset_y) +{ + g_return_if_fail (GIMP_IS_FILL_OPTIONS (options)); + g_return_if_fail (gimp_fill_options_get_style (options) != + GIMP_FILL_STYLE_PATTERN || + gimp_context_get_pattern (GIMP_CONTEXT (options)) != NULL); + g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); + g_return_if_fail (GEGL_IS_BUFFER (buffer)); + + switch (gimp_fill_options_get_style (options)) + { + case GIMP_FILL_STYLE_SOLID: + { + GimpRGB color; + + gimp_context_get_foreground (GIMP_CONTEXT (options), &color); + gimp_palettes_add_color_history (GIMP_CONTEXT (options)->gimp, &color); + + gimp_drawable_fill_buffer (drawable, buffer, + &color, NULL, 0, 0); + } + break; + + case GIMP_FILL_STYLE_PATTERN: + { + GimpPattern *pattern; + + pattern = gimp_context_get_pattern (GIMP_CONTEXT (options)); + + gimp_drawable_fill_buffer (drawable, buffer, + NULL, pattern, + pattern_offset_x, + pattern_offset_y); + } + break; + } +} |