diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 924b80c03..3e8375f7d 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -2860,6 +2860,8 @@ _cairo_pdf_surface_fill (void *abstract_surface, return status; } +#define GLYPH_POSITION_TOLERANCE 0.001 + static cairo_int_status_t _cairo_pdf_surface_show_glyphs (void *abstract_surface, cairo_operator_t op, @@ -2870,9 +2872,11 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface, { cairo_pdf_surface_t *surface = abstract_surface; unsigned int current_subset_id = (unsigned int)-1; - unsigned int font_id, subset_id, subset_glyph_index; - cairo_bool_t diagonal; + cairo_scaled_font_subsets_glyph_t subset_glyph; + cairo_bool_t diagonal, in_TJ; cairo_status_t status; + double Tlm_x = 0, Tlm_y = 0; + double Tm_x = 0, y; int i; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) @@ -2893,35 +2897,118 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface, else diagonal = FALSE; + in_TJ = FALSE; for (i = 0; i < num_glyphs; i++) { - status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets, - scaled_font, glyphs[i].index, - &font_id, &subset_id, &subset_glyph_index); + status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets, + scaled_font, glyphs[i].index, + &subset_glyph); if (status) - return status; + return status; - if (subset_id != current_subset_id) - _cairo_output_stream_printf (surface->output, - "/CairoFont-%d-%d 1 Tf\r\n", - font_id, subset_id); + if (subset_glyph.is_scaled == FALSE) { + y = 0.0; + cairo_matrix_transform_distance (&scaled_font->scale, + &subset_glyph.x_advance, + &y); + } - if (subset_id != current_subset_id || !diagonal) { + if (subset_glyph.subset_id != current_subset_id) { + if (in_TJ) { + _cairo_output_stream_printf (surface->output, ">] TJ\r\n"); + in_TJ = FALSE; + } _cairo_output_stream_printf (surface->output, - "%f %f %f %f %f %f Tm <%02x> Tj\r\n", + "/CairoFont-%d-%d 1 Tf\r\n", + subset_glyph.font_id, + subset_glyph.subset_id); + } + + if (subset_glyph.subset_id != current_subset_id || !diagonal) { + _cairo_output_stream_printf (surface->output, + "%f %f %f %f %f %f Tm\r\n", scaled_font->scale.xx, scaled_font->scale.yx, -scaled_font->scale.xy, -scaled_font->scale.yy, glyphs[i].x, - glyphs[i].y, - subset_glyph_index); - current_subset_id = subset_id; + glyphs[i].y); + current_subset_id = subset_glyph.subset_id; + Tlm_x = glyphs[i].x; + Tlm_y = glyphs[i].y; + Tm_x = Tlm_x; + } + + if (diagonal) { + if (i < num_glyphs - 1 && + fabs((glyphs[i].y - glyphs[i+1].y)/scaled_font->scale.yy) < GLYPH_POSITION_TOLERANCE && + fabs((glyphs[i].x - glyphs[i+1].x)/scaled_font->scale.xx) < 10) + { + if (!in_TJ) { + if (i != 0) { + _cairo_output_stream_printf (surface->output, + "%f %f Td\r\n", + (glyphs[i].x - Tlm_x)/scaled_font->scale.xx, + (glyphs[i].y - Tlm_y)/-scaled_font->scale.yy); + Tlm_x = glyphs[i].x; + Tlm_y = glyphs[i].y; + Tm_x = Tlm_x; + } + _cairo_output_stream_printf (surface->output, + "[<%02x", + subset_glyph.subset_glyph_index); + Tm_x += subset_glyph.x_advance; + in_TJ = TRUE; + } else { + if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) { + double delta = glyphs[i].x - Tm_x; + + _cairo_output_stream_printf (surface->output, + "> %f <", + -1000.0*delta/scaled_font->scale.xx); + Tm_x += delta; + } + _cairo_output_stream_printf (surface->output, + "%02x", + subset_glyph.subset_glyph_index); + Tm_x += subset_glyph.x_advance; + } + } + else + { + if (in_TJ) { + if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) { + double delta = glyphs[i].x - Tm_x; + + _cairo_output_stream_printf (surface->output, + "> %f <", + -1000.0*delta/scaled_font->scale.xx); + Tm_x += delta; + } + _cairo_output_stream_printf (surface->output, + "%02x>] TJ\r\n", + subset_glyph.subset_glyph_index); + Tm_x += subset_glyph.x_advance; + in_TJ = FALSE; + } else { + if (i != 0) { + _cairo_output_stream_printf (surface->output, + "%f %f Td ", + (glyphs[i].x - Tlm_x)/scaled_font->scale.xx, + (glyphs[i].y - Tlm_x)/-scaled_font->scale.yy); + Tlm_x = glyphs[i].x; + Tlm_y = glyphs[i].y; + Tm_x = Tlm_x; + } + _cairo_output_stream_printf (surface->output, + "<%02x> Tj ", + subset_glyph.subset_glyph_index); + Tm_x += subset_glyph.x_advance; + } + } } else { _cairo_output_stream_printf (surface->output, - "%f %f Td <%02x> Tj\r\n", - (glyphs[i].x - glyphs[i-1].x)/scaled_font->scale.xx, - (glyphs[i].y - glyphs[i-1].y)/-scaled_font->scale.yy, - subset_glyph_index); + "<%02x> Tj\r\n", + subset_glyph.subset_glyph_index); } } diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 5f43e98c7..bdae519f9 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -2200,12 +2200,13 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, cairo_ps_surface_t *surface = abstract_surface; cairo_output_stream_t *stream = surface->stream; unsigned int current_subset_id = -1; - unsigned int font_id; + cairo_scaled_font_subsets_glyph_t subset_glyph; cairo_ps_glyph_id_t *glyph_ids; cairo_status_t status; unsigned int num_glyphs_unsigned, i, j, last, end; cairo_bool_t vertical, horizontal; cairo_output_stream_t *word_wrap; + double x_advance; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _cairo_ps_surface_analyze_operation (surface, op, source); @@ -2228,11 +2229,11 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, for (i = 0; i < num_glyphs_unsigned; i++) { status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets, scaled_font, glyphs[i].index, - &font_id, - &(glyph_ids[i].subset_id), - &(glyph_ids[i].glyph_id)); + &subset_glyph); if (status) goto fail; + glyph_ids[i].subset_id = subset_glyph.subset_id; + glyph_ids[i].glyph_id = subset_glyph.subset_glyph_index; } i = 0; @@ -2242,7 +2243,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, "/CairoFont-%d-%d findfont\n" "[ %f %f %f %f 0 0 ] makefont\n" "setfont\n", - font_id, + subset_glyph.font_id, glyph_ids[i].subset_id, scaled_font->scale.xx, scaled_font->scale.yx, diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h index 510434049..db655f77d 100644 --- a/src/cairo-scaled-font-subsets-private.h +++ b/src/cairo-scaled-font-subsets-private.h @@ -41,6 +41,14 @@ typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t; +typedef struct _cairo_scaled_font_subsets_glyph { + unsigned int font_id; + unsigned int subset_id; + unsigned int subset_glyph_index; + cairo_bool_t is_scaled; + double x_advance; +} cairo_scaled_font_subsets_glyph_t; + /** * _cairo_scaled_font_subsets_create: * @@ -85,6 +93,8 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets); * @font_subsets: a #cairo_scaled_font_subsets_t * @scaled_font: the font of the glyph to be mapped * @scaled_font_glyph_index: the index of the glyph to be mapped + * @subset_glyph_ret: return structure containing subset font and glyph id + * * @font_id_ret: return value giving the font ID of the mapped glyph * @subset_id_ret: return value giving the subset ID of the mapped glyph within the @font_id_ret * @subset_glyph_index_ret: return value giving the index of the mapped glyph within the @subset_id_ret subset @@ -126,6 +136,17 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets); * used by #cairo_scaled_font_subset_t as provided by * _cairo_scaled_font_subsets_foreach. * + * The returned values in the cairo_scaled_font_subsets_glyph_t struct are: + * + * @font_id: The font ID of the mapped glyph + * @subset_id : The subset ID of the mapped glyph within the @font_id + * @subset_glyph_index: The index of the mapped glyph within the @subset_id subset + * @is_scaled: If true, the mapped glyph is from a bitmap font, and separate font + * subset is created for each font scale used. If false, the outline of the mapped glyph + * is available. One font subset for each font face is created. + * @x_advance: When @is_scaled is true, @x_advance contains the x_advance for the mapped glyph in device space. + * When @is_scaled is false, @x_advance contains the x_advance for the the mapped glyph from an unhinted 1 point font. + * * Return value: CAIRO_STATUS_SUCCESS if successful, or a non-zero * value indicating an error. Possible errors include * CAIRO_STATUS_NO_MEMORY. @@ -134,9 +155,7 @@ cairo_private cairo_status_t _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *font_subsets, cairo_scaled_font_t *scaled_font, unsigned long scaled_font_glyph_index, - unsigned int *font_id_ret, - unsigned int *subset_id_ret, - unsigned int *subset_glyph_index_ret); + cairo_scaled_font_subsets_glyph_t *subset_glyph_ret); typedef void (*cairo_scaled_font_subset_callback_func_t) (cairo_scaled_font_subset_t *font_subset, diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c index d98cba2f8..974aebb04 100644 --- a/src/cairo-scaled-font-subsets.c +++ b/src/cairo-scaled-font-subsets.c @@ -74,6 +74,7 @@ typedef struct _cairo_sub_font_glyph { unsigned int subset_id; unsigned int subset_glyph_index; + double x_advance; } cairo_sub_font_glyph_t; typedef struct _cairo_sub_font_collection { @@ -107,7 +108,8 @@ _cairo_sub_font_glyphs_equal (const void *key_a, const void *key_b) static cairo_sub_font_glyph_t * _cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index, unsigned int subset_id, - unsigned int subset_glyph_index) + unsigned int subset_glyph_index, + double x_advance) { cairo_sub_font_glyph_t *sub_font_glyph; @@ -118,6 +120,7 @@ _cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index, _cairo_sub_font_glyph_init_key (sub_font_glyph, scaled_font_glyph_index); sub_font_glyph->subset_id = subset_id; sub_font_glyph->subset_glyph_index = subset_glyph_index; + sub_font_glyph->x_advance = x_advance; return sub_font_glyph; } @@ -207,7 +210,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, _cairo_sub_font_init_key (sub_font, scaled_font); sub_font->parent = parent; - sub_font->scaled_font = cairo_scaled_font_reference (scaled_font); + sub_font->scaled_font = scaled_font; sub_font->font_id = font_id; sub_font->current_subset = 0; @@ -248,7 +251,8 @@ static cairo_status_t _cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font, unsigned long scaled_font_glyph_index, unsigned int *subset_id, - unsigned int *subset_glyph_index) + unsigned int *subset_glyph_index, + double *x_advance) { cairo_sub_font_glyph_t key, *sub_font_glyph; @@ -258,6 +262,7 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font, { *subset_id = sub_font_glyph->subset_id; *subset_glyph_index = sub_font_glyph->subset_glyph_index; + *x_advance = sub_font_glyph->x_advance; return CAIRO_STATUS_SUCCESS; } @@ -269,10 +274,12 @@ static cairo_status_t _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, unsigned long scaled_font_glyph_index, unsigned int *subset_id, - unsigned int *subset_glyph_index) + unsigned int *subset_glyph_index, + double *x_advance) { cairo_sub_font_glyph_t key, *sub_font_glyph; cairo_status_t status; + cairo_scaled_glyph_t *scaled_glyph; _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index); if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base, @@ -284,9 +291,17 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, sub_font->num_glyphs_in_current_subset = 0; } - sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index, + status = _cairo_scaled_glyph_lookup (sub_font->scaled_font, + scaled_font_glyph_index, + CAIRO_SCALED_GLYPH_INFO_METRICS, + &scaled_glyph); + if (status) + return status; + + sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index, sub_font->current_subset, - sub_font->num_glyphs_in_current_subset++); + sub_font->num_glyphs_in_current_subset++, + scaled_glyph->metrics.x_advance); if (sub_font_glyph == NULL) return CAIRO_STATUS_NO_MEMORY; @@ -308,6 +323,7 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, *subset_id = sub_font_glyph->subset_id; *subset_glyph_index = sub_font_glyph->subset_glyph_index; + *x_advance = sub_font_glyph->x_advance; return CAIRO_STATUS_SUCCESS; } @@ -404,12 +420,14 @@ cairo_private cairo_status_t _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, cairo_scaled_font_t *scaled_font, unsigned long scaled_font_glyph_index, - unsigned int *font_id, - unsigned int *subset_id, - unsigned int *subset_glyph_index) + cairo_scaled_font_subsets_glyph_t *subset_glyph) { cairo_sub_font_t key, *sub_font; cairo_scaled_glyph_t *scaled_glyph; + cairo_font_face_t *font_face; + cairo_matrix_t identity; + cairo_font_options_t font_options; + cairo_scaled_font_t *unscaled_font; cairo_status_t status; /* Lookup glyph in unscaled subsets */ @@ -419,10 +437,14 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, if (_cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base, (cairo_hash_entry_t **) &sub_font)) { - status = _cairo_sub_font_lookup_glyph (sub_font, scaled_font_glyph_index, - subset_id, subset_glyph_index); + status = _cairo_sub_font_lookup_glyph (sub_font, + scaled_font_glyph_index, + &subset_glyph->subset_id, + &subset_glyph->subset_glyph_index, + &subset_glyph->x_advance); if (status == CAIRO_STATUS_SUCCESS) { - *font_id = sub_font->font_id; + subset_glyph->font_id = sub_font->font_id; + subset_glyph->is_scaled = FALSE; return CAIRO_STATUS_SUCCESS; } } @@ -435,10 +457,14 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, if (_cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base, (cairo_hash_entry_t **) &sub_font)) { - status = _cairo_sub_font_lookup_glyph (sub_font, scaled_font_glyph_index, - subset_id, subset_glyph_index); + status = _cairo_sub_font_lookup_glyph (sub_font, + scaled_font_glyph_index, + &subset_glyph->subset_id, + &subset_glyph->subset_glyph_index, + &subset_glyph->x_advance); if (status == CAIRO_STATUS_SUCCESS) { - *font_id = sub_font->font_id; + subset_glyph->font_id = sub_font->font_id; + subset_glyph->is_scaled = TRUE; return CAIRO_STATUS_SUCCESS; } } @@ -457,7 +483,18 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, if (! _cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base, (cairo_hash_entry_t **) &sub_font)) { - sub_font = _cairo_sub_font_create (subsets, scaled_font, + font_face = cairo_scaled_font_get_font_face (scaled_font); + cairo_matrix_init_identity (&identity); + _cairo_font_options_init_default (&font_options); + cairo_font_options_set_hint_style (&font_options, CAIRO_HINT_STYLE_NONE); + cairo_font_options_set_hint_metrics (&font_options, CAIRO_HINT_METRICS_OFF); + unscaled_font = cairo_scaled_font_create (font_face, + &identity, + &identity, + &font_options); + + sub_font = _cairo_sub_font_create (subsets, + unscaled_font, subsets->num_sub_fonts++, subsets->max_glyphs_per_unscaled_subset_limit, FALSE); @@ -469,6 +506,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, if (status) return status; } + subset_glyph->is_scaled = FALSE; } else if (subsets->max_glyphs_per_scaled_subset_limit > 0) { /* No path available. Add to scaled subset. */ key.is_scaled = TRUE; @@ -476,7 +514,8 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, if (! _cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base, (cairo_hash_entry_t **) &sub_font)) { - sub_font = _cairo_sub_font_create (subsets, scaled_font, + sub_font = _cairo_sub_font_create (subsets, + cairo_scaled_font_reference (scaled_font), subsets->num_sub_fonts++, subsets->max_glyphs_per_scaled_subset_limit, TRUE); @@ -488,13 +527,17 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, if (status) return status; } + subset_glyph->is_scaled = TRUE; } else { return CAIRO_INT_STATUS_UNSUPPORTED; } - *font_id = sub_font->font_id; + subset_glyph->font_id = sub_font->font_id; - return _cairo_sub_font_map_glyph (sub_font, scaled_font_glyph_index, - subset_id, subset_glyph_index); + return _cairo_sub_font_map_glyph (sub_font, + scaled_font_glyph_index, + &subset_glyph->subset_id, + &subset_glyph->subset_glyph_index, + &subset_glyph->x_advance); } static cairo_status_t diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 0da155785..703017a9a 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -1877,7 +1877,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface, cairo_svg_document_t *document = surface->document; cairo_path_fixed_t path; cairo_status_t status; - unsigned int font_id, subset_id, subset_glyph_index; + cairo_scaled_font_subsets_glyph_t subset_glyph; int i; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) @@ -1901,7 +1901,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface, for (i = 0; i < num_glyphs; i++) { status = _cairo_scaled_font_subsets_map_glyph (document->font_subsets, scaled_font, glyphs[i].index, - &font_id, &subset_id, &subset_glyph_index); + &subset_glyph); if (status) { glyphs += i; num_glyphs -= i; @@ -1911,7 +1911,8 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface, _cairo_output_stream_printf (surface->xml_node, " \n", - font_id, subset_glyph_index, + subset_glyph.font_id, + subset_glyph.subset_glyph_index, glyphs[i].x, glyphs[i].y); }