static inline void fill_color(xyStackArray* stack, const T* replace_color, const T* target_color, T* r, T* g, T* b, int width, int x, int y, T tol) { int offset = y * width + x; if (!color_equal(replace_color, r[offset], g[offset], b[offset]) && color_is_similar(target_color, r[offset], g[offset], b[offset], tol)) { xyStackArrayPush(stack, x, y); color_copy(replace_color, r[offset], g[offset], b[offset]); } }
static void cb_color_changed_back (G_GNUC_UNUSED GOComboColor *go_combo_color, GOColor color, G_GNUC_UNUSED gboolean custom, G_GNUC_UNUSED gboolean by_user, G_GNUC_UNUSED gboolean is_default, SheetManager *state) { GList *selected_rows, *l; GtkTreeSelection *selection = gtk_tree_view_get_selection (state->sheet_list); WorkbookSheetState *old_state; WorkbookControl *wbc = GNM_WBC (state->wbcg); Workbook *wb = wb_control_get_workbook (wbc); GdkRGBA gdk_color; GdkRGBA *p_gdk_color; GnmColor *gnm_color; g_return_if_fail (selection != NULL); selected_rows = gtk_tree_selection_get_selected_rows (selection, NULL); p_gdk_color = (color == 0) ? NULL : go_color_to_gdk_rgba (color, &gdk_color); gnm_color = (color == 0) ? NULL : gnm_color_new_gdk (&gdk_color); old_state = workbook_sheet_state_new (wb); for (l = selected_rows; l != NULL; l = l->next) { Sheet *this_sheet; GtkTreeIter sel_iter; GtkTreePath *path = l->data; gtk_tree_model_get_iter (GTK_TREE_MODEL (state->model), &sel_iter, path); gtk_tree_model_get (GTK_TREE_MODEL (state->model), &sel_iter, SHEET_POINTER, &this_sheet, -1); if (color_equal (p_gdk_color, this_sheet->tab_color)) continue; gtk_list_store_set (state->model, &sel_iter, BACKGROUND_COLOUR, p_gdk_color, -1); g_object_set (this_sheet, "tab-background", gnm_color, NULL); } style_color_unref (gnm_color); cmd_reorganize_sheets (wbc, old_state, NULL); update_undo (state, wbc); g_list_free_full (selected_rows, (GDestroyNotify) gtk_tree_path_free); }
static void DoRenderFloodFillRGB(T** data, int width, int height, int start_x, int start_y, float* replace_data, float tolerance) { T *r = data[0], *g = data[1], *b = data[2]; int offset, x, y; T target_color[3]; T replace_color[3]; T tol = (T)tolerance; replace_color[0] = (T)replace_data[0]; replace_color[1] = (T)replace_data[1]; replace_color[2] = (T)replace_data[2]; offset = start_y * width + start_x; if (color_equal(replace_color, r[offset], g[offset], b[offset])) return; color_init(target_color, r[offset], g[offset], b[offset]); /* very simple 4 neighbors stack based flood fill */ xyStackArray* stack = xyStackArrayCreate(); /* a color in the xy_stack is always similar to the target color, and it was already replaced */ xyStackArrayPush(stack, start_x, start_y); color_copy(replace_color, r[offset], g[offset], b[offset]); while (xyStackArrayHasData(stack)) { xyStackArrayPop(stack, x, y); /* right */ if (x < width - 1) fill_color(stack, replace_color, target_color, r, g, b, width, x + 1, y, tol); /* left */ if (x > 0) fill_color(stack, replace_color, target_color, r, g, b, width, x - 1, y, tol); /* top */ if (y < height - 1) fill_color(stack, replace_color, target_color, r, g, b, width, x, y + 1, tol); /* bottom */ if (y > 0) fill_color(stack, replace_color, target_color, r, g, b, width, x, y - 1, tol); } xyStackArrayDestroy(stack); }