📄 cairo-surface.c
字号:
if (clip->region) return _cairo_surface_set_clip_region (surface, clip->region, clip->serial); } return _cairo_surface_reset_clip (surface);}/** * _cairo_surface_get_extents: * @surface: the #cairo_surface_t to fetch extents for * * This function returns a bounding box for the surface. The surface * bounds are defined as a region beyond which no rendering will * possibly be recorded, in otherwords, it is the maximum extent of * potentially usable coordinates. * * For vector surfaces, (PDF, PS, SVG and meta-surfaces), the surface * might be conceived as unbounded, but we force the user to provide a * maximum size at the time of surface_create. So get_extents uses * that size. * * NOTE: The coordinates returned are in "backend" space rather than * "surface" space. That is, they are relative to the true (0,0) * origin rather than the device_transform origin. This might seem a * bit inconsistent with other cairo_surface interfaces, but all * current callers are within the surface layer where backend space is * desired. * * This behavior would have to be changed is we ever exported a public * variant of this function. */cairo_status_t_cairo_surface_get_extents (cairo_surface_t *surface, cairo_rectangle_int16_t *rectangle){ if (surface->status) return surface->status; if (surface->finished) return CAIRO_STATUS_SURFACE_FINISHED; return surface->backend->get_extents (surface, rectangle);}cairo_status_t_cairo_surface_show_glyphs (cairo_surface_t *surface, cairo_operator_t op, cairo_pattern_t *source, const cairo_glyph_t *glyphs, int num_glyphs, cairo_scaled_font_t *scaled_font){ cairo_status_t status; cairo_glyph_t *dev_glyphs = (cairo_glyph_t*) glyphs; cairo_scaled_font_t *dev_scaled_font = scaled_font; cairo_pattern_union_t dev_source; assert (! surface->is_snapshot); if (source->type == CAIRO_PATTERN_TYPE_SURFACE && (source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD)) { return CAIRO_STATUS_NO_MEMORY; } _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base); if (_cairo_surface_has_device_transform (surface)) { int i; dev_glyphs = malloc (sizeof(cairo_glyph_t) * num_glyphs); if (!dev_glyphs) return CAIRO_STATUS_NO_MEMORY; for (i = 0; i < num_glyphs; i++) { dev_glyphs[i].index = glyphs[i].index; dev_glyphs[i].x = glyphs[i].x; dev_glyphs[i].y = glyphs[i].y; cairo_matrix_transform_point (&surface->device_transform, &dev_glyphs[i].x, &dev_glyphs[i].y); } if (! _cairo_matrix_is_integer_translation (&surface->device_transform, NULL, NULL)) { cairo_font_options_t *font_options; cairo_matrix_t font_matrix, dev_ctm; font_options = cairo_font_options_create (); cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix); cairo_scaled_font_get_ctm (scaled_font, &dev_ctm); cairo_matrix_multiply (&dev_ctm, &dev_ctm, &surface->device_transform); cairo_scaled_font_get_font_options (scaled_font, font_options); dev_scaled_font = cairo_scaled_font_create (cairo_scaled_font_get_font_face (scaled_font), &font_matrix, &dev_ctm, font_options); cairo_font_options_destroy (font_options); } } if (surface->backend->show_glyphs) { status = surface->backend->show_glyphs (surface, op, &dev_source.base, dev_glyphs, num_glyphs, dev_scaled_font); if (status != CAIRO_INT_STATUS_UNSUPPORTED) goto FINISH; } status = _cairo_surface_fallback_show_glyphs (surface, op, &dev_source.base, dev_glyphs, num_glyphs, dev_scaled_font);FINISH: if (dev_glyphs != glyphs) free (dev_glyphs); if (dev_scaled_font != scaled_font) cairo_scaled_font_destroy (dev_scaled_font); return status;}/* XXX: Previously, we had a function named _cairo_surface_show_glyphs * with not-so-useful semantics. We've now got a new * _cairo_surface_show_glyphs with the proper semantics, and its * fallback still uses this old function (which still needs to be * cleaned up in terms of both semantics and naming). */cairo_status_t_cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font, cairo_operator_t op, cairo_pattern_t *pattern, cairo_surface_t *dst, int source_x, int source_y, int dest_x, int dest_y, unsigned int width, unsigned int height, const cairo_glyph_t *glyphs, int num_glyphs){ cairo_status_t status; assert (! dst->is_snapshot); if (dst->status) return dst->status; if (dst->finished) return CAIRO_STATUS_SURFACE_FINISHED; if (dst->backend->old_show_glyphs) { status = dst->backend->old_show_glyphs (scaled_font, op, pattern, dst, source_x, source_y, dest_x, dest_y, width, height, glyphs, num_glyphs); } else status = CAIRO_INT_STATUS_UNSUPPORTED; return status;}static cairo_status_t_cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst, cairo_rectangle_int16_t *src_rectangle, cairo_rectangle_int16_t *mask_rectangle, int dst_x, int dst_y, unsigned int width, unsigned int height){ cairo_rectangle_int16_t dst_rectangle; cairo_rectangle_int16_t drawn_rectangle; pixman_region16_t *drawn_region; pixman_region16_t *clear_region; cairo_status_t status = CAIRO_STATUS_SUCCESS; /* The area that was drawn is the area in the destination rectangle but not within * the source or the mask. */ dst_rectangle.x = dst_x; dst_rectangle.y = dst_y; dst_rectangle.width = width; dst_rectangle.height = height; drawn_rectangle = dst_rectangle; if (src_rectangle) _cairo_rectangle_intersect (&drawn_rectangle, src_rectangle); if (mask_rectangle) _cairo_rectangle_intersect (&drawn_rectangle, mask_rectangle); /* Now compute the area that is in dst_rectangle but not in drawn_rectangle */ drawn_region = _cairo_region_create_from_rectangle (&drawn_rectangle); clear_region = _cairo_region_create_from_rectangle (&dst_rectangle); if (!drawn_region || !clear_region) { status = CAIRO_STATUS_NO_MEMORY; goto CLEANUP_REGIONS; } if (pixman_region_subtract (clear_region, clear_region, drawn_region) != PIXMAN_REGION_STATUS_SUCCESS) { status = CAIRO_STATUS_NO_MEMORY; goto CLEANUP_REGIONS; } status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_SOURCE, CAIRO_COLOR_TRANSPARENT, clear_region); CLEANUP_REGIONS: if (drawn_region) pixman_region_destroy (drawn_region); if (clear_region) pixman_region_destroy (clear_region); return status;}/** * _cairo_surface_composite_fixup_unbounded: * @dst: the destination surface * @src_attr: source surface attributes (from _cairo_pattern_acquire_surface()) * @src_width: width of source surface * @src_height: height of source surface * @mask_attr: mask surface attributes or %NULL if no mask * @mask_width: width of mask surface * @mask_height: height of mask surface * @src_x: @src_x from _cairo_surface_composite() * @src_y: @src_y from _cairo_surface_composite() * @mask_x: @mask_x from _cairo_surface_composite() * @mask_y: @mask_y from _cairo_surface_composite() * @dst_x: @dst_x from _cairo_surface_composite() * @dst_y: @dst_y from _cairo_surface_composite() * @width: @width from _cairo_surface_composite() * @height: @height_x from _cairo_surface_composite() * * Eeek! Too many parameters! This is a helper function to take care of fixing * up for bugs in libpixman and RENDER where, when asked to composite an * untransformed surface with an unbounded operator (like CLEAR or SOURCE) * only the region inside both the source and the mask is affected. * This function clears the region that should have been drawn but was wasn't. **/cairo_status_t_cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst, cairo_surface_attributes_t *src_attr, int src_width, int src_height, cairo_surface_attributes_t *mask_attr, int mask_width, int mask_height, int src_x, int src_y, int mask_x, int mask_y, int dst_x, int dst_y, unsigned int width, unsigned int height){ cairo_rectangle_int16_t src_tmp, mask_tmp; cairo_rectangle_int16_t *src_rectangle = NULL; cairo_rectangle_int16_t *mask_rectangle = NULL; assert (! dst->is_snapshot); /* The RENDER/libpixman operators are clipped to the bounds of the untransformed, * non-repeating sources and masks. Other sources and masks can be ignored. */ if (_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) && src_attr->extend == CAIRO_EXTEND_NONE) { src_tmp.x = (dst_x - (src_x + src_attr->x_offset)); src_tmp.y = (dst_y - (src_y + src_attr->y_offset)); src_tmp.width = src_width; src_tmp.height = src_height; src_rectangle = &src_tmp; } if (mask_attr && _cairo_matrix_is_integer_translation (&mask_attr->matrix, NULL, NULL) && mask_attr->extend == CAIRO_EXTEND_NONE) { mask_tmp.x = (dst_x - (mask_x + mask_attr->x_offset)); mask_tmp.y = (dst_y - (mask_y + mask_attr->y_offset)); mask_tmp.width = mask_width; mask_tmp.height = mask_height; mask_rectangle = &mask_tmp; } return _cairo_surface_composite_fixup_unbounded_internal (dst, src_rectangle, mask_rectangle, dst_x, dst_y, width, height);}/** * _cairo_surface_composite_shape_fixup_unbounded: * @dst: the destination surface * @src_attr: source surface attributes (from _cairo_pattern_acquire_surface()) * @src_width: width of source surface * @src_height: height of source surface * @mask_width: width of mask surface * @mask_height: height of mask surface * @src_x: @src_x from _cairo_surface_composite() * @src_y: @src_y from _cairo_surface_composite() * @mask_x: @mask_x from _cairo_surface_composite() * @mask_y: @mask_y from _cairo_surface_composite() * @dst_x: @dst_x from _cairo_surface_composite() * @dst_y: @dst_y from _cairo_surface_composite() * @width: @width from _cairo_surface_composite() * @height: @height_x from _cairo_surface_composite() * * Like _cairo_surface_composite_fixup_unbounded(), but instead of * handling the case where we have a source pattern and a mask * pattern, handle the case where we are compositing a source pattern * using a mask we create ourselves, as in * _cairo_surface_composite_glyphs() or _cairo_surface_composite_trapezoids() **/cairo_status_t_cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst, cairo_surface_attributes_t *src_attr, int src_width, int src_height, int mask_width, int mask_height, int src_x, int src_y, int mask_x, int mask_y, int dst_x, int dst_y, unsigned int width, unsigned int height){ cairo_rectangle_int16_t src_tmp, mask_tmp; cairo_rectangle_int16_t *src_rectangle = NULL; cairo_rectangle_int16_t *mask_rectangle = NULL; assert (! dst->is_snapshot); /* The RENDER/libpixman operators are clipped to the bounds of the untransformed, * non-repeating sources and masks. Other sources and masks can be ignored. */ if (_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) && src_attr->extend == CAIRO_EXTEND_NONE) { src_tmp.x = (dst_x - (src_x + src_attr->x_offset)); src_tmp.y = (dst_y - (src_y + src_attr->y_offset)); src_tmp.width = src_width; src_tmp.height = src_height; src_rectangle = &src_tmp; } mask_tmp.x = dst_x - mask_x; mask_tmp.y = dst_y - mask_y; mask_tmp.width = mask_width; mask_tmp.height = mask_height; mask_rectangle = &mask_tmp; return _cairo_surface_composite_fixup_unbounded_internal (dst, src_rectangle, mask_rectangle, dst_x, dst_y, width, height);}/** * _cairo_surface_copy_pattern_for_destination * @pattern: the pattern to copy * @destination: the destination surface for which the pattern is being copied * @pattern_out: the location to hold the copy * * Copies the given pattern, taking into account device scale and offsets * of the destination surface. */void_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern, cairo_surface_t *destination, cairo_pattern_t *pattern_out){ _cairo_pattern_init_copy (pattern_out, pattern); if (_cairo_surface_has_device_transform (destination)) { cairo_matrix_t device_to_surface = destination->device_transform; cairo_status_t status; status = cairo_matrix_invert (&device_to_surface); /* We only ever allow for scaling (under the implementation's * control) or translation (under the user's control). So the * matrix should always be invertible. */ assert (status == CAIRO_STATUS_SUCCESS); _cairo_pattern_transform (pattern_out, &device_to_surface); }}/* LocalWords: rasterized */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -