1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimpviewrendererpalette.c
5 * Copyright (C) 2005 Michael Natterer <mitch@gimp.org>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <string.h>
24
25 #include <gegl.h>
26 #include <gtk/gtk.h>
27
28 #include "libgimpcolor/gimpcolor.h"
29 #include "libgimpmath/gimpmath.h"
30 #include "libgimpwidgets/gimpwidgets.h"
31
32 #include "widgets-types.h"
33
34 #include "core/gimppalette.h"
35
36 #include "gimpviewrendererpalette.h"
37
38
39 #define COLUMNS 16
40
41
42 static void gimp_view_renderer_palette_finalize (GObject *object);
43
44 static void gimp_view_renderer_palette_render (GimpViewRenderer *renderer,
45 GtkWidget *widget);
46
47
G_DEFINE_TYPE(GimpViewRendererPalette,gimp_view_renderer_palette,GIMP_TYPE_VIEW_RENDERER)48 G_DEFINE_TYPE (GimpViewRendererPalette, gimp_view_renderer_palette,
49 GIMP_TYPE_VIEW_RENDERER)
50
51 #define parent_class gimp_view_renderer_palette_parent_class
52
53
54 static void
55 gimp_view_renderer_palette_class_init (GimpViewRendererPaletteClass *klass)
56 {
57 GObjectClass *object_class = G_OBJECT_CLASS (klass);
58 GimpViewRendererClass *renderer_class = GIMP_VIEW_RENDERER_CLASS (klass);
59
60 object_class->finalize = gimp_view_renderer_palette_finalize;
61
62 renderer_class->render = gimp_view_renderer_palette_render;
63 }
64
65 static void
gimp_view_renderer_palette_init(GimpViewRendererPalette * renderer)66 gimp_view_renderer_palette_init (GimpViewRendererPalette *renderer)
67 {
68 renderer->cell_size = 4;
69 renderer->draw_grid = FALSE;
70 renderer->columns = COLUMNS;
71 }
72
73 static void
gimp_view_renderer_palette_finalize(GObject * object)74 gimp_view_renderer_palette_finalize (GObject *object)
75 {
76 G_OBJECT_CLASS (parent_class)->finalize (object);
77 }
78
79 static void
gimp_view_renderer_palette_render(GimpViewRenderer * renderer,GtkWidget * widget)80 gimp_view_renderer_palette_render (GimpViewRenderer *renderer,
81 GtkWidget *widget)
82 {
83 GimpViewRendererPalette *renderpal = GIMP_VIEW_RENDERER_PALETTE (renderer);
84 GimpPalette *palette;
85 GimpColorTransform *transform;
86 guchar *row;
87 guchar *dest;
88 GList *list;
89 gdouble cell_width;
90 gint grid_width;
91 gint dest_stride;
92 gint y;
93
94 palette = GIMP_PALETTE (renderer->viewable);
95
96 if (gimp_palette_get_n_colors (palette) == 0)
97 return;
98
99 grid_width = renderpal->draw_grid ? 1 : 0;
100
101 if (renderpal->cell_size > 0)
102 {
103 gint n_columns = gimp_palette_get_columns (palette);
104
105 if (n_columns > 0)
106 cell_width = MAX ((gdouble) renderpal->cell_size,
107 (gdouble) (renderer->width - grid_width) /
108 (gdouble) n_columns);
109 else
110 cell_width = renderpal->cell_size;
111 }
112 else
113 {
114 gint n_columns = gimp_palette_get_columns (palette);
115
116 if (n_columns > 0)
117 cell_width = ((gdouble) (renderer->width - grid_width) /
118 (gdouble) n_columns);
119 else
120 cell_width = (gdouble) (renderer->width - grid_width) / 16.0;
121 }
122
123 cell_width = MAX (4.0, cell_width);
124
125 renderpal->cell_width = cell_width;
126
127 renderpal->columns = (gdouble) (renderer->width - grid_width) / cell_width;
128
129 renderpal->rows = gimp_palette_get_n_colors (palette) / renderpal->columns;
130 if (gimp_palette_get_n_colors (palette) % renderpal->columns)
131 renderpal->rows += 1;
132
133 renderpal->cell_height = MAX (4, ((renderer->height - grid_width) /
134 renderpal->rows));
135
136 if (! renderpal->draw_grid)
137 renderpal->cell_height = MIN (renderpal->cell_height,
138 renderpal->cell_width);
139
140 list = gimp_palette_get_colors (palette);
141
142 if (! renderer->surface)
143 renderer->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
144 renderer->width,
145 renderer->height);
146
147 cairo_surface_flush (renderer->surface);
148
149 row = g_new (guchar, renderer->width * 4);
150
151 dest = cairo_image_surface_get_data (renderer->surface);
152 dest_stride = cairo_image_surface_get_stride (renderer->surface);
153
154 transform = gimp_view_renderer_get_color_transform (renderer, widget,
155 babl_format ("cairo-RGB24"),
156 babl_format ("cairo-RGB24"));
157
158 for (y = 0; y < renderer->height; y++)
159 {
160 if ((y % renderpal->cell_height) == 0)
161 {
162 guchar r, g, b;
163 gint x;
164 gint n = 0;
165 guchar *d = row;
166
167 memset (row, renderpal->draw_grid ? 0 : 255, renderer->width * 4);
168
169 r = g = b = (renderpal->draw_grid ? 0 : 255);
170
171 for (x = 0; x < renderer->width; x++, d += 4)
172 {
173 if ((x % renderpal->cell_width) == 0)
174 {
175 if (list && n < renderpal->columns &&
176 renderer->width - x >= renderpal->cell_width)
177 {
178 GimpPaletteEntry *entry = list->data;
179
180 list = g_list_next (list);
181 n++;
182
183 gimp_rgb_get_uchar (&entry->color, &r, &g, &b);
184 }
185 else
186 {
187 r = g = b = (renderpal->draw_grid ? 0 : 255);
188 }
189 }
190
191 if (renderpal->draw_grid && (x % renderpal->cell_width) == 0)
192 {
193 GIMP_CAIRO_RGB24_SET_PIXEL (d, 0, 0, 0);
194 }
195 else
196 {
197 GIMP_CAIRO_RGB24_SET_PIXEL (d, r, g, b);
198 }
199 }
200 }
201
202 if (renderpal->draw_grid && (y % renderpal->cell_height) == 0)
203 {
204 memset (dest, 0, renderer->width * 4);
205 }
206 else
207 {
208 if (transform)
209 {
210 gimp_color_transform_process_pixels (transform,
211 babl_format ("cairo-RGB24"),
212 row,
213 babl_format ("cairo-RGB24"),
214 dest,
215 renderer->width);
216 }
217 else
218 {
219 memcpy (dest, row, renderer->width * 4);
220 }
221 }
222
223 dest += dest_stride;
224 }
225
226 g_free (row);
227
228 cairo_surface_mark_dirty (renderer->surface);
229 }
230
231
232 /* public functions */
233
234 void
gimp_view_renderer_palette_set_cell_size(GimpViewRendererPalette * renderer,gint cell_size)235 gimp_view_renderer_palette_set_cell_size (GimpViewRendererPalette *renderer,
236 gint cell_size)
237 {
238 g_return_if_fail (GIMP_IS_VIEW_RENDERER_PALETTE (renderer));
239
240 if (cell_size != renderer->cell_size)
241 {
242 renderer->cell_size = cell_size;
243
244 gimp_view_renderer_invalidate (GIMP_VIEW_RENDERER (renderer));
245 }
246 }
247
248 void
gimp_view_renderer_palette_set_draw_grid(GimpViewRendererPalette * renderer,gboolean draw_grid)249 gimp_view_renderer_palette_set_draw_grid (GimpViewRendererPalette *renderer,
250 gboolean draw_grid)
251 {
252 g_return_if_fail (GIMP_IS_VIEW_RENDERER_PALETTE (renderer));
253
254 if (draw_grid != renderer->draw_grid)
255 {
256 renderer->draw_grid = draw_grid ? TRUE : FALSE;
257
258 gimp_view_renderer_invalidate (GIMP_VIEW_RENDERER (renderer));
259 }
260 }
261