コード例 #1
0
static cairo_int_status_t
render_glyphs_via_mask (cairo_gl_surface_t *dst,
			int dst_x, int dst_y,
			cairo_operator_t  op,
			cairo_surface_t *source,
			cairo_composite_glyphs_info_t *info)
{
    cairo_surface_t *mask;
    cairo_status_t status;
    cairo_bool_t has_component_alpha;

    TRACE ((stderr, "%s\n", __FUNCTION__));

    /* XXX: For non-CA, this should be CAIRO_CONTENT_ALPHA to save memory */
    mask = cairo_gl_surface_create (dst->base.device,
                                    CAIRO_CONTENT_COLOR_ALPHA,
                                    info->extents.width,
                                    info->extents.height);
    if (unlikely (mask->status))
        return mask->status;

    status = render_glyphs ((cairo_gl_surface_t *) mask,
			    info->extents.x, info->extents.y,
			    CAIRO_OPERATOR_ADD, NULL,
			    info, &has_component_alpha);
    if (likely (status == CAIRO_STATUS_SUCCESS)) {
	cairo_surface_pattern_t mask_pattern;
	cairo_surface_pattern_t source_pattern;

	mask->is_clear = FALSE;
	_cairo_pattern_init_for_surface (&mask_pattern, mask);
	mask_pattern.base.has_component_alpha = has_component_alpha;
	mask_pattern.base.filter = CAIRO_FILTER_NEAREST;
	mask_pattern.base.extend = CAIRO_EXTEND_NONE;

	cairo_matrix_init_translate (&mask_pattern.base.matrix,
		                     dst_x-info->extents.x, dst_y-info->extents.y);

	_cairo_pattern_init_for_surface (&source_pattern, source);
	cairo_matrix_init_translate (&source_pattern.base.matrix,
		                     dst_x-info->extents.x, dst_y-info->extents.y);

	status = _cairo_surface_mask (&dst->base, op,
		                      &source_pattern.base,
				      &mask_pattern.base,
				      NULL);

	_cairo_pattern_fini (&mask_pattern.base);
	_cairo_pattern_fini (&source_pattern.base);
    }

    cairo_surface_destroy (mask);

    return status;
}
コード例 #2
0
ファイル: cairo-clip.c プロジェクト: AliYousuf/cairo
/* Combines the region of clip->surface given by extents in
 * device backend coordinates into the given temporary surface,
 * which has its origin at dst_x, dst_y in backend coordinates
 */
cairo_status_t
_cairo_clip_combine_to_surface (cairo_clip_t                  *clip,
				cairo_operator_t              op,
				cairo_surface_t               *dst,
				int                           dst_x,
				int                           dst_y,
				const cairo_rectangle_int_t *extents)
{
    cairo_surface_pattern_t pattern;
    cairo_status_t status;

    if (clip->all_clipped)
	return CAIRO_STATUS_SUCCESS;

    _cairo_pattern_init_for_surface (&pattern, clip->surface);

    status = _cairo_surface_composite (op,
				       &pattern.base,
				       NULL,
				       dst,
				       extents->x - clip->surface_rect.x,
				       extents->y - clip->surface_rect.y,
				       0, 0,
				       extents->x - dst_x,
				       extents->y - dst_y,
				       extents->width, extents->height);

    _cairo_pattern_fini (&pattern.base);

    return status;
}
コード例 #3
0
ファイル: cairo-clip.c プロジェクト: manoj-makkuboy/magnetism
/* Combines the region of clip->surface given by extents in
 * device backend coordinates into the given temporary surface,
 * which has its origin at dst_x, dst_y in backend coordinates
 */
