void gimp_display_shell_render (GimpDisplayShell *shell, cairo_t *cr, gint x, gint y, gint w, gint h) { GimpImage *image; GeglBuffer *buffer; #ifdef USE_NODE_BLIT GeglNode *node; #endif gdouble scale_x = 1.0; gdouble scale_y = 1.0; gdouble buffer_scale = 1.0; gint viewport_offset_x; gint viewport_offset_y; gint viewport_width; gint viewport_height; gint scaled_x; gint scaled_y; gint scaled_width; gint scaled_height; cairo_surface_t *xfer; gint xfer_src_x; gint xfer_src_y; gint mask_src_x = 0; gint mask_src_y = 0; gint cairo_stride; guchar *cairo_data; GeglBuffer *cairo_buffer; g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); g_return_if_fail (cr != NULL); g_return_if_fail (w > 0 && h > 0); image = gimp_display_get_image (shell->display); buffer = gimp_pickable_get_buffer (GIMP_PICKABLE (image)); #ifdef USE_NODE_BLIT node = gimp_projectable_get_graph (GIMP_PROJECTABLE (image)); #endif #ifdef GIMP_DISPLAY_RENDER_ENABLE_SCALING /* if we had this future API, things would look pretty on hires (retina) */ scale_x = gdk_window_get_scale_factor (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (shell)))); #endif scale_x = MIN (scale_x, GIMP_DISPLAY_RENDER_MAX_SCALE); scale_y = scale_x; if (shell->scale_x > shell->scale_y) { scale_y *= (shell->scale_x / shell->scale_y); buffer_scale = shell->scale_y * scale_y; } else if (shell->scale_y > shell->scale_x) { scale_x *= (shell->scale_y / shell->scale_x); buffer_scale = shell->scale_x * scale_x; } else { buffer_scale = shell->scale_x * scale_x; } gimp_display_shell_scroll_get_scaled_viewport (shell, &viewport_offset_x, &viewport_offset_y, &viewport_width, &viewport_height); scaled_x = floor ((x + viewport_offset_x) * scale_x); scaled_y = floor ((y + viewport_offset_y) * scale_y); scaled_width = ceil (w * scale_x); scaled_height = ceil (h * scale_y); if (shell->rotate_transform) { xfer = cairo_surface_create_similar_image (cairo_get_target (cr), CAIRO_FORMAT_ARGB32, scaled_width, scaled_height); cairo_surface_mark_dirty (xfer); xfer_src_x = 0; xfer_src_y = 0; } else { xfer = gimp_display_xfer_get_surface (shell->xfer, scaled_width, scaled_height, &xfer_src_x, &xfer_src_y); } cairo_stride = cairo_image_surface_get_stride (xfer); cairo_data = cairo_image_surface_get_data (xfer) + xfer_src_y * cairo_stride + xfer_src_x * 4; cairo_buffer = gegl_buffer_linear_new_from_data (cairo_data, babl_format ("cairo-ARGB32"), GEGL_RECTANGLE (0, 0, scaled_width, scaled_height), cairo_stride, NULL, NULL); if (shell->profile_transform || gimp_display_shell_has_filter (shell)) { gboolean can_convert_to_u8; /* if there is a profile transform or a display filter, we need * to use temp buffers */ can_convert_to_u8 = gimp_display_shell_profile_can_convert_to_u8 (shell); /* create the filter buffer if we have filters */ if ((gimp_display_shell_has_filter (shell) || ! can_convert_to_u8) && ! shell->filter_buffer) { gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH * GIMP_DISPLAY_RENDER_MAX_SCALE; gint h = GIMP_DISPLAY_RENDER_BUF_HEIGHT * GIMP_DISPLAY_RENDER_MAX_SCALE; shell->filter_data = gegl_malloc (w * h * babl_format_get_bytes_per_pixel (shell->filter_format)); shell->filter_stride = w * babl_format_get_bytes_per_pixel (shell->filter_format); shell->filter_buffer = gegl_buffer_linear_new_from_data (shell->filter_data, shell->filter_format, GEGL_RECTANGLE (0, 0, w, h), GEGL_AUTO_ROWSTRIDE, (GDestroyNotify) gegl_free, shell->filter_data); } if (shell->profile_transform) { /* if there is a profile transform, load the projection * pixels into the profile_buffer */ #ifndef USE_NODE_BLIT gegl_buffer_get (buffer, GEGL_RECTANGLE (scaled_x, scaled_y, scaled_width, scaled_height), buffer_scale, gimp_projectable_get_format (GIMP_PROJECTABLE (image)), shell->profile_data, shell->profile_stride, GEGL_ABYSS_CLAMP); #else gegl_node_blit (node, buffer_scale, GEGL_RECTANGLE (scaled_x, scaled_y, scaled_width, scaled_height), gimp_projectable_get_format (GIMP_PROJECTABLE (image)), shell->profile_data, shell->profile_stride, GEGL_BLIT_CACHE); #endif if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8) { /* if there are filters, convert the pixels from the * profile_buffer to the filter_buffer */ gimp_display_shell_profile_convert_buffer (shell, shell->profile_buffer, GEGL_RECTANGLE (0, 0, scaled_width, scaled_height), shell->filter_buffer, GEGL_RECTANGLE (0, 0, scaled_width, scaled_height)); } else { /* otherwise, convert the profile_buffer directly into * the cairo_buffer */ gimp_display_shell_profile_convert_buffer (shell, shell->profile_buffer, GEGL_RECTANGLE (0, 0, scaled_width, scaled_height), cairo_buffer, GEGL_RECTANGLE (0, 0, scaled_width, scaled_height)); } } else { /* otherwise, load the projection pixels directly into the * filter_buffer */ #ifndef USE_NODE_BLIT gegl_buffer_get (buffer, GEGL_RECTANGLE (scaled_x, scaled_y, scaled_width, scaled_height), buffer_scale, shell->filter_format, shell->filter_data, shell->filter_stride, GEGL_ABYSS_CLAMP); #else gegl_node_blit (node, buffer_scale, GEGL_RECTANGLE (scaled_x, scaled_y, scaled_width, scaled_height), shell->filter_format, shell->filter_data, shell->filter_stride, GEGL_BLIT_CACHE); #endif } if (gimp_display_shell_has_filter (shell)) { /* convert the filter_buffer in place */ gimp_color_display_stack_convert_buffer (shell->filter_stack, shell->filter_buffer, GEGL_RECTANGLE (0, 0, scaled_width, scaled_height)); } if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8) { /* finally, copy the filter buffer to the cairo-ARGB32 buffer */ gegl_buffer_get (shell->filter_buffer, GEGL_RECTANGLE (0, 0, scaled_width, scaled_height), 1.0, babl_format ("cairo-ARGB32"), cairo_data, cairo_stride, GEGL_ABYSS_CLAMP); } } else { /* otherwise we can copy the projection pixels straight to the * cairo-ARGB32 buffer */ #ifndef USE_NODE_BLIT gegl_buffer_get (buffer, GEGL_RECTANGLE (scaled_x, scaled_y, scaled_width, scaled_height), buffer_scale, babl_format ("cairo-ARGB32"), cairo_data, cairo_stride, GEGL_ABYSS_CLAMP); #else gegl_node_blit (node, buffer_scale, GEGL_RECTANGLE (scaled_x, scaled_y, scaled_width, scaled_height), babl_format ("cairo-ARGB32"), cairo_data, cairo_stride, GEGL_BLIT_CACHE); #endif } g_object_unref (cairo_buffer); if (shell->mask) { if (! shell->mask_surface) { shell->mask_surface = cairo_image_surface_create (CAIRO_FORMAT_A8, GIMP_DISPLAY_RENDER_BUF_WIDTH * GIMP_DISPLAY_RENDER_MAX_SCALE, GIMP_DISPLAY_RENDER_BUF_HEIGHT * GIMP_DISPLAY_RENDER_MAX_SCALE); } cairo_surface_mark_dirty (shell->mask_surface); cairo_stride = cairo_image_surface_get_stride (shell->mask_surface); cairo_data = cairo_image_surface_get_data (shell->mask_surface) + mask_src_y * cairo_stride + mask_src_x * 4; gegl_buffer_get (shell->mask, GEGL_RECTANGLE (scaled_x - shell->mask_offset_x, scaled_y - shell->mask_offset_y, scaled_width, scaled_height), buffer_scale, babl_format ("Y u8"), cairo_data, cairo_stride, GEGL_ABYSS_NONE); if (shell->mask_inverted) { gint mask_height = scaled_height; while (mask_height--) { gint mask_width = scaled_width; guchar *d = cairo_data; while (mask_width--) { guchar inv = 255 - *d; *d++ = inv; } cairo_data += cairo_stride; } } } /* put it to the screen */ cairo_save (cr); cairo_rectangle (cr, x, y, w, h); cairo_scale (cr, 1.0 / scale_x, 1.0 / scale_y); cairo_set_source_surface (cr, xfer, x * scale_x - xfer_src_x, y * scale_y - xfer_src_y); if (shell->rotate_transform) { cairo_pattern_t *pattern; pattern = cairo_get_source (cr); cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD); cairo_set_line_width (cr, 1.0); cairo_stroke_preserve (cr); cairo_surface_destroy (xfer); } cairo_clip (cr); cairo_paint (cr); if (shell->mask) { gimp_cairo_set_source_rgba (cr, &shell->mask_color); cairo_mask_surface (cr, shell->mask_surface, (x - mask_src_x) * scale_x, (y - mask_src_y) * scale_y); } cairo_restore (cr); }
unsigned char* LcCairoPainter::data() { return cairo_image_surface_get_data(_surface); }
static void cdcreatecanvas(cdCanvas* canvas, void* data) { cdCtxCanvas* ctxcanvas; cairo_surface_t *surface; int w = 0, h = 0, use_alpha = 0; double res = 3.78; unsigned char *rgb = NULL; char* str_data = (char*)data; char* res_ptr = NULL; cairo_format_t format = CAIRO_FORMAT_RGB24; /* Starting parameters */ if (str_data == NULL) return; if (strstr(str_data, "-a")) use_alpha = 1; res_ptr = strstr(str_data, "-r"); if (res_ptr) sscanf(res_ptr+2, "%lg", &res); /* size and rgb */ #ifdef SunOS_OLD sscanf(str_data, "%dx%d %d", &w, &h, &rgb); #else sscanf(str_data, "%dx%d %p", &w, &h, &rgb); #endif if (w == 0) w = 1; if (h == 0) h = 1; canvas->w = w; canvas->h = h; canvas->yres = res; canvas->xres = res; canvas->w_mm = ((double)w) / res; canvas->h_mm = ((double)h) / res; if (use_alpha) { canvas->bpp = 32; format = CAIRO_FORMAT_ARGB32; } else canvas->bpp = 24; /* fake value, image bpp is always 32 */ if (rgb) surface = cairo_image_surface_create_for_data(rgb, format, w, h, w*32); else surface = cairo_image_surface_create(format, canvas->w, canvas->h); /* Starting Cairo driver */ ctxcanvas = cdcairoCreateCanvas(canvas, cairo_create(surface)); cairo_surface_destroy(surface); if (rgb) { ctxcanvas->user_image = 1; ctxcanvas->rgb = rgb; } else { ctxcanvas->user_image = 0; ctxcanvas->rgb = cairo_image_surface_get_data(cairo_get_target(ctxcanvas->cr)); /* fill with white */ /* transparent, this is the normal alpha coding */ cairo_set_source_rgba(ctxcanvas->cr, 1.0, 1.0, 1.0, 0.0); cairo_rectangle(ctxcanvas->cr, 0, 0, canvas->w, canvas->h); cairo_fill(ctxcanvas->cr); } cdRegisterAttribute(canvas, &stride_attrib); cdRegisterAttribute(canvas, &write2png_attrib); cdRegisterAttribute(canvas, &data_attrib); }
double lime_cairo_image_surface_get_data (double handle) { return (intptr_t)cairo_image_surface_get_data ((cairo_surface_t*)(intptr_t)handle); }
gboolean draw_page_cairo (GtkPrintContext *context, PrintData *data) { GimpDrawable *drawable = gimp_drawable_get (data->drawable_id); GimpPixelRgn region; cairo_t *cr; cairo_surface_t *surface; guchar *pixels; gdouble cr_width; gdouble cr_height; gdouble cr_dpi_x; gdouble cr_dpi_y; gint width; gint height; gint stride; gint y; gdouble scale_x; gdouble scale_y; width = drawable->width; height = drawable->height; gimp_tile_cache_ntiles (width / gimp_tile_width () + 1); cr = gtk_print_context_get_cairo_context (context); cr_width = gtk_print_context_get_width (context); cr_height = gtk_print_context_get_height (context); cr_dpi_x = gtk_print_context_get_dpi_x (context); cr_dpi_y = gtk_print_context_get_dpi_y (context); scale_x = cr_dpi_x / data->xres; scale_y = cr_dpi_y / data->yres; #if 0 /* print header if it is requested */ if (data->show_info_header) { draw_info_header (context, cr, data); /* In points */ #define HEADER_HEIGHT (20 * 72.0 / 25.4) cairo_translate (cr, 0, HEADER_HEIGHT); cr_height -= HEADER_HEIGHT; } #endif cairo_translate (cr, data->offset_x / cr_dpi_x * 72.0, data->offset_y / cr_dpi_y * 72.0); cairo_scale (cr, scale_x, scale_y); gimp_pixel_rgn_init (®ion, drawable, 0, 0, width, height, FALSE, FALSE); surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height); pixels = cairo_image_surface_get_data (surface); stride = cairo_image_surface_get_stride (surface); for (y = 0; y < height; y++, pixels += stride) { gimp_pixel_rgn_get_row (®ion, pixels, 0, y, width); switch (drawable->bpp) { case 3: convert_from_rgb (pixels, width); break; case 4: convert_from_rgba (pixels, width); break; } if (y % 16 == 0) gimp_progress_update ((gdouble) y / (gdouble) height); } cairo_set_source_surface (cr, surface, 0, 0); cairo_rectangle (cr, 0, 0, width, height); cairo_fill (cr); cairo_surface_destroy (surface); gimp_progress_update (1.0); gimp_drawable_detach (drawable); return TRUE; }
static inline cairo_region_t * get_cairo_region_create_from_surface(struct qp_graph *gr, cairo_surface_t *surface, int width, int height) { /* TODO: this is a resource pig. Make it better. */ cairo_rectangle_int_t rect; cairo_surface_t *image; cairo_region_t *region; cairo_t *cr; uint32_t *data, bg; int x, y, stride; if(!gr->x11) /* Creates region that covers the area where the * given surface is more than 50% opaque. * The below code copies this method. This GDK * code is a pig too. */ return gdk_cairo_region_create_from_surface(surface); if(!gr->x11->background_set) { /* We need to see what the background color is when it is * applied to an image. A small image. */ image = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 1, 1); cr = cairo_create(image); cairo_set_source_rgba(cr, gr->background_color.r, gr->background_color.g, gr->background_color.b, gr->background_color.a); cairo_paint (cr); cairo_destroy (cr); data = (void *) cairo_image_surface_get_data(image); gr->x11->background = (data[0] & 0x00FFFFFF); cairo_surface_destroy(image); gr->x11->background_set = 1; } bg = gr->x11->background; image = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height); cr = cairo_create(image); cairo_set_source_surface(cr, surface, 0, 0); cairo_paint (cr); cairo_destroy (cr); data = (void *) cairo_image_surface_get_data(image); stride = cairo_image_surface_get_stride(image); region = cairo_region_create(); for(y=0; y < height; y++) { for(x=0; x < width; x++) { /* Search for a continuous range of "background pixels"*/ gint x0=x; while(x < width) { if((data[x] & 0x00FFFFFF) == bg) /* This pixel is the background color */ break; x++; } if(x > x0) { /* Add the pixels (x0, y) to (x, y+1) as a new rectangle * in the region */ rect.x = x0; rect.width = x - x0; rect.y = y; rect.height = 1; cairo_region_union_rectangle(region, &rect); } } data += stride/4; } cairo_surface_destroy(image); return region; }
int msRenderRasterizedSVGSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) struct svg_symbol_cache *svg_cache; symbolStyleObj pixstyle; symbolObj pixsymbol; int status; if(MS_SUCCESS != msPreloadSVGSymbol(symbol)) return MS_FAILURE; svg_cache = (struct svg_symbol_cache*) symbol->renderer_cache; //already rendered at the right size and scale? return if(svg_cache->scale != style->scale || svg_cache->rotation != style->rotation) { cairo_t *cr; cairo_surface_t *surface; unsigned char *pb; int width, height, surface_w, surface_h; /* need to recompute the pixmap */ if(svg_cache->pixmap_buffer) { msFreeRasterBuffer(svg_cache->pixmap_buffer); } else { svg_cache->pixmap_buffer = msSmallCalloc(1,sizeof(rasterBufferObj)); } //increase pixmap size to accomodate scaling/rotation if (style->scale != 1.0) { width = surface_w = (symbol->sizex * style->scale + 0.5); height = surface_h = (symbol->sizey * style->scale + 0.5); } else { width = surface_w = symbol->sizex; height = surface_h = symbol->sizey; } if (style->rotation != 0) { surface_w = surface_h = MS_NINT(MS_MAX(height, width) * 1.415); } surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, surface_w, surface_h); cr = cairo_create(surface); if (style->rotation != 0) { cairo_translate(cr, surface_w / 2, surface_h / 2); cairo_rotate(cr, -style->rotation); cairo_translate(cr, -width / 2, -height / 2); } if (style->scale != 1.0) { cairo_scale(cr, style->scale, style->scale); } #ifdef USE_SVG_CAIRO if(svg_cairo_render(svg_cache->svgc, cr) != SVG_CAIRO_STATUS_SUCCESS) { return MS_FAILURE; } #else rsvg_handle_render_cairo(svg_cache->svgc, cr); #endif pb = cairo_image_surface_get_data(surface); //set up raster initializeRasterBufferCairo(svg_cache->pixmap_buffer, surface_w, surface_h, 0); memcpy(svg_cache->pixmap_buffer->data.rgba.pixels, pb, surface_w * surface_h * 4 * sizeof (unsigned char)); svg_cache->scale = style->scale; svg_cache->rotation = style->rotation; cairo_destroy(cr); cairo_surface_destroy(surface); } assert(svg_cache->pixmap_buffer->height && svg_cache->pixmap_buffer->width); pixstyle = *style; pixstyle.rotation = 0.0; pixstyle.scale = 1.0; pixsymbol.pixmap_buffer = svg_cache->pixmap_buffer; pixsymbol.type = MS_SYMBOL_PIXMAP; status = MS_IMAGE_RENDERER(img)->renderPixmapSymbol(img,x,y,&pixsymbol,&pixstyle); MS_IMAGE_RENDERER(img)->freeSymbol(&pixsymbol); return status; #else msSetError(MS_MISCERR, "SVG Symbols requested but MapServer is not built with libsvgcairo", "renderSVGSymbolCairo()"); return MS_FAILURE; #endif }
static void draw_page_cairo(GtkPrintContext *context, PrintData *data) { cairo_t *cr; GdkPixbuf *pixbuf_to_draw; cairo_surface_t *surface; guchar *surface_pixels; guchar *pixbuf_pixels; gint stride; gint pixbuf_stride; gint pixbuf_n_channels; gdouble cr_dpi_x; gdouble cr_dpi_y; gdouble scale_x; gdouble scale_y; gint y; cr = gtk_print_context_get_cairo_context(context); pixbuf_to_draw = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(vik_viewport_get_pixmap(data->vvp)), NULL, 0, 0, 0, 0, data->width, data->height); surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, data->width, data->height); cr_dpi_x = gtk_print_context_get_dpi_x (context); cr_dpi_y = gtk_print_context_get_dpi_y (context); scale_x = cr_dpi_x / data->xres; scale_y = cr_dpi_y / data->yres; cairo_translate (cr, data->offset_x / cr_dpi_x * 72.0, data->offset_y / cr_dpi_y * 72.0); cairo_scale (cr, scale_x, scale_y); surface_pixels = cairo_image_surface_get_data (surface); stride = cairo_image_surface_get_stride (surface); pixbuf_pixels = gdk_pixbuf_get_pixels (pixbuf_to_draw); pixbuf_stride = gdk_pixbuf_get_rowstride(pixbuf_to_draw); pixbuf_n_channels = gdk_pixbuf_get_n_channels(pixbuf_to_draw); // fprintf(stderr, "DEBUG: %s() surface_pixels=%p pixbuf_pixels=%p size=%d surface_width=%d surface_height=%d stride=%d data_height=%d pixmap_stride=%d pixmap_nchannels=%d pixmap_bit_per_Sample=%d\n", __PRETTY_FUNCTION__, surface_pixels, pixbuf_pixels, stride * data->height, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface), stride, data->height, gdk_pixbuf_get_rowstride(pixbuf_to_draw), gdk_pixbuf_get_n_channels(pixbuf_to_draw), gdk_pixbuf_get_bits_per_sample(pixbuf_to_draw)); /* Assume the pixbuf has 8 bits per channel */ for (y = 0; y < data->height; y++, surface_pixels += stride, pixbuf_pixels += pixbuf_stride) { switch (pixbuf_n_channels) { case 3: copy_row_from_rgb (surface_pixels, pixbuf_pixels, data->width); break; case 4: copy_row_from_rgba (surface_pixels, pixbuf_pixels, data->width); break; } } g_object_unref(G_OBJECT(pixbuf_to_draw)); cairo_set_source_surface(cr, surface, 0, 0); cairo_rectangle(cr, 0, 0, data->width, data->height); cairo_fill(cr); cairo_surface_destroy(surface); }
TGUIFont *Alloc_GUIFont(const char *AFontName, float AHeight) { TGUIFont *BFont = (TGUIFont *)malloc(sizeof(TGUIFont)); BFont->FGridWidth = 0; BFont->FGridHeight = 0; BFont->FHeight = AHeight; BFont->FExtents = (TGUIFontExtent *)malloc(sizeof(TGUIFontExtent) * 256); TGUIFontExtent *BCharExtent = BFont->FExtents; cairo_text_extents_t *BExtents = (cairo_text_extents_t *)malloc(sizeof(cairo_text_extents_t)); int BRow = 0; int BColumn = 0; GUIFont_GetGreaterSize(AFontName, AHeight, &BFont->FGridWidth, &BFont->FGridHeight); printf("[MESSAGE] Font grid of size (%i, %i).\n", BFont->FGridWidth, BFont->FGridHeight); BFont->FTextureWidth = Get_NextP2(BFont->FGridWidth * 16); BFont->FTextureHeight = Get_NextP2(BFont->FGridHeight * 16); printf("[MESSAGE] Font texture of size (%i, %i).\n", BFont->FTextureWidth, BFont->FTextureHeight); unsigned char *BData = NULL; unsigned char *BText = (unsigned char *)malloc(sizeof(unsigned char) * 2); BText[0] = 0; BText[1] = '\0'; // Create texture data . cairo_surface_t *BSurface = cairo_image_surface_create(CAIRO_FORMAT_A8, BFont->FTextureWidth, BFont->FTextureHeight); cairo_t *BContext = cairo_create(BSurface); cairo_set_antialias(BContext, CAIRO_ANTIALIAS_NONE); cairo_set_operator(BContext, CAIRO_OPERATOR_OVER); cairo_set_source_rgba(BContext, 0.0, 0.0, 0.0, 0.0); cairo_font_options_t *cfo = cairo_font_options_create(); cairo_font_options_set_antialias(cfo, CAIRO_ANTIALIAS_SUBPIXEL); cairo_set_font_options(BContext, cfo); cairo_set_source_rgba(BContext, 0.0, 0.0, 0.0, 1.0); cairo_select_font_face(BContext, AFontName, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(BContext, AHeight); for (BText[0] = 0; BText[0] < 255; BText[0]++) { cairo_text_extents(BContext, BText, BExtents); if (BExtents) { BCharExtent->FAdvanceX = BExtents->x_advance; if (BText[0] == 32) { //BCharExtent->FAdvanceX = BFont->FGridWidth; }; BCharExtent->FAdvanceY = BExtents->y_advance; BCharExtent->FBearingX = BExtents->x_bearing; BCharExtent->FBearingY = BExtents->y_bearing; BCharExtent->FWidth = BExtents->width; BCharExtent->FHeight = BExtents->height; BRow = BText[0] / 16; BColumn = BText[0] % 16; cairo_move_to(BContext, -BExtents->x_bearing + (BColumn * BFont->FGridWidth), -BExtents->y_bearing + (BRow * BFont->FGridHeight)); cairo_show_text(BContext, BText); } else { printf("[MESSAGE] Fail to create font. Extents of char %i returned as null.\n", BText[0]); return NULL; }; BCharExtent++; }; cairo_surface_flush(BSurface); //cairo_surface_write_to_png(BSurface, "/home/felipefs/Desktop/texture.png"); BData = cairo_image_surface_get_data(BSurface); glGenTextures(1, &BFont->FTexture); glBindTexture(GL_TEXTURE_2D, BFont->FTexture); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BFont->FTextureWidth, BFont->FTextureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, BData); cairo_destroy(BContext); cairo_surface_destroy(BSurface); //free(BData); if (glIsTexture(BFont->FTexture) == GL_FALSE) { printf("[ERROR] Fail to create character texture of size %ix%i.\n", BFont->FTextureWidth, BFont->FTextureHeight); }; printf("[MESSAGE] Font created.\n"); return BFont; };
bool TextAsset::load() { // Set up a temporary Cairo surface/context for text measurement cairo_surface_t* probeSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1); if (cairo_surface_status(probeSurface) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not create Cairo surface\n"); _error = true; return false; } cairo_t* probeContext = cairo_create(probeSurface); if (cairo_status(probeContext) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not create Cairo context\n"); _error = true; return false; } // Text rectangle drawn within border const int idealWidth = _maxSize.width - _marginLeft - _marginRight; const Size textRegion(idealWidth, _maxSize.height - _marginTop - _marginBottom); const float fontSize = primaryFontSize(probeContext, textRegion); const std::string fontDesc = _fontName + " " + boost::lexical_cast<std::string>(fontSize); PangoFontDescription* fontDescription = pango_font_description_from_string(fontDesc.c_str()); const std::string req_desc_str(pango_font_description_to_string(fontDescription)); PangoFontMap* fontMap = pango_cairo_font_map_new_for_font_type(CAIRO_FONT_TYPE_FT); PangoContext* pango_context = pango_font_map_create_context(fontMap); // TODO: Does this need to be freed or does the context take it with it? PangoFont* pangoFont = pango_font_map_load_font(fontMap, pango_context, fontDescription); PangoFontDescription* reverseDescription = pango_font_describe(pangoFont); const std::string match_desc_str(pango_font_description_to_string(reverseDescription)); pango_font_description_free(reverseDescription); g_object_unref(pango_context); if (req_desc_str.find(match_desc_str) == std::string::npos) { fprintf(stderr, "Warning: Unable to correctly match font \"%s\", using " "\"%s\" instead.\n", req_desc_str.c_str(), match_desc_str.c_str()); } float shadowXOffset = 0; float shadowYOffset = 0; if (_dropShadow) { shadowXOffset = _dropShadowOffset.x() * CLIENT_TO_SERVER_SCALE * fontSize; shadowYOffset = _dropShadowOffset.y() * CLIENT_TO_SERVER_SCALE * fontSize; } Rect tight; const Size textSize = computeSizeOfText(probeContext, _textContent, idealWidth, fontDescription, &tight); const Size imageSize = imageSizeForTextSize(tight.size, shadowXOffset, shadowYOffset); // Tear down scratch contexts cairo_destroy(probeContext); cairo_surface_destroy(probeSurface); const int width = imageSize.width; const int height = imageSize.height; // Configure the actual Cairo drawing surface/context now that we know the final resolution cairo_surface_t* cairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); if (cairo_surface_status(cairoSurface) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not create Cairo surface\n"); _error = true; return false; } cairo_t* cairoContext = cairo_create(cairoSurface); // Flip the context like in the iOS version. // This fixes flipped filters associated with text assets. cairo_translate(cairoContext, 0.0, height); cairo_scale(cairoContext, 1.0, -1.0); if (cairo_status(cairoContext) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not create Cairo context\n"); _error = true; return false; } // Fill the box with the background color cairo_save(cairoContext); cairo_set_operator(cairoContext, CAIRO_OPERATOR_SOURCE); const mf::Color& bgColor(_style->getBackgroundColor()); cairo_set_source_rgba(cairoContext, bgColor.red, bgColor.green, bgColor.blue, bgColor.alpha); if (_shape == 0) { if (_cornerWidth > 0 && _cornerHeight > 0) { // TODO: Support independent corner width and height drawRoundedRect(cairoContext, 0, 0, imageSize.width, imageSize.height, _cornerWidth); } else { cairo_paint(cairoContext); if (_strokeThickness > 0.0f) { drawStrokedRect(cairoContext, 0, 0, imageSize.width, imageSize.height, _strokeThickness); } } } else if (_shape == 1) { strokeFillBezier(cairoContext, 0, 0, imageSize.width, imageSize.height, _strokeThickness); } cairo_restore(cairoContext); const Rect textRect = textRectForTextSize(textSize, imageSize, tight); if (_dropShadow) { const Rect shadowRect(textRect.x + shadowXOffset, textRect.y + shadowYOffset, textRect.size.width, textRect.size.height); cairo_set_source_rgba(cairoContext, _dropShadowColor.red, _dropShadowColor.green, _dropShadowColor.blue, _dropShadowColor.alpha); drawText(cairoContext, _textContent, shadowRect, fontDescription, false); } cairo_set_source_rgba(cairoContext, _textColor.red, _textColor.green, _textColor.blue, _textColor.alpha); if (_textColor.alpha > 0.0) { drawText(cairoContext, _textContent, textRect, fontDescription, true); } // DEBUG: Dump rendered text to an image // cairo_surface_write_to_png(cairoSurface, "text.png"); // Transfer Cairo surface to OpenGL texture GLubyte* imageData = static_cast<GLubyte *>(cairo_image_surface_get_data(cairoSurface)); glGenTextures(1, &_texture.textureID); glBindTexture(GL_TEXTURE_2D, _texture.textureID); _texture.width = width; _texture.height = height; _texture.s = 1.0; _texture.t = 1.0; _texture.aspect = static_cast<GLfloat>(_texture.width) / _texture.height; _texture.flipImage = true; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); #ifdef GL_BGRA // Allocate and transfer data into texture (allow OpenGL swizzling) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, imageData); #else // Cairo uses a BGRA layout, OpenGL ES 2.0 does not support GL_BGRA as a // source format so manually perform swizzling. for (size_t i = 0; i < width * height * BYTES_PER_PIXEL; i += BYTES_PER_PIXEL) { std::swap(imageData[i], imageData[i + 2]); } // Allocate and transfer data into texture glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData); #endif // Clean up pango_font_description_free(fontDescription); cairo_destroy(cairoContext); cairo_surface_destroy(cairoSurface); g_object_unref(pangoFont); _loading = false; _loaded = !_loading && !_error; return true; }
/* Print text scale */ void RenderText() { int i = 0; cairo_surface_t *surface; cairo_t *cr; const unsigned char* surfaceData; if (viewType == TWO_D){ xX = -0.1, yY = 0.05, zZ = 0; } else { xX = -0.02, yY = 0, zZ = 0; } glColor3f(1, 1, 1); for (i = 0 + (zoom * hzStep); i <= ((hzStep * bandsNumber *zoomFactor) + (zoom * hzStep)); i+= ((hzStep * bandsNumber * zoomFactor)/10)) { sprintf(textToRender, "%d", i); surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 32, 32); cr = cairo_create (surface); //cairo_select_font_face (cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); if (viewType == TWO_D){ cairo_set_font_size (cr, 8.0); cairo_move_to (cr, 0, 12); } else { cairo_set_font_size (cr, 10.0); cairo_move_to (cr, 0, 18); } cairo_show_text (cr, textToRender); cairo_surface_flush(surface); surfaceData = cairo_image_surface_get_data (surface); unsigned Texture = 0; glGenTextures(1, &Texture); glBindTexture(GL_TEXTURE_2D, Texture); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface), 0, GL_BGRA, GL_UNSIGNED_BYTE, surfaceData); glBegin(GL_QUADS); glColor4f(1, 1, 1, 1); glTexCoord2d(0, 0); glVertex3d(xX, yY, 0.01); glTexCoord2d(1, 0); glVertex3d(xX+0.1, yY, 0.01); glTexCoord2d(1, 1); glVertex3d(xX+0.1, yY-0.2, 0.01); glTexCoord2d(0, 1); glVertex3d(xX, yY-0.2, 0.01); glEnd(); glDeleteTextures(1, &Texture); cairo_destroy (cr); cairo_surface_destroy (surface); if (viewType == TWO_D){ yY += y_2d/10; } else { xX += x/10; } } }
bool GraphicsContext3D::ImageExtractor::extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile) { // This implementation is taken from GraphicsContext3DCairo. if (!m_image) return false; // We need this to stay in scope because the native image is just a shallow copy of the data. m_decoder = new ImageSource(premultiplyAlpha ? ImageSource::AlphaPremultiplied : ImageSource::AlphaNotPremultiplied, ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied); if (!m_decoder) return false; ImageSource& decoder = *m_decoder; m_alphaOp = AlphaDoNothing; if (m_image->data()) { decoder.setData(m_image->data(), true); if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0)) return false; m_imageSurface = decoder.createFrameAtIndex(0); } else { m_imageSurface = m_image->nativeImageForCurrentFrame(); // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value is 0xFF for each pixel, // which is true at present and may be changed in the future and needs adjustment accordingly. // 2. For texImage2D with HTMLCanvasElement input in which Alpha is already Premultiplied in this port, // do AlphaDoUnmultiply if UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to false. if (!premultiplyAlpha && m_imageHtmlDomSource != HtmlDomVideo) m_alphaOp = AlphaDoUnmultiply; } if (!m_imageSurface) return false; m_imageWidth = cairo_image_surface_get_width(m_imageSurface.get()); m_imageHeight = cairo_image_surface_get_height(m_imageSurface.get()); if (!m_imageWidth || !m_imageHeight) return false; if (cairo_image_surface_get_format(m_imageSurface.get()) != CAIRO_FORMAT_ARGB32) return false; uint srcUnpackAlignment = 1; size_t bytesPerRow = cairo_image_surface_get_stride(m_imageSurface.get()); size_t bitsPerPixel = 32; unsigned padding = bytesPerRow - bitsPerPixel / 8 * m_imageWidth; if (padding) { srcUnpackAlignment = padding + 1; while (bytesPerRow % srcUnpackAlignment) ++srcUnpackAlignment; } m_imagePixelData = cairo_image_surface_get_data(m_imageSurface.get()); m_imageSourceFormat = DataFormatBGRA8; m_imageSourceUnpackAlignment = srcUnpackAlignment; return true; }
static gboolean gimp_color_bar_expose (GtkWidget *widget, GdkEventExpose *event) { GimpColorBar *bar = GIMP_COLOR_BAR (widget); cairo_t *cr; GtkAllocation allocation; cairo_surface_t *surface; cairo_pattern_t *pattern; guchar *src; guchar *dest; gint x, y; gint width, height; gint i; cr = gdk_cairo_create (event->window); gdk_cairo_region (cr, event->region); cairo_clip (cr); gtk_widget_get_allocation (widget, &allocation); x = y = gtk_container_get_border_width (GTK_CONTAINER (bar)); width = allocation.width - 2 * x; height = allocation.height - 2 * y; if (width < 1 || height < 1) return TRUE; cairo_translate (cr, allocation.x + x, allocation.y + y); cairo_rectangle (cr, 0, 0, width, height); cairo_clip (cr); surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 256, 1); for (i = 0, src = bar->buf, dest = cairo_image_surface_get_data (surface); i < 256; i++, src += 3, dest += 4) { GIMP_CAIRO_RGB24_SET_PIXEL(dest, src[0], src[1], src[2]); } cairo_surface_mark_dirty (surface); pattern = cairo_pattern_create_for_surface (surface); cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REFLECT); cairo_surface_destroy (surface); if (bar->orientation == GTK_ORIENTATION_HORIZONTAL) { cairo_scale (cr, (gdouble) width / 256.0, 1.0); } else { cairo_translate (cr, 0, height); cairo_scale (cr, 1.0, (gdouble) height / 256.0); cairo_rotate (cr, - G_PI / 2); } cairo_set_source (cr, pattern); cairo_pattern_destroy (pattern); cairo_paint (cr); cairo_destroy (cr); return TRUE; }
static const char * write_ppm (cairo_surface_t *surface, int fd) { char buf[4096]; cairo_format_t format; const char *format_str; const unsigned char *data; int len; int width, height, stride; int i, j; data = cairo_image_surface_get_data (surface); height = cairo_image_surface_get_height (surface); width = cairo_image_surface_get_width (surface); stride = cairo_image_surface_get_stride (surface); format = cairo_image_surface_get_format (surface); if (format == CAIRO_FORMAT_ARGB32) { /* see if we can convert to a standard ppm type and trim a few bytes */ const unsigned char *alpha = data; for (j = height; j--; alpha += stride) { for (i = 0; i < width; i++) { if ((*(unsigned int *) (alpha+4*i) & 0xff000000) != 0xff000000) goto done; } } format = CAIRO_FORMAT_RGB24; done: ; } switch (format) { case CAIRO_FORMAT_ARGB32: /* XXX need true alpha for svg */ format_str = "P7"; break; case CAIRO_FORMAT_RGB24: format_str = "P6"; break; case CAIRO_FORMAT_A8: format_str = "P5"; break; case CAIRO_FORMAT_A1: case CAIRO_FORMAT_RGB16_565: case CAIRO_FORMAT_RGB30: case CAIRO_FORMAT_INVALID: default: return "unhandled image format"; } len = sprintf (buf, "%s %d %d 255\n", format_str, width, height); for (j = 0; j < height; j++) { const unsigned int *row = (unsigned int *) (data + stride * j); switch ((int) format) { case CAIRO_FORMAT_ARGB32: len = _cairo_write (fd, buf, sizeof (buf), len, (unsigned char *) row, 4 * width); break; case CAIRO_FORMAT_RGB24: for (i = 0; i < width; i++) { unsigned char rgb[3]; unsigned int p = *row++; rgb[0] = (p & 0xff0000) >> 16; rgb[1] = (p & 0x00ff00) >> 8; rgb[2] = (p & 0x0000ff) >> 0; len = _cairo_write (fd, buf, sizeof (buf), len, rgb, 3); } break; case CAIRO_FORMAT_A8: len = _cairo_write (fd, buf, sizeof (buf), len, (unsigned char *) row, width); break; } if (len < 0) return "write failed"; } if (len && ! _cairo_writen (fd, buf, len)) return "write failed"; return NULL; }
static bool_t to_ninepatch(cairo_surface_t * surface, struct lninepatch_t * patch) { cairo_surface_t * cs; cairo_t * cr; unsigned char * data; int width, height; int stride; int w, h; int i; if(!surface || !patch) return FALSE; width = cairo_image_surface_get_width(surface); height = cairo_image_surface_get_height(surface); if(width < 3 || height < 3) return FALSE; /* Nine patch chunk */ cs = cairo_surface_create_similar_image(surface, CAIRO_FORMAT_ARGB32, width, height); cr = cairo_create(cs); cairo_set_source_surface(cr, surface, 0, 0); cairo_paint(cr); cairo_destroy(cr); data = cairo_image_surface_get_data(cs); stride = cairo_image_surface_get_stride(cs); /* Nine patch default size */ width = width - 2; height = height - 2; patch->width = width; patch->height = height; /* Stretch information */ patch->left = 0; patch->right = 0; patch->top = 0; patch->right = 0; for(i = 0; i < width; i++) { if(detect_black_pixel(&data[(i + 1) * 4])) { patch->left = i; break; } } for(i = width - 1; i >= 0; i--) { if(detect_black_pixel(&data[(i + 1) * 4])) { patch->right = width - 1 - i; break; } } for(i = 0; i < height; i++) { if(detect_black_pixel(&data[stride * (i + 1)])) { patch->top = i; break; } } for(i = height - 1; i >= 0; i--) { if(detect_black_pixel(&data[stride * (i + 1)])) { patch->bottom = height - 1 - i; break; } } cairo_surface_destroy(cs); /* Left top */ w = patch->left; h = patch->top; if(w > 0 && h > 0) { cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), patch->left, patch->top); cr = cairo_create(cs); cairo_set_source_surface(cr, surface, -1, -1); cairo_paint(cr); cairo_destroy(cr); patch->lt = cs; } else { patch->lt = NULL; } /* Middle top */ w = width - patch->left - patch->right; h = patch->top; if(w > 0 && h > 0) { cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h); cr = cairo_create(cs); cairo_set_source_surface(cr, surface, -patch->left - 1, -1); cairo_paint(cr); cairo_destroy(cr); patch->mt = cs; } else { patch->mt = NULL; } /* Right top */ w = patch->right; h = patch->top; if(w > 0 && h > 0) { cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h); cr = cairo_create(cs); cairo_set_source_surface(cr, surface, -(width - patch->right) - 1, -1); cairo_paint(cr); cairo_destroy(cr); patch->rt = cs; } else { patch->rt = NULL; } /* Left Middle */ w = patch->left; h = height - patch->top - patch->bottom; if(w > 0 && h > 0) { cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h); cr = cairo_create(cs); cairo_set_source_surface(cr, surface, -1, -patch->top - 1); cairo_paint(cr); cairo_destroy(cr); patch->lm = cs; } else { patch->lm = NULL; } /* Middle Middle */ w = width - patch->left - patch->right; h = height - patch->top - patch->bottom; if(w > 0 && h > 0) { cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h); cr = cairo_create(cs); cairo_set_source_surface(cr, surface, -patch->left - 1, -patch->top - 1); cairo_paint(cr); cairo_destroy(cr); patch->mm = cs; } else { patch->mm = NULL; } /* Right middle */ w = patch->right; h = height - patch->top - patch->bottom; if(w > 0 && h > 0) { cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h); cr = cairo_create(cs); cairo_set_source_surface(cr, surface, -(width - patch->right) - 1, -patch->top - 1); cairo_paint(cr); cairo_destroy(cr); patch->rm = cs; } else { patch->rm = NULL; } /* Left bottom */ w = patch->left; h = patch->bottom; if(w > 0 && h > 0) { cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h); cr = cairo_create(cs); cairo_set_source_surface(cr, surface, -1, -(height - patch->bottom) - 1); cairo_paint(cr); cairo_destroy(cr); patch->lb = cs; } else { patch->lb = NULL; } /* Middle bottom */ w = width - patch->left - patch->right; h = patch->bottom; if(w > 0 && h > 0) { cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h); cr = cairo_create(cs); cairo_set_source_surface(cr, surface, -patch->left - 1, -(height - patch->bottom) - 1); cairo_paint(cr); cairo_destroy(cr); patch->mb = cs; } else { patch->mb = NULL; } /* Right bottom */ w = patch->right; h = patch->bottom; if(w > 0 && h > 0) { cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h); cr = cairo_create(cs); cairo_set_source_surface(cr, surface, -(width - patch->right) - 1, -(height - patch->bottom) - 1); cairo_paint(cr); cairo_destroy(cr); patch->rb = cs; } else { patch->rb = NULL; } ninepatch_stretch(patch, width, height); return TRUE; }
static double find_signed_distance( int px, int py, cairo_surface_t* surface, int scan_width, int scan_height ) { int width = cairo_image_surface_get_width(surface); unsigned char* data = cairo_image_surface_get_data(surface); unsigned char base = data[(px * width) + py]; int base_solid = base > 0; double closest = MAX_VALUE; int closest_valid = 0; int start_x = px - (scan_width / 2); int end_x = start_x + scan_width; int start_y = py - (scan_height / 2); int end_y = start_y + scan_height; int x; int y; for(x = start_x; x < end_x; x++) { if(x < 0 || x >= width) continue; for(y = start_y; y < end_y; y++) { unsigned char c; if(y < 0 || y >= width) continue; c = data[(x * width) + y]; if(base_solid) { if(c == 0) { double dist = separation(px, py, x, y); if (dist < closest) { closest = dist; closest_valid = 1; } } } else { if(c > 0) { double dist = separation(px, py, x, y); if(dist < closest) { closest = dist; closest_valid = 1; } } } } } if(base_solid) { if(closest_valid) return closest; else return MAX_VALUE; } else { if(closest_valid) return -closest; else return MIN_VALUE; } }
void TileEngine::renderPixels( cairo_surface_t *destSurf, cairo_surface_t *cmapSurf, PyObject *tileFunction, PyObject *tileMap, int renderCol, int renderRow, int renderCols, int renderRows) { if ((tileFunction != Py_None) && !PyCallable_Check(tileFunction)) { PyErr_SetString( PyExc_TypeError, "expected tileFunction to be a callable function or None"); return; } // The tileMap should be None, or an array of 4 byte integers, // mapping virtual tiles indices to absolute tile numbers. const int *tileMapData = NULL; unsigned int tileMapCount = 0; if (tileMap != Py_None) { if (!PySequence_Check(tileMap)) { PyErr_SetString( PyExc_TypeError, "expected tileMap to be an array " "of 4 byte integers or None"); return; } tileMapCount = (unsigned int)PySequence_Size(tileMap); Py_ssize_t tileMapLength = 0; if (PyObject_AsReadBuffer( tileMap, (const void **)&tileMapData, &tileMapLength) != 0) { PyErr_SetString( PyExc_TypeError, "expected tileMap with read buffer"); return; } int tileMapDataCount = (int)tileMapLength / sizeof(unsigned int); if (tileMapDataCount != (int)tileMapCount) { PyErr_SetString( PyExc_TypeError, "expected tileMap read buffer of 4 byte integers"); return; } } unsigned char *destData = cairo_image_surface_get_data(destSurf); int destStride = cairo_image_surface_get_stride(destSurf); unsigned char *cmapData = cairo_image_surface_get_data(cmapSurf); int cmapWidth = cairo_image_surface_get_width(cmapSurf); int cmapStride = cairo_image_surface_get_stride(cmapSurf); int r; for (r = 0; r < renderRows; r++) { int c; for (c = 0; c < renderCols; c++) { int col = (renderCol + c) % width; int row = (renderRow + r) % height; unsigned long tile = getValue( col, row, tileFunction, tileMapData, tileMapCount); int sourceX = tile % cmapWidth; int sourceY = tile / cmapWidth; unsigned char *sourcePixel = cmapData + (sourceX * 4) + (sourceY * cmapStride); unsigned char *destPixel = destData + (c * 4) + (r * destStride); *(long *)destPixel = *(long *)sourcePixel; } } }
static void pango_loadimage_ps(GVJ_t * job, usershape_t *us, boxf b, boolean filled) { cairo_surface_t *surface; /* source surface */ cairo_format_t format; int X, Y, x, y, stride; unsigned char *data, *ix, alpha, red, green, blue; surface = cairo_loadimage(job, us); if (surface) { format = cairo_image_surface_get_format(surface); if ((format != CAIRO_FORMAT_ARGB32) && (format != CAIRO_FORMAT_RGB24)) return; X = cairo_image_surface_get_width(surface); Y = cairo_image_surface_get_height(surface); stride = cairo_image_surface_get_stride(surface); data = cairo_image_surface_get_data(surface); gvputs(job, "save\n"); /* define image data as string array (one per raster line) */ /* see parallel code in gd_loadimage_ps(). FIXME: refactor... */ gvputs(job, "/myctr 0 def\n"); gvputs(job, "/myarray [\n"); for (y = 0; y < Y; y++) { gvputs(job, "<"); ix = data + y * stride; for (x = 0; x < X; x++) { /* FIXME - this code may have endian problems */ blue = *ix++; green = *ix++; red = *ix++; alpha = *ix++; if (alpha < 0x7f) gvputs(job, "ffffff"); else gvprintf(job, "%02x%02x%02x", red, green, blue); } gvputs(job, ">\n"); } gvputs(job, "] def\n"); gvputs(job,"/myproc { myarray myctr get /myctr myctr 1 add def } def\n"); /* this sets the position of the image */ gvprintf(job, "%g %g translate\n", (b.LL.x + (b.UR.x - b.LL.x) * (1. - (job->dpi.x) / 96.) / 2.), (b.LL.y + (b.UR.y - b.LL.y) * (1. - (job->dpi.y) / 96.) / 2.)); /* this sets the rendered size to fit the box */ gvprintf(job,"%g %g scale\n", ((b.UR.x - b.LL.x) * 72. / 96.), ((b.UR.y - b.LL.y) * 72. / 96.)); /* xsize ysize bits-per-sample [matrix] */ gvprintf(job, "%d %d 8 [%d 0 0 %d 0 %d]\n", X, Y, X, -Y, Y); gvputs(job, "{myproc} false 3 colorimage\n"); gvputs(job, "restore\n"); } }
static void byzanz_encoder_gstreamer_need_data (GstAppSrc *src, guint length, gpointer data) { ByzanzEncoder *encoder = data; ByzanzEncoderGStreamer *gst = data; GstBuffer *buffer; cairo_t *cr; cairo_surface_t *surface; cairo_region_t *region; GError *error = NULL; guint64 msecs; int i, num_rects; if (!byzanz_deserialize (encoder->input_stream, &msecs, &surface, ®ion, encoder->cancellable, &error)) { gst_element_message_full (GST_ELEMENT (src), GST_MESSAGE_ERROR, error->domain, error->code, g_strdup (error->message), NULL, __FILE__, GST_FUNCTION, __LINE__); g_error_free (error); return; } if (surface == NULL) { gst_app_src_end_of_stream (gst->src); if (gst->audiosrc) gst_element_send_event (gst->audiosrc, gst_event_new_eos ()); return; } if (cairo_surface_get_reference_count (gst->surface) > 1) { cairo_surface_t *copy = cairo_image_surface_create (CAIRO_FORMAT_RGB24, cairo_image_surface_get_width (gst->surface), cairo_image_surface_get_height (gst->surface)); cr = cairo_create (copy); cairo_set_source_surface (cr, gst->surface, 0, 0); cairo_paint (cr); cairo_destroy (cr); cairo_surface_destroy (gst->surface); gst->surface = copy; } cr = cairo_create (gst->surface); cairo_set_source_surface (cr, surface, 0, 0); num_rects = cairo_region_num_rectangles (region); for (i = 0; i < num_rects; i++) { cairo_rectangle_int_t rect; cairo_region_get_rectangle (region, i, &rect); cairo_rectangle (cr, rect.x, rect.y, rect.width, rect.height); } cairo_fill (cr); cairo_destroy (cr); /* create a buffer and send it */ /* FIXME: stride just works? */ cairo_surface_reference (gst->surface); buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, cairo_image_surface_get_data (gst->surface), cairo_image_surface_get_stride (gst->surface) * cairo_image_surface_get_height (gst->surface), 0, cairo_image_surface_get_stride (gst->surface) * cairo_image_surface_get_height (gst->surface), gst->surface, (GDestroyNotify) cairo_surface_destroy); GST_BUFFER_TIMESTAMP (buffer) = msecs * GST_MSECOND; gst_app_src_push_buffer (gst->src, buffer); }
static void _GraphicsScreen_cellArrayOrImage (GraphicsScreen me, double **z_float, double_rgbt **z_rgbt, unsigned char **z_byte, long ix1, long ix2, long x1DC, long x2DC, long iy1, long iy2, long y1DC, long y2DC, double minimum, double maximum, long clipx1, long clipx2, long clipy1, long clipy2, int interpolate) { /*long t=clock();*/ long nx = ix2 - ix1 + 1; /* The number of cells along the horizontal axis. */ long ny = iy2 - iy1 + 1; /* The number of cells along the vertical axis. */ double dx = (double) (x2DC - x1DC) / (double) nx; /* Horizontal pixels per cell. Positive. */ double dy = (double) (y2DC - y1DC) / (double) ny; /* Vertical pixels per cell. Negative. */ double scale = 255.0 / (maximum - minimum), offset = 255.0 + minimum * scale; if (x2DC <= x1DC || y1DC <= y2DC) return; trace ("scale %f", scale); /* Clip by the intersection of the world window and the outline of the cells. */ //Melder_casual ("clipy1 %ld clipy2 %ld", clipy1, clipy2); if (clipx1 < x1DC) clipx1 = x1DC; if (clipx2 > x2DC) clipx2 = x2DC; if (clipy1 > y1DC) clipy1 = y1DC; if (clipy2 < y2DC) clipy2 = y2DC; /* * The first decision is whether we are going to use the standard rectangle drawing * (cellArray only), or whether we are going to write into a bitmap. * The standard drawing is best for small numbers of cells, * provided that some cells are larger than a pixel. */ if (! interpolate && nx * ny < 3000 && (dx > 1.0 || dy < -1.0)) { try { /*unsigned int cellWidth = (unsigned int) dx + 1;*/ unsigned int cellHeight = (unsigned int) (- (int) dy) + 1; long ix, iy; #if cairo cairo_pattern_t *grey [256]; for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey ++) { double v = igrey / ((double) (sizeof (grey) / sizeof (*grey)) - 1.0); grey [igrey] = cairo_pattern_create_rgb (v, v, v); } #elif win static HBRUSH greyBrush [256]; RECT rect; if (! greyBrush [0]) for (int igrey = 0; igrey <= 255; igrey ++) greyBrush [igrey] = CreateSolidBrush (RGB (igrey, igrey, igrey)); // once #elif mac GraphicsQuartz_initDraw (me); CGContextSetAlpha (my d_macGraphicsContext, 1.0); CGContextSetBlendMode (my d_macGraphicsContext, kCGBlendModeNormal); #endif autoNUMvector <long> lefts (ix1, ix2 + 1); for (ix = ix1; ix <= ix2 + 1; ix ++) lefts [ix] = x1DC + (long) ((ix - ix1) * dx); for (iy = iy1; iy <= iy2; iy ++) { long bottom = y1DC + (long) ((iy - iy1) * dy), top = bottom - cellHeight; if (top > clipy1 || bottom < clipy2) continue; if (top < clipy2) top = clipy2; if (bottom > clipy1) bottom = clipy1; #if win rect. bottom = bottom; rect. top = top; #endif for (ix = ix1; ix <= ix2; ix ++) { long left = lefts [ix], right = lefts [ix + 1]; if (right < clipx1 || left > clipx2) continue; if (left < clipx1) left = clipx1; if (right > clipx2) right = clipx2; if (z_rgbt) { #if cairo // NYI #elif win // NYI #elif mac double red = z_rgbt [iy] [ix]. red; double green = z_rgbt [iy] [ix]. green; double blue = z_rgbt [iy] [ix]. blue; double transparency = z_rgbt [iy] [ix]. transparency; red = ( red <= 0.0 ? 0.0 : red >= 1.0 ? 1.0 : red ); green = ( green <= 0.0 ? 0.0 : green >= 1.0 ? 1.0 : green ); blue = ( blue <= 0.0 ? 0.0 : blue >= 1.0 ? 1.0 : blue ); CGContextSetRGBFillColor (my d_macGraphicsContext, red, green, blue, 1.0 - transparency); CGContextFillRect (my d_macGraphicsContext, CGRectMake (left, top, right - left, bottom - top)); #endif } else { #if cairo long value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] ); cairo_set_source (my d_cairoGraphicsContext, grey [value <= 0 ? 0 : value >= sizeof (grey) / sizeof (*grey) ? sizeof (grey) / sizeof (*grey) : value]); cairo_rectangle (my d_cairoGraphicsContext, left, top, right - left, bottom - top); cairo_fill (my d_cairoGraphicsContext); #elif win long value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] ); rect. left = left; rect. right = right; FillRect (my d_gdiGraphicsContext, & rect, greyBrush [value <= 0 ? 0 : value >= 255 ? 255 : value]); #elif mac double value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] ); double igrey = ( value <= 0 ? 0 : value >= 255 ? 255 : value ) / 255.0; CGContextSetRGBFillColor (my d_macGraphicsContext, igrey, igrey, igrey, 1.0); CGContextFillRect (my d_macGraphicsContext, CGRectMake (left, top, right - left, bottom - top)); #endif } } } #if cairo for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey ++) cairo_pattern_destroy (grey [igrey]); #elif mac CGContextSetRGBFillColor (my d_macGraphicsContext, 0.0, 0.0, 0.0, 1.0); GraphicsQuartz_exitDraw (me); #endif } catch (MelderError) { } } else { long xDC, yDC; long undersampling = 1; /* * Prepare for off-screen bitmap drawing. */ #if cairo long arrayWidth = clipx2 - clipx1; long arrayHeight = clipy1 - clipy2; trace ("arrayWidth %f, arrayHeight %f", (double) arrayWidth, (double) arrayHeight); cairo_surface_t *sfc = cairo_image_surface_create (CAIRO_FORMAT_RGB24, arrayWidth, arrayHeight); unsigned char *bits = cairo_image_surface_get_data (sfc); int scanLineLength = cairo_image_surface_get_stride (sfc); unsigned char grey [256]; trace ("image surface address %p, bits address %p, scanLineLength %d, numberOfGreys %d", sfc, bits, scanLineLength, sizeof(grey)/sizeof(*grey)); for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey++) grey [igrey] = 255 - (unsigned char) (igrey * 255.0 / (sizeof (grey) / sizeof (*grey) - 1)); #elif win long bitmapWidth = clipx2 - clipx1, bitmapHeight = clipy1 - clipy2; int igrey; /* * Create a device-independent bitmap, 32 bits deep. */ struct { BITMAPINFOHEADER header; } bitmapInfo; long scanLineLength = bitmapWidth * 4; // for 24 bits: (bitmapWidth * 3 + 3) & ~3L; HBITMAP bitmap; unsigned char *bits; // a pointer to memory allocated by VirtualAlloc or by CreateDIBSection () bitmapInfo. header.biSize = sizeof (BITMAPINFOHEADER); bitmapInfo. header.biWidth = bitmapWidth; // scanLineLength; bitmapInfo. header.biHeight = bitmapHeight; bitmapInfo. header.biPlanes = 1; bitmapInfo. header.biBitCount = 32; bitmapInfo. header.biCompression = 0; bitmapInfo. header.biSizeImage = 0; bitmapInfo. header.biXPelsPerMeter = 0; bitmapInfo. header.biYPelsPerMeter = 0; bitmapInfo. header.biClrUsed = 0; bitmapInfo. header.biClrImportant = 0; bitmap = CreateDIBSection (my d_gdiGraphicsContext /* ignored */, (CONST BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS, (VOID **) & bits, NULL, 0); #elif mac long bytesPerRow = (clipx2 - clipx1) * 4; Melder_assert (bytesPerRow > 0); long numberOfRows = clipy1 - clipy2; Melder_assert (numberOfRows > 0); unsigned char *imageData = Melder_malloc_f (unsigned char, bytesPerRow * numberOfRows); #endif /* * Draw into the bitmap. */ #if cairo #define ROW_START_ADDRESS (bits + (clipy1 - 1 - yDC) * scanLineLength) #define PUT_PIXEL \ if (1) { \ unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = 0; \ } #elif win #define ROW_START_ADDRESS (bits + (clipy1 - 1 - yDC) * scanLineLength) #define PUT_PIXEL \ if (1) { \ unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = 0; \ } #elif mac #define ROW_START_ADDRESS (imageData + (clipy1 - 1 - yDC) * bytesPerRow) #define PUT_PIXEL \ if (my colourScale == kGraphics_colourScale_GREY) { \ unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = 0; \ } else if (my colourScale == kGraphics_colourScale_BLUE_TO_RED) { \ if (value < 0.0) { \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 63; \ *pixelAddress ++ = 0; \ } else if (value < 64.0) { \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ *pixelAddress ++ = (int) (value * 3 + 63.999); \ *pixelAddress ++ = 0; \ } else if (value < 128.0) { \ *pixelAddress ++ = (int) (value * 4 - 256.0); \ *pixelAddress ++ = (int) (value * 4 - 256.0); \ *pixelAddress ++ = 255; \ *pixelAddress ++ = 0; \ } else if (value < 192.0) { \ *pixelAddress ++ = 255; \ *pixelAddress ++ = (int) ((256.0 - value) * 4 - 256.0); \ *pixelAddress ++ = (int) ((256.0 - value) * 4 - 256.0); \ *pixelAddress ++ = 0; \ } else if (value < 256.0) { \ *pixelAddress ++ = (int) ((256.0 - value) * 3 + 63.999); \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ } else { \ *pixelAddress ++ = 63; \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ } \ } #else #define ROW_START_ADDRESS NULL #define PUT_PIXEL #endif if (interpolate) { try { autoNUMvector <long> ileft (clipx1, clipx2); autoNUMvector <long> iright (clipx1, clipx2); autoNUMvector <double> rightWeight (clipx1, clipx2); autoNUMvector <double> leftWeight (clipx1, clipx2); for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double ix_real = ix1 - 0.5 + ((double) nx * (xDC - x1DC)) / (x2DC - x1DC); ileft [xDC] = floor (ix_real), iright [xDC] = ileft [xDC] + 1; rightWeight [xDC] = ix_real - ileft [xDC], leftWeight [xDC] = 1.0 - rightWeight [xDC]; if (ileft [xDC] < ix1) ileft [xDC] = ix1; if (iright [xDC] > ix2) iright [xDC] = ix2; } for (yDC = clipy2; yDC < clipy1; yDC += undersampling) { double iy_real = iy2 + 0.5 - ((double) ny * (yDC - y2DC)) / (y1DC - y2DC); long itop = ceil (iy_real), ibottom = itop - 1; double bottomWeight = itop - iy_real, topWeight = 1.0 - bottomWeight; unsigned char *pixelAddress = ROW_START_ADDRESS; if (itop > iy2) itop = iy2; if (ibottom < iy1) ibottom = iy1; if (z_float) { double *ztop = z_float [itop], *zbottom = z_float [ibottom]; for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double interpol = rightWeight [xDC] * (topWeight * ztop [iright [xDC]] + bottomWeight * zbottom [iright [xDC]]) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]] + bottomWeight * zbottom [ileft [xDC]]); double value = offset - scale * interpol; PUT_PIXEL } } else if (z_rgbt) { double_rgbt *ztop = z_rgbt [itop], *zbottom = z_rgbt [ibottom]; for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double red = rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. red + bottomWeight * zbottom [iright [xDC]]. red) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]]. red + bottomWeight * zbottom [ileft [xDC]]. red); double green = rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. green + bottomWeight * zbottom [iright [xDC]]. green) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]]. green + bottomWeight * zbottom [ileft [xDC]]. green); double blue = rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. blue + bottomWeight * zbottom [iright [xDC]]. blue) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]]. blue + bottomWeight * zbottom [ileft [xDC]]. blue); double transparency = rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. transparency + bottomWeight * zbottom [iright [xDC]]. transparency) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]]. transparency + bottomWeight * zbottom [ileft [xDC]]. transparency); if (red < 0.0) red = 0.0; else if (red > 1.0) red = 1.0; if (green < 0.0) green = 0.0; else if (green > 1.0) green = 1.0; if (blue < 0.0) blue = 0.0; else if (blue > 1.0) blue = 1.0; if (transparency < 0.0) transparency = 0.0; else if (transparency > 1.0) transparency = 1.0; #if win *pixelAddress ++ = blue * 255.0; *pixelAddress ++ = green * 255.0; *pixelAddress ++ = red * 255.0; *pixelAddress ++ = 0; #elif mac *pixelAddress ++ = red * 255.0; *pixelAddress ++ = green * 255.0; *pixelAddress ++ = blue * 255.0; *pixelAddress ++ = transparency * 255.0; #elif cairo *pixelAddress ++ = blue * 255.0; *pixelAddress ++ = green * 255.0; *pixelAddress ++ = red * 255.0; *pixelAddress ++ = transparency * 255.0; #endif } } else { unsigned char *ztop = z_byte [itop], *zbottom = z_byte [ibottom]; for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double interpol = rightWeight [xDC] * (topWeight * ztop [iright [xDC]] + bottomWeight * zbottom [iright [xDC]]) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]] + bottomWeight * zbottom [ileft [xDC]]); double value = offset - scale * interpol; PUT_PIXEL } } } } catch (MelderError) { Melder_clearError (); } } else { try { autoNUMvector <long> ix (clipx1, clipx2); for (xDC = clipx1; xDC < clipx2; xDC += undersampling) ix [xDC] = floor (ix1 + (nx * (xDC - x1DC)) / (x2DC - x1DC)); for (yDC = clipy2; yDC < clipy1; yDC += undersampling) { long iy = ceil (iy2 - (ny * (yDC - y2DC)) / (y1DC - y2DC)); unsigned char *pixelAddress = ROW_START_ADDRESS; Melder_assert (iy >= iy1 && iy <= iy2); if (z_float) { double *ziy = z_float [iy]; for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double value = offset - scale * ziy [ix [xDC]]; PUT_PIXEL } } else { unsigned char *ziy = z_byte [iy]; for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double value = offset - scale * ziy [ix [xDC]]; PUT_PIXEL } } } } catch (MelderError) { Melder_clearError (); } } /* * Copy the bitmap to the screen. */ #if cairo cairo_matrix_t clip_trans; cairo_matrix_init_identity (& clip_trans); cairo_matrix_scale (& clip_trans, 1, -1); // we painted in the reverse y-direction cairo_matrix_translate (& clip_trans, - clipx1, - clipy1); cairo_pattern_t *bitmap_pattern = cairo_pattern_create_for_surface (sfc); trace ("bitmap pattern %p", bitmap_pattern); if (cairo_status_t status = cairo_pattern_status (bitmap_pattern)) { Melder_casual ("bitmap pattern status: %s", cairo_status_to_string (status)); } else { cairo_pattern_set_matrix (bitmap_pattern, & clip_trans); cairo_save (my d_cairoGraphicsContext); cairo_set_source (my d_cairoGraphicsContext, bitmap_pattern); cairo_paint (my d_cairoGraphicsContext); cairo_restore (my d_cairoGraphicsContext); } cairo_pattern_destroy (bitmap_pattern); #elif win SetDIBitsToDevice (my d_gdiGraphicsContext, clipx1, clipy2, bitmapWidth, bitmapHeight, 0, 0, 0, bitmapHeight, bits, (CONST BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS); //StretchDIBits (my d_gdiGraphicsContext, clipx1, clipy2, bitmapWidth, bitmapHeight, 0, 0, 0, bitmapHeight, // bits, (CONST BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS, SRCCOPY); #elif mac CGImageRef image; static CGColorSpaceRef colourSpace = NULL; if (colourSpace == NULL) { colourSpace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB); // used to be kCGColorSpaceUserRGB Melder_assert (colourSpace != NULL); } if (1) { CGDataProviderRef dataProvider = CGDataProviderCreateWithData (NULL, imageData, bytesPerRow * numberOfRows, _mac_releaseDataCallback // we need this because we cannot release the image data immediately after drawing, // because in PDF files the imageData has to stay available through EndPage ); Melder_assert (dataProvider != NULL); image = CGImageCreate (clipx2 - clipx1, numberOfRows, 8, 32, bytesPerRow, colourSpace, kCGImageAlphaNone, dataProvider, NULL, false, kCGRenderingIntentDefault); CGDataProviderRelease (dataProvider); } else if (0) { Melder_assert (CGBitmapContextCreate != NULL); CGContextRef bitmaptest = CGBitmapContextCreate (imageData, 100, 100, 8, 800, colourSpace, 0); Melder_assert (bitmaptest != NULL); CGContextRef bitmap = CGBitmapContextCreate (NULL/*imageData*/, clipx2 - clipx1, numberOfRows, 8, bytesPerRow, colourSpace, kCGImageAlphaLast); Melder_assert (bitmap != NULL); image = CGBitmapContextCreateImage (bitmap); // release bitmap? } Melder_assert (image != NULL); GraphicsQuartz_initDraw (me); CGContextDrawImage (my d_macGraphicsContext, CGRectMake (clipx1, clipy2, clipx2 - clipx1, clipy1 - clipy2), image); GraphicsQuartz_exitDraw (me); //CGColorSpaceRelease (colourSpace); CGImageRelease (image); #endif /* * Clean up. */ #if cairo cairo_surface_destroy (sfc); #elif win DeleteBitmap (bitmap); #endif }
cairo_surface_t * cairo_boilerplate_image_surface_create_from_ppm_stream (FILE *file) { char format; int width, height, stride; int x, y; unsigned char *data; cairo_surface_t *image = NULL; if (fscanf (file, "P%c %d %d 255\n", &format, &width, &height) != 3) goto FAIL; switch (format) { case '7': /* XXX */ image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); break; case '6': image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height); break; case '5': image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height); break; default: goto FAIL; } if (cairo_surface_status (image)) return image; data = cairo_image_surface_get_data (image); stride = cairo_image_surface_get_stride (image); for (y = 0; y < height; y++) { unsigned char *buf = data + y*stride; switch (format) { case '7': if (! freadn (buf, 4 * width, file)) goto FAIL; break; case '6': if (! freadn (buf, 3*width, file)) goto FAIL; buf += 3*width; for (x = width; x--; ) { buf -= 3; ((uint32_t *) (data + y*stride))[x] = (buf[0] << 16) | (buf[1] << 8) | (buf[2] << 0); } break; case '5': if (! freadn (buf, width, file)) goto FAIL; break; } } cairo_surface_mark_dirty (image); return image; FAIL: cairo_surface_destroy (image); return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_READ_ERROR); }
GtkWidget *CreateImageButton( const char* image_file_path, const gchar* label, const char* font_file ) { #define DISPLAY_FONT_HEIGHT 8.5 // 貼り付けるイメージ cairo_surface_t *image = cairo_image_surface_create_from_png(image_file_path); // 文字描画用 cairo_t *cairo_p = cairo_create(image); // 画像のフォーマット cairo_format_t format = cairo_image_surface_get_format(image); // 画像の幅と高さ int32 width = cairo_image_surface_get_width(image); int32 height = cairo_image_surface_get_height(image); // 画像の一列分のバイト数 int32 stride = width * ((format == CAIRO_FORMAT_ARGB32) ? 4 : 3); // 文字表示のY座標 gdouble draw_y = 9.0; GtkWidget *image_widget; // ピクセルバッファ GdkPixbuf *pixbuf; // 返り値 GtkWidget *button; // 改行処理用のバッファ gchar* str = (label == NULL) ? NULL : MEM_STRDUP_FUNC(label); gchar* show_text = str; // 改行処理用 gchar *now, *next; // 文字列を描画 if(label != NULL && *label != '\0') { // フォントサイズセット cairo_select_font_face(cairo_p, font_file, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cairo_p, DISPLAY_FONT_HEIGHT); // 改行を処理しながら表示 now = show_text = str; next = g_utf8_next_char(show_text); while(*now != '\0' && *next != '\0') { if((uint8)*now == 0x5c && *next == 'n') { *now = '\0'; cairo_move_to(cairo_p, 0.0, draw_y); cairo_show_text(cairo_p, show_text); show_text = now = g_utf8_next_char(next); next = g_utf8_next_char(now); draw_y += DISPLAY_FONT_HEIGHT; } else if((next - now) >= 2 && (uint8)*now == 0xc2 && (uint8)(*(now+1)) == 0xa5 && (uint8)*next == 'n') { *now = '\0'; cairo_move_to(cairo_p, 0.0, draw_y); cairo_show_text(cairo_p, show_text); show_text = now = g_utf8_next_char(next); next = g_utf8_next_char(now); draw_y += DISPLAY_FONT_HEIGHT; } else { now = next; next = g_utf8_next_char(next); } } cairo_move_to(cairo_p, 0.0, draw_y); cairo_show_text(cairo_p, show_text); } // イメージからピクセルバッファを生成 pixbuf = gdk_pixbuf_new_from_data( cairo_image_surface_get_data(image), GDK_COLORSPACE_RGB, (format == CAIRO_FORMAT_ARGB32) ? TRUE : FALSE, 8, width, height, stride, NULL, NULL ); #if defined(USE_BGR_COLOR_SPACE) && USE_BGR_COLOR_SPACE != 0 { // WindowsならばBGR→RGBの変換を行う uint8* pix = cairo_image_surface_get_data(image); uint8 b; int32 channel = (format == CAIRO_FORMAT_ARGB32) ? 4 : 3; int32 i, j; for(i=0; i<height; i++) { for(j=0; j<width; j++) { b = pix[i*stride+j*channel]; pix[i*stride+j*channel] = pix[i*stride+j*channel+2]; pix[i*stride+j*channel+2] = b; } } } #endif // #if defined(DISPLAY_BGR) && DISPLAY_BGR != 0 image_widget = gtk_image_new_from_pixbuf(pixbuf); button = gtk_toggle_button_new(); // ボタンにイメージデータを載せる gtk_container_add(GTK_CONTAINER(button), image_widget); cairo_destroy(cairo_p); MEM_FREE_FUNC(str); return button; }
/* Compares two CAIRO_FORMAT_ARGB32 buffers, returning NULL if the * buffers are equal or a surface containing a diff between the two * surfaces. * * This function should be rewritten to compare all formats supported by * cairo_format_t instead of taking a mask as a parameter. * * This function is originally from cairo:test/buffer-diff.c. * Copyright © 2004 Richard D. Worth */ static cairo_surface_t * buffer_diff_core (const guchar *buf_a, int stride_a, const guchar *buf_b, int stride_b, int width, int height) { int x, y; guchar *buf_diff = NULL; int stride_diff = 0; cairo_surface_t *diff = NULL; for (y = 0; y < height; y++) { const guint32 *row_a = (const guint32 *) (buf_a + y * stride_a); const guint32 *row_b = (const guint32 *) (buf_b + y * stride_b); guint32 *row = (guint32 *) (buf_diff + y * stride_diff); for (x = 0; x < width; x++) { int channel; guint32 diff_pixel = 0; /* check if the pixels are the same */ if (row_a[x] == row_b[x]) continue; if (diff == NULL) { diff = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height); g_assert (cairo_surface_status (diff) == CAIRO_STATUS_SUCCESS); buf_diff = cairo_image_surface_get_data (diff); stride_diff = cairo_image_surface_get_stride (diff); row = (guint32 *) (buf_diff + y * stride_diff); } /* calculate a difference value for all 4 channels */ for (channel = 0; channel < 4; channel++) { int value_a = (row_a[x] >> (channel*8)) & 0xff; int value_b = (row_b[x] >> (channel*8)) & 0xff; guint diff; diff = ABS (value_a - value_b); diff *= 4; /* emphasize */ if (diff) diff += 128; /* make sure it's visible */ if (diff > 255) diff = 255; diff_pixel |= diff << (channel*8); } if ((diff_pixel & 0x00ffffff) == 0) { /* alpha only difference, convert to luminance */ guint8 alpha = diff_pixel >> 24; diff_pixel = alpha * 0x010101; } row[x] = diff_pixel; } }
unsigned char * _cairo_image_surface_flush_and_get_data (cairo_surface_t *surface) { cairo_surface_flush (surface); return cairo_image_surface_get_data (surface); }
/** * _st_create_shadow_cairo_pattern: * @shadow_spec: the definition of the shadow * @src_pattern: surface pattern for which we create the shadow * (must be a surface pattern) * * This is a utility function for creating shadows used by * st-theme-node.c; it's in this file to share the gaussian * blur implementation. The usage of this function is quite different * depending on whether shadow_spec->inset is %TRUE or not. If * shadow_spec->inset is %TRUE, the caller should pass in a @src_pattern * which is the <i>inverse</i> of what they want shadowed, and must take * care of the spread and offset from the shadow spec themselves. If * shadow_spec->inset is %FALSE then the caller should pass in what they * want shadowed directly, and this function takes care of the spread and * the offset. */ cairo_pattern_t * _st_create_shadow_cairo_pattern (StShadow *shadow_spec, cairo_pattern_t *src_pattern) { static cairo_user_data_key_t shadow_pattern_user_data; cairo_t *cr; cairo_surface_t *src_surface; cairo_surface_t *surface_in; cairo_surface_t *surface_out; cairo_pattern_t *dst_pattern; guchar *pixels_in, *pixels_out; gint width_in, height_in, rowstride_in; gint width_out, height_out, rowstride_out; cairo_matrix_t shadow_matrix; int i, j; g_return_val_if_fail (shadow_spec != NULL, NULL); g_return_val_if_fail (src_pattern != NULL, NULL); cairo_pattern_get_surface (src_pattern, &src_surface); width_in = cairo_image_surface_get_width (src_surface); height_in = cairo_image_surface_get_height (src_surface); /* We want the output to be a color agnostic alpha mask, * so we need to strip the color channels from the input */ if (cairo_image_surface_get_format (src_surface) != CAIRO_FORMAT_A8) { surface_in = cairo_image_surface_create (CAIRO_FORMAT_A8, width_in, height_in); cr = cairo_create (surface_in); cairo_set_source_surface (cr, src_surface, 0, 0); cairo_paint (cr); cairo_destroy (cr); } else { surface_in = cairo_surface_reference (src_surface); } pixels_in = cairo_image_surface_get_data (surface_in); rowstride_in = cairo_image_surface_get_stride (surface_in); pixels_out = blur_pixels (pixels_in, width_in, height_in, rowstride_in, shadow_spec->blur, &width_out, &height_out, &rowstride_out); cairo_surface_destroy (surface_in); /* Invert pixels for inset shadows */ if (shadow_spec->inset) { for (j = 0; j < height_out; j++) { guchar *p = pixels_out + rowstride_out * j; for (i = 0; i < width_out; i++, p++) *p = ~*p; } } surface_out = cairo_image_surface_create_for_data (pixels_out, CAIRO_FORMAT_A8, width_out, height_out, rowstride_out); cairo_surface_set_user_data (surface_out, &shadow_pattern_user_data, pixels_out, (cairo_destroy_func_t) g_free); dst_pattern = cairo_pattern_create_for_surface (surface_out); cairo_surface_destroy (surface_out); cairo_pattern_get_matrix (src_pattern, &shadow_matrix); if (shadow_spec->inset) { /* For inset shadows, offsets and spread radius have already been * applied to the original pattern, so all left to do is shift the * blurred image left, so that it aligns centered under the * unblurred one */ cairo_matrix_translate (&shadow_matrix, (width_out - width_in) / 2.0, (height_out - height_in) / 2.0); cairo_pattern_set_matrix (dst_pattern, &shadow_matrix); return dst_pattern; } /* Read all the code from the cairo_pattern_set_matrix call * at the end of this function to here from bottom to top, * because each new affine transformation is applied in * front of all the previous ones */ /* 6. Invert the matrix back */ cairo_matrix_invert (&shadow_matrix); /* 5. Adjust based on specified offsets */ cairo_matrix_translate (&shadow_matrix, shadow_spec->xoffset, shadow_spec->yoffset); /* 4. Recenter the newly scaled image */ cairo_matrix_translate (&shadow_matrix, - shadow_spec->spread, - shadow_spec->spread); /* 3. Scale up the blurred image to fill the spread */ cairo_matrix_scale (&shadow_matrix, (width_in + 2.0 * shadow_spec->spread) / width_in, (height_in + 2.0 * shadow_spec->spread) / height_in); /* 2. Shift the blurred image left, so that it aligns centered * under the unblurred one */ cairo_matrix_translate (&shadow_matrix, - (width_out - width_in) / 2.0, - (height_out - height_in) / 2.0); /* 1. Invert the matrix so we can work with it in pattern space */ cairo_matrix_invert (&shadow_matrix); cairo_pattern_set_matrix (dst_pattern, &shadow_matrix); return dst_pattern; }
static void gimp_view_renderer_palette_render (GimpViewRenderer *renderer, GtkWidget *widget) { GimpViewRendererPalette *renderpal = GIMP_VIEW_RENDERER_PALETTE (renderer); GimpPalette *palette; guchar *row; guchar *dest; GList *list; gdouble cell_width; gint grid_width; gint dest_stride; gint y; palette = GIMP_PALETTE (renderer->viewable); if (palette->n_colors < 1) return; grid_width = renderpal->draw_grid ? 1 : 0; if (renderpal->cell_size > 0) { if (palette->n_columns > 0) cell_width = MAX ((gdouble) renderpal->cell_size, (gdouble) (renderer->width - grid_width) / (gdouble) palette->n_columns); else cell_width = renderpal->cell_size; } else { if (palette->n_columns > 0) cell_width = ((gdouble) (renderer->width - grid_width) / (gdouble) palette->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 = palette->n_colors / renderpal->columns; if (palette->n_colors % 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 = palette->colors; 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); 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 { memcpy (dest, row, renderer->width * 4); } dest += dest_stride; } g_free (row); cairo_surface_mark_dirty (renderer->surface); renderer->needs_render = FALSE; }
static void _lib_modulelist_populate_callback(gpointer instance, gpointer user_data) { dt_lib_module_t *self = (dt_lib_module_t *)user_data; if(!self || !(self->data)) return; GtkListStore *store; GtkTreeIter iter; GtkWidget *view = GTK_WIDGET(((dt_lib_modulelist_t *)self->data)->tree); GtkCellRenderer *pix_renderer, *fav_renderer, *text_renderer; GdkRGBA color; GtkStyleContext *context = gtk_widget_get_style_context(view); gboolean color_found = gtk_style_context_lookup_color (context, "selected_bg_color", &color); if(!color_found) { color.red = 1.0; color.green = 0.0; color.blue = 0.0; color.alpha = 1.0; } store = gtk_list_store_new(NUM_COLS, GDK_TYPE_PIXBUF, G_TYPE_POINTER); gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store)); g_object_unref(store); gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), COL_MODULE, _lib_modulelist_gui_sort, NULL, NULL); gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), COL_MODULE, GTK_SORT_ASCENDING); pix_renderer = gtk_cell_renderer_pixbuf_new(); g_object_set(pix_renderer, "cell-background-rgba", &color, NULL); fav_renderer = gtk_cell_renderer_pixbuf_new(); cairo_surface_t *fav_cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, ICON_SIZE, ICON_SIZE); cairo_t *fav_cr = cairo_create(fav_cst); cairo_set_source_rgb(fav_cr, 0.7, 0.7, 0.7); dtgtk_cairo_paint_modulegroup_favorites(fav_cr, 0, 0, ICON_SIZE, ICON_SIZE, 0); guchar *data = cairo_image_surface_get_data(fav_cst); dt_draw_cairo_to_gdk_pixbuf(data, ICON_SIZE, ICON_SIZE); ((dt_lib_modulelist_t *)self->data)->fav_pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, TRUE, 8, ICON_SIZE, ICON_SIZE, cairo_image_surface_get_stride(fav_cst), NULL, NULL); g_object_set(fav_renderer, "cell-background-rgba", &color, NULL); g_object_set(fav_renderer, "width", gdk_pixbuf_get_width(((dt_lib_modulelist_t *)self->data)->fav_pixbuf), NULL); text_renderer = gtk_cell_renderer_text_new(); g_object_set(text_renderer, "cell-background-rgba", &color, NULL); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(view), FALSE); GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); gtk_tree_selection_set_mode(selection, GTK_SELECTION_NONE); GtkTreeViewColumn *col; col = gtk_tree_view_get_column(GTK_TREE_VIEW(view), 0); if(col) gtk_tree_view_remove_column(GTK_TREE_VIEW(view), col); gtk_tree_view_insert_column_with_data_func(GTK_TREE_VIEW(view), 0, "favorite", fav_renderer, favorite_renderer_function, NULL, NULL); col = gtk_tree_view_get_column(GTK_TREE_VIEW(view), 1); if(col) gtk_tree_view_remove_column(GTK_TREE_VIEW(view), col); gtk_tree_view_insert_column_with_data_func(GTK_TREE_VIEW(view), 1, "image", pix_renderer, image_renderer_function, NULL, NULL); col = gtk_tree_view_get_column(GTK_TREE_VIEW(view), 2); if(col) gtk_tree_view_remove_column(GTK_TREE_VIEW(view), col); gtk_tree_view_insert_column_with_data_func(GTK_TREE_VIEW(view), 2, "name", text_renderer, text_renderer_function, NULL, NULL); /* go thru list of iop modules and add them to the list */ GList *modules = g_list_last(darktable.develop->iop); char datadir[PATH_MAX] = { 0 }; dt_loc_get_datadir(datadir, sizeof(datadir)); while(modules) { dt_iop_module_t *module = (dt_iop_module_t *)(modules->data); if(!dt_iop_is_hidden(module) && !(module->flags() & IOP_FLAGS_DEPRECATED) && module->multi_priority == 0) { GdkPixbuf *pixbuf; char filename[PATH_MAX] = { 0 }; snprintf(filename, sizeof(filename), "%s/pixmaps/plugins/darkroom/%s.svg", datadir, module->op); pixbuf = load_image(filename); if(pixbuf) goto end; snprintf(filename, sizeof(filename), "%s/pixmaps/plugins/darkroom/%s.png", datadir, module->op); pixbuf = load_image(filename); if(pixbuf) goto end; snprintf(filename, sizeof(filename), "%s/pixmaps/plugins/darkroom/template.svg", datadir); pixbuf = load_image(filename); if(pixbuf) goto end; snprintf(filename, sizeof(filename), "%s/pixmaps/plugins/darkroom/template.png", datadir); pixbuf = load_image(filename); if(pixbuf) goto end; // wow, we could neither load the SVG nor the PNG files. something is f****d up. pixbuf = gdk_pixbuf_new_from_data(fallback_pixel, GDK_COLORSPACE_RGB, TRUE, 8, 1, 1, 4, NULL, NULL); end: gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, COL_IMAGE, pixbuf, COL_MODULE, module, -1); g_object_unref(pixbuf); } modules = g_list_previous(modules); } }
uint8_t* SurfaceImage::getData() { return cairo_image_surface_get_data( mCairoSurface ); }
double lime_cairo_image_surface_get_data (value handle) { return (intptr_t)cairo_image_surface_get_data ((cairo_surface_t*)val_data (handle)); }
static uint8_t const* read(data_type_t const& data_in) { return cairo_image_surface_get_data(data_in); }