--- gimp-2.6.6/app/actions/tool-options-commands.c 2008-11-21 07:43:04 +0900 +++ gimp-painter--2.6.6-20100627/app/actions/tool-options-commands.c 2010-06-27 02:14:18 +0900 @@ -53,6 +53,9 @@ static void tool_options_rename_callback (GtkWidget *widget, const gchar *name, gpointer data); +static void tool_options_sync (GObject *src, + GObject *dest, + GParamFlags flags); /* public functions */ @@ -116,9 +119,22 @@ options = gimp_tool_presets_get_options (tool_info->presets, value); if (options) - gimp_config_sync (G_OBJECT (options), - G_OBJECT (tool_info->tool_options), - GIMP_CONFIG_PARAM_SERIALIZE); + { + GdkModifierType state; + guint flags = GIMP_CONFIG_PARAM_DONT_RESTORE; + + if (gtk_get_current_event_state (&state)) + { + if (state & GDK_SHIFT_MASK && ! (state & GDK_CONTROL_MASK)) + flags = 0; + else if (state & GDK_CONTROL_MASK && ! (state & GDK_SHIFT_MASK)) + flags |= GIMP_CONFIG_PARAM_DONT_RESTORE_SECONDARY; + } + + tool_options_sync (G_OBJECT (options), + G_OBJECT (tool_info->tool_options), + flags); + } } void @@ -263,3 +279,40 @@ else gimp_object_set_static_name (GIMP_OBJECT (options), _("Saved Options")); } + +static void +tool_options_sync (GObject *src, + GObject *dest, + GParamFlags flags) +{ + GParamSpec **param_specs; + guint n_param_specs; + gint i; + + g_return_val_if_fail (G_IS_OBJECT (src), FALSE); + g_return_val_if_fail (G_IS_OBJECT (dest), FALSE); + + param_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (src), + &n_param_specs); + + for (i = 0; i < n_param_specs; i++) + { + GParamSpec *prop_spec = param_specs[i]; + + if ((prop_spec->flags & GIMP_CONFIG_PARAM_SERIALIZE) && ! (prop_spec->flags & (flags | G_PARAM_CONSTRUCT_ONLY))) + { + GValue value = { 0, }; + + g_value_init (&value, prop_spec->value_type); + + g_object_get_property (src, prop_spec->name, &value); + g_object_set_property (dest, prop_spec->name, &value); + + g_value_unset (&value); + } + } + + g_free (param_specs); + + return; + } --- gimp-2.6.6/app/core/core-enums.h 2008-11-21 07:42:58 +0900 +++ gimp-painter--2.6.6-20100627/app/core/core-enums.h 2010-06-27 02:14:18 +0900 @@ -603,15 +603,16 @@ GIMP_CONTEXT_PROP_FOREGROUND = 6, GIMP_CONTEXT_PROP_BACKGROUND = 7, GIMP_CONTEXT_PROP_OPACITY = 8, - GIMP_CONTEXT_PROP_PAINT_MODE = 9, - GIMP_CONTEXT_PROP_BRUSH = 10, - GIMP_CONTEXT_PROP_PATTERN = 11, - GIMP_CONTEXT_PROP_GRADIENT = 12, - GIMP_CONTEXT_PROP_PALETTE = 13, - GIMP_CONTEXT_PROP_FONT = 14, - GIMP_CONTEXT_PROP_BUFFER = 15, - GIMP_CONTEXT_PROP_IMAGEFILE = 16, - GIMP_CONTEXT_PROP_TEMPLATE = 17, + GIMP_CONTEXT_PROP_FLOW = 9, + GIMP_CONTEXT_PROP_PAINT_MODE = 10, + GIMP_CONTEXT_PROP_BRUSH = 11, + GIMP_CONTEXT_PROP_PATTERN = 12, + GIMP_CONTEXT_PROP_GRADIENT = 13, + GIMP_CONTEXT_PROP_PALETTE = 14, + GIMP_CONTEXT_PROP_FONT = 15, + GIMP_CONTEXT_PROP_BUFFER = 16, + GIMP_CONTEXT_PROP_IMAGEFILE = 17, + GIMP_CONTEXT_PROP_TEMPLATE = 18, GIMP_CONTEXT_LAST_PROP = GIMP_CONTEXT_PROP_TEMPLATE } GimpContextPropType; @@ -626,20 +627,22 @@ GIMP_CONTEXT_FOREGROUND_MASK = 1 << 6, GIMP_CONTEXT_BACKGROUND_MASK = 1 << 7, GIMP_CONTEXT_OPACITY_MASK = 1 << 8, - GIMP_CONTEXT_PAINT_MODE_MASK = 1 << 9, - GIMP_CONTEXT_BRUSH_MASK = 1 << 10, - GIMP_CONTEXT_PATTERN_MASK = 1 << 11, - GIMP_CONTEXT_GRADIENT_MASK = 1 << 12, - GIMP_CONTEXT_PALETTE_MASK = 1 << 13, - GIMP_CONTEXT_FONT_MASK = 1 << 14, - GIMP_CONTEXT_BUFFER_MASK = 1 << 15, - GIMP_CONTEXT_IMAGEFILE_MASK = 1 << 16, - GIMP_CONTEXT_TEMPLATE_MASK = 1 << 17, + GIMP_CONTEXT_FLOW_MASK = 1 << 9, + GIMP_CONTEXT_PAINT_MODE_MASK = 1 << 10, + GIMP_CONTEXT_BRUSH_MASK = 1 << 11, + GIMP_CONTEXT_PATTERN_MASK = 1 << 12, + GIMP_CONTEXT_GRADIENT_MASK = 1 << 13, + GIMP_CONTEXT_PALETTE_MASK = 1 << 14, + GIMP_CONTEXT_FONT_MASK = 1 << 15, + GIMP_CONTEXT_BUFFER_MASK = 1 << 16, + GIMP_CONTEXT_IMAGEFILE_MASK = 1 << 17, + GIMP_CONTEXT_TEMPLATE_MASK = 1 << 18, /* aliases */ GIMP_CONTEXT_PAINT_PROPS_MASK = (GIMP_CONTEXT_FOREGROUND_MASK | GIMP_CONTEXT_BACKGROUND_MASK | GIMP_CONTEXT_OPACITY_MASK | + GIMP_CONTEXT_FLOW_MASK | GIMP_CONTEXT_PAINT_MODE_MASK | GIMP_CONTEXT_BRUSH_MASK | GIMP_CONTEXT_PATTERN_MASK | --- gimp-2.6.6/app/core/gimpbrushgenerated.c 2008-11-21 07:42:58 +0900 +++ gimp-painter--2.6.6-20100627/app/core/gimpbrushgenerated.c 2010-06-27 02:14:18 +0900 @@ -34,8 +34,11 @@ #include "gimpbrushgenerated-save.h" -#define OVERSAMPLING 4 +#define MAX_OVERSAMPLING 32 +#define MIN_OVERSAMPLING 4 /* original value */ +#define OVERSAMPLING (_oversampling) +static gint _oversampling; enum { @@ -348,7 +351,9 @@ gdouble d; gdouble sum; gdouble exponent; - gdouble buffer[OVERSAMPLING]; + gdouble buffer[MAX_OVERSAMPLING]; + + _oversampling = MAX (MAX_OVERSAMPLING - (radius - 0.5), MIN_OVERSAMPLING); length = OVERSAMPLING * ceil (1 + sqrt (2 * SQR (ceil (radius + 1.0)))); --- gimp-2.6.6/app/core/gimpcontext.c 2008-11-21 07:42:58 +0900 +++ gimp-painter--2.6.6-20100627/app/core/gimpcontext.c 2010-06-27 02:14:18 +0900 @@ -145,6 +145,10 @@ static void gimp_context_real_set_opacity (GimpContext *context, gdouble opacity); +/* flow */ +static void gimp_context_real_set_flow (GimpContext *context, + gdouble flow); + /* paint mode */ static void gimp_context_real_set_paint_mode (GimpContext *context, GimpLayerModeEffects paint_mode); @@ -266,6 +270,7 @@ FOREGROUND_CHANGED, BACKGROUND_CHANGED, OPACITY_CHANGED, + FLOW_CHANGED, PAINT_MODE_CHANGED, BRUSH_CHANGED, PATTERN_CHANGED, @@ -289,6 +294,7 @@ "foreground", "background", "opacity", + "flow", "paint-mode", "brush", "pattern", @@ -312,6 +318,7 @@ G_TYPE_NONE, G_TYPE_NONE, G_TYPE_NONE, + G_TYPE_NONE, 0, 0, 0, @@ -421,6 +428,16 @@ G_TYPE_NONE, 1, G_TYPE_DOUBLE); + gimp_context_signals[FLOW_CHANGED] = + g_signal_new ("flow-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpContextClass, flow_changed), + NULL, NULL, + gimp_marshal_VOID__DOUBLE, + G_TYPE_NONE, 1, + G_TYPE_DOUBLE); + gimp_context_signals[PAINT_MODE_CHANGED] = g_signal_new ("paint-mode-changed", G_TYPE_FROM_CLASS (klass), @@ -526,6 +543,7 @@ klass->foreground_changed = NULL; klass->background_changed = NULL; klass->opacity_changed = NULL; + klass->flow_changed = NULL; klass->paint_mode_changed = NULL; klass->brush_changed = NULL; klass->pattern_changed = NULL; @@ -581,13 +599,13 @@ gimp_context_prop_names[GIMP_CONTEXT_PROP_FOREGROUND], NULL, FALSE, &black, - GIMP_PARAM_STATIC_STRINGS); + GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_DONT_RESTORE); GIMP_CONFIG_INSTALL_PROP_RGB (object_class, GIMP_CONTEXT_PROP_BACKGROUND, gimp_context_prop_names[GIMP_CONTEXT_PROP_BACKGROUND], NULL, FALSE, &white, - GIMP_PARAM_STATIC_STRINGS); + GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_DONT_RESTORE); GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, GIMP_CONTEXT_PROP_OPACITY, gimp_context_prop_names[GIMP_CONTEXT_PROP_OPACITY], @@ -597,42 +615,50 @@ GIMP_OPACITY_OPAQUE, GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, GIMP_CONTEXT_PROP_FLOW, + gimp_context_prop_names[GIMP_CONTEXT_PROP_FLOW], + NULL, + GIMP_OPACITY_TRANSPARENT, + GIMP_OPACITY_OPAQUE, + GIMP_OPACITY_OPAQUE, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, GIMP_CONTEXT_PROP_PAINT_MODE, gimp_context_prop_names[GIMP_CONTEXT_PROP_PAINT_MODE], NULL, GIMP_TYPE_LAYER_MODE_EFFECTS, GIMP_NORMAL_MODE, - GIMP_PARAM_STATIC_STRINGS); + GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_DONT_RESTORE_SECONDARY); GIMP_CONFIG_INSTALL_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_BRUSH, gimp_context_prop_names[GIMP_CONTEXT_PROP_BRUSH], NULL, GIMP_TYPE_BRUSH, - GIMP_PARAM_STATIC_STRINGS); + GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_DONT_RESTORE_SECONDARY); GIMP_CONFIG_INSTALL_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_PATTERN, gimp_context_prop_names[GIMP_CONTEXT_PROP_PATTERN], NULL, GIMP_TYPE_PATTERN, - GIMP_PARAM_STATIC_STRINGS); + GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_DONT_RESTORE); GIMP_CONFIG_INSTALL_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_GRADIENT, gimp_context_prop_names[GIMP_CONTEXT_PROP_GRADIENT], NULL, GIMP_TYPE_GRADIENT, - GIMP_PARAM_STATIC_STRINGS); + GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_DONT_RESTORE); GIMP_CONFIG_INSTALL_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_PALETTE, gimp_context_prop_names[GIMP_CONTEXT_PROP_PALETTE], NULL, GIMP_TYPE_PALETTE, - GIMP_PARAM_STATIC_STRINGS); + GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_DONT_RESTORE); GIMP_CONFIG_INSTALL_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_FONT, gimp_context_prop_names[GIMP_CONTEXT_PROP_FONT], NULL, GIMP_TYPE_FONT, - GIMP_PARAM_STATIC_STRINGS); + GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_DONT_RESTORE); g_object_class_install_property (object_class, GIMP_CONTEXT_PROP_BUFFER, g_param_spec_object (gimp_context_prop_names[GIMP_CONTEXT_PROP_BUFFER], @@ -972,6 +998,9 @@ case GIMP_CONTEXT_PROP_OPACITY: gimp_context_set_opacity (context, g_value_get_double (value)); break; + case GIMP_CONTEXT_PROP_FLOW: + gimp_context_set_flow (context, g_value_get_double (value)); + break; case GIMP_CONTEXT_PROP_PAINT_MODE: gimp_context_set_paint_mode (context, g_value_get_enum (value)); break; @@ -1049,6 +1078,9 @@ case GIMP_CONTEXT_PROP_OPACITY: g_value_set_double (value, gimp_context_get_opacity (context)); break; + case GIMP_CONTEXT_PROP_FLOW: + g_value_set_double (value, gimp_context_get_flow (context)); + break; case GIMP_CONTEXT_PROP_PAINT_MODE: g_value_set_enum (value, gimp_context_get_paint_mode (context)); break; @@ -1478,6 +1510,10 @@ gimp_context_real_set_opacity (dest, src->opacity); break; + case GIMP_CONTEXT_PROP_FLOW: + gimp_context_real_set_flow (dest, src->flow); + break; + case GIMP_CONTEXT_PROP_PAINT_MODE: gimp_context_real_set_paint_mode (dest, src->paint_mode); break; @@ -2233,6 +2269,50 @@ gimp_context_opacity_changed (context); } +/*****************************************************************************/ +/* flow ********************************************************************/ + +gdouble +gimp_context_get_flow (GimpContext *context) +{ + g_return_val_if_fail (GIMP_IS_CONTEXT (context), GIMP_OPACITY_OPAQUE); + + return context->flow; +} + +void +gimp_context_set_flow (GimpContext *context, + gdouble flow) +{ + g_return_if_fail (GIMP_IS_CONTEXT (context)); + context_find_defined (context, GIMP_CONTEXT_PROP_FLOW); + + gimp_context_real_set_flow (context, flow); +} + +void +gimp_context_flow_changed (GimpContext *context) +{ + g_return_if_fail (GIMP_IS_CONTEXT (context)); + + g_signal_emit (context, + gimp_context_signals[FLOW_CHANGED], 0, + context->flow); +} + +static void +gimp_context_real_set_flow (GimpContext *context, + gdouble flow) +{ + if (context->flow == flow) + return; + + context->flow = flow; + + g_object_notify (G_OBJECT (context), "flow"); + gimp_context_flow_changed (context); +} + /*****************************************************************************/ /* paint mode **************************************************************/ --- gimp-2.6.6/app/core/gimpcontext.h 2008-11-21 07:42:58 +0900 +++ gimp-painter--2.6.6-20100627/app/core/gimpcontext.h 2010-06-27 02:14:18 +0900 @@ -26,6 +26,11 @@ #include "gimpobject.h" +/* Definitions of special GParamFlags for restoring the tool presets */ +#define GIMP_CONFIG_PARAM_DONT_RESTORE (1 << (6 + G_PARAM_USER_SHIFT)) +#define GIMP_CONFIG_PARAM_DONT_RESTORE_SECONDARY (1 << (7 + G_PARAM_USER_SHIFT)) + + #define GIMP_TYPE_CONTEXT (gimp_context_get_type ()) #define GIMP_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_CONTEXT, GimpContext)) #define GIMP_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST (klass, GIMP_TYPE_CONTEXT, GimpContextClass)) @@ -60,6 +65,7 @@ GimpRGB background; gdouble opacity; + gdouble flow; GimpLayerModeEffects paint_mode; GimpBrush *brush; @@ -107,6 +113,8 @@ GimpRGB *color); void (* opacity_changed) (GimpContext *context, gdouble opacity); + void (* flow_changed) (GimpContext *context, + gdouble flow); void (* paint_mode_changed) (GimpContext *context, GimpLayerModeEffects paint_mode); void (* brush_changed) (GimpContext *context, @@ -244,6 +252,13 @@ void gimp_context_opacity_changed (GimpContext *context); +/* flow */ +gdouble gimp_context_get_flow (GimpContext *context); +void gimp_context_set_flow (GimpContext *context, + gdouble flow); +void gimp_context_flow_changed (GimpContext *context); + + /* paint mode */ GimpLayerModeEffects gimp_context_get_paint_mode (GimpContext *context); --- gimp-2.6.6/app/core/gimpprojection.c 2008-11-21 07:42:58 +0900 +++ gimp-painter--2.6.6-20100627/app/core/gimpprojection.c 2010-06-27 02:14:18 +0900 @@ -36,7 +36,7 @@ /* halfway between G_PRIORITY_HIGH_IDLE and G_PRIORITY_DEFAULT_IDLE */ -#define GIMP_PROJECTION_IDLE_PRIORITY 150 +#define GIMP_PROJECTION_IDLE_PRIORITY G_PRIORITY_HIGH_IDLE enum --- gimp-2.6.6/app/core/gimptooloptions.c 2008-11-21 07:42:58 +0900 +++ gimp-painter--2.6.6-20100627/app/core/gimptooloptions.c 2010-06-27 02:14:18 +0900 @@ -45,7 +45,8 @@ enum { PROP_0, - PROP_TOOL_INFO + PROP_TOOL_INFO, + PROP_MAX_COORD_SMOOTH }; @@ -80,6 +81,10 @@ GIMP_TYPE_TOOL_INFO, GIMP_PARAM_READWRITE)); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_MAX_COORD_SMOOTH, + "max-coord-smooth", NULL, + 0.0, 1.0, 0.0, + GIMP_PARAM_STATIC_STRINGS); } static void @@ -110,6 +115,10 @@ } break; + case PROP_MAX_COORD_SMOOTH: + options->max_coord_smooth = g_value_get_double (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -130,6 +139,10 @@ g_value_set_object (value, options->tool_info); break; + case PROP_MAX_COORD_SMOOTH: + g_value_set_double (value, options->max_coord_smooth); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; --- gimp-2.6.6/app/core/gimptooloptions.h 2008-11-21 07:42:58 +0900 +++ gimp-painter--2.6.6-20100627/app/core/gimptooloptions.h 2010-06-27 02:14:18 +0900 @@ -38,6 +38,8 @@ GimpContext parent_instance; GimpToolInfo *tool_info; + + gdouble max_coord_smooth; }; struct _GimpToolOptionsClass --- gimp-2.6.6/app/dialogs/about-dialog.c 2008-11-21 07:43:00 +0900 +++ gimp-painter--2.6.6-20100627/app/dialogs/about-dialog.c 2010-06-27 02:14:18 +0900 @@ -597,9 +597,9 @@ static void about_dialog_add_message (GtkWidget *vbox) { -#ifdef GIMP_UNSTABLE GtkWidget *label; +#ifdef GIMP_UNSTABLE label = gtk_label_new (_("This is an unstable development release.")); gimp_label_set_attributes (GTK_LABEL (label), PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC, @@ -608,5 +608,10 @@ gtk_box_reorder_child (GTK_BOX (vbox), label, 2); gtk_widget_show (label); #endif + + label = gtk_label_new (_("gimp-painter- (release 20100627)")); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + gtk_box_reorder_child (GTK_BOX (vbox), label, 2); + gtk_widget_show (label); } --- gimp-2.6.6/app/dialogs/preferences-dialog.c 2008-12-28 08:13:03 +0900 +++ gimp-painter--2.6.6-20100627/app/dialogs/preferences-dialog.c 2010-06-27 02:14:18 +0900 @@ -1978,6 +1978,11 @@ vbox2 = prefs_frame_new (_("Appearance"), GTK_CONTAINER (vbox), FALSE); + prefs_check_button_add_with_icon (object, "toolbox-wilber", + _("Show _Wilber"), + GIMP_STOCK_WILBER, + GTK_BOX (vbox2), size_group); + prefs_check_button_add_with_icon (object, "toolbox-color-area", _("Show _foreground & background color"), GIMP_STOCK_DEFAULT_COLORS, @@ -2412,6 +2417,14 @@ g_object_unref (size_group); size_group = NULL; + /* Zoom Quality */ + vbox2 = prefs_frame_new (_("Zoomed-out View"), GTK_CONTAINER (vbox), FALSE); + table = prefs_table_new (1, GTK_CONTAINER (vbox2)); + + prefs_enum_combo_box_add (object, "zoom-quality", 0, 0, + _("_Quality:"), + GTK_TABLE (table), 0, NULL); + /**********************/ /* Color Management */ @@ -2636,7 +2649,7 @@ _("Hint for other _docks:"), GTK_TABLE (table), 1, size_group); -#ifdef GIMP_UNSTABLE +#if 1 prefs_check_button_add (object, "transient-docks", _("Toolbox and other docks are transient " "to the active image window"), --- gimp-2.6.6/app/display/gimpdisplayshell-callbacks.c 2008-11-21 07:43:04 +0900 +++ gimp-painter--2.6.6-20100627/app/display/gimpdisplayshell-callbacks.c 2010-06-27 02:14:18 +0900 @@ -41,6 +41,7 @@ #include "core/gimpimage-quick-mask.h" #include "core/gimplayer.h" #include "core/gimptoolinfo.h" +#include "core/gimptooloptions.h" #include "tools/gimpimagemaptool.h" #include "tools/gimpmovetool.h" @@ -1201,6 +1202,11 @@ { GdkTimeCoord **history_events; gint n_history_events; + gdouble max_coord_smooth = 0; + GimpToolOptions *active_tool_options; + + if ((active_tool_options = GIMP_TOOL_GET_OPTIONS (active_tool))) + max_coord_smooth = active_tool_options->max_coord_smooth; /* if the first mouse button is down, check for automatic * scrolling... @@ -1262,7 +1268,7 @@ */ if (gimp_display_shell_eval_event (shell, &image_coords, - active_tool->max_coord_smooth, + max_coord_smooth, history_events[i]->time)) { tool_manager_motion_active (gimp, @@ -1283,7 +1289,7 @@ */ if (gimp_display_shell_eval_event (shell, &image_coords, - active_tool->max_coord_smooth, + max_coord_smooth, time)) { tool_manager_motion_active (gimp, --- gimp-2.6.6/app/paint/Makefile.am 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/Makefile.am 2010-06-27 02:14:18 +0900 @@ -76,7 +76,17 @@ gimpsourcecore.c \ gimpsourcecore.h \ gimpsourceoptions.c \ - gimpsourceoptions.h + gimpsourceoptions.h \ + gimpink2.c \ + gimpink2.h \ + gimpink2undo.c \ + gimpink2undo.h \ + gimpink2options.c \ + gimpink2options.h \ + gimpmixbrush.c \ + gimpmixbrush.h \ + gimpmixbrushoptions.c \ + gimpmixbrushoptions.h libapppaint_a_built_sources = paint-enums.c --- gimp-2.6.6/app/paint/Makefile.in 2009-03-16 05:58:04 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/Makefile.in 2010-06-27 02:14:18 +0900 @@ -66,7 +66,9 @@ gimppaintbrush.$(OBJEXT) gimpperspectiveclone.$(OBJEXT) \ gimpperspectivecloneoptions.$(OBJEXT) gimpsmudge.$(OBJEXT) \ gimpsmudgeoptions.$(OBJEXT) gimpsourcecore.$(OBJEXT) \ - gimpsourceoptions.$(OBJEXT) + gimpsourceoptions.$(OBJEXT) \ + gimpink2.$(OBJEXT) gimpink2options.$(OBJEXT) gimpink2undo.$(OBJEXT) \ + gimpmixbrush.$(OBJEXT) gimpmixbrushoptions.$(OBJEXT) am_libapppaint_a_OBJECTS = $(am__objects_1) $(am__objects_2) libapppaint_a_OBJECTS = $(am_libapppaint_a_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) @@ -475,7 +477,17 @@ gimpsourcecore.c \ gimpsourcecore.h \ gimpsourceoptions.c \ - gimpsourceoptions.h + gimpsourceoptions.h \ + gimpink2.c \ + gimpink2.h \ + gimpink2options.c \ + gimpink2options.h \ + gimpink2undo.c \ + gimpink2undo.h \ + gimpmixbrush.c \ + gimpmixbrush.h \ + gimpmixbrushoptions.c \ + gimpmixbrushoptions.h libapppaint_a_built_sources = paint-enums.c libapppaint_a_SOURCES = $(libapppaint_a_built_sources) $(libapppaint_a_sources) @@ -565,6 +577,11 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpsourcecore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpsourceoptions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/paint-enums.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpink2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpink2options.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpink2undo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpmixbrush.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpmixbrushoptions.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< --- gimp-2.6.6/app/paint/gimp-paint.c 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimp-paint.c 2010-06-27 02:14:18 +0900 @@ -39,6 +39,8 @@ #include "gimppencil.h" #include "gimpperspectiveclone.h" #include "gimpsmudge.h" +#include "gimpink2.h" +#include "gimpmixbrush.h" /* local function prototypes */ @@ -68,7 +70,9 @@ gimp_airbrush_register, gimp_eraser_register, gimp_paintbrush_register, - gimp_pencil_register + gimp_pencil_register, + gimp_ink2_register, + gimp_mixbrush_register }; gint i; --- gimp-2.6.6/app/paint/gimpbrushcore.c 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpbrushcore.c 2010-06-27 02:14:18 +0900 @@ -828,11 +828,13 @@ gimp_brush_core_paste_canvas (GimpBrushCore *core, GimpDrawable *drawable, gdouble brush_opacity, + gdouble brush_flow, gdouble image_opacity, GimpLayerModeEffects paint_mode, GimpBrushApplicationMode brush_hardness, gdouble dynamic_hardness, - GimpPaintApplicationMode mode) + GimpPaintApplicationMode mode, + GimpUpdateFreqOptions *update_freq_options) { TempBuf *brush_mask = gimp_brush_core_get_brush_mask (core, brush_hardness, @@ -859,9 +861,9 @@ paint_core->canvas_buf->height); gimp_paint_core_paste (paint_core, &brush_maskPR, drawable, - brush_opacity, + brush_opacity, brush_flow, image_opacity, paint_mode, - mode); + mode, update_freq_options); } } @@ -876,7 +878,8 @@ gdouble image_opacity, GimpBrushApplicationMode brush_hardness, gdouble dynamic_hardness, - GimpPaintApplicationMode mode) + GimpPaintApplicationMode mode, + GimpUpdateFreqOptions *update_freq_options) { TempBuf *brush_mask = gimp_brush_core_get_brush_mask (core, brush_hardness, @@ -905,7 +908,7 @@ gimp_paint_core_replace (paint_core, &brush_maskPR, drawable, brush_opacity, image_opacity, - mode); + mode, update_freq_options); } } --- gimp-2.6.6/app/paint/gimpbrushcore.h 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpbrushcore.h 2010-06-27 02:14:18 +0900 @@ -108,18 +108,21 @@ void gimp_brush_core_paste_canvas (GimpBrushCore *core, GimpDrawable *drawable, gdouble brush_opacity, + gdouble brush_flow, gdouble image_opacity, GimpLayerModeEffects paint_mode, GimpBrushApplicationMode brush_hardness, gdouble dynamic_hardness, - GimpPaintApplicationMode mode); + GimpPaintApplicationMode mode, + GimpUpdateFreqOptions *update_freq_options); void gimp_brush_core_replace_canvas (GimpBrushCore *core, GimpDrawable *drawable, gdouble brush_opacity, gdouble image_opacity, GimpBrushApplicationMode brush_hardness, gdouble dynamic_hardness, - GimpPaintApplicationMode mode); + GimpPaintApplicationMode mode, + GimpUpdateFreqOptions *update_freq_options); void gimp_brush_core_color_area_with_pixmap (GimpBrushCore *core, --- gimp-2.6.6/app/paint/gimpclone.c 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpclone.c 2010-06-27 02:14:18 +0900 @@ -244,6 +244,7 @@ gimp_brush_core_paste_canvas (GIMP_BRUSH_CORE (paint_core), drawable, MIN (opacity, GIMP_OPACITY_OPAQUE), + GIMP_OPACITY_OPAQUE, gimp_context_get_opacity (context), gimp_context_get_paint_mode (context), gimp_paint_options_get_brush_mode (paint_options), @@ -257,7 +258,8 @@ */ source_options->align_mode == GIMP_SOURCE_ALIGN_FIXED ? - GIMP_PAINT_INCREMENTAL : GIMP_PAINT_CONSTANT); + GIMP_PAINT_INCREMENTAL : GIMP_PAINT_CONSTANT, + paint_options->update_freq_options); } static void --- gimp-2.6.6/app/paint/gimpconvolve.c 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpconvolve.c 2010-06-27 02:14:18 +0900 @@ -211,7 +211,8 @@ gimp_context_get_opacity (context), gimp_paint_options_get_brush_mode (paint_options), 1.0, - GIMP_PAINT_INCREMENTAL); + GIMP_PAINT_INCREMENTAL, + paint_options->update_freq_options); } static void --- gimp-2.6.6/app/paint/gimpdodgeburn.c 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpdodgeburn.c 2010-06-27 02:14:18 +0900 @@ -248,7 +248,8 @@ gimp_context_get_opacity (context), gimp_paint_options_get_brush_mode (paint_options), hardness, - GIMP_PAINT_CONSTANT); + GIMP_PAINT_CONSTANT, + paint_options->update_freq_options); } static void --- gimp-2.6.6/app/paint/gimperaser.c 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimperaser.c 2010-06-27 02:14:18 +0900 @@ -139,10 +139,12 @@ gimp_brush_core_paste_canvas (GIMP_BRUSH_CORE (paint_core), drawable, MIN (opacity, GIMP_OPACITY_OPAQUE), + GIMP_OPACITY_OPAQUE, gimp_context_get_opacity (context), (options->anti_erase ? GIMP_ANTI_ERASE_MODE : GIMP_ERASE_MODE), gimp_paint_options_get_brush_mode (paint_options), hardness, - paint_options->application_mode); + paint_options->application_mode, + paint_options->update_freq_options); } --- gimp-2.6.6/app/paint/gimpheal.c 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpheal.c 2010-06-27 02:14:18 +0900 @@ -555,5 +555,6 @@ gimp_context_get_opacity (context), gimp_paint_options_get_brush_mode (paint_options), hardness, - GIMP_PAINT_INCREMENTAL); + GIMP_PAINT_INCREMENTAL, + paint_options->update_freq_options); } --- gimp-2.6.6/app/paint/gimpink.c 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpink.c 2010-06-27 02:14:18 +0900 @@ -327,9 +327,11 @@ gimp_paint_core_paste (paint_core, &blob_maskPR, drawable, GIMP_OPACITY_OPAQUE, + GIMP_OPACITY_OPAQUE, gimp_context_get_opacity (context), gimp_context_get_paint_mode (context), - GIMP_PAINT_CONSTANT); + GIMP_PAINT_CONSTANT, + paint_options->update_freq_options); if (blob_union) g_free (blob_union); --- gimp-2.6.6/app/paint/gimpink2.c 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpink2.c 2010-06-27 02:14:18 +0900 @@ -0,0 +1,918 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include + +#include "libgimpmath/gimpmath.h" + +#include "paint-types.h" + +#include "base/pixel-region.h" +#include "base/temp-buf.h" +#include "base/tile.h" +#include "base/tile-manager.h" + +#include "paint-funcs/paint-funcs.h" + +#include "core/gimpdrawable.h" +#include "core/gimpimage.h" +#include "core/gimpimage-undo.h" + +#include "gimpink2options.h" +#include "gimpink2.h" +#include "gimpink-blob.h" +#include "gimpink2undo.h" + +#include "gimp-intl.h" + + +#define SUBSAMPLE 8 + + +/* local function prototypes */ + +static void gimp_ink2_finalize (GObject *object); + +static void gimp_ink2_paint (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpPaintState paint_state, + guint32 time); +static TempBuf * gimp_ink2_get_paint_area (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options); +static GimpUndo* gimp_ink2_push_undo (GimpPaintCore *core, + GimpImage *image, + const gchar *undo_desc); + +static void gimp_ink2_motion (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + guint32 time, + gboolean at_last); + +static Blob * ink2_pen_ellipse (GimpInk2Options *options, + gdouble x_center, + gdouble y_center, + gdouble pressure, + gdouble xtilt, + gdouble ytilt, + gdouble velocity); + +static void time_smoother_add (GimpInk2 *ink, + guint32 value); +static guint32 time_smoother_result (GimpInk2 *ink); +static void time_smoother_init (GimpInk2 *ink, + guint32 initval); + +static void dist_smoother_add (GimpInk2 *ink, + gdouble value); +static gdouble dist_smoother_result (GimpInk2 *ink); +static void dist_smoother_init (GimpInk2 *ink, + gdouble initval); + +static void render_blob (Blob *blob, + PixelRegion *dest); + +/* Ink2 additional functions */ +static void hist_init (GimpInk2 *ink, GimpCoords* coords); +static void hist_add (GimpInk2 *ink, GimpCoords* coords, gdouble speed); +static GimpCoords hist_result (GimpInk2 *ink, GimpInk2Options *options); + +static gdouble PI; +/* */ + + +G_DEFINE_TYPE (GimpInk2, gimp_ink2, GIMP_TYPE_PAINT_CORE) + +#define parent_class gimp_ink2_parent_class + + +void +gimp_ink2_register (Gimp *gimp, + GimpPaintRegisterCallback callback) +{ + (* callback) (gimp, + GIMP_TYPE_INK2, + GIMP_TYPE_INK2_OPTIONS, + "gimp-ink2", + _("G-pen"), + "gimp-tool-ink2"); +} + +static void +gimp_ink2_class_init (GimpInk2Class *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GimpPaintCoreClass *paint_core_class = GIMP_PAINT_CORE_CLASS (klass); + + object_class->finalize = gimp_ink2_finalize; + + paint_core_class->paint = gimp_ink2_paint; + paint_core_class->get_paint_area = gimp_ink2_get_paint_area; + paint_core_class->push_undo = gimp_ink2_push_undo; + + /* initialize internal variables */ + PI = 4 * atan(1); +} + +static void +gimp_ink2_init (GimpInk2 *ink) +{ +} + +static void +gimp_ink2_finalize (GObject *object) +{ + GimpInk2 *ink = GIMP_INK2 (object); + + if (ink->start_blob) + { + g_free (ink->start_blob); + ink->start_blob = NULL; + } + + if (ink->last_blob) + { + g_free (ink->last_blob); + ink->last_blob = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gimp_ink2_paint (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpPaintState paint_state, + guint32 time) +{ + GimpInk2 *ink = GIMP_INK2 (paint_core); + + switch (paint_state) + { + case GIMP_PAINT_STATE_INIT: + if (paint_core->cur_coords.x == paint_core->last_coords.x && + paint_core->cur_coords.y == paint_core->last_coords.y) + { + /* start with new blobs if we're not interpolating */ + + if (ink->start_blob) + { + g_free (ink->start_blob); + ink->start_blob = NULL; + } + + if (ink->last_blob) + { + g_free (ink->last_blob); + ink->last_blob = NULL; + } + } + else if (ink->last_blob) + { + /* save the start blob of the line for undo otherwise */ + + if (ink->start_blob) + g_free (ink->start_blob); + + ink->start_blob = blob_duplicate (ink->last_blob); + } + break; + + case GIMP_PAINT_STATE_MOTION: + gimp_ink2_motion (paint_core, drawable, paint_options, time, FALSE); + break; + + case GIMP_PAINT_STATE_FINISH: + gimp_ink2_motion (paint_core, drawable, paint_options, time, TRUE); + /*g_printf("\n");*/ + break; + } +} + +static TempBuf * +gimp_ink2_get_paint_area (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options) +{ + GimpInk2 *ink = GIMP_INK2 (paint_core); + gint x, y; + gint width, height; + gint dwidth, dheight; + gint x1, y1, x2, y2; + gint bytes; + + bytes = gimp_drawable_bytes_with_alpha (drawable); + + blob_bounds (ink->cur_blob, &x, &y, &width, &height); + + dwidth = gimp_item_width (GIMP_ITEM (drawable)); + dheight = gimp_item_height (GIMP_ITEM (drawable)); + + x1 = CLAMP (x / SUBSAMPLE - 1, 0, dwidth); + y1 = CLAMP (y / SUBSAMPLE - 1, 0, dheight); + x2 = CLAMP ((x + width) / SUBSAMPLE + 2, 0, dwidth); + y2 = CLAMP ((y + height) / SUBSAMPLE + 2, 0, dheight); + + /* configure the canvas buffer */ + if ((x2 - x1) && (y2 - y1)) + paint_core->canvas_buf = temp_buf_resize (paint_core->canvas_buf, bytes, + x1, y1, + (x2 - x1), (y2 - y1)); + else + return NULL; + + return paint_core->canvas_buf; +} + +static GimpUndo * +gimp_ink2_push_undo (GimpPaintCore *core, + GimpImage *image, + const gchar *undo_desc) +{ + return gimp_image_undo_push (image, GIMP_TYPE_INK2_UNDO, + GIMP_UNDO_INK, undo_desc, + 0, + "paint-core", core, + NULL); +} + +static void +gimp_ink2_motion (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + guint32 time, + gboolean at_last) +{ + GimpInk2 *ink = GIMP_INK2 (paint_core); + GimpInk2Options *options = GIMP_INK2_OPTIONS (paint_options); + GimpContext *context = GIMP_CONTEXT (paint_options); + GimpImage *image; + Blob *blob_union = NULL; + Blob *blob_to_render; + TempBuf *area; + guchar col[MAX_CHANNELS]; + PixelRegion blob_maskPR; + + if (at_last && !options->compensate_at_last) + return; + + image = gimp_item_get_image (GIMP_ITEM (drawable)); + + if (! ink->last_blob) + { + ink->last_blob = ink2_pen_ellipse (options, + paint_core->cur_coords.x, + paint_core->cur_coords.y, + paint_core->cur_coords.pressure, + paint_core->cur_coords.xtilt, + paint_core->cur_coords.ytilt, + 10.0); + + if (ink->start_blob) + g_free (ink->start_blob); + + ink->start_blob = blob_duplicate (ink->last_blob); + + time_smoother_init (ink, time); + ink->last_time = time; + + dist_smoother_init (ink, 0.0); + ink->init_velocity = TRUE; + + hist_init (ink, &paint_core->cur_coords); + + blob_to_render = ink->last_blob; + } + else + { + Blob *blob; + gdouble dist; + gdouble velocity; + guint32 lasttime = ink->last_time; + guint32 thistime; + GimpCoords average_hist; + GimpCoords average_velocity; + + time_smoother_add (ink, time); + thistime = ink->last_time = time_smoother_result (ink); + + /* The time resolution on X-based GDK motion events is bloody + * awful, hence the use of the smoothing function. Sadly this + * also means that there is always the chance of having an + * indeterminite velocity since this event and the previous + * several may still appear to issue at the same + * instant. -ADM + */ + if (thistime == lasttime) + thistime = lasttime + 1; + + dist = sqrt ((paint_core->last_coords.x - paint_core->cur_coords.x) * + (paint_core->last_coords.x - paint_core->cur_coords.x) + + (paint_core->last_coords.y - paint_core->cur_coords.y) * + (paint_core->last_coords.y - paint_core->cur_coords.y)); + + if (ink->init_velocity) + { + dist_smoother_init (ink, dist); + ink->init_velocity = FALSE; + } + else + { + dist_smoother_add (ink, dist); + dist = dist_smoother_result (ink); + } + + velocity = 10.0 * sqrt ((dist) / (gdouble) (thistime - lasttime)); + + /* g_printf("%f, %f, %f\n", paint_core->cur_coords.x, paint_core->cur_coords.y, velocity); */ + + if (!at_last && options->compensation_hist_size > 1) + { + hist_add(ink, &paint_core->cur_coords, velocity); + average_hist = hist_result(ink, options); + blob = ink2_pen_ellipse (options, + average_hist.x, + average_hist.y, + paint_core->cur_coords.pressure, + paint_core->cur_coords.xtilt, + paint_core->cur_coords.ytilt, + velocity); + ink->last_point = average_hist; + } + else + { + blob = ink2_pen_ellipse (options, + paint_core->cur_coords.x, + paint_core->cur_coords.y, + paint_core->cur_coords.pressure, + paint_core->cur_coords.xtilt, + paint_core->cur_coords.ytilt, + velocity); + } + + blob_union = blob_convex_union (ink->last_blob, blob); + g_free (ink->last_blob); + ink->last_blob = blob; + + blob_to_render = blob_union; + } + + /* Get the buffer */ + ink->cur_blob = blob_to_render; + area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options); + ink->cur_blob = NULL; + + if (! area) + return; + + gimp_image_get_foreground (image, context, gimp_drawable_type (drawable), col); + + /* set the alpha channel */ + col[paint_core->canvas_buf->bytes - 1] = OPAQUE_OPACITY; + + /* color the pixels */ + color_pixels (temp_buf_data (paint_core->canvas_buf), col, + area->width * area->height, area->bytes); + + gimp_paint_core_validate_canvas_tiles (paint_core, + paint_core->canvas_buf->x, + paint_core->canvas_buf->y, + paint_core->canvas_buf->width, + paint_core->canvas_buf->height); + + /* draw the blob directly to the canvas_tiles */ + pixel_region_init (&blob_maskPR, paint_core->canvas_tiles, + paint_core->canvas_buf->x, + paint_core->canvas_buf->y, + paint_core->canvas_buf->width, + paint_core->canvas_buf->height, + TRUE); + + render_blob (blob_to_render, &blob_maskPR); + + /* draw the canvas_buf using the just rendered canvas_tiles as mask */ + pixel_region_init (&blob_maskPR, paint_core->canvas_tiles, + paint_core->canvas_buf->x, + paint_core->canvas_buf->y, + paint_core->canvas_buf->width, + paint_core->canvas_buf->height, + FALSE); + + gimp_paint_core_paste (paint_core, &blob_maskPR, drawable, + GIMP_OPACITY_OPAQUE, + GIMP_OPACITY_OPAQUE, + gimp_context_get_opacity (context), + gimp_context_get_paint_mode (context), + GIMP_PAINT_CONSTANT, + paint_options->update_freq_options); + + if (blob_union) + g_free (blob_union); +} + +static Blob * +ink2_pen_ellipse (GimpInk2Options *options, + gdouble x_center, + gdouble y_center, + gdouble pressure, + gdouble xtilt, + gdouble ytilt, + gdouble velocity) +{ + BlobFunc blob_function; + gdouble size; + gdouble tsin, tcos; + gdouble aspect, radmin; + gdouble x,y; + gdouble tscale; + gdouble tscale_c; + gdouble tscale_s; + + /* Adjust the size depending on pressure. */ + + size = options->size * (1.0 + options->size_sensitivity * + (2.0 * pressure - 1.0)); + + /* Adjust the size further depending on pointer velocity and + * velocity-sensitivity. These 'magic constants' are 'feels + * natural' tigert-approved. --ADM + */ + + if (velocity < 3.0) + velocity = 3.0; + +#ifdef VERBOSE + g_printerr ("%g (%g) -> ", size, velocity); +#endif + + size = (options->vel_sensitivity * + ((4.5 * size) / (1.0 + options->vel_sensitivity * (2.0 * velocity))) + + (1.0 - options->vel_sensitivity) * size); + +#ifdef VERBOSE + g_printerr ("%g\n", (gfloat) size); +#endif + + /* Clamp resulting size to sane limits */ + + if (size > options->size * (1.0 + options->size_sensitivity)) + size = options->size * (1.0 + options->size_sensitivity); + + if (size * SUBSAMPLE < 1.0) + size = 1.0 / SUBSAMPLE; + + /* Add brush angle/aspect to tilt vectorially */ + + /* I'm not happy with the way the brush widget info is combined with + * tilt info from the brush. My personal feeling is that + * representing both as affine transforms would make the most + * sense. -RLL + */ + + tscale = options->tilt_sensitivity * 10.0; + tscale_c = tscale * cos (gimp_deg_to_rad (options->tilt_angle)); + tscale_s = tscale * sin (gimp_deg_to_rad (options->tilt_angle)); + + x = (options->blob_aspect * cos (options->blob_angle) + + xtilt * tscale_c - ytilt * tscale_s); + y = (options->blob_aspect * sin (options->blob_angle) + + ytilt * tscale_c + xtilt * tscale_s); + +#ifdef VERBOSE + g_printerr ("angle %g aspect %g; %g %g; %g %g\n", + options->blob_angle, options->blob_aspect, + tscale_c, tscale_s, x, y); +#endif + + aspect = sqrt (x * x + y * y); + + if (aspect != 0) + { + tcos = x / aspect; + tsin = y / aspect; + } + else + { + tsin = sin (options->blob_angle); + tcos = cos (options->blob_angle); + } + + aspect = CLAMP (aspect, 1.0, 10.0); + + radmin = MAX (1.0, SUBSAMPLE * size / aspect); + + switch (options->blob_type) + { + case GIMP_INK_BLOB_TYPE_ELLIPSE: + blob_function = blob_ellipse; + break; + + case GIMP_INK_BLOB_TYPE_SQUARE: + blob_function = blob_square; + break; + + case GIMP_INK_BLOB_TYPE_DIAMOND: + blob_function = blob_diamond; + break; + + default: + g_return_val_if_reached (NULL); + break; + } + + return (* blob_function) (x_center * SUBSAMPLE, + y_center * SUBSAMPLE, + radmin * aspect * tcos, + radmin * aspect * tsin, + -radmin * tsin, + radmin * tcos); +} + + +static void +time_smoother_init (GimpInk2 *ink, + guint32 initval) +{ + gint i; + + ink->ts_index = 0; + + for (i = 0; i < INK2_TIME_SMOOTHER_BUFFER; i++) + ink->ts_buffer[i] = initval; +} + +static guint32 +time_smoother_result (GimpInk2 *ink) +{ + gint i; + guint64 result = 0; + + for (i = 0; i < INK2_TIME_SMOOTHER_BUFFER; i++) + result += ink->ts_buffer[i]; + + return (result / (guint64) INK2_TIME_SMOOTHER_BUFFER); +} + +static void +time_smoother_add (GimpInk2 *ink, + guint32 value) +{ + guint64 long_value = (guint64) value; + + /* handle wrap-around of time values */ + if (long_value < ink->ts_buffer[ink->ts_index]) + long_value += (guint64) + G_MAXUINT32; + + ink->ts_buffer[ink->ts_index++] = long_value; + + ink->ts_buffer[ink->ts_index++] = value; + + if (ink->ts_index == INK2_TIME_SMOOTHER_BUFFER) + ink->ts_index = 0; +} + + +static void +dist_smoother_init (GimpInk2 *ink, + gdouble initval) +{ + gint i; + + ink->dt_index = 0; + + for (i = 0; i < INK2_DIST_SMOOTHER_BUFFER; i++) + ink->dt_buffer[i] = initval; +} + +static gdouble +dist_smoother_result (GimpInk2 *ink) +{ + gint i; + gdouble result = 0.0; + + for (i = 0; i < INK2_DIST_SMOOTHER_BUFFER; i++) + result += ink->dt_buffer[i]; + + return (result / (gdouble) INK2_DIST_SMOOTHER_BUFFER); +} + +static void +dist_smoother_add (GimpInk2 *ink, + gdouble value) +{ + ink->dt_buffer[ink->dt_index++] = value; + + if (ink->dt_index == INK2_DIST_SMOOTHER_BUFFER) + ink->dt_index = 0; +} + +/**************************************************************/ + +static void +hist_init(GimpInk2 * ink, GimpCoords* coords) +{ + ink->hist_index = 0; + ink->hist_count = 0; + if (coords) + hist_add(ink, coords, 0); +} + +#define HIST_IGNORE_THRESHOULD 0.0001 + +static void +hist_add(GimpInk2 *ink, GimpCoords* coords, gdouble speed) +{ + gdouble dist = 0; + if (coords) { + if (ink->hist_count > 0) { + gint prev_index = (ink->hist_index + INK2_HISTORY_BUFFER - 1) % INK2_HISTORY_BUFFER; + gdouble dist_x = coords->x - ink->hist_buffer[prev_index].x; + gdouble dist_y = coords->y - ink->hist_buffer[prev_index].y; + dist = sqrt(dist_x * dist_x + dist_y * dist_y); + if (dist < HIST_IGNORE_THRESHOULD) + return; + } + ink->hist_buffer[ink->hist_index] = *coords; + ink->hist_dist_buffer[ink->hist_index] = speed; + ink->hist_index ++; + + if (ink->hist_count < INK2_HISTORY_BUFFER) + ink->hist_count ++; + + if (ink->hist_index == INK2_HISTORY_BUFFER) + ink->hist_index = 0; + } +} + +static GimpCoords +hist_result(GimpInk2 *ink, GimpInk2Options* options) +{ + gint i; + GimpCoords result; + result.x = result.y = 0.0; + gdouble scale_sum = 0.0; + + if (ink->hist_count > 0) { + gint max_hist_count = MIN(ink->hist_count, options->compensation_hist_size); + gint cur_index = (ink->hist_index + INK2_HISTORY_BUFFER - 1) % INK2_HISTORY_BUFFER; + + gdouble gaussian_weight = 0.0; + gdouble gaussian_weight2 = SQR (options->compensation_rate_temperature); + gdouble velocity_sum = 0.0; + + if (gaussian_weight2 != 0.0) + gaussian_weight = 1 / (sqrt (2 * PI) * options->compensation_rate_temperature); + + for (i = 0; i < max_hist_count; i ++, cur_index --) + { + gdouble rate = 0; + if (cur_index == -1) + cur_index = INK2_HISTORY_BUFFER - 1; + + if (gaussian_weight2 != 0) + { + /* We use gaussian function with velocity as a window function */ + velocity_sum += ink->hist_dist_buffer[cur_index]; + rate = gaussian_weight * exp (-velocity_sum*velocity_sum / (2 * gaussian_weight2)); + /* If i == 0 && rate == 0.0, resulting value becomes zero. + * To avoid this, we treat this as a special case. + */ + if (i == 0 && rate == 0.0) + rate = 1.0; + } + else + { + rate = (i == 0) ? 1.0 : 0.0; + } + scale_sum += rate; + result.x += rate * ink->hist_buffer[cur_index].x; + result.y += rate * ink->hist_buffer[cur_index].y; + } + + if (scale_sum != 0.0) + { + result.x /= scale_sum; + result.y /= scale_sum; + } + } + return result; +} + +/**************************************************************/ + +/*********************************/ +/* Rendering functions */ +/*********************************/ + +/* Some of this stuff should probably be combined with the + * code it was copied from in paint_core.c; but I wanted + * to learn this stuff, so I've kept it simple. + * + * The following only supports CONSTANT mode. Incremental + * would, I think, interact strangely with the way we + * do things. But it wouldn't be hard to implement at all. + */ + +enum { ROW_START, ROW_STOP }; + +/* The insertion sort here, for SUBSAMPLE = 8, tends to beat out + * qsort() by 4x with CFLAGS=-O2, 2x with CFLAGS=-g + */ +static void +insert_sort (gint *data, + gint n) +{ + gint i, j, k; + gint tmp1, tmp2; + + for (i = 2; i < 2 * n; i += 2) + { + tmp1 = data[i]; + tmp2 = data[i + 1]; + j = 0; + while (data[j] < tmp1) + j += 2; + + for (k = i; k > j; k -= 2) + { + data[k] = data[k - 2]; + data[k + 1] = data[k - 1]; + } + + data[j] = tmp1; + data[j + 1] = tmp2; + } +} + +static void +fill_run (guchar *dest, + guchar alpha, + gint w) +{ + if (alpha == 255) + { + memset (dest, 255, w); + } + else + { + while (w--) + { + *dest = MAX (*dest, alpha); + dest++; + } + } +} + +static void +render_blob_line (Blob *blob, + guchar *dest, + gint x, + gint y, + gint width) +{ + gint buf[4 * SUBSAMPLE]; + gint *data = buf; + gint n = 0; + gint i, j; + gint current = 0; /* number of filled rows at this point + * in the scan line + */ + gint last_x; + + /* Sort start and ends for all lines */ + + j = y * SUBSAMPLE - blob->y; + for (i = 0; i < SUBSAMPLE; i++) + { + if (j >= blob->height) + break; + + if ((j > 0) && (blob->data[j].left <= blob->data[j].right)) + { + data[2 * n] = blob->data[j].left; + data[2 * n + 1] = ROW_START; + data[2 * SUBSAMPLE + 2 * n] = blob->data[j].right; + data[2 * SUBSAMPLE + 2 * n + 1] = ROW_STOP; + n++; + } + j++; + } + + /* If we have less than SUBSAMPLE rows, compress */ + if (n < SUBSAMPLE) + { + for (i = 0; i < 2 * n; i++) + data[2 * n + i] = data[2 * SUBSAMPLE + i]; + } + + /* Now count start and end separately */ + n *= 2; + + insert_sort (data, n); + + /* Discard portions outside of tile */ + + while ((n > 0) && (data[0] < SUBSAMPLE*x)) + { + if (data[1] == ROW_START) + current++; + else + current--; + data += 2; + n--; + } + + while ((n > 0) && (data[2*(n-1)] >= SUBSAMPLE*(x+width))) + n--; + + /* Render the row */ + + last_x = 0; + for (i = 0; i < n;) + { + gint cur_x = data[2 * i] / SUBSAMPLE - x; + gint pixel; + + /* Fill in portion leading up to this pixel */ + if (current && cur_x != last_x) + fill_run (dest + last_x, (255 * current) / SUBSAMPLE, cur_x - last_x); + + /* Compute the value for this pixel */ + pixel = current * SUBSAMPLE; + + while (ih; + s = dest->data; + + for (i=0; ix, dest->y + i, dest->w); + s += dest->rowstride; + } + } +} --- gimp-2.6.6/app/paint/gimpink2.h 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpink2.h 2010-06-27 02:14:18 +0900 @@ -0,0 +1,83 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __GIMP_INK2_H__ +#define __GIMP_INK2_H__ + + +#include "gimppaintcore.h" +#include "gimpink-blob.h" + + +#define INK2_DIST_SMOOTHER_BUFFER 10 +#define INK2_TIME_SMOOTHER_BUFFER 10 +#define INK2_HISTORY_BUFFER 20 + + +#define GIMP_TYPE_INK2 (gimp_ink2_get_type ()) +#define GIMP_INK2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_INK2, GimpInk2)) +#define GIMP_INK2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_INK2, GimpInk2Class)) +#define GIMP_IS_INK2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_INK2)) +#define GIMP_IS_INK2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_INK2)) +#define GIMP_INK2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_INK2, GimpInk2Class)) + + +typedef struct _GimpInk2Class GimpInk2Class; + +struct _GimpInk2 +{ + GimpPaintCore parent_instance; + + Blob *start_blob; /* starting blob (for undo) */ + + Blob *cur_blob; /* current blob */ + Blob *last_blob; /* blob for last cursor position */ + + /* circular distance history buffer */ + gdouble dt_buffer[INK2_DIST_SMOOTHER_BUFFER]; + gint dt_index; + + /* circular timing history buffer */ + guint32 ts_buffer[INK2_TIME_SMOOTHER_BUFFER]; + gint ts_index; + + GimpCoords hist_buffer[INK2_HISTORY_BUFFER]; + gdouble hist_dist_buffer[INK2_HISTORY_BUFFER]; + gint hist_index; + gint hist_count; + + guint32 last_time; /* previous time of a motion event */ + + GimpCoords last_point; /* last compensated position */ + + gboolean init_velocity; +}; + +struct _GimpInk2Class +{ + GimpPaintCoreClass parent_class; +}; + + +void gimp_ink2_register (Gimp *gimp, + GimpPaintRegisterCallback callback); + +GType gimp_ink2_get_type (void) G_GNUC_CONST; + + +#endif /* __GIMP_INK2_H__ */ --- gimp-2.6.6/app/paint/gimpink2options.c 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpink2options.c 2010-06-27 02:14:18 +0900 @@ -0,0 +1,245 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include "libgimpconfig/gimpconfig.h" + +#include "paint-types.h" + +#include "core/gimp.h" +#include "core/gimpdrawable.h" +#include "core/gimppaintinfo.h" + +#include "gimpink2.h" +#include "gimpink2options.h" +#include "gimpink-blob.h" + +#include "gimp-intl.h" + + +enum +{ + PROP_0, + PROP_SIZE, + PROP_TILT_ANGLE, + PROP_SIZE_SENSITIVITY, + PROP_VEL_SENSITIVITY, + PROP_TILT_SENSITIVITY, + PROP_BLOB_TYPE, + PROP_BLOB_ASPECT, + PROP_BLOB_ANGLE, + PROP_COMPENSATION_HIST_SIZE, + PROP_COMPENSATE_AT_LAST, + PROP_COMPENSATION_RATE_TEMPERATURE, + + PROP_MAX_COORD_SMOOTH +}; + + +static void gimp_ink2_options_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_ink2_options_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + + +G_DEFINE_TYPE (GimpInk2Options, gimp_ink2_options, GIMP_TYPE_PAINT_OPTIONS) + + +static void +gimp_ink2_options_class_init (GimpInk2OptionsClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = gimp_ink2_options_set_property; + object_class->get_property = gimp_ink2_options_get_property; + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_SIZE, + "size", NULL, + 0.0, 200.0, 16.0, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_TILT_ANGLE, + "tilt-angle", NULL, + -90.0, 90.0, 0.0, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_SIZE_SENSITIVITY, + "size-sensitivity", NULL, + 0.0, 1.0, 1.0, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_VEL_SENSITIVITY, + "vel-sensitivity", NULL, + 0.0, 1.0, 0.8, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_TILT_SENSITIVITY, + "tilt-sensitivity", NULL, + 0.0, 1.0, 0.4, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_BLOB_TYPE, + "blob-type", NULL, + GIMP_TYPE_INK_BLOB_TYPE, + GIMP_INK_BLOB_TYPE_ELLIPSE, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_BLOB_ASPECT, + "blob-aspect", NULL, + 1.0, 10.0, 1.0, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_BLOB_ANGLE, + "blob-angle", NULL, + -90.0, 90.0, 0.0, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_COMPENSATION_HIST_SIZE, + "compensation-history-size", NULL, + 1, INK2_HISTORY_BUFFER, MIN(20, INK2_HISTORY_BUFFER), 0); + GIMP_CONFIG_INSTALL_PROP_BOOLEAN(object_class, PROP_COMPENSATE_AT_LAST, + "compensate-at-last", NULL, + FALSE, 0); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_COMPENSATION_RATE_TEMPERATURE, + "compensation-rate-temperature", NULL, + 0.0, 1000, 25, + 0); + + /* G-Pen uses the own smoothing routin, so disable the GimpDisplayShell's one */ + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_MAX_COORD_SMOOTH, + "ink2-max-coord-smooth", NULL, + 0.0, 0.0, 0.0, + GIMP_PARAM_STATIC_STRINGS); + + g_object_class_override_property (object_class, PROP_MAX_COORD_SMOOTH, "paint-max-coord-smooth"); +} + +static void +gimp_ink2_options_init (GimpInk2Options *options) +{ +} + +static void +gimp_ink2_options_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpInk2Options *options = GIMP_INK2_OPTIONS (object); + + switch (property_id) + { + case PROP_SIZE: + options->size = g_value_get_double (value); + break; + case PROP_TILT_ANGLE: + options->tilt_angle = g_value_get_double (value); + break; + case PROP_SIZE_SENSITIVITY: + options->size_sensitivity = g_value_get_double (value); + break; + case PROP_VEL_SENSITIVITY: + options->vel_sensitivity = g_value_get_double (value); + break; + case PROP_TILT_SENSITIVITY: + options->tilt_sensitivity = g_value_get_double (value); + break; + case PROP_BLOB_TYPE: + options->blob_type = g_value_get_enum (value); + break; + case PROP_BLOB_ASPECT: + options->blob_aspect = g_value_get_double (value); + break; + case PROP_BLOB_ANGLE: + options->blob_angle = g_value_get_double (value); + break; + case PROP_COMPENSATION_HIST_SIZE: + options->compensation_hist_size = g_value_get_int (value); + break; + case PROP_COMPENSATE_AT_LAST: + options->compensate_at_last = g_value_get_boolean (value); + break; + case PROP_COMPENSATION_RATE_TEMPERATURE: + options->compensation_rate_temperature = g_value_get_double (value); + break; + + case PROP_MAX_COORD_SMOOTH: + GIMP_TOOL_OPTIONS (options)->max_coord_smooth = g_value_get_double (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_ink2_options_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpInk2Options *options = GIMP_INK2_OPTIONS (object); + + switch (property_id) + { + case PROP_SIZE: + g_value_set_double (value, options->size); + break; + case PROP_TILT_ANGLE: + g_value_set_double (value, options->tilt_angle); + break; + case PROP_SIZE_SENSITIVITY: + g_value_set_double (value, options->size_sensitivity); + break; + case PROP_VEL_SENSITIVITY: + g_value_set_double (value, options->vel_sensitivity); + break; + case PROP_TILT_SENSITIVITY: + g_value_set_double (value, options->tilt_sensitivity); + break; + case PROP_BLOB_TYPE: + g_value_set_enum (value, options->blob_type); + break; + case PROP_BLOB_ASPECT: + g_value_set_double (value, options->blob_aspect); + break; + case PROP_BLOB_ANGLE: + g_value_set_double (value, options->blob_angle); + break; + case PROP_COMPENSATION_HIST_SIZE: + g_value_set_int (value, options->compensation_hist_size); + break; + case PROP_COMPENSATE_AT_LAST: + g_value_set_boolean (value, options->compensate_at_last); + break; + case PROP_COMPENSATION_RATE_TEMPERATURE: + g_value_set_double (value, options->compensation_rate_temperature); + break; + + case PROP_MAX_COORD_SMOOTH: + g_value_set_double (value, GIMP_TOOL_OPTIONS (options)->max_coord_smooth); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} --- gimp-2.6.6/app/paint/gimpink2options.h 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpink2options.h 2010-06-27 02:14:18 +0900 @@ -0,0 +1,65 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __GIMP_INK2_OPTIONS_H__ +#define __GIMP_INK2_OPTIONS_H__ + + +#include "gimppaintoptions.h" + + +#define GIMP_TYPE_INK2_OPTIONS (gimp_ink2_options_get_type ()) +#define GIMP_INK2_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_INK2_OPTIONS, GimpInk2Options)) +#define GIMP_INK2_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_INK2_OPTIONS, GimpInk2OptionsClass)) +#define GIMP_IS_INK2_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_INK2_OPTIONS)) +#define GIMP_IS_INK2_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_INK2_OPTIONS)) +#define GIMP_INK2_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_INK2_OPTIONS, GimpInk2OptionsClass)) + + +typedef struct _GimpInk2OptionsClass GimpInk2OptionsClass; + +struct _GimpInk2Options +{ + GimpPaintOptions parent_instance; + + gdouble size; + gdouble tilt_angle; + + gdouble size_sensitivity; + gdouble vel_sensitivity; + gdouble tilt_sensitivity; + + GimpInkBlobType blob_type; + gdouble blob_aspect; + gdouble blob_angle; + + gint compensation_hist_size; + gboolean compensate_at_last; + gdouble compensation_rate_temperature; +}; + +struct _GimpInk2OptionsClass +{ + GimpPaintOptionsClass parent_instance; +}; + + +GType gimp_ink2_options_get_type (void) G_GNUC_CONST; + + +#endif /* __GIMP_INK2_OPTIONS_H__ */ --- gimp-2.6.6/app/paint/gimpink2undo.c 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpink2undo.c 2010-06-27 02:14:18 +0900 @@ -0,0 +1,121 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include + +#include "paint-types.h" + +#include "gimpink2.h" +#include "gimpink-blob.h" +#include "gimpink2undo.h" + + +static GObject * gimp_ink2_undo_constructor (GType type, + guint n_params, + GObjectConstructParam *params); + +static void gimp_ink2_undo_pop (GimpUndo *undo, + GimpUndoMode undo_mode, + GimpUndoAccumulator *accum); +static void gimp_ink2_undo_free (GimpUndo *undo, + GimpUndoMode undo_mode); + + +G_DEFINE_TYPE (GimpInk2Undo, gimp_ink2_undo, GIMP_TYPE_PAINT_CORE_UNDO) + +#define parent_class gimp_ink2_undo_parent_class + + +static void +gimp_ink2_undo_class_init (GimpInk2UndoClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GimpUndoClass *undo_class = GIMP_UNDO_CLASS (klass); + + object_class->constructor = gimp_ink2_undo_constructor; + + undo_class->pop = gimp_ink2_undo_pop; + undo_class->free = gimp_ink2_undo_free; +} + +static void +gimp_ink2_undo_init (GimpInk2Undo *undo) +{ +} + +static GObject * +gimp_ink2_undo_constructor (GType type, + guint n_params, + GObjectConstructParam *params) +{ + GObject *object; + GimpInk2Undo *ink_undo; + GimpInk2 *ink; + + object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params); + + ink_undo = GIMP_INK2_UNDO (object); + + g_assert (GIMP_IS_INK2 (GIMP_PAINT_CORE_UNDO (ink_undo)->paint_core)); + + ink = GIMP_INK2 (GIMP_PAINT_CORE_UNDO (ink_undo)->paint_core); + + if (ink->start_blob) + ink_undo->last_blob = blob_duplicate (ink->start_blob); + + return object; +} + +static void +gimp_ink2_undo_pop (GimpUndo *undo, + GimpUndoMode undo_mode, + GimpUndoAccumulator *accum) +{ + GimpInk2Undo *ink_undo = GIMP_INK2_UNDO (undo); + + GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum); + + if (GIMP_PAINT_CORE_UNDO (ink_undo)->paint_core) + { + GimpInk2 *ink = GIMP_INK2 (GIMP_PAINT_CORE_UNDO (ink_undo)->paint_core); + Blob *tmp_blob; + + tmp_blob = ink->last_blob; + ink->last_blob = ink_undo->last_blob; + ink_undo->last_blob = tmp_blob; + } +} + +static void +gimp_ink2_undo_free (GimpUndo *undo, + GimpUndoMode undo_mode) +{ + GimpInk2Undo *ink_undo = GIMP_INK2_UNDO (undo); + + if (ink_undo->last_blob) + { + g_free (ink_undo->last_blob); + ink_undo->last_blob = NULL; + } + + GIMP_UNDO_CLASS (parent_class)->free (undo, undo_mode); +} --- gimp-2.6.6/app/paint/gimpink2undo.h 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpink2undo.h 2010-06-27 02:14:18 +0900 @@ -0,0 +1,53 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __GIMP_INK2_UNDO_H__ +#define __GIMP_INK2_UNDO_H__ + + +#include "gimppaintcoreundo.h" +#include "gimpink2.h" + + +#define GIMP_TYPE_INK2_UNDO (gimp_ink2_undo_get_type ()) +#define GIMP_INK2_UNDO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_INK2_UNDO, GimpInk2Undo)) +#define GIMP_INK2_UNDO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_INK2_UNDO, GimpInk2UndoClass)) +#define GIMP_IS_INK2_UNDO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_INK2_UNDO)) +#define GIMP_IS_INK2_UNDO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_INK2_UNDO)) +#define GIMP_INK2_UNDO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_INK2_UNDO, GimpInk2UndoClass)) + + +typedef struct _GimpInk2UndoClass GimpInk2UndoClass; + +struct _GimpInk2Undo +{ + GimpPaintCoreUndo parent_instance; + + Blob *last_blob; +}; + +struct _GimpInk2UndoClass +{ + GimpPaintCoreUndoClass parent_class; +}; + + +GType gimp_ink2_undo_get_type (void) G_GNUC_CONST; + + +#endif /* __GIMP_INK2_UNDO_H__ */ --- gimp-2.6.6/app/paint/gimpmixbrush.c 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpmixbrush.c 2010-06-27 02:14:18 +0900 @@ -0,0 +1,1777 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include "config.h" + +#include + +#include "libgimpcolor/gimpcolor.h" +#include "libgimpmath/gimpmath.h" +#include "libgimpbase/gimpbase.h" + +#include "paint-types.h" + +#include "base/pixel-region.h" +#include "base/temp-buf.h" + +#include "base/pixel-processor.h" + +#include "paint-funcs/paint-funcs.h" + +#include "core/gimp.h" +#include "core/gimpbrush.h" +#include "core/gimpchannel.h" +#include "core/gimpdrawable.h" +#include "core/gimplayer.h" +#include "core/gimpgradient.h" +#include "core/gimppattern.h" +#include "core/gimpimage.h" +#include "core/gimppickable.h" +#include "core/gimpprojection.h" + +#include "gimpmixbrush.h" +#include "gimpmixbrushoptions.h" + +#ifdef GIMP_MIXBRUSH_COMPOSITE +#include "gimpmixbrush-composite.h" +#endif + +#include "gimp-intl.h" + + +/* Coords history */ + +typedef struct _CoordsHistory +{ + GimpCoords coords; + GimpCoords prev_coords; + gdouble pixel_dist; + GimpRGB color; + gdouble opacity; + gdouble hardness; +} CoordsHistory; + + +/* Params of composite functions */ + +typedef struct _CompositeDabParam +{ + GimpRGB paint_color; + GimpRGB _paint_color; + gdouble opacity; + gdouble adjusted_opacity; + gint x; + gint y; + gint drawable_x; + gint drawable_y; + gboolean fringe; + gdouble fringe_contrast; + gdouble fringe_contrast_offset; + gdouble grain; + gint texture_jitter_x; + gint texture_jitter_y; + gboolean is_rgb; + gboolean has_alpha; + gboolean active_components[MAX_CHANNELS]; + + guchar *texture_data; + gint texture_bytes; + gint texture_width; + gint texture_height; + gint texture_stride; +} CompositeDabParam; + + +static void gimp_mixbrush_finalize (GObject *object); + +static void gimp_mixbrush_paint (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpPaintState paint_state, + guint32 time); + +static void gimp_mixbrush_motion (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options); + +static void gimp_mixbrush_start (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options); + +static void gimp_mixbrush_finish (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options); + + +static void gimp_mixbrush_paste_canvas (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options); + +static void coords_history_free (CoordsHistory *history, + gpointer dummy); + +static inline gboolean get_canvas_color (GimpImage *image, + GimpDrawable *drawable, + GimpPaintCore *paint_core, + gint x, + gint y, + guint sample_size_limit, + gboolean merged, + GimpRGB *color); + +static inline gboolean pick_up_avarage_color (GimpPickable *pickable, + GimpBrushCore *brush_core, + gint x, + gint y, + gint size_limit, + GimpRGB *color); + +static inline void color_to_alpha (GimpRGB *src, + const GimpRGB *color); + +static inline void composite_rgba (const GimpRGB *color1, + gdouble op1, + const GimpRGB *color2, + gdouble op2, + GimpRGB *result, + gboolean use_alt_alpha_op); + +static inline void blend_rgba (const GimpRGB *color1, + gdouble op1, + const GimpRGB *color2, + gdouble op2, + GimpRGB *result, + gboolean use_alt_alpha_op); + +static inline void calc_pressure_params (PressureParams *params, + gdouble in1, + gdouble in2, + gdouble out1, + gdouble out2); + +static inline gdouble calc_pressure (gdouble value, + PressureParams *params); + +#ifndef GIMP_MIXBRUSH_COMPOSITE +void paste_canvas (GimpPaintCore *core, + GimpDrawable *drawable, + GimpPattern *texture, + GimpRGB *paint_color, + gdouble opacity, + GimpBrushApplicationMode hardness_mode, + gdouble hardness, + gboolean fringe, + gdouble fringe_contrast, + gdouble grain, + gint jitter, + GimpUpdateFreqOptions *update_freq_options); + +static void composite_dab (CompositeDabParam *params, + PixelRegion *srcPR, + PixelRegion *maskPR); + +static void composite_textured_dab (CompositeDabParam *params, + PixelRegion *srcPR, + PixelRegion *maskPR); + +static void composite_dab_selection (CompositeDabParam *params, + PixelRegion *srcPR, + PixelRegion *maskPR, + PixelRegion *selPR); + +static void composite_textured_dab_selection (CompositeDabParam *params, + PixelRegion *srcPR, + PixelRegion *maskPR, + PixelRegion *selPR); + +#endif + + +G_DEFINE_TYPE (GimpMixbrush, gimp_mixbrush, GIMP_TYPE_PAINTBRUSH) + +#define parent_class gimp_mixbrush_parent_class + + +void +gimp_mixbrush_register (Gimp *gimp, + GimpPaintRegisterCallback callback) +{ + (* callback) (gimp, + GIMP_TYPE_MIXBRUSH, + GIMP_TYPE_MIXBRUSH_OPTIONS, + "gimp-mixbrush", + _("Mixbrush"), + "gimp-tool-mixbrush"); +} + +static void +gimp_mixbrush_class_init (GimpMixbrushClass *klass) +{ + GimpPaintCoreClass *paint_core_class = GIMP_PAINT_CORE_CLASS (klass); + GimpBrushCoreClass *brush_core_class = GIMP_BRUSH_CORE_CLASS (klass); + + paint_core_class->paint = gimp_mixbrush_paint; + G_OBJECT_CLASS (klass)->finalize = gimp_mixbrush_finalize; + + brush_core_class->handles_changing_brush = TRUE; +} + +static void +gimp_mixbrush_init (GimpMixbrush *mixbrush) +{ + mixbrush->history = NULL; + mixbrush->mask = NULL; + +#ifdef GIMP_MIXBRUSH_COMPOSITE + gimp_mixbrush_composite_init (); +#endif +} + +static void +gimp_mixbrush_finalize (GObject *object) +{ + GimpMixbrush *mixbrush = GIMP_MIXBRUSH (object); + + if (mixbrush->history) { + g_list_foreach (mixbrush->history, (GFunc)coords_history_free, NULL); + g_list_free (mixbrush->history); + } + if (mixbrush->mask) + temp_buf_free (mixbrush->mask); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gimp_mixbrush_paint (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpPaintState paint_state, + guint32 time) +{ +#ifdef CHECK_TIME + GTimer *timer; + static gdouble total_time = 0; + static guint count = 0; +#endif + switch (paint_state) + { + case GIMP_PAINT_STATE_INIT: +#ifdef CHECK_TIME + total_time = 0; + count = 0; +#endif + gimp_mixbrush_start (paint_core, drawable, paint_options); + GIMP_PAINT_CORE_CLASS (parent_class)->paint (paint_core, drawable, + paint_options, + paint_state, time); + break; + + case GIMP_PAINT_STATE_MOTION: +#ifdef CHECK_TIME + timer = g_timer_new (); + g_timer_start (timer); + gimp_mixbrush_motion (paint_core, drawable, paint_options); + g_timer_stop (timer); + total_time += g_timer_elapsed (timer, NULL); + g_timer_destroy (timer); + count++; +#else + gimp_mixbrush_motion (paint_core, drawable, paint_options); +#endif + break; + + case GIMP_PAINT_STATE_FINISH: +#ifdef CHECK_TIME + g_printerr ("average time:%f\n", total_time / count); +#endif + gimp_mixbrush_finish (paint_core, drawable, paint_options); + GIMP_PAINT_CORE_CLASS (parent_class)->paint (paint_core, drawable, + paint_options, + paint_state, time); + break; + + default: + break; + } +} + +static void +gimp_mixbrush_start (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options) +{ + GimpMixbrush *mixbrush = GIMP_MIXBRUSH (paint_core); + GimpMixbrushOptions *mixbrush_options = GIMP_MIXBRUSH_OPTIONS (paint_options); + GimpImage *image; + guchar color_uchar[MAX_CHANNELS]; + + image = gimp_item_get_image (GIMP_ITEM (drawable)); + + mixbrush->use_alt_alpha_op = + (mixbrush_options->alpha_channel_mixing && gimp_drawable_has_alpha (drawable)); + + /* Init the pressure params */ + calc_pressure_params (&mixbrush->pr_texture_grain, + mixbrush_options->texture_options->grain_pressure_in1, + mixbrush_options->texture_options->grain_pressure_in2, + mixbrush_options->texture_options->grain_pressure_out1, + mixbrush_options->texture_options->grain_pressure_out2); + calc_pressure_params (&mixbrush->pr_main_density, + mixbrush_options->main_color_density_pressure_in1, + mixbrush_options->main_color_density_pressure_in2, + mixbrush_options->main_color_density_pressure_out1, + mixbrush_options->main_color_density_pressure_out2); + calc_pressure_params (&mixbrush->pr_main_rate, + mixbrush_options->main_color_pressure_in1, + mixbrush_options->main_color_pressure_in2, + mixbrush_options->main_color_pressure_out1, + mixbrush_options->main_color_pressure_out2); + calc_pressure_params (&mixbrush->pr_canvas_density, + mixbrush_options->canvas_color_density_pressure_in1, + mixbrush_options->canvas_color_density_pressure_in2, + mixbrush_options->canvas_color_density_pressure_out1, + mixbrush_options->canvas_color_density_pressure_out2); + calc_pressure_params (&mixbrush->pr_canvas_rate, + mixbrush_options->canvas_color_pressure_in1, + mixbrush_options->canvas_color_pressure_in2, + mixbrush_options->canvas_color_pressure_out1, + mixbrush_options->canvas_color_pressure_out2); + + /* Get the index of the alpha component */ + switch (gimp_drawable_type_without_alpha (drawable)) + { + case GIMP_RGB: + mixbrush->alpha_pix = ALPHA_PIX; + break; + case GIMP_GRAY: + mixbrush->alpha_pix = ALPHA_G_PIX; + break; + case GIMP_INDEXED: + default: + mixbrush->alpha_pix = ALPHA_I_PIX; + } + + /* Setup the paint(foreground) color */ + gimp_image_get_foreground (image, GIMP_CONTEXT (paint_options), + gimp_drawable_type (drawable), + color_uchar); + + if (mixbrush->alpha_pix == ALPHA_PIX) + gimp_rgba_set_uchar (&mixbrush->paint_color, + color_uchar[0], + color_uchar[1], + color_uchar[2], + color_uchar[3]); + else + gimp_rgba_set_uchar (&mixbrush->paint_color, + color_uchar[0], + color_uchar[0], + color_uchar[0], + color_uchar[1]); + + mixbrush->paint_color.a = 1.0; + + /* Setup the last color */ + if (mixbrush->use_alt_alpha_op) + { + get_canvas_color (image, drawable, paint_core, + (gint) paint_core->cur_coords.x, (gint) paint_core->cur_coords.y, + mixbrush_options->sample_size_limit, + mixbrush_options->merged, + &mixbrush->last_color); + mixbrush->last_color.a *= mixbrush_options->canvas_color_density * + calc_pressure (paint_core->cur_coords.pressure, &mixbrush->pr_canvas_density); + } + else + mixbrush->last_color.a = 0.0; + + /* Setup the hidden color */ + mixbrush->hidden_color.a = 0.0; + + if (gimp_drawable_has_alpha (drawable)) + { + switch (mixbrush_options->hidden_color) + { + case GIMP_HIDDEN_COLOR_WHITE: + gimp_rgba_set (&mixbrush->hidden_color, 1.0, 1.0, 1.0, 1.0); + break; + case GIMP_HIDDEN_COLOR_BACKGROUND: + gimp_image_get_background (image, GIMP_CONTEXT (paint_options), + gimp_drawable_type (drawable), + color_uchar); + + gimp_rgba_set_uchar (&mixbrush->hidden_color, + color_uchar[0], + color_uchar[1], + color_uchar[2], + color_uchar[3]); + + mixbrush->hidden_color.a = 1.0; + break; + } + } + + /* Reset the rounding error */ + gimp_rgba_set (&mixbrush->error, 0, 0, 0, 0); +} + +static void +gimp_mixbrush_finish (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options) +{ + GimpMixbrush *mixbrush = GIMP_MIXBRUSH (paint_core); + + if (!(GIMP_MIXBRUSH_OPTIONS (paint_options)->tail) && mixbrush->history) + { + g_list_foreach (mixbrush->history, (GFunc)coords_history_free, NULL); + g_list_free (mixbrush->history); + mixbrush->history = NULL; + } + + while (mixbrush->history) + gimp_mixbrush_paste_canvas (paint_core, drawable, paint_options); + + if (mixbrush->mask) + { + temp_buf_free (mixbrush->mask); + mixbrush->mask = NULL; + } +} + +static void +gimp_mixbrush_motion (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options) +{ + GimpImage *image; + GimpMixbrush *mixbrush = GIMP_MIXBRUSH (paint_core); + GimpMixbrushOptions *mixbrush_options = GIMP_MIXBRUSH_OPTIONS (paint_options); + CoordsHistory *history; + gdouble opacity = GIMP_OPACITY_OPAQUE; + + image = gimp_item_get_image (GIMP_ITEM (drawable)); + + opacity *= gimp_paint_options_get_fade (paint_options, image, + paint_core->pixel_dist); + + /* Add history item */ + history = g_new (CoordsHistory, 1); + history->coords = paint_core->cur_coords; + history->prev_coords = paint_core->last_coords; + history->pixel_dist = paint_core->pixel_dist; + + /* Pick up the raw canvas color */ + get_canvas_color (image, drawable, paint_core, + (gint) history->coords.x, (gint) history->coords.y, + mixbrush_options->sample_size_limit, + mixbrush_options->merged, + &history->color); + + history->opacity = opacity; + + mixbrush->history = g_list_append (mixbrush->history, history); + + /* Process a history item */ + if (g_list_length (mixbrush->history) > mixbrush_options->delay) + gimp_mixbrush_paste_canvas (paint_core, drawable, paint_options); +} + +static void +gimp_mixbrush_paste_canvas (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options) +{ + GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_core); + GimpContext *context = GIMP_CONTEXT (paint_options); + GimpDynamicOptions *pressure_options = paint_options->pressure_options; + GimpImage *image; + TempBuf *area; + GimpMixbrush *mixbrush = GIMP_MIXBRUSH (paint_core); + GimpRGB *last_color = &mixbrush->last_color; + GimpMixbrushOptions *mixbrush_options = GIMP_MIXBRUSH_OPTIONS (paint_options); + GimpPaintApplicationMode paint_appl_mode; + CoordsHistory *history; + GimpCoords orig_coords; + GimpCoords prev_coords; + + if (mixbrush->history == NULL) + return; + + history = mixbrush->history->data; + mixbrush->history = g_list_delete_link (mixbrush->history, mixbrush->history); + + if (history->opacity != 0.0) + { + image = gimp_item_get_image (GIMP_ITEM (drawable)); + + paint_appl_mode = paint_options->application_mode; + + orig_coords = paint_core->cur_coords; + prev_coords = paint_core->last_coords; + paint_core->cur_coords = history->coords; + paint_core->last_coords = history->prev_coords; + area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options); + + if (area) { + guchar color_uchar[MAX_CHANNELS]; + GimpRGB main_color, canvas_color; + gdouble main_op, canvas_op; + + /* Init the main color */ + if (!gimp_paint_options_get_gradient_color (paint_options, image, + paint_core->cur_coords.pressure, + paint_core->pixel_dist, + &main_color)) + main_color = mixbrush->paint_color; + + /* Blend the main color and last color */ + main_op = CLAMP (mixbrush_options->main_color_rate * + calc_pressure (paint_core->cur_coords.pressure, &mixbrush->pr_main_rate), + 0.0, 1.0); + + /*if (mixbrush_options->alpha_channel_mixing) + blend_rgba (&main_color, main_op, + last_color, 1.0 - main_op, + &main_color, FALSE); + else + composite_rgba (&main_color, main_op, + last_color, 1.0, + &main_color, FALSE);*/ + composite_rgba (&main_color, main_op, + last_color, 1.0, + &main_color, FALSE); + + /* Pick up the covered canvas color */ + get_canvas_color (image, drawable, paint_core, + (gint) paint_core->cur_coords.x, (gint) paint_core->cur_coords.y, + mixbrush_options->sample_size_limit, + mixbrush_options->merged, + &canvas_color); + + /* Blend the covered canvas color and the raw canvas color */ + canvas_op = CLAMP (mixbrush_options->canvas_color_rate * + calc_pressure (paint_core->cur_coords.pressure, &mixbrush->pr_canvas_rate), + 0.0, 1.0); + + /*if (mixbrush_options->alpha_channel_mixing) + blend_rgba (&canvas_color, canvas_op, + &history->color, 1.0 - canvas_op, + &canvas_color, FALSE); + else + composite_rgba (&canvas_color, canvas_op, + &history->color, 1.0, + &canvas_color, FALSE);*/ + blend_rgba (&canvas_color, canvas_op, + &history->color, 1.0 - canvas_op, + &canvas_color, TRUE/*FALSE*/); + + /* Correct the rounding error came from the last process */ + gimp_rgba_add (&canvas_color, &mixbrush->error); + + /* Put the hidden color below the canvas color */ + if (mixbrush->hidden_color.a > 0.0) + composite_rgba (&canvas_color, 1.0, &mixbrush->hidden_color, 1.0, &canvas_color, FALSE); + + + /* Blend the main color and the canvas color */ + main_op = mixbrush_options->main_color_density; + + main_op *= calc_pressure (paint_core->cur_coords.pressure, &mixbrush->pr_main_density); + + if (mixbrush_options->dryout > 0) + main_op *= 1.0 - MIN (paint_core->pixel_dist / mixbrush_options->dryout, 1.0); + + canvas_op = mixbrush_options->canvas_color_density; + + canvas_op *= calc_pressure (paint_core->cur_coords.pressure, &mixbrush->pr_canvas_density); + + /* If the canvas color is transparent, assume that * + * the main color and the hidden color are same. + if (canvas_color.a == 0.0) + gimp_rgb_set (&canvas_color, main_color.r, main_color.g, main_color.b);*/ + + main_op = CLAMP (main_op, 0.0, 1.0); + canvas_op = CLAMP (canvas_op, 0.0, 1.0); + +//g_printerr ("m:%f, %f, %f %f\n",canvas_color.r,canvas_color.g,canvas_color.b,canvas_color.a); +//g_printerr ("l:%f, %f, %f %f\n",history->color.r,history->color.g,history->color.b,history->color.a); + if (mixbrush_options->pigment) + composite_rgba (&main_color, main_op, &canvas_color, canvas_op, + last_color, /*FALSE*/mixbrush->use_alt_alpha_op); + else + blend_rgba (&main_color, main_op, &canvas_color, canvas_op, + last_color, /*FALSE*/mixbrush->use_alt_alpha_op); +//g_printerr ("r:%f, %f, %f %f\n\n",canvas_color.r,canvas_color.g,canvas_color.b,canvas_color.a); + +#if 0 + if (mixbrush_options->remove_color && + gimp_drawable_type_without_alpha (drawable) == GIMP_RGB_IMAGE) + { + /* Remove color */ + GimpRGB color1, color2; + guchar paint_color[4]; + + gimp_rgba_set_uchar (&color1, + color[0], color[1], color[2], OPAQUE_OPACITY); + gimp_rgba_set_uchar (&color2, + hidden_color[0], hidden_color[1], hidden_color[2], OPAQUE_OPACITY); + + color_to_alpha (&color1, &color2); + + history->opacity *= color1.a; + + gimp_rgba_get_uchar (&color1, + &paint_color[0], &paint_color[1], &paint_color[2], &paint_color[3]); + paint_color[mixbrush->alpha_pix] = OPAQUE_OPACITY; + + color_pixels (temp_buf_data (area), paint_color, + area->width * area->height, + area->bytes); + } + else + { + color[mixbrush->alpha_pix] = OPAQUE_OPACITY; + + color_pixels (temp_buf_data (area), color, + area->width * area->height, + area->bytes); + } +#else + + +#endif + + history->opacity *= gimp_paint_options_get_dynamic_opacity (paint_options, + &paint_core->cur_coords); + + history->hardness = gimp_paint_options_get_dynamic_hardness (paint_options, + &paint_core->cur_coords); + + /* finally, let the brush core paste the colored area on the canvas */ + if (mixbrush_options->alpha_channel_mixing && + paint_appl_mode == GIMP_PAINT_INCREMENTAL) + { + gdouble op = MIN (history->opacity, GIMP_OPACITY_OPAQUE) * gimp_context_get_opacity (context); + gdouble grain = 0.0; + GimpPattern *texture = NULL; + + if (mixbrush_options->texture_options->use_texture) + { + grain = mixbrush_options->texture_options->grain; + grain = -1.0 + (grain + 1.0) * calc_pressure (paint_core->cur_coords.pressure, + &mixbrush->pr_texture_grain); + + texture = gimp_context_get_pattern (context); + } + + paste_canvas (paint_core, drawable, + texture, + last_color, op, + gimp_paint_options_get_brush_mode (paint_options), + history->hardness, + mixbrush_options->texture_options->fringe, + mixbrush_options->texture_options->fringe_contrast, + grain, + mixbrush_options->texture_options->jitter, + paint_options->update_freq_options); + } + else + { + gimp_rgba_get_uchar (last_color, + &color_uchar[0], + &color_uchar[1], + &color_uchar[2], + &color_uchar[3]); + + /* Set the rounding error to mixbrush->error */ + mixbrush->error.r = last_color->r - color_uchar[0] / 255.0; + mixbrush->error.g = last_color->g - color_uchar[1] / 255.0; + mixbrush->error.b = last_color->b - color_uchar[2] / 255.0; + mixbrush->error.a = last_color->a - color_uchar[3] / 255.0; + + color_uchar[mixbrush->alpha_pix] = OPAQUE_OPACITY; + + color_pixels (temp_buf_data (area), color_uchar, + area->width * area->height, + area->bytes); + + history->opacity *= last_color->a; + + gimp_brush_core_paste_canvas (brush_core, drawable, + MIN (history->opacity, GIMP_OPACITY_OPAQUE), + gimp_context_get_flow (context), + gimp_context_get_opacity (context), + gimp_context_get_paint_mode (context), + gimp_paint_options_get_brush_mode (paint_options), + history->hardness, + paint_appl_mode, + paint_options->update_freq_options); + } + } + paint_core->cur_coords = orig_coords; + paint_core->last_coords = prev_coords; + } + else + { + last_color->a = 0.0; + gimp_rgba_set (&mixbrush->error, 0, 0, 0, 0); + } + + g_free (history); +} + + +static void +coords_history_free (CoordsHistory *history, gpointer dummy) +{ + g_free (history); +} + +static inline gboolean +get_canvas_color (GimpImage *image, + GimpDrawable *drawable, + GimpPaintCore *paint_core, + gint x, + gint y, + guint sample_size_limit, + gboolean merged, + GimpRGB *color) +{ + GimpPickable *pickable; + GimpItem *item = GIMP_ITEM (drawable); + gint offset_x, offset_y; + + offset_x = CLAMP (x, 0, gimp_item_width (item) - 1); + offset_y = CLAMP (y, 0, gimp_item_height (item) - 1); + + if (merged && GIMP_IS_LAYER (drawable)) + { + gint item_offset_x, item_offset_y; + + gimp_item_offsets (item, &item_offset_x, &item_offset_y); + offset_x += item_offset_x; + offset_y += item_offset_y; + + pickable = GIMP_PICKABLE (image->projection); + gimp_pickable_flush (pickable); + } + else + pickable = GIMP_PICKABLE (drawable); + + return pick_up_avarage_color (pickable, + GIMP_BRUSH_CORE (paint_core), + offset_x, offset_y, + sample_size_limit, + color); +} + +static inline gboolean +pick_up_avarage_color (GimpPickable *pickable, + GimpBrushCore *brush_core, + gint x, + gint y, + gint size_limit, + GimpRGB *color) +{ + gint index; + gboolean result; + gint width, height; + + gimp_brush_scale_size (brush_core->brush, brush_core->scale, &width, &height); + + result = gimp_pickable_pick_color (pickable, + x, y, + TRUE, + CLAMP (MIN (width, height), 1, size_limit) / 2.0, + color, + &index); + + return result; +} + + +/* This function came from colortoalpha.c */ + +static inline void +color_to_alpha (GimpRGB *src, + const GimpRGB *color) +{ + GimpRGB alpha; + + alpha.a = src->a; + + if (color->r < 0.0001) + alpha.r = src->r; + else if (src->r > color->r) + alpha.r = (src->r - color->r) / (1.0 - color->r); + else if (src->r < color->r) + alpha.r = (color->r - src->r) / color->r; + else alpha.r = 0.0; + + if (color->g < 0.0001) + alpha.g = src->g; + else if (src->g > color->g) + alpha.g = (src->g - color->g) / (1.0 - color->g); + else if (src->g < color->g) + alpha.g = (color->g - src->g) / (color->g); + else alpha.g = 0.0; + + if (color->b < 0.0001) + alpha.b = src->b; + else if (src->b > color->b) + alpha.b = (src->b - color->b) / (1.0 - color->b); + else if (src->b < color->b) + alpha.b = (color->b - src->b) / (color->b); + else alpha.b = 0.0; + + if (alpha.r > alpha.g) + { + if (alpha.r > alpha.b) + { + src->a = alpha.r; + } + else + { + src->a = alpha.b; + } + } + else if (alpha.g > alpha.b) + { + src->a = alpha.g; + } + else + { + src->a = alpha.b; + } + + if (src->a < 0.0001) + return; + + src->r = (src->r - color->r) / src->a + color->r; + src->g = (src->g - color->g) / src->a + color->g; + src->b = (src->b - color->b) / src->a + color->b; + + src->a *= alpha.a; +} + +static inline void +composite_rgba (const GimpRGB *color1, + gdouble op1, + const GimpRGB *color2, + gdouble op2, + GimpRGB *result, + gboolean use_alt_alpha_op) +{ + GimpRGB rgb1 = *color1, rgb2 = *color2; + + rgb1.a *= op1; + rgb2.a = (1.0 - rgb1.a) * rgb2.a * op2; + + if (rgb1.a == 0.0) + rgb1 = rgb2; + else if (rgb2.a > 0.0) + { + gdouble factor1 = rgb1.a / (rgb1.a + rgb2.a); + gdouble factor2 = 1.0 - factor1; + + rgb1.r = rgb1.r * factor1 + rgb2.r * factor2; + rgb1.g = rgb1.g * factor1 + rgb2.g * factor2; + rgb1.b = rgb1.b * factor1 + rgb2.b * factor2; + rgb1.a += rgb2.a; + } /* if (rgb1.a > 0.0 && rgb2.a == 0.0) rgb1 = rgb1; */ + + if (use_alt_alpha_op) + { + op1 = pow (op1, 1.35); /* workaround against opacity inflation */ + op2 = pow (op2, 1.15); + rgb1.a = op1 + op2; + + if (rgb1.a != 0) + { + rgb1.a = op1 / rgb1.a; /* factor */ + rgb1.a = color1->a * rgb1.a + color2->a * (1.0 - rgb1.a); + rgb1.a *= op1 + (1.0 - op1) * op2; + } + } + +#if 0 + { + static gint count = 0; + //if ((count %= 3) == 0) { + g_printerr("1 = %f %f %f %f\n",color1->r,color1->g,color1->b,color1->a); + g_printerr("2 = %f %f %f %f\n",color2->r,color2->g,color2->b,color2->a); + g_printerr("r = %f %f %f %f\n",rgb1.r,rgb1.g,rgb1.b,rgb1.a); + g_printerr("o = %f %f\n",op1, op2); + //} + count++; + } +#endif + + *result = rgb1; +} + +static inline void +blend_rgba (const GimpRGB *color1, + gdouble op1, + const GimpRGB *color2, + gdouble op2, + GimpRGB *result, + gboolean use_alt_alpha_op) +{ + GimpRGB rgb1 = *color1, rgb2 = *color2, _result; + gdouble _op3; + gdouble factor1, factor2; + + rgb1.a *= op1; + rgb2.a *= op2; + + if (rgb1.a == 0) + _result = rgb2; + else if (rgb2.a == 0) + _result = rgb1; + else + { + _op3 = rgb1.a + rgb2.a; + + factor1 = _op3 == 0 ? 0.5 : rgb1.a / _op3; + factor2 = 1.0 - factor1; + + _result.r = rgb1.r * factor1 + rgb2.r * factor2; + _result.g = rgb1.g * factor1 + rgb2.g * factor2; + _result.b = rgb1.b * factor1 + rgb2.b * factor2; + _result.a = rgb1.a * factor1 + rgb2.a * factor2; + } + + if (use_alt_alpha_op) + { + _result.a = op1 + op2; + if (_result.a != 0) + { + gdouble factor = op1 / _result.a; + _result.a = color1->a * factor + color2->a * (1.0 - factor); + //_result.a = MAX (_result.a, color2->a); + } + } +#if 0 + { + static gint count = 0; + //if ((count %= 3) == 1) { + g_printerr("1 = %f %f %f %f\n",color1->r,color1->g,color1->b,color1->a); + g_printerr("2 = %f %f %f %f\n",color2->r,color2->g,color2->b,color2->a); + g_printerr("r = %f %f %f %f\n",_result.r,_result.g,_result.b,_result.a); + g_printerr("o = %f %f\n",op1, op2); + g_printerr("o'= %f %f\n",_op1, _op2); + g_printerr("f = %f %f\n\n",factor1, factor2); + //} + count++; + } +#endif + + *result = _result; +} + +/* Pressure */ + +static inline void calc_pressure_params (PressureParams *params, + gdouble in1, + gdouble in2, + gdouble out1, + gdouble out2) +{ + if (in1 == in2) + { + params->in_min = in1; + params->in_factor = 0; + } + else if (in1 > in2) + { + params->in_min = in2; + params->in_factor = 1.0 / (in1 - in2); + } + else + { + params->in_min = in1; + params->in_factor = 1.0 / (in2 - in1); + } + + if (out1 == out2) + { + params->out_min = out1; + params->out_factor = 0; + } + else if (out1 > out2) + { + params->out_min = out2; + params->out_factor = out1 - out2; + params->invert = TRUE; + } + else + { + params->out_min = out1; + params->out_factor = out2 - out1; + params->invert = FALSE; + } +} + +static inline gdouble calc_pressure (gdouble value, + PressureParams *params) +{ + g_return_val_if_fail (params != NULL, 1.0); + + if (params->out_factor == 0) + return params->out_min; + + if (params->in_factor != 0) + { + value = MIN (MAX (value - params->in_min, 0.0) * params->in_factor, 1.0); + + if (params->invert) + value = 1.0 - value; + } + else + value = params->in_min; + + return CLAMP (value * params->out_factor + params->out_min, 0.0, 1.0); +} + + +#ifndef GIMP_MIXBRUSH_COMPOSITE +void +paste_canvas (GimpPaintCore *core, + GimpDrawable *drawable, + GimpPattern *texture, + GimpRGB *paint_color, + gdouble opacity, + GimpBrushApplicationMode hardness_mode, + gdouble hardness, + gboolean fringe, + gdouble fringe_contrast, + gdouble grain, + gint jitter, + GimpUpdateFreqOptions *update_freq_options) +{ + CompositeDabParam params; + + GimpChannel *selection; + TempBuf *brush_mask; + TempBuf *canvas_buf; + gint c_x, c_y, c_w, c_h; + PixelRegion srcPR, maskPR, selPR; + gint off_x = 0; + gint off_y = 0; + + selection = gimp_image_get_mask (gimp_item_get_image (GIMP_ITEM (drawable))); + /* don't apply the mask to itself and don't apply an empty mask */ + if (GIMP_DRAWABLE (selection) == drawable || gimp_channel_is_empty (selection)) + selection = NULL; + + brush_mask = gimp_brush_core_get_brush_mask (GIMP_BRUSH_CORE (core), + hardness_mode, + hardness); + canvas_buf = core->canvas_buf; + + if (!brush_mask || + !canvas_buf || + opacity == 0.0 || + (texture && !fringe && grain <= -1.0)) + return; + + params.x = (gint) floor (core->cur_coords.x) - (brush_mask->width >> 1); + params.y = (gint) floor (core->cur_coords.y) - (brush_mask->height >> 1); + + gimp_item_offsets (GIMP_ITEM (drawable), ¶ms.drawable_x, ¶ms.drawable_y); + + c_x = canvas_buf->x; + c_y = canvas_buf->y; + c_w = canvas_buf->width; + c_h = canvas_buf->height; + + /* set undo blocks */ + gimp_paint_core_validate_undo_tiles (core, drawable, + c_x, c_y, c_w, c_h); + if (selection) + { + gint x2, y2; + gint sel_x, sel_y, sel_x2, sel_y2; + + gimp_item_offsets (GIMP_ITEM (selection), &sel_x, &sel_y); + + sel_x -= params.drawable_x; + sel_y -= params.drawable_y; + sel_x2 = sel_x + gimp_item_width (GIMP_ITEM (selection)); + sel_y2 = sel_y + gimp_item_height (GIMP_ITEM (selection)); + + x2 = c_x + c_w; + y2 = c_y + c_h; + + if (c_x < sel_x) + { + off_x = sel_x - c_x; + c_x = sel_x; + } + if (c_y < sel_y) + { + off_y = sel_y - c_y; + c_y = sel_y; + } + c_w = MIN (x2, sel_x2) - c_x; + c_h = MIN (y2, sel_y2) - c_y; + } + + /* init the pixel regions */ + if (!off_x && (params.x < 0)) + off_x = -params.x; + if (!off_y && (params.y < 0)) + off_y = -params.y; + + pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable), + c_x, c_y, c_w, c_h, + TRUE); + + pixel_region_init_temp_buf (&maskPR, brush_mask, + off_x, off_y, + brush_mask->width, brush_mask->height); + + params.is_rgb = (srcPR.bytes > 2); + params.has_alpha = (srcPR.bytes == 2 || srcPR.bytes == 4); + + /* configure the active channel array */ + gimp_drawable_get_active_components (drawable, params.active_components); + + /* setup the composite params */ + params.paint_color = *paint_color; + params._paint_color.r = paint_color->r * 255.0; + if (params.is_rgb) + { + params._paint_color.g = paint_color->g * 255.0; + params._paint_color.b = paint_color->b * 255.0; + } + params.opacity = opacity; + params.adjusted_opacity = pow (opacity, 1.0 / 1.5); + + if (texture) + { + params.grain = grain; + params.fringe = fringe; + params.fringe_contrast = fringe_contrast; + params.fringe_contrast_offset = (fringe_contrast - 1.0) * 0.5; + params.texture_jitter_x = g_random_int_range (-jitter, jitter + 1); + params.texture_jitter_y = g_random_int_range (-jitter, jitter + 1); + + params.texture_data = temp_buf_data (texture->mask); + params.texture_bytes = texture->mask->bytes; + params.texture_width = texture->mask->width; + params.texture_height = texture->mask->height; + params.texture_stride = params.texture_width * params.texture_bytes; + + if (selection) + { + pixel_region_init (&selPR, + gimp_drawable_get_tiles (GIMP_DRAWABLE (selection)), + c_x + params.drawable_x, + c_y + params.drawable_y, + c_w, c_h, + FALSE); + + pixel_regions_process_parallel ((PixelProcessorFunc) composite_textured_dab_selection, + ¶ms, 3, &srcPR, &maskPR, &selPR); + } + else + pixel_regions_process_parallel ((PixelProcessorFunc) composite_textured_dab, + ¶ms, 2, &srcPR, &maskPR); + } + else + { + if (selection) + { + pixel_region_init (&selPR, + gimp_drawable_get_tiles (GIMP_DRAWABLE (selection)), + c_x + params.drawable_x, + c_y + params.drawable_y, + c_w, c_h, + FALSE); + + pixel_regions_process_parallel ((PixelProcessorFunc) composite_dab_selection, + ¶ms, 3, &srcPR, &maskPR, &selPR); + } + else + pixel_regions_process_parallel ((PixelProcessorFunc) composite_dab, + ¶ms, 2, &srcPR, &maskPR); + } + +#if 0 + { + static int c = 0; + if (++c == 1) + { + /*g_file_set_contents ("r:\\out_canvas_buf_00.raw", temp_buf_data (canvas_buf), + canvas_buf->width * canvas_buf->height * canvas_buf->bytes, + NULL); + g_file_set_contents ("r:\\out_brush_mask_00.raw", temp_buf_data (brush_mask), + brush_mask->width * brush_mask->height * brush_mask->bytes, + NULL);*/ + + TileManager *tm = gimp_drawable_get_tiles (drawable); + guint stride = tile_manager_width (tm) * tile_manager_bpp (tm); + guint len = stride * tile_manager_height (tm); + guchar *buf = g_malloc(len); + read_pixel_data (tm, 0, 0, + tile_manager_width (tm) - 1, + tile_manager_height (tm) - 1, + buf, stride); + g_file_set_contents ("r:\\out_drawable_00.raw", buf, len, NULL); + } + } +#endif + + /* Update the undo extents */ + core->x1 = MIN (core->x1, c_x); + core->y1 = MIN (core->y1, c_y); + core->x2 = MAX (core->x2, c_x + c_w) ; + core->y2 = MAX (core->y2, c_y + c_h) ; + + /* Update the drawable */ + if (update_freq_options->reduce_update_freq) + { + gdouble n; + gdouble r, v; + gint m; + + v = core->cur_coords.velocity - update_freq_options->v_threshold; + r = (core->canvas_buf->width + core->canvas_buf->height) / 2.0; + + if (v > 0 && r > update_freq_options->s_threshold) + { + n = v * 25.0; + + m = MIN (n * faster_pow (r / update_freq_options->s_threshold, + update_freq_options->gamma), + update_freq_options->max_n_dabs); + //g_printerr ("velo : %f / n : %f / threshold %d\n", core->cur_coords.velocity, n, (gint)(MIN (n, 25.0 - sqrt (r)))); + } + else + m = 0; + + if (core->update_count) + { + core->_x1 = MIN (core->_x1, c_x); + core->_y1 = MIN (core->_y1, c_y); + core->_x2 = MAX (core->_x2, c_x + c_w - 1); + core->_y2 = MAX (core->_y2, c_y + c_h - 1); + } + else + { + core->_x1 = c_x; + core->_x2 = c_x + c_w - 1; + core->_y1 = c_y; + core->_y2 = c_y + c_h - 1; + } + + if (++core->update_count >= m) + { + core->update_count = 0; + core->updated = TRUE; + + gimp_drawable_update (drawable, + core->_x1, + core->_y1, + core->_x2 - core->_x1 + 1, + core->_y2 - core->_y1 + 1); + } + else + core->updated = FALSE; + } + else + gimp_drawable_update (drawable, c_x, c_y, c_w, c_h); + +} + +static void +composite_dab (CompositeDabParam *params, + PixelRegion *srcPR, + PixelRegion *maskPR) +{ + gint width, height, bytes; + gint src_bytes; + gint src_stride, mask_stride; + guchar *src_data, *_src_data; + guchar *mask_data, *_mask_data; + + gint i, j; + + src_data = srcPR->data; + src_bytes = srcPR->bytes; + mask_data = maskPR->data; + width = maskPR->w; + height = maskPR->h; + bytes = maskPR->bytes; + src_stride = srcPR->rowstride; + mask_stride = maskPR->rowstride; + + for (i = 0; i < height; i++) + { + _src_data = src_data; + _mask_data = mask_data; + + for (j = 0; j < width; j++) + { + gdouble op, mask_op, paint_color_op, canvas_color_op, src_op; + gdouble factor1, factor2; + gdouble component; + +#if 0 + if (j == c_w / 2 && i == c_h / 2) + { + g_printerr ( "\nPos : %d %d\n", j, i); + g_printerr ( "Paint color: %f %f %f %f\n", params->_paint_color.r, params->_paint_color.g, params->_paint_color.b, params->paint_color->a); + g_printerr ( "Canvas color: %d %d %d %d\n", _src_data[0], _src_data[1], _src_data[2], _src_data[3]); + g_printerr ( "Opacity : %f\n", params->opacity); + } +#endif + if (_mask_data[0]) + { + mask_op = _mask_data[0] / 255.0; + + if (params->has_alpha && params->active_components[src_bytes - 1]) + { + gfloat n; + guint32 _n; + + src_op = _src_data[src_bytes - 1] / 255.0; + + /* workaround against insufficiency of opacity */ + /*if (params->paint_color->a > src_op) + op = pow (params->opacity, 1.0 / 1.5) * mask_op;*/ + n = params->paint_color.a - src_op; + _n = (*(guint32 *) &n) >> 31; + op = (params->opacity * _n + params->adjusted_opacity * (1 - _n)) * mask_op; + + component = (params->paint_color.a * op + src_op * (1.0 - op)) * 255.0/* + error.a*/; + _src_data[src_bytes - 1] = component + .5; + /*_error.a += component - _src_data[src_bytes - 1];*/ + } + else + src_op = 1.0; + + op = params->opacity * mask_op; + paint_color_op = params->paint_color.a * op; + + if (paint_color_op > 0.0) + { + canvas_color_op = (1.0 - paint_color_op) * src_op; + + factor1 = paint_color_op / (paint_color_op + canvas_color_op); + factor2 = 1.0 - factor1; + + component = params->_paint_color.r * factor1 + _src_data[0] * factor2/* + error.r*/; + _src_data[0] = component + .5; + /*_error.r += component - _src_data[0];*/ + if (params->is_rgb) + { + component = params->_paint_color.g * factor1 + _src_data[1] * factor2/* + error.g*/; + _src_data[1] = component + .5; + /*_error.g += component - _src_data[1];*/ + + component = params->_paint_color.b * factor1 + _src_data[2] * factor2/* + error.b*/; + _src_data[2] = component + .5; + /*_error.b += component - _src_data[2];*/ + } + } + } +#if 0 + if (j == c_w / 2 && i == c_h / 2) + { + g_printerr ( "Result color: %d %d %d %d\n", _src_data[0], _src_data[1], _src_data[2], _src_data[3]); + } +#endif + _src_data += src_bytes; + _mask_data++; + } + src_data += src_stride; + mask_data += mask_stride; + } +} /* end of iteration */ + + +static void +composite_textured_dab (CompositeDabParam *params, + PixelRegion *srcPR, + PixelRegion *maskPR) +{ + gint width, height, bytes; + gint src_bytes; + gint src_stride, mask_stride; + guchar *src_data, *_src_data; + guchar *mask_data, *_mask_data; + + gint i, j; + gint texture_off_x, _texture_off_x, texture_off_y; + guchar *texture_row_data; + + /* calc origin of texture buffer */ + texture_off_x = params->drawable_x + params->x + maskPR->x + params->texture_jitter_x; + if (texture_off_x < 0) + texture_off_x = params->texture_width + (texture_off_x % params->texture_width); + + texture_off_y = params->drawable_y + params->y + maskPR->y + params->texture_jitter_y; + if (texture_off_y < 0) + texture_off_y = params->texture_height + (texture_off_y % params->texture_height); + + src_data = srcPR->data; + src_bytes = srcPR->bytes; + mask_data = maskPR->data; + width = maskPR->w; + height = maskPR->h; + bytes = maskPR->bytes; + src_stride = srcPR->rowstride; + mask_stride = maskPR->rowstride; + +//g_printerr("<<"); + for (i = 0; i < height; i++, texture_off_y++) + { + _src_data = src_data; + _mask_data = mask_data; + + texture_off_y = texture_off_y % params->texture_height; + _texture_off_x = texture_off_x; + texture_row_data = params->texture_data + texture_off_y * params->texture_stride; + + for (j = 0; j < width; j++, _texture_off_x++) + { + gdouble op, mask_op, paint_color_op, canvas_color_op, src_op; + gdouble texture_op; + gdouble factor1, factor2; + gdouble component; + + _texture_off_x = _texture_off_x % params->texture_width; + + texture_op = *(texture_row_data + _texture_off_x * params->texture_bytes) / 255.0; + texture_op = CLAMP (texture_op + params->grain, 0.0, 1.0); + + if (_mask_data[0]) + { + mask_op = _mask_data[0] / 255.0; + +#if 0 + if (params->fringe) + { + texture_op = (texture_op * (1.0 - mask_op) + mask_op); + mask_op = CLAMP (mask_op * texture_op * params->fringe_contrast - params->fringe_contrast_offset, 0.0, 1.0); + } + else + mask_op *= texture_op; +#else + if (params->fringe) + texture_op = (texture_op * (1.0 - mask_op) + mask_op); + + if (params->fringe_contrast > 1.0) + mask_op = CLAMP (mask_op * texture_op * params->fringe_contrast - params->fringe_contrast_offset, 0.0, 1.0); + else + mask_op *= texture_op; +#endif + + if (mask_op) + { + if (params->has_alpha && params->active_components[src_bytes - 1]) + { + gfloat n; + guint32 _n; + + src_op = _src_data[src_bytes - 1] / 255.0; + + /* workaround against insufficiency of opacity */ + /*if (params->paint_color.a > src_op) + op = pow (params->opacity, 1.0 / 1.5) * mask_op;*/ + n = params->paint_color.a - src_op; + _n = (*(guint32 *) &n) >> 31; + op = (params->opacity * _n + params->adjusted_opacity * (1 - _n)) * mask_op; + + component = (params->paint_color.a * op + src_op * (1.0 - op)) * 255.0/* + error.a*/; + _src_data[src_bytes - 1] = component + .5; + /*_error.a += component - _src_data[src_bytes - 1];*/ + } + else + src_op = 1.0; + + op = params->opacity * mask_op; + paint_color_op = params->paint_color.a * op; + + if (paint_color_op > 0.0) + { + canvas_color_op = (1.0 - paint_color_op) * src_op; + + factor1 = paint_color_op / (paint_color_op + canvas_color_op); + factor2 = 1.0 - factor1; + + component = params->_paint_color.r * factor1 + _src_data[0] * factor2/* + error.r*/; + _src_data[0] = component + .5; + /*_error.r += component - _src_data[0];*/ + if (params->is_rgb) + { + component = params->_paint_color.g * factor1 + _src_data[1] * factor2/* + error.g*/; + _src_data[1] = component + .5; + /*_error.g += component - _src_data[1];*/ + + component = params->_paint_color.b * factor1 + _src_data[2] * factor2/* + error.b*/; + _src_data[2] = component + .5; + /*_error.b += component - _src_data[2];*/ + } + } + } + } + _src_data += src_bytes; + _mask_data++; + } + src_data += src_stride; + mask_data += mask_stride; + } +//g_printerr(">>"); +} /* end of iteration */ + +/* compositing with selection */ +static void +composite_dab_selection (CompositeDabParam *params, + PixelRegion *srcPR, + PixelRegion *maskPR, + PixelRegion *selPR) +{ + gint width, height, bytes; + gint src_bytes; + gint src_stride, mask_stride, sel_stride; + guchar *src_data, *_src_data; + guchar *mask_data, *_mask_data; + guchar *sel_data, *_sel_data; + + gint i, j; + + src_data = srcPR->data; + src_bytes = srcPR->bytes; + mask_data = maskPR->data; + sel_data = selPR->data; + width = maskPR->w; + height = maskPR->h; + bytes = maskPR->bytes; + src_stride = srcPR->rowstride; + mask_stride = maskPR->rowstride; + sel_stride = selPR->rowstride; + + for (i = 0; i < height; i++) + { + _src_data = src_data; + _mask_data = mask_data; + _sel_data = sel_data; + + for (j = 0; j < width; j++) + { + gdouble op, mask_op, paint_color_op, canvas_color_op, src_op; + gdouble factor1, factor2; + gdouble component; + + if (*_mask_data && *_sel_data) + { + mask_op = *_mask_data * *_sel_data / 65025.0; + + if (params->has_alpha && params->active_components[src_bytes - 1]) + { + gfloat n; + guint32 _n; + + src_op = _src_data[src_bytes - 1] / 255.0; + + /* workaround against insufficiency of opacity */ + /*if (params->paint_color->a > src_op) + op = pow (params->opacity, 1.0 / 1.5) * mask_op;*/ + n = params->paint_color.a - src_op; + _n = (*(guint32 *) &n) >> 31; + op = (params->opacity * _n + params->adjusted_opacity * (1 - _n)) * mask_op; + + component = (params->paint_color.a * op + src_op * (1.0 - op)) * 255.0/* + error.a*/; + _src_data[src_bytes - 1] = component + .5; + /*_error.a += component - _src_data[src_bytes - 1];*/ + } + else + src_op = 1.0; + + op = params->opacity * mask_op; + paint_color_op = params->paint_color.a * op; + + if (paint_color_op > 0.0) + { + canvas_color_op = (1.0 - paint_color_op) * src_op; + + factor1 = paint_color_op / (paint_color_op + canvas_color_op); + factor2 = 1.0 - factor1; + + component = params->_paint_color.r * factor1 + _src_data[0] * factor2/* + error.r*/; + _src_data[0] = component + .5; + /*_error.r += component - _src_data[0];*/ + if (params->is_rgb) + { + component = params->_paint_color.g * factor1 + _src_data[1] * factor2/* + error.g*/; + _src_data[1] = component + .5; + /*_error.g += component - _src_data[1];*/ + + component = params->_paint_color.b * factor1 + _src_data[2] * factor2/* + error.b*/; + _src_data[2] = component + .5; + /*_error.b += component - _src_data[2];*/ + } + } + } + _src_data += src_bytes; + _mask_data++; + _sel_data++; + } + src_data += src_stride; + mask_data += mask_stride; + sel_data += sel_stride; + } +} /* end of iteration */ + +static void +composite_textured_dab_selection (CompositeDabParam *params, + PixelRegion *srcPR, + PixelRegion *maskPR, + PixelRegion *selPR) +{ + gint width, height, bytes; + gint src_bytes; + gint src_stride, mask_stride, sel_stride; + guchar *src_data, *_src_data; + guchar *mask_data, *_mask_data; + guchar *sel_data, *_sel_data; + + gint i, j; + gint texture_off_x, _texture_off_x, texture_off_y; + guchar *texture_row_data; + + /* calc origin of texture buffer */ + texture_off_x = params->drawable_x + params->x + maskPR->x + params->texture_jitter_x; + if (texture_off_x < 0) + texture_off_x = params->texture_width + (texture_off_x % params->texture_width); + + texture_off_y = params->drawable_y + params->y + maskPR->y + params->texture_jitter_y; + if (texture_off_y < 0) + texture_off_y = params->texture_height + (texture_off_y % params->texture_height); + + src_data = srcPR->data; + src_bytes = srcPR->bytes; + mask_data = maskPR->data; + sel_data = selPR->data; + width = maskPR->w; + height = maskPR->h; + bytes = maskPR->bytes; + src_stride = srcPR->rowstride; + mask_stride = maskPR->rowstride; + sel_stride = selPR->rowstride; + + for (i = 0; i < height; i++, texture_off_y++) + { + _src_data = src_data; + _mask_data = mask_data; + _sel_data = sel_data; + + texture_off_y = texture_off_y % params->texture_height; + _texture_off_x = texture_off_x; + texture_row_data = params->texture_data + texture_off_y * params->texture_stride; + + for (j = 0; j < width; j++, _texture_off_x++) + { + gdouble op, mask_op, paint_color_op, canvas_color_op, src_op; + gdouble texture_op; + gdouble factor1, factor2; + gdouble component; + + _texture_off_x = _texture_off_x % params->texture_width; + + texture_op = *(texture_row_data + _texture_off_x * params->texture_bytes) / 255.0; + texture_op = CLAMP (texture_op + params->grain, 0.0, 1.0); + + if (*_mask_data && *_sel_data) + { + mask_op = *_mask_data * *_sel_data / 65025.0; + + if (params->fringe) + texture_op = (texture_op * (1.0 - mask_op) + mask_op); + + if (params->fringe_contrast > 1.0) + mask_op = CLAMP (mask_op * texture_op * params->fringe_contrast - params->fringe_contrast_offset, 0.0, 1.0); + else + mask_op *= texture_op; + + if (mask_op) + { + if (params->has_alpha && params->active_components[src_bytes - 1]) + { + gfloat n; + guint32 _n; + + src_op = _src_data[src_bytes - 1] / 255.0; + + /* workaround against insufficiency of opacity */ + /*if (params->paint_color.a > src_op) + op = pow (params->opacity, 1.0 / 1.5) * mask_op;*/ + n = params->paint_color.a - src_op; + _n = (*(guint32 *) &n) >> 31; + op = (params->opacity * _n + params->adjusted_opacity * (1 - _n)) * mask_op; + + component = (params->paint_color.a * op + src_op * (1.0 - op)) * 255.0/* + error.a*/; + _src_data[src_bytes - 1] = component + .5; + /*_error.a += component - _src_data[src_bytes - 1];*/ + } + else + src_op = 1.0; + + op = params->opacity * mask_op; + paint_color_op = params->paint_color.a * op; + + if (paint_color_op > 0.0) + { + canvas_color_op = (1.0 - paint_color_op) * src_op; + + factor1 = paint_color_op / (paint_color_op + canvas_color_op); + factor2 = 1.0 - factor1; + + component = params->_paint_color.r * factor1 + _src_data[0] * factor2/* + error.r*/; + _src_data[0] = component + .5; + /*_error.r += component - _src_data[0];*/ + if (params->is_rgb) + { + component = params->_paint_color.g * factor1 + _src_data[1] * factor2/* + error.g*/; + _src_data[1] = component + .5; + /*_error.g += component - _src_data[1];*/ + + component = params->_paint_color.b * factor1 + _src_data[2] * factor2/* + error.b*/; + _src_data[2] = component + .5; + /*_error.b += component - _src_data[2];*/ + } + } + } + } + _src_data += src_bytes; + _mask_data++; + _sel_data++; + } + src_data += src_stride; + mask_data += mask_stride; + sel_data += sel_stride; + } +} /* end of iteration */ +#endif --- gimp-2.6.6/app/paint/gimpmixbrush.h 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpmixbrush.h 2010-06-27 02:14:18 +0900 @@ -0,0 +1,81 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __GIMP_MIXBRUSH_H__ +#define __GIMP_MIXBRUSH_H__ + + +#include "gimppaintbrush.h" + + +/* Pressure control params */ + +typedef struct _PressureParams +{ + gdouble in_min; + gdouble in_factor; + gdouble out_min; + gdouble out_factor; + gboolean invert; +} PressureParams; + + +#define GIMP_TYPE_MIXBRUSH (gimp_mixbrush_get_type ()) +#define GIMP_MIXBRUSH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_MIXBRUSH, GimpMixbrush)) +#define GIMP_MIXBRUSH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_MIXBRUSH, GimpMixbrushClass)) +#define GIMP_IS_MIXBRUSH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_MIXBRUSH)) +#define GIMP_IS_MIXBRUSH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_MIXBRUSH)) +#define GIMP_MIXBRUSH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_MIXBRUSH, GimpMixbrushClass)) + + +typedef struct _GimpMixbrushClass GimpMixbrushClass; + +struct _GimpMixbrush +{ + GimpPaintbrush parent_instance; + + GimpDrawable *drawable; + GimpPaintOptions *paint_options; + TempBuf *mask; + PressureParams pr_texture_grain; + PressureParams pr_main_density; + PressureParams pr_main_rate; + PressureParams pr_canvas_density; + PressureParams pr_canvas_rate; + gint alpha_pix; + GimpRGB paint_color; + GimpRGB last_color; + GimpRGB hidden_color; + GimpRGB error; + GList *history; + gboolean use_alt_alpha_op; +}; + +struct _GimpMixbrushClass +{ + GimpPaintbrushClass parent_class; +}; + + +void gimp_mixbrush_register (Gimp *gimp, + GimpPaintRegisterCallback callback); + +GType gimp_mixbrush_get_type (void) G_GNUC_CONST; + + +#endif /* __GIMP_MIXBRUSH_H__ */ --- gimp-2.6.6/app/paint/gimpmixbrushoptions.c 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpmixbrushoptions.c 2010-06-27 02:14:18 +0900 @@ -0,0 +1,644 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include "libgimpconfig/gimpconfig.h" + +#include "paint-types.h" + +#include "gimppaintoptions.h" +#include "gimpmixbrushoptions.h" + + +#define MIXBRUSH_DEFAULT_USE_TEXTURE FALSE +#define MIXBRUSH_DEFAULT_TEXTURE_FRINGE FALSE +#define MIXBRUSH_DEFAULT_TEXTURE_FRINGE_CONTRAST 1.0 +#define MIXBRUSH_DEFAULT_TEXTURE_GRAIN 0.0 +#define MIXBRUSH_DEFAULT_TEXTURE_JITTER 0 + +#define MIXBRUSH_DEFAULT_MAIN_COLOR_DENSITY 0.5 +#define MIXBRUSH_DEFAULT_MAIN_COLOR_RATE 0.2 +#define MIXBRUSH_DEFAULT_CANVAS_COLOR_DENSITY 1.0 +#define MIXBRUSH_DEFAULT_CANVAS_COLOR_RATE 1.0 +#define MIXBRUSH_DEFAULT_PRESSURE_IN1 0.0 +#define MIXBRUSH_DEFAULT_PRESSURE_IN2 1.0 +#define MIXBRUSH_DEFAULT_PRESSURE_OUT1 0.5 +#define MIXBRUSH_DEFAULT_PRESSURE_OUT2 1.0 +#define MIXBRUSH_DEFAULT_CANVAS_PRESSURE_OUT1 1.0 +#define MIXBRUSH_DEFAULT_CANVAS_PRESSURE_OUT2 1.0 +#define MIXBRUSH_DEFAULT_DRYOUT 0.0 +#define MIXBRUSH_DEFAULT_DELAY 0 +#define MIXBRUSH_DEFAULT_TAIL FALSE +#define MIXBRUSH_DEFAULT_MERGED FALSE +#define MIXBRUSH_DEFAULT_PIGMENT TRUE +#define MIXBRUSH_DEFAULT_HIDDEN_COLOR GIMP_HIDDEN_COLOR_NORMAL +#define MIXBRUSH_DEFAULT_REMOVE_COLOR FALSE +#define MIXBRUSH_DEFAULT_SAMPLE_SIZE_LIMIT 1 +#define MIXBRUSH_DEFAULT_ALPHA_CHANNEL_MIXING TRUE +#define MIXBRUSH_DEFAULT_APPLICATION_MODE GIMP_PAINT_INCREMENTAL + + +enum +{ + PROP_0, + PROP_USE_TEXTURE, + PROP_TEXTURE_FRINGE, + PROP_TEXTURE_FRINGE_CONTRAST, + PROP_TEXTURE_GRAIN, + PROP_TEXTURE_GRAIN_PRESSURE_IN1, + PROP_TEXTURE_GRAIN_PRESSURE_IN2, + PROP_TEXTURE_GRAIN_PRESSURE_OUT1, + PROP_TEXTURE_GRAIN_PRESSURE_OUT2, + PROP_TEXTURE_JITTER, + + PROP_MAIN_COLOR_DENSITY, + PROP_MAIN_COLOR_RATE, + PROP_CANVAS_COLOR_DENSITY, + PROP_CANVAS_COLOR_RATE, + PROP_MAIN_COLOR_DENSITY_PRESSURE_IN1, + PROP_MAIN_COLOR_DENSITY_PRESSURE_IN2, + PROP_MAIN_COLOR_DENSITY_PRESSURE_OUT1, + PROP_MAIN_COLOR_DENSITY_PRESSURE_OUT2, + PROP_MAIN_COLOR_PRESSURE_IN1, + PROP_MAIN_COLOR_PRESSURE_IN2, + PROP_MAIN_COLOR_PRESSURE_OUT1, + PROP_MAIN_COLOR_PRESSURE_OUT2, + PROP_CANVAS_COLOR_DENSITY_PRESSURE_IN1, + PROP_CANVAS_COLOR_DENSITY_PRESSURE_IN2, + PROP_CANVAS_COLOR_DENSITY_PRESSURE_OUT1, + PROP_CANVAS_COLOR_DENSITY_PRESSURE_OUT2, + PROP_CANVAS_COLOR_PRESSURE_IN1, + PROP_CANVAS_COLOR_PRESSURE_IN2, + PROP_CANVAS_COLOR_PRESSURE_OUT1, + PROP_CANVAS_COLOR_PRESSURE_OUT2, + PROP_DRYOUT, + PROP_DELAY, + PROP_TAIL, + PROP_MERGED, + PROP_PIGMENT, + PROP_HIDDEN_COLOR, + PROP_REMOVE_COLOR, + PROP_SAMPLE_SIZE_LIMIT, + PROP_ALPHA_CHANNEL_MIXING, + PROP_APPLICATION_MODE +}; + + +static void gimp_mixbrush_options_finalize (GObject *object); +static void gimp_mixbrush_options_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_mixbrush_options_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + + +G_DEFINE_TYPE (GimpMixbrushOptions, gimp_mixbrush_options, + GIMP_TYPE_PAINT_OPTIONS) + +#define parent_class gimp_mixbrush_options_parent_class + + +static void +gimp_mixbrush_options_class_init (GimpMixbrushOptionsClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gimp_mixbrush_options_finalize; + object_class->set_property = gimp_mixbrush_options_set_property; + object_class->get_property = gimp_mixbrush_options_get_property; + + GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_USE_TEXTURE, + "use-texture", NULL, + MIXBRUSH_DEFAULT_USE_TEXTURE, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_TEXTURE_FRINGE, + "texture-fringe", NULL, + MIXBRUSH_DEFAULT_TEXTURE_FRINGE, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_TEXTURE_FRINGE_CONTRAST, + "texture-fringe-contrast", NULL, + 1.0, 10.0, MIXBRUSH_DEFAULT_TEXTURE_FRINGE_CONTRAST, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_TEXTURE_GRAIN, + "texture-grain", NULL, + -1.0, 1.0, MIXBRUSH_DEFAULT_TEXTURE_GRAIN, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_TEXTURE_GRAIN_PRESSURE_IN1, + "texture-grain-pressure-in1", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_IN1, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_TEXTURE_GRAIN_PRESSURE_IN2, + "texture-grain-pressure-in2", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_IN2, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_TEXTURE_GRAIN_PRESSURE_OUT1, + "texture-grain-pressure-out1", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_OUT1, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_TEXTURE_GRAIN_PRESSURE_OUT2, + "texture-grain-pressure-out2", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_OUT2, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_UINT (object_class, PROP_TEXTURE_JITTER, + "texture-jitter", NULL, + 0, 1000, MIXBRUSH_DEFAULT_TEXTURE_JITTER, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_MAIN_COLOR_DENSITY, + "main-color-density", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_MAIN_COLOR_DENSITY, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_MAIN_COLOR_RATE, + "main-color-rate", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_MAIN_COLOR_RATE, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_MAIN_COLOR_DENSITY_PRESSURE_IN1, + "main-color-density-pressure-in1", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_IN1, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_MAIN_COLOR_DENSITY_PRESSURE_IN2, + "main-color-density-pressure-in2", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_IN2, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_MAIN_COLOR_DENSITY_PRESSURE_OUT1, + "main-color-density-pressure-out1", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_OUT1, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_MAIN_COLOR_DENSITY_PRESSURE_OUT2, + "main-color-density-pressure-out2", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_OUT2, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_MAIN_COLOR_PRESSURE_IN1, + "main-color-pressure-in1", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_IN1, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_MAIN_COLOR_PRESSURE_IN2, + "main-color-pressure-in2", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_IN2, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_MAIN_COLOR_PRESSURE_OUT1, + "main-color-pressure-out1", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_OUT1, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_MAIN_COLOR_PRESSURE_OUT2, + "main-color-pressure-out2", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_OUT2, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_CANVAS_COLOR_DENSITY, + "canvas-color-density", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_CANVAS_COLOR_DENSITY, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_CANVAS_COLOR_RATE, + "canvas-color-rate", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_CANVAS_COLOR_RATE, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_CANVAS_COLOR_DENSITY_PRESSURE_IN1, + "canvas-color-density-pressure-in1", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_IN1, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_CANVAS_COLOR_DENSITY_PRESSURE_IN2, + "canvas-color-density-pressure-in2", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_IN2, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_CANVAS_COLOR_DENSITY_PRESSURE_OUT1, + "canvas-color-density-pressure-out1", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_CANVAS_PRESSURE_OUT1, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_CANVAS_COLOR_DENSITY_PRESSURE_OUT2, + "canvas-color-density-pressure-out2", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_CANVAS_PRESSURE_OUT2, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_CANVAS_COLOR_PRESSURE_IN1, + "canvas-color-pressure-in1", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_IN1, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_CANVAS_COLOR_PRESSURE_IN2, + "canvas-color-pressure-in2", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_PRESSURE_IN2, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_CANVAS_COLOR_PRESSURE_OUT1, + "canvas-color-pressure-out1", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_CANVAS_PRESSURE_OUT1, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_CANVAS_COLOR_PRESSURE_OUT2, + "canvas-color-pressure-out2", NULL, + 0.0, 1.0, MIXBRUSH_DEFAULT_CANVAS_PRESSURE_OUT2, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_UINT (object_class, PROP_DRYOUT, + "dryout", NULL, + 0, 10000, MIXBRUSH_DEFAULT_DRYOUT, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_UINT (object_class, PROP_DELAY, + "delay", NULL, + 0, 10, MIXBRUSH_DEFAULT_DELAY, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_TAIL, + "tail", NULL, + MIXBRUSH_DEFAULT_TAIL, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_MERGED, + "merged", NULL, + MIXBRUSH_DEFAULT_MERGED, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_PIGMENT, + "pigment", NULL, + MIXBRUSH_DEFAULT_PIGMENT, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_HIDDEN_COLOR, + "hidden-color", NULL, + GIMP_TYPE_HIDDEN_COLOR, + MIXBRUSH_DEFAULT_HIDDEN_COLOR, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_REMOVE_COLOR, + "remove-color", NULL, + MIXBRUSH_DEFAULT_REMOVE_COLOR, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_UINT (object_class, PROP_SAMPLE_SIZE_LIMIT, + "sample-size-limit", NULL, + 1, 50, MIXBRUSH_DEFAULT_SAMPLE_SIZE_LIMIT, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_ALPHA_CHANNEL_MIXING, + "alpha-channel-mixing", NULL, + MIXBRUSH_DEFAULT_ALPHA_CHANNEL_MIXING, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_APPLICATION_MODE, + "mixbrush-application-mode", NULL, + GIMP_TYPE_PAINT_APPLICATION_MODE, + MIXBRUSH_DEFAULT_APPLICATION_MODE, + GIMP_PARAM_STATIC_STRINGS); + + g_object_class_override_property (object_class, PROP_APPLICATION_MODE, "application-mode"); +} + +static void +gimp_mixbrush_options_init (GimpMixbrushOptions *options) +{ + options->texture_options = g_slice_new0 (GimpTextureOptions); +} + +static void +gimp_mixbrush_options_finalize (GObject *object) +{ + GimpMixbrushOptions *options = GIMP_MIXBRUSH_OPTIONS (object); + + g_slice_free (GimpTextureOptions, options->texture_options); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gimp_mixbrush_options_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpMixbrushOptions *options = GIMP_MIXBRUSH_OPTIONS (object); + GimpTextureOptions *texture_options = options->texture_options; + + switch (property_id) + { + case PROP_USE_TEXTURE: + texture_options->use_texture = g_value_get_boolean (value); + break; + case PROP_TEXTURE_FRINGE: + texture_options->fringe = g_value_get_boolean (value); + break; + case PROP_TEXTURE_FRINGE_CONTRAST: + texture_options->fringe_contrast = g_value_get_double (value); + break; + case PROP_TEXTURE_GRAIN: + texture_options->grain = g_value_get_double (value); + break; + case PROP_TEXTURE_GRAIN_PRESSURE_IN1: + texture_options->grain_pressure_in1 = g_value_get_double (value); + break; + case PROP_TEXTURE_GRAIN_PRESSURE_IN2: + texture_options->grain_pressure_in2 = g_value_get_double (value); + break; + case PROP_TEXTURE_GRAIN_PRESSURE_OUT1: + texture_options->grain_pressure_out1 = g_value_get_double (value); + break; + case PROP_TEXTURE_GRAIN_PRESSURE_OUT2: + texture_options->grain_pressure_out2 = g_value_get_double (value); + break; + case PROP_TEXTURE_JITTER: + texture_options->jitter = g_value_get_uint (value); + break; + case PROP_MAIN_COLOR_DENSITY: + options->main_color_density = g_value_get_double (value); + break; + case PROP_MAIN_COLOR_RATE: + options->main_color_rate = g_value_get_double (value); + break; + case PROP_MAIN_COLOR_DENSITY_PRESSURE_IN1: + options->main_color_density_pressure_in1 = g_value_get_double (value); + break; + case PROP_MAIN_COLOR_DENSITY_PRESSURE_IN2: + options->main_color_density_pressure_in2 = g_value_get_double (value); + break; + case PROP_MAIN_COLOR_DENSITY_PRESSURE_OUT1: + options->main_color_density_pressure_out1 = g_value_get_double (value); + break; + case PROP_MAIN_COLOR_DENSITY_PRESSURE_OUT2: + options->main_color_density_pressure_out2 = g_value_get_double (value); + break; + case PROP_MAIN_COLOR_PRESSURE_IN1: + options->main_color_pressure_in1 = g_value_get_double (value); + break; + case PROP_MAIN_COLOR_PRESSURE_IN2: + options->main_color_pressure_in2 = g_value_get_double (value); + break; + case PROP_MAIN_COLOR_PRESSURE_OUT1: + options->main_color_pressure_out1 = g_value_get_double (value); + break; + case PROP_MAIN_COLOR_PRESSURE_OUT2: + options->main_color_pressure_out2 = g_value_get_double (value); + break; + case PROP_CANVAS_COLOR_DENSITY: + options->canvas_color_density = g_value_get_double (value); + break; + case PROP_CANVAS_COLOR_RATE: + options->canvas_color_rate = g_value_get_double (value); + break; + case PROP_CANVAS_COLOR_DENSITY_PRESSURE_IN1: + options->canvas_color_density_pressure_in1 = g_value_get_double (value); + break; + case PROP_CANVAS_COLOR_DENSITY_PRESSURE_IN2: + options->canvas_color_density_pressure_in2 = g_value_get_double (value); + break; + case PROP_CANVAS_COLOR_DENSITY_PRESSURE_OUT1: + options->canvas_color_density_pressure_out1 = g_value_get_double (value); + break; + case PROP_CANVAS_COLOR_DENSITY_PRESSURE_OUT2: + options->canvas_color_density_pressure_out2 = g_value_get_double (value); + break; + case PROP_CANVAS_COLOR_PRESSURE_IN1: + options->canvas_color_pressure_in1 = g_value_get_double (value); + break; + case PROP_CANVAS_COLOR_PRESSURE_IN2: + options->canvas_color_pressure_in2 = g_value_get_double (value); + break; + case PROP_CANVAS_COLOR_PRESSURE_OUT1: + options->canvas_color_pressure_out1 = g_value_get_double (value); + break; + case PROP_CANVAS_COLOR_PRESSURE_OUT2: + options->canvas_color_pressure_out2 = g_value_get_double (value); + break; + case PROP_DRYOUT: + options->dryout = g_value_get_uint (value); + break; + case PROP_DELAY: + options->delay = g_value_get_uint (value); + break; + case PROP_TAIL: + options->tail = g_value_get_boolean (value); + break; + case PROP_MERGED: + options->merged = g_value_get_boolean (value); + break; + case PROP_PIGMENT: + options->pigment = g_value_get_boolean (value); + break; + case PROP_HIDDEN_COLOR: + options->hidden_color = g_value_get_enum (value); + break; + case PROP_REMOVE_COLOR: + options->remove_color = g_value_get_boolean (value); + break; + case PROP_SAMPLE_SIZE_LIMIT: + options->sample_size_limit = g_value_get_uint (value); + break; + case PROP_ALPHA_CHANNEL_MIXING: + options->alpha_channel_mixing = g_value_get_boolean (value); + break; + case PROP_APPLICATION_MODE: + GIMP_PAINT_OPTIONS (options)->application_mode = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_mixbrush_options_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpMixbrushOptions *options = GIMP_MIXBRUSH_OPTIONS (object); + GimpTextureOptions *texture_options = options->texture_options; + + switch (property_id) + { + case PROP_USE_TEXTURE: + g_value_set_boolean (value, texture_options->use_texture); + break; + case PROP_TEXTURE_FRINGE: + g_value_set_boolean (value, texture_options->fringe); + break; + case PROP_TEXTURE_FRINGE_CONTRAST: + g_value_set_double (value, texture_options->fringe_contrast); + break; + case PROP_TEXTURE_GRAIN: + g_value_set_double (value, texture_options->grain); + break; + case PROP_TEXTURE_GRAIN_PRESSURE_IN1: + g_value_set_double (value, texture_options->grain_pressure_in1); + break; + case PROP_TEXTURE_GRAIN_PRESSURE_IN2: + g_value_set_double (value, texture_options->grain_pressure_in2); + break; + case PROP_TEXTURE_GRAIN_PRESSURE_OUT1: + g_value_set_double (value, texture_options->grain_pressure_out1); + break; + case PROP_TEXTURE_GRAIN_PRESSURE_OUT2: + g_value_set_double (value, texture_options->grain_pressure_out2); + break; + case PROP_TEXTURE_JITTER: + g_value_set_uint (value, texture_options->jitter); + break; + case PROP_MAIN_COLOR_DENSITY: + g_value_set_double (value, options->main_color_density); + break; + case PROP_MAIN_COLOR_RATE: + g_value_set_double (value, options->main_color_rate); + break; + case PROP_MAIN_COLOR_DENSITY_PRESSURE_IN1: + g_value_set_double (value, options->main_color_density_pressure_in1); + break; + case PROP_MAIN_COLOR_DENSITY_PRESSURE_IN2: + g_value_set_double (value, options->main_color_density_pressure_in2); + break; + case PROP_MAIN_COLOR_DENSITY_PRESSURE_OUT1: + g_value_set_double (value, options->main_color_density_pressure_out1); + break; + case PROP_MAIN_COLOR_DENSITY_PRESSURE_OUT2: + g_value_set_double (value, options->main_color_density_pressure_out2); + break; + case PROP_MAIN_COLOR_PRESSURE_IN1: + g_value_set_double (value, options->main_color_pressure_in1); + break; + case PROP_MAIN_COLOR_PRESSURE_IN2: + g_value_set_double (value, options->main_color_pressure_in2); + break; + case PROP_MAIN_COLOR_PRESSURE_OUT1: + g_value_set_double (value, options->main_color_pressure_out1); + break; + case PROP_MAIN_COLOR_PRESSURE_OUT2: + g_value_set_double (value, options->main_color_pressure_out2); + break; + case PROP_CANVAS_COLOR_DENSITY: + g_value_set_double (value, options->canvas_color_density); + break; + case PROP_CANVAS_COLOR_RATE: + g_value_set_double (value, options->canvas_color_rate); + break; + case PROP_CANVAS_COLOR_DENSITY_PRESSURE_IN1: + g_value_set_double (value, options->canvas_color_density_pressure_in1); + break; + case PROP_CANVAS_COLOR_DENSITY_PRESSURE_IN2: + g_value_set_double (value, options->canvas_color_density_pressure_in2); + break; + case PROP_CANVAS_COLOR_DENSITY_PRESSURE_OUT1: + g_value_set_double (value, options->canvas_color_density_pressure_out1); + break; + case PROP_CANVAS_COLOR_DENSITY_PRESSURE_OUT2: + g_value_set_double (value, options->canvas_color_density_pressure_out2); + break; + case PROP_CANVAS_COLOR_PRESSURE_IN1: + g_value_set_double (value, options->canvas_color_pressure_in1); + break; + case PROP_CANVAS_COLOR_PRESSURE_IN2: + g_value_set_double (value, options->canvas_color_pressure_in2); + break; + case PROP_CANVAS_COLOR_PRESSURE_OUT1: + g_value_set_double (value, options->canvas_color_pressure_out1); + break; + case PROP_CANVAS_COLOR_PRESSURE_OUT2: + g_value_set_double (value, options->canvas_color_pressure_out2); + break; + case PROP_DRYOUT: + g_value_set_uint (value, options->dryout); + break; + case PROP_DELAY: + g_value_set_uint (value, options->delay); + break; + case PROP_TAIL: + g_value_set_boolean (value, options->tail); + break; + case PROP_MERGED: + g_value_set_boolean (value, options->merged); + break; + case PROP_PIGMENT: + g_value_set_boolean (value, options->pigment); + break; + case PROP_HIDDEN_COLOR: + g_value_set_enum (value, options->hidden_color); + break; + case PROP_REMOVE_COLOR: + g_value_set_boolean (value, options->remove_color); + break; + case PROP_SAMPLE_SIZE_LIMIT: + g_value_set_uint (value, options->sample_size_limit); + break; + case PROP_ALPHA_CHANNEL_MIXING: + g_value_set_boolean (value, options->alpha_channel_mixing); + break; + case PROP_APPLICATION_MODE: + g_value_set_enum (value, GIMP_PAINT_OPTIONS (options)->application_mode); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +GType +gimp_hidden_color_get_type (void) +{ + static const GEnumValue values[] = + { + { GIMP_HIDDEN_COLOR_NORMAL, "GIMP_HIDDEN_COLOR_NORMAL", "normal" }, + { GIMP_HIDDEN_COLOR_WHITE, "GIMP_HIDDEN_COLOR_WHITE", "white" }, + { GIMP_HIDDEN_COLOR_BACKGROUND, "GIMP_HIDDEN_COLOR_BACKGROUND", "background color" }, + { 0, NULL, NULL } + }; + + static const GimpEnumDesc descs[] = + { + { GIMP_HIDDEN_COLOR_NORMAL, "normal", NULL }, + { GIMP_HIDDEN_COLOR_WHITE, "white", NULL }, + { GIMP_HIDDEN_COLOR_BACKGROUND, "background color", NULL }, + { 0, NULL, NULL } + }; + + static GType type = 0; + + if (! type) + { + type = g_enum_register_static ("GimpHiddenColor", values); + gimp_enum_set_value_descriptions (type, descs); + } + + return type; +} --- gimp-2.6.6/app/paint/gimpmixbrushoptions.h 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpmixbrushoptions.h 2010-06-27 02:14:18 +0900 @@ -0,0 +1,109 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __GIMP_MIXBRUSH_OPTIONS_H__ +#define __GIMP_MIXBRUSH_OPTIONS_H__ + + +#include "gimppaintoptions.h" + + +/* enum(s) */ + +typedef enum +{ + GIMP_HIDDEN_COLOR_NORMAL, + GIMP_HIDDEN_COLOR_WHITE, + GIMP_HIDDEN_COLOR_BACKGROUND +} GimpHiddenColor; + +#define GIMP_TYPE_HIDDEN_COLOR (gimp_hidden_color_get_type ()) + +GType gimp_hidden_color_get_type (void) G_GNUC_CONST; + + + +#define GIMP_TYPE_MIXBRUSH_OPTIONS (gimp_mixbrush_options_get_type ()) +#define GIMP_MIXBRUSH_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_MIXBRUSH_OPTIONS, GimpMixbrushOptions)) +#define GIMP_MIXBRUSH_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_MIXBRUSH_OPTIONS, GimpMixbrushOptionsClass)) +#define GIMP_IS_MIXBRUSH_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_MIXBRUSH_OPTIONS)) +#define GIMP_IS_MIXBRUSH_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_MIXBRUSH_OPTIONS)) +#define GIMP_MIXBRUSH_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_MIXBRUSH_OPTIONS, GimpMixbrushOptionsClass)) + + +typedef struct _GimpMixbrushOptionsClass GimpMixbrushOptionsClass; + +typedef struct _GimpTextureOptions +{ + gboolean use_texture; + gboolean fringe; + gdouble fringe_contrast; + gdouble grain; + gdouble grain_pressure_in1; + gdouble grain_pressure_in2; + gdouble grain_pressure_out1; + gdouble grain_pressure_out2; + guint jitter; +} GimpTextureOptions; + +struct _GimpMixbrushOptions +{ + GimpPaintOptions parent_instance; + + GimpTextureOptions *texture_options; + gdouble main_color_density; /* 塗料の量 */ + gdouble main_color_rate; /* 塗料に前回の塗り色が混じる割合(実際は1-rate) */ + gdouble main_color_density_pressure_in1; + gdouble main_color_density_pressure_in2; + gdouble main_color_density_pressure_out1; + gdouble main_color_density_pressure_out2; + gdouble main_color_pressure_in1; + gdouble main_color_pressure_in2; + gdouble main_color_pressure_out1; + gdouble main_color_pressure_out2; + gdouble canvas_color_density; /* 地の色が混じる量 */ + gdouble canvas_color_rate; /* 着色前の地の色が混じる割合(実際は1-rate) */ + gdouble canvas_color_density_pressure_in1; + gdouble canvas_color_density_pressure_in2; + gdouble canvas_color_density_pressure_out1; + gdouble canvas_color_density_pressure_out2; + gdouble canvas_color_pressure_in1; + gdouble canvas_color_pressure_in2; + gdouble canvas_color_pressure_out1; + gdouble canvas_color_pressure_out2; + guint dryout; /* main_color_densityが完全に尽きる距離(pixel) */ + guint delay; + gboolean tail; + gboolean merged; + gboolean pigment; + GimpHiddenColor hidden_color; + gboolean remove_color; + guint sample_size_limit; + gboolean alpha_channel_mixing; +}; + +struct _GimpMixbrushOptionsClass +{ + GimpPaintOptionsClass parent_class; +}; + + +GType gimp_mixbrush_options_get_type (void) G_GNUC_CONST; + + +#endif /* __GIMP_MIXBRUSH_OPTIONS_H__ */ --- gimp-2.6.6/app/paint/gimppaintbrush.c 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimppaintbrush.c 2010-06-27 02:14:18 +0900 @@ -103,7 +103,7 @@ _gimp_paintbrush_motion (GimpPaintCore *paint_core, GimpDrawable *drawable, GimpPaintOptions *paint_options, - gdouble opacity) + gdouble flow) { GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_core); GimpContext *context = GIMP_CONTEXT (paint_options); @@ -114,11 +114,12 @@ GimpPaintApplicationMode paint_appl_mode; gdouble grad_point; gdouble hardness; + gdouble opacity; image = gimp_item_get_image (GIMP_ITEM (drawable)); - opacity *= gimp_paint_options_get_fade (paint_options, image, - paint_core->pixel_dist); + opacity = gimp_paint_options_get_fade (paint_options, image, + paint_core->pixel_dist); if (opacity == 0.0) return; @@ -143,13 +144,14 @@ &col[RED_PIX], &col[GREEN_PIX], &col[BLUE_PIX]); - col[ALPHA_PIX] = OPAQUE_OPACITY; + + col[area->bytes - 1] = OPAQUE_OPACITY; color_pixels (temp_buf_data (area), col, area->width * area->height, area->bytes); - paint_appl_mode = GIMP_PAINT_INCREMENTAL; + /*paint_appl_mode = GIMP_PAINT_INCREMENTAL;*/ } /* otherwise check if the brush has a pixmap and use that to color the area */ else if (brush_core->brush && brush_core->brush->pixmap) @@ -158,7 +160,7 @@ area, gimp_paint_options_get_brush_mode (paint_options)); - paint_appl_mode = GIMP_PAINT_INCREMENTAL; + /*paint_appl_mode = GIMP_PAINT_INCREMENTAL;*/ } /* otherwise fill the area with the foreground color */ else @@ -176,15 +178,19 @@ opacity *= gimp_paint_options_get_dynamic_opacity (paint_options, &paint_core->cur_coords); + flow *= gimp_context_get_flow (context); + hardness = gimp_paint_options_get_dynamic_hardness (paint_options, &paint_core->cur_coords); /* finally, let the brush core paste the colored area on the canvas */ gimp_brush_core_paste_canvas (brush_core, drawable, MIN (opacity, GIMP_OPACITY_OPAQUE), + flow, gimp_context_get_opacity (context), gimp_context_get_paint_mode (context), gimp_paint_options_get_brush_mode (paint_options), hardness, - paint_appl_mode); + paint_appl_mode, + paint_options->update_freq_options); } --- gimp-2.6.6/app/paint/gimppaintbrush.h 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimppaintbrush.h 2010-06-27 02:14:18 +0900 @@ -55,7 +55,7 @@ void _gimp_paintbrush_motion (GimpPaintCore *paint_core, GimpDrawable *drawable, GimpPaintOptions *paint_options, - gdouble opacity); + gdouble flow); #endif /* __GIMP_PAINTBRUSH_H__ */ --- gimp-2.6.6/app/paint/gimppaintcore.c 2008-12-28 08:13:04 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimppaintcore.c 2010-06-27 02:14:18 +0900 @@ -101,12 +101,17 @@ static void paint_mask_to_canvas_tiles (GimpPaintCore *core, PixelRegion *paint_maskPR, + gdouble paint_opacity_limit, gdouble paint_opacity); static void paint_mask_to_canvas_buf (GimpPaintCore *core, PixelRegion *paint_maskPR, gdouble paint_opacity); static void canvas_tiles_to_canvas_buf (GimpPaintCore *core); +static inline void drawable_update_reduced_freq (GimpDrawable *drawable, + GimpPaintCore *core, + GimpUpdateFreqOptions *update_freq_options); + G_DEFINE_TYPE (GimpPaintCore, gimp_paint_core, GIMP_TYPE_OBJECT) @@ -157,6 +162,7 @@ core->undo_tiles = NULL; core->saved_proj_tiles = NULL; + core->color_tiles = NULL; core->canvas_tiles = NULL; core->orig_buf = NULL; @@ -322,7 +328,14 @@ paint_options, paint_state, time); - core_class->post_paint (core, drawable, + if (paint_state == GIMP_PAINT_STATE_FINISH && ! core->updated) + gimp_drawable_update (drawable, + core->_x1, + core->_y1, + core->_x2 - core->_x1 + 1, + core->_y2 - core->_y1 + 1); + + core_class->post_paint (core, drawable, paint_options, paint_state, time); } @@ -380,6 +393,14 @@ tile_manager_bpp (tiles)); } + /* Allocate the color blocks structure */ + if (core->color_tiles) + tile_manager_unref (core->color_tiles); + + core->color_tiles = tile_manager_new (gimp_item_width (item), + gimp_item_height (item), + gimp_drawable_bytes_without_alpha (drawable)); + /* Allocate the canvas blocks structure */ if (core->canvas_tiles) tile_manager_unref (core->canvas_tiles); @@ -440,6 +461,26 @@ tile_manager_unref (core->saved_proj_tiles); core->saved_proj_tiles = NULL; } +#if 0 /* DEBUG */ + if (core->canvas_tiles) + { + TileManager *tm = core->canvas_tiles; + gint w = tile_manager_width (tm); + gint h = tile_manager_height (tm); + gint bytes = tile_manager_bpp (tm); + gint len = w * h * bytes; + guchar *buf = g_new (guchar, len); + + read_pixel_data (tm, 0, 0, w - 1, h - 1, buf, w * bytes ); + + g_file_set_contents ("out.raw", buf, len, NULL); + + g_free (buf); + g_printerr ("wrote out.raw w:%d h:%d bpp:%d\n",w,h,bytes); + } + else + g_printerr ("has no color tiles!\n"); +#endif gimp_viewable_preview_thaw (GIMP_VIEWABLE (drawable)); } @@ -528,6 +569,12 @@ core->saved_proj_tiles = NULL; } + if (core->color_tiles) + { + tile_manager_unref (core->color_tiles); + core->color_tiles = NULL; + } + if (core->canvas_tiles) { tile_manager_unref (core->canvas_tiles); @@ -776,14 +823,18 @@ return core->orig_proj_buf; } +/* paint_opacity_limitが従来のpaint_opacityにあたる */ +/* paint_opacityはPaintbrushのFlowパラメータのために使う */ void gimp_paint_core_paste (GimpPaintCore *core, PixelRegion *paint_maskPR, GimpDrawable *drawable, + gdouble paint_opacity_limit, gdouble paint_opacity, gdouble image_opacity, GimpLayerModeEffects paint_mode, - GimpPaintApplicationMode mode) + GimpPaintApplicationMode mode, + GimpUpdateFreqOptions *update_freq_options) { TileManager *alt = NULL; PixelRegion srcPR; @@ -832,13 +883,123 @@ if (paint_maskPR->tiles != core->canvas_tiles) { /* initialize any invalid canvas tiles */ +#if 1 +/* These macros came from paint-funcs-generic.c */ +#define INT_MULT(a,b,t) ((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8)) +#define INT_BLEND(a,b,alpha,tmp) (INT_MULT((a) - (b), alpha, tmp) + (b)) + gimp_paint_core_validate_canvas_tiles (core, core->canvas_buf->x, core->canvas_buf->y, core->canvas_buf->width, core->canvas_buf->height); - paint_mask_to_canvas_tiles (core, paint_maskPR, paint_opacity); +#if 0 /* DEBUG */ + static gint count = 0; + if ((count = (++count) % 500) == 0) + { + TileManager *tm = core->canvas_tiles; + gint w = tile_manager_width (tm); + gint h = tile_manager_height (tm); + gint bytes = tile_manager_bpp (tm); + gint len = w * h * bytes; + guchar *buf = g_new (guchar, len); + + read_pixel_data (tm, 0, 0, w - 1, h - 1, buf, w * bytes ); + + g_file_set_contents ("r:\\out.raw", buf, len, NULL); + + g_free (buf); + g_printerr ("wrote out.raw w:%d h:%d bpp:%d\n",w,h,bytes); + } + else + g_printerr ("count => %d\n", count); +#endif + /* Update the color tiles */ + { + PixelRegion canvas_bufPR, canvas_tilesPR, color_tilesPR, maskPR; + gpointer iter; + gint x, y, w, h; + + x = core->canvas_buf->x; + y = core->canvas_buf->y; + w = core->canvas_buf->width; + h = core->canvas_buf->height; + + pixel_region_init (&color_tilesPR, core->color_tiles, + x, y, w, h, + FALSE); + pixel_region_init (&canvas_tilesPR, core->canvas_tiles, + x, y, w, h, + FALSE); + pixel_region_init_temp_buf (&canvas_bufPR, + core->canvas_buf, + 0, 0, w, h); + + g_memmove (&maskPR, paint_maskPR, sizeof (maskPR)); + + for (iter = pixel_regions_register (4, &color_tilesPR, + &canvas_tilesPR, + &canvas_bufPR, + &maskPR); + iter != NULL; + iter = pixel_regions_process (iter)) + { + guchar *canvas_tiles = canvas_tilesPR.data; + guchar *paint_mask = maskPR.data; + guchar *color_tiles = color_tilesPR.data; + guchar *canvas_buf = canvas_bufPR.data; + gint i, j, k; + + for (i = 0; i < canvas_bufPR.h; i++) + { + for (j = 0;j < canvas_bufPR.w; j++) + { + guchar ct = canvas_tiles[j]; + guchar pm = paint_mask[j]; + gint color_offset = j * color_tilesPR.bytes; + gint canvas_offset = j * canvas_bufPR.bytes; + + gint tmp, blend_op; + guchar value; + + if ((blend_op = pm + ct)) + { + blend_op = CLAMP (pm * 255 / blend_op, 0, 255); + + for (k = 0; k < color_tilesPR.bytes; k++) + { + value = INT_BLEND (canvas_buf[canvas_offset + k], + color_tiles[color_offset + k], + blend_op, tmp); + value = INT_BLEND (canvas_buf[canvas_offset + k], + value, + pm, tmp); + + canvas_buf[canvas_offset + k] = value; + color_tiles[color_offset + k] = value; + } + } + } + canvas_tiles += canvas_tilesPR.rowstride; + canvas_buf += canvas_bufPR.rowstride; + paint_mask += maskPR.rowstride; + color_tiles += color_tilesPR.rowstride; + } + + } + } + + paint_mask_to_canvas_tiles (core, paint_maskPR, paint_opacity_limit, paint_opacity); +#else + gimp_paint_core_validate_canvas_tiles (core, + core->canvas_buf->x, + core->canvas_buf->y, + core->canvas_buf->width, + core->canvas_buf->height); + + paint_mask_to_canvas_tiles (core, paint_maskPR, paint_opacity_limit, paint_opacity); +#endif } canvas_tiles_to_canvas_buf (core); @@ -849,7 +1010,7 @@ */ else { - paint_mask_to_canvas_buf (core, paint_maskPR, paint_opacity); + paint_mask_to_canvas_buf (core, paint_maskPR, paint_opacity_limit); } /* intialize canvas buf source pixel regions */ @@ -873,11 +1034,14 @@ core->y2 = MAX (core->y2, core->canvas_buf->y + core->canvas_buf->height); /* Update the drawable */ - gimp_drawable_update (drawable, - core->canvas_buf->x, - core->canvas_buf->y, - core->canvas_buf->width, - core->canvas_buf->height); + if (update_freq_options->reduce_update_freq) + drawable_update_reduced_freq (drawable, core, update_freq_options); + else + gimp_drawable_update (drawable, + core->canvas_buf->x, + core->canvas_buf->y, + core->canvas_buf->width, + core->canvas_buf->height); } /* This works similarly to gimp_paint_core_paste. However, instead of @@ -894,7 +1058,8 @@ GimpDrawable *drawable, gdouble paint_opacity, gdouble image_opacity, - GimpPaintApplicationMode mode) + GimpPaintApplicationMode mode, + GimpUpdateFreqOptions *update_freq_options) { PixelRegion srcPR; @@ -902,8 +1067,10 @@ { gimp_paint_core_paste (core, paint_maskPR, drawable, paint_opacity, + GIMP_OPACITY_OPAQUE, image_opacity, GIMP_NORMAL_MODE, - mode); + mode, + update_freq_options); return; } @@ -929,7 +1096,7 @@ core->canvas_buf->height); /* combine the paint mask and the canvas tiles */ - paint_mask_to_canvas_tiles (core, paint_maskPR, paint_opacity); + paint_mask_to_canvas_tiles (core, paint_maskPR, paint_opacity, GIMP_OPACITY_OPAQUE); /* initialize the maskPR from the canvas tiles */ pixel_region_init (paint_maskPR, core->canvas_tiles, @@ -966,11 +1133,15 @@ core->y2 = MAX (core->y2, core->canvas_buf->y + core->canvas_buf->height) ; /* Update the drawable */ - gimp_drawable_update (drawable, - core->canvas_buf->x, - core->canvas_buf->y, - core->canvas_buf->width, - core->canvas_buf->height); + if (update_freq_options->reduce_update_freq) + drawable_update_reduced_freq (drawable, core, update_freq_options); + else + gimp_drawable_update (drawable, + core->canvas_buf->x, + core->canvas_buf->y, + core->canvas_buf->width, + core->canvas_buf->height); + } static void @@ -999,6 +1170,7 @@ static void paint_mask_to_canvas_tiles (GimpPaintCore *core, PixelRegion *paint_maskPR, + gdouble paint_opacity_limit, gdouble paint_opacity) { PixelRegion srcPR; @@ -1012,8 +1184,13 @@ TRUE); /* combine the mask to the canvas tiles */ - combine_mask_and_region (&srcPR, paint_maskPR, - paint_opacity * 255.999, GIMP_IS_AIRBRUSH (core)); + if (GIMP_IS_PAINTBRUSH (core)) + combine_mask_and_region_limit (&srcPR, paint_maskPR, + paint_opacity_limit * 255.999, + paint_opacity * 255.999); + else + combine_mask_and_region (&srcPR, paint_maskPR, + paint_opacity_limit * 255.999, FALSE); } static void @@ -1139,3 +1316,58 @@ } } } + + +static inline void +drawable_update_reduced_freq (GimpDrawable *drawable, + GimpPaintCore *core, + GimpUpdateFreqOptions *update_freq_options) +{ + gdouble n; + gdouble r, v; + gint m; + + v = core->cur_coords.velocity - update_freq_options->v_threshold; + r = (core->canvas_buf->width + core->canvas_buf->height) / 2.0; + + if (v > 0 && r > update_freq_options->s_threshold) + { + n = v * 25.0; + + m = MIN (n * faster_pow (r / update_freq_options->s_threshold, + update_freq_options->gamma), + update_freq_options->max_n_dabs); + //g_printerr ("velo : %f / n : %f / threshold %d\n", core->cur_coords.velocity, n, (gint)(MIN (n, 25.0 - sqrt (r)))); + } + else + m = 0; + + if (core->update_count) + { + core->_x1 = MIN (core->_x1, core->canvas_buf->x); + core->_y1 = MIN (core->_y1, core->canvas_buf->y); + core->_x2 = MAX (core->_x2, core->canvas_buf->x + core->canvas_buf->width - 1); + core->_y2 = MAX (core->_y2, core->canvas_buf->y + core->canvas_buf->height - 1); + } + else + { + core->_x1 = core->canvas_buf->x; + core->_x2 = core->canvas_buf->x + core->canvas_buf->width - 1; + core->_y1 = core->canvas_buf->y; + core->_y2 = core->canvas_buf->y + core->canvas_buf->height - 1; + } + + if (++core->update_count >= m) + { + core->update_count = 0; + core->updated = TRUE; + + gimp_drawable_update (drawable, + core->_x1, + core->_y1, + core->_x2 - core->_x1 + 1, + core->_y2 - core->_y1 + 1); + } + else + core->updated = FALSE; +} --- gimp-2.6.6/app/paint/gimppaintcore.h 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimppaintcore.h 2010-06-27 02:14:18 +0900 @@ -23,6 +23,8 @@ #include "libgimpmath/gimpvector.h" #include "core/gimpobject.h" +#include "gimppaintoptions.h" + #define GIMP_TYPE_PAINT_CORE (gimp_paint_core_get_type ()) #define GIMP_PAINT_CORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_PAINT_CORE, GimpPaintCore)) @@ -59,11 +61,18 @@ TileManager *undo_tiles; /* tiles which have been modified */ TileManager *saved_proj_tiles; /* proj tiles which have been modified */ + TileManager *color_tiles; /* the buffer to paint the color to */ TileManager *canvas_tiles; /* the buffer to paint the mask to */ TempBuf *orig_buf; /* the unmodified drawable pixels */ TempBuf *orig_proj_buf; /* the unmodified projection pixels */ TempBuf *canvas_buf; /* the buffer to paint pixels to */ + + /* to reduce update frequency */ + gint update_count; + gboolean updated; + gint _x1, _y1; + gint _x2, _y2; }; struct _GimpPaintCoreClass @@ -154,16 +163,19 @@ void gimp_paint_core_paste (GimpPaintCore *core, PixelRegion *paint_maskPR, GimpDrawable *drawable, + gdouble paint_opacity_limit, gdouble paint_opacity, gdouble image_opacity, GimpLayerModeEffects paint_mode, - GimpPaintApplicationMode mode); + GimpPaintApplicationMode mode, + GimpUpdateFreqOptions *update_freq_options); void gimp_paint_core_replace (GimpPaintCore *core, PixelRegion *paint_maskPR, GimpDrawable *drawable, gdouble paint_opacity, gdouble image_opacity, - GimpPaintApplicationMode mode); + GimpPaintApplicationMode mode, + GimpUpdateFreqOptions *update_freq_options); void gimp_paint_core_validate_undo_tiles (GimpPaintCore *core, GimpDrawable *drawable, @@ -184,4 +196,20 @@ gint h); +/* Utility function(s) */ +static inline gdouble faster_pow (gdouble a, gdouble b) +{ + guchar n[8] = "\0\0\0\0\0\0\0\0"; + guint32 i; + + (*((gdouble *)n)) = a; + i = (*((guint64 *)n)) >> 32; + + i = (guint32)(b * ((gint32)i - 1072632447) + 1072632447); + (*((guint64 *)n)) = (guint64)i << 32; + + return (*((gdouble *)n)); +} + + #endif /* __GIMP_PAINT_CORE_H__ */ --- gimp-2.6.6/app/paint/gimppaintoptions.c 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimppaintoptions.c 2010-06-27 02:14:18 +0900 @@ -34,48 +34,58 @@ #include "gimppaintoptions.h" -#define DEFAULT_BRUSH_SCALE 1.0 -#define DEFAULT_APPLICATION_MODE GIMP_PAINT_CONSTANT -#define DEFAULT_HARD FALSE - -#define DEFAULT_DYNAMICS_EXPANDED FALSE - -#define DEFAULT_PRESSURE_OPACITY TRUE -#define DEFAULT_PRESSURE_HARDNESS FALSE -#define DEFAULT_PRESSURE_RATE FALSE -#define DEFAULT_PRESSURE_SIZE FALSE -#define DEFAULT_PRESSURE_INVERSE_SIZE FALSE -#define DEFAULT_PRESSURE_COLOR FALSE -#define DEFAULT_PRESSURE_PRESCALE 1.0 - -#define DEFAULT_VELOCITY_OPACITY FALSE -#define DEFAULT_VELOCITY_HARDNESS FALSE -#define DEFAULT_VELOCITY_RATE FALSE -#define DEFAULT_VELOCITY_SIZE FALSE -#define DEFAULT_VELOCITY_INVERSE_SIZE FALSE -#define DEFAULT_VELOCITY_COLOR FALSE -#define DEFAULT_VELOCITY_PRESCALE 1.0 - -#define DEFAULT_RANDOM_OPACITY FALSE -#define DEFAULT_RANDOM_HARDNESS FALSE -#define DEFAULT_RANDOM_RATE FALSE -#define DEFAULT_RANDOM_SIZE FALSE -#define DEFAULT_RANDOM_INVERSE_SIZE FALSE -#define DEFAULT_RANDOM_COLOR FALSE -#define DEFAULT_RANDOM_PRESCALE 1.0 - -#define DEFAULT_USE_FADE FALSE -#define DEFAULT_FADE_LENGTH 100.0 -#define DEFAULT_FADE_UNIT GIMP_UNIT_PIXEL - -#define DEFAULT_USE_JITTER FALSE -#define DEFAULT_JITTER_AMOUNT 0.2 - -#define DEFAULT_USE_GRADIENT FALSE -#define DEFAULT_GRADIENT_REVERSE FALSE -#define DEFAULT_GRADIENT_REPEAT GIMP_REPEAT_TRIANGULAR -#define DEFAULT_GRADIENT_LENGTH 100.0 -#define DEFAULT_GRADIENT_UNIT GIMP_UNIT_PIXEL +#define DEFAULT_BRUSH_SCALE 1.0 +#define DEFAULT_APPLICATION_MODE GIMP_PAINT_CONSTANT +#define DEFAULT_HARD FALSE + +#define DEFAULT_DYNAMICS_EXPANDED FALSE + +#define DEFAULT_PRESSURE_OPACITY TRUE +#define DEFAULT_PRESSURE_HARDNESS FALSE +#define DEFAULT_PRESSURE_RATE FALSE +#define DEFAULT_PRESSURE_SIZE FALSE +#define DEFAULT_PRESSURE_INVERSE_SIZE FALSE +#define DEFAULT_PRESSURE_COLOR FALSE +#define DEFAULT_PRESSURE_PRESCALE 1.0 +#define DEFAULT_PRESSURE_MIN_SCALE 0 +#define DEFAULT_PRESSURE_POWER_SIZE 0.5 + +#define DEFAULT_VELOCITY_OPACITY FALSE +#define DEFAULT_VELOCITY_HARDNESS FALSE +#define DEFAULT_VELOCITY_RATE FALSE +#define DEFAULT_VELOCITY_SIZE FALSE +#define DEFAULT_VELOCITY_INVERSE_SIZE FALSE +#define DEFAULT_VELOCITY_COLOR FALSE +#define DEFAULT_VELOCITY_PRESCALE 1.0 + +#define DEFAULT_RANDOM_OPACITY FALSE +#define DEFAULT_RANDOM_HARDNESS FALSE +#define DEFAULT_RANDOM_RATE FALSE +#define DEFAULT_RANDOM_SIZE FALSE +#define DEFAULT_RANDOM_INVERSE_SIZE FALSE +#define DEFAULT_RANDOM_COLOR FALSE +#define DEFAULT_RANDOM_PRESCALE 1.0 + +#define DEFAULT_USE_FADE FALSE +#define DEFAULT_FADE_LENGTH 100.0 +#define DEFAULT_FADE_UNIT GIMP_UNIT_PIXEL + +#define DEFAULT_USE_JITTER FALSE +#define DEFAULT_JITTER_AMOUNT 0.2 + +#define DEFAULT_USE_GRADIENT FALSE +#define DEFAULT_GRADIENT_REVERSE FALSE +#define DEFAULT_GRADIENT_REPEAT GIMP_REPEAT_TRIANGULAR +#define DEFAULT_GRADIENT_LENGTH 100.0 +#define DEFAULT_GRADIENT_UNIT GIMP_UNIT_PIXEL + +#define DEFAULT_REDUCE_UPDATE_FREQ FALSE +#define DEFAULT_UPDATE_FREQ_S_THRESHOLD 30.0 +#define DEFAULT_UPDATE_FREQ_V_THRESHOLD 0.015 +#define DEFAULT_UPDATE_FREQ_GAMMA 1.35 +#define DEFAULT_UPDATE_FREQ_MAX_N_DABS 18 + +#define DEFAULT_MAX_COORD_SMOOTH 0.8 enum @@ -96,6 +106,8 @@ PROP_PRESSURE_INVERSE_SIZE, PROP_PRESSURE_COLOR, PROP_PRESSURE_PRESCALE, + PROP_PRESSURE_MIN_SCALE, + PROP_PRESSURE_POWER_SIZE, PROP_VELOCITY_OPACITY, PROP_VELOCITY_HARDNESS, @@ -131,7 +143,15 @@ PROP_PATTERN_VIEW_TYPE, PROP_PATTERN_VIEW_SIZE, PROP_GRADIENT_VIEW_TYPE, - PROP_GRADIENT_VIEW_SIZE + PROP_GRADIENT_VIEW_SIZE, + + PROP_REDUCE_UPDATE_FREQ, + PROP_UPDATE_FREQ_S_THRESHOLD, + PROP_UPDATE_FREQ_V_THRESHOLD, + PROP_UPDATE_FREQ_GAMMA, + PROP_UPDATE_FREQ_MAX_N_DABS, + + PROP_MAX_COORD_SMOOTH }; @@ -224,6 +244,14 @@ "pressure-prescale", NULL, 0.0, 1.0, DEFAULT_PRESSURE_PRESCALE, GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_PRESSURE_MIN_SCALE, + "pressure-min-scale", NULL, + 0.0, 1.0, DEFAULT_PRESSURE_MIN_SCALE, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_PRESSURE_POWER_SIZE, + "pressure-power-size", NULL, + 0.1, 10.0, DEFAULT_PRESSURE_POWER_SIZE, + GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_VELOCITY_OPACITY, "velocity-opacity", NULL, @@ -362,6 +390,34 @@ GIMP_VIEWABLE_MAX_BUTTON_SIZE, GIMP_VIEW_SIZE_LARGE, GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_REDUCE_UPDATE_FREQ, + "reduce-update-frequency", NULL, + DEFAULT_REDUCE_UPDATE_FREQ, + GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_DONT_RESTORE_SECONDARY); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_UPDATE_FREQ_S_THRESHOLD, + "update-freq-size-threshold", NULL, + 0.1, 100.0, DEFAULT_UPDATE_FREQ_S_THRESHOLD, + GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_DONT_RESTORE_SECONDARY); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_UPDATE_FREQ_V_THRESHOLD, + "update-freq-velo-threshold", NULL, + 0.001, 0.1, DEFAULT_UPDATE_FREQ_V_THRESHOLD, + GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_DONT_RESTORE_SECONDARY); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_UPDATE_FREQ_GAMMA, + "update-freq-gamma", NULL, + 0.1, 2.5, DEFAULT_UPDATE_FREQ_GAMMA, + GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_DONT_RESTORE_SECONDARY); + GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_UPDATE_FREQ_MAX_N_DABS, + "update-freq-max-n-dabs", NULL, + 5, 40, DEFAULT_UPDATE_FREQ_MAX_N_DABS, + GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_DONT_RESTORE_SECONDARY); + + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_MAX_COORD_SMOOTH, + "paint-max-coord-smooth", NULL, + 0.0, 1.0, DEFAULT_MAX_COORD_SMOOTH, + GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_DONT_RESTORE); + + g_object_class_override_property (object_class, PROP_MAX_COORD_SMOOTH, "max-coord-smooth"); } static void @@ -369,12 +425,13 @@ { options->application_mode_save = DEFAULT_APPLICATION_MODE; - options->pressure_options = g_slice_new0 (GimpDynamicOptions); - options->velocity_options = g_slice_new0 (GimpDynamicOptions); - options->random_options = g_slice_new0 (GimpDynamicOptions); - options->fade_options = g_slice_new0 (GimpFadeOptions); - options->jitter_options = g_slice_new0 (GimpJitterOptions); - options->gradient_options = g_slice_new0 (GimpGradientOptions); + options->pressure_options = g_slice_new0 (GimpDynamicOptions); + options->velocity_options = g_slice_new0 (GimpDynamicOptions); + options->random_options = g_slice_new0 (GimpDynamicOptions); + options->fade_options = g_slice_new0 (GimpFadeOptions); + options->jitter_options = g_slice_new0 (GimpJitterOptions); + options->gradient_options = g_slice_new0 (GimpGradientOptions); + options->update_freq_options = g_slice_new0 (GimpUpdateFreqOptions); } static void @@ -385,12 +442,13 @@ if (options->paint_info) g_object_unref (options->paint_info); - g_slice_free (GimpDynamicOptions, options->pressure_options); - g_slice_free (GimpDynamicOptions, options->velocity_options); - g_slice_free (GimpDynamicOptions, options->random_options); - g_slice_free (GimpFadeOptions, options->fade_options); - g_slice_free (GimpJitterOptions, options->jitter_options); - g_slice_free (GimpGradientOptions, options->gradient_options); + g_slice_free (GimpDynamicOptions, options->pressure_options); + g_slice_free (GimpDynamicOptions, options->velocity_options); + g_slice_free (GimpDynamicOptions, options->random_options); + g_slice_free (GimpFadeOptions, options->fade_options); + g_slice_free (GimpJitterOptions, options->jitter_options); + g_slice_free (GimpGradientOptions, options->gradient_options); + g_slice_free (GimpUpdateFreqOptions, options->update_freq_options); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -401,13 +459,14 @@ const GValue *value, GParamSpec *pspec) { - GimpPaintOptions *options = GIMP_PAINT_OPTIONS (object); - GimpDynamicOptions *pressure_options = options->pressure_options; - GimpDynamicOptions *velocity_options = options->velocity_options; - GimpDynamicOptions *random_options = options->random_options; - GimpFadeOptions *fade_options = options->fade_options; - GimpJitterOptions *jitter_options = options->jitter_options; - GimpGradientOptions *gradient_options = options->gradient_options; + GimpPaintOptions *options = GIMP_PAINT_OPTIONS (object); + GimpDynamicOptions *pressure_options = options->pressure_options; + GimpDynamicOptions *velocity_options = options->velocity_options; + GimpDynamicOptions *random_options = options->random_options; + GimpFadeOptions *fade_options = options->fade_options; + GimpJitterOptions *jitter_options = options->jitter_options; + GimpGradientOptions *gradient_options = options->gradient_options; + GimpUpdateFreqOptions *update_freq_options = options->update_freq_options; switch (property_id) { @@ -459,6 +518,14 @@ pressure_options->prescale = g_value_get_double (value); break; + case PROP_PRESSURE_MIN_SCALE: + pressure_options->min_scale = g_value_get_double (value); + break; + + case PROP_PRESSURE_POWER_SIZE: + pressure_options->power_size = g_value_get_double (value); + break; + case PROP_VELOCITY_OPACITY: velocity_options->opacity = g_value_get_boolean (value); break; @@ -579,6 +646,26 @@ options->gradient_view_size = g_value_get_int (value); break; + case PROP_REDUCE_UPDATE_FREQ: + update_freq_options->reduce_update_freq = g_value_get_boolean (value); + break; + case PROP_UPDATE_FREQ_S_THRESHOLD: + update_freq_options->s_threshold = g_value_get_double (value); + break; + case PROP_UPDATE_FREQ_V_THRESHOLD: + update_freq_options->v_threshold = g_value_get_double (value); + break; + case PROP_UPDATE_FREQ_GAMMA: + update_freq_options->gamma = g_value_get_double (value); + break; + case PROP_UPDATE_FREQ_MAX_N_DABS: + update_freq_options->max_n_dabs = g_value_get_int (value); + break; + + case PROP_MAX_COORD_SMOOTH: + GIMP_TOOL_OPTIONS (options)->max_coord_smooth = g_value_get_double (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -591,13 +678,14 @@ GValue *value, GParamSpec *pspec) { - GimpPaintOptions *options = GIMP_PAINT_OPTIONS (object); - GimpDynamicOptions *pressure_options = options->pressure_options; - GimpDynamicOptions *velocity_options = options->velocity_options; - GimpDynamicOptions *random_options = options->random_options; - GimpFadeOptions *fade_options = options->fade_options; - GimpJitterOptions *jitter_options = options->jitter_options; - GimpGradientOptions *gradient_options = options->gradient_options; + GimpPaintOptions *options = GIMP_PAINT_OPTIONS (object); + GimpDynamicOptions *pressure_options = options->pressure_options; + GimpDynamicOptions *velocity_options = options->velocity_options; + GimpDynamicOptions *random_options = options->random_options; + GimpFadeOptions *fade_options = options->fade_options; + GimpJitterOptions *jitter_options = options->jitter_options; + GimpGradientOptions *gradient_options = options->gradient_options; + GimpUpdateFreqOptions *update_freq_options = options->update_freq_options; switch (property_id) { @@ -649,6 +737,14 @@ g_value_set_double (value, pressure_options->prescale); break; + case PROP_PRESSURE_MIN_SCALE: + g_value_set_double (value, pressure_options->min_scale); + break; + + case PROP_PRESSURE_POWER_SIZE: + g_value_set_double (value, pressure_options->power_size); + break; + case PROP_VELOCITY_OPACITY: g_value_set_boolean (value, velocity_options->opacity); break; @@ -769,6 +865,26 @@ g_value_set_int (value, options->gradient_view_size); break; + case PROP_REDUCE_UPDATE_FREQ: + g_value_set_boolean (value, update_freq_options->reduce_update_freq); + break; + case PROP_UPDATE_FREQ_S_THRESHOLD: + g_value_set_double (value, update_freq_options->s_threshold); + break; + case PROP_UPDATE_FREQ_V_THRESHOLD: + g_value_set_double (value, update_freq_options->v_threshold); + break; + case PROP_UPDATE_FREQ_GAMMA: + g_value_set_double (value, update_freq_options->gamma); + break; + case PROP_UPDATE_FREQ_MAX_N_DABS: + g_value_set_int (value, update_freq_options->max_n_dabs); + break; + + case PROP_MAX_COORD_SMOOTH: + g_value_set_double (value, GIMP_TOOL_OPTIONS (options)->max_coord_smooth); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -779,7 +895,7 @@ gimp_paint_options_notify (GObject *object, GParamSpec *pspec) { - GimpPaintOptions *options = GIMP_PAINT_OPTIONS (object); + /*GimpPaintOptions *options = GIMP_PAINT_OPTIONS (object); if (pspec->param_id == PROP_USE_GRADIENT) { @@ -797,7 +913,7 @@ } if (G_OBJECT_CLASS (parent_class)->notify) - G_OBJECT_CLASS (parent_class)->notify (object, pspec); + G_OBJECT_CLASS (parent_class)->notify (object, pspec);*/ } GimpPaintOptions * @@ -1081,8 +1197,9 @@ gboolean use_dynamics) { gdouble scale = 1.0; + gdouble min_scale = paint_options->pressure_options->min_scale; - if (use_dynamics) + if (use_dynamics && min_scale < 1.0) { gdouble pressure = -1.0; gdouble velocity = -1.0; @@ -1122,14 +1239,18 @@ random, paint_options->random_options->prescale); - if (scale < 1 / 64.0) - scale = 1 / 8.0; - else - scale = sqrt (scale); + scale = pow (scale, paint_options->pressure_options->power_size); + + if (min_scale > 0) + scale = min_scale + (1.0 - min_scale) * scale; + + //scale = MAX (scale, 1 / 8.0); } scale *= paint_options->brush_scale; + //g_printerr ("Result of modefied code: %f, pressure: %f\n",scale, coords->pressure); + return scale; } --- gimp-2.6.6/app/paint/gimppaintoptions.h 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimppaintoptions.h 2010-06-27 02:14:18 +0900 @@ -34,6 +34,7 @@ typedef struct _GimpFadeOptions GimpFadeOptions; typedef struct _GimpJitterOptions GimpJitterOptions; typedef struct _GimpGradientOptions GimpGradientOptions; +typedef struct _GimpUpdateFreqOptions GimpUpdateFreqOptions; struct _GimpDynamicOptions { @@ -44,6 +45,8 @@ gboolean inverse_size; gboolean color; gdouble prescale; + gdouble min_scale; + gdouble power_size; }; struct _GimpFadeOptions @@ -68,6 +71,15 @@ GimpRepeatMode gradient_repeat; }; +struct _GimpUpdateFreqOptions +{ + gboolean reduce_update_freq; + gdouble s_threshold; + gdouble v_threshold; + gdouble gamma; + gint max_n_dabs; +}; + #define GIMP_TYPE_PAINT_OPTIONS (gimp_paint_options_get_type ()) #define GIMP_PAINT_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_PAINT_OPTIONS, GimpPaintOptions)) @@ -109,6 +121,8 @@ GimpViewSize pattern_view_size; GimpViewType gradient_view_type; GimpViewSize gradient_view_size; + + GimpUpdateFreqOptions *update_freq_options; }; struct _GimpPaintOptionsClass --- gimp-2.6.6/app/paint/gimpsmudge.c 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/gimpsmudge.c 2010-06-27 02:14:18 +0900 @@ -315,7 +315,8 @@ gimp_context_get_opacity (context), gimp_paint_options_get_brush_mode (paint_options), hardness, - GIMP_PAINT_INCREMENTAL); + GIMP_PAINT_INCREMENTAL, + paint_options->update_freq_options); } static void --- gimp-2.6.6/app/paint/paint-types.h 2008-11-21 07:43:08 +0900 +++ gimp-painter--2.6.6-20100627/app/paint/paint-types.h 2010-06-27 02:14:18 +0900 @@ -41,6 +41,8 @@ typedef struct _GimpPencil GimpPencil; typedef struct _GimpPerspectiveClone GimpPerspectiveClone; typedef struct _GimpSmudge GimpSmudge; +typedef struct _GimpInk2 GimpInk2; +typedef struct _GimpMixbrush GimpMixbrush; /* paint options */ @@ -57,12 +59,15 @@ typedef struct _GimpPencilOptions GimpPencilOptions; typedef struct _GimpPerspectiveCloneOptions GimpPerspectiveCloneOptions; typedef struct _GimpSmudgeOptions GimpSmudgeOptions; +typedef struct _GimpInk2Options GimpInk2Options; +typedef struct _GimpMixbrushOptions GimpMixbrushOptions; /* paint undos */ typedef struct _GimpPaintCoreUndo GimpPaintCoreUndo; typedef struct _GimpInkUndo GimpInkUndo; +typedef struct _GimpInk2Undo GimpInk2Undo; /* functions */ --- gimp-2.6.6/app/paint-funcs/paint-funcs-generic.h 2008-11-21 07:43:00 +0900 +++ gimp-painter--2.6.6-20100627/app/paint-funcs/paint-funcs-generic.h 2010-06-27 02:14:19 +0900 @@ -1533,6 +1533,48 @@ inline void +combine_mask_and_alpha_channel_stroke_limit (guchar *src, + const guchar *mask, + guint limit, + guint opacity, + guint length, + guint bytes) +{ + /* align with alpha channel */ + src += bytes - 1; + + if (opacity != 255 || limit != 255) + { + gint tmp; + gint _opacity = INT_MULT (opacity, limit, tmp); + + while (length --) + { + if (limit > *src) + { + gint mask_val = INT_MULT (*mask, _opacity, tmp); + + *src = *src + INT_MULT ((limit - *src) , mask_val, tmp); + } + + src += bytes; + mask++; + } + } + else + while (length --) + { + gint tmp; + + *src = *src + INT_MULT ((255 - *src) , *mask, tmp); + + src += bytes; + mask++; + } +} + + +inline void copy_gray_to_inten_a_pixels (const guchar *src, guchar *dest, guint length, --- gimp-2.6.6/app/paint-funcs/paint-funcs.c 2008-11-21 07:43:00 +0900 +++ gimp-painter--2.6.6-20100627/app/paint-funcs/paint-funcs.c 2010-06-27 02:14:19 +0900 @@ -3906,6 +3906,26 @@ } +static void +combine_mask_and_sub_region_stroke_limit (guint *param, + PixelRegion *src, + PixelRegion *mask) +{ + guchar *s = src->data; + const guchar *m = mask->data; + gint h = src->h; + guint limit = param[0]; + guint opacity = param[1]; + + while (h--) + { + combine_mask_and_alpha_channel_stroke_limit (s, m, limit, opacity, src->w, src->bytes); + s += src->rowstride; + m += mask->rowstride; + } +} + + void combine_mask_and_region (PixelRegion *src, PixelRegion *mask, @@ -3924,6 +3944,23 @@ void +combine_mask_and_region_limit (PixelRegion *src, + PixelRegion *mask, + guint limit, + guint opacity) +{ + guint param[2]; + + param[0] = limit; + param[1] = opacity; + + pixel_regions_process_parallel ((PixelProcessorFunc) + combine_mask_and_sub_region_stroke_limit, + param, 2, src, mask); +} + + +void copy_gray_to_region (PixelRegion *src, PixelRegion *dest) { --- gimp-2.6.6/app/paint-funcs/paint-funcs.h 2008-11-21 07:43:00 +0900 +++ gimp-painter--2.6.6-20100627/app/paint-funcs/paint-funcs.h 2010-06-27 02:14:19 +0900 @@ -444,6 +444,11 @@ guint opacity, gboolean stipple); +void combine_mask_and_region_limit (PixelRegion *src, + PixelRegion *mask, + guint limit, + guint opacity); + /* Copy a gray image to an intensity-alpha region */ void copy_gray_to_region (PixelRegion *src, PixelRegion *dest); --- gimp-2.6.6/app/tools/Makefile.am 2008-11-21 07:42:59 +0900 +++ gimp-painter--2.6.6-20100627/app/tools/Makefile.am 2010-06-27 02:14:19 +0900 @@ -189,7 +189,13 @@ gimpvectoroptions.c \ gimpvectoroptions.h \ gimpvectortool.c \ - gimpvectortool.h + gimpvectortool.h \ + gimpink2options-gui.c \ + gimpink2options-gui.h \ + gimpinktool2.c \ + gimpinktool2.h \ + gimpmixbrushtool.c \ + gimpmixbrushtool.h libapptools_a_built_sources = tools-enums.c --- gimp-2.6.6/app/tools/Makefile.in 2009-03-16 05:58:05 +0900 +++ gimp-painter--2.6.6-20100627/app/tools/Makefile.in 2010-06-27 02:14:19 +0900 @@ -98,7 +98,9 @@ gimptoolcontrol.$(OBJEXT) gimptooloptions-gui.$(OBJEXT) \ gimptransformoptions.$(OBJEXT) gimptransformtool.$(OBJEXT) \ gimptransformtoolundo.$(OBJEXT) gimpvectoroptions.$(OBJEXT) \ - gimpvectortool.$(OBJEXT) + gimpvectortool.$(OBJEXT) \ + gimpinktool2.$(OBJEXT) gimpink2options-gui.$(OBJEXT) \ + gimpmixbrushtool.$(OBJEXT) am_libapptools_a_OBJECTS = $(am__objects_1) $(am__objects_2) libapptools_a_OBJECTS = $(am_libapptools_a_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) @@ -620,7 +622,13 @@ gimpvectoroptions.c \ gimpvectoroptions.h \ gimpvectortool.c \ - gimpvectortool.h + gimpvectortool.h \ + gimpinktool2.c \ + gimpinktool2.h \ + gimpink2options-gui.c \ + gimpink2options-gui.h \ + gimpmixbrushtool.c \ + gimpmixbrushtool.h libapptools_a_built_sources = tools-enums.c libapptools_a_SOURCES = $(libapptools_a_built_sources) $(libapptools_a_sources) @@ -766,6 +774,9 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tool_manager.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tools-enums.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tools-utils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpink2options-gui.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpinktool2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpmixbrushtool.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< --- gimp-2.6.6/app/tools/gimp-tools.c 2008-11-21 07:42:59 +0900 +++ gimp-painter--2.6.6-20100627/app/tools/gimp-tools.c 2010-06-27 02:14:19 +0900 @@ -80,6 +80,8 @@ #include "gimpsmudgetool.h" #include "gimptexttool.h" #include "gimpvectortool.h" +#include "gimpinktool2.h" +#include "gimpmixbrushtool.h" #include "gimp-intl.h" @@ -143,6 +145,8 @@ gimp_blend_tool_register, gimp_bucket_fill_tool_register, gimp_text_tool_register, + gimp_ink2_tool_register, + gimp_mixbrush_tool_register, /* transform tools */ @@ -498,6 +502,14 @@ { paint_core_name = "gimp-ink"; } + else if (tool_type == GIMP_TYPE_INK2_TOOL) + { + paint_core_name = "gimp-ink2"; + } + else if (tool_type == GIMP_TYPE_MIXBRUSH_TOOL) + { + paint_core_name = "gimp-mixbrush"; + } else { paint_core_name = "gimp-paintbrush"; --- gimp-2.6.6/app/tools/gimpink2options-gui.c 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/tools/gimpink2options-gui.c 2010-06-27 02:14:19 +0900 @@ -0,0 +1,232 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include "libgimpwidgets/gimpwidgets.h" + +#include "tools-types.h" + +#include "config/gimpconfig-utils.h" + +#include "paint/gimpink2options.h" +#include "paint/gimpink2.h" + +#include "widgets/gimpblobeditor.h" + +#include "gimpink2options-gui.h" +#include "gimppaintoptions-gui.h" + +#include "gimp-intl.h" + + +static GtkWidget * blob_image_new (GimpInkBlobType blob_type); + + +GtkWidget * +gimp_ink2_options_gui (GimpToolOptions *tool_options) +{ + GObject *config = G_OBJECT (tool_options); + GimpInk2Options *ink_options = GIMP_INK2_OPTIONS (tool_options); + GtkWidget *vbox = gimp_paint_options_gui (tool_options); + GtkWidget *frame; + GtkWidget *table; + GtkWidget *blob_vbox; + GtkWidget *hbox; + GtkWidget *editor; + GtkObject *adj; + GtkWidget *compensate_box; + GtkWidget *compensate_vbox; + GtkWidget *checkbox; + + /* adjust sliders */ + frame = gimp_frame_new (_("Adjustment")); + gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0); + gtk_widget_show (frame); + + table = gtk_table_new (2, 3, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 2); + gtk_container_add (GTK_CONTAINER (frame), table); + gtk_widget_show (table); + + /* size slider */ + adj = gimp_prop_scale_entry_new (config, "size", + GTK_TABLE (table), 0, 0, + _("Size:"), + 1.0, 2.0, 1, + FALSE, 0.0, 0.0); + gimp_scale_entry_set_logarithmic (adj, TRUE); + + /* angle adjust slider */ + gimp_prop_scale_entry_new (config, "tilt-angle", + GTK_TABLE (table), 0, 1, + _("Angle:"), + 1.0, 10.0, 1, + FALSE, 0.0, 0.0); + + /* sens sliders */ + frame = gimp_frame_new (_("Sensitivity")); + gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0); + gtk_widget_show (frame); + + table = gtk_table_new (3, 3, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 2); + gtk_container_add (GTK_CONTAINER (frame), table); + gtk_widget_show (table); + + /* size sens slider */ + gimp_prop_scale_entry_new (config, "size-sensitivity", + GTK_TABLE (table), 0, 0, + _("Size:"), + 0.01, 0.1, 1, + FALSE, 0.0, 0.0); + + /* tilt sens slider */ + gimp_prop_scale_entry_new (config, "tilt-sensitivity", + GTK_TABLE (table), 0, 1, + _("Tilt:"), + 0.01, 0.1, 1, + FALSE, 0.0, 0.0); + + /* velocity sens slider */ + gimp_prop_scale_entry_new (config, "vel-sensitivity", + GTK_TABLE (table), 0, 2, + _("Speed:"), + 0.01, 0.1, 1, + FALSE, 0.0, 0.0); + + /* compensate at last checkbox */ + compensate_box = gtk_frame_new (_("Pointer Adjustment")); + gtk_box_pack_start (GTK_BOX (vbox), compensate_box, FALSE, TRUE, 0); + gtk_widget_show(compensate_box); + compensate_vbox = gtk_vbox_new (FALSE, 2); + gtk_container_add (GTK_CONTAINER (compensate_box), compensate_vbox); + gtk_widget_show (compensate_vbox); + + table = gtk_table_new (3, 3, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 2); + gtk_box_pack_start (GTK_VBOX (compensate_vbox), table, TRUE, TRUE, 0); + gtk_widget_show (table); + + /* compensation history size slider */ + gimp_prop_scale_entry_new (config, "compensation-history-size", + GTK_TABLE (table), 0, 0, + _("Quality:"), + 1, 1, 0, + FALSE, 1.0, INK2_HISTORY_BUFFER); + + /* pointer tracking rate slider */ + adj = gimp_prop_scale_entry_new (config, "compensation-rate-temperature", + GTK_TABLE (table), 0, 1, + _("Rate:"), + 1, 10, 1, + FALSE, 0, 100); + gimp_scale_entry_set_logarithmic (adj, TRUE); + + checkbox = + gimp_prop_check_button_new (config, "compensate-at-last", + _("Draw pen line to finished point:")); + gtk_box_pack_start (GTK_VBOX (compensate_vbox), checkbox, FALSE, FALSE, 0); + gtk_widget_show(checkbox); + + /* bottom hbox */ + hbox = gtk_hbox_new (FALSE, 2); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + /* Blob type radiobuttons */ + frame = gimp_prop_enum_radio_frame_new (config, "blob-type", + _("Type"), 0, 0); + gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0); + gtk_widget_show (frame); + + { + GList *children; + GList *list; + GimpInkBlobType blob_type; + + children = + gtk_container_get_children (GTK_CONTAINER (GTK_BIN (frame)->child)); + + for (list = children, blob_type = GIMP_INK_BLOB_TYPE_ELLIPSE; + list; + list = g_list_next (list), blob_type++) + { + GtkWidget *radio = GTK_WIDGET (list->data); + GtkWidget *blob; + + gtk_container_remove (GTK_CONTAINER (radio), GTK_BIN (radio)->child); + + blob = blob_image_new (blob_type); + gtk_container_add (GTK_CONTAINER (radio), blob); + gtk_widget_show (blob); + } + + g_list_free (children); + } + + /* Blob shape widget */ + frame = gimp_frame_new (_("Shape")); + gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0); + gtk_widget_show (frame); + + blob_vbox = gtk_vbox_new (FALSE, 2); + gtk_container_add (GTK_CONTAINER (frame), blob_vbox); + gtk_widget_show (blob_vbox); + + frame = gtk_aspect_frame_new (NULL, 0.0, 0.5, 1.0, FALSE); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (blob_vbox), frame, TRUE, TRUE, 0); + gtk_widget_show (frame); + + editor = gimp_blob_editor_new (ink_options->blob_type, + ink_options->blob_aspect, + ink_options->blob_angle); + gtk_widget_set_size_request (editor, 60, 60); + gtk_container_add (GTK_CONTAINER (frame), editor); + gtk_widget_show (editor); + + gimp_config_connect (config, G_OBJECT (editor), NULL); + + return vbox; +} + +static GtkWidget * +blob_image_new (GimpInkBlobType blob_type) +{ + const gchar *stock_id = NULL; + + switch (blob_type) + { + case GIMP_INK_BLOB_TYPE_ELLIPSE: + stock_id = GIMP_STOCK_SHAPE_CIRCLE; + break; + + case GIMP_INK_BLOB_TYPE_SQUARE: + stock_id = GIMP_STOCK_SHAPE_SQUARE; + break; + + case GIMP_INK_BLOB_TYPE_DIAMOND: + stock_id = GIMP_STOCK_SHAPE_DIAMOND; + break; + } + + return gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU); +} --- gimp-2.6.6/app/tools/gimpink2options-gui.h 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/tools/gimpink2options-gui.h 2010-06-27 02:14:19 +0900 @@ -0,0 +1,26 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __GIMP_INK2_OPTIONS_GUI_H__ +#define __GIMP_INK2_OPTIONS_GUI_H__ + + +GtkWidget * gimp_ink2_options_gui (GimpToolOptions *tool_options); + + +#endif /* __GIMP_INK2_OPTIONS_GUI_H__ */ --- gimp-2.6.6/app/tools/gimpinktool2.c 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/tools/gimpinktool2.c 2010-06-27 02:14:19 +0900 @@ -0,0 +1,86 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include "libgimpwidgets/gimpwidgets.h" + +#include "tools-types.h" + +#include "paint/gimpink2options.h" + +#include "widgets/gimphelp-ids.h" + +#include "gimpink2options-gui.h" +#include "gimpinktool2.h" +#include "gimptoolcontrol.h" + +#include "gimp-intl.h" + + +G_DEFINE_TYPE (GimpInk2Tool, gimp_ink2_tool, GIMP_TYPE_PAINT_TOOL) + +#define parent_class gimp_ink2_tool_parent_class + + +void +gimp_ink2_tool_register (GimpToolRegisterCallback callback, + gpointer data) +{ + (* callback) (GIMP_TYPE_INK2_TOOL, + GIMP_TYPE_INK2_OPTIONS, + gimp_ink2_options_gui, + GIMP_CONTEXT_FOREGROUND_MASK | + GIMP_CONTEXT_BACKGROUND_MASK | + GIMP_CONTEXT_OPACITY_MASK | + GIMP_CONTEXT_PAINT_MODE_MASK, + "gimp-ink2-tool", + _("G-pen"), + _("Draw in G-pen -2-"), + N_("G-pen"), "G", + NULL, GIMP_HELP_TOOL_INK, + GIMP_STOCK_TOOL_INK, + data); +} + +static void +gimp_ink2_tool_class_init (GimpInk2ToolClass *klass) +{ +} + +static void +gimp_ink2_tool_init (GimpInk2Tool *ink_tool) +{ + GimpTool *tool = GIMP_TOOL (ink_tool); + + gimp_tool_control_set_tool_cursor (tool->control, GIMP_TOOL_CURSOR_INK); + gimp_tool_control_set_action_value_2 (tool->control, + "tools/tools-ink-blob-size-set"); + gimp_tool_control_set_action_value_3 (tool->control, + "tools/tools-ink-blob-aspect-set"); + gimp_tool_control_set_action_value_4 (tool->control, + "tools/tools-ink-blob-angle-set"); + + gimp_paint_tool_enable_color_picker (GIMP_PAINT_TOOL (ink_tool), + GIMP_COLOR_PICK_MODE_FOREGROUND); + + /* G-Pen uses the own smoothing routin, so disable the GimpDisplayShell's one */ + tool->max_coord_smooth = 0.0; +} --- gimp-2.6.6/app/tools/gimpinktool2.h 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/tools/gimpinktool2.h 2010-06-27 02:14:19 +0900 @@ -0,0 +1,54 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __GIMP_INK2_TOOL_H__ +#define __GIMP_INK2_TOOL_H__ + + +#include "gimppainttool.h" + + +#define GIMP_TYPE_INK2_TOOL (gimp_ink2_tool_get_type ()) +#define GIMP_INK2_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_INK2_TOOL, GimpInk2Tool)) +#define GIMP_INK2_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_INK2_TOOL, GimpInk2ToolClass)) +#define GIMP_IS_INK2_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_INK2_TOOL)) +#define GIMP_IS_INK2_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_INK2_TOOL)) +#define GIMP_INK2_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_INK2_TOOL, GimpInk2ToolClass)) + + +typedef struct _GimpInk2Tool GimpInk2Tool; +typedef struct _GimpInk2ToolClass GimpInk2ToolClass; + +struct _GimpInk2Tool +{ + GimpPaintTool parent_instance; +}; + +struct _GimpInk2ToolClass +{ + GimpPaintToolClass parent_class; +}; + + +void gimp_ink2_tool_register (GimpToolRegisterCallback callback, + gpointer data); + +GType gimp_ink2_tool_get_type (void) G_GNUC_CONST; + + +#endif /* __GIMP_INK2_TOOL_H__ */ --- gimp-2.6.6/app/tools/gimpmixbrushtool.c 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/tools/gimpmixbrushtool.c 2010-06-27 02:14:19 +0900 @@ -0,0 +1,420 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include "libgimpwidgets/gimpwidgets.h" + +#include "tools-types.h" + +#include "paint/gimpmixbrushoptions.h" + +#include "widgets/gimphelp-ids.h" +#include "widgets/gimppropwidgets.h" +#include "widgets/gimpviewablebox.h" + +#include "gimpmixbrushtool.h" +#include "gimppaintoptions-gui.h" +#include "gimptoolcontrol.h" + +#include "gimp-intl.h" + + +static GtkWidget * gimp_mixbrush_options_gui (GimpToolOptions *tool_options); + + +G_DEFINE_TYPE (GimpMixbrushTool, gimp_mixbrush_tool, GIMP_TYPE_PAINTBRUSH_TOOL) + + +void +gimp_mixbrush_tool_register (GimpToolRegisterCallback callback, + gpointer data) +{ + (* callback) (GIMP_TYPE_MIXBRUSH_TOOL, + GIMP_TYPE_MIXBRUSH_OPTIONS, + gimp_mixbrush_options_gui, + GIMP_PAINT_OPTIONS_CONTEXT_MASK | + GIMP_CONTEXT_PATTERN_MASK | + GIMP_CONTEXT_GRADIENT_MASK, + "gimp-mixbrush-tool", + _("Mixbrush"), + _("Mixbrush Tool: Brush with mixing color feature"), + N_("_Mixbrush"), "W", + NULL, GIMP_HELP_TOOL_PAINTBRUSH, + GIMP_STOCK_TOOL_PAINTBRUSH, + data); +} + +static void +gimp_mixbrush_tool_class_init (GimpMixbrushToolClass *klass) +{ +} + +static void +gimp_mixbrush_tool_init (GimpMixbrushTool *mixbrush) +{ + GimpTool *tool = GIMP_TOOL (mixbrush); + + gimp_tool_control_set_tool_cursor (tool->control, GIMP_TOOL_CURSOR_PAINTBRUSH); + + gimp_paint_tool_enable_color_picker (GIMP_PAINT_TOOL (mixbrush), + GIMP_COLOR_PICK_MODE_FOREGROUND); +} + + +/* tool options stuff */ + +static GtkWidget * +gimp_mixbrush_options_gui (GimpToolOptions *tool_options) +{ + GObject *config = G_OBJECT (tool_options); + GtkWidget *vbox = gimp_paint_options_gui (tool_options); + GtkWidget *table; + GtkWidget *mixbrush_box; + GtkWidget *mixbrush_vbox; + GtkWidget *mixbrush_button; + GtkWidget *mixbrush_frame; + GtkObject *adj; + + /* Texture configurations */ + { + table = gtk_table_new (3, 7, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 2); + + mixbrush_frame = gimp_prop_expanding_frame_new (config, "use-texture", "Use texture", table, NULL); + + mixbrush_box = gimp_prop_pattern_box_new (NULL, GIMP_CONTEXT (tool_options), 2, + "pattern-view-type", "pattern-view-size"); + gtk_table_attach (GTK_TABLE (table), mixbrush_box, 0, 3, 1, 2, + GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, + 0, 0); + gtk_widget_show (mixbrush_box); + + gimp_prop_scale_entry_new (config, "texture-grain", + GTK_TABLE (table), 0, 2, + _("Grain:"), + 0.01, 0.1, 2, + FALSE, -1.0, 1.0); + + { + GtkWidget *expander = gtk_expander_new (_("Pressure")); + GtkWidget *inner_table = gtk_table_new (3, 4, FALSE); + + gtk_container_add (GTK_CONTAINER (expander), inner_table); + gtk_table_attach (GTK_TABLE (table), expander, 0, 3, 3, 4, + GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, + 0, 0); + + gimp_prop_scale_entry_new (config, "texture-grain-pressure-in1", + GTK_TABLE (inner_table), 0, 0, + _("In1:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + gimp_prop_scale_entry_new (config, "texture-grain-pressure-in2", + GTK_TABLE (inner_table), 0, 1, + _("In2:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + gimp_prop_scale_entry_new (config, "texture-grain-pressure-out1", + GTK_TABLE (inner_table), 0, 2, + _("Out1:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + gimp_prop_scale_entry_new (config, "texture-grain-pressure-out2", + GTK_TABLE (inner_table), 0, 3, + _("Out2:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + + gtk_widget_show_all (expander); + } + + gimp_prop_scale_entry_new (config, "texture-jitter", + GTK_TABLE (table), 0, 4, + _("Jitter:"), + 10, 100, 0, + FALSE, 0, 1000); + + mixbrush_button = gimp_prop_check_button_new (config, "texture-fringe", _("Apply fringe")); + gtk_table_attach (GTK_TABLE (table), mixbrush_button, 0, 3, 5, 6, + GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, + 0, 0); + gtk_widget_show (mixbrush_button); + + gimp_prop_scale_entry_new (config, "texture-fringe-contrast", + GTK_TABLE (table), 0, 6, + _("Contrast:"), + 0.5, 1.0, 1, + FALSE, 1.0, 10.0); + + gtk_box_pack_start (GTK_BOX (vbox), mixbrush_frame, FALSE, FALSE, 0); + gtk_widget_show (mixbrush_frame); + } + + mixbrush_button = gimp_prop_check_button_new (config, "alpha-channel-mixing", _("Alpha channel mixing")); + gtk_box_pack_start (GTK_BOX (vbox), mixbrush_button, FALSE, TRUE, 0); + gtk_widget_show (mixbrush_button); + + /* Main color configurations */ + mixbrush_box = gtk_frame_new (_("Main Color")); + gtk_box_pack_start (GTK_BOX (vbox), mixbrush_box, FALSE, TRUE, 0); + gtk_widget_show(mixbrush_box); + mixbrush_vbox = gtk_vbox_new (FALSE, 2); + gtk_container_add (GTK_CONTAINER (mixbrush_box), mixbrush_vbox); + gtk_widget_show (mixbrush_vbox); + + table = gtk_table_new (3, 6, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 2); + gtk_box_pack_start (GTK_BOX (mixbrush_vbox), table, TRUE, TRUE, 0); + gtk_widget_show (table); + + mixbrush_button = gimp_prop_check_button_new (config, "pigment", _("Paint with pigment")); + gtk_table_attach (GTK_TABLE (table), mixbrush_button, 0, 3, 0, 1, + GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, + 0, 0); + gtk_widget_show (mixbrush_button); + + gimp_prop_scale_entry_new (config, "main-color-density", + GTK_TABLE (table), 0, 1, + _("Density:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + + { + GtkWidget *expander = gtk_expander_new (_("Pressure")); + GtkWidget *inner_table = gtk_table_new (3, 4, FALSE); + + gtk_container_add (GTK_CONTAINER (expander), inner_table); + gtk_table_attach (GTK_TABLE (table), expander, 0, 3, 2, 3, + GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, + 0, 0); + + gimp_prop_scale_entry_new (config, "main-color-density-pressure-in1", + GTK_TABLE (inner_table), 0, 0, + _("In1:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + gimp_prop_scale_entry_new (config, "main-color-density-pressure-in2", + GTK_TABLE (inner_table), 0, 1, + _("In2:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + gimp_prop_scale_entry_new (config, "main-color-density-pressure-out1", + GTK_TABLE (inner_table), 0, 2, + _("Out1:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + gimp_prop_scale_entry_new (config, "main-color-density-pressure-out2", + GTK_TABLE (inner_table), 0, 3, + _("Out2:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + + gtk_widget_show_all (expander); + } + + adj = gimp_prop_scale_entry_new (config, "main-color-rate", + GTK_TABLE (table), 0, 3, + _("Rate:"), + 0.01, 0.1, 3, + FALSE, 0.0, 1.0); + gimp_scale_entry_set_logarithmic (adj, TRUE); + + { + GtkWidget *expander = gtk_expander_new (_("Pressure")); + GtkWidget *inner_table = gtk_table_new (3, 4, FALSE); + + gtk_container_add (GTK_CONTAINER (expander), inner_table); + gtk_table_attach (GTK_TABLE (table), expander, 0, 3, 4, 5, + GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, + 0, 0); + + gimp_prop_scale_entry_new (config, "main-color-pressure-in1", + GTK_TABLE (inner_table), 0, 0, + _("In1:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + gimp_prop_scale_entry_new (config, "main-color-pressure-in2", + GTK_TABLE (inner_table), 0, 1, + _("In2:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + gimp_prop_scale_entry_new (config, "main-color-pressure-out1", + GTK_TABLE (inner_table), 0, 2, + _("Out1:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + gimp_prop_scale_entry_new (config, "main-color-pressure-out2", + GTK_TABLE (inner_table), 0, 3, + _("Out2:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + + gtk_widget_show_all (expander); + } + + gimp_prop_scale_entry_new (config, "dryout", + GTK_TABLE (table), 0, 5, + _("Dryout:"), + 10.0, 100.0, 0, + TRUE, 0.0, 10000); + + /* Canvas Color Picking Configurations */ + mixbrush_box = gtk_frame_new (_("Canvas Color")); + gtk_box_pack_start (GTK_BOX (vbox), mixbrush_box, FALSE, TRUE, 0); + gtk_widget_show(mixbrush_box); + mixbrush_vbox = gtk_vbox_new (FALSE, 2); + gtk_container_add (GTK_CONTAINER (mixbrush_box), mixbrush_vbox); + gtk_widget_show (mixbrush_vbox); + + table = gtk_table_new (3, 5, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 2); + gtk_box_pack_start (GTK_BOX (mixbrush_vbox), table, TRUE, TRUE, 0); + gtk_widget_show (table); + + gimp_prop_scale_entry_new (config, "canvas-color-density", + GTK_TABLE (table), 0, 0, + _("Density:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + + { + GtkWidget *expander = gtk_expander_new (_("Pressure")); + GtkWidget *inner_table = gtk_table_new (3, 4, FALSE); + + gtk_container_add (GTK_CONTAINER (expander), inner_table); + gtk_table_attach (GTK_TABLE (table), expander, 0, 3, 1, 2, + GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, + 0, 0); + + gimp_prop_scale_entry_new (config, "canvas-color-density-pressure-in1", + GTK_TABLE (inner_table), 0, 0, + _("In1:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + gimp_prop_scale_entry_new (config, "canvas-color-density-pressure-in2", + GTK_TABLE (inner_table), 0, 1, + _("In2:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + gimp_prop_scale_entry_new (config, "canvas-color-density-pressure-out1", + GTK_TABLE (inner_table), 0, 2, + _("Out1:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + gimp_prop_scale_entry_new (config, "canvas-color-density-pressure-out2", + GTK_TABLE (inner_table), 0, 3, + _("Out2:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + + gtk_widget_show_all (expander); + } + + gimp_prop_scale_entry_new (config, "canvas-color-rate", + GTK_TABLE (table), 0, 2, + _("Rate:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + + { + GtkWidget *expander = gtk_expander_new (_("Pressure")); + GtkWidget *inner_table = gtk_table_new (3, 4, FALSE); + + gtk_container_add (GTK_CONTAINER (expander), inner_table); + gtk_table_attach (GTK_TABLE (table), expander, 0, 3, 3, 4, + GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, + 0, 0); + + gimp_prop_scale_entry_new (config, "canvas-color-pressure-in1", + GTK_TABLE (inner_table), 0, 0, + _("In1:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + gimp_prop_scale_entry_new (config, "canvas-color-pressure-in2", + GTK_TABLE (inner_table), 0, 1, + _("In2:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + gimp_prop_scale_entry_new (config, "canvas-color-pressure-out1", + GTK_TABLE (inner_table), 0, 2, + _("Out1:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + gimp_prop_scale_entry_new (config, "canvas-color-pressure-out2", + GTK_TABLE (inner_table), 0, 3, + _("Out2:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + + gtk_widget_show_all (expander); + } + + /* */ + mixbrush_box = gtk_frame_new (_("Pick up")); + gtk_box_pack_start (GTK_BOX (vbox), mixbrush_box, FALSE, TRUE, 0); + gtk_widget_show(mixbrush_box); + mixbrush_vbox = gtk_vbox_new (FALSE, 2); + gtk_container_add (GTK_CONTAINER (mixbrush_box), mixbrush_vbox); + gtk_widget_show (mixbrush_vbox); + + table = gtk_table_new (3, 1, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 2); + gtk_box_pack_start (GTK_BOX (mixbrush_vbox), table, TRUE, TRUE, 0); + gtk_widget_show (table); + + gimp_prop_scale_entry_new (config, "sample-size-limit", + GTK_TABLE (table), 0, 0, + _("Sample size:"), + 1.0, 10.0, 0, + TRUE, 1.0, 100.0); + + /*mixbrush_button = gimp_prop_check_button_new (config, "merged", _("Pick up underlying color"));*/ + mixbrush_button = gimp_prop_check_button_new (config, "merged", _("Use merged color")); + gtk_box_pack_start (GTK_BOX (mixbrush_vbox), mixbrush_button, TRUE, TRUE, 0); + gtk_widget_show (mixbrush_button); + + table = gtk_table_new (3, 1, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 2); + gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); + gtk_widget_show (table); + + gimp_prop_scale_entry_new (config, "delay", + GTK_TABLE (table), 0, 0, + _("Delay:"), + 1.0, 2.0, 0, + TRUE, 0.0, 10); + + mixbrush_button = gimp_prop_check_button_new (config, "tail", _("Paint the tail of stroke (delay > 0)")); + gtk_box_pack_start (GTK_BOX (vbox), mixbrush_button, FALSE, TRUE, 0); + gtk_widget_show (mixbrush_button); + + mixbrush_frame = gimp_prop_enum_radio_frame_new (config, "hidden-color", + _("Assume that the hidden color is:"), + 0, 0); + gtk_box_pack_start (GTK_BOX (vbox), mixbrush_frame, FALSE, TRUE, 0); + gtk_widget_show (mixbrush_frame); + + /*mixbrush_button = gimp_prop_check_button_new (config, "remove-color", _("Remove background color")); + gtk_box_pack_start (GTK_BOX (vbox), mixbrush_button, FALSE, TRUE, 0); + gtk_widget_show (mixbrush_button);*/ + + return vbox; +} --- gimp-2.6.6/app/tools/gimpmixbrushtool.h 1970-01-01 09:00:00 +0900 +++ gimp-painter--2.6.6-20100627/app/tools/gimpmixbrushtool.h 2010-06-27 02:14:19 +0900 @@ -0,0 +1,54 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __GIMP_MIXBRUSH_TOOL_H__ +#define __GIMP_MIXBRUSH_TOOL_H__ + + +#include "gimppaintbrushtool.h" + + +#define GIMP_TYPE_MIXBRUSH_TOOL (gimp_mixbrush_tool_get_type ()) +#define GIMP_MIXBRUSH_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_MIXBRUSH_TOOL, GimpMixbrushTool)) +#define GIMP_MIXBRUSH_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_MIXBRUSH_TOOL, GimpMixbrushToolClass)) +#define GIMP_IS_MIXBRUSH_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_MIXBRUSH_TOOL)) +#define GIMP_IS_MIXBRUSH_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_MIXBRUSH_TOOL)) +#define GIMP_MIXBRUSH_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_MIXBRUSH_TOOL, GimpMixbrushToolClass)) + + +typedef struct _GimpMixbrushTool GimpMixbrushTool; +typedef struct _GimpMixbrushToolClass GimpMixbrushToolClass; + +struct _GimpMixbrushTool +{ + GimpPaintbrushTool parent_instance; +}; + +struct _GimpMixbrushToolClass +{ + GimpPaintbrushToolClass parent_class; +}; + + +void gimp_mixbrush_tool_register (GimpToolRegisterCallback callback, + gpointer data); + +GType gimp_mixbrush_tool_get_type (void) G_GNUC_CONST; + + +#endif /* __GIMP_MIXBRUSH_TOOL_H__ */ --- gimp-2.6.6/app/tools/gimppaintoptions-gui.c 2008-11-21 07:42:59 +0900 +++ gimp-painter--2.6.6-20100627/app/tools/gimppaintoptions-gui.c 2010-06-27 02:14:19 +0900 @@ -33,6 +33,8 @@ #include "widgets/gimpwidgets-utils.h" #include "gimpairbrushtool.h" +#include "gimpblendtool.h" +#include "gimpbucketfilltool.h" #include "gimpclonetool.h" #include "gimpconvolvetool.h" #include "gimpdodgeburntool.h" @@ -43,6 +45,8 @@ #include "gimppenciltool.h" #include "gimpperspectiveclonetool.h" #include "gimpsmudgetool.h" +#include "gimpinktool2.h" +#include "gimpmixbrushtool.h" #include "gimptooloptions-gui.h" #include "gimp-intl.h" @@ -54,26 +58,29 @@ static gboolean tool_has_size_dynamics (GType tool_type); static gboolean tool_has_color_dynamics (GType tool_type); -static void pressure_options_gui (GimpPaintOptions *paint_options, - GType tool_type, - GtkTable *table, - gint row, - GtkWidget *labels[]); -static void velocity_options_gui (GimpPaintOptions *paint_options, - GType tool_type, - GtkTable *table, - gint row); -static void random_options_gui (GimpPaintOptions *paint_options, - GType tool_type, - GtkTable *table, - gint row); -static GtkWidget * fade_options_gui (GimpPaintOptions *paint_options, - GType tool_type); -static GtkWidget * gradient_options_gui (GimpPaintOptions *paint_options, - GType tool_type, - GtkWidget *incremental_toggle); -static GtkWidget * jitter_options_gui (GimpPaintOptions *paint_options, - GType tool_type); +static void pressure_options_gui (GimpPaintOptions *paint_options, + GType tool_type, + GtkTable *table, + gint row, + GtkWidget *labels[]); +static void velocity_options_gui (GimpPaintOptions *paint_options, + GType tool_type, + GtkTable *table, + gint row); +static void random_options_gui (GimpPaintOptions *paint_options, + GType tool_type, + GtkTable *table, + gint row); +static GtkWidget * fade_options_gui (GimpPaintOptions *paint_options, + GType tool_type); +static GtkWidget * gradient_options_gui (GimpPaintOptions *paint_options, + GType tool_type, + GtkWidget *incremental_toggle); +static GtkWidget * jitter_options_gui (GimpPaintOptions *paint_options, + GType tool_type); +static GtkWidget * update_freq_options_gui (GimpUpdateFreqOptions *update_freq, + GimpPaintOptions *paint_options, + GType tool_type); /* public functions */ @@ -125,6 +132,24 @@ gimp_prop_opacity_entry_new (config, "opacity", GTK_TABLE (table), 0, table_row++, _("Opacity:")); + /* the flow scale */ + if (g_type_is_a (tool_type, GIMP_TYPE_PAINTBRUSH_TOOL) && + tool_type != GIMP_TYPE_AIRBRUSH_TOOL) + gimp_prop_opacity_entry_new (config, "flow", + GTK_TABLE (table), 0, table_row++, + _("Flow:")); + /* coords smoothing */ + if (tool_type != GIMP_TYPE_INK2_TOOL && + tool_type != GIMP_TYPE_BLEND_TOOL && + tool_type != GIMP_TYPE_BUCKET_FILL_TOOL) + { + gimp_prop_scale_entry_new (config, "max-coord-smooth", + GTK_TABLE (table), 0, table_row++, + _("Smoothing:"), + 0.01, 0.1, 2, + FALSE, 0.0, 1.0); + } + /* the brush */ if (g_type_is_a (tool_type, GIMP_TYPE_BRUSH_TOOL)) @@ -143,6 +168,19 @@ 0.01, 0.1, 2, FALSE, 0.0, 0.0); gimp_scale_entry_set_logarithmic (adj, TRUE); + + gimp_prop_scale_entry_new (config, "pressure-min-scale", + GTK_TABLE (table), 0, table_row++, + _("Minimum scale:"), + 0.01, 0.1, 2, + FALSE, 0.0, 0.0); + + adj = gimp_prop_scale_entry_new (config, "pressure-power-size", + GTK_TABLE (table), 0, table_row++, + _("Power:"), + 0.01, 0.1, 2, + FALSE, 0.0, 0.0); + gimp_scale_entry_set_logarithmic (adj, TRUE); } if (tool_has_opacity_dynamics (tool_type)) @@ -256,6 +294,7 @@ /* the "incremental" toggle */ if (tool_type == GIMP_TYPE_PENCIL_TOOL || tool_type == GIMP_TYPE_PAINTBRUSH_TOOL || + tool_type == GIMP_TYPE_MIXBRUSH_TOOL || tool_type == GIMP_TYPE_ERASER_TOOL) { incremental_toggle = @@ -289,6 +328,14 @@ gtk_widget_show (frame); } + frame = update_freq_options_gui (options->update_freq_options, + options, tool_type); + if (frame) + { + gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + } + return vbox; } @@ -317,6 +364,7 @@ tool_type == GIMP_TYPE_ERASER_TOOL || tool_type == GIMP_TYPE_DODGE_BURN_TOOL || tool_type == GIMP_TYPE_PAINTBRUSH_TOOL || + tool_type == GIMP_TYPE_MIXBRUSH_TOOL || tool_type == GIMP_TYPE_SMUDGE_TOOL); } @@ -631,13 +679,13 @@ _("Use color from gradient"), table, &button); - if (incremental_toggle) + /*if (incremental_toggle) { gtk_widget_set_sensitive (incremental_toggle, ! paint_options->gradient_options->use_gradient); g_object_set_data (G_OBJECT (button), "inverse_sensitive", incremental_toggle); - } + }*/ /* the gradient view */ button = gimp_prop_gradient_box_new (NULL, GIMP_CONTEXT (config), 2, @@ -674,3 +722,52 @@ return frame; } + +static GtkWidget * +update_freq_options_gui (GimpUpdateFreqOptions *update_freq, + GimpPaintOptions *paint_options, + GType tool_type) +{ + GObject *config = G_OBJECT (paint_options); + GtkWidget *frame = NULL; + + if (tool_type != GIMP_TYPE_PERSPECTIVE_CLONE_TOOL && + tool_type != GIMP_TYPE_BLEND_TOOL && + tool_type != GIMP_TYPE_BUCKET_FILL_TOOL) + { + GtkWidget *table; + + table = gtk_table_new (3, 5, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 2); + + frame = gimp_prop_expanding_frame_new (config, "reduce-update-frequency", + _("Reduce update frequency"), + table, NULL); + + gimp_prop_scale_entry_new (config, "update-freq-size-threshold", + GTK_TABLE (table), 0, 0, + _("Size:"), + 0.1, 1.0, 1, + TRUE, 0.1, 100.0); + + gimp_prop_scale_entry_new (config, "update-freq-velo-threshold", + GTK_TABLE (table), 0, 1, + _("Velocity:"), + 0.001, 0.1, 3, + TRUE, 0.001, 0.1); + + gimp_prop_scale_entry_new (config, "update-freq-gamma", + GTK_TABLE (table), 0, 2, + _("Strength:"), + 0.1, 1.0, 2, + TRUE, 0.1, 2.5); + + gimp_prop_scale_entry_new (config, "update-freq-max-n-dabs", + GTK_TABLE (table), 0, 3, + _("Limit:"), + 1, 5, 0, + TRUE, 5, 40); + } + + return frame; +} --- gimp-2.6.6/app/widgets/gimptooloptionseditor.c 2008-11-21 07:43:05 +0900 +++ gimp-painter--2.6.6-20100627/app/widgets/gimptooloptionseditor.c 2010-06-27 02:14:19 +0900 @@ -83,6 +83,9 @@ GimpToolPresets *presets); static void gimp_tool_options_editor_save_presets (GimpToolOptionsEditor *editor); +static void gimp_tool_options_editor_style_set (GtkWidget *widget, + GtkStyle *prev_style); + G_DEFINE_TYPE_WITH_CODE (GimpToolOptionsEditor, gimp_tool_options_editor, GIMP_TYPE_EDITOR, @@ -97,10 +100,21 @@ { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->constructor = gimp_tool_options_editor_constructor; gtk_object_class->destroy = gimp_tool_options_editor_destroy; + + widget_class->style_set = gimp_tool_options_editor_style_set; + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("content-border", + NULL, NULL, + 0, + G_MAXINT, + 0, + GIMP_PARAM_READABLE)); } static void @@ -523,3 +537,20 @@ gtk_widget_set_sensitive (editor->delete_button, delete_sensitive); gtk_widget_set_sensitive (editor->reset_button, reset_sensitive); } + + +static void +gimp_tool_options_editor_style_set (GtkWidget *widget, + GtkStyle *prev_style) +{ + GimpToolOptionsEditor *editor = GIMP_TOOL_OPTIONS_EDITOR (widget); + gint content_border; + + //GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style); + + gtk_widget_style_get (widget, + "content-border", &content_border, + NULL); + + gtk_container_set_border_width (GTK_CONTAINER (editor->options_vbox), content_border); +}