コード例 #1
0
static cairo_status_t
_recording_surface_get_ink_bbox (cairo_recording_surface_t *surface,
				 cairo_box_t *bbox,
				 const cairo_matrix_t *transform)
{
    cairo_surface_t *null_surface;
    cairo_surface_t *analysis_surface;
    cairo_status_t status;

    null_surface = _cairo_null_surface_create (surface->content);
    analysis_surface = _cairo_analysis_surface_create (null_surface);
    cairo_surface_destroy (null_surface);

    status = analysis_surface->status;
    if (unlikely (status))
	return status;

    if (transform != NULL)
	_cairo_analysis_surface_set_ctm (analysis_surface, transform);

    status = _cairo_recording_surface_replay (&surface->base, analysis_surface);
    _cairo_analysis_surface_get_bounding_box (analysis_surface, bbox);
    cairo_surface_destroy (analysis_surface);

    return status;
}
コード例 #2
0
ファイル: cairo-user-font.c プロジェクト: soubok/libset
static cairo_int_status_t
_cairo_user_scaled_glyph_init (void			 *abstract_font,
			       cairo_scaled_glyph_t	 *scaled_glyph,
			       cairo_scaled_glyph_info_t  info)
{
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
    cairo_user_scaled_font_t *scaled_font = abstract_font;
    cairo_surface_t *meta_surface = scaled_glyph->meta_surface;

    if (!scaled_glyph->meta_surface) {
	cairo_user_font_face_t *face =
	    (cairo_user_font_face_t *) scaled_font->base.font_face;
	cairo_text_extents_t extents = scaled_font->default_glyph_extents;
	cairo_t *cr;

	cr = _cairo_user_scaled_font_create_meta_context (scaled_font);

	if (face->scaled_font_methods.render_glyph)
	    status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
							     _cairo_scaled_glyph_index(scaled_glyph),
							     cr, &extents);
	else
	    status = CAIRO_STATUS_USER_FONT_ERROR;

	if (status == CAIRO_STATUS_SUCCESS)
	    status = cairo_status (cr);

	meta_surface = cairo_surface_reference (cairo_get_target (cr));

	cairo_destroy (cr);

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

	_cairo_scaled_glyph_set_meta_surface (scaled_glyph,
					      &scaled_font->base,
					      meta_surface);


	/* set metrics */

	if (extents.width == 0.) {
	    /* Compute extents.x/y/width/height from meta_surface, in font space */

	    cairo_box_t bbox;
	    double x1, y1, x2, y2;
	    double x_scale, y_scale;
	    cairo_surface_t *null_surface;
	    cairo_surface_t *analysis_surface;

	    null_surface = _cairo_null_surface_create (cairo_surface_get_content (meta_surface));
	    analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
	    cairo_surface_destroy (null_surface);

	    _cairo_analysis_surface_set_ctm (analysis_surface, &scaled_font->extent_scale);
	    status = _cairo_meta_surface_replay (meta_surface, analysis_surface);
	    _cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
	    cairo_surface_destroy (analysis_surface);

	    if (status)
		return status;

	    _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);

	    x_scale = scaled_font->extent_x_scale;
	    y_scale = scaled_font->extent_y_scale;
	    extents.x_bearing = x1 * x_scale;
	    extents.y_bearing = y1 * y_scale;
	    extents.width     = (x2 - x1) * x_scale;
	    extents.height    = (y2 - y1) * y_scale;
	}

	if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
	    extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale;
	    extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale;
	}

	_cairo_scaled_glyph_set_metrics (scaled_glyph,
					 &scaled_font->base,
					 &extents);
    }

    if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
	cairo_surface_t	*surface;
	cairo_status_t status = CAIRO_STATUS_SUCCESS;
	cairo_format_t format;
	int width, height;

	/* TODO
	 * extend the glyph cache to support argb glyphs.
	 * need to figure out the semantics and interaction with subpixel
	 * rendering first.
	 */

	width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
	  _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
	height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
	  _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);

	switch (scaled_font->base.options.antialias) {
	default:
	case CAIRO_ANTIALIAS_DEFAULT:
	case CAIRO_ANTIALIAS_GRAY:	format = CAIRO_FORMAT_A8;	break;
	case CAIRO_ANTIALIAS_NONE:	format = CAIRO_FORMAT_A1;	break;
	case CAIRO_ANTIALIAS_SUBPIXEL:	format = CAIRO_FORMAT_ARGB32;	break;
	}
	surface = cairo_image_surface_create (format, width, height);

	cairo_surface_set_device_offset (surface,
	                                 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
	                                 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
	status = _cairo_meta_surface_replay (meta_surface, surface);

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

	_cairo_scaled_glyph_set_surface (scaled_glyph,
					 &scaled_font->base,
					 (cairo_image_surface_t *) surface);
    }

    if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
	cairo_path_fixed_t *path = _cairo_path_fixed_create ();
	if (!path)
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);

	status = _cairo_meta_surface_get_path (meta_surface, path);

	if (status) {
	    _cairo_path_fixed_destroy (path);
	    return status;
	}

	_cairo_scaled_glyph_set_path (scaled_glyph,
				      &scaled_font->base,
				      path);
    }

    return status;
}