summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 21de5bd)
raw | patch | inline | side by side (parent: 21de5bd)
author | johncoswell <johncoswell@users.sourceforge.net> | |
Mon, 28 May 2007 18:02:50 +0000 (18:02 +0000) | ||
committer | johncoswell <johncoswell@users.sourceforge.net> | |
Mon, 28 May 2007 18:02:50 +0000 (18:02 +0000) |
src/flood-context.cpp | patch | blob | history | |
src/flood-context.h | patch | blob | history | |
src/widgets/toolbox.cpp | patch | blob | history |
diff --git a/src/flood-context.cpp b/src/flood-context.cpp
index 3b7cc8d741d01c39e7c0f1efae6cf39237fb5740..b5b6359b47d4a886548348f11dfd322a672f12ed 100644 (file)
--- a/src/flood-context.cpp
+++ b/src/flood-context.cpp
return glist;
}
+GList * flood_autogap_dropdown_items_list() {
+ GList *glist = NULL;
+
+ glist = g_list_append (glist, _("None"));
+ glist = g_list_append (glist, _("Small"));
+ glist = g_list_append (glist, _("Medium"));
+ glist = g_list_append (glist, _("Large"));
+
+ return glist;
+}
+
static bool compare_pixels(unsigned char *check, unsigned char *orig, unsigned char *dtc, int threshold, PaintBucketChannels method) {
int diff = 0;
float hsl_check[3], hsl_orig[3];
@@ -296,12 +307,12 @@ static bool compare_pixels(unsigned char *check, unsigned char *orig, unsigned c
return false;
}
-static bool try_add_to_queue(std::deque<NR::Point> *fill_queue, guchar *px, guchar *trace_px, unsigned char *orig, unsigned char *dtc, int x, int y, int width, int threshold, PaintBucketChannels method, bool fill_switch) {
+static bool try_add_to_queue(std::deque<NR::Point> *fill_queue, guchar *px, guchar *trace_px, unsigned char *orig, unsigned char *dtc, int x, int y, int width, int threshold, PaintBucketChannels method, bool fill_switch, unsigned int max_queue_size) {
unsigned char *t = get_pixel(px, x, y, width);
if (compare_pixels(t, orig, dtc, threshold, method)) {
unsigned char *trace_t = get_pixel(trace_px, x, y, width);
if (trace_t[3] != 255 && trace_t[0] != 255) {
- if (fill_switch) {
+ if (fill_switch && (fill_queue->size() < max_queue_size)) {
fill_queue->push_back(NR::Point(x, y));
trace_t[0] = 255;
}
int y;
int y_limit;
int width;
+ int height;
int threshold;
+ int radius;
PaintBucketChannels method;
unsigned char *dtc;
bool top_fill;
SCANLINE_CHECK_BOUNDARY
};
+static void paint_pixel(guchar *px, guchar *trace_px, unsigned char *orig_color, bitmap_coords_info bci) {
+ unsigned char *t, *trace_t;
+
+ for (int r = 0; r <= bci.radius; r++) {
+ if (r == 0) {
+ t = get_pixel(px, bci.x, bci.y, bci.width);
+ if (compare_pixels(t, orig_color, bci.dtc, bci.threshold, bci.method)) {
+ for (int i = 0; i < 4; i++) { t[i] = 255 - t[i]; }
+ trace_t = get_pixel(trace_px, bci.x, bci.y, bci.width);
+ trace_t[3] = 255;
+ }
+ } else {
+ for (int y = -bci.radius; y <= bci.radius; y++) {
+ for (int x = -bci.radius; x <= bci.radius; x++) {
+ int tx = bci.x + x;
+ int ty = bci.y + y;
+
+ if ( (tx >= 0)
+ && (tx < bci.width)
+ && (ty >= 0)
+ && (ty < bci.height)) {
+ t = get_pixel(px, tx, ty, bci.width);
+ if (compare_pixels(t, orig_color, bci.dtc, bci.threshold, bci.method)) {
+ for (int i = 0; i < 4; i++) { t[i] = 255 - t[i]; }
+ trace_t = get_pixel(trace_px, tx, ty, bci.width);
+ trace_t[3] = 255;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
static ScanlineCheckResult perform_bitmap_scanline_check(std::deque<NR::Point> *fill_queue, guchar *px, guchar *trace_px, unsigned char *orig_color, bitmap_coords_info bci) {
bool aborted = false;
bool reached_screen_boundary = false;
bool ok;
bool keep_tracing;
- unsigned char *t, *trace_t;
+ unsigned char *t;
+
+ unsigned int max_queue_size = bci.width * bci.height;
do {
ok = false;
@@ -466,19 +515,17 @@ static ScanlineCheckResult perform_bitmap_scanline_check(std::deque<NR::Point> *
if (keep_tracing) {
t = get_pixel(px, bci.x, bci.y, bci.width);
if (compare_pixels(t, orig_color, bci.dtc, bci.threshold, bci.method)) {
- for (int i = 0; i < 4; i++) { t[i] = 255 - t[i]; }
- trace_t = get_pixel(trace_px, bci.x, bci.y, bci.width);
- trace_t[3] = 255;
+ paint_pixel(px, trace_px, orig_color, bci);
if (bci.y > 0) {
- bci.top_fill = try_add_to_queue(fill_queue, px, trace_px, orig_color, bci.dtc, bci.x, bci.y - 1, bci.width, bci.threshold, bci.method, bci.top_fill);
+ bci.top_fill = try_add_to_queue(fill_queue, px, trace_px, orig_color, bci.dtc, bci.x, bci.y - (1 + bci.radius), bci.width, bci.threshold, bci.method, bci.top_fill, max_queue_size);
}
if (bci.y < bci.y_limit) {
- bci.bottom_fill = try_add_to_queue(fill_queue, px, trace_px, orig_color, bci.dtc, bci.x, bci.y + 1, bci.width, bci.threshold, bci.method, bci.bottom_fill);
+ bci.bottom_fill = try_add_to_queue(fill_queue, px, trace_px, orig_color, bci.dtc, bci.x, bci.y + (1 + bci.radius), bci.width, bci.threshold, bci.method, bci.bottom_fill, max_queue_size);
}
if (bci.is_left) {
- bci.x--;
+ bci.x -= (1 + bci.radius);
} else {
- bci.x++;
+ bci.x += (1 + bci.radius);
}
ok = true;
}
@@ -638,11 +685,15 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even
bci.y_limit = y_limit;
bci.width = width;
+ bci.height = height;
bci.threshold = threshold;
bci.method = method;
bci.bbox = *bbox;
bci.screen = screen;
bci.dtc = dtc;
+ bci.radius = prefs_get_int_attribute_limited("tools.paintbucket", "autogap", 0, 0, 3);
+
+ unsigned int max_queue_size = width * height;
while (!color_queue.empty() && !aborted) {
NR::Point color_point = color_queue.front();
@@ -676,7 +727,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even
bool bottom_fill = true;
if (y > 0) {
- top_fill = try_add_to_queue(&fill_queue, px, trace_px, orig_color, dtc, x, y - 1, width, threshold, method, top_fill);
+ top_fill = try_add_to_queue(&fill_queue, px, trace_px, orig_color, dtc, x, y - (1 + bci.radius), width, threshold, method, top_fill, max_queue_size);
} else {
if (bbox->min()[NR::Y] > screen.min()[NR::Y]) {
aborted = true; break;
@@ -685,7 +736,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even
}
}
if (y < y_limit) {
- bottom_fill = try_add_to_queue(&fill_queue, px, trace_px, orig_color, dtc, x, y + 1, width, threshold, method, bottom_fill);
+ bottom_fill = try_add_to_queue(&fill_queue, px, trace_px, orig_color, dtc, x, y + (1 + bci.radius), width, threshold, method, bottom_fill, max_queue_size);
} else {
if (bbox->max()[NR::Y] < screen.max()[NR::Y]) {
aborted = true; break;
@@ -714,7 +765,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even
}
bci.is_left = false;
- bci.x = x + 1;
+ bci.x = x + (1 + bci.radius);
bci.y = y;
bci.top_fill = top_fill;
bci.bottom_fill = bottom_fill;
diff --git a/src/flood-context.h b/src/flood-context.h
index 10de77896360ee64c25a9e97a7eef92c34fe493b..a0d9e7d44fbbc4d0c10776abc05ba90fbc2e80b2 100644 (file)
--- a/src/flood-context.h
+++ b/src/flood-context.h
GtkType sp_flood_context_get_type (void);
GList* flood_channels_dropdown_items_list (void);
+GList* flood_autogap_dropdown_items_list (void);
void flood_channels_set_channels( gint channels );
enum PaintBucketChannels {
index 9698d7c0c1d6bb8621286b5e72432816b47eb142..9f8e675c2ab5a24502bb210cd5c0eb4aa47b466b 100644 (file)
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
" <toolitem action='OffsetAction' />"
" <toolitem action='PaintbucketUnitsAction' />"
" <separator />"
+ " <toolitem action='AutoGapAction' />"
+ " <separator />"
" <toolitem action='PaintbucketResetAction' />"
" </toolbar>"
prefs_set_int_attribute("tools.paintbucket", "threshold", (gint)adj->value);
}
+static void paintbucket_autogap_changed(EgeSelectOneAction* act, GObject *tbl)
+{
+ prefs_set_int_attribute("tools.paintbucket", "autogap", ege_select_one_action_get_active( act ));
+}
+
static void paintbucket_offset_changed(GtkAdjustment *adj, GObject *tbl)
{
UnitTracker* tracker = reinterpret_cast<UnitTracker*>(g_object_get_data( tbl, "tracker" ));
EgeSelectOneAction* channels_action = EGE_SELECT_ONE_ACTION( g_object_get_data( dataKludge, "channels_action" ) );
ege_select_one_action_set_active( channels_action, FLOOD_CHANNELS_RGB );
+ EgeSelectOneAction* autogap_action = EGE_SELECT_ONE_ACTION( g_object_get_data( dataKludge, "autogap_action" ) );
+ ege_select_one_action_set_active( autogap_action, 0 );
}
static void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
@@ -4411,6 +4420,28 @@ static void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
}
+ /* Auto Gap */
+ {
+ GtkListStore* model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT );
+
+ GList* items = 0;
+ gint count = 0;
+ for ( items = flood_autogap_dropdown_items_list(); items ; items = g_list_next(items) )
+ {
+ GtkTreeIter iter;
+ gtk_list_store_append( model, &iter );
+ gtk_list_store_set( model, &iter, 0, reinterpret_cast<gchar*>(items->data), 1, count, -1 );
+ count++;
+ }
+ g_list_free( items );
+ items = 0;
+ EgeSelectOneAction* act2 = ege_select_one_action_new( "AutoGapAction", _("Fill gaps:"), _(""), NULL, GTK_TREE_MODEL(model) );
+ ege_select_one_action_set_active( act2, prefs_get_int_attribute("tools.paintbucket", "autogap", 0) );
+ g_signal_connect( G_OBJECT(act2), "changed", G_CALLBACK(paintbucket_autogap_changed), holder );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(act2) );
+ g_object_set_data( holder, "autogap_action", act2 );
+ }
+
/* Reset */
{
GtkAction* act = gtk_action_new( "PaintbucketResetAction",