gimpviewrendererpalette.c 7.7 KB
Newer Older
1
/* GIMP - The GNU Image Manipulation Program
2 3 4 5 6
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * gimpviewrendererpalette.c
 * Copyright (C) 2005 Michael Natterer <mitch@gimp.org>
 *
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 11 12 13 14 15 16 17
 * (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
18
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19 20 21 22 23 24
 */

#include "config.h"

#include <string.h>

25
#include <gegl.h>
26 27 28 29
#include <gtk/gtk.h>

#include "libgimpcolor/gimpcolor.h"
#include "libgimpmath/gimpmath.h"
30
#include "libgimpwidgets/gimpwidgets.h"
31 32 33 34 35 36 37 38

#include "widgets-types.h"

#include "core/gimppalette.h"

#include "gimpviewrendererpalette.h"


39 40 41
#define COLUMNS 16


42
static void   gimp_view_renderer_palette_finalize (GObject          *object);
43

44 45
static void   gimp_view_renderer_palette_render   (GimpViewRenderer *renderer,
                                                   GtkWidget        *widget);
46 47


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 55 56 57 58 59 60 61 62 63 64 65 66 67


static void
gimp_view_renderer_palette_class_init (GimpViewRendererPaletteClass *klass)
{
  GObjectClass          *object_class   = G_OBJECT_CLASS (klass);
  GimpViewRendererClass *renderer_class = GIMP_VIEW_RENDERER_CLASS (klass);

  object_class->finalize = gimp_view_renderer_palette_finalize;

  renderer_class->render = gimp_view_renderer_palette_render;
}

static void
gimp_view_renderer_palette_init (GimpViewRendererPalette *renderer)
{
68 69
  renderer->cell_size = 4;
  renderer->draw_grid = FALSE;
70
  renderer->columns   = COLUMNS;
71 72 73 74 75 76 77 78 79 80 81 82 83 84
}

static void
gimp_view_renderer_palette_finalize (GObject *object)
{
  G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
gimp_view_renderer_palette_render (GimpViewRenderer *renderer,
                                   GtkWidget        *widget)
{
  GimpViewRendererPalette *renderpal = GIMP_VIEW_RENDERER_PALETTE (renderer);
  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 95

  palette = GIMP_PALETTE (renderer->viewable);

96
  if (gimp_palette_get_n_colors (palette) == 0)
97 98
    return;

99 100
  grid_width = renderpal->draw_grid ? 1 : 0;

101 102
  if (renderpal->cell_size > 0)
    {
103 104 105
      gint n_columns = gimp_palette_get_columns (palette);

      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 115 116
      gint n_columns = gimp_palette_get_columns (palette);

      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 124 125
  cell_width = MAX (4.0, cell_width);

  renderpal->cell_width = cell_width;
126

127
  renderpal->columns = (gdouble) (renderer->width - grid_width) / cell_width;
128

129 130
  renderpal->rows = gimp_palette_get_n_colors (palette) / renderpal->columns;
  if (gimp_palette_get_n_colors (palette) % renderpal->columns)
131
    renderpal->rows += 1;
132

133 134
  renderpal->cell_height = MAX (4, ((renderer->height - grid_width) /
                                    renderpal->rows));
135 136

  if (! renderpal->draw_grid)
137 138
    renderpal->cell_height = MIN (renderpal->cell_height,
                                  renderpal->cell_width);
139

140
  list = gimp_palette_get_colors (palette);
141

142 143 144 145
  if (! renderer->surface)
    renderer->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
                                                    renderer->width,
                                                    renderer->height);
146

147 148
  cairo_surface_flush (renderer->surface);

149
  row = g_new (guchar, renderer->width * 4);
150

151 152
  dest        = cairo_image_surface_get_data (renderer->surface);
  dest_stride = cairo_image_surface_get_stride (renderer->surface);
153

154 155 156 157
  transform = gimp_view_renderer_get_color_transform (renderer, widget,
                                                      babl_format ("cairo-RGB24"),
                                                      babl_format ("cairo-RGB24"));

158 159 160
  for (y = 0; y < renderer->height; y++)
    {
      if ((y % renderpal->cell_height) == 0)
161
        {
162 163
          guchar  r, g, b;
          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 174
              if ((x % renderpal->cell_width) == 0)
                {
175 176
                  if (list && n < renderpal->columns &&
                      renderer->width - x >= renderpal->cell_width)
177 178 179 180
                    {
                      GimpPaletteEntry *entry = list->data;

                      list = g_list_next (list);
181
                      n++;
182 183 184 185 186 187 188 189 190 191 192

                      gimp_rgb_get_uchar (&entry->color, &r, &g, &b);
                    }
                  else
                    {
                      r = g = b = (renderpal->draw_grid ? 0 : 255);
                    }
                }

              if (renderpal->draw_grid && (x % renderpal->cell_width) == 0)
                {
193
                  GIMP_CAIRO_RGB24_SET_PIXEL (d, 0, 0, 0);
194 195 196
                }
              else
                {
197
                  GIMP_CAIRO_RGB24_SET_PIXEL (d, r, g, b);
198
                }
199 200 201
            }
        }

202 203
      if (renderpal->draw_grid && (y % renderpal->cell_height) == 0)
        {
204
          memset (dest, 0, renderer->width * 4);
205 206 207
        }
      else
        {
208 209 210 211 212 213 214 215 216 217 218 219 220
          if (transform)
            {
              gimp_color_transform_process_pixels (transform,
                                                   babl_format ("cairo-RGB24"),
                                                   row,
                                                   babl_format ("cairo-RGB24"),
                                                   dest,
                                                   renderer->width);
            }
          else
            {
              memcpy (dest, row, renderer->width * 4);
            }
221 222
        }

223
      dest += dest_stride;
224 225 226 227
    }

  g_free (row);

228
  cairo_surface_mark_dirty (renderer->surface);
229
}
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260


/*  public functions  */

void
gimp_view_renderer_palette_set_cell_size (GimpViewRendererPalette *renderer,
                                          gint                     cell_size)
{
  g_return_if_fail (GIMP_IS_VIEW_RENDERER_PALETTE (renderer));

  if (cell_size != renderer->cell_size)
    {
      renderer->cell_size = cell_size;

      gimp_view_renderer_invalidate (GIMP_VIEW_RENDERER (renderer));
    }
}

void
gimp_view_renderer_palette_set_draw_grid (GimpViewRendererPalette *renderer,
                                          gboolean                 draw_grid)
{
  g_return_if_fail (GIMP_IS_VIEW_RENDERER_PALETTE (renderer));

  if (draw_grid != renderer->draw_grid)
    {
      renderer->draw_grid = draw_grid ? TRUE : FALSE;

      gimp_view_renderer_invalidate (GIMP_VIEW_RENDERER (renderer));
    }
}