/** * cairo_image_surface_create_for_data: * @data: a pointer to a buffer supplied by the application in which * to write contents. This pointer must be suitably aligned for any * kind of variable, (for example, a pointer returned by malloc). * @format: the format of pixels in the buffer * @width: the width of the image to be stored in the buffer * @height: the height of the image to be stored in the buffer * @stride: the number of bytes between the start of rows in the * buffer as allocated. This value should always be computed by * cairo_format_stride_for_width() before allocating the data * buffer. * * Creates an image surface for the provided pixel data. The output * buffer must be kept around until the #cairo_surface_t is destroyed * or cairo_surface_finish() is called on the surface. The initial * contents of @data will be used as the initial image contents; you * must explicitly clear the buffer, using, for example, * cairo_rectangle() and cairo_fill() if you want it cleared. * * Note that the stride may be larger than * width*bytes_per_pixel to provide proper alignment for each pixel * and row. This alignment is required to allow high-performance rendering * within cairo. The correct way to obtain a legal stride value is to * call cairo_format_stride_for_width() with the desired format and * maximum image width value, and the use the resulting stride value * to allocate the data and to create the image surface. See * cairo_format_stride_for_width() for example code. * * Return value: a pointer to the newly created surface. The caller * owns the surface and should call cairo_surface_destroy() when done * with it. * * This function always returns a valid pointer, but it will return a * pointer to a "nil" surface in the case of an error such as out of * memory or an invalid stride value. In case of invalid stride value * the error status of the returned surface will be * %CAIRO_STATUS_INVALID_STRIDE. You can use * cairo_surface_status() to check for this. * * See cairo_surface_set_user_data() for a means of attaching a * destroy-notification fallback to the surface if necessary. **/ cairo_surface_t * cairo_image_surface_create_for_data (unsigned char *data, cairo_format_t format, int width, int height, int stride) { pixman_format_code_t pixman_format; int minstride; if (! CAIRO_FORMAT_VALID (format)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); if ((stride & (CAIRO_STRIDE_ALIGNMENT-1)) != 0) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); minstride = cairo_format_stride_for_width (format, width); if (stride < 0) { if (stride > -minstride) { return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); } } else { if (stride < minstride) { return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); } } pixman_format = _cairo_format_to_pixman_format_code (format); return _cairo_image_surface_create_with_pixman_format (data, pixman_format, width, height, stride); }
static cairo_surface_t * radeon_surface_create_internal (cairo_drm_device_t *device, cairo_format_t format, int width, int height) { radeon_surface_t *surface; cairo_status_t status; surface = malloc (sizeof (radeon_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); radeon_surface_init (surface, device, format, width, height); if (width && height) { surface->base.stride = cairo_format_stride_for_width (surface->base.format, width); surface->base.bo = radeon_bo_create (to_radeon_device (&device->base), surface->base.stride * height, RADEON_GEM_DOMAIN_GTT); if (unlikely (surface->base.bo == NULL)) { status = _cairo_drm_surface_finish (&surface->base); free (surface); return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } } return &surface->base.base; }
cairo_surface_t * cairo_gl_surface_create_for_window (cairo_device_t *device, Window win, int width, int height) { cairo_glx_surface_t *surface; if (unlikely (device->status)) return _cairo_surface_create_in_error (device->status); if (device->backend->type != CAIRO_DEVICE_TYPE_GL) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); if (width <= 0 || height <= 0) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); surface = calloc (1, sizeof (cairo_glx_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_gl_surface_init (device, &surface->base, CAIRO_CONTENT_COLOR_ALPHA, width, height); surface->win = win; return &surface->base.base; }
static cairo_surface_t * _cairo_gl_surface_create_similar (void *abstract_surface, cairo_content_t content, int width, int height) { cairo_surface_t *surface = abstract_surface; cairo_gl_context_t *ctx; cairo_status_t status; if (! _cairo_gl_surface_size_valid (abstract_surface, width, height)) return _cairo_image_surface_create_with_content (content, width, height); status = _cairo_gl_context_acquire (surface->device, &ctx); if (unlikely (status)) return _cairo_surface_create_in_error (status); surface = _cairo_gl_surface_create_scratch (ctx, content, width, height); status = _cairo_gl_context_release (ctx, status); if (unlikely (status)) { cairo_surface_destroy (surface); return _cairo_surface_create_in_error (status); } return surface; }
/** * cairo_xcb_surface_create_for_bitmap: * @connection: an XCB connection * @screen: the XCB screen associated with @bitmap * @bitmap: an XCB drawable (a Pixmap with depth 1) * @width: the current width of @bitmap * @height: the current height of @bitmap * * Creates an XCB surface that draws to the given bitmap. * This will be drawn to as a %CAIRO_FORMAT_A1 object. * * Return value: a pointer to the newly created surface. The caller * owns the surface and should call cairo_surface_destroy() when done * with it. * * This function always returns a valid pointer, but it will return a * pointer to a "nil" surface if an error such as out of memory * occurs. You can use cairo_surface_status() to check for this. **/ cairo_surface_t * cairo_xcb_surface_create_for_bitmap (xcb_connection_t *connection, xcb_screen_t *screen, xcb_pixmap_t bitmap, int width, int height) { cairo_xcb_screen_t *cairo_xcb_screen; if (xcb_connection_has_error (connection)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR)); if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); if (unlikely (width <= 0 || height <= 0)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); cairo_xcb_screen = _cairo_xcb_screen_get (connection, screen); if (unlikely (cairo_xcb_screen == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); return _cairo_xcb_surface_create_internal (cairo_xcb_screen, bitmap, FALSE, PIXMAN_a1, cairo_xcb_screen->connection->standard_formats[CAIRO_FORMAT_A1], width, height); }
static cairo_surface_t * radeon_surface_map_to_image (radeon_surface_t *surface) { if (surface->base.fallback == NULL) { cairo_surface_t *image; cairo_status_t status; void *ptr; if (surface->base.base.backend->flush != NULL) { status = surface->base.base.backend->flush (surface); if (unlikely (status)) return _cairo_surface_create_in_error (status); } ptr = radeon_bo_map (to_radeon_device (surface->base.base.device), to_radeon_bo (surface->base.bo)); if (unlikely (ptr == NULL)) return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); image = cairo_image_surface_create_for_data (ptr, surface->base.format, surface->base.width, surface->base.height, surface->base.stride); if (unlikely (image->status)) { radeon_bo_unmap (to_radeon_bo (surface->base.bo)); return image; } surface->base.fallback = image; } return surface->base.fallback; }
/** * cairo_gl_surface_create_for_texture: * @content: type of content in the surface * @tex: name of texture to use for storage of surface pixels * @width: width of the surface, in pixels * @height: height of the surface, in pixels * * Creates a GL surface for the specified texture with the specified * content and dimensions. The texture must be kept around until the * #cairo_surface_t is destroyed or cairo_surface_finish() is called * on the surface. The initial contents of @tex will be used as the * initial image contents; you must explicitly clear the buffer, * using, for example, cairo_rectangle() and cairo_fill() if you want * it cleared. The format of @tex should be compatible with @content, * in the sense that it must have the color components required by * @content. * * Return value: a pointer to the newly created surface. The caller * owns the surface and should call cairo_surface_destroy() when done * with it. * * This function always returns a valid pointer, but it will return a * pointer to a "nil" surface if an error such as out of memory * occurs. You can use cairo_surface_status() to check for this. **/ cairo_surface_t * cairo_gl_surface_create_for_texture (cairo_device_t *abstract_device, cairo_content_t content, unsigned int tex, int width, int height) { cairo_gl_context_t *ctx; cairo_gl_surface_t *surface; cairo_status_t status; if (! CAIRO_CONTENT_VALID (content)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); if (abstract_device == NULL) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER)); if (abstract_device->status) return _cairo_surface_create_in_error (abstract_device->status); if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_GL) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH)); status = _cairo_gl_context_acquire (abstract_device, &ctx); if (unlikely (status)) return _cairo_surface_create_in_error (status); surface = (cairo_gl_surface_t *) _cairo_gl_surface_create_scratch_for_texture (ctx, content, tex, width, height); status = _cairo_gl_context_release (ctx, status); return &surface->base; }
cairo_surface_t * _cairo_gl_pattern_to_source (cairo_surface_t *dst, const cairo_pattern_t *pattern, cairo_bool_t is_mask, const cairo_rectangle_int_t *extents, const cairo_rectangle_int_t *sample, int *src_x, int *src_y) { cairo_gl_source_t *source; cairo_int_status_t status; TRACE ((stderr, "%s\n", __FUNCTION__)); if (pattern == NULL) return _cairo_gl_white_source (); source = malloc (sizeof (*source)); if (unlikely (source == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&source->base, &cairo_gl_source_backend, NULL, /* device */ CAIRO_CONTENT_COLOR_ALPHA); *src_x = *src_y = 0; status = _cairo_gl_operand_init (&source->operand, pattern, (cairo_gl_surface_t *)dst, sample, extents, FALSE); if (unlikely (status)) { cairo_surface_destroy (&source->base); return _cairo_surface_create_in_error (status); } return &source->base; }
cairo_surface_t * _cairo_image_surface_create_with_pixman_format (unsigned char *data, pixman_format_code_t pixman_format, int width, int height, int stride) { cairo_surface_t *surface; pixman_image_t *pixman_image; if (! _cairo_image_surface_is_size_valid (width, height)) { return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); } pixman_image = pixman_image_create_bits (pixman_format, width, height, (uint32_t *) data, stride); if (unlikely (pixman_image == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); surface = _cairo_image_surface_create_for_pixman_image (pixman_image, pixman_format); if (unlikely (surface->status)) { pixman_image_unref (pixman_image); return surface; } /* we can not make any assumptions about the initial state of user data */ surface->is_clear = data == NULL; return surface; }
cairo_surface_t * cairo_tee_surface_index (cairo_surface_t *abstract_surface, int index) { cairo_tee_surface_t *surface; if (unlikely (abstract_surface->status)) return _cairo_surface_create_in_error (abstract_surface->status); if (abstract_surface->backend != &cairo_tee_surface_backend) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); surface = (cairo_tee_surface_t *) abstract_surface; if (index == 0) { return surface->master.target; } else { cairo_surface_wrapper_t *slave; index--; if (index >= _cairo_array_num_elements (&surface->slaves)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_INDEX)); slave = _cairo_array_index (&surface->slaves, index); return slave->target; } }
/** * cairo_surface_create_for_rectangle: * @target: an existing surface for which the sub-surface will point to * @x: the x-origin of the sub-surface from the top-left of the target surface (in device-space units) * @y: the y-origin of the sub-surface from the top-left of the target surface (in device-space units) * @width: width of the sub-surface (in device-space units) * @height: height of the sub-surface (in device-space units) * * Create a new surface that is a rectangle within the target surface. * All operations drawn to this surface are then clipped and translated * onto the target surface. Nothing drawn via this sub-surface outside of * its bounds is drawn onto the target surface, making this a useful method * for passing constrained child surfaces to library routines that draw * directly onto the parent surface, i.e. with no further backend allocations, * double buffering or copies. * * <note><para>The semantics of subsurfaces have not been finalized yet * unless the rectangle is in full device units, is contained within * the extents of the target surface, and the target or subsurface's * device transforms are not changed.</para></note> * * Return value: a pointer to the newly allocated surface. The caller * owns the surface and should call cairo_surface_destroy() when done * with it. * * This function always returns a valid pointer, but it will return a * pointer to a "nil" surface if @other is already in an error state * or any other error occurs. * * Since: 1.10 **/ cairo_surface_t * cairo_surface_create_for_rectangle (cairo_surface_t *target, double x, double y, double width, double height) { cairo_surface_subsurface_t *surface; if (unlikely (width < 0 || height < 0)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); if (unlikely (target->status)) return _cairo_surface_create_in_error (target->status); if (unlikely (target->finished)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); surface = malloc (sizeof (cairo_surface_subsurface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); x *= target->device_transform.xx; y *= target->device_transform.yy; width *= target->device_transform.xx; height *= target->device_transform.yy; x += target->device_transform.x0; y += target->device_transform.y0; _cairo_surface_init (&surface->base, &_cairo_surface_subsurface_backend, NULL, /* device */ target->content); /* XXX forced integer alignment */ surface->extents.x = ceil (x); surface->extents.y = ceil (y); surface->extents.width = floor (x + width) - surface->extents.x; surface->extents.height = floor (y + height) - surface->extents.y; if ((surface->extents.width | surface->extents.height) < 0) surface->extents.width = surface->extents.height = 0; if (target->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) { /* Maintain subsurfaces as 1-depth */ cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) target; surface->extents.x += sub->extents.x; surface->extents.y += sub->extents.y; target = sub->target; } surface->target = cairo_surface_reference (target); surface->base.type = surface->target->type; surface->snapshot = NULL; cairo_surface_set_device_scale (&surface->base, target->device_transform.xx, target->device_transform.yy); return &surface->base; }
static cairo_surface_t * intel_surface_create (cairo_drm_device_t *device, cairo_format_t format, int width, int height) { intel_surface_t *surface; cairo_status_t status; surface = malloc (sizeof (intel_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); intel_surface_init (surface, &intel_surface_backend, device, format, width, height); if (width && height) { /* Vol I, p134: size restrictions for textures */ width = (width + 3) & -4; height = (height + 1) & -2; surface->drm.stride = cairo_format_stride_for_width (surface->drm.format, width); surface->drm.bo = &intel_bo_create (to_intel_device (&device->base), surface->drm.stride * height, surface->drm.stride * height, TRUE, I915_TILING_NONE, surface->drm.stride)->base; if (surface->drm.bo == NULL) { status = _cairo_drm_surface_finish (&surface->drm); free (surface); return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } } return &surface->drm.base; }
cairo_surface_t * intel_surface_map_to_image (void *abstract_surface) { intel_surface_t *surface = abstract_surface; if (surface->drm.fallback == NULL) { cairo_surface_t *image; cairo_status_t status; void *ptr; if (surface->drm.base.backend->flush != NULL) { status = surface->drm.base.backend->flush (surface); if (unlikely (status)) return _cairo_surface_create_in_error (status); } ptr = intel_bo_map (to_intel_device (surface->drm.base.device), to_intel_bo (surface->drm.bo)); if (unlikely (ptr == NULL)) return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); image = cairo_image_surface_create_for_data (ptr, surface->drm.format, surface->drm.width, surface->drm.height, surface->drm.stride); if (unlikely (image->status)) return image; surface->drm.fallback = image; } return surface->drm.fallback; }
cairo_surface_t * cairo_tee_surface_create (cairo_surface_t *master) { cairo_tee_surface_t *surface; if (unlikely (master->status)) return _cairo_surface_create_in_error (master->status); surface = malloc (sizeof (cairo_tee_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &cairo_tee_surface_backend, master->content); _cairo_surface_wrapper_init (&surface->master, master); /* we trust that these are already set and remain constant */ surface->base.device_transform = master->device_transform; surface->base.device_transform_inverse = master->device_transform_inverse; _cairo_array_init (&surface->slaves, sizeof (cairo_surface_wrapper_t)); return &surface->base; }
cairo_surface_t * _cairo_surface_create_for_rectangle_int (cairo_surface_t *target, const cairo_rectangle_int_t *extents) { cairo_surface_subsurface_t *surface; if (unlikely (target->status)) return _cairo_surface_create_in_error (target->status); if (unlikely (target->finished)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); assert (target->backend->type != CAIRO_SURFACE_TYPE_SUBSURFACE); surface = malloc (sizeof (cairo_surface_subsurface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); assert (_cairo_matrix_is_translation (&target->device_transform)); _cairo_surface_init (&surface->base, &_cairo_surface_subsurface_backend, NULL, /* device */ target->content); surface->extents = *extents; surface->extents.x += target->device_transform.x0; surface->extents.y += target->device_transform.y0; surface->target = cairo_surface_reference (target); surface->base.type = surface->target->type; surface->snapshot = NULL; return &surface->base; }
/** * cairo_win32_surface_create_with_ddb: * @hdc: a DC compatible with the surface to create * @format: format of pixels in the surface to create * @width: width of the surface, in pixels * @height: height of the surface, in pixels * * Creates a device-dependent-bitmap surface not associated with * any particular existing surface or device context. The created * bitmap will be uninitialized. * * Return value: the newly created surface * * Since: 1.4 **/ cairo_surface_t * cairo_win32_surface_create_with_ddb (HDC hdc, cairo_format_t format, int width, int height) { cairo_win32_display_surface_t *new_surf; HBITMAP ddb; HDC screen_dc, ddb_dc; HBITMAP saved_dc_bitmap; if (format != CAIRO_FORMAT_RGB24) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); /* XXX handle these eventually format != CAIRO_FORMAT_A8 || format != CAIRO_FORMAT_A1) */ if (!hdc) { screen_dc = GetDC (NULL); hdc = screen_dc; } else { screen_dc = NULL; } ddb_dc = CreateCompatibleDC (hdc); if (ddb_dc == NULL) { new_surf = (cairo_win32_display_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); goto FINISH; } ddb = CreateCompatibleBitmap (hdc, width, height); if (ddb == NULL) { DeleteDC (ddb_dc); /* Note that if an app actually does hit this out of memory * condition, it's going to have lots of other issues, as * video memory is probably exhausted. However, it can often * continue using DIBs instead of DDBs. */ new_surf = (cairo_win32_display_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); goto FINISH; } saved_dc_bitmap = SelectObject (ddb_dc, ddb); new_surf = (cairo_win32_display_surface_t*) cairo_win32_surface_create (ddb_dc); new_surf->bitmap = ddb; new_surf->saved_dc_bitmap = saved_dc_bitmap; new_surf->is_dib = FALSE; FINISH: if (screen_dc) ReleaseDC (NULL, screen_dc); return &new_surf->win32.base; }
/** * cairo_xcb_surface_create_with_xrender_format: * @connection: an XCB connection * @drawable: an XCB drawable * @screen: the XCB screen associated with @drawable * @format: the picture format to use for drawing to @drawable. The * depth of @format mush match the depth of the drawable. * @width: the current width of @drawable * @height: the current height of @drawable * * Creates an XCB surface that draws to the given drawable. * The way that colors are represented in the drawable is specified * by the provided picture format. * * Note: If @drawable is a Window, then the function * cairo_xcb_surface_set_size() must be called whenever the size of the * window changes. * * When @drawable is a Window containing child windows then drawing to * the created surface will be clipped by those child windows. When * the created surface is used as a source, the contents of the * children will be included. * * Return value: a pointer to the newly created surface. The caller * owns the surface and should call cairo_surface_destroy() when done * with it. * * This function always returns a valid pointer, but it will return a * pointer to a "nil" surface if an error such as out of memory * occurs. You can use cairo_surface_status() to check for this. **/ cairo_surface_t * cairo_xcb_surface_create_with_xrender_format (xcb_connection_t *connection, xcb_screen_t *screen, xcb_drawable_t drawable, xcb_render_pictforminfo_t *format, int width, int height) { cairo_xcb_screen_t *cairo_xcb_screen; cairo_format_masks_t image_masks; pixman_format_code_t pixman_format; if (xcb_connection_has_error (connection)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR)); if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); if (unlikely (width <= 0 || height <= 0)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); image_masks.alpha_mask = (unsigned long) format->direct.alpha_mask << format->direct.alpha_shift; image_masks.red_mask = (unsigned long) format->direct.red_mask << format->direct.red_shift; image_masks.green_mask = (unsigned long) format->direct.green_mask << format->direct.green_shift; image_masks.blue_mask = (unsigned long) format->direct.blue_mask << format->direct.blue_shift; #if 0 image_masks.bpp = format->depth; #else if (format->depth > 16) image_masks.bpp = 32; else if (format->depth > 8) image_masks.bpp = 16; else if (format->depth > 1) image_masks.bpp = 8; else image_masks.bpp = 1; #endif if (! _pixman_format_from_masks (&image_masks, &pixman_format)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); cairo_xcb_screen = _cairo_xcb_screen_get (connection, screen); if (unlikely (cairo_xcb_screen == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); return _cairo_xcb_surface_create_internal (cairo_xcb_screen, drawable, FALSE, pixman_format, format->id, width, height); }
/** * _cairo_surface_snapshot: * @surface: a #cairo_surface_t * * Make an immutable reference to @surface. It is an error to call a * surface-modifying function on the result of this function. The * resulting 'snapshot' is a lazily copied-on-write surface i.e. it * remains a reference to the original surface until that surface is * written to again, at which time a copy is made of the original surface * and the snapshot then points to that instead. Multiple snapshots of the * same unmodified surface point to the same copy. * * The caller owns the return value and should call * cairo_surface_destroy() when finished with it. This function will not * return %NULL, but will return a nil surface instead. * * Return value: The snapshot surface. Note that the return surface * may not necessarily be of the same type as @surface. **/ cairo_surface_t * _cairo_surface_snapshot (cairo_surface_t *surface) { cairo_surface_snapshot_t *snapshot; cairo_status_t status; TRACE ((stderr, "%s: target=%d\n", __FUNCTION__, surface->unique_id)); if (unlikely (surface->status)) return _cairo_surface_create_in_error (surface->status); if (unlikely (surface->finished)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); if (surface->snapshot_of != NULL) return cairo_surface_reference (surface); if (_cairo_surface_is_snapshot (surface)) return cairo_surface_reference (surface); snapshot = (cairo_surface_snapshot_t *) _cairo_surface_has_snapshot (surface, &_cairo_surface_snapshot_backend); if (snapshot != NULL) return cairo_surface_reference (&snapshot->base); snapshot = malloc (sizeof (cairo_surface_snapshot_t)); if (unlikely (snapshot == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); _cairo_surface_init (&snapshot->base, &_cairo_surface_snapshot_backend, NULL, /* device */ surface->content); snapshot->base.type = surface->type; CAIRO_MUTEX_INIT (snapshot->mutex); snapshot->target = surface; snapshot->clone = NULL; status = _cairo_surface_copy_mime_data (&snapshot->base, surface); if (unlikely (status)) { cairo_surface_destroy (&snapshot->base); return _cairo_surface_create_in_error (status); } snapshot->base.device_transform = surface->device_transform; snapshot->base.device_transform_inverse = surface->device_transform_inverse; _cairo_surface_attach_snapshot (surface, &snapshot->base, _cairo_surface_snapshot_copy_on_write); return &snapshot->base; }
cairo_surface_t * cairo_xcb_surface_create (xcb_connection_t *xcb_connection, xcb_drawable_t drawable, xcb_visualtype_t *visual, int width, int height) { cairo_xcb_screen_t *screen; xcb_screen_t *xcb_screen; cairo_format_masks_t image_masks; pixman_format_code_t pixman_format; xcb_render_pictformat_t xrender_format; int depth; if (xcb_connection_has_error (xcb_connection)) return _cairo_surface_create_in_error (CAIRO_STATUS_WRITE_ERROR); if (unlikely (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)) return _cairo_surface_create_in_error (CAIRO_STATUS_INVALID_SIZE); xcb_screen = _cairo_xcb_screen_from_visual (xcb_connection, visual, &depth); if (unlikely (xcb_screen == NULL)) return _cairo_surface_create_in_error (CAIRO_STATUS_INVALID_VISUAL); image_masks.alpha_mask = 0; image_masks.red_mask = visual->red_mask; image_masks.green_mask = visual->green_mask; image_masks.blue_mask = visual->blue_mask; if (depth > 16) image_masks.bpp = 32; else if (depth > 8) image_masks.bpp = 16; else if (depth > 1) image_masks.bpp = 8; else image_masks.bpp = 1; if (! _pixman_format_from_masks (&image_masks, &pixman_format)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); screen = _cairo_xcb_screen_get (xcb_connection, xcb_screen); if (unlikely (screen == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); xrender_format = _cairo_xcb_connection_get_xrender_format_for_visual (screen->connection, visual->visual_id); return _cairo_xcb_surface_create_internal (screen, drawable, FALSE, pixman_format, xrender_format, width, height); }
cairo_surface_t * _cairo_analysis_surface_create (cairo_surface_t *target, int width, int height) { cairo_analysis_surface_t *surface; cairo_status_t status; status = target->status; if (unlikely (status)) return _cairo_surface_create_in_error (status); surface = malloc (sizeof (cairo_analysis_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); /* I believe the content type here is truly arbitrary. I'm quite * sure nothing will ever use this value. */ _cairo_surface_init (&surface->base, &cairo_analysis_surface_backend, CAIRO_CONTENT_COLOR_ALPHA); surface->width = width; surface->height = height; cairo_matrix_init_identity (&surface->ctm); surface->has_ctm = FALSE; surface->target = cairo_surface_reference (target); surface->first_op = TRUE; surface->has_supported = FALSE; surface->has_unsupported = FALSE; surface->page_bbox.p1.x = 0; surface->page_bbox.p1.y = 0; surface->page_bbox.p2.x = 0; surface->page_bbox.p2.y = 0; _cairo_region_init (&surface->supported_region); _cairo_region_init (&surface->fallback_region); if (width == -1 && height == -1) { surface->current_clip.x = CAIRO_RECT_INT_MIN; surface->current_clip.y = CAIRO_RECT_INT_MIN; surface->current_clip.width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN; surface->current_clip.height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN; } else { surface->current_clip.x = 0; surface->current_clip.y = 0; surface->current_clip.width = width; surface->current_clip.height = height; } return &surface->base; }
cairo_surface_t * cairo_xml_surface_create (cairo_device_t *device, cairo_content_t content, double width, double height) { if (unlikely (device->backend->type != CAIRO_DEVICE_TYPE_XML)) return _cairo_surface_create_in_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); if (unlikely (device->status)) return _cairo_surface_create_in_error (device->status); return _cairo_xml_surface_create_internal (device, content, width, height); }
/** * cairo_symbian_surface_create: * @window: an RWindow * * Creates a Symbian surface that draws to the given window. * * Note: * The function cairo_symbian_surface_set_size() must be called whenever the size of the * window changes. * * Return value: the newly created surface **/ cairo_surface_t * cairo_symbian_surface_create (symbian_window_t window) { if (window == NULL) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER)); XCairoSymbianSurface *surface = NULL; surface = XCairoSymbianSurface::Create(window); if (surface == NULL) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); return (cairo_surface_t *)surface; }
static cairo_gl_surface_t * tristrip_to_surface (void *_dst, const cairo_rectangle_int_t *extents, cairo_antialias_t antialias, cairo_tristrip_t *strip) { pixman_format_code_t pixman_format; pixman_image_t *pixman_image; cairo_surface_t *image, *mask; cairo_status_t status; pixman_format = antialias != CAIRO_ANTIALIAS_NONE ? PIXMAN_a8 : PIXMAN_a1, pixman_image = pixman_image_create_bits (pixman_format, extents->width, extents->height, NULL, 0); if (unlikely (pixman_image == NULL)) return (cairo_gl_surface_t *)_cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _pixman_image_add_tristrip (pixman_image, extents->x, extents->y, strip); image = _cairo_image_surface_create_for_pixman_image (pixman_image, pixman_format); if (unlikely (image->status)) { pixman_image_unref (pixman_image); return (cairo_gl_surface_t *)image; } mask = _cairo_surface_create_scratch (_dst, CAIRO_CONTENT_COLOR_ALPHA, extents->width, extents->height, NULL); if (unlikely (mask->status)) { cairo_surface_destroy (image); return (cairo_gl_surface_t *)mask; } status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *)mask, (cairo_image_surface_t *)image, 0, 0, extents->width, extents->height, 0, 0, TRUE); cairo_surface_destroy (image); if (unlikely (status)) { cairo_surface_destroy (mask); return (cairo_gl_surface_t*)_cairo_surface_create_in_error (status); } return (cairo_gl_surface_t*)mask; }
cairo_surface_t * cairo_qt_surface_create_with_qpixmap (cairo_content_t content, int width, int height) { cairo_qt_surface_t *qs; if ((content & CAIRO_CONTENT_COLOR) == 0) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); qs = (cairo_qt_surface_t *) malloc (sizeof(cairo_qt_surface_t)); if (qs == NULL) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); memset (qs, 0, sizeof(cairo_qt_surface_t)); QPixmap *pixmap = new QPixmap (width, height); if (pixmap == NULL) { free (qs); return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } // By default, a QPixmap is opaque; however, if it's filled // with a color with a transparency component, it is converted // to a format that preserves transparency. if (content == CAIRO_CONTENT_COLOR_ALPHA) pixmap->fill(Qt::transparent); _cairo_surface_init (&qs->base, &cairo_qt_surface_backend, NULL, /* device */ content); _cairo_surface_clipper_init (&qs->clipper, _cairo_qt_surface_clipper_intersect_clip_path); qs->pixmap = pixmap; if (!pixmap->isNull()) { qs->p = new QPainter(pixmap); qs->supports_porter_duff = qs->p->paintEngine()->hasFeature(QPaintEngine::PorterDuff); } qs->window = QRect(0, 0, width, height); D(fprintf(stderr, "qpainter_surface_create: qpixmap: [%d %d %d %d] pd:%d\n", qs->window.x(), qs->window.y(), qs->window.width(), qs->window.height(), qs->supports_porter_duff)); return &qs->base; }
cairo_surface_t * _cairo_surface_fallback_snapshot (cairo_surface_t *surface) { cairo_surface_t *snapshot; cairo_status_t status; cairo_pattern_union_t pattern; cairo_image_surface_t *image; void *image_extra; status = _cairo_surface_acquire_source_image (surface, &image, &image_extra); if (status) return _cairo_surface_create_in_error (status); snapshot = cairo_image_surface_create (image->format, image->width, image->height); if (cairo_surface_status (snapshot)) { _cairo_surface_release_source_image (surface, image, image_extra); return snapshot; } _cairo_pattern_init_for_surface (&pattern.surface, &image->base); status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE, &pattern.base, NULL, snapshot, 0, 0, 0, 0, 0, 0, image->width, image->height); _cairo_pattern_fini (&pattern.base); _cairo_surface_release_source_image (surface, image, image_extra); if (status) { cairo_surface_destroy (snapshot); return _cairo_surface_create_in_error (status); } snapshot->device_transform = surface->device_transform; snapshot->device_transform_inverse = surface->device_transform_inverse; snapshot->is_snapshot = TRUE; return snapshot; }
cairo_surface_t * _cairo_surface_fallback_snapshot (cairo_surface_t *surface) { cairo_surface_t *snapshot; cairo_status_t status; cairo_format_t format; cairo_surface_pattern_t pattern; cairo_image_surface_t *image; void *image_extra; status = _cairo_surface_acquire_source_image (surface, &image, &image_extra); if (unlikely (status)) return _cairo_surface_create_in_error (status); format = image->format; if (format == CAIRO_FORMAT_INVALID) { /* Non-standard images formats can be generated when retrieving * images from unusual xservers, for example. */ format = _cairo_format_from_content (image->base.content); } snapshot = cairo_image_surface_create (format, image->width, image->height); if (cairo_surface_status (snapshot)) { _cairo_surface_release_source_image (surface, image, image_extra); return snapshot; } _cairo_pattern_init_for_surface (&pattern, &image->base); status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE, &pattern.base, NULL, snapshot, 0, 0, 0, 0, 0, 0, image->width, image->height); _cairo_pattern_fini (&pattern.base); _cairo_surface_release_source_image (surface, image, image_extra); if (unlikely (status)) { cairo_surface_destroy (snapshot); return _cairo_surface_create_in_error (status); } return snapshot; }
static cairo_surface_t * _cairo_xcb_surface_create_shm_image (cairo_xcb_connection_t *connection, pixman_format_code_t pixman_format, int width, int height, cairo_bool_t might_reuse, cairo_xcb_shm_info_t **shm_info_out) { cairo_surface_t *image; cairo_xcb_shm_info_t *shm_info; cairo_int_status_t status; size_t stride; *shm_info_out = NULL; stride = CAIRO_STRIDE_FOR_WIDTH_BPP (width, PIXMAN_FORMAT_BPP (pixman_format)); status = _cairo_xcb_connection_allocate_shm_info (connection, stride * height, might_reuse, &shm_info); if (unlikely (status)) { if (status == CAIRO_INT_STATUS_UNSUPPORTED) return NULL; return _cairo_surface_create_in_error (status); } image = _cairo_image_surface_create_with_pixman_format (shm_info->mem, pixman_format, width, height, stride); if (unlikely (image->status)) { _cairo_xcb_shm_info_destroy (shm_info); return image; } status = _cairo_user_data_array_set_data (&image->user_data, (const cairo_user_data_key_t *) connection, shm_info, (cairo_destroy_func_t) _cairo_xcb_shm_info_destroy); if (unlikely (status)) { cairo_surface_destroy (image); _cairo_xcb_shm_info_destroy (shm_info); return _cairo_surface_create_in_error (status); } *shm_info_out = shm_info; return image; }
/** * cairo_recording_surface_create: * @content: the content of the recording surface * @extents: the extents to record in pixels, can be %NULL to record * unbounded operations. * * Creates a recording-surface which can be used to record all drawing operations * at the highest level (that is, the level of paint, mask, stroke, fill * and show_text_glyphs). The recording surface can then be "replayed" against * any target surface by using it as a source to drawing operations. * * The recording phase of the recording surface is careful to snapshot all * necessary objects (paths, patterns, etc.), in order to achieve * accurate replay. * * Return value: a pointer to the newly created surface. The caller * owns the surface and should call cairo_surface_destroy() when done * with it. * * Since: 1.10 **/ cairo_surface_t * cairo_recording_surface_create (cairo_content_t content, const cairo_rectangle_t *extents) { cairo_recording_surface_t *recording_surface; cairo_status_t status; recording_surface = malloc (sizeof (cairo_recording_surface_t)); if (unlikely (recording_surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&recording_surface->base, &cairo_recording_surface_backend, NULL, /* device */ content); recording_surface->content = content; recording_surface->unbounded = TRUE; _cairo_clip_init (&recording_surface->clip); /* unbounded -> 'infinite' extents */ if (extents != NULL) { recording_surface->extents_pixels = *extents; /* XXX check for overflow */ recording_surface->extents.x = floor (extents->x); recording_surface->extents.y = floor (extents->y); recording_surface->extents.width = ceil (extents->x + extents->width) - recording_surface->extents.x; recording_surface->extents.height = ceil (extents->y + extents->height) - recording_surface->extents.y; status = _cairo_clip_rectangle (&recording_surface->clip, &recording_surface->extents); if (unlikely (status)) { free (recording_surface); return _cairo_surface_create_in_error (status); } recording_surface->unbounded = FALSE; } _cairo_array_init (&recording_surface->commands, sizeof (cairo_command_t *)); recording_surface->replay_start_idx = 0; recording_surface->base.is_clear = TRUE; return &recording_surface->base; }
/* A convenience function for when one needs to coerce an image * surface to an alternate format. */ cairo_image_surface_t * _cairo_image_surface_coerce_to_format (cairo_image_surface_t *surface, cairo_format_t format) { cairo_image_surface_t *clone; cairo_status_t status; status = surface->base.status; if (unlikely (status)) return (cairo_image_surface_t *)_cairo_surface_create_in_error (status); if (surface->format == format) return (cairo_image_surface_t *)cairo_surface_reference(&surface->base); clone = (cairo_image_surface_t *) cairo_image_surface_create (format, surface->width, surface->height); if (unlikely (clone->base.status)) return clone; pixman_image_composite32 (PIXMAN_OP_SRC, surface->pixman_image, NULL, clone->pixman_image, 0, 0, 0, 0, 0, 0, surface->width, surface->height); clone->base.is_clear = FALSE; clone->base.device_transform = surface->base.device_transform; clone->base.device_transform_inverse = surface->base.device_transform_inverse; return clone; }
static cairo_surface_t * _cairo_xcb_surface_fallback (cairo_xcb_surface_t *surface, cairo_composite_rectangles_t *composite) { cairo_image_surface_t *image; cairo_status_t status; status = _cairo_composite_rectangles_add_to_damage (composite, &surface->fallback_damage); if (unlikely (status)) return _cairo_surface_create_in_error (status); if (surface->fallback) return &surface->fallback->base; image = (cairo_image_surface_t *) _get_image (surface, TRUE, 0, 0, surface->width, surface->height); /* If there was a deferred clear, _get_image applied it */ if (image->base.status == CAIRO_STATUS_SUCCESS) { surface->deferred_clear = FALSE; surface->fallback = image; } return &surface->fallback->base; }