cairo_status_t
_cairo_clip_combine_to_surface (cairo_clip_t                  *clip,
				cairo_operator_t              op,
				cairo_surface_t               *dst,
				int                           dst_x,
				int                           dst_y,
				const cairo_rectangle_int16_t *extents)
{
    cairo_pattern_union_t pattern;
    cairo_status_t status;

    _cairo_pattern_init_for_surface (&pattern.surface, clip->surface);

    status = _cairo_surface_composite (op,
				       &pattern.base,
				       NULL,
				       dst,
				       extents->x - clip->surface_rect.x,
				       extents->y - clip->surface_rect.y,
				       0, 0,
				       extents->x - dst_x,
				       extents->y - dst_y,
				       extents->width, extents->height);

    _cairo_pattern_fini (&pattern.base);

    return status;
}
コード例 #4
0
static cairo_status_t
_cairo_surface_subsurface_acquire_source_image (void                    *abstract_surface,
						cairo_image_surface_t  **image_out,
						void                   **extra_out)
{
    cairo_surface_subsurface_t *surface = abstract_surface;
    cairo_surface_pattern_t pattern;
    cairo_surface_t *image;
    cairo_status_t status;

    image = _cairo_image_surface_create_with_content (surface->base.content,
						      surface->extents.width,
						      surface->extents.height);
    if (unlikely (image->status))
	return image->status;

    _cairo_pattern_init_for_surface (&pattern, surface->target);
    cairo_matrix_init_translate (&pattern.base.matrix,
				 surface->extents.x,
				 surface->extents.y);
    pattern.base.filter = CAIRO_FILTER_NEAREST;
    status = _cairo_surface_paint (image,
				   CAIRO_OPERATOR_SOURCE,
				   &pattern.base, NULL);
    _cairo_pattern_fini (&pattern.base);
    if (unlikely (status)) {
	cairo_surface_destroy (image);
	return status;
    }

    *image_out = (cairo_image_surface_t *)image;
    *extra_out = NULL;
    return CAIRO_STATUS_SUCCESS;
}
コード例 #5
0
static cairo_surface_t *
_cairo_surface_subsurface_snapshot (void *abstract_surface)
{
    cairo_surface_subsurface_t *surface = abstract_surface;
    cairo_surface_pattern_t pattern;
    cairo_surface_t *clone;
    cairo_status_t status;

    TRACE ((stderr, "%s: target=%d\n", __FUNCTION__, surface->target->unique_id));

    clone = _cairo_surface_create_similar_scratch (surface->target,
						   surface->target->content,
						   surface->extents.width,
						   surface->extents.height);
    if (unlikely (clone->status))
	return clone;

    _cairo_pattern_init_for_surface (&pattern, surface->target);
    cairo_matrix_init_translate (&pattern.base.matrix,
				 surface->extents.x, surface->extents.y);
    pattern.base.filter = CAIRO_FILTER_NEAREST;
    status = _cairo_surface_paint (clone,
				   CAIRO_OPERATOR_SOURCE,
				   &pattern.base, NULL);
    _cairo_pattern_fini (&pattern.base);

    if (unlikely (status)) {
	cairo_surface_destroy (clone);
	clone = _cairo_surface_create_in_error (status);
    }

    return clone;
}
コード例 #6
0
static cairo_int_status_t
_cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t	*dst,
			                cairo_operator_t	 op,
					const cairo_pattern_t	*source,
					cairo_glyph_t		*glyphs,
					int			 num_glyphs,
					const cairo_rectangle_int_t *glyph_extents,
					cairo_scaled_font_t	*scaled_font,
					cairo_clip_t		*clip,
					int			*remaining_glyphs)
{
    cairo_surface_t *mask;
    cairo_status_t status;
    cairo_solid_pattern_t solid;
    int i;

    mask = cairo_gl_surface_create (dst->ctx,
	                            CAIRO_CONTENT_ALPHA,
				    glyph_extents->width,
				    glyph_extents->height);
    if (unlikely (mask->status))
	return mask->status;

    for (i = 0; i < num_glyphs; i++) {
	glyphs[i].x -= glyph_extents->x;
	glyphs[i].y -= glyph_extents->y;
    }

    _cairo_pattern_init_solid (&solid, CAIRO_COLOR_WHITE, CAIRO_CONTENT_ALPHA);
    status = _render_glyphs ((cairo_gl_surface_t *) mask, 0, 0,
	                     CAIRO_OPERATOR_ADD, &solid.base,
	                     glyphs, num_glyphs, glyph_extents,
			     scaled_font, NULL, remaining_glyphs);
    if (likely (status == CAIRO_STATUS_SUCCESS)) {
	cairo_surface_pattern_t mask_pattern;

	_cairo_pattern_init_for_surface (&mask_pattern, mask);
	cairo_matrix_init_translate (&mask_pattern.base.matrix,
		                     -glyph_extents->x, -glyph_extents->y);
	status = _cairo_surface_mask (&dst->base, op,
		                      source, &mask_pattern.base, clip);
	_cairo_pattern_fini (&mask_pattern.base);
    } else {
	for (i = 0; i < num_glyphs; i++) {
	    glyphs[i].x += glyph_extents->x;
	    glyphs[i].y += glyph_extents->y;
	}
	*remaining_glyphs = num_glyphs;
    }

    cairo_surface_destroy (mask);
    return status;
}
コード例 #7
0
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;
}
コード例 #8
0
/* Creates a cairo-gl pattern surface for the given trapezoids */
static cairo_status_t
_cairo_gl_get_traps_pattern (cairo_gl_surface_t *dst,
			     int dst_x, int dst_y,
			     int width, int height,
			     cairo_trapezoid_t *traps,
			     int num_traps,
			     cairo_antialias_t antialias,
			     cairo_surface_pattern_t *pattern)
{
    pixman_format_code_t pixman_format;
    pixman_image_t *image;
    cairo_surface_t *surface;
    int i;

    pixman_format = antialias != CAIRO_ANTIALIAS_NONE ? PIXMAN_a8 : PIXMAN_a1,
    image = pixman_image_create_bits (pixman_format, width, height, NULL, 0);
    if (unlikely (image == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    for (i = 0; i < num_traps; i++) {
	pixman_trapezoid_t trap;

	trap.top = _cairo_fixed_to_16_16 (traps[i].top);
	trap.bottom = _cairo_fixed_to_16_16 (traps[i].bottom);

	trap.left.p1.x = _cairo_fixed_to_16_16 (traps[i].left.p1.x);
	trap.left.p1.y = _cairo_fixed_to_16_16 (traps[i].left.p1.y);
	trap.left.p2.x = _cairo_fixed_to_16_16 (traps[i].left.p2.x);
	trap.left.p2.y = _cairo_fixed_to_16_16 (traps[i].left.p2.y);

	trap.right.p1.x = _cairo_fixed_to_16_16 (traps[i].right.p1.x);
	trap.right.p1.y = _cairo_fixed_to_16_16 (traps[i].right.p1.y);
	trap.right.p2.x = _cairo_fixed_to_16_16 (traps[i].right.p2.x);
	trap.right.p2.y = _cairo_fixed_to_16_16 (traps[i].right.p2.y);

	pixman_rasterize_trapezoid (image, &trap, -dst_x, -dst_y);
    }

    surface = _cairo_image_surface_create_for_pixman_image (image,
							    pixman_format);
    if (unlikely (surface->status)) {
	pixman_image_unref (image);
	return surface->status;
    }

    _cairo_pattern_init_for_surface (pattern, surface);
    cairo_surface_destroy (surface);

    return CAIRO_STATUS_SUCCESS;
}
コード例 #9
0
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;
}
コード例 #10
0
static cairo_int_status_t
_paint_fallback_image (cairo_paginated_surface_t *surface,
		       cairo_rectangle_int_t     *rect)
{
    double x_scale = surface->base.x_fallback_resolution / surface->target->x_resolution;
    double y_scale = surface->base.y_fallback_resolution / surface->target->y_resolution;
    int x, y, width, height;
    cairo_status_t status;
    cairo_surface_t *image;
    cairo_surface_pattern_t pattern;
    cairo_clip_t *clip;

    x = rect->x;
    y = rect->y;
    width = rect->width;
    height = rect->height;
    image = _cairo_paginated_surface_create_image_surface (surface,
							   ceil (width  * x_scale),
							   ceil (height * y_scale));
    _cairo_surface_set_device_scale (image, x_scale, y_scale);
    /* set_device_offset just sets the x0/y0 components of the matrix;
     * so we have to do the scaling manually. */
    cairo_surface_set_device_offset (image, -x*x_scale, -y*y_scale);

    status = _cairo_recording_surface_replay (surface->recording_surface, image);
    if (unlikely (status))
	goto CLEANUP_IMAGE;

    _cairo_pattern_init_for_surface (&pattern, image);
    cairo_matrix_init (&pattern.base.matrix,
		       x_scale, 0, 0, y_scale, -x*x_scale, -y*y_scale);
    /* the fallback should be rendered at native resolution, so disable
     * filtering (if possible) to avoid introducing potential artifacts. */
    pattern.base.filter = CAIRO_FILTER_NEAREST;

    clip = _cairo_clip_intersect_rectangle (NULL, rect);
    status = _cairo_surface_paint (surface->target,
				   CAIRO_OPERATOR_SOURCE,
				   &pattern.base, clip);
    _cairo_clip_destroy (clip);
    _cairo_pattern_fini (&pattern.base);

CLEANUP_IMAGE:
    cairo_surface_destroy (image);

    return (cairo_int_status_t)status;
}
コード例 #11
0
cairo_status_t
_cairo_surface_fallback_clone_similar (cairo_surface_t	*surface,
				       cairo_surface_t	*src,
				       cairo_content_t	 content,
				       int		 src_x,
				       int		 src_y,
				       int		 width,
				       int		 height,
				       int		*clone_offset_x,
				       int		*clone_offset_y,
				       cairo_surface_t **clone_out)
{
    cairo_surface_t *new_surface;
    cairo_surface_pattern_t pattern;
    cairo_status_t status;

    new_surface = _cairo_surface_create_similar_scratch (surface,
							 src->content & content,
							 width, height);
    if (new_surface->status)
	return new_surface->status;

    /* We have to copy these here, so that the coordinate spaces are correct */
    new_surface->device_transform = src->device_transform;
    new_surface->device_transform_inverse = src->device_transform_inverse;

    _cairo_pattern_init_for_surface (&pattern, src);
    cairo_matrix_init_translate (&pattern.base.matrix, src_x, src_y);
    pattern.base.filter = CAIRO_FILTER_NEAREST;

    status = _cairo_surface_paint (new_surface,
				   CAIRO_OPERATOR_SOURCE,
				   &pattern.base, NULL);
    _cairo_pattern_fini (&pattern.base);

    if (unlikely (status)) {
	cairo_surface_destroy (new_surface);
	return status;
    }

    *clone_offset_x = src_x;
    *clone_offset_y = src_y;
    *clone_out = new_surface;
    return CAIRO_STATUS_SUCCESS;
}
コード例 #12
0
static cairo_int_status_t
fixup_unbounded_mask (const cairo_spans_compositor_t *compositor,
		      const cairo_composite_rectangles_t *extents,
		      cairo_boxes_t *boxes)
{
    cairo_composite_rectangles_t composite;
    cairo_surface_t *clip;
    cairo_int_status_t status;

    TRACE((stderr, "%s\n", __FUNCTION__));

    clip = get_clip_surface (compositor, extents->surface, extents->clip,
			     &extents->unbounded);
    if (unlikely (clip->status)) {
	if ((cairo_int_status_t)clip->status == CAIRO_INT_STATUS_NOTHING_TO_DO)
	    return CAIRO_STATUS_SUCCESS;

	return clip->status;
    }

    status = _cairo_composite_rectangles_init_for_boxes (&composite,
							 extents->surface,
							 CAIRO_OPERATOR_CLEAR,
							 &_cairo_pattern_clear.base,
							 boxes,
							 NULL);
    if (unlikely (status))
	goto cleanup_clip;

    _cairo_pattern_init_for_surface (&composite.mask_pattern.surface, clip);
    composite.mask_pattern.base.filter = CAIRO_FILTER_NEAREST;
    composite.mask_pattern.base.extend = CAIRO_EXTEND_NONE;

    status = composite_boxes (compositor, &composite, boxes);

    _cairo_pattern_fini (&composite.mask_pattern.base);
    _cairo_composite_rectangles_fini (&composite);

cleanup_clip:
    cairo_surface_destroy (clip);
    return status;
}
コード例 #13
0
static cairo_status_t
_create_composite_mask_pattern (cairo_surface_pattern_t       *mask_pattern,
				cairo_clip_t                  *clip,
				cairo_draw_func_t             draw_func,
				void                          *draw_closure,
				cairo_surface_t               *dst,
				const cairo_rectangle_int_t   *extents)
{
    cairo_surface_t *mask;
    cairo_status_t status;

    mask = cairo_surface_create_similar (dst,
					 CAIRO_CONTENT_ALPHA,
					 extents->width,
					 extents->height);
    if (mask->status)
	return mask->status;

    status = (*draw_func) (draw_closure, CAIRO_OPERATOR_ADD,
			   NULL, mask,
			   extents->x, extents->y,
			   extents);
    if (status)
	goto CLEANUP_SURFACE;

    if (clip && clip->surface)
	status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_IN,
						 mask,
						 extents->x, extents->y,
						 extents);
    if (status)
	goto CLEANUP_SURFACE;

    _cairo_pattern_init_for_surface (mask_pattern, mask);

 CLEANUP_SURFACE:
    cairo_surface_destroy (mask);

    return status;
}
コード例 #14
0
static cairo_int_status_t
_cairo_shape_mask_compositor_stroke (const cairo_compositor_t *_compositor,
				     cairo_composite_rectangles_t *extents,
				     const cairo_path_fixed_t	*path,
				     const cairo_stroke_style_t	*style,
				     const cairo_matrix_t	*ctm,
				     const cairo_matrix_t	*ctm_inverse,
				     double		 tolerance,
				     cairo_antialias_t	 antialias)
{
    cairo_surface_t *mask;
    cairo_surface_pattern_t pattern;
    cairo_int_status_t status;
    cairo_clip_t *clip;

    if (! extents->is_bounded)
	return CAIRO_INT_STATUS_UNSUPPORTED;

    TRACE ((stderr, "%s\n", __FUNCTION__));
    mask = _cairo_surface_create_scratch (extents->surface,
					  CAIRO_CONTENT_ALPHA,
					  extents->bounded.width,
					  extents->bounded.height,
					  NULL);
    if (unlikely (mask->status))
	return mask->status;

    clip = extents->clip;
    if (! _cairo_clip_is_region (clip))
	clip = _cairo_clip_copy_region (clip);

    if (! mask->is_clear) {
	status = _cairo_surface_offset_paint (mask,
					      extents->bounded.x,
					      extents->bounded.y,
					      CAIRO_OPERATOR_CLEAR,
					      &_cairo_pattern_clear.base,
					      clip);
	if (unlikely (status))
	    goto error;
    }

    status = _cairo_surface_offset_stroke (mask,
					   extents->bounded.x,
					   extents->bounded.y,
					   CAIRO_OPERATOR_ADD,
					   &_cairo_pattern_white.base,
					   path, style, ctm, ctm_inverse,
					   tolerance, antialias,
					   clip);
    if (unlikely (status))
	goto error;

    if (clip != extents->clip) {
	status = _cairo_clip_combine_with_surface (extents->clip, mask,
						   extents->bounded.x,
						   extents->bounded.y);
	if (unlikely (status))
	    goto error;
    }

    _cairo_pattern_init_for_surface (&pattern, mask);
    cairo_matrix_init_translate (&pattern.base.matrix,
				 -extents->bounded.x,
				 -extents->bounded.y);
    pattern.base.filter = CAIRO_FILTER_NEAREST;
    pattern.base.extend = CAIRO_EXTEND_NONE;
    if (extents->op == CAIRO_OPERATOR_SOURCE) {
	status = _cairo_surface_mask (extents->surface,
				      CAIRO_OPERATOR_DEST_OUT,
				      &_cairo_pattern_white.base,
				      &pattern.base,
				      clip);
	if ((status == CAIRO_INT_STATUS_SUCCESS)) {
	    status = _cairo_surface_mask (extents->surface,
					  CAIRO_OPERATOR_ADD,
					  &extents->source_pattern.base,
					  &pattern.base,
					  clip);
	}
    } else {
	status = _cairo_surface_mask (extents->surface,
				      extents->op,
				      &extents->source_pattern.base,
				      &pattern.base,
				      clip);
    }
    _cairo_pattern_fini (&pattern.base);

error:
    cairo_surface_destroy (mask);
    if (clip != extents->clip)
	_cairo_clip_destroy (clip);
    return status;
}
コード例 #15
0
cairo_warn cairo_int_status_t
_cairo_dwrite_scaled_show_glyphs(void			*scaled_font,
				 cairo_operator_t	 op,
				 const cairo_pattern_t	*pattern,
				 cairo_surface_t	*generic_surface,
				 int			 source_x,
				 int			 source_y,
				 int			 dest_x,
				 int			 dest_y,
				 unsigned int		 width,
				 unsigned int		 height,
				 cairo_glyph_t		*glyphs,
				 int			 num_glyphs,
				 cairo_region_t		*clip_region,
				 int			*remaining_glyphs)
{
    cairo_win32_surface_t *surface = (cairo_win32_surface_t *)generic_surface;
    cairo_int_status_t status;

    if (width == 0 || height == 0)
	return (cairo_int_status_t)CAIRO_STATUS_SUCCESS;

    if (_cairo_surface_is_win32 (generic_surface) &&
	surface->format == CAIRO_FORMAT_RGB24 &&
	op == CAIRO_OPERATOR_OVER) {

	    //XXX: we need to set the clip region here

	status = (cairo_int_status_t)_cairo_dwrite_show_glyphs_on_surface (surface, op, pattern,
									  glyphs, num_glyphs, 
									  (cairo_scaled_font_t*)scaled_font, NULL);

	return status;
    } else {
	cairo_dwrite_scaled_font_t *dwritesf =
	    static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
	UINT16 *indices = new UINT16[num_glyphs];
	DWRITE_GLYPH_OFFSET *offsets = new DWRITE_GLYPH_OFFSET[num_glyphs];
	FLOAT *advances = new FLOAT[num_glyphs];
	BOOL transform = FALSE;

	DWRITE_GLYPH_RUN run;
	run.bidiLevel = 0;
	run.fontFace = ((cairo_dwrite_font_face_t*)dwritesf->base.font_face)->dwriteface;
	run.glyphIndices = indices;
	run.glyphCount = num_glyphs;
	run.isSideways = FALSE;
	run.glyphOffsets = offsets;
	run.glyphAdvances = advances;
    	IDWriteGlyphRunAnalysis *analysis;

	if (dwritesf->mat.xy == 0 && dwritesf->mat.yx == 0 &&
	    dwritesf->mat.xx == dwritesf->base.font_matrix.xx && 
	    dwritesf->mat.yy == dwritesf->base.font_matrix.yy) {

	    for (int i = 0; i < num_glyphs; i++) {
		indices[i] = (WORD) glyphs[i].index;
		// Since we will multiply by our ctm matrix later for rotation effects
		// and such, adjust positions by the inverse matrix now.
		offsets[i].ascenderOffset = (FLOAT)dest_y - (FLOAT)glyphs[i].y;
		offsets[i].advanceOffset = (FLOAT)glyphs[i].x - dest_x;
		advances[i] = 0.0;
	    }
	    run.fontEmSize = (FLOAT)dwritesf->base.font_matrix.yy;
	} else {
	    transform = TRUE;

	    for (int i = 0; i < num_glyphs; i++) {
		indices[i] = (WORD) glyphs[i].index;
		double x = glyphs[i].x - dest_x;
		double y = glyphs[i].y - dest_y;
		cairo_matrix_transform_point(&dwritesf->mat_inverse, &x, &y);
		// Since we will multiply by our ctm matrix later for rotation effects
		// and such, adjust positions by the inverse matrix now.
		offsets[i].ascenderOffset = -(FLOAT)y;
		offsets[i].advanceOffset = (FLOAT)x;
		advances[i] = 0.0;
	    }
	    run.fontEmSize = 1.0f;
	}

	if (!transform) {
	    DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run,
							      1.0f,
							      NULL,
							      DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
							      DWRITE_MEASURING_MODE_NATURAL,
							      0,
							      0,
							      &analysis);
	} else {
	    DWRITE_MATRIX dwmatrix = _cairo_dwrite_matrix_from_matrix(&dwritesf->mat);
	    DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run,
							      1.0f,
							      &dwmatrix,
							      DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
							      DWRITE_MEASURING_MODE_NATURAL,
							      0,
							      0,
							      &analysis);
	}

	RECT r;
	r.left = 0;
	r.top = 0;
	r.right = width;
	r.bottom = height;

	BYTE *surface = new BYTE[width * height * 3];

	analysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, &r, surface, width * height * 3);

	cairo_image_surface_t *mask_surface = 
	    (cairo_image_surface_t*)cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);

	cairo_surface_flush(&mask_surface->base);

	for (unsigned int y = 0; y < height; y++) {
	    for (unsigned int x = 0; x < width; x++) {
		mask_surface->data[y * mask_surface->stride + x * 4] = surface[y * width * 3 + x * 3 + 1];
		mask_surface->data[y * mask_surface->stride + x * 4 + 1] = surface[y * width * 3 + x * 3 + 1];
		mask_surface->data[y * mask_surface->stride + x * 4 + 2] = surface[y * width * 3 + x * 3 + 1];
		mask_surface->data[y * mask_surface->stride + x * 4 + 3] = surface[y * width * 3 + x * 3 + 1];
	    }
	}
	cairo_surface_mark_dirty(&mask_surface->base);

	pixman_image_set_component_alpha(mask_surface->pixman_image, 1);

	cairo_surface_pattern_t mask;
	_cairo_pattern_init_for_surface (&mask, &mask_surface->base);

	status = (cairo_int_status_t)_cairo_surface_composite (op, pattern,
							       &mask.base,
							       generic_surface,
							       source_x, source_y,
							       0, 0,
							       dest_x, dest_y,
							       width, height,
							       clip_region);

	_cairo_pattern_fini (&mask.base);

	analysis->Release();
	delete [] surface;
	delete [] indices;
	delete [] offsets;
	delete [] advances;

	cairo_surface_destroy (&mask_surface->base);
	*remaining_glyphs = 0;

	return (cairo_int_status_t)CAIRO_STATUS_SUCCESS;
    }
}
コード例 #16
0
ファイル: cairo-clip.c プロジェクト: Dirbaio/libgdiplus
static cairo_status_t
_cairo_clip_intersect_mask (cairo_clip_t      *clip,
			    cairo_traps_t     *traps,
			    cairo_antialias_t antialias,
			    cairo_surface_t   *target)
{
    cairo_pattern_union_t pattern;
    cairo_box_t extents;
    cairo_rectangle_int_t surface_rect, target_rect;
    cairo_surface_t *surface;
    cairo_status_t status;

    if (clip->all_clipped)
	return CAIRO_STATUS_SUCCESS;

    /* Represent the clip as a mask surface.  We create a new surface
     * the size of the intersection of the old mask surface and the
     * extents of the new clip path. */

    _cairo_traps_extents (traps, &extents);
    _cairo_box_round_to_rectangle (&extents, &surface_rect);

    if (clip->surface != NULL)
	_cairo_rectangle_intersect (&surface_rect, &clip->surface_rect);

    /* Intersect with the target surface rectangle so we don't use
     * more memory and time than we need to. */

    status = _cairo_surface_get_extents (target, &target_rect);
    if (!status)
	_cairo_rectangle_intersect (&surface_rect, &target_rect);

    if (surface_rect.width == 0 || surface_rect.height == 0) {
	surface = NULL;
	status = CAIRO_STATUS_SUCCESS;
	if (clip->surface != NULL)
	    cairo_surface_destroy (clip->surface);
	goto DONE;
    }

    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
			       CAIRO_CONTENT_COLOR);
    /* The clipping operation should ideally be something like the following to
     * avoid having to do as many passes over the data

	if (clip->surface != NULL) {
	    _cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
	} else {
	    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
			       CAIRO_CONTENT_COLOR);
	}
	status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_IN,
						  &pattern.base,
						  surface,
						  antialias,
						  0, 0,
						  0, 0,
						  surface_rect.width,
						  surface_rect.height,
						  traps->traps,
						  traps->num_traps);

	However this operation is not accelerated by pixman

	I believe the best possible operation would probably an unbounded SRC
	operator.  Using SRC we could potentially avoid having to initialize
	the surface which would be ideal from an efficiency point of view.
	However, _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_SOURCE) is
	bounded by the mask.

    */

    surface = _cairo_surface_create_similar_solid (target,
						   CAIRO_CONTENT_ALPHA,
						   surface_rect.width,
						   surface_rect.height,
						   CAIRO_COLOR_TRANSPARENT,
						   &pattern.base);
    if (surface->status) {
	_cairo_pattern_fini (&pattern.base);
	return surface->status;
    }

    /* Render the new clipping path into the new mask surface. */

    _cairo_traps_translate (traps, -surface_rect.x, -surface_rect.y);

    status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_ADD,
						  &pattern.base,
						  surface,
						  antialias,
						  0, 0,
						  0, 0,
						  surface_rect.width,
						  surface_rect.height,
						  traps->traps,
						  traps->num_traps);

    _cairo_pattern_fini (&pattern.base);

    if (status) {
	cairo_surface_destroy (surface);
	return status;
    }

    /* If there was a clip surface already, combine it with the new
     * mask surface using the IN operator, so we get the intersection
     * of the old and new clipping paths. */

    if (clip->surface != NULL) {
	_cairo_pattern_init_for_surface (&pattern.surface, clip->surface);

	status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
					   &pattern.base,
					   NULL,
					   surface,
					   surface_rect.x - clip->surface_rect.x,
					   surface_rect.y - clip->surface_rect.y,
					   0, 0,
					   0, 0,
					   surface_rect.width,
					   surface_rect.height);

	_cairo_pattern_fini (&pattern.base);

	if (status) {
	    cairo_surface_destroy (surface);
	    return status;
	}

	cairo_surface_destroy (clip->surface);
    }

 DONE:
    clip->surface = surface;
    clip->surface_rect = surface_rect;
    clip->serial = _cairo_surface_allocate_clip_serial (target);

    if (surface_rect.width == 0 || surface_rect.height == 0)
	_cairo_clip_set_all_clipped (clip, target);

    return status;
}
コード例 #17
0
static cairo_int_status_t
traps_to_operand (void *_dst,
		  const cairo_rectangle_int_t *extents,
		  cairo_antialias_t	antialias,
		  cairo_traps_t		*traps,
		  cairo_gl_operand_t	*operand,
		  int dst_x, int dst_y)
{
    pixman_format_code_t pixman_format;
    pixman_image_t *pixman_image;
    cairo_surface_t *image, *mask;
    cairo_surface_pattern_t pattern;
    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_error (CAIRO_STATUS_NO_MEMORY);

    _pixman_image_add_traps (pixman_image, extents->x, extents->y, traps);
    image = _cairo_image_surface_create_for_pixman_image (pixman_image,
							  pixman_format);
    if (unlikely (image->status)) {
	pixman_image_unref (pixman_image);
	return image->status;
    }

    /* GLES2 only supports RGB/RGBA when uploading */
    if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES) {
	cairo_surface_pattern_t pattern;
	cairo_surface_t *rgba_image;

	/* XXX perform this fixup inside _cairo_gl_draw_image() */

	rgba_image =
	    _cairo_image_surface_create_with_pixman_format (NULL,
							    _cairo_is_little_endian () ?  PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8,
							    extents->width,
							    extents->height,
							    0);
	if (unlikely (rgba_image->status))
	    return rgba_image->status;

	_cairo_pattern_init_for_surface (&pattern, image);
	status = _cairo_surface_paint (rgba_image, CAIRO_OPERATOR_SOURCE,
				       &pattern.base, NULL);
	_cairo_pattern_fini (&pattern.base);

	cairo_surface_destroy (image);
	image = rgba_image;

	if (unlikely (status)) {
	    cairo_surface_destroy (image);
	    return status;
	}
    }

    mask = _cairo_surface_create_similar_scratch (_dst,
						  CAIRO_CONTENT_COLOR_ALPHA,
						  extents->width,
						  extents->height);
    if (unlikely (mask->status)) {
	cairo_surface_destroy (image);
	return mask->status;
    }

    status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *)mask,
					   (cairo_image_surface_t *)image,
					   0, 0,
					   extents->width, extents->height,
					   0, 0);
    cairo_surface_destroy (image);

    if (unlikely (status))
	goto error;

    _cairo_pattern_init_for_surface (&pattern, mask);
    cairo_matrix_init_translate (&pattern.base.matrix,
				 -extents->x+dst_x, -extents->y+dst_y);
    pattern.base.filter = CAIRO_FILTER_NEAREST;
    pattern.base.extend = CAIRO_EXTEND_NONE;
    status = _cairo_gl_operand_init (operand, &pattern.base, _dst,
				     &_cairo_unbounded_rectangle,
				     &_cairo_unbounded_rectangle);
    _cairo_pattern_fini (&pattern.base);

    if (unlikely (status))
	goto error;

    operand->texture.owns_surface = mask;
    return CAIRO_STATUS_SUCCESS;

