diff options
author | Adrian Johnson <ajohnson@redneon.com> | 2008-04-05 23:33:29 +1030 |
---|---|---|
committer | Adrian Johnson <ajohnson@redneon.com> | 2008-04-06 00:36:02 +1030 |
commit | 0d5902b7167f8cb4bfc96fd813003cd220441151 (patch) | |
tree | aea4095b92f874f0164fca58e7dc01773ada69d6 | |
parent | 03d2b098ff245ff6724b1d83a121f5ce9dcd0b51 (diff) |
Type1-fallback: Use correct glyph metrics for .notdef glyph
Bug 15348 references the following PDF that was printing incorrectly
when running through poppler and cairo to generate PostScript.
http://launchpadlibrarian.net/12921700/UbuntuDesktop.pdf
The PostScript output had too much space between each word causing
strings of glyphs printed with the TJ operator to overlap.
The original PDF file contains an CFF font with CID Identity-H
encoding. The PDF file is using character code 0 (glyph 0 due to
Identity-H encoding) as a space character. The CFF specification
defines glyph 0 to be the .notdef glyph.
The PS backend subsets CFF fonts as a Type1-fallback
font. Type1-fallback creates it's own empty .notdef glyph with an
arbitrary glyph advance of 500. The problem here is the TJ operator
used to output the glyphs depends on the glyph advance being
correct. pdf-operators.c uses the glyph advance returned by
_scaled_glyph_init(). However the PostScript interpreter sees the
glyph advance of 500 for .notdef. This problem does not occur when
generating PDF as the PDF font dictionary contains an list of glyph
advances that override the font metrics.
Fix this by making Type1-fallback not treat .notdef as special and to
create it the path and metrics obtained from _scaled_glyph_init(). As
a special case, make it not fail if _scaled_glyph_init() is unable to
return a path for .notdef. This was probably the reason Type1-fallback
previously created it's own .notdef glyph as calling
_scaled_glyph_init(_GLYPH_INFO_PATH) for glyph 0 returns
CAIRO_INT_STATUS_UNSUPPORTED for some fonts.
This ensures the Type1-fallback font metrics match the metrics used
by pdf-operators.c to position the glyphs. This also results in the
removal of some duplicated code.
-rw-r--r-- | src/cairo-type1-fallback.c | 92 |
1 files changed, 29 insertions, 63 deletions
diff --git a/src/cairo-type1-fallback.c b/src/cairo-type1-fallback.c index 0d81ccb5f..539ddf227 100644 --- a/src/cairo-type1-fallback.c +++ b/src/cairo-type1-fallback.c @@ -332,33 +332,6 @@ charstring_encrypt (cairo_array_t *data) } static cairo_int_status_t -create_notdef_charstring (cairo_array_t *data, cairo_charstring_type_t type) -{ - cairo_status_t status; - - /* We're passing constants below, so we know the 0 values will - * only use 1 byte each, and the 500 values will use 2 bytes - * each. Then 2 more for each of the commands is 10 total. */ - status = _cairo_array_grow_by (data, 10); - if (status) - return status; - - if (type == CAIRO_CHARSTRING_TYPE1) { - charstring_encode_integer (data, 0, type); - charstring_encode_integer (data, 0, type); - - /* The width is arbitrary. */ - charstring_encode_integer (data, 500, type); - charstring_encode_integer (data, 0, type); - charstring_encode_command (data, CHARSTRING_sbw); - } - - charstring_encode_command (data, CHARSTRING_endchar); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t cairo_type1_font_create_charstring (cairo_type1_font_t *font, int subset_index, int glyph_index, @@ -369,6 +342,7 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font, cairo_scaled_glyph_t *scaled_glyph; t1_path_info_t path_info; cairo_text_extents_t *metrics; + cairo_bool_t emit_path = TRUE; /* This call may return CAIRO_INT_STATUS_UNSUPPORTED for bitmap fonts. */ status = _cairo_scaled_glyph_lookup (font->type1_scaled_font, @@ -376,6 +350,16 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font, CAIRO_SCALED_GLYPH_INFO_METRICS| CAIRO_SCALED_GLYPH_INFO_PATH, &scaled_glyph); + + /* It is ok for the .notdef glyph to not have a path available. We + * just need the metrics to emit an empty glyph. */ + if (glyph_index == 0 && status == CAIRO_INT_STATUS_UNSUPPORTED) { + emit_path = FALSE; + status = _cairo_scaled_glyph_lookup (font->type1_scaled_font, + glyph_index, + CAIRO_SCALED_GLYPH_INFO_METRICS, + &scaled_glyph); + } if (status) return status; @@ -418,15 +402,17 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font, } path_info.data = data; path_info.type = type; - status = _cairo_path_fixed_interpret (scaled_glyph->path, - CAIRO_DIRECTION_FORWARD, - _charstring_move_to, - _charstring_line_to, - _charstring_curve_to, - _charstring_close_path, - &path_info); - if (status) - return status; + if (emit_path) { + status = _cairo_path_fixed_interpret (scaled_glyph->path, + CAIRO_DIRECTION_FORWARD, + _charstring_move_to, + _charstring_line_to, + _charstring_curve_to, + _charstring_close_path, + &path_info); + if (status) + return status; + } status = _cairo_array_grow_by (data, 1); if (status) @@ -455,7 +441,7 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font, "2 index /CharStrings %d dict dup begin\n", font->scaled_font_subset->num_glyphs + 1); - for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) { + for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { _cairo_array_truncate (&data, 0); /* four "random" bytes required by encryption algorithm */ status = _cairo_array_append_multiple (&data, zeros, 4); @@ -473,6 +459,8 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font, _cairo_output_stream_printf (encrypted_output, "/%s %d RD ", font->scaled_font_subset->glyph_names[i], length); + } else if (i == 0) { + _cairo_output_stream_printf (encrypted_output, "/.notdef %d RD ", length); } else { _cairo_output_stream_printf (encrypted_output, "/g%d %d RD ", i, length); } @@ -482,24 +470,6 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font, _cairo_output_stream_printf (encrypted_output, " ND\n"); } - /* All type 1 fonts must have a /.notdef charstring */ - - _cairo_array_truncate (&data, 0); - /* four "random" bytes required by encryption algorithm */ - status = _cairo_array_append_multiple (&data, zeros, 4); - if (status) - goto fail; - status = create_notdef_charstring (&data, CAIRO_CHARSTRING_TYPE1); - if (status) - goto fail; - charstring_encrypt (&data); - length = _cairo_array_num_elements (&data); - _cairo_output_stream_printf (encrypted_output, "/.notdef %d RD ", length); - _cairo_output_stream_write (encrypted_output, - _cairo_array_index (&data, 0), - length); - _cairo_output_stream_printf (encrypted_output, " ND\n"); - fail: _cairo_array_fini (&data); return status; @@ -856,14 +826,10 @@ _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset, if (status) goto fail2; - if (i == 0) { - status = create_notdef_charstring (&charstring, CAIRO_CHARSTRING_TYPE2); - } else { - status = cairo_type1_font_create_charstring (font, i, - font->scaled_font_subset->glyphs[i], - CAIRO_CHARSTRING_TYPE2, - &charstring); - } + status = cairo_type1_font_create_charstring (font, i, + font->scaled_font_subset->glyphs[i], + CAIRO_CHARSTRING_TYPE2, + &charstring); if (status) goto fail2; |