static cairo_int_status_t
_cairo_paginated_surface_show_glyphs (void			*abstract_surface,
				      cairo_operator_t		 op,
				      cairo_pattern_t		*source,
				      cairo_glyph_t		*glyphs,
				      int			 num_glyphs,
				      cairo_scaled_font_t	*scaled_font)
{
    cairo_paginated_surface_t *surface = abstract_surface;
    cairo_int_status_t status;

    /* Optimize away erasing of nothing. */
    if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
	return CAIRO_STATUS_SUCCESS;

    surface->page_is_blank = FALSE;

    /* Since this is a "wrapping" surface, we're calling back into
     * _cairo_surface_show_glyphs from within a call to the same.
     * Since _cairo_surface_show_glyphs acquires a mutex, we release
     * and re-acquire the mutex around this nested call.
     *
     * Yes, this is ugly, but we consider it pragmatic as compared to
     * adding locking code to all 18 surface-backend-specific
     * show_glyphs functions, (which would get less testing and likely
     * lead to bugs).
     */
    CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
    status = _cairo_surface_show_glyphs (surface->meta, op, source,
					 glyphs, num_glyphs,
					 scaled_font);
    CAIRO_MUTEX_LOCK (scaled_font->mutex);

    return status;
}
예제 #2
0
cairo_status_t
_cairo_scaled_font_show_glyphs (cairo_scaled_font_t    *scaled_font,
				cairo_operator_t        operator,
				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,
				cairo_glyph_t          *glyphs,
				int                     num_glyphs)
{
    cairo_status_t status;

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

    status = _cairo_surface_show_glyphs (scaled_font, operator, pattern, 
					 surface,
					 source_x, source_y,
					 dest_x, dest_y,
					 width, height,
					 glyphs, num_glyphs);
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
	return status;

    /* Surface display routine either does not exist or failed. */
    return scaled_font->backend->show_glyphs (scaled_font, operator, pattern, 
					      surface,
					      source_x, source_y,
					      dest_x, dest_y,
					      width, height,
					      glyphs, num_glyphs);
}
cairo_int_status_t
_cairo_meta_surface_replay (cairo_surface_t *surface,
			    cairo_surface_t *target)
{
    cairo_meta_surface_t *meta;
    cairo_command_t *command, **elements;
    int i, num_elements;
    cairo_int_status_t status;
    cairo_traps_t traps;
    cairo_clip_t clip;

    meta = (cairo_meta_surface_t *) surface;
    status = CAIRO_STATUS_SUCCESS;

    _cairo_clip_init (&clip, target);    

    num_elements = meta->commands.num_elements;
    elements = (cairo_command_t **) meta->commands.elements;
    for (i = 0; i < num_elements; i++) {
	command = elements[i];
	switch (command->type) {
	case CAIRO_COMMAND_COMPOSITE:
	    status = _cairo_surface_set_clip (target, &clip);
	    if (status)
		break;

	    status = _cairo_surface_composite
		(command->composite.operator,
		 &command->composite.src_pattern.base,
		 command->composite.mask_pattern_pointer,
		 target,
		 command->composite.src_x,
		 command->composite.src_y,
		 command->composite.mask_x,
		 command->composite.mask_y,
		 command->composite.dst_x,
		 command->composite.dst_y,
		 command->composite.width,
		 command->composite.height);
	    break;

	case CAIRO_COMMAND_FILL_RECTANGLES:
	    status = _cairo_surface_set_clip (target, &clip);
	    if (status)
		break;

	    status = _cairo_surface_fill_rectangles
		(target,
		 command->fill_rectangles.operator,
		 &command->fill_rectangles.color,
		 command->fill_rectangles.rects,
		 command->fill_rectangles.num_rects);
	    break;

	case CAIRO_COMMAND_COMPOSITE_TRAPEZOIDS:
	    status = _cairo_surface_set_clip (target, &clip);
	    if (status)
		break;

	    status = _cairo_surface_composite_trapezoids
		(command->composite_trapezoids.operator,
		 &command->composite_trapezoids.pattern.base,
		 target,
		 command->composite_trapezoids.antialias,
		 command->composite_trapezoids.x_src,
		 command->composite_trapezoids.y_src,
		 command->composite_trapezoids.x_dst,
		 command->composite_trapezoids.y_dst,
		 command->composite_trapezoids.width,
		 command->composite_trapezoids.height,
		 command->composite_trapezoids.traps,
		 command->composite_trapezoids.num_traps);
	    break;

	case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
	    /* XXX Meta surface clipping is broken and requires some
	     * cairo-gstate.c rewriting.  Work around it for now. */
	    if (command->intersect_clip_path.path_pointer == NULL)
		status = _cairo_clip_reset (&clip);
	    else
		status = _cairo_clip_clip (&clip,
					   command->intersect_clip_path.path_pointer,
					   command->intersect_clip_path.fill_rule,
					   command->intersect_clip_path.tolerance,
					   command->intersect_clip_path.antialias,
					   target);
	    break;

	case CAIRO_COMMAND_SHOW_GLYPHS:
	    status = _cairo_surface_set_clip (target, &clip);
	    if (status)
		break;

	    status = _cairo_surface_show_glyphs
		(command->show_glyphs.scaled_font,
		 command->show_glyphs.operator,
		 &command->show_glyphs.pattern.base,
		 target,
		 command->show_glyphs.source_x,
		 command->show_glyphs.source_y,
		 command->show_glyphs.dest_x,
		 command->show_glyphs.dest_y,
		 command->show_glyphs.width,
		 command->show_glyphs.height,
		 command->show_glyphs.glyphs,
		 command->show_glyphs.num_glyphs);
	    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
		break;
	    
	    status = (*command->show_glyphs.scaled_font->backend->
		      show_glyphs) (command->show_glyphs.scaled_font,
				    command->show_glyphs.operator,
				    &command->show_glyphs.pattern.base,
				    target,
				    command->show_glyphs.source_x,
				    command->show_glyphs.source_y,
				    command->show_glyphs.dest_x,
				    command->show_glyphs.dest_y,
				    command->show_glyphs.width,
				    command->show_glyphs.height,
				    command->show_glyphs.glyphs,
				    command->show_glyphs.num_glyphs);

	    break;

	case CAIRO_COMMAND_FILL_PATH:
	    status = _cairo_surface_set_clip (target, &clip);
	    if (status)
		break;

	    status = _cairo_surface_fill_path (command->fill_path.operator,
					       &command->fill_path.pattern.base,
					       target,
					       &command->fill_path.path,
					       command->fill_path.fill_rule,
					       command->fill_path.tolerance);
	    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
		break;

	    _cairo_traps_init (&traps);

	    status = _cairo_path_fixed_fill_to_traps (&command->fill_path.path,
						      command->fill_path.fill_rule,
						      command->fill_path.tolerance,
						      &traps);
	    if (status) {
		_cairo_traps_fini (&traps);
		break;
	    }

	    status = _cairo_surface_clip_and_composite_trapezoids (&command->fill_path.pattern.base,
								   command->fill_path.operator,
								   target,
								   &traps,
								   &clip,
								   command->fill_path.antialias);

	    _cairo_traps_fini (&traps);
	    break;

	default:
	    ASSERT_NOT_REACHED;
	}

	if (status)
	    break;
    }

    _cairo_clip_fini (&clip);

    return status;
}