Merge branch 'pdf-color-fonts' into 'master'
PDF Type 3 color fonts See merge request cairo/cairo!434
|
|
@ -831,6 +831,14 @@ _cairo_analysis_surface_tag (void *abstract_surface,
|
|||
return backend_status;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_analysis_surface_supports_color_glyph (void *abstract_surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph_index)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_analysis_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
|
||||
|
||||
|
|
@ -865,7 +873,8 @@ static const cairo_surface_backend_t cairo_analysis_surface_backend = {
|
|||
_cairo_analysis_surface_has_show_text_glyphs,
|
||||
_cairo_analysis_surface_show_text_glyphs,
|
||||
NULL, /* get_supported_mime_types */
|
||||
_cairo_analysis_surface_tag
|
||||
_cairo_analysis_surface_tag,
|
||||
_cairo_analysis_surface_supports_color_glyph
|
||||
};
|
||||
|
||||
cairo_surface_t *
|
||||
|
|
|
|||
|
|
@ -336,3 +336,10 @@ _cairo_hash_bytes (uintptr_t hash,
|
|||
hash = ((hash << 5) + hash) + *bytes++;
|
||||
return hash;
|
||||
}
|
||||
|
||||
uintptr_t
|
||||
_cairo_hash_uintptr (uintptr_t hash,
|
||||
uintptr_t u)
|
||||
{
|
||||
return _cairo_hash_bytes (hash, &u, sizeof(u));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -756,6 +756,14 @@ _cairo_paginated_surface_tag (void *abstract_surface,
|
|||
begin, tag_name, attributes);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_paginated_surface_supports_color_glyph (void *abstract_surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph_index)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_paginated_surface_snapshot (void *abstract_other)
|
||||
{
|
||||
|
|
@ -811,4 +819,5 @@ static const cairo_surface_backend_t cairo_paginated_surface_backend = {
|
|||
_cairo_paginated_surface_show_text_glyphs,
|
||||
_cairo_paginated_surface_get_supported_mime_types,
|
||||
_cairo_paginated_surface_tag,
|
||||
_cairo_paginated_surface_supports_color_glyph,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -258,6 +258,13 @@ typedef struct _cairo_pdf_interchange {
|
|||
|
||||
} cairo_pdf_interchange_t;
|
||||
|
||||
typedef struct _cairo_pdf_color_glyph {
|
||||
cairo_hash_entry_t base;
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
unsigned long glyph_index;
|
||||
cairo_bool_t supported;
|
||||
} cairo_pdf_color_glyph_t;
|
||||
|
||||
/* pdf surface data */
|
||||
|
||||
typedef struct _cairo_pdf_surface cairo_pdf_surface_t;
|
||||
|
|
@ -288,6 +295,7 @@ struct _cairo_pdf_surface {
|
|||
cairo_array_t knockout_group;
|
||||
cairo_array_t jbig2_global;
|
||||
cairo_array_t page_heights;
|
||||
cairo_hash_table_t *color_glyphs;
|
||||
|
||||
cairo_scaled_font_subsets_t *font_subsets;
|
||||
cairo_array_t fonts;
|
||||
|
|
@ -335,11 +343,13 @@ struct _cairo_pdf_surface {
|
|||
|
||||
cairo_pdf_operators_t pdf_operators;
|
||||
cairo_paginated_mode_t paginated_mode;
|
||||
cairo_bool_t type3_replay;
|
||||
cairo_bool_t select_pattern_gstate_saved;
|
||||
|
||||
cairo_bool_t force_fallbacks;
|
||||
|
||||
cairo_operator_t current_operator;
|
||||
cairo_bool_t reset_gs_required;
|
||||
cairo_bool_t current_pattern_is_solid_color;
|
||||
cairo_bool_t current_color_is_stroke;
|
||||
double current_color_red;
|
||||
|
|
|
|||
|
|
@ -280,7 +280,8 @@ typedef struct _cairo_pdf_alpha_linear_function {
|
|||
} cairo_pdf_alpha_linear_function_t;
|
||||
|
||||
static void
|
||||
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
|
||||
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface,
|
||||
cairo_bool_t clear_doc_surfaces);
|
||||
|
||||
static void
|
||||
_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group);
|
||||
|
|
@ -338,6 +339,9 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface);
|
|||
static cairo_bool_t
|
||||
_cairo_pdf_source_surface_equal (const void *key_a, const void *key_b);
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_pdf_color_glyph_equal (const void *key_a, const void *key_b);
|
||||
|
||||
static const cairo_surface_backend_t cairo_pdf_surface_backend;
|
||||
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
|
||||
|
||||
|
|
@ -485,12 +489,18 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
|
|||
goto BAIL0;
|
||||
}
|
||||
|
||||
surface->color_glyphs = _cairo_hash_table_create (_cairo_pdf_color_glyph_equal);
|
||||
if (unlikely (surface->color_glyphs == NULL)) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto BAIL1;
|
||||
}
|
||||
|
||||
_cairo_pdf_group_resources_init (&surface->resources);
|
||||
|
||||
surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
|
||||
if (! surface->font_subsets) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto BAIL1;
|
||||
goto BAIL2;
|
||||
}
|
||||
|
||||
_cairo_scaled_font_subsets_enable_latin_subset (surface->font_subsets, TRUE);
|
||||
|
|
@ -499,7 +509,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
|
|||
surface->pages_resource = _cairo_pdf_surface_new_object (surface);
|
||||
if (surface->pages_resource.id == 0) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto BAIL2;
|
||||
goto BAIL3;
|
||||
}
|
||||
|
||||
surface->struct_tree_root.id = 0;
|
||||
|
|
@ -515,11 +525,13 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
|
|||
_cairo_array_init (&surface->object_stream.objects, sizeof (cairo_xref_stream_object_t));
|
||||
|
||||
surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
|
||||
surface->type3_replay = FALSE;
|
||||
|
||||
surface->force_fallbacks = FALSE;
|
||||
surface->select_pattern_gstate_saved = FALSE;
|
||||
surface->current_pattern_is_solid_color = FALSE;
|
||||
surface->current_operator = CAIRO_OPERATOR_OVER;
|
||||
surface->reset_gs_required = FALSE;
|
||||
surface->header_emitted = FALSE;
|
||||
|
||||
_cairo_surface_clipper_init (&surface->clipper,
|
||||
|
|
@ -537,7 +549,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
|
|||
|
||||
status = _cairo_pdf_interchange_init (surface);
|
||||
if (unlikely (status))
|
||||
goto BAIL2;
|
||||
goto BAIL3;
|
||||
|
||||
surface->page_parent_tree = -1;
|
||||
_cairo_array_init (&surface->page_annots, sizeof (cairo_pdf_resource_t));
|
||||
|
|
@ -568,8 +580,10 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
|
|||
return surface->paginated_surface;
|
||||
}
|
||||
|
||||
BAIL2:
|
||||
BAIL3:
|
||||
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
|
||||
BAIL2:
|
||||
_cairo_hash_table_destroy (surface->color_glyphs);
|
||||
BAIL1:
|
||||
_cairo_hash_table_destroy (surface->all_surfaces);
|
||||
BAIL0:
|
||||
|
|
@ -998,12 +1012,14 @@ cairo_pdf_surface_set_thumbnail_size (cairo_surface_t *surface,
|
|||
}
|
||||
|
||||
static void
|
||||
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
|
||||
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface,
|
||||
cairo_bool_t clear_doc_surfaces)
|
||||
{
|
||||
int i, size;
|
||||
cairo_pdf_pattern_t *pattern;
|
||||
cairo_pdf_source_surface_t *src_surface;
|
||||
cairo_pdf_smask_group_t *group;
|
||||
cairo_pdf_source_surface_t doc_surface;
|
||||
|
||||
size = _cairo_array_num_elements (&surface->page_patterns);
|
||||
for (i = 0; i < size; i++) {
|
||||
|
|
@ -1037,6 +1053,21 @@ _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
|
|||
if (surface->thumbnail_image)
|
||||
cairo_surface_destroy (&surface->thumbnail_image->base);
|
||||
surface->thumbnail_image = NULL;
|
||||
|
||||
if (clear_doc_surfaces) {
|
||||
size = _cairo_array_num_elements (&surface->doc_surfaces);
|
||||
for (i = 0; i < size; i++) {
|
||||
_cairo_array_copy_element (&surface->doc_surfaces, i, &doc_surface);
|
||||
if (doc_surface.type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
|
||||
cairo_pattern_destroy (doc_surface.raster_pattern);
|
||||
} else {
|
||||
if (_cairo_surface_is_recording (doc_surface.surface) && doc_surface.region_id != 0)
|
||||
_cairo_recording_surface_region_array_remove (doc_surface.surface, doc_surface.region_id);
|
||||
cairo_surface_destroy (doc_surface.surface);
|
||||
}
|
||||
}
|
||||
_cairo_array_truncate (&surface->doc_surfaces, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1443,6 +1474,25 @@ _cairo_pdf_source_surface_init_key (cairo_pdf_source_surface_entry_t *key)
|
|||
}
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_pdf_color_glyph_equal (const void *key_a, const void *key_b)
|
||||
{
|
||||
const cairo_pdf_color_glyph_t *a = key_a;
|
||||
const cairo_pdf_color_glyph_t *b = key_b;
|
||||
|
||||
if (a->scaled_font != b->scaled_font)
|
||||
return FALSE;
|
||||
|
||||
return (a->glyph_index == b->glyph_index);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_pdf_color_glyph_init_key (cairo_pdf_color_glyph_t *key)
|
||||
{
|
||||
key->base.hash = _cairo_hash_uintptr (_CAIRO_HASH_INIT_VALUE, (uintptr_t)key->scaled_font);
|
||||
key->base.hash = _cairo_hash_uintptr (key->base.hash, key->glyph_index);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_acquire_source_image_from_pattern (cairo_pdf_surface_t *surface,
|
||||
const cairo_pattern_t *pattern,
|
||||
|
|
@ -2131,7 +2181,7 @@ _cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface,
|
|||
surface->group_stream.bbox = *bbox;
|
||||
|
||||
/* Reset gstate */
|
||||
_cairo_output_stream_printf (surface->output, "/gs0 gs\n");
|
||||
surface->reset_gs_required = TRUE;
|
||||
surface->current_pattern_is_solid_color = FALSE;
|
||||
surface->current_operator = CAIRO_OPERATOR_OVER;
|
||||
_cairo_pdf_operators_reset (&surface->pdf_operators);
|
||||
|
|
@ -2488,6 +2538,18 @@ _cairo_pdf_source_surface_entry_pluck (void *entry, void *closure)
|
|||
free (surface_entry);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_pdf_color_glyph_pluck (void *entry, void *closure)
|
||||
{
|
||||
cairo_pdf_color_glyph_t *glyph_entry = entry;
|
||||
cairo_hash_table_t *patterns = closure;
|
||||
|
||||
_cairo_hash_table_remove (patterns, &glyph_entry->base);
|
||||
cairo_scaled_font_destroy (glyph_entry->scaled_font);
|
||||
|
||||
free (glyph_entry);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_surface_finish (void *abstract_surface)
|
||||
{
|
||||
|
|
@ -2496,7 +2558,6 @@ _cairo_pdf_surface_finish (void *abstract_surface)
|
|||
cairo_pdf_resource_t catalog;
|
||||
cairo_status_t status, status2;
|
||||
int size, i;
|
||||
cairo_pdf_source_surface_t doc_surface;
|
||||
cairo_pdf_jbig2_global_t *global;
|
||||
char *label;
|
||||
cairo_pdf_resource_t xref_res;
|
||||
|
|
@ -2505,7 +2566,7 @@ _cairo_pdf_surface_finish (void *abstract_surface)
|
|||
if (surface->base.status != CAIRO_STATUS_SUCCESS)
|
||||
goto CLEANUP;
|
||||
|
||||
_cairo_pdf_surface_clear (surface);
|
||||
_cairo_pdf_surface_clear (surface, FALSE);
|
||||
|
||||
status = _cairo_pdf_surface_open_object_stream (surface);
|
||||
if (unlikely (status))
|
||||
|
|
@ -2514,10 +2575,17 @@ _cairo_pdf_surface_finish (void *abstract_surface)
|
|||
/* Emit unbounded surfaces */
|
||||
_cairo_pdf_surface_write_patterns_and_smask_groups (surface, TRUE);
|
||||
|
||||
_cairo_pdf_surface_clear (surface, TRUE);
|
||||
|
||||
status = surface->base.status;
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = _cairo_pdf_surface_emit_font_subsets (surface);
|
||||
|
||||
/* Emit any new patterns or surfaces created by the Type 3 font subset. */
|
||||
_cairo_pdf_surface_write_patterns_and_smask_groups (surface, TRUE);
|
||||
|
||||
_cairo_pdf_surface_clear (surface, TRUE);
|
||||
|
||||
status = _cairo_pdf_surface_write_pages (surface);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
|
@ -2608,17 +2676,6 @@ _cairo_pdf_surface_finish (void *abstract_surface)
|
|||
_cairo_array_fini (&surface->page_surfaces);
|
||||
_cairo_array_fini (&surface->object_stream.objects);
|
||||
|
||||
size = _cairo_array_num_elements (&surface->doc_surfaces);
|
||||
for (i = 0; i < size; i++) {
|
||||
_cairo_array_copy_element (&surface->doc_surfaces, i, &doc_surface);
|
||||
if (doc_surface.type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
|
||||
cairo_pattern_destroy (doc_surface.raster_pattern);
|
||||
} else {
|
||||
if (_cairo_surface_is_recording (doc_surface.surface) && doc_surface.region_id != 0)
|
||||
_cairo_recording_surface_region_array_remove (doc_surface.surface, doc_surface.region_id);
|
||||
cairo_surface_destroy (doc_surface.surface);
|
||||
}
|
||||
}
|
||||
_cairo_array_fini (&surface->doc_surfaces);
|
||||
_cairo_hash_table_foreach (surface->all_surfaces,
|
||||
_cairo_pdf_source_surface_entry_pluck,
|
||||
|
|
@ -2630,6 +2687,11 @@ _cairo_pdf_surface_finish (void *abstract_surface)
|
|||
_cairo_array_fini (&surface->page_annots);
|
||||
_cairo_array_fini (&surface->forward_links);
|
||||
|
||||
_cairo_hash_table_foreach (surface->color_glyphs,
|
||||
_cairo_pdf_color_glyph_pluck,
|
||||
surface->color_glyphs);
|
||||
_cairo_hash_table_destroy (surface->color_glyphs);
|
||||
|
||||
if (surface->font_subsets) {
|
||||
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
|
||||
surface->font_subsets = NULL;
|
||||
|
|
@ -3727,7 +3789,7 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
|
|||
goto err;
|
||||
|
||||
/* Reset gstate */
|
||||
_cairo_output_stream_printf (surface->output, "/gs0 gs\n");
|
||||
surface->reset_gs_required = TRUE;
|
||||
|
||||
if (source->content == CAIRO_CONTENT_COLOR) {
|
||||
status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
|
||||
|
|
@ -5080,6 +5142,7 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
|
|||
alpha != 1.0, /* need_transp_group */
|
||||
extents,
|
||||
smask_res,
|
||||
|
||||
&pdf_source,
|
||||
&x_offset,
|
||||
&y_offset,
|
||||
|
|
@ -5267,6 +5330,11 @@ _cairo_pdf_surface_select_operator (cairo_pdf_surface_t *surface,
|
|||
{
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (surface->reset_gs_required) {
|
||||
_cairo_output_stream_printf (surface->output, "/gs0 gs\n");
|
||||
surface->reset_gs_required = FALSE;
|
||||
}
|
||||
|
||||
if (op == surface->current_operator)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
|
@ -5430,7 +5498,7 @@ _cairo_pdf_surface_show_page (void *abstract_surface)
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_pdf_surface_clear (surface);
|
||||
_cairo_pdf_surface_clear (surface, FALSE);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -6479,6 +6547,208 @@ _cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
|
|||
return _cairo_output_stream_get_status (stream);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
cairo_pdf_surface_emit_color_glyph (cairo_pdf_surface_t *surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph_index,
|
||||
cairo_box_t *bbox,
|
||||
double *width)
|
||||
{
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_matrix_t mat;
|
||||
cairo_int_status_t status;
|
||||
double x_advance, y_advance;
|
||||
cairo_matrix_t font_matrix_inverse;
|
||||
cairo_surface_t *analysis;
|
||||
cairo_rectangle_int_t old_surface_extents;
|
||||
cairo_bool_t old_surface_bounded;
|
||||
cairo_paginated_mode_t old_paginated_mode;
|
||||
cairo_surface_t *glyph_surface = NULL;
|
||||
unsigned int regions_id = 0;
|
||||
cairo_surface_pattern_t surface_pattern;
|
||||
|
||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
glyph_index,
|
||||
CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE,
|
||||
NULL, /* foreground color */
|
||||
&scaled_glyph);
|
||||
if (status == CAIRO_INT_STATUS_SUCCESS)
|
||||
glyph_surface = cairo_surface_reference (scaled_glyph->recording_surface);
|
||||
|
||||
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
analysis = _cairo_analysis_surface_create (&surface->base, TRUE);
|
||||
if (unlikely (analysis->status)) {
|
||||
status = _cairo_surface_set_error (&surface->base, analysis->status);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
extents.x = _cairo_fixed_to_double (scaled_glyph->bbox.p1.x);
|
||||
extents.y = _cairo_fixed_to_double (scaled_glyph->bbox.p1.y);
|
||||
extents.width = _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) - extents.x;
|
||||
extents.height = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y) - extents.y;
|
||||
|
||||
old_surface_extents = surface->surface_extents;
|
||||
old_surface_bounded = surface->surface_bounded;
|
||||
old_paginated_mode = surface->paginated_mode;
|
||||
surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
|
||||
surface->type3_replay = TRUE;
|
||||
surface->surface_extents = extents;
|
||||
surface->surface_bounded = TRUE;
|
||||
|
||||
status = _cairo_recording_surface_region_array_attach (glyph_surface, ®ions_id);
|
||||
if (status)
|
||||
goto cleanup;
|
||||
|
||||
status = _cairo_recording_surface_replay_and_create_regions (glyph_surface, regions_id,
|
||||
NULL, analysis, TRUE);
|
||||
if (status)
|
||||
goto cleanup;
|
||||
|
||||
surface->surface_extents = old_surface_extents;
|
||||
surface->surface_bounded = old_surface_bounded;
|
||||
surface->paginated_mode = old_paginated_mode;
|
||||
surface->type3_replay = FALSE;
|
||||
|
||||
if (status == CAIRO_INT_STATUS_SUCCESS &&
|
||||
_cairo_analysis_surface_has_unsupported (analysis))
|
||||
{
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
cairo_surface_destroy (analysis);
|
||||
if (status)
|
||||
goto cleanup;
|
||||
|
||||
_cairo_pattern_init_for_surface (&surface_pattern, glyph_surface);
|
||||
surface_pattern.region_array_id = regions_id;
|
||||
|
||||
cairo_matrix_init_identity (&mat);
|
||||
cairo_matrix_multiply (&mat, &mat, &scaled_font->scale_inverse);
|
||||
|
||||
/* transform glyph extents to operation space */
|
||||
cairo_box_t box;
|
||||
_cairo_box_from_rectangle (&box, &extents);
|
||||
_cairo_matrix_transform_bounding_box_fixed (&mat, &box, NULL);
|
||||
_cairo_box_round_to_rectangle (&box, &extents);
|
||||
|
||||
status = cairo_matrix_invert (&mat);
|
||||
if (status) {
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cairo_pattern_set_matrix (&surface_pattern.base, &mat);
|
||||
|
||||
x_advance = scaled_glyph->metrics.x_advance;
|
||||
y_advance = scaled_glyph->metrics.y_advance;
|
||||
font_matrix_inverse = scaled_font->font_matrix;
|
||||
status = cairo_matrix_invert (&font_matrix_inverse);
|
||||
if (status) {
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cairo_matrix_transform_distance (&font_matrix_inverse, &x_advance, &y_advance);
|
||||
*width = x_advance;
|
||||
|
||||
*bbox = scaled_glyph->bbox;
|
||||
_cairo_matrix_transform_bounding_box_fixed (&scaled_font->scale_inverse,
|
||||
bbox, NULL);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%f 0 d0\n",
|
||||
x_advance);
|
||||
|
||||
_cairo_pdf_surface_paint_surface_pattern (surface,
|
||||
CAIRO_OPERATOR_OVER,
|
||||
&surface_pattern.base,
|
||||
&extents,
|
||||
1.0, /* alpha */
|
||||
NULL, /* smask_res */
|
||||
FALSE); /* mask */
|
||||
|
||||
cleanup:
|
||||
cairo_surface_destroy (glyph_surface);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
cairo_pdf_surface_emit_color_glyph_image (cairo_pdf_surface_t *surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph_index,
|
||||
cairo_box_t *bbox,
|
||||
double *width)
|
||||
{
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_pattern_t *image_pattern;
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_matrix_t mat;
|
||||
cairo_int_status_t status, status2;
|
||||
double x_advance, y_advance;
|
||||
cairo_matrix_t font_matrix_inverse;
|
||||
|
||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
glyph_index,
|
||||
CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE,
|
||||
NULL, /* foreground color */
|
||||
&scaled_glyph);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
extents.x = _cairo_fixed_to_double (scaled_glyph->bbox.p1.x);
|
||||
extents.y = _cairo_fixed_to_double (scaled_glyph->bbox.p1.y);
|
||||
extents.width = _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) - extents.x;
|
||||
extents.height = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y) - extents.y;
|
||||
|
||||
image_pattern = cairo_pattern_create_for_surface (&scaled_glyph->color_surface->base);
|
||||
|
||||
cairo_matrix_init_translate (&mat, extents.x, extents.y);
|
||||
cairo_matrix_multiply (&mat, &mat, &scaled_font->scale_inverse);
|
||||
status2 = cairo_matrix_invert (&mat);
|
||||
cairo_pattern_set_matrix (image_pattern, &mat);
|
||||
|
||||
x_advance = scaled_glyph->metrics.x_advance;
|
||||
y_advance = scaled_glyph->metrics.y_advance;
|
||||
font_matrix_inverse = 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 mapped to the
|
||||
* subset. */
|
||||
assert (status2 == CAIRO_INT_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 (&scaled_font->scale_inverse,
|
||||
bbox, NULL);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%f 0 d0\n",
|
||||
x_advance);
|
||||
|
||||
_cairo_pdf_surface_paint_surface_pattern (surface,
|
||||
CAIRO_OPERATOR_OVER,
|
||||
image_pattern,
|
||||
&extents,
|
||||
1.0, /* alpha */
|
||||
NULL, /* smask_res */
|
||||
FALSE); /* mask */
|
||||
cairo_pattern_destroy (image_pattern);
|
||||
FAIL:
|
||||
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
|
|
@ -6541,6 +6811,20 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
|
|||
font_subset->glyphs[i],
|
||||
&bbox,
|
||||
&widths[i]);
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
status = cairo_pdf_surface_emit_color_glyph (surface,
|
||||
font_subset->scaled_font,
|
||||
font_subset->glyphs[i],
|
||||
&bbox,
|
||||
&widths[i]);
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
status = cairo_pdf_surface_emit_color_glyph_image (surface,
|
||||
font_subset->scaled_font,
|
||||
font_subset->glyphs[i],
|
||||
&bbox,
|
||||
&widths[i]);
|
||||
}
|
||||
}
|
||||
if (unlikely (status))
|
||||
break;
|
||||
|
||||
|
|
@ -6725,12 +7009,6 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
|
|||
status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
|
||||
_cairo_pdf_surface_emit_scaled_font_subset,
|
||||
surface);
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
||||
status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
|
||||
_cairo_pdf_surface_emit_scaled_font_subset,
|
||||
surface);
|
||||
|
||||
BAIL:
|
||||
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
|
||||
|
|
@ -7627,6 +7905,9 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
|
|||
/* The SOURCE operator is supported if the pattern is opaque or if
|
||||
* there is nothing painted underneath. */
|
||||
if (op == CAIRO_OPERATOR_SOURCE) {
|
||||
if (surface->type3_replay)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
|
||||
|
||||
|
|
@ -8762,6 +9043,13 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
|
|||
return status;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
|
||||
/* Enabling text in Type 3 fonts currently crashes cairo. Most
|
||||
* PDF viewers don't seem to suport text in Type 3 so we let
|
||||
* this go to image fallback.
|
||||
*/
|
||||
if (surface->type3_replay)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
@ -8915,6 +9203,68 @@ _cairo_pdf_surface_tag (void *abstract_surface,
|
|||
return status;
|
||||
}
|
||||
|
||||
/* The Type 3 font subset support will the embed the
|
||||
* CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE image if vector operations
|
||||
* are not supported. The only case we don't currently handle is if a
|
||||
* foreground color is used.
|
||||
*/
|
||||
static cairo_bool_t
|
||||
_cairo_pdf_surface_supports_color_glyph (void *abstract_surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph_index)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
cairo_pdf_color_glyph_t glyph_key;
|
||||
cairo_pdf_color_glyph_t *glyph_entry;
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_status_t status;
|
||||
|
||||
glyph_key.scaled_font = scaled_font;
|
||||
glyph_key.glyph_index = glyph_index;
|
||||
|
||||
_cairo_pdf_color_glyph_init_key (&glyph_key);
|
||||
glyph_entry = _cairo_hash_table_lookup (surface->color_glyphs, &glyph_key.base);
|
||||
if (glyph_entry)
|
||||
return glyph_entry->supported;
|
||||
|
||||
glyph_entry = _cairo_malloc (sizeof (cairo_pdf_color_glyph_t));
|
||||
if (glyph_entry == NULL) {
|
||||
status = _cairo_surface_set_error (&surface->base,
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
glyph_entry->scaled_font = cairo_scaled_font_reference (scaled_font);
|
||||
glyph_entry->glyph_index = glyph_index;
|
||||
_cairo_pdf_color_glyph_init_key (glyph_entry);
|
||||
|
||||
glyph_entry->supported = FALSE;
|
||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
glyph_index,
|
||||
CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE,
|
||||
NULL, /* foreground color */
|
||||
&scaled_glyph);
|
||||
if (unlikely (status))
|
||||
goto done;
|
||||
|
||||
glyph_entry->supported = !(scaled_glyph->recording_uses_foreground_color ||
|
||||
scaled_glyph->recording_uses_foreground_marker);
|
||||
|
||||
done:
|
||||
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||
|
||||
status = _cairo_hash_table_insert (surface->color_glyphs,
|
||||
&glyph_entry->base);
|
||||
if (unlikely(status)) {
|
||||
status = _cairo_surface_set_error (&surface->base,
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return glyph_entry->supported;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
|
||||
cairo_paginated_mode_t paginated_mode)
|
||||
|
|
@ -8973,6 +9323,7 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
|
|||
_cairo_pdf_surface_show_text_glyphs,
|
||||
_cairo_pdf_surface_get_supported_mime_types,
|
||||
_cairo_pdf_surface_tag,
|
||||
_cairo_pdf_surface_supports_color_glyph,
|
||||
};
|
||||
|
||||
static const cairo_paginated_surface_backend_t
|
||||
|
|
|
|||
|
|
@ -912,18 +912,11 @@ _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface)
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
|
||||
_cairo_ps_surface_emit_scaled_font_subset,
|
||||
surface);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
return _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
|
||||
_cairo_ps_surface_emit_scaled_font_subset,
|
||||
surface);
|
||||
return _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
|
||||
_cairo_ps_surface_emit_scaled_font_subset,
|
||||
surface);
|
||||
}
|
||||
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_ps_surface_emit_forms (cairo_ps_surface_t *surface)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1231,6 +1231,14 @@ _cairo_recording_surface_tag (void *abstract_surface,
|
|||
return status;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_recording_surface_supports_color_glyph (void *abstract_surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph_index)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_command_init_copy (cairo_recording_surface_t *surface,
|
||||
cairo_command_header_t *dst,
|
||||
|
|
@ -1703,6 +1711,7 @@ static const cairo_surface_backend_t cairo_recording_surface_backend = {
|
|||
_cairo_recording_surface_show_text_glyphs,
|
||||
NULL, /* get_supported_mime_types */
|
||||
_cairo_recording_surface_tag,
|
||||
_cairo_recording_surface_supports_color_glyph,
|
||||
};
|
||||
|
||||
static unsigned int
|
||||
|
|
|
|||
|
|
@ -296,41 +296,6 @@ _cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t
|
|||
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
||||
void *closure);
|
||||
|
||||
/**
|
||||
* _cairo_scaled_font_subsets_foreach_user:
|
||||
* @font_subsets: a #cairo_scaled_font_subsets_t
|
||||
* @font_subset_callback: a function to be called for each font subset
|
||||
* @closure: closure data for the callback function
|
||||
*
|
||||
* Iterate over each unique scaled font subset as created by calls to
|
||||
* _cairo_scaled_font_subsets_map_glyph(). A subset is determined by
|
||||
* unique pairs of (font_id, subset_id) as returned by
|
||||
* _cairo_scaled_font_subsets_map_glyph().
|
||||
*
|
||||
* For each subset, @font_subset_callback will be called and will be
|
||||
* provided with both a #cairo_scaled_font_subset_t object containing
|
||||
* all the glyphs in the subset as well as the value of @closure.
|
||||
*
|
||||
* The #cairo_scaled_font_subset_t object contains the scaled_font,
|
||||
* the font_id, and the subset_id corresponding to all glyphs
|
||||
* belonging to the subset. In addition, it contains an array providing
|
||||
* a mapping between subset glyph indices and the original scaled font
|
||||
* glyph indices.
|
||||
*
|
||||
* The index of the array corresponds to subset_glyph_index values
|
||||
* returned by _cairo_scaled_font_subsets_map_glyph() while the
|
||||
* values of the array correspond to the scaled_font_glyph_index
|
||||
* values passed as input to the same function.
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS if successful, or a non-zero
|
||||
* value indicating an error. Possible errors include
|
||||
* %CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_subsets_foreach_user (cairo_scaled_font_subsets_t *font_subsets,
|
||||
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
||||
void *closure);
|
||||
|
||||
/**
|
||||
* _cairo_scaled_font_subset_create_glyph_names:
|
||||
* @font_subsets: a #cairo_scaled_font_subsets_t
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ typedef enum {
|
|||
typedef enum {
|
||||
CAIRO_SUBSETS_FOREACH_UNSCALED,
|
||||
CAIRO_SUBSETS_FOREACH_SCALED,
|
||||
CAIRO_SUBSETS_FOREACH_USER
|
||||
} cairo_subsets_foreach_type_t;
|
||||
|
||||
typedef struct _cairo_sub_font {
|
||||
|
|
@ -70,7 +69,6 @@ typedef struct _cairo_sub_font {
|
|||
|
||||
cairo_bool_t is_scaled;
|
||||
cairo_bool_t is_composite;
|
||||
cairo_bool_t is_user;
|
||||
cairo_bool_t use_latin_subset;
|
||||
cairo_bool_t reserve_notdef;
|
||||
cairo_scaled_font_subsets_t *parent;
|
||||
|
|
@ -284,8 +282,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
|
|||
|
||||
sub_font->is_scaled = is_scaled;
|
||||
sub_font->is_composite = is_composite;
|
||||
sub_font->is_user = _cairo_font_face_is_user (scaled_font->font_face);
|
||||
sub_font->reserve_notdef = !sub_font->is_user;
|
||||
sub_font->reserve_notdef = !sub_font->is_scaled;
|
||||
_cairo_sub_font_init_key (sub_font, scaled_font);
|
||||
|
||||
sub_font->parent = parent;
|
||||
|
|
@ -295,7 +292,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
|
|||
sub_font->use_latin_subset = parent->use_latin_subset;
|
||||
|
||||
/* latin subsets of Type 3 and CID CFF fonts are not supported */
|
||||
if (sub_font->is_user || sub_font->is_scaled ||
|
||||
if (sub_font->is_scaled ||
|
||||
_cairo_cff_scaled_font_is_cid_cff (scaled_font) )
|
||||
{
|
||||
sub_font->use_latin_subset = FALSE;
|
||||
|
|
@ -620,12 +617,11 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
|
|||
}
|
||||
}
|
||||
|
||||
/* If glyph is in the winansi encoding and font is not a user
|
||||
/* If glyph is in the winansi encoding and font is not a scaled
|
||||
* font, put glyph in the latin subset. */
|
||||
is_latin = FALSE;
|
||||
latin_character = -1;
|
||||
if (sub_font->use_latin_subset &&
|
||||
(! _cairo_font_face_is_user (sub_font->scaled_font->font_face)))
|
||||
if (sub_font->use_latin_subset && !sub_font->is_scaled)
|
||||
{
|
||||
latin_character = _cairo_unicode_to_winansi (font_unicode);
|
||||
if (latin_character > 0)
|
||||
|
|
@ -839,6 +835,9 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
|
|||
cairo_int_status_t status;
|
||||
int max_glyphs;
|
||||
cairo_bool_t type1_font;
|
||||
cairo_bool_t has_path;
|
||||
cairo_bool_t has_color;
|
||||
cairo_bool_t is_user;
|
||||
|
||||
/* Lookup glyph in unscaled subsets */
|
||||
if (subsets->type != CAIRO_SUBSETS_SCALED) {
|
||||
|
|
@ -872,30 +871,47 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
|
|||
|
||||
/* Glyph not found. Determine whether the glyph is outline or
|
||||
* bitmap and add to the appropriate subset.
|
||||
*
|
||||
* glyph_index 0 (the .notdef glyph) is a special case. Some fonts
|
||||
*/
|
||||
is_user = _cairo_font_face_is_user (scaled_font->font_face);
|
||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||
/* Check if glyph is color */
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
scaled_font_glyph_index,
|
||||
CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE,
|
||||
NULL, /* foreground color */
|
||||
&scaled_glyph);
|
||||
has_color = (status == CAIRO_INT_STATUS_SUCCESS);
|
||||
|
||||
/* Check if glyph has a path */
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
scaled_font_glyph_index,
|
||||
CAIRO_SCALED_GLYPH_INFO_PATH,
|
||||
NULL, /* foreground color */
|
||||
&scaled_glyph);
|
||||
has_path = (status == CAIRO_INT_STATUS_SUCCESS);
|
||||
|
||||
/* glyph_index 0 (the .notdef glyph) is a special case. Some fonts
|
||||
* will return CAIRO_INT_STATUS_UNSUPPORTED when doing a
|
||||
* _scaled_glyph_lookup(_GLYPH_INFO_PATH). Type1-fallback creates
|
||||
* empty glyphs in this case so we can put the glyph in a unscaled
|
||||
* subset. */
|
||||
if (scaled_font_glyph_index == 0 ||
|
||||
_cairo_font_face_is_user (scaled_font->font_face)) {
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
} else {
|
||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
scaled_font_glyph_index,
|
||||
CAIRO_SCALED_GLYPH_INFO_PATH,
|
||||
* subset.
|
||||
*/
|
||||
if (scaled_font_glyph_index == 0 && !is_user)
|
||||
has_path = TRUE;
|
||||
|
||||
/* If this fails there is nothing we can do with this glyph. */
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
scaled_font_glyph_index,
|
||||
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
||||
NULL, /* foreground color */
|
||||
&scaled_glyph);
|
||||
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||
}
|
||||
&scaled_glyph);
|
||||
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||
if (_cairo_int_status_is_error (status))
|
||||
return status;
|
||||
|
||||
if (status == CAIRO_INT_STATUS_SUCCESS &&
|
||||
subsets->type != CAIRO_SUBSETS_SCALED &&
|
||||
! _cairo_font_face_is_user (scaled_font->font_face))
|
||||
/* Type 3 glyphs (is_user and has_color) must be added to scaled subset */
|
||||
if (subsets->type != CAIRO_SUBSETS_SCALED &&
|
||||
has_path && !has_color && !is_user)
|
||||
{
|
||||
/* Path available. Add to unscaled subset. */
|
||||
key.is_scaled = FALSE;
|
||||
|
|
@ -1007,19 +1023,12 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
|
|||
{
|
||||
cairo_sub_font_collection_t collection;
|
||||
cairo_sub_font_t *sub_font;
|
||||
cairo_bool_t is_scaled, is_user;
|
||||
cairo_bool_t is_scaled;
|
||||
|
||||
is_scaled = FALSE;
|
||||
is_user = FALSE;
|
||||
|
||||
if (type == CAIRO_SUBSETS_FOREACH_USER)
|
||||
is_user = TRUE;
|
||||
|
||||
if (type == CAIRO_SUBSETS_FOREACH_SCALED ||
|
||||
type == CAIRO_SUBSETS_FOREACH_USER)
|
||||
{
|
||||
if (type == CAIRO_SUBSETS_FOREACH_SCALED)
|
||||
is_scaled = TRUE;
|
||||
}
|
||||
|
||||
if (is_scaled)
|
||||
collection.glyphs_size = font_subsets->max_glyphs_per_scaled_subset_used;
|
||||
|
|
@ -1055,9 +1064,7 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
|
|||
sub_font = font_subsets->unscaled_sub_fonts_list;
|
||||
|
||||
while (sub_font) {
|
||||
if (sub_font->is_user == is_user)
|
||||
_cairo_sub_font_collect (sub_font, &collection);
|
||||
|
||||
_cairo_sub_font_collect (sub_font, &collection);
|
||||
sub_font = sub_font->next;
|
||||
}
|
||||
free (collection.utf8);
|
||||
|
|
@ -1090,17 +1097,6 @@ _cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *fo
|
|||
CAIRO_SUBSETS_FOREACH_UNSCALED);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_scaled_font_subsets_foreach_user (cairo_scaled_font_subsets_t *font_subsets,
|
||||
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
||||
void *closure)
|
||||
{
|
||||
return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
|
||||
font_subset_callback,
|
||||
closure,
|
||||
CAIRO_SUBSETS_FOREACH_USER);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_string_equal (const void *key_a, const void *key_b)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -124,14 +124,14 @@ struct _cairo_surface_backend {
|
|||
(*paint) (void *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_clip_t *clip);
|
||||
const cairo_clip_t *clip);
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
(*mask) (void *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
const cairo_clip_t *clip);
|
||||
const cairo_clip_t *clip);
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
(*stroke) (void *surface,
|
||||
|
|
@ -143,7 +143,7 @@ struct _cairo_surface_backend {
|
|||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_clip_t *clip);
|
||||
const cairo_clip_t *clip);
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
(*fill) (void *surface,
|
||||
|
|
@ -153,7 +153,7 @@ struct _cairo_surface_backend {
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_clip_t *clip);
|
||||
const cairo_clip_t *clip);
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
(*fill_stroke) (void *surface,
|
||||
|
|
@ -196,7 +196,7 @@ struct _cairo_surface_backend {
|
|||
int num_clusters,
|
||||
cairo_text_cluster_flags_t cluster_flags,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
const cairo_clip_t *clip);
|
||||
const cairo_clip_t *clip);
|
||||
|
||||
const char **
|
||||
(*get_supported_mime_types) (void *surface);
|
||||
|
|
@ -207,6 +207,10 @@ struct _cairo_surface_backend {
|
|||
const char *tag_name,
|
||||
const char *attributes);
|
||||
|
||||
cairo_bool_t
|
||||
(*supports_color_glyph) (void *surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph_index);
|
||||
};
|
||||
|
||||
cairo_private cairo_status_t
|
||||
|
|
|
|||
|
|
@ -2795,9 +2795,21 @@ composite_color_glyphs (cairo_surface_t *surface,
|
|||
goto UNLOCK;
|
||||
|
||||
if ((scaled_glyph->has_info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) != 0) {
|
||||
skip_cluster = FALSE;
|
||||
break;
|
||||
}
|
||||
cairo_bool_t supports_color_glyph = FALSE;
|
||||
|
||||
if (surface->backend->supports_color_glyph) {
|
||||
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||
supports_color_glyph = _cairo_surface_supports_color_glyph (surface, scaled_font, glyphs[gp].index);
|
||||
|
||||
memset (glyph_cache, 0, sizeof (glyph_cache));
|
||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||
}
|
||||
|
||||
if (!supports_color_glyph) {
|
||||
skip_cluster = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (skip_cluster) {
|
||||
|
|
@ -2967,9 +2979,9 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
|
|||
|
||||
if (num_glyphs == 0)
|
||||
goto DONE;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
utf8_copy = NULL;
|
||||
}
|
||||
|
||||
/* The logic here is duplicated in _cairo_analysis_surface show_glyphs and
|
||||
* show_text_glyphs. Keep in synch. */
|
||||
|
|
@ -3057,6 +3069,16 @@ _cairo_surface_tag (cairo_surface_t *surface,
|
|||
return _cairo_surface_set_error (surface, status);
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_surface_supports_color_glyph (cairo_surface_t *surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph_index)
|
||||
{
|
||||
if (surface->backend->supports_color_glyph != NULL)
|
||||
return surface->backend->supports_color_glyph (surface, scaled_font, glyph_index);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_surface_set_resolution:
|
||||
|
|
|
|||
|
|
@ -1555,14 +1555,6 @@ _cairo_svg_document_emit_font_subsets (cairo_svg_document_t *document)
|
|||
status = _cairo_scaled_font_subsets_foreach_scaled (document->font_subsets,
|
||||
_cairo_svg_document_emit_font_subset,
|
||||
document);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
status = _cairo_scaled_font_subsets_foreach_user (document->font_subsets,
|
||||
_cairo_svg_document_emit_font_subset,
|
||||
document);
|
||||
|
||||
FAIL:
|
||||
_cairo_scaled_font_subsets_destroy (document->font_subsets);
|
||||
document->font_subsets = NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -457,12 +457,22 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
|
|||
_cairo_type3_glyph_surface_set_stream (surface, stream);
|
||||
|
||||
_cairo_scaled_font_freeze_cache (surface->scaled_font);
|
||||
|
||||
/* Check if this is a color glyph and bail out if it is */
|
||||
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
|
||||
glyph_index,
|
||||
CAIRO_SCALED_GLYPH_INFO_METRICS |
|
||||
CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE,
|
||||
CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE,
|
||||
NULL, /* foreground color */
|
||||
&scaled_glyph);
|
||||
if (status == CAIRO_INT_STATUS_SUCCESS) {
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
goto FAIL;
|
||||
} status = _cairo_scaled_glyph_lookup (surface->scaled_font,
|
||||
glyph_index,
|
||||
CAIRO_SCALED_GLYPH_INFO_METRICS |
|
||||
CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE,
|
||||
NULL, /* foreground color */
|
||||
&scaled_glyph);
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
|
||||
glyph_index,
|
||||
|
|
|
|||
|
|
@ -183,7 +183,9 @@ _cairo_user_scaled_glyph_init_record_glyph (cairo_user_scaled_font_t *scaled_fon
|
|||
} else {
|
||||
status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||
|
||||
if (face->scaled_font_methods.render_color_glyph) {
|
||||
if (face->scaled_font_methods.render_color_glyph &&
|
||||
scaled_font->base.options.color_mode != CAIRO_COLOR_MODE_NO_COLOR)
|
||||
{
|
||||
recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, TRUE, foreground_color);
|
||||
|
||||
cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, TRUE);
|
||||
|
|
|
|||
|
|
@ -406,6 +406,10 @@ _cairo_hash_bytes (uintptr_t hash,
|
|||
const void *bytes,
|
||||
unsigned int length);
|
||||
|
||||
cairo_private uintptr_t
|
||||
_cairo_hash_uintptr (uintptr_t hash,
|
||||
uintptr_t u);
|
||||
|
||||
/* We use bits 24-27 to store phases for subpixel positions */
|
||||
#define _cairo_scaled_glyph_index(g) ((unsigned long)((g)->hash_entry.hash & 0xffffff))
|
||||
#define _cairo_scaled_glyph_xphase(g) (int)(((g)->hash_entry.hash >> 24) & 3)
|
||||
|
|
@ -1483,6 +1487,11 @@ _cairo_surface_tag (cairo_surface_t *surface,
|
|||
const char *tag_name,
|
||||
const char *attributes);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_surface_supports_color_glyph (cairo_surface_t *surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph_index);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_acquire_source_image (cairo_surface_t *surface,
|
||||
cairo_image_surface_t **image_out,
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.2 KiB |
BIN
test/reference/ft-color-font.pdf.xfail.png
Normal file
|
After Width: | Height: | Size: 585 B |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 9 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
BIN
test/reference/user-font.pdf.xfail.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
test/reference/user-font.svg.argb32.ref.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
test/reference/user-font.svg.rgb24.ref.png
Normal file
|
After Width: | Height: | Size: 14 KiB |