static void cdisplay_lcms_convert_surface (GimpColorDisplay *display, cairo_surface_t *surface) { CdisplayLcms *lcms = CDISPLAY_LCMS (display); gint width = cairo_image_surface_get_width (surface); gint height = cairo_image_surface_get_height (surface); gint stride = cairo_image_surface_get_stride (surface); guchar *buf = cairo_image_surface_get_data (surface); cairo_format_t fmt = cairo_image_surface_get_format (surface); guchar *rowbuf; gint x, y; guchar r, g, b, a; if (fmt != CAIRO_FORMAT_ARGB32) return; if (! lcms->transform) return; rowbuf = g_malloc (stride); for (y = 0; y < height; y++, buf += stride) { /* Switch buf from ARGB premul to ARGB non-premul, since lcms ignores the * alpha channel. The macro takes care of byte order. */ for (x = 0; x < width; x++) { GIMP_CAIRO_ARGB32_GET_PIXEL (buf + 4*x, r, g, b, a); rowbuf[4*x+0] = a; rowbuf[4*x+1] = r; rowbuf[4*x+2] = g; rowbuf[4*x+3] = b; } cmsDoTransform (lcms->transform, rowbuf, rowbuf, width); /* And back to ARGB premul */ for (x = 0; x < width; x++) { a = rowbuf[4*x+0]; r = rowbuf[4*x+1]; g = rowbuf[4*x+2]; b = rowbuf[4*x+3]; GIMP_CAIRO_ARGB32_SET_PIXEL (buf + 4*x, r, g, b, a); } } g_free (rowbuf); }
static void cdisplay_gamma_convert_surface (GimpColorDisplay *display, cairo_surface_t *surface) { CdisplayGamma *gamma = CDISPLAY_GAMMA (display); gint width = cairo_image_surface_get_width (surface); gint height = cairo_image_surface_get_height (surface); gint stride = cairo_image_surface_get_stride (surface); guchar *buf = cairo_image_surface_get_data (surface); cairo_format_t fmt = cairo_image_surface_get_format (surface); gint i, j, skip; gint r, g, b, a; if (fmt != CAIRO_FORMAT_ARGB32) return; /* You will not be using the entire buffer most of the time. * Hence, the simplistic code for this is as follows: * * for (j = 0; j < height; j++) * { * for (i = 0; i < width * bpp; i++) * buf[i] = lookup[buf[i]]; * buf += bpl; * } */ j = height; skip = stride - 4 * width; while (j--) { i = width; while (i--) { GIMP_CAIRO_ARGB32_GET_PIXEL (buf, r, g, b, a); r = gamma->lookup[r]; g = gamma->lookup[g]; b = gamma->lookup[b]; GIMP_CAIRO_ARGB32_SET_PIXEL (buf, r, g, b, a); buf += 4; } buf += skip; } }
static void gimp_text_layer_render_layout (GimpTextLayer *layer, GimpTextLayout *layout) { GimpDrawable *drawable = GIMP_DRAWABLE (layer); GimpItem *item = GIMP_ITEM (layer); GimpImage *image = gimp_item_get_image (item); cairo_t *cr; cairo_surface_t *surface; PixelRegion layerPR; const guchar *data; GimpImageType layer_type; gint layer_alpha_byte; gint rowstride; gint width; gint height; gpointer pr; g_return_if_fail (gimp_drawable_has_alpha (drawable)); width = gimp_item_get_width (item); height = gimp_item_get_height (item); surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); cr = cairo_create (surface); gimp_text_layout_render (layout, cr, layer->text->base_dir, FALSE); cairo_destroy (cr); pixel_region_init (&layerPR, gimp_drawable_get_tiles (drawable), 0, 0, width, height, TRUE); layer_type = gimp_drawable_type (drawable); layer_alpha_byte = layerPR.bytes - 1; cairo_surface_flush (surface); data = cairo_image_surface_get_data (surface); rowstride = cairo_image_surface_get_stride (surface); for (pr = pixel_regions_register (1, &layerPR); pr != NULL; pr = pixel_regions_process (pr)) { const guchar *src = data + layerPR.y * rowstride + layerPR.x * 4; guchar *dest = layerPR.data; gint rows = layerPR.h; while (rows--) { const guchar *s = src; guchar *d = dest; gint w = layerPR.w; while (w--) { guchar color[4]; GIMP_CAIRO_ARGB32_GET_PIXEL (s, color[0], color[1], color[2], color[3]); gimp_image_transform_color (image, layer_type, d, GIMP_RGB, color); d[layer_alpha_byte] = color[3]; s += 4; d += layerPR.bytes; } src += rowstride; dest += layerPR.rowstride; } } cairo_surface_destroy (surface); gimp_drawable_update (drawable, 0, 0, width, height); }