static void gimp_view_renderer_gradient_render (GimpViewRenderer *renderer, GtkWidget *widget) { GimpViewRendererGradient *rendergrad = GIMP_VIEW_RENDERER_GRADIENT (renderer); GimpGradient *gradient = GIMP_GRADIENT (renderer->viewable); GimpGradientSegment *seg = NULL; GimpColorTransform *transform; guchar *buf; guchar *dest; gint dest_stride; gint x; gint y; gdouble dx, cur_x; GimpRGB color; buf = g_alloca (4 * renderer->width); dx = (rendergrad->right - rendergrad->left) / (renderer->width - 1); cur_x = rendergrad->left; for (x = 0, dest = buf; x < renderer->width; x++, dest += 4) { guchar r, g, b, a; seg = gimp_gradient_get_color_at (gradient, renderer->context, seg, cur_x, rendergrad->reverse, &color); cur_x += dx; gimp_rgba_get_uchar (&color, &r, &g, &b, &a); GIMP_CAIRO_ARGB32_SET_PIXEL (dest, r, g, b, a); } if (! renderer->surface) renderer->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, renderer->width, renderer->height); cairo_surface_flush (renderer->surface); dest = cairo_image_surface_get_data (renderer->surface); dest_stride = cairo_image_surface_get_stride (renderer->surface); transform = gimp_view_renderer_get_color_transform (renderer, widget, babl_format ("cairo-ARGB32"), babl_format ("cairo-ARGB32")); if (transform) gimp_color_transform_process_pixels (transform, babl_format ("cairo-ARGB32"), buf, babl_format ("cairo-ARGB32"), buf, renderer->width); for (y = 0; y < renderer->height; y++, dest += dest_stride) { memcpy (dest, buf, renderer->width * 4); } cairo_surface_mark_dirty (renderer->surface); }
static void gimp_view_renderer_palette_render (GimpViewRenderer *renderer, GtkWidget *widget) { GimpViewRendererPalette *renderpal = GIMP_VIEW_RENDERER_PALETTE (renderer); GimpPalette *palette; GimpColorTransform *transform; guchar *row; guchar *dest; GList *list; gdouble cell_width; gint grid_width; gint dest_stride; gint y; palette = GIMP_PALETTE (renderer->viewable); if (gimp_palette_get_n_colors (palette) == 0) return; grid_width = renderpal->draw_grid ? 1 : 0; if (renderpal->cell_size > 0) { gint n_columns = gimp_palette_get_columns (palette); if (n_columns > 0) cell_width = MAX ((gdouble) renderpal->cell_size, (gdouble) (renderer->width - grid_width) / (gdouble) n_columns); else cell_width = renderpal->cell_size; } else { gint n_columns = gimp_palette_get_columns (palette); if (n_columns > 0) cell_width = ((gdouble) (renderer->width - grid_width) / (gdouble) n_columns); else cell_width = (gdouble) (renderer->width - grid_width) / 16.0; } cell_width = MAX (4.0, cell_width); renderpal->cell_width = cell_width; renderpal->columns = (gdouble) (renderer->width - grid_width) / cell_width; renderpal->rows = gimp_palette_get_n_colors (palette) / renderpal->columns; if (gimp_palette_get_n_colors (palette) % renderpal->columns) renderpal->rows += 1; renderpal->cell_height = MAX (4, ((renderer->height - grid_width) / renderpal->rows)); if (! renderpal->draw_grid) renderpal->cell_height = MIN (renderpal->cell_height, renderpal->cell_width); list = gimp_palette_get_colors (palette); if (! renderer->surface) renderer->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, renderer->width, renderer->height); cairo_surface_flush (renderer->surface); row = g_new (guchar, renderer->width * 4); dest = cairo_image_surface_get_data (renderer->surface); dest_stride = cairo_image_surface_get_stride (renderer->surface); transform = gimp_view_renderer_get_color_transform (renderer, widget, babl_format ("cairo-RGB24"), babl_format ("cairo-RGB24")); for (y = 0; y < renderer->height; y++) { if ((y % renderpal->cell_height) == 0) { guchar r, g, b; gint x; gint n = 0; guchar *d = row; memset (row, renderpal->draw_grid ? 0 : 255, renderer->width * 4); r = g = b = (renderpal->draw_grid ? 0 : 255); for (x = 0; x < renderer->width; x++, d += 4) { if ((x % renderpal->cell_width) == 0) { if (list && n < renderpal->columns && renderer->width - x >= renderpal->cell_width) { GimpPaletteEntry *entry = list->data; list = g_list_next (list); n++; 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) { GIMP_CAIRO_RGB24_SET_PIXEL (d, 0, 0, 0); } else { GIMP_CAIRO_RGB24_SET_PIXEL (d, r, g, b); } } } if (renderpal->draw_grid && (y % renderpal->cell_height) == 0) { memset (dest, 0, renderer->width * 4); } else { 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); } } dest += dest_stride; } g_free (row); cairo_surface_mark_dirty (renderer->surface); }
static gboolean gimp_fg_bg_view_expose (GtkWidget *widget, GdkEventExpose *eevent) { GimpFgBgView *view = GIMP_FG_BG_VIEW (widget); GtkStyle *style = gtk_widget_get_style (widget); GdkWindow *window = gtk_widget_get_window (widget); cairo_t *cr; GtkAllocation allocation; gint rect_w, rect_h; GimpRGB color; if (! gtk_widget_is_drawable (widget)) return FALSE; cr = gdk_cairo_create (eevent->window); gdk_cairo_region (cr, eevent->region); cairo_clip (cr); gtk_widget_get_allocation (widget, &allocation); cairo_translate (cr, allocation.x, allocation.y); rect_w = allocation.width * 3 / 4; rect_h = allocation.height * 3 / 4; if (! view->transform) gimp_fg_bg_view_create_transform (view); /* draw the background area */ if (view->context) { gimp_context_get_background (view->context, &color); if (view->transform) gimp_color_transform_process_pixels (view->transform, babl_format ("R'G'B'A double"), &color, babl_format ("R'G'B'A double"), &color, 1); gimp_cairo_set_source_rgb (cr, &color); cairo_rectangle (cr, allocation.width - rect_w + 1, allocation.height - rect_h + 1, rect_w - 2, rect_h - 2); cairo_fill (cr); } gtk_paint_shadow (style, window, GTK_STATE_NORMAL, GTK_SHADOW_IN, NULL, widget, NULL, allocation.x + allocation.width - rect_w, allocation.y + allocation.height - rect_h, rect_w, rect_h); /* draw the foreground area */ if (view->context) { gimp_context_get_foreground (view->context, &color); if (view->transform) gimp_color_transform_process_pixels (view->transform, babl_format ("R'G'B'A double"), &color, babl_format ("R'G'B'A double"), &color, 1); gimp_cairo_set_source_rgb (cr, &color); cairo_rectangle (cr, 1, 1, rect_w - 2, rect_h - 2); cairo_fill (cr); } gtk_paint_shadow (style, window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, widget, NULL, allocation.x, allocation.y, rect_w, rect_h); cairo_destroy (cr); return TRUE; }
static void gimp_pick_button_pick (GimpPickButton *button, GdkEvent *event) { GdkScreen *screen = gdk_event_get_screen (event); GimpColorProfile *monitor_profile; GdkMonitor *monitor; GimpRGB rgb; gint x_root; gint y_root; gdouble x_win; gdouble y_win; gdk_window_get_origin (gdk_event_get_window (event), &x_root, &y_root); gdk_event_get_coords (event, &x_win, &y_win); x_root += x_win; y_root += y_win; #ifdef G_OS_WIN32 { HDC hdc; RECT rect; COLORREF win32_color; /* For MS Windows, use native GDI functions to get the pixel, as * cairo does not handle the case where you have multiple monitors * with a monitor on the left or above the primary monitor. That * scenario create a cairo primary surface with negative extent, * which is not handled properly (bug 740634). */ hdc = GetDC (HWND_DESKTOP); GetClipBox (hdc, &rect); win32_color = GetPixel (hdc, x_root + rect.left, y_root + rect.top); ReleaseDC (HWND_DESKTOP, hdc); gimp_rgba_set_uchar (&rgb, GetRValue (win32_color), GetGValue (win32_color), GetBValue (win32_color), 255); } #else { GdkWindow *window; gint x_window; gint y_window; cairo_surface_t *image; cairo_t *cr; guchar *data; guchar color[3]; /* we try to pick from the local window under the cursor, and fall * back to picking from the root window if this fails (i.e., if * the cursor is not under a local window). on wayland, picking * from the root window is not supported, so this at least allows * us to pick from local windows. see bug #780375. */ window = gdk_device_get_window_at_position (gdk_event_get_device (event), &x_window, &y_window); if (! window) { window = gdk_screen_get_root_window (screen); x_window = x_root; y_window = y_root; } image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 1, 1); cr = cairo_create (image); gdk_cairo_set_source_window (cr, window, -x_window, -y_window); cairo_paint (cr); cairo_destroy (cr); data = cairo_image_surface_get_data (image); GIMP_CAIRO_RGB24_GET_PIXEL (data, color[0], color[1], color[2]); cairo_surface_destroy (image); gimp_rgba_set_uchar (&rgb, color[0], color[1], color[2], 255); } #endif monitor = gdk_display_get_monitor_at_point (gdk_screen_get_display (screen), x_root, y_root); monitor_profile = gimp_monitor_get_color_profile (monitor); if (monitor_profile) { GimpColorProfile *srgb_profile; GimpColorTransform *transform; const Babl *format; GimpColorTransformFlags flags = 0; format = babl_format ("R'G'B'A double"); flags |= GIMP_COLOR_TRANSFORM_FLAGS_NOOPTIMIZE; flags |= GIMP_COLOR_TRANSFORM_FLAGS_BLACK_POINT_COMPENSATION; srgb_profile = gimp_color_profile_new_rgb_srgb (); transform = gimp_color_transform_new (monitor_profile, format, srgb_profile, format, GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL, flags); g_object_unref (srgb_profile); if (transform) { gimp_color_transform_process_pixels (transform, format, &rgb, format, &rgb, 1); gimp_rgb_clamp (&rgb); g_object_unref (transform); } } g_signal_emit_by_name (button, "color-picked", &rgb); }