static cairo_int_status_t _paint_page (cairo_paginated_surface_t *surface) { cairo_surface_t *analysis; cairo_surface_t *image; cairo_pattern_t *pattern; cairo_status_t status; analysis = _cairo_analysis_surface_create (surface->target, surface->width, surface->height); if (analysis == NULL) return CAIRO_STATUS_NO_MEMORY; surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE); status = _cairo_meta_surface_replay (surface->meta, analysis); surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER); if (status || analysis->status) { if (status == CAIRO_STATUS_SUCCESS) status = analysis->status; cairo_surface_destroy (analysis); return status; } if (_cairo_analysis_surface_has_unsupported (analysis)) { double x_scale = surface->base.x_fallback_resolution / 72.0; double y_scale = surface->base.y_fallback_resolution / 72.0; cairo_matrix_t matrix; image = _cairo_paginated_surface_create_image_surface (surface, surface->width * x_scale, surface->height * y_scale); _cairo_surface_set_device_scale (image, x_scale, y_scale); status = _cairo_meta_surface_replay (surface->meta, image); if (status) goto CLEANUP_IMAGE; pattern = cairo_pattern_create_for_surface (image); cairo_matrix_init_scale (&matrix, x_scale, y_scale); cairo_pattern_set_matrix (pattern, &matrix); status = _cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern); cairo_pattern_destroy (pattern); CLEANUP_IMAGE: cairo_surface_destroy (image); } else { status = _cairo_meta_surface_replay (surface->meta, surface->target); } cairo_surface_destroy (analysis); return status; }
static cairo_status_t _cairo_paginated_surface_acquire_source_image (void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra) { cairo_paginated_surface_t *surface = abstract_surface; cairo_surface_t *image; cairo_status_t status; cairo_rectangle_int_t extents; status = _cairo_surface_get_extents (surface->target, &extents); if (status) return status; image = _cairo_paginated_surface_create_image_surface (surface, extents.width, extents.height); status = _cairo_meta_surface_replay (surface->meta, image); if (status) { cairo_surface_destroy (image); return status; } *image_out = (cairo_image_surface_t*) image; *image_extra = NULL; return CAIRO_STATUS_SUCCESS; }
cairo_status_t _cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface, unsigned long glyph_index) { cairo_type3_glyph_surface_t *surface = abstract_surface; cairo_scaled_glyph_t *scaled_glyph; cairo_status_t status, status2; cairo_output_stream_t *null_stream; null_stream = _cairo_null_stream_create (); _cairo_type3_glyph_surface_set_stream (surface, null_stream); _cairo_scaled_font_freeze_cache (surface->scaled_font); status = _cairo_scaled_glyph_lookup (surface->scaled_font, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS | CAIRO_SCALED_GLYPH_INFO_META_SURFACE, &scaled_glyph); if (_cairo_status_is_error (status)) goto cleanup; if (status == CAIRO_INT_STATUS_UNSUPPORTED) { status = CAIRO_STATUS_SUCCESS; goto cleanup; } status = _cairo_meta_surface_replay (scaled_glyph->meta_surface, &surface->base); if (status) goto cleanup; status2 = _cairo_pdf_operators_flush (&surface->pdf_operators); if (status == CAIRO_STATUS_SUCCESS) status = status2; if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) status = CAIRO_STATUS_SUCCESS; cleanup: _cairo_scaled_font_thaw_cache (surface->scaled_font); status2 = _cairo_output_stream_destroy (null_stream); if (status == CAIRO_STATUS_SUCCESS) status = status2; return status; }
static cairo_int_status_t _paint_fallback_image (cairo_paginated_surface_t *surface, cairo_box_int_t *box) { double x_scale = surface->base.x_fallback_resolution / surface->target->x_resolution; double y_scale = surface->base.y_fallback_resolution / surface->target->y_resolution; cairo_matrix_t matrix; int x, y, width, height; cairo_status_t status; cairo_surface_t *image; cairo_pattern_t *pattern; x = box->p1.x; y = box->p1.y; width = box->p2.x - x; height = box->p2.y - y; 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_meta_surface_replay (surface->meta, image); if (status) goto CLEANUP_IMAGE; pattern = cairo_pattern_create_for_surface (image); cairo_matrix_init (&matrix, x_scale, 0, 0, y_scale, -x*x_scale, -y*y_scale); cairo_pattern_set_matrix (pattern, &matrix); status = _cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern); cairo_pattern_destroy (pattern); CLEANUP_IMAGE: cairo_surface_destroy (image); return status; }
static cairo_surface_t * _cairo_paginated_surface_snapshot (void *abstract_other) { cairo_status_t status; cairo_paginated_surface_t *other = abstract_other; /* XXX: Just making a snapshot of other->meta is what we really * want. But this currently triggers a bug somewhere (the "mask" * test from the test suite segfaults). * * For now, we'll create a new image surface and replay onto * that. It would be tempting to replay into other->image and then * return a snapshot of that, but that will cause the self-copy * test to fail, (since our replay will be affected by a clip that * should not have any effect on the use of the resulting snapshot * as a source). */ #if 0 return _cairo_surface_snapshot (other->meta); #else cairo_rectangle_int16_t extents; cairo_surface_t *surface; status = _cairo_surface_get_extents (other->target, &extents); if (status) return (cairo_surface_t*) &_cairo_surface_nil; surface = _cairo_paginated_surface_create_image_surface (other, extents.width, extents.height); status = _cairo_meta_surface_replay (other->meta, surface); if (status) { cairo_surface_destroy (surface); surface = (cairo_surface_t*) &_cairo_surface_nil; } return surface; #endif }
static cairo_status_t _cairo_meta_surface_acquire_source_image (void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra) { cairo_status_t status; cairo_meta_surface_t *surface = abstract_surface; cairo_surface_t *image; image = _cairo_image_surface_create_with_content (surface->content, surface->width_pixels, surface->height_pixels); status = _cairo_meta_surface_replay (&surface->base, image); if (status) { cairo_surface_destroy (image); return status; } *image_out = (cairo_image_surface_t *) image; *image_extra = NULL; return status; }
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; }
cairo_status_t _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface, cairo_output_stream_t *stream, unsigned long glyph_index, cairo_box_t *bbox, double *width) { cairo_type3_glyph_surface_t *surface = abstract_surface; cairo_scaled_glyph_t *scaled_glyph; cairo_status_t status, status2; double x_advance, y_advance; cairo_output_stream_t *mem_stream; cairo_matrix_t font_matrix_inverse; _cairo_type3_glyph_surface_set_stream (surface, stream); status = _cairo_scaled_glyph_lookup (surface->scaled_font, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS | CAIRO_SCALED_GLYPH_INFO_META_SURFACE, &scaled_glyph); if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) return status; if (status == CAIRO_INT_STATUS_UNSUPPORTED) { status = _cairo_scaled_glyph_lookup (surface->scaled_font, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS, &scaled_glyph); if (status) return status; status = CAIRO_INT_STATUS_IMAGE_FALLBACK; } x_advance = scaled_glyph->metrics.x_advance; y_advance = scaled_glyph->metrics.y_advance; font_matrix_inverse = surface->scaled_font->font_matrix; status2 = cairo_matrix_invert (&font_matrix_inverse); /* The invertability of font_matrix is tested in * pdf_operators_show_glyphs before any glyphs are mappped to the * subset. */ assert (status2 == CAIRO_STATUS_SUCCESS); cairo_matrix_transform_distance (&font_matrix_inverse, &x_advance, &y_advance); *width = x_advance; *bbox = scaled_glyph->bbox; _cairo_matrix_transform_bounding_box_fixed (&surface->scaled_font->scale_inverse, bbox, NULL); _cairo_output_stream_printf (surface->stream, "%f 0 %f %f %f %f d1\n", x_advance, _cairo_fixed_to_double (bbox->p1.x), - _cairo_fixed_to_double (bbox->p2.y), _cairo_fixed_to_double (bbox->p2.x), - _cairo_fixed_to_double (bbox->p1.y)); if (status == CAIRO_STATUS_SUCCESS) { mem_stream = _cairo_memory_stream_create (); _cairo_type3_glyph_surface_set_stream (surface, mem_stream); _cairo_output_stream_printf (surface->stream, "q\n"); status = _cairo_meta_surface_replay (scaled_glyph->meta_surface, &surface->base); status = _cairo_pdf_operators_flush (&surface->pdf_operators); if (status) return status; _cairo_output_stream_printf (surface->stream, "Q\n"); _cairo_type3_glyph_surface_set_stream (surface, stream); if (status == CAIRO_STATUS_SUCCESS) _cairo_memory_stream_copy (mem_stream, stream); status2 = _cairo_output_stream_destroy (mem_stream); if (status2) return status2; } if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) status = _cairo_type3_glyph_surface_emit_fallback_image (surface, glyph_index); return status; }