error:
    cairo_surface_destroy (mask);
    return status;
}
コード例 #18
0
cairo_status_t
_cairo_scaled_font_show_glyphs (cairo_scaled_font_t    *scaled_font,
				cairo_operator_t        op,
				cairo_pattern_t        *pattern,
				cairo_surface_t        *surface,
				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;
    cairo_surface_t *mask = NULL;
    int i;

    /* These operators aren't interpreted the same way by the backends;
     * they are implemented in terms of other operators in cairo-gstate.c
     */
    assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR);
    
    if (scaled_font->status)
	return scaled_font->status;

    if (scaled_font->backend->show_glyphs != NULL) {
	status = scaled_font->backend->show_glyphs (scaled_font,
						    op, pattern, 
						    surface,
						    source_x, source_y,
						    dest_x, dest_y,
						    width, height,
						    glyphs, num_glyphs);
	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
	    return status;
    }

    /* Font display routine either does not exist or failed. */
    
    status = CAIRO_STATUS_SUCCESS;

    _cairo_cache_freeze (scaled_font->glyphs);

    for (i = 0; i < num_glyphs; i++) {
	int x, y;
	cairo_surface_pattern_t glyph_pattern;
	cairo_image_surface_t *glyph_surface;
	cairo_scaled_glyph_t *scaled_glyph;
	
	status = _cairo_scaled_glyph_lookup (scaled_font,
					     glyphs[i].index,
					     CAIRO_SCALED_GLYPH_INFO_SURFACE,
					     &scaled_glyph);

	if (status)
	    goto CLEANUP_MASK;
	
	glyph_surface = scaled_glyph->surface;

	/* Create the mask using the format from the first glyph */
	if (mask == NULL) {
	    mask = cairo_image_surface_create (glyph_surface->format,
					       width, height);
	    if (mask->status) {
		status = mask->status;
		goto CLEANUP_MASK;
	    }

	    status = _cairo_surface_fill_rectangle (mask,
						    CAIRO_OPERATOR_CLEAR,
						    CAIRO_COLOR_TRANSPARENT,
						    0, 0,
						    width, height);
	    if (status)
		goto CLEANUP_MASK;
	    if (glyph_surface->format == CAIRO_FORMAT_ARGB32)
		pixman_image_set_component_alpha (((cairo_image_surface_t*) mask)->
						  pixman_image, TRUE);

	}
	
	/* round glyph locations to the nearest pixel */
	x = (int) floor (glyphs[i].x + 
			 glyph_surface->base.device_x_offset +
			 0.5);
	y = (int) floor (glyphs[i].y +
			 glyph_surface->base.device_y_offset +
			 0.5);
	
	_cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base);

	status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, 
					   &glyph_pattern.base, 
					   NULL,
					   mask,
					   0, 0,
					   0, 0, 
					   x - dest_x, 
					   y - dest_y, 
					   glyph_surface->width,
					   glyph_surface->height);

	_cairo_pattern_fini (&glyph_pattern.base);
	if (status)
	    break;
    }
    
    if (mask != NULL) {
	cairo_surface_pattern_t mask_pattern;

	_cairo_pattern_init_for_surface (&mask_pattern, mask);
    
	status = _cairo_surface_composite (op, pattern, &mask_pattern.base,
					   surface,
					   source_x, source_y, 
					   0,        0,
					   dest_x,   dest_y,
					   width,    height);
    
	_cairo_pattern_fini (&mask_pattern.base);
    }
	
CLEANUP_MASK:
    _cairo_cache_thaw (scaled_font->glyphs);
    
    if (mask != NULL)
	cairo_surface_destroy (mask);
    return status;
}
コード例 #19
0
ファイル: cairo-gl-surface.c プロジェクト: mrobinson/cairo
cairo_status_t
_cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
			      cairo_image_surface_t *src,
			      int src_x, int src_y,
			      int width, int height,
			      int dst_x, int dst_y)
{
    GLenum internal_format, format, type;
    cairo_bool_t has_alpha, needs_swap;
    cairo_image_surface_t *clone = NULL;
    cairo_gl_context_t *ctx;
    int cpp;
    cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;

    status = _cairo_gl_context_acquire (dst->base.device, &ctx);
    if (unlikely (status))
	return status;

    if (! _cairo_gl_get_image_format_and_type (ctx->gl_flavor,
					       src->pixman_format,
					       &internal_format,
					       &format,
					       &type,
					       &has_alpha,
					       &needs_swap))
    {
	cairo_bool_t is_supported;

	clone = _cairo_image_surface_coerce (src);
	if (unlikely (status = clone->base.status))
	    goto FAIL;

	is_supported =
	    _cairo_gl_get_image_format_and_type (ctx->gl_flavor,
						 clone->pixman_format,
		                                 &internal_format,
						 &format,
						 &type,
						 &has_alpha,
						 &needs_swap);
	assert (is_supported);
	assert (!needs_swap);
	src = clone;
    }

    cpp = PIXMAN_FORMAT_BPP (src->pixman_format) / 8;

    status = _cairo_gl_surface_flush (&dst->base);
    if (unlikely (status))
	goto FAIL;

    if (_cairo_gl_surface_is_texture (dst)) {
	void *data_start = src->data + src_y * src->stride + src_x * cpp;
	void *data_start_gles2 = NULL;

	/*
	 * Due to GL_UNPACK_ROW_LENGTH missing in GLES2 we have to extract the
	 * image data ourselves in some cases. In particular, we must extract
	 * the pixels if:
	 * a. we don't want full-length lines or
	 * b. the row stride cannot be handled by GL itself using a 4 byte
	 *     alignment constraint
	 */
	if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES &&
	    (src->width * cpp < src->stride - 3 ||
	     width != src->width))
	{
	    glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
	    status = _cairo_gl_surface_extract_image_data (src, src_x, src_y,
							   width, height,
							   &data_start_gles2);
	    if (unlikely (status))
		goto FAIL;

	    data_start = data_start_gles2;
	}
	else
	{
	    glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
	    if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
		glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp);
	}

        _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP);
	glBindTexture (ctx->tex_target, dst->tex);
	glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexSubImage2D (ctx->tex_target, 0,
			 dst_x, dst_y, width, height,
			 format, type, data_start);

	free (data_start_gles2);

	/* If we just treated some rgb-only data as rgba, then we have to
	 * go back and fix up the alpha channel where we filled in this
	 * texture data.
	 */
	if (!has_alpha) {
	    _cairo_gl_surface_fill_alpha_channel (dst, ctx,
						  dst_x, dst_y,
						  width, height);
	}
    } else {
        cairo_surface_t *tmp;

        tmp = _cairo_gl_surface_create_scratch (ctx,
                                                dst->base.content,
                                                width, height);
        if (unlikely (tmp->status))
            goto FAIL;

        status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *) tmp,
                                               src,
                                               src_x, src_y,
                                               width, height,
                                               0, 0);
        if (status == CAIRO_INT_STATUS_SUCCESS) {
            cairo_surface_pattern_t tmp_pattern;
	    cairo_rectangle_int_t r;
	    cairo_clip_t *clip;

            _cairo_pattern_init_for_surface (&tmp_pattern, tmp);
	    cairo_matrix_init_translate (&tmp_pattern.base.matrix,
					 -dst_x, -dst_y);
	    tmp_pattern.base.filter = CAIRO_FILTER_NEAREST;
	    tmp_pattern.base.extend = CAIRO_EXTEND_NONE;

	    r.x = dst_x;
	    r.y = dst_y;
	    r.width = width;
	    r.height = height;
	    clip = _cairo_clip_intersect_rectangle (NULL, &r);
	    status = _cairo_surface_paint (&dst->base,
					   CAIRO_OPERATOR_SOURCE,
					   &tmp_pattern.base,
					   clip);
	    _cairo_clip_destroy (clip);
            _cairo_pattern_fini (&tmp_pattern.base);
        }

        cairo_surface_destroy (tmp);
    }

