diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c index 48cab1462..e3a0e4b3f 100644 --- a/src/cairo-cff-subset.c +++ b/src/cairo-cff-subset.c @@ -739,9 +739,9 @@ cairo_cff_font_read_private_dict (cairo_cff_font_t *font, if (unlikely (status)) return status; - /* Use maximum sized encoding to reserve space for later modification. */ - end_buf = encode_integer_max (buf, 0); - status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf); + /* Use maximum sized encoding to reserve space for later modification. */ + end_buf = encode_integer_max (buf, 0); + status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf); if (unlikely (status)) return status; } @@ -935,23 +935,37 @@ cairo_cff_font_read_top_dict (cairo_cff_font_t *font) if (unlikely (status)) goto fail; - status = cff_dict_set_operands (font->top_dict, - FDSELECT_OP, buf, end_buf - buf); - if (unlikely (status)) - goto fail; - - status = cff_dict_set_operands (font->top_dict, - FDARRAY_OP, buf, end_buf - buf); - if (unlikely (status)) - goto fail; - status = cff_dict_set_operands (font->top_dict, CHARSET_OP, buf, end_buf - buf); if (unlikely (status)) goto fail; - cff_dict_remove (font->top_dict, ENCODING_OP); - cff_dict_remove (font->top_dict, PRIVATE_OP); + if (font->scaled_font_subset->is_latin) { + status = cff_dict_set_operands (font->top_dict, + ENCODING_OP, buf, end_buf - buf); + if (unlikely (status)) + goto fail; + + /* Private has two operands - size and offset */ + end_buf = encode_integer_max (end_buf, 0); + cff_dict_set_operands (font->top_dict, PRIVATE_OP, buf, end_buf - buf); + if (unlikely (status)) + goto fail; + + } else { + status = cff_dict_set_operands (font->top_dict, + FDSELECT_OP, buf, end_buf - buf); + if (unlikely (status)) + goto fail; + + status = cff_dict_set_operands (font->top_dict, + FDARRAY_OP, buf, end_buf - buf); + if (unlikely (status)) + goto fail; + + cff_dict_remove (font->top_dict, ENCODING_OP); + cff_dict_remove (font->top_dict, PRIVATE_OP); + } /* Remove the unique identifier operators as the subsetted font is * not the same is the original font. */ @@ -1238,20 +1252,28 @@ cairo_cff_font_subset_font (cairo_cff_font_t *font) { cairo_status_t status; - status = cairo_cff_font_set_ros_strings (font); - if (unlikely (status)) - return status; + if (!font->scaled_font_subset->is_latin) { + status = cairo_cff_font_set_ros_strings (font); + if (unlikely (status)) + return status; + } status = cairo_cff_font_subset_charstrings (font); if (unlikely (status)) return status; - if (font->is_cid) - status = cairo_cff_font_subset_fontdict (font); - else - status = cairo_cff_font_create_cid_fontdict (font); - if (unlikely (status)) - return status; + if (!font->scaled_font_subset->is_latin) { + if (font->is_cid) + status = cairo_cff_font_subset_fontdict (font); + else + status = cairo_cff_font_create_cid_fontdict (font); + if (unlikely (status)) + return status; + } else { + font->private_dict_offset = malloc (sizeof (int)); + if (unlikely (font->private_dict_offset == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } status = cairo_cff_font_subset_strings (font); if (unlikely (status)) @@ -1373,6 +1395,30 @@ cairo_cff_font_write_global_subrs (cairo_cff_font_t *font) return cff_index_write (&font->global_sub_index, &font->output); } +static cairo_status_t +cairo_cff_font_write_encoding (cairo_cff_font_t *font) +{ + unsigned char buf[2]; + cairo_status_t status; + unsigned int i; + + cairo_cff_font_set_topdict_operator_to_cur_pos (font, ENCODING_OP); + buf[0] = 0; /* Format 0 */ + buf[1] = font->scaled_font_subset->num_glyphs - 1; + status = _cairo_array_append_multiple (&font->output, buf, 2); + if (unlikely (status)) + return status; + + for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) { + unsigned char ch = font->scaled_font_subset->to_latin_char[i]; + status = _cairo_array_append (&font->output, &ch); + if (unlikely (status)) + return status; + } + + return CAIRO_STATUS_SUCCESS; +} + static cairo_status_t cairo_cff_font_write_fdselect (cairo_cff_font_t *font) { @@ -1426,8 +1472,100 @@ cairo_cff_font_write_fdselect (cairo_cff_font_t *font) return CAIRO_STATUS_SUCCESS; } +/* Winansi to CFF standard strings mapping for characters 128 to 255 */ +const int winansi_to_cff_std_string[] = { + /* 128 */ + 0, 0, 117, 101, 118, 121, 112, 113, + 126, 122, 192, 107, 142, 0, 199, 0, + /* 144 */ + 0, 65, 8, 105, 119, 116, 111, 137, + 127, 153, 221, 108, 148, 0, 228, 198, + /* 160 */ + 0, 96, 97, 98, 103, 100, 160, 102, + 131, 170, 139, 106, 151, 0, 165, 128, + /* 176 */ + 161, 156, 164, 169, 125, 152, 115, 114, + 133, 150, 143, 187, 158, 155, 163, 123, + /* 192 */ + 174, 171, 172, 176, 173, 175, 138, 177, + 181, 178, 179, 180, 185, 182, 183, 184, + /* 208 */ + 154, 186, 190, 187, 188, 191, 189, 168, + 141, 196, 193, 194, 195, 197, 157, 149, + /* 224 */ + 203, 200, 201, 205, 202, 204, 144, 206, + 210, 207, 208, 209, 214, 211, 212, 213, + /* 240 */ + 167, 215, 219, 216, 217, 220, 218, 159, + 147, 225, 222, 223, 224, 226, 162, 227, +}; + static cairo_status_t -cairo_cff_font_write_charset (cairo_cff_font_t *font) +cairo_cff_font_get_sid_for_winansi_char (cairo_cff_font_t *font, int ch, int *sid_out) +{ + int sid; + cairo_status_t status; + const char *euro = "Euro"; + + if (ch == 39) { + sid = 104; + + } else if (ch == 96) { + sid = 124; + + } else if (ch >= 32 && ch <= 126) { + sid = ch - 31; + + } else if (ch == 128) { + sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index); + status = cff_index_append_copy (&font->strings_subset_index, + (unsigned char *)euro, strlen(euro)); + if (unlikely (status)) + return status; + + } else if (ch >= 128 && ch <= 255) { + sid = winansi_to_cff_std_string[ch - 128]; + + } else { + sid = 0; + } + + *sid_out = sid; + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +cairo_cff_font_write_type1_charset (cairo_cff_font_t *font) +{ + unsigned char format = 0; + unsigned int i; + int ch, sid; + cairo_status_t status; + uint16_t sid_be16; + + cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP); + status = _cairo_array_append (&font->output, &format); + if (unlikely (status)) + return status; + + for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) { + ch = font->scaled_font_subset->to_latin_char[i]; + status = cairo_cff_font_get_sid_for_winansi_char (font, ch, &sid); + if (unlikely (status)) + return status; + + sid_be16 = cpu_to_be16(sid); + status = _cairo_array_append_multiple (&font->output, &sid_be16, sizeof(sid_be16)); + if (unlikely (status)) + return status; + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +cairo_cff_font_write_cid_charset (cairo_cff_font_t *font) { unsigned char byte; uint16_t word; @@ -1499,9 +1637,9 @@ cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font) static cairo_status_t cairo_cff_font_write_private_dict (cairo_cff_font_t *font, - int dict_num, - cairo_hash_table_t *parent_dict, - cairo_hash_table_t *private_dict) + int dict_num, + cairo_hash_table_t *parent_dict, + cairo_hash_table_t *private_dict) { int offset; int size; @@ -1605,32 +1743,75 @@ cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t *font) return CAIRO_STATUS_SUCCESS; } +static cairo_status_t +cairo_cff_font_write_type1_private_dict_and_local_sub (cairo_cff_font_t *font) +{ + cairo_int_status_t status; + + status = cairo_cff_font_write_private_dict (font, + 0, + font->top_dict, + font->private_dict); + if (unlikely (status)) + return status; + + status = cairo_cff_font_write_local_sub (font, + 0, + font->private_dict, + &font->local_sub_index); + if (unlikely (status)) + return status; + + return CAIRO_STATUS_SUCCESS; +} + + typedef cairo_status_t (*font_write_t) (cairo_cff_font_t *font); -static const font_write_t font_write_funcs[] = { +static const font_write_t font_write_cid_funcs[] = { cairo_cff_font_write_header, cairo_cff_font_write_name, cairo_cff_font_write_top_dict, cairo_cff_font_write_strings, cairo_cff_font_write_global_subrs, - cairo_cff_font_write_charset, + cairo_cff_font_write_cid_charset, cairo_cff_font_write_fdselect, cairo_cff_font_write_charstrings, cairo_cff_font_write_cid_fontdict, cairo_cff_font_write_cid_private_dict_and_local_sub, }; +static const font_write_t font_write_type1_funcs[] = { + cairo_cff_font_write_header, + cairo_cff_font_write_name, + cairo_cff_font_write_top_dict, + cairo_cff_font_write_strings, + cairo_cff_font_write_global_subrs, + cairo_cff_font_write_encoding, + cairo_cff_font_write_type1_charset, + cairo_cff_font_write_charstrings, + cairo_cff_font_write_type1_private_dict_and_local_sub, +}; + static cairo_status_t cairo_cff_font_write_subset (cairo_cff_font_t *font) { cairo_int_status_t status; unsigned int i; - for (i = 0; i < ARRAY_LENGTH (font_write_funcs); i++) { - status = font_write_funcs[i] (font); - if (unlikely (status)) - return status; + if (font->scaled_font_subset->is_latin) { + for (i = 0; i < ARRAY_LENGTH (font_write_type1_funcs); i++) { + status = font_write_type1_funcs[i] (font); + if (unlikely (status)) + return status; + } + } else { + for (i = 0; i < ARRAY_LENGTH (font_write_cid_funcs); i++) { + status = font_write_cid_funcs[i] (font); + if (unlikely (status)) + return status; + } } return CAIRO_STATUS_SUCCESS; @@ -1984,6 +2165,12 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset, memcpy (cff_subset->data, data, length); cff_subset->data_length = length; + { + FILE *f; + f=fopen("font.cff", "wb"); + fwrite(data, length, 1, f); + fclose(f); + } cairo_cff_font_destroy (font); return CAIRO_STATUS_SUCCESS; @@ -2012,23 +2199,90 @@ _cairo_cff_subset_fini (cairo_cff_subset_t *subset) } cairo_bool_t -_cairo_cff_scaled_font_is_cff (cairo_scaled_font_t *scaled_font) +_cairo_cff_scaled_font_is_cid_cff (cairo_scaled_font_t *scaled_font) { const cairo_scaled_font_backend_t *backend; cairo_status_t status; + unsigned char *data; unsigned long data_length; + unsigned char *current_ptr; + unsigned char *data_end; + cff_header_t *header; + cff_index_element_t *element; + cairo_hash_table_t *top_dict; + cairo_array_t index; + int size; + cairo_bool_t is_cid = FALSE; backend = scaled_font->backend; if (!backend->load_truetype_table) return FALSE; + /* check for CFF font */ data_length = 0; status = backend->load_truetype_table(scaled_font, TT_TAG_CFF, 0, NULL, &data_length); if (status) - return FALSE;; + return FALSE; - return TRUE; + /* load CFF data */ + data = malloc (data_length); + if (unlikely (data == NULL)) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + return FALSE; + } + + status = backend->load_truetype_table (scaled_font, TT_TAG_CFF, + 0, data, &data_length); + if (unlikely (status)) + goto fail1; + + data_end = data + data_length; + + /* skip header */ + if (data_length < sizeof (cff_header_t)) + goto fail1; + + header = (cff_header_t *) data; + current_ptr = data + header->header_size; + + /* skip name */ + cff_index_init (&index); + status = cff_index_read (&index, ¤t_ptr, data_end); + cff_index_fini (&index); + + if (status) + goto fail1; + + /* read top dict */ + cff_index_init (&index); + status = cff_index_read (&index, ¤t_ptr, data_end); + if (unlikely (status)) + goto fail2; + + status = cff_dict_init (&top_dict); + if (unlikely (status)) + goto fail2; + + element = _cairo_array_index (&index, 0); + status = cff_dict_read (top_dict, element->data, element->length); + if (unlikely (status)) + goto fail3; + + /* check for ROS operator indicating a CID font */ + if (cff_dict_get_operands (top_dict, ROS_OP, &size) != NULL) + is_cid = TRUE; + +fail3: + cff_dict_fini (top_dict); + +fail2: + cff_index_fini (&index); + +fail1: + free (data); + + return is_cid; } static cairo_int_status_t @@ -2133,8 +2387,9 @@ cairo_cff_font_fallback_generate (cairo_cff_font_t *font, cff_header_t header; cairo_array_t *charstring; unsigned char buf[40]; - unsigned char *end_buf; + unsigned char *end_buf, *end_buf2; unsigned int i; + int sid; /* Create header */ header.major = 1; @@ -2145,6 +2400,28 @@ cairo_cff_font_fallback_generate (cairo_cff_font_t *font, /* Create Top Dict */ font->is_cid = FALSE; + + snprintf((char*)buf, sizeof(buf), "CairoFont-%u-%u", + font->scaled_font_subset->font_id, + font->scaled_font_subset->subset_id); + sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index); + status = cff_index_append_copy (&font->strings_subset_index, + (unsigned char *)buf, + strlen((char*)buf)); + if (unlikely (status)) + return status; + + end_buf = encode_integer (buf, sid); + status = cff_dict_set_operands (font->top_dict, FULLNAME_OP, + buf, end_buf - buf); + if (unlikely (status)) + return status; + + status = cff_dict_set_operands (font->top_dict, FAMILYNAME_OP, + buf, end_buf - buf); + if (unlikely (status)) + return status; + end_buf = encode_integer (buf, type2_subset->x_min); end_buf = encode_integer (end_buf, type2_subset->y_min); end_buf = encode_integer (end_buf, type2_subset->x_max); @@ -2160,29 +2437,50 @@ cairo_cff_font_fallback_generate (cairo_cff_font_t *font, if (unlikely (status)) return status; - status = cff_dict_set_operands (font->top_dict, - FDSELECT_OP, buf, end_buf - buf); - if (unlikely (status)) - return status; - status = cff_dict_set_operands (font->top_dict, - FDARRAY_OP, buf, end_buf - buf); - if (unlikely (status)) - return status; + if (font->scaled_font_subset->is_latin) { + status = cff_dict_set_operands (font->top_dict, + ENCODING_OP, buf, end_buf - buf); + if (unlikely (status)) + return status; + + /* Private has two operands - size and offset */ + end_buf2 = encode_integer_max (end_buf, 0); + cff_dict_set_operands (font->top_dict, PRIVATE_OP, buf, end_buf2 - buf); + if (unlikely (status)) + return status; + + } else { + status = cff_dict_set_operands (font->top_dict, + FDSELECT_OP, buf, end_buf - buf); + if (unlikely (status)) + return status; + + status = cff_dict_set_operands (font->top_dict, + FDARRAY_OP, buf, end_buf - buf); + if (unlikely (status)) + return status; + } status = cff_dict_set_operands (font->top_dict, CHARSET_OP, buf, end_buf - buf); if (unlikely (status)) return status; - status = cairo_cff_font_set_ros_strings (font); - if (unlikely (status)) - return status; + if (!font->scaled_font_subset->is_latin) { + status = cairo_cff_font_set_ros_strings (font); + if (unlikely (status)) + return status; - /* Create CID FD dictionary */ - status = cairo_cff_font_create_cid_fontdict (font); - if (unlikely (status)) - return status; + /* Create CID FD dictionary */ + status = cairo_cff_font_create_cid_fontdict (font); + if (unlikely (status)) + return status; + } else { + font->private_dict_offset = malloc (sizeof (int)); + if (unlikely (font->private_dict_offset == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } /* Create charstrings */ for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { @@ -2261,7 +2559,13 @@ _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset, memcpy (cff_subset->data, data, length); cff_subset->data_length = length; - cff_subset->data_length = length; + + { + FILE *f; + f=fopen("font.cff", "wb"); + fwrite(data, length, 1, f); + fclose(f); + } _cairo_type2_charstrings_fini (&type2_subset); cairo_cff_font_destroy (font); diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 7efae8b7e..6e377fa37 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -3888,7 +3888,7 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface, cairo_pdf_resource_t stream, descriptor, cidfont_dict; cairo_pdf_resource_t subset_resource, to_unicode_stream; cairo_pdf_font_t font; - unsigned int i; + unsigned int i, last_glyph; cairo_status_t status; char tag[10]; @@ -3903,6 +3903,8 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface, status = _cairo_pdf_surface_open_stream (surface, NULL, TRUE, + font_subset->is_latin ? + " /Subtype /Type1C\n" : " /Subtype /CIDFontType0C\n"); if (unlikely (status)) return status; @@ -3959,58 +3961,106 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface, (long)(subset->y_max*PDF_UNITS_PER_EM), stream.id); - cidfont_dict = _cairo_pdf_surface_new_object (surface); - if (cidfont_dict.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (font_subset->is_latin) { + /* find last glyph used */ + for (i = 255; i >= 32; i--) + if (font_subset->latin_to_subset_glyph_index[i] > 0) + break; - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Font\n" - " /Subtype /CIDFontType0\n" - " /BaseFont /%s+%s\n" - " /CIDSystemInfo\n" - " << /Registry (Adobe)\n" - " /Ordering (Identity)\n" - " /Supplement 0\n" - " >>\n" - " /FontDescriptor %d 0 R\n" - " /W [0 [", - cidfont_dict.id, - tag, - subset->ps_name, - descriptor.id); - - for (i = 0; i < font_subset->num_glyphs; i++) + last_glyph = i; + _cairo_pdf_surface_update_object (surface, subset_resource); _cairo_output_stream_printf (surface->output, - " %ld", - (long)(subset->widths[i]*PDF_UNITS_PER_EM)); + "%d 0 obj\r\n" + "<< /Type /Font\n" + " /Subtype /Type1\n" + " /BaseFont /%s+%s\n" + " /FirstChar 32\n" + " /LastChar %d\n" + " /FontDescriptor %d 0 R\n" + " /Encoding /WinAnsiEncoding\n" + " /Widths [", + subset_resource.id, + tag, + subset->ps_name, + last_glyph, + descriptor.id); - _cairo_output_stream_printf (surface->output, - " ]]\n" - ">>\n" - "endobj\n"); + for (i = 32; i < last_glyph + 1; i++) { + int glyph = font_subset->latin_to_subset_glyph_index[i]; + if (glyph > 0) { + _cairo_output_stream_printf (surface->output, + " %ld", + (long)(subset->widths[glyph]*PDF_UNITS_PER_EM)); + } else { + _cairo_output_stream_printf (surface->output, " 0"); + } + } - _cairo_pdf_surface_update_object (surface, subset_resource); - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Type /Font\n" - " /Subtype /Type0\n" - " /BaseFont /%s+%s\n" - " /Encoding /Identity-H\n" - " /DescendantFonts [ %d 0 R]\n", - subset_resource.id, - tag, - subset->ps_name, - cidfont_dict.id); + _cairo_output_stream_printf (surface->output, + " ]\n"); - if (to_unicode_stream.id != 0) - _cairo_output_stream_printf (surface->output, - " /ToUnicode %d 0 R\n", - to_unicode_stream.id); + if (to_unicode_stream.id != 0) + _cairo_output_stream_printf (surface->output, + " /ToUnicode %d 0 R\n", + to_unicode_stream.id); - _cairo_output_stream_printf (surface->output, - ">>\n" - "endobj\n"); + _cairo_output_stream_printf (surface->output, + ">>\n" + "endobj\n"); + } else { + cidfont_dict = _cairo_pdf_surface_new_object (surface); + if (cidfont_dict.id == 0) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + _cairo_output_stream_printf (surface->output, + "%d 0 obj\n" + "<< /Type /Font\n" + " /Subtype /CIDFontType0\n" + " /BaseFont /%s+%s\n" + " /CIDSystemInfo\n" + " << /Registry (Adobe)\n" + " /Ordering (Identity)\n" + " /Supplement 0\n" + " >>\n" + " /FontDescriptor %d 0 R\n" + " /W [0 [", + cidfont_dict.id, + tag, + subset->ps_name, + descriptor.id); + + for (i = 0; i < font_subset->num_glyphs; i++) + _cairo_output_stream_printf (surface->output, + " %ld", + (long)(subset->widths[i]*PDF_UNITS_PER_EM)); + + _cairo_output_stream_printf (surface->output, + " ]]\n" + ">>\n" + "endobj\n"); + + _cairo_pdf_surface_update_object (surface, subset_resource); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\n" + "<< /Type /Font\n" + " /Subtype /Type0\n" + " /BaseFont /%s+%s\n" + " /Encoding /Identity-H\n" + " /DescendantFonts [ %d 0 R]\n", + subset_resource.id, + tag, + subset->ps_name, + cidfont_dict.id); + + if (to_unicode_stream.id != 0) + _cairo_output_stream_printf (surface->output, + " /ToUnicode %d 0 R\n", + to_unicode_stream.id); + + _cairo_output_stream_printf (surface->output, + ">>\n" + "endobj\n"); + } font.font_id = font_subset->font_id; font.subset_id = font_subset->subset_id; diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h index 8de49fa06..b1e06b7f3 100644 --- a/src/cairo-scaled-font-subsets-private.h +++ b/src/cairo-scaled-font-subsets-private.h @@ -387,13 +387,13 @@ cairo_private void _cairo_cff_subset_fini (cairo_cff_subset_t *cff_subset); /** - * _cairo_cff_scaled_font_is_cff: + * _cairo_cff_scaled_font_is_cid_cff: * @scaled_font: a #cairo_scaled_font_t * - * Return %TRUE if @scaled_font is a CFF font, otherwise return %FALSE. + * Return %TRUE if @scaled_font is a CID CFF font, otherwise return %FALSE. **/ cairo_bool_t -_cairo_cff_scaled_font_is_cff (cairo_scaled_font_t *scaled_font); +_cairo_cff_scaled_font_is_cid_cff (cairo_scaled_font_t *scaled_font); /** * _cairo_cff_fallback_init: diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c index 79a778ff1..a019851a2 100644 --- a/src/cairo-scaled-font-subsets.c +++ b/src/cairo-scaled-font-subsets.c @@ -121,6 +121,7 @@ typedef struct _cairo_sub_font_collection { unsigned long *glyphs; /* scaled_font_glyph_index */ char **utf8; unsigned int glyphs_size; + int *to_latin_char; unsigned long *latin_to_subset_glyph_index; unsigned int max_glyph; unsigned int num_glyphs; @@ -232,6 +233,7 @@ _cairo_sub_font_glyph_collect (void *entry, void *closure) collection->glyphs[subset_glyph_index] = scaled_font_glyph_index; collection->utf8[subset_glyph_index] = sub_font_glyph->utf8; + collection->to_latin_char[subset_glyph_index] = sub_font_glyph->latin_character; if (sub_font_glyph->is_latin) collection->latin_to_subset_glyph_index[sub_font_glyph->latin_character] = subset_glyph_index; @@ -296,8 +298,8 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, sub_font->font_id = font_id; sub_font->use_latin_subset = parent->use_latin_subset; - if (_cairo_cff_scaled_font_is_cff (scaled_font)) - sub_font->use_latin_subset = FALSE; /* CFF latin subsets are NYI */ + if (_cairo_cff_scaled_font_is_cid_cff (scaled_font)) + sub_font->use_latin_subset = FALSE; /* latin subsets of CID CFF fonts are not supported */ if (sub_font->use_latin_subset) sub_font->current_subset = 1; /* reserve subset 0 for latin glyphs */ @@ -349,16 +351,20 @@ static unsigned int _winansi_0x80_to_0x9f[] = { }; int -_cairo_unicode_to_winansi (unsigned long unicode) +_cairo_unicode_to_winansi (unsigned long uni) { int i; - if (unicode < 0x80 || (unicode >= 0xa0 && unicode <= 0xff)) - return unicode; + /* exclude the extra "hyphen" at 0xad to avoid duplicate glyphnames */ + if ((uni >= 0x20 && uni <= 0x7e) || + (uni >= 0xa1 && uni <= 0xff && uni != 0xad)) + return uni; - for (i = 0; i < 32; i++) { - if (_winansi_0x80_to_0x9f[i] == unicode) - return i + 0x80; + if (uni >= 0x80 && uni <= 0x9f) { + for (i = 0; i < 32; i++) { + if (_winansi_0x80_to_0x9f[i] == uni) + return i + 0x80; + } } return -1; @@ -709,8 +715,10 @@ _cairo_sub_font_collect (void *entry, void *closure) subset.is_latin = FALSE; if (sub_font->use_latin_subset && i == 0) { subset.is_latin = TRUE; + subset.to_latin_char = collection->to_latin_char; subset.latin_to_subset_glyph_index = collection->latin_to_subset_glyph_index; } else { + subset.to_latin_char = NULL; subset.latin_to_subset_glyph_index = NULL; } @@ -1025,14 +1033,18 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t collection.glyphs = _cairo_malloc_ab (collection.glyphs_size, sizeof(unsigned long)); collection.utf8 = _cairo_malloc_ab (collection.glyphs_size, sizeof(char *)); + collection.to_latin_char = _cairo_malloc_ab (collection.glyphs_size, sizeof(int)); collection.latin_to_subset_glyph_index = _cairo_malloc_ab (256, sizeof(unsigned long)); if (unlikely (collection.glyphs == NULL || collection.utf8 == NULL || + collection.to_latin_char == NULL || collection.latin_to_subset_glyph_index == NULL)) { if (collection.glyphs != NULL) free (collection.glyphs); if (collection.utf8 != NULL) free (collection.utf8); + if (collection.to_latin_char != NULL) + free (collection.to_latin_char); if (collection.latin_to_subset_glyph_index != NULL) free (collection.latin_to_subset_glyph_index); @@ -1056,6 +1068,7 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t } free (collection.utf8); free (collection.glyphs); + free (collection.to_latin_char); free (collection.latin_to_subset_glyph_index); return collection.status; @@ -1191,7 +1204,7 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset if (utf16_len == 1) { int ch = _cairo_unicode_to_winansi (utf16[0]); - if (ch > 0) + if (ch > 0 && _cairo_winansi_to_glyphname (ch)) strncpy (buf, _cairo_winansi_to_glyphname (ch), sizeof (buf)); else snprintf (buf, sizeof (buf), "uni%04X", (int) utf16[0]); diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c index 93469513a..45e6e477a 100644 --- a/src/cairo-type1-subset.c +++ b/src/cairo-type1-subset.c @@ -836,7 +836,7 @@ static const char *winansi_encoding[256] = { NULL, NULL, NULL, NULL, /* 32 */ "space", "exclam", "quotedbl", "numbersign", - "dollar", "percent", "ampersand", "quoteright", + "dollar", "percent", "ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", /* 48 */ @@ -855,7 +855,7 @@ static const char *winansi_encoding[256] = { "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", /* 96 */ - "quoteleft", "a", "b", "c", + "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", @@ -868,17 +868,18 @@ static const char *winansi_encoding[256] = { "Euro", NULL, "quotesinglbase","florin", "quotedblbase", "ellipsis", "dagger", "daggerdbl", "circumflex", "perthousand", "Scaron", "guilsinglleft", - "OE", "bullet", "Zcaron", NULL, + "OE", NULL, "Zcaron", NULL, /* 144 */ NULL, "quoteleft", "quoteright", "quotedblleft", "quotedblright","bullet", "endash", "emdash", "tilde", "trademark", "scaron", "guilsinglright", - "oe", "bullet", "zcaron", "Ydieresis", + "oe", NULL, "zcaron", "Ydieresis", /* 160 */ - "space", "exclamdown", "cent", "sterling", + NULL, "exclamdown", "cent", "sterling", "currency", "yen", "brokenbar", "section", "dieresis", "copyright", "ordfeminine", "guillemotleft", - "logicalnot", "hyphen", "registered", "macron", + /* 173 is also "hyphen" but we leave this NULL to avoid duplicate names */ + "logicalnot", NULL, "registered", "macron", /* 176 */ "degree", "plusminus", "twosuperior", "threesuperior", "acute", "mu", "paragraph", "periodcentered", diff --git a/src/cairoint.h b/src/cairoint.h index d0ae66a7d..73386d19a 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -433,9 +433,11 @@ typedef struct _cairo_scaled_font_subset { * Value of glyphs array is scaled_font_glyph_index. */ unsigned long *glyphs; + unsigned long *to_unicode; char **utf8; char **glyph_names; + int *to_latin_char; unsigned long *latin_to_subset_glyph_index; unsigned int num_glyphs; cairo_bool_t is_composite;