/* LIBGIMP - The GIMP Library * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball * * gimpcolorscale.c * Copyright (C) 2002-2010 Sven Neumann * Michael Natterer * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see * . */ #include "config.h" #include #include #include #include "libgimpbase/gimpbase.h" #include "libgimpconfig/gimpconfig.h" #include "libgimpcolor/gimpcolor.h" #include "gimpwidgetstypes.h" #include "gimpcairo-utils.h" #include "gimpcolorscale.h" #include "gimpwidgetsutils.h" /** * SECTION: gimpcolorscale * @title: GimpColorScale * @short_description: Fancy colored sliders. * * Fancy colored sliders. **/ enum { PROP_0, PROP_CHANNEL }; struct _GimpColorScale { GtkScale parent_instance; GimpColorConfig *config; guchar oog_color[3]; const Babl *format; GimpColorSelectorChannel channel; GeglColor *color; guchar *buf; guint width; guint height; guint rowstride; gboolean needs_render; }; static void gimp_color_scale_dispose (GObject *object); static void gimp_color_scale_finalize (GObject *object); static void gimp_color_scale_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); static void gimp_color_scale_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static void gimp_color_scale_size_allocate (GtkWidget *widget, GtkAllocation *allocation); static gboolean gimp_color_scale_draw (GtkWidget *widget, cairo_t *cr); static void gimp_color_scale_render (GimpColorScale *scale); static void gimp_color_scale_render_alpha (GimpColorScale *scale); static void gimp_color_scale_notify_config (GimpColorConfig *config, const GParamSpec *pspec, GimpColorScale *scale); G_DEFINE_TYPE (GimpColorScale, gimp_color_scale, GTK_TYPE_SCALE) #define parent_class gimp_color_scale_parent_class static const Babl *fish_lch_to_rgb = NULL; static const Babl *fish_hsv_to_rgb = NULL; static const Babl *fish_rgb_to_cairo = NULL; static void gimp_color_scale_class_init (GimpColorScaleClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = gimp_color_scale_dispose; object_class->finalize = gimp_color_scale_finalize; object_class->get_property = gimp_color_scale_get_property; object_class->set_property = gimp_color_scale_set_property; widget_class->size_allocate = gimp_color_scale_size_allocate; widget_class->draw = gimp_color_scale_draw; /** * GimpColorScale:channel: * * The channel which is edited by the color scale. * * Since: 2.8 */ g_object_class_install_property (object_class, PROP_CHANNEL, g_param_spec_enum ("channel", "Channel", "The channel which is edited by the color scale", GIMP_TYPE_COLOR_SELECTOR_CHANNEL, GIMP_COLOR_SELECTOR_VALUE, GIMP_PARAM_READWRITE | G_PARAM_CONSTRUCT)); gtk_widget_class_set_css_name (widget_class, "GimpColorScale"); fish_lch_to_rgb = babl_fish (babl_format ("CIE LCH(ab) float"), babl_format ("R'G'B' double")); fish_hsv_to_rgb = babl_fish (babl_format ("HSV float"), babl_format ("R'G'B' double")); fish_rgb_to_cairo = babl_fish (babl_format ("R'G'B' u8"), babl_format ("cairo-RGB24")); } static void gimp_color_scale_init (GimpColorScale *scale) { GtkRange *range = GTK_RANGE (scale); GtkCssProvider *css; gtk_widget_set_can_focus (GTK_WIDGET (scale), TRUE); gtk_range_set_slider_size_fixed (range, TRUE); gtk_range_set_flippable (GTK_RANGE (scale), TRUE); gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE); scale->channel = GIMP_COLOR_SELECTOR_VALUE; scale->needs_render = TRUE; gtk_orientable_set_orientation (GTK_ORIENTABLE (range), GTK_ORIENTATION_HORIZONTAL); scale->color = gegl_color_new ("black"); css = gtk_css_provider_new (); gtk_css_provider_load_from_data (css, "GimpColorScale {" " padding: 2px 12px 2px 12px;" " min-width: 24px;" " min-height: 24px;" "}\n" "GimpColorScale contents trough {" " min-width: 20px;" " min-height: 20px;" "}\n" "GimpColorScale contents trough slider {" " min-width: 12px;" " min-height: 12px;" " margin: -6px -6px -6px -6px;" "}", -1, NULL); gtk_style_context_add_provider (gtk_widget_get_style_context (GTK_WIDGET (scale)), GTK_STYLE_PROVIDER (css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); g_object_unref (css); } static void gimp_color_scale_dispose (GObject *object) { GimpColorScale *scale = GIMP_COLOR_SCALE (object); gimp_color_scale_set_color_config (scale, NULL); G_OBJECT_CLASS (parent_class)->dispose (object); } static void gimp_color_scale_finalize (GObject *object) { GimpColorScale *scale = GIMP_COLOR_SCALE (object); g_clear_pointer (&scale->buf, g_free); scale->width = 0; scale->height = 0; scale->rowstride = 0; g_object_unref (scale->color); G_OBJECT_CLASS (parent_class)->finalize (object); } static void gimp_color_scale_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GimpColorScale *scale = GIMP_COLOR_SCALE (object); switch (property_id) { case PROP_CHANNEL: g_value_set_enum (value, scale->channel); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gimp_color_scale_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GimpColorScale *scale = GIMP_COLOR_SCALE (object); switch (property_id) { case PROP_CHANNEL: gimp_color_scale_set_channel (scale, g_value_get_enum (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gimp_color_scale_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GimpColorScale *scale = GIMP_COLOR_SCALE (widget); GtkRange *range = GTK_RANGE (widget); GdkRectangle range_rect; GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); gtk_range_get_range_rect (range, &range_rect); if (range_rect.width != scale->width || range_rect.height != scale->height) { scale->width = range_rect.width; scale->height = range_rect.height; /* TODO: we should move to CAIRO_FORMAT_RGBA128F. */ scale->rowstride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, scale->width); g_free (scale->buf); scale->buf = g_new (guchar, 3 * scale->width * scale->height); scale->needs_render = TRUE; } } static gboolean gimp_color_scale_draw (GtkWidget *widget, cairo_t *cr) { GimpColorScale *scale = GIMP_COLOR_SCALE (widget); GtkRange *range = GTK_RANGE (widget); GtkStyleContext *context = gtk_widget_get_style_context (widget); GdkRectangle range_rect; GdkRectangle area = { 0, }; cairo_surface_t *buffer; guchar *buf = NULL; guchar *src; guchar *dest; gint slider_start; gint slider_end; gint slider_mid; gint slider_size; const Babl *render_space; if (! scale->buf) return FALSE; gtk_range_get_range_rect (range, &range_rect); gtk_range_get_slider_range (range, &slider_start, &slider_end); slider_mid = slider_start + (slider_end - slider_start) / 2; slider_size = 6; if (scale->needs_render) { gimp_color_scale_render (scale); scale->needs_render = FALSE; } render_space = gimp_widget_get_render_space (widget, scale->config); fish_rgb_to_cairo = babl_fish (babl_format_with_space ("R'G'B' u8", scale->format), babl_format_with_space ("cairo-RGB24", render_space)), src = scale->buf; buf = g_new (guchar, scale->rowstride * scale->height); dest = buf; /* We convert per line because the cairo rowstride may be bigger than the * real contents. */ for (gint i = 0; i < scale->height; i++) { babl_process (fish_rgb_to_cairo, src, dest, scale->width); src += 3 * scale->width; dest += scale->rowstride; } buffer = cairo_image_surface_create_for_data (buf, CAIRO_FORMAT_RGB24, scale->width, scale->height, scale->rowstride); cairo_surface_set_user_data (buffer, NULL, buf, (cairo_destroy_func_t) g_free); switch (gtk_orientable_get_orientation (GTK_ORIENTABLE (range))) { case GTK_ORIENTATION_HORIZONTAL: cairo_set_source_surface (cr, buffer, range_rect.x, range_rect.y); break; case GTK_ORIENTATION_VERTICAL: cairo_set_source_surface (cr, buffer, range_rect.x, range_rect.y); break; } cairo_surface_destroy (buffer); if (! gtk_widget_is_sensitive (widget)) { static cairo_pattern_t *pattern = NULL; if (! pattern) { static const guchar stipple[] = { 0, 255, 0, 0, 255, 0, 0, 0 }; cairo_surface_t *surface; gint stride; stride = cairo_format_stride_for_width (CAIRO_FORMAT_A8, 2); surface = cairo_image_surface_create_for_data ((guchar *) stipple, CAIRO_FORMAT_A8, 2, 2, stride); pattern = cairo_pattern_create_for_surface (surface); cairo_surface_destroy (surface); cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT); } cairo_mask (cr, pattern); } else { cairo_paint (cr); } if (gtk_widget_has_focus (widget)) gtk_render_focus (context, cr, 0, 0, gtk_widget_get_allocated_width (widget), gtk_widget_get_allocated_height (widget)); switch (gtk_orientable_get_orientation (GTK_ORIENTABLE (range))) { case GTK_ORIENTATION_HORIZONTAL: area.x = slider_mid - slider_size; area.y = range_rect.y; area.width = 2 * slider_size; area.height = range_rect.height; break; case GTK_ORIENTATION_VERTICAL: area.x = range_rect.x; area.y = slider_mid - slider_size; area.width = range_rect.width; area.height = 2 * slider_size; break; } if (gtk_widget_is_sensitive (widget)) cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); else cairo_set_source_rgb (cr, 0.2, 0.2, 0.2); switch (gtk_orientable_get_orientation (GTK_ORIENTABLE (range))) { case GTK_ORIENTATION_HORIZONTAL: cairo_move_to (cr, area.x, area.y); cairo_line_to (cr, area.x + area.width, area.y); cairo_line_to (cr, area.x + area.width / 2 + 0.5, area.y + slider_size); break; case GTK_ORIENTATION_VERTICAL: cairo_move_to (cr, area.x, area.y); cairo_line_to (cr, area.x, area.y + area.height); cairo_line_to (cr, area.x + slider_size, area.y + area.height / 2 + 0.5); break; } cairo_close_path (cr); cairo_fill (cr); if (gtk_widget_is_sensitive (widget)) cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); else cairo_set_source_rgb (cr, 0.8, 0.8, 0.8); switch (gtk_orientable_get_orientation (GTK_ORIENTABLE (range))) { case GTK_ORIENTATION_HORIZONTAL: cairo_move_to (cr, area.x, area.y + area.height); cairo_line_to (cr, area.x + area.width, area.y + area.height); cairo_line_to (cr, area.x + area.width / 2 + 0.5, area.y + area.height - slider_size); break; case GTK_ORIENTATION_VERTICAL: cairo_move_to (cr, area.x + area.width, area.y); cairo_line_to (cr, area.x + area.width, area.y + area.height); cairo_line_to (cr, area.x + area.width - slider_size, area.y + area.height / 2 + 0.5); break; } cairo_close_path (cr); cairo_fill (cr); return FALSE; } /** * gimp_color_scale_new: * @orientation: the scale's orientation (horizontal or vertical) * @channel: the scale's color channel * * Creates a new #GimpColorScale widget. * * Returns: a new #GimpColorScale widget **/ GtkWidget * gimp_color_scale_new (GtkOrientation orientation, GimpColorSelectorChannel channel) { GimpColorScale *scale = g_object_new (GIMP_TYPE_COLOR_SCALE, "orientation", orientation, "channel", channel, NULL); gtk_range_set_flippable (GTK_RANGE (scale), orientation == GTK_ORIENTATION_HORIZONTAL); return GTK_WIDGET (scale); } /** * gimp_color_scale_set_format: * @scale: a #GimpColorScale widget * @format: the Babl format represented by @scale. * * Changes the color format displayed by the @scale. **/ void gimp_color_scale_set_format (GimpColorScale *scale, const Babl *format) { if (scale->format != format) { scale->format = format; fish_lch_to_rgb = babl_fish (babl_format ("CIE LCH(ab) float"), babl_format_with_space ("R'G'B' double", format)); fish_hsv_to_rgb = babl_fish (babl_format_with_space ("HSV float", format), babl_format_with_space ("R'G'B' double", format)); scale->needs_render = TRUE; gtk_widget_queue_draw (GTK_WIDGET (scale)); } } /** * gimp_color_scale_set_channel: * @scale: a #GimpColorScale widget * @channel: the new color channel * * Changes the color channel displayed by the @scale. **/ void gimp_color_scale_set_channel (GimpColorScale *scale, GimpColorSelectorChannel channel) { g_return_if_fail (GIMP_IS_COLOR_SCALE (scale)); if (channel != scale->channel) { scale->channel = channel; scale->needs_render = TRUE; gtk_widget_queue_draw (GTK_WIDGET (scale)); g_object_notify (G_OBJECT (scale), "channel"); } } /** * gimp_color_scale_set_color: * @scale: a #GimpColorScale widget * @color: the new color. * * Changes the color value of the @scale. **/ void gimp_color_scale_set_color (GimpColorScale *scale, GeglColor *color) { GeglColor *old_color; g_return_if_fail (GIMP_IS_COLOR_SCALE (scale)); g_return_if_fail (GEGL_IS_COLOR (color)); old_color = scale->color; scale->color = gegl_color_duplicate (color); if (! gimp_color_is_perceptually_identical (old_color, scale->color)) { scale->needs_render = TRUE; gtk_widget_queue_draw (GTK_WIDGET (scale)); } g_object_unref (old_color); } /** * gimp_color_scale_set_color_config: * @scale: a #GimpColorScale widget. * @config: a #GimpColorConfig object. * * Sets the color management configuration to use with this color scale. * * Since: 2.10 */ void gimp_color_scale_set_color_config (GimpColorScale *scale, GimpColorConfig *config) { g_return_if_fail (GIMP_IS_COLOR_SCALE (scale)); g_return_if_fail (config == NULL || GIMP_IS_COLOR_CONFIG (config)); if (config != scale->config) { if (scale->config) { g_signal_handlers_disconnect_by_func (scale->config, gimp_color_scale_notify_config, scale); } g_set_object (&scale->config, config); if (scale->config) { g_signal_connect (scale->config, "notify", G_CALLBACK (gimp_color_scale_notify_config), scale); gimp_color_scale_notify_config (scale->config, NULL, scale); } } } /* as in gtkrange.c */ static gboolean should_invert (GtkRange *range) { gboolean inverted = gtk_range_get_inverted (range); gboolean flippable = gtk_range_get_flippable (range); if (gtk_orientable_get_orientation (GTK_ORIENTABLE (range)) == GTK_ORIENTATION_HORIZONTAL) { return (inverted && !flippable) || (inverted && flippable && gtk_widget_get_direction (GTK_WIDGET (range)) == GTK_TEXT_DIR_LTR) || (!inverted && flippable && gtk_widget_get_direction (GTK_WIDGET (range)) == GTK_TEXT_DIR_RTL); } else { return inverted; } } static void gimp_color_scale_render (GimpColorScale *scale) { GtkRange *range = GTK_RANGE (scale); gdouble rgb[4]; gfloat hsv[3]; gfloat lch[3]; gint multiplier = 1; guint x, y; gdouble *channel_value = NULL; gfloat *channel_value_f = NULL; gboolean from_hsv = FALSE; gboolean from_lch = FALSE; gboolean invert; guchar *buf; guchar *d; if ((buf = scale->buf) == NULL) return; if (scale->channel == GIMP_COLOR_SELECTOR_ALPHA) { gimp_color_scale_render_alpha (scale); return; } gegl_color_get_pixel (scale->color, babl_format_with_space ("R'G'B'A double", scale->format), rgb); gegl_color_get_pixel (scale->color, babl_format_with_space ("HSV float", scale->format), hsv); gegl_color_get_pixel (scale->color, babl_format ("CIE LCH(ab) float"), lch); switch (scale->channel) { case GIMP_COLOR_SELECTOR_HUE: channel_value_f = &hsv[0]; break; case GIMP_COLOR_SELECTOR_SATURATION: channel_value_f = &hsv[1]; break; case GIMP_COLOR_SELECTOR_VALUE: channel_value_f = &hsv[2]; break; case GIMP_COLOR_SELECTOR_RED: channel_value = &rgb[0]; break; case GIMP_COLOR_SELECTOR_GREEN: channel_value = &rgb[1]; break; case GIMP_COLOR_SELECTOR_BLUE: channel_value = &rgb[2]; break; case GIMP_COLOR_SELECTOR_ALPHA: channel_value = &rgb[3]; break; case GIMP_COLOR_SELECTOR_LCH_LIGHTNESS: channel_value_f = &lch[0]; break; case GIMP_COLOR_SELECTOR_LCH_CHROMA: channel_value_f = &lch[1]; break; case GIMP_COLOR_SELECTOR_LCH_HUE: channel_value_f = &lch[2]; break; } switch (scale->channel) { case GIMP_COLOR_SELECTOR_HUE: case GIMP_COLOR_SELECTOR_SATURATION: case GIMP_COLOR_SELECTOR_VALUE: from_hsv = TRUE; break; case GIMP_COLOR_SELECTOR_LCH_LIGHTNESS: multiplier = 100; from_lch = TRUE; break; case GIMP_COLOR_SELECTOR_LCH_CHROMA: multiplier = 200; from_lch = TRUE; break; case GIMP_COLOR_SELECTOR_LCH_HUE: multiplier = 360; from_lch = TRUE; break; default: break; } invert = should_invert (range); switch (gtk_orientable_get_orientation (GTK_ORIENTABLE (range))) { case GTK_ORIENTATION_HORIZONTAL: for (x = 0, d = buf; x < scale->width; x++, d += 3) { gdouble value = (gdouble) x * multiplier / (gdouble) (scale->width - 1); if (invert) value = multiplier - value; if (channel_value) *channel_value = value; else if (channel_value_f) *channel_value_f = (gfloat) value; if (from_hsv) babl_process (fish_hsv_to_rgb, &hsv, &rgb, 1); else if (from_lch) babl_process (fish_lch_to_rgb, &lch, &rgb, 1); /* This is only checking if a color is within the sRGB gamut. I want * to check compared to the image's space (anySpace) or softproof * space. TODO. */ if (rgb[0] < 0.0 || rgb[0] > 1.0 || rgb[1] < 0.0 || rgb[1] > 1.0 || rgb[2] < 0.0 || rgb[2] > 1.0) { d[0] = scale->oog_color[0]; d[1] = scale->oog_color[1]; d[2] = scale->oog_color[2]; } else { d[0] = rgb[0] * 255; d[1] = rgb[1] * 255; d[2] = rgb[2] * 255; } } d = buf + scale->width * 3; for (y = 1; y < scale->height; y++) { memcpy (d, buf, scale->width * 3); d += scale->width * 3; } break; case GTK_ORIENTATION_VERTICAL: for (y = 0; y < scale->height; y++) { gdouble value = (gdouble) y * multiplier / (gdouble) (scale->height - 1); guchar u8rgb[3]; if (invert) value = multiplier - value; if (channel_value) *channel_value = value; else if (channel_value_f) *channel_value_f = (gfloat) value; if (from_hsv) babl_process (fish_hsv_to_rgb, &hsv, &rgb, 1); else if (from_lch) babl_process (fish_lch_to_rgb, &lch, &rgb, 1); if (rgb[0] < 0.0 || rgb[0] > 1.0 || rgb[1] < 0.0 || rgb[1] > 1.0 || rgb[2] < 0.0 || rgb[2] > 1.0) { u8rgb[0] = scale->oog_color[0]; u8rgb[1] = scale->oog_color[1]; u8rgb[2] = scale->oog_color[2]; } else { u8rgb[0] = rgb[0] * 255; u8rgb[1] = rgb[1] * 255; u8rgb[2] = rgb[2] * 255; } for (x = 0, d = buf; x < scale->width; x++, d += 3) { d[0] = u8rgb[0]; d[1] = u8rgb[1]; d[2] = u8rgb[2]; } buf += scale->width * 3; } break; } } static void gimp_color_scale_render_alpha (GimpColorScale *scale) { GtkRange *range = GTK_RANGE (scale); gdouble rgb[3]; gboolean invert; gdouble a; guint x, y; guchar *buf; guchar *d, *l; invert = should_invert (range); buf = scale->buf; gegl_color_get_pixel (scale->color, babl_format_with_space ("R'G'B' double", scale->format), rgb); switch (gtk_orientable_get_orientation (GTK_ORIENTABLE (range))) { case GTK_ORIENTATION_HORIZONTAL: { guchar *light; guchar *dark; light = buf; /* this won't work correctly for very thin scales */ dark = (scale->height > GIMP_CHECK_SIZE_SM ? buf + GIMP_CHECK_SIZE_SM * 3 * scale->width : light); for (x = 0, d = light, l = dark; x < scale->width; x++) { if ((x % GIMP_CHECK_SIZE_SM) == 0) { guchar *t; t = d; d = l; l = t; } a = (gdouble) x / (gdouble) (scale->width - 1); if (invert) a = 1.0 - a; l[0] = (GIMP_CHECK_LIGHT + (rgb[0] - GIMP_CHECK_LIGHT) * a) * 255.999; l[1] = (GIMP_CHECK_LIGHT + (rgb[1] - GIMP_CHECK_LIGHT) * a) * 255.999; l[2] = (GIMP_CHECK_LIGHT + (rgb[2] - GIMP_CHECK_LIGHT) * a) * 255.999; l += 3; d[0] = (GIMP_CHECK_DARK + (rgb[0] - GIMP_CHECK_DARK) * a) * 255.999; d[1] = (GIMP_CHECK_DARK + (rgb[1] - GIMP_CHECK_DARK) * a) * 255.999; d[2] = (GIMP_CHECK_DARK + (rgb[2] - GIMP_CHECK_DARK) * a) * 255.999; d += 3; } for (y = 0, d = buf; y < scale->height; y++, d += 3 * scale->width) { if (y == 0 || y == GIMP_CHECK_SIZE_SM) continue; if ((y / GIMP_CHECK_SIZE_SM) & 1) memcpy (d, dark, 3 * scale->width); else memcpy (d, light, 3 * scale->width); } } break; case GTK_ORIENTATION_VERTICAL: { guchar light[3] = {0xff, 0xff, 0xff}; guchar dark[3] = {0xff, 0xff, 0xff}; for (y = 0, d = buf; y < scale->height; y++, d += scale->width * 3) { a = (gdouble) y / (gdouble) (scale->height - 1); if (invert) a = 1.0 - a; light[0] = (GIMP_CHECK_LIGHT + (rgb[0] - GIMP_CHECK_LIGHT) * a) * 255.999; light[1] = (GIMP_CHECK_LIGHT + (rgb[1] - GIMP_CHECK_LIGHT) * a) * 255.999; light[2] = (GIMP_CHECK_LIGHT + (rgb[2] - GIMP_CHECK_LIGHT) * a) * 255.999; dark[0] = (GIMP_CHECK_DARK + (rgb[0] - GIMP_CHECK_DARK) * a) * 255.999; dark[1] = (GIMP_CHECK_DARK + (rgb[1] - GIMP_CHECK_DARK) * a) * 255.999; dark[2] = (GIMP_CHECK_DARK + (rgb[2] - GIMP_CHECK_DARK) * a) * 255.999; for (x = 0, l = d; x < scale->width; x++, l += 3) { if (((x / GIMP_CHECK_SIZE_SM) ^ (y / GIMP_CHECK_SIZE_SM)) & 1) { l[0] = light[0]; l[1] = light[1]; l[2] = light[2]; } else { l[0] = dark[0]; l[1] = dark[1]; l[2] = dark[2]; } } } } break; } } static void gimp_color_scale_notify_config (GimpColorConfig *config, const GParamSpec *pspec, GimpColorScale *scale) { GeglColor *color; color = gimp_color_config_get_out_of_gamut_color (config); /* TODO: shouldn't this be color-managed too, using the target space into * consideration? */ gegl_color_get_pixel (color, babl_format ("R'G'B' u8"), scale->oog_color); scale->needs_render = TRUE; g_object_unref (color); }