FAIL:
    status = _cairo_gl_context_release (ctx, status);

    if (clone)
        cairo_surface_destroy (&clone->base);

    return status;
}
コード例 #20
0
/* Handles compositing with a clip surface when we have to do the operation
 * in two pieces and combine them together.
 */
static cairo_status_t
_clip_and_composite_combine (cairo_clip_t                  *clip,
			     cairo_operator_t               op,
			     cairo_pattern_t               *src,
			     cairo_draw_func_t              draw_func,
			     void                          *draw_closure,
			     cairo_surface_t               *dst,
			     const cairo_rectangle_int_t   *extents)
{
    cairo_surface_t *intermediate;
    cairo_surface_pattern_t dst_pattern;
    cairo_surface_pattern_t intermediate_pattern;
    cairo_status_t status;

    /* We'd be better off here creating a surface identical in format
     * to dst, but we have no way of getting that information.
     * A CAIRO_CONTENT_CLONE or something might be useful.
     * cairo_surface_create_similar() also unnecessarily clears the surface.
     */
    intermediate = cairo_surface_create_similar (dst,
						 CAIRO_CONTENT_COLOR_ALPHA,
						 extents->width,
						 extents->height);
    if (intermediate->status)
	return intermediate->status;

    /* Initialize the intermediate surface from the destination surface
     */
    _cairo_pattern_init_for_surface (&dst_pattern, dst);

    status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
				       &dst_pattern.base, NULL, intermediate,
				       extents->x,     extents->y,
				       0,              0,
				       0,              0,
				       extents->width, extents->height);

    _cairo_pattern_fini (&dst_pattern.base);

    if (status)
	goto CLEANUP_SURFACE;

    status = (*draw_func) (draw_closure, op,
			   src, intermediate,
			   extents->x, extents->y,
			   extents);
    if (status)
	goto CLEANUP_SURFACE;

    /* Combine that with the clip
     */
    status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_DEST_IN,
					     intermediate,
					     extents->x, extents->y,
					     extents);
    if (status)
	goto CLEANUP_SURFACE;

    /* Punch the clip out of the destination
     */
    status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_DEST_OUT,
					     dst,
					     0, 0,
					     extents);
    if (status)
	goto CLEANUP_SURFACE;

    /* Now add the two results together
     */
    _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);

    status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
				       &intermediate_pattern.base, NULL, dst,
				       0,              0,
				       0,              0,
				       extents->x,     extents->y,
				       extents->width, extents->height);

    _cairo_pattern_fini (&intermediate_pattern.base);

 CLEANUP_SURFACE:
    cairo_surface_destroy (intermediate);

    return status;
}
コード例 #21
0
/* Composites a region representing a set of trapezoids.
 */
static cairo_status_t
_composite_trap_region (cairo_clip_t            *clip,
			cairo_pattern_t         *src,
			cairo_operator_t         op,
			cairo_surface_t         *dst,
			cairo_region_t          *trap_region,
			cairo_rectangle_int_t   *extents)
{
    cairo_status_t status;
    cairo_pattern_union_t solid_pattern;
    cairo_pattern_union_t mask;
    int num_rects = _cairo_region_num_boxes (trap_region);
    unsigned int clip_serial;
    cairo_surface_t *clip_surface = clip ? clip->surface : NULL;

    if (clip_surface && op == CAIRO_OPERATOR_CLEAR) {
	_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE,
				   CAIRO_CONTENT_COLOR);
	src = &solid_pattern.base;
	op = CAIRO_OPERATOR_DEST_OUT;
    }

    if (num_rects == 0)
	return CAIRO_STATUS_SUCCESS;

    if (num_rects > 1) {
      if (_cairo_surface_get_clip_mode (dst) != CAIRO_CLIP_MODE_REGION)
	    return CAIRO_INT_STATUS_UNSUPPORTED;

	clip_serial = _cairo_surface_allocate_clip_serial (dst);
	status = _cairo_surface_set_clip_region (dst,
						 trap_region,
						 clip_serial);
	if (status)
	    return status;
    }

    if (clip_surface)
	_cairo_pattern_init_for_surface (&mask.surface, clip_surface);

    status = _cairo_surface_composite (op,
				       src,
				       clip_surface ? &mask.base : NULL,
				       dst,
				       extents->x, extents->y,
				       extents->x - (clip_surface ? clip->surface_rect.x : 0),
				       extents->y - (clip_surface ? clip->surface_rect.y : 0),
				       extents->x, extents->y,
				       extents->width, extents->height);

    /* Restore the original clip if we modified it temporarily. */
    if (num_rects > 1) {
	cairo_status_t status2 = _cairo_surface_set_clip (dst, clip);
	if (status == CAIRO_STATUS_SUCCESS)
	    status = status2;
    }

    if (clip_surface)
      _cairo_pattern_fini (&mask.base);

    if (src == &solid_pattern.base)
	_cairo_pattern_fini (&solid_pattern.base);

    return status;
}
コード例 #22
0
static cairo_surface_t *
_cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
			      cairo_surface_t *target)
{
    cairo_surface_t *surface;
    cairo_pattern_union_t pattern;
    cairo_status_t status;
    const cairo_rectangle_int_t *clip_extents = &clip_path->extents;
    cairo_clip_path_t *prev;
    cairo_bool_t need_translate;

    if (clip_path->surface != NULL &&
	clip_path->surface->backend == target->backend)
    {
	return cairo_surface_reference (clip_path->surface);
    }

    surface = _cairo_surface_create_similar_solid (target,
						   CAIRO_CONTENT_ALPHA,
						   clip_extents->width,
						   clip_extents->height,
						   CAIRO_COLOR_TRANSPARENT,
						   FALSE);
    if (surface == NULL) {
	if (clip_path->surface != NULL &&
	    clip_path->surface->backend == &_cairo_image_surface_backend)
	{
	    return cairo_surface_reference (clip_path->surface);
	}

	surface =
	    _cairo_image_surface_create_with_content (CAIRO_CONTENT_ALPHA,
						      clip_extents->width,
						      clip_extents->height);
    }
    if (unlikely (surface->status))
	return surface;

    _cairo_pattern_init_solid (&pattern.solid,
			       CAIRO_COLOR_WHITE,
			       CAIRO_CONTENT_COLOR);

    status = _cairo_clip_path_to_region (clip_path);
    if (unlikely (_cairo_status_is_error (status)))
	goto BAIL;

    need_translate = clip_extents->x | clip_extents->y;
    if (status == CAIRO_STATUS_SUCCESS) {
	if (need_translate) {
	    cairo_region_translate (clip_path->region,
				    -clip_extents->x, -clip_extents->y);
	}
	status = _cairo_surface_fill_region (surface,
					     CAIRO_OPERATOR_SOURCE,
					     CAIRO_COLOR_WHITE,
					     clip_path->region);
	if (need_translate) {
	    cairo_region_translate (clip_path->region,
				    clip_extents->x, clip_extents->y);
	}
	if (unlikely (status))
	    goto BAIL;

	goto DONE;
    } else {
	if (need_translate) {
	    _cairo_path_fixed_translate (&clip_path->path,
					 _cairo_fixed_from_int (-clip_extents->x),
					 _cairo_fixed_from_int (-clip_extents->y));
	}
	status = _cairo_surface_fill (surface,
				      CAIRO_OPERATOR_OVER,
				      &pattern.base,
				      &clip_path->path,
				      clip_path->fill_rule,
				      clip_path->tolerance,
				      clip_path->antialias,
				      NULL);
	if (need_translate) {
	    _cairo_path_fixed_translate (&clip_path->path,
					 _cairo_fixed_from_int (clip_extents->x),
					 _cairo_fixed_from_int (clip_extents->y));
	}

	if (unlikely (status))
	    goto BAIL;
    }

    prev = clip_path->prev;
  NEXT_PATH:
    if (prev != NULL) {
	status = _cairo_clip_path_to_region (prev);
	if (unlikely (_cairo_status_is_error (status)))
	    goto BAIL;

	if (status == CAIRO_STATUS_SUCCESS) {
	    status = _combine_region (surface, prev->region, clip_extents);
	    if (unlikely (status))
		goto BAIL;
	} else if (prev->flags & CAIRO_CLIP_PATH_IS_BOX) {
	    /* a simple box only affects the extents */
	} else if (prev->path.is_rectilinear) {
	    if (need_translate) {
		_cairo_path_fixed_translate (&prev->path,
					     _cairo_fixed_from_int (-clip_extents->x),
					     _cairo_fixed_from_int (-clip_extents->y));
	    }
	    status = _cairo_surface_fill (surface,
					  CAIRO_OPERATOR_IN,
					  &pattern.base,
					  &prev->path,
					  prev->fill_rule,
					  prev->tolerance,
					  prev->antialias,
					  NULL);
	    if (need_translate) {
		_cairo_path_fixed_translate (&prev->path,
					     _cairo_fixed_from_int (clip_extents->x),
					     _cairo_fixed_from_int (clip_extents->y));
	    }

	    if (unlikely (status))
		goto BAIL;

	    prev = prev->prev;
	    goto NEXT_PATH;
	} else {
	    cairo_surface_t *prev_surface;

	    prev_surface = _cairo_clip_path_get_surface (prev, target);
	    _cairo_pattern_init_for_surface (&pattern.surface, prev_surface);
	    cairo_surface_destroy (prev_surface);

	    cairo_matrix_init_translate (&pattern.base.matrix,
					 -prev->extents.x + clip_extents->x,
					 -prev->extents.y + clip_extents->y);
	    status = _cairo_surface_paint (surface,
					   CAIRO_OPERATOR_IN,
					   &pattern.base,
					   NULL);
	    _cairo_pattern_fini (&pattern.base);

	    if (unlikely (status))
		goto BAIL;
	}
    }

  DONE:
    cairo_surface_destroy (clip_path->surface);
    return clip_path->surface = cairo_surface_reference (surface);

  BAIL:
    cairo_surface_destroy (surface);
    return _cairo_surface_create_in_error (status);
}
コード例 #23
0
ファイル: cairo-gl-operand.c プロジェクト: zwcloud/CairoSharp
static cairo_status_t
_cairo_gl_subsurface_clone_operand_init (cairo_gl_operand_t *operand,
					 const cairo_pattern_t *_src,
					 cairo_gl_surface_t *dst,
					 const cairo_rectangle_int_t *sample,
					 const cairo_rectangle_int_t *extents,
					 cairo_bool_t use_texgen)
{
    const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
    cairo_surface_pattern_t local_pattern;
    cairo_surface_subsurface_t *sub;
    cairo_gl_surface_t *surface;
    cairo_gl_context_t *ctx;
    cairo_surface_attributes_t *attributes;
    cairo_status_t status;

    sub = (cairo_surface_subsurface_t *) src->surface;

    if (sub->snapshot &&
	sub->snapshot->type == CAIRO_SURFACE_TYPE_GL &&
	sub->snapshot->device == dst->base.device)
    {
	surface = (cairo_gl_surface_t *)
	    cairo_surface_reference (sub->snapshot);
    }
    else
    {
	status = _cairo_gl_context_acquire (dst->base.device, &ctx);
	if (unlikely (status))
	    return status;

	/* XXX Trim surface to the sample area within the subsurface? */
	surface = (cairo_gl_surface_t *)
	    _cairo_gl_surface_create_scratch (ctx,
					      sub->target->content,
					      sub->extents.width,
					      sub->extents.height);
	if (surface->base.status)
	    return _cairo_gl_context_release (ctx, surface->base.status);

	_cairo_pattern_init_for_surface (&local_pattern, sub->target);
	cairo_matrix_init_translate (&local_pattern.base.matrix,
				     sub->extents.x, sub->extents.y);
	local_pattern.base.filter = CAIRO_FILTER_NEAREST;
	status = _cairo_surface_paint (&surface->base,
				       CAIRO_OPERATOR_SOURCE,
				       &local_pattern.base,
				       NULL);
	_cairo_pattern_fini (&local_pattern.base);

	status = _cairo_gl_context_release (ctx, status);
	if (unlikely (status)) {
	    cairo_surface_destroy (&surface->base);
	    return status;
	}

	_cairo_surface_subsurface_set_snapshot (&sub->base, &surface->base);
    }

    status = _cairo_gl_surface_resolve_multisampling (surface);
    if (unlikely (status))
        return status;

    attributes = &operand->texture.attributes;

    operand->type = CAIRO_GL_OPERAND_TEXTURE;
    operand->texture.surface = surface;
    operand->texture.owns_surface = surface;
    operand->texture.tex = surface->tex;

    if (_cairo_gl_device_requires_power_of_two_textures (dst->base.device)) {
	attributes->matrix = src->base.matrix;
    } else {
	cairo_matrix_t m;

	cairo_matrix_init_scale (&m,
				 1.0 / surface->width,
				 1.0 / surface->height);
	cairo_matrix_multiply (&attributes->matrix, &src->base.matrix, &m);
    }

    attributes->extend = src->base.extend;
    attributes->filter = src->base.filter;
    attributes->has_component_alpha = src->base.has_component_alpha;

    operand->texture.texgen = use_texgen;
    return CAIRO_STATUS_SUCCESS;
}
コード例 #24
0
ファイル: cairo-clip.c プロジェクト: AliYousuf/cairo
static cairo_status_t
_cairo_clip_intersect_mask_using_spans (cairo_clip_t       *clip,
					cairo_path_fixed_t *path,
					cairo_fill_rule_t   fill_rule,
					double		    tolerance,
					cairo_antialias_t   antialias,
					cairo_surface_t    *target)
{
    cairo_span_renderer_t *renderer = NULL;
    cairo_pattern_union_t pattern;
    cairo_rectangle_int_t surface_rect;
    cairo_surface_t *surface = NULL;
    cairo_status_t status;
    cairo_operator_t op;
    cairo_composite_rectangles_t rects;

    if (clip->all_clipped)
	return CAIRO_STATUS_SUCCESS;

    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
			       CAIRO_CONTENT_COLOR);

    /* If we have a clip surface we're going to use IN to combine our
     * new clip with the old clip.  The ADD is done to a transparent
     * surface, as that's a fast way of doing it currently.  We should
     * really be using SOURCE instead, but _cairo_surface_composite()
     * checks that it's not called with SOURCE or DEST. */
    op = clip->surface ? CAIRO_OPERATOR_IN : CAIRO_OPERATOR_ADD;

    /* Test if the target can composite spans.  We're going to assume
     * this is a good indicator of whether a similar surface is going
     * to be able to composite spans too. */
    if ( !_cairo_surface_check_span_renderer (op,
					      &pattern.base,
					      target,
					      antialias,
					      NULL))
    {
	status = CAIRO_INT_STATUS_UNSUPPORTED;
	goto BAIL;
    }

    status = _cairo_surface_get_extents (target, &surface_rect);
    if (status)
	goto BAIL;

    /* We'll create a new surface the size of the intersection of the
     * old mask surface and the extents of the new clip path. */
    {
	cairo_rectangle_int_t extents;

	_cairo_path_fixed_approximate_clip_extents (path, &extents);
	if (! _cairo_rectangle_intersect (&surface_rect, &extents))
	    goto SUCCESS;

	if (clip->surface != NULL &&
	    ! _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect))
	    goto SUCCESS;
    }

    /* Make the new mask surface and optionally initialise it from the
     * previous clip if we have one. */
    surface = _cairo_surface_create_similar_solid (target,
						   CAIRO_CONTENT_ALPHA,
						   surface_rect.width,
						   surface_rect.height,
						   CAIRO_COLOR_TRANSPARENT);
    if (surface->status) {
	_cairo_pattern_fini (&pattern.base);
	return surface->status;
    }

    if (clip->surface) {
	cairo_surface_pattern_t old_clip;
	_cairo_pattern_init_for_surface (&old_clip, clip->surface);
	status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
					   &old_clip.base,
					   NULL,
					   surface,
					   surface_rect.x - clip->surface_rect.x,
					   surface_rect.y - clip->surface_rect.y,
					   0, 0,
					   0, 0,
					   surface_rect.width,
					   surface_rect.height);
	_cairo_pattern_fini (&old_clip.base);
	if (status)
	    goto BAIL;
    }

    _cairo_composite_rectangles_init (&rects,
				      surface_rect.x,
				      surface_rect.y,
				      surface_rect.width,
				      surface_rect.height);
    rects.dst.x = 0;
    rects.dst.y = 0;

    /* Render the new clipping path into the new mask surface. We've
     * chosen op to either combine the new clip path with the existing
     * clip mask (if there is one) or just render it. */
    status =_cairo_path_fixed_fill_using_spans (op, &pattern.base,
						path, surface,
						fill_rule, tolerance,
						antialias, &rects);
    if (status)
	goto BAIL;

 SUCCESS:
    if (clip->surface != NULL)
	cairo_surface_destroy (clip->surface);
    clip->surface = surface;
    clip->surface_rect = surface_rect;
    clip->serial = _cairo_surface_allocate_clip_serial (target);
    surface = NULL;

    if (surface_rect.width == 0 || surface_rect.height == 0)
	_cairo_clip_set_all_clipped (clip, target);

 BAIL:
    if (renderer)
	renderer->destroy(renderer);
    if (surface)
	cairo_surface_destroy (surface);
    _cairo_pattern_fini (&pattern.base);
    return status;
}
コード例 #25
0
ファイル: cairo-clip.c プロジェクト: manoj-makkuboy/magnetism
static cairo_status_t
_cairo_clip_intersect_mask (cairo_clip_t      *clip,
			    cairo_traps_t     *traps,
			    cairo_antialias_t antialias,
			    cairo_surface_t   *target)
{
    cairo_pattern_union_t pattern;
    cairo_box_t extents;
    cairo_rectangle_int16_t surface_rect, target_rect;
    cairo_surface_t *surface;
    cairo_status_t status;

    /* Represent the clip as a mask surface.  We create a new surface
     * the size of the intersection of the old mask surface and the
     * extents of the new clip path. */

    _cairo_traps_extents (traps, &extents);
    _cairo_box_round_to_rectangle (&extents, &surface_rect);

    if (clip->surface != NULL)
	_cairo_rectangle_intersect (&surface_rect, &clip->surface_rect);

    /* Intersect with the target surface rectangle so we don't use
     * more memory and time than we need to. */

    status = _cairo_surface_get_extents (target, &target_rect);
    if (!status)
	_cairo_rectangle_intersect (&surface_rect, &target_rect);

    surface = _cairo_surface_create_similar_solid (target,
						   CAIRO_CONTENT_ALPHA,
						   surface_rect.width,
						   surface_rect.height,
						   CAIRO_COLOR_WHITE);
    if (surface->status)
	return CAIRO_STATUS_NO_MEMORY;

    /* Render the new clipping path into the new mask surface. */

    _cairo_traps_translate (traps, -surface_rect.x, -surface_rect.y);
    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);

    status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_IN,
						  &pattern.base,
						  surface,
						  antialias,
						  0, 0,
						  0, 0,
						  surface_rect.width,
						  surface_rect.height,
						  traps->traps,
						  traps->num_traps);

    _cairo_pattern_fini (&pattern.base);

    if (status) {
	cairo_surface_destroy (surface);
	return status;
    }

    /* If there was a clip surface already, combine it with the new
     * mask surface using the IN operator, so we get the intersection
     * of the old and new clipping paths. */

    if (clip->surface != NULL) {
	_cairo_pattern_init_for_surface (&pattern.surface, clip->surface);

	status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
					   &pattern.base,
					   NULL,
					   surface,
					   surface_rect.x - clip->surface_rect.x,
					   surface_rect.y - clip->surface_rect.y,
					   0, 0,
					   0, 0,
					   surface_rect.width,
					   surface_rect.height);

	_cairo_pattern_fini (&pattern.base);

	if (status) {
	    cairo_surface_destroy (surface);
	    return status;
	}

	cairo_surface_destroy (clip->surface);
    }

    clip->surface = surface;
    clip->surface_rect = surface_rect;
    clip->serial = _cairo_surface_allocate_clip_serial (target);

    return status;
}
コード例 #26
0
cairo_status_t
_cairo_clip_combine_with_surface (cairo_clip_t *clip,
				  cairo_surface_t *dst,
				  const cairo_rectangle_int_t *extents)
{
    cairo_pattern_union_t pattern;
    cairo_clip_path_t *clip_path = clip->path;
    cairo_bool_t need_translate;
    cairo_status_t status;

    assert (clip_path != NULL);

    if (clip_path->surface != NULL &&
	clip_path->surface->backend == dst->backend)
    {
	_cairo_pattern_init_for_surface (&pattern.surface,
					 clip_path->surface);
	cairo_matrix_init_translate (&pattern.base.matrix,
				     extents->x - clip_path->extents.x,
				     extents->y - clip_path->extents.y);
	status = _cairo_surface_paint (dst,
				       CAIRO_OPERATOR_IN,
				       &pattern.base,
				       NULL);

	_cairo_pattern_fini (&pattern.base);

	return status;
    }

    _cairo_pattern_init_solid (&pattern.solid,
			       CAIRO_COLOR_WHITE,
			       CAIRO_CONTENT_COLOR);

    need_translate = extents->x | extents->y;
    do {
	status = _cairo_clip_path_to_region (clip_path);
	if (unlikely (_cairo_status_is_error (status)))
	    return status;

	if (status == CAIRO_STATUS_SUCCESS)
	    return _combine_region (dst, clip_path->region, extents);

	if (clip_path->surface != NULL &&
	    clip_path->surface->backend == dst->backend)
	{
	    _cairo_pattern_init_for_surface (&pattern.surface,
					     clip_path->surface);
	    cairo_matrix_init_translate (&pattern.base.matrix,
					 extents->x - clip_path->extents.x,
					 extents->y - clip_path->extents.y);
	    status = _cairo_surface_paint (dst,
					   CAIRO_OPERATOR_IN,
					   &pattern.base,
					   NULL);

	    _cairo_pattern_fini (&pattern.base);

	    return status;
	}

	if (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX) {
	    cairo_region_t clip_region;

	    _cairo_region_init_rectangle (&clip_region, &clip_path->extents);
	    status = _combine_region (dst, &clip_region, extents);
	} else {
	    if (need_translate) {
		_cairo_path_fixed_translate (&clip_path->path,
					     _cairo_fixed_from_int (-extents->x),
					     _cairo_fixed_from_int (-extents->y));
	    }
	    status = _cairo_surface_fill (dst,
					  CAIRO_OPERATOR_IN,
					  &pattern.base,
					  &clip_path->path,
					  clip_path->fill_rule,
					  clip_path->tolerance,
					  clip_path->antialias,
					  NULL);
	    if (need_translate) {
		_cairo_path_fixed_translate (&clip_path->path,
					     _cairo_fixed_from_int (extents->x),
					     _cairo_fixed_from_int (extents->y));
	    }
	}

	if (unlikely (status))
	    return status;
    } while ((clip_path = clip_path->prev) != NULL);

    return CAIRO_STATUS_SUCCESS;
}