Rev 1897 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1897 | Rev 3959 | ||
---|---|---|---|
Line 40... | Line 40... | ||
40 | * http://www.microsoft.com/typography/specs/default.htm |
40 | * http://www.microsoft.com/typography/specs/default.htm |
41 | */ |
41 | */ |
Line 42... | Line 42... | ||
42 | 42 | ||
43 | #define _BSD_SOURCE /* for snprintf(), strdup() */ |
43 | #define _BSD_SOURCE /* for snprintf(), strdup() */ |
- | 44 | #include "cairoint.h" |
|
- | 45 | ||
44 | #include "cairoint.h" |
46 | #include "cairo-array-private.h" |
Line 45... | Line 47... | ||
45 | #include "cairo-error-private.h" |
47 | #include "cairo-error-private.h" |
Line 46... | Line 48... | ||
46 | 48 | ||
Line 90... | Line 92... | ||
90 | cairo_array_t string_offsets; |
92 | cairo_array_t string_offsets; |
91 | unsigned long last_offset; |
93 | unsigned long last_offset; |
92 | unsigned long last_boundary; |
94 | unsigned long last_boundary; |
93 | int *parent_to_subset; |
95 | int *parent_to_subset; |
94 | cairo_status_t status; |
96 | cairo_status_t status; |
95 | - | ||
- | 97 | cairo_bool_t is_pdf; |
|
96 | }; |
98 | }; |
Line 97... | Line 99... | ||
97 | 99 | ||
98 | /* |
100 | /* |
99 | * Test that the structs we define for TrueType tables have the |
101 | * Test that the structs we define for TrueType tables have the |
Line 120... | Line 122... | ||
120 | 122 | ||
121 | static cairo_status_t |
123 | static cairo_status_t |
122 | _cairo_truetype_font_set_error (cairo_truetype_font_t *font, |
124 | _cairo_truetype_font_set_error (cairo_truetype_font_t *font, |
123 | cairo_status_t status) |
125 | cairo_status_t status) |
- | 126 | { |
|
124 | { |
127 | if (status == CAIRO_STATUS_SUCCESS || |
125 | if (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED) |
128 | status == (int)CAIRO_INT_STATUS_UNSUPPORTED) |
Line 126... | Line 129... | ||
126 | return status; |
129 | return status; |
Line 127... | Line 130... | ||
127 | 130 | ||
128 | _cairo_status_set_error (&font->status, status); |
131 | _cairo_status_set_error (&font->status, status); |
Line 129... | Line 132... | ||
129 | 132 | ||
130 | return _cairo_error (status); |
133 | return _cairo_error (status); |
- | 134 | } |
|
131 | } |
135 | |
132 | 136 | static cairo_status_t |
|
133 | static cairo_status_t |
137 | _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, |
134 | _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, |
138 | cairo_bool_t is_pdf, |
135 | cairo_truetype_font_t **font_return) |
139 | cairo_truetype_font_t **font_return) |
Line 153... | Line 157... | ||
153 | * |
157 | * |
154 | * if (cairo_font_options_get_vertical_layout (scaled_font_subset->scaled_font)) |
158 | * if (cairo_font_options_get_vertical_layout (scaled_font_subset->scaled_font)) |
155 | * return CAIRO_INT_STATUS_UNSUPPORTED; |
159 | * return CAIRO_INT_STATUS_UNSUPPORTED; |
156 | */ |
160 | */ |
Line -... | Line 161... | ||
- | 161 | ||
- | 162 | /* We need to use a fallback font generated from the synthesized outlines. */ |
|
- | 163 | if (backend->is_synthetic && backend->is_synthetic (scaled_font_subset->scaled_font)) |
|
- | 164 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
157 | 165 | ||
158 | size = sizeof (tt_head_t); |
166 | size = sizeof (tt_head_t); |
159 | status = backend->load_truetype_table (scaled_font_subset->scaled_font, |
167 | status = backend->load_truetype_table (scaled_font_subset->scaled_font, |
160 | TT_TAG_head, 0, |
168 | TT_TAG_head, 0, |
161 | (unsigned char *) &head, |
169 | (unsigned char *) &head, |
Line 204... | Line 212... | ||
204 | if (unlikely (font->parent_to_subset == NULL)) { |
212 | if (unlikely (font->parent_to_subset == NULL)) { |
205 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
213 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
206 | goto fail2; |
214 | goto fail2; |
207 | } |
215 | } |
Line -... | Line 216... | ||
- | 216 | ||
208 | 217 | font->is_pdf = is_pdf; |
|
209 | font->base.num_glyphs = 0; |
218 | font->base.num_glyphs = 0; |
210 | font->base.x_min = (int16_t) be16_to_cpu (head.x_min); |
219 | font->base.x_min = (int16_t) be16_to_cpu (head.x_min); |
211 | font->base.y_min = (int16_t) be16_to_cpu (head.y_min); |
220 | font->base.y_min = (int16_t) be16_to_cpu (head.y_min); |
212 | font->base.x_max = (int16_t) be16_to_cpu (head.x_max); |
221 | font->base.x_max = (int16_t) be16_to_cpu (head.x_max); |
Line 260... | Line 269... | ||
260 | free (font->base.widths); |
269 | free (font->base.widths); |
261 | fail4: |
270 | fail4: |
262 | free (font->base.ps_name); |
271 | free (font->base.ps_name); |
263 | fail3: |
272 | fail3: |
264 | free (font->parent_to_subset); |
273 | free (font->parent_to_subset); |
265 | if (font->base.font_name) |
- | |
266 | free (font->base.font_name); |
274 | free (font->base.font_name); |
267 | fail2: |
275 | fail2: |
268 | free (font->glyphs); |
276 | free (font->glyphs); |
269 | fail1: |
277 | fail1: |
270 | _cairo_array_fini (&font->output); |
278 | _cairo_array_fini (&font->output); |
Line 277... | Line 285... | ||
277 | cairo_truetype_font_destroy (cairo_truetype_font_t *font) |
285 | cairo_truetype_font_destroy (cairo_truetype_font_t *font) |
278 | { |
286 | { |
279 | _cairo_array_fini (&font->string_offsets); |
287 | _cairo_array_fini (&font->string_offsets); |
280 | free (font->base.widths); |
288 | free (font->base.widths); |
281 | free (font->base.ps_name); |
289 | free (font->base.ps_name); |
282 | if (font->base.font_name) |
- | |
283 | free (font->base.font_name); |
290 | free (font->base.font_name); |
284 | free (font->parent_to_subset); |
291 | free (font->parent_to_subset); |
285 | free (font->glyphs); |
292 | free (font->glyphs); |
286 | _cairo_array_fini (&font->output); |
293 | _cairo_array_fini (&font->output); |
287 | free (font); |
294 | free (font); |
Line 391... | Line 398... | ||
391 | font->last_boundary = boundary; |
398 | font->last_boundary = boundary; |
Line 392... | Line 399... | ||
392 | 399 | ||
393 | return CAIRO_STATUS_SUCCESS; |
400 | return CAIRO_STATUS_SUCCESS; |
Line -... | Line 401... | ||
- | 401 | } |
|
- | 402 | ||
- | 403 | typedef struct _cmap_unicode_range { |
|
- | 404 | unsigned int start; |
|
- | 405 | unsigned int end; |
|
- | 406 | } cmap_unicode_range_t; |
|
- | 407 | ||
- | 408 | static cmap_unicode_range_t winansi_unicode_ranges[] = { |
|
- | 409 | { 0x0020, 0x007f }, |
|
- | 410 | { 0x00a0, 0x00ff }, |
|
- | 411 | { 0x0152, 0x0153 }, |
|
- | 412 | { 0x0160, 0x0161 }, |
|
- | 413 | { 0x0178, 0x0178 }, |
|
- | 414 | { 0x017d, 0x017e }, |
|
- | 415 | { 0x0192, 0x0192 }, |
|
- | 416 | { 0x02c6, 0x02c6 }, |
|
- | 417 | { 0x02dc, 0x02dc }, |
|
- | 418 | { 0x2013, 0x2026 }, |
|
- | 419 | { 0x2030, 0x2030 }, |
|
- | 420 | { 0x2039, 0x203a }, |
|
- | 421 | { 0x20ac, 0x20ac }, |
|
- | 422 | { 0x2122, 0x2122 }, |
|
394 | } |
423 | }; |
395 | 424 | ||
396 | static cairo_status_t |
425 | static cairo_status_t |
397 | cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font, |
426 | cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font, |
- | 427 | unsigned long tag) |
|
398 | unsigned long tag) |
428 | { |
- | 429 | int i; |
|
- | 430 | unsigned int j; |
|
- | 431 | int range_offset; |
|
- | 432 | int num_ranges; |
|
- | 433 | int entry_selector; |
|
- | 434 | int length; |
|
- | 435 | ||
- | 436 | num_ranges = ARRAY_LENGTH (winansi_unicode_ranges); |
|
- | 437 | ||
- | 438 | length = 16 + (num_ranges + 1)*8; |
|
- | 439 | for (i = 0; i < num_ranges; i++) |
|
- | 440 | length += (winansi_unicode_ranges[i].end - winansi_unicode_ranges[i].start + 1)*2; |
|
- | 441 | ||
- | 442 | entry_selector = 0; |
|
- | 443 | while ((1 << entry_selector) <= (num_ranges + 1)) |
|
- | 444 | entry_selector++; |
|
Line 399... | Line 445... | ||
399 | { |
445 | |
400 | unsigned int i; |
446 | entry_selector--; |
Line 401... | Line 447... | ||
401 | 447 | ||
402 | cairo_truetype_font_write_be16 (font, 0); /* Table version */ |
448 | cairo_truetype_font_write_be16 (font, 0); /* Table version */ |
403 | cairo_truetype_font_write_be16 (font, 2); /* Num tables */ |
449 | cairo_truetype_font_write_be16 (font, 1); /* Num tables */ |
Line 404... | Line -... | ||
404 | - | ||
405 | cairo_truetype_font_write_be16 (font, 3); /* Platform */ |
- | |
406 | cairo_truetype_font_write_be16 (font, 0); /* Encoding */ |
- | |
407 | cairo_truetype_font_write_be32 (font, 20); /* Offset to start of table */ |
- | |
408 | 450 | ||
Line 409... | Line 451... | ||
409 | cairo_truetype_font_write_be16 (font, 1); /* Platform */ |
451 | cairo_truetype_font_write_be16 (font, 3); /* Platform */ |
410 | cairo_truetype_font_write_be16 (font, 0); /* Encoding */ |
452 | cairo_truetype_font_write_be16 (font, 1); /* Encoding */ |
411 | cairo_truetype_font_write_be32 (font, 52); /* Offset to start of table */ |
453 | cairo_truetype_font_write_be32 (font, 12); /* Offset to start of table */ |
412 | 454 | ||
413 | /* Output a format 4 encoding table. */ |
455 | /* Output a format 4 encoding table for the winansi encoding */ |
414 | 456 | ||
415 | cairo_truetype_font_write_be16 (font, 4); /* Format */ |
457 | cairo_truetype_font_write_be16 (font, 4); /* Format */ |
- | 458 | cairo_truetype_font_write_be16 (font, length); /* Length */ |
|
416 | cairo_truetype_font_write_be16 (font, 32); /* Length */ |
459 | cairo_truetype_font_write_be16 (font, 0); /* Version */ |
417 | cairo_truetype_font_write_be16 (font, 0); /* Version */ |
460 | cairo_truetype_font_write_be16 (font, num_ranges*2 + 2); /* 2*segcount */ |
- | 461 | cairo_truetype_font_write_be16 (font, (1 << (entry_selector + 1))); /* searchrange */ |
|
418 | cairo_truetype_font_write_be16 (font, 4); /* 2*segcount */ |
462 | cairo_truetype_font_write_be16 (font, entry_selector); /* entry selector */ |
- | 463 | cairo_truetype_font_write_be16 (font, num_ranges*2 + 2 - (1 << (entry_selector + 1))); /* rangeshift */ |
|
- | 464 | for (i = 0; i < num_ranges; i++) |
|
419 | cairo_truetype_font_write_be16 (font, 4); /* searchrange */ |
465 | cairo_truetype_font_write_be16 (font, winansi_unicode_ranges[i].end); /* end count[] */ |
420 | cairo_truetype_font_write_be16 (font, 1); /* entry selector */ |
466 | cairo_truetype_font_write_be16 (font, 0xffff); /* end count[] */ |
- | 467 | ||
- | 468 | cairo_truetype_font_write_be16 (font, 0); /* reserved */ |
|
421 | cairo_truetype_font_write_be16 (font, 0); /* rangeshift */ |
469 | |
422 | cairo_truetype_font_write_be16 (font, 0xf000 + font->base.num_glyphs - 1); /* end count[0] */ |
470 | for (i = 0; i < num_ranges; i++) |
- | 471 | cairo_truetype_font_write_be16 (font, winansi_unicode_ranges[i].start); /* startCode[] */ |
|
- | 472 | cairo_truetype_font_write_be16 (font, 0xffff); /* startCode[] */ |
|
- | 473 | ||
423 | cairo_truetype_font_write_be16 (font, 0xffff); /* end count[1] */ |
474 | for (i = 0; i < num_ranges; i++) |
- | 475 | cairo_truetype_font_write_be16 (font, 0x0000); /* delta[] */ |
|
- | 476 | cairo_truetype_font_write_be16 (font, 1); /* delta[] */ |
|
424 | cairo_truetype_font_write_be16 (font, 0); /* reserved */ |
477 | |
425 | cairo_truetype_font_write_be16 (font, 0xf000); /* startCode[0] */ |
478 | range_offset = num_ranges*2 + 2; |
- | 479 | for (i = 0; i < num_ranges; i++) { |
|
- | 480 | cairo_truetype_font_write_be16 (font, range_offset); /* rangeOffset[] */ |
|
426 | cairo_truetype_font_write_be16 (font, 0xffff); /* startCode[1] */ |
481 | range_offset += (winansi_unicode_ranges[i].end - winansi_unicode_ranges[i].start + 1)*2 - 2; |
- | 482 | } |
|
427 | cairo_truetype_font_write_be16 (font, 0x1000); /* delta[0] */ |
483 | cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[] */ |
428 | cairo_truetype_font_write_be16 (font, 1); /* delta[1] */ |
484 | |
429 | cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[0] */ |
485 | for (i = 0; i < num_ranges; i++) { |
430 | cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[1] */ |
486 | for (j = winansi_unicode_ranges[i].start; j < winansi_unicode_ranges[i].end + 1; j++) { |
431 | - | ||
432 | /* Output a format 6 encoding table. */ |
- | |
433 | 487 | int ch = _cairo_unicode_to_winansi (j); |
|
434 | cairo_truetype_font_write_be16 (font, 6); |
488 | int glyph; |
- | 489 | ||
- | 490 | if (ch > 0) |
|
Line 435... | Line 491... | ||
435 | cairo_truetype_font_write_be16 (font, 10 + 2 * font->base.num_glyphs); |
491 | glyph = font->scaled_font_subset->latin_to_subset_glyph_index[ch]; |
436 | cairo_truetype_font_write_be16 (font, 0); |
492 | else |
Line 437... | Line 493... | ||
437 | cairo_truetype_font_write_be16 (font, 0); /* First character */ |
493 | glyph = 0; |
Line 983... | Line 1039... | ||
983 | * in which the callback functions will be called. |
1039 | * in which the callback functions will be called. |
984 | * |
1040 | * |
985 | * The tables in the table directory must be listed in alphabetical |
1041 | * The tables in the table directory must be listed in alphabetical |
986 | * order. The "cvt", "fpgm", and "prep" are optional tables. They |
1042 | * order. The "cvt", "fpgm", and "prep" are optional tables. They |
987 | * will only be embedded in the subset if they exist in the source |
1043 | * will only be embedded in the subset if they exist in the source |
988 | * font. The pos parameter of cairo_truetype_font_add_truetype_table() |
1044 | * font. "cmap" is only embedded for latin fonts. The pos parameter of |
- | 1045 | * cairo_truetype_font_add_truetype_table() specifies the position of |
|
989 | * specifies the position of the table in the table directory. |
1046 | * the table in the table directory. |
990 | */ |
1047 | */ |
991 | static void |
1048 | static void |
992 | cairo_truetype_font_create_truetype_table_list (cairo_truetype_font_t *font) |
1049 | cairo_truetype_font_create_truetype_table_list (cairo_truetype_font_t *font) |
993 | { |
1050 | { |
994 | cairo_bool_t has_cvt = FALSE; |
1051 | cairo_bool_t has_cvt = FALSE; |
Line 998... | Line 1055... | ||
998 | int pos; |
1055 | int pos; |
Line 999... | Line 1056... | ||
999 | 1056 | ||
1000 | size = 0; |
1057 | size = 0; |
1001 | if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1058 | if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1002 | TT_TAG_cvt, 0, NULL, |
1059 | TT_TAG_cvt, 0, NULL, |
1003 | &size) == CAIRO_STATUS_SUCCESS) |
1060 | &size) == CAIRO_INT_STATUS_SUCCESS) |
Line 1004... | Line 1061... | ||
1004 | has_cvt = TRUE; |
1061 | has_cvt = TRUE; |
1005 | 1062 | ||
1006 | size = 0; |
1063 | size = 0; |
1007 | if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1064 | if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1008 | TT_TAG_fpgm, 0, NULL, |
1065 | TT_TAG_fpgm, 0, NULL, |
Line 1009... | Line 1066... | ||
1009 | &size) == CAIRO_STATUS_SUCCESS) |
1066 | &size) == CAIRO_INT_STATUS_SUCCESS) |
1010 | has_fpgm = TRUE; |
1067 | has_fpgm = TRUE; |
1011 | 1068 | ||
1012 | size = 0; |
1069 | size = 0; |
1013 | if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
1070 | if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, |
Line 1014... | Line 1071... | ||
1014 | TT_TAG_prep, 0, NULL, |
1071 | TT_TAG_prep, 0, NULL, |
1015 | &size) == CAIRO_STATUS_SUCCESS) |
1072 | &size) == CAIRO_INT_STATUS_SUCCESS) |
- | 1073 | has_prep = TRUE; |
|
- | 1074 | ||
1016 | has_prep = TRUE; |
1075 | font->num_tables = 0; |
1017 | 1076 | pos = 0; |
|
1018 | font->num_tables = 0; |
1077 | if (font->is_pdf && font->scaled_font_subset->is_latin) |
1019 | pos = 1; |
1078 | pos++; |
1020 | if (has_cvt) |
1079 | if (has_cvt) |
Line 1021... | Line 1080... | ||
1021 | pos++; |
1080 | pos++; |
- | 1081 | if (has_fpgm) |
|
1022 | if (has_fpgm) |
1082 | pos++; |
1023 | pos++; |
1083 | cairo_truetype_font_add_truetype_table (font, TT_TAG_glyf, cairo_truetype_font_write_glyf_table, pos); |
1024 | cairo_truetype_font_add_truetype_table (font, TT_TAG_glyf, cairo_truetype_font_write_glyf_table, pos); |
1084 | |
1025 | 1085 | pos = 0; |
|
1026 | pos = 0; |
1086 | if (font->is_pdf && font->scaled_font_subset->is_latin) |
Line 1037... | Line 1097... | ||
1037 | cairo_truetype_font_add_truetype_table (font, TT_TAG_maxp, cairo_truetype_font_write_maxp_table, pos++); |
1097 | cairo_truetype_font_add_truetype_table (font, TT_TAG_maxp, cairo_truetype_font_write_maxp_table, pos++); |
1038 | if (has_prep) |
1098 | if (has_prep) |
1039 | cairo_truetype_font_add_truetype_table (font, TT_TAG_prep, cairo_truetype_font_write_generic_table, pos); |
1099 | cairo_truetype_font_add_truetype_table (font, TT_TAG_prep, cairo_truetype_font_write_generic_table, pos); |
1040 | } |
1100 | } |
Line 1041... | Line 1101... | ||
1041 | 1101 | ||
1042 | cairo_status_t |
1102 | static cairo_status_t |
1043 | _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset, |
1103 | cairo_truetype_subset_init_internal (cairo_truetype_subset_t *truetype_subset, |
- | 1104 | cairo_scaled_font_subset_t *font_subset, |
|
1044 | cairo_scaled_font_subset_t *font_subset) |
1105 | cairo_bool_t is_pdf) |
1045 | { |
1106 | { |
1046 | cairo_truetype_font_t *font = NULL; |
1107 | cairo_truetype_font_t *font = NULL; |
1047 | cairo_status_t status; |
1108 | cairo_status_t status; |
1048 | const char *data = NULL; /* squelch bogus compiler warning */ |
1109 | const char *data = NULL; /* squelch bogus compiler warning */ |
1049 | unsigned long length = 0; /* squelch bogus compiler warning */ |
1110 | unsigned long length = 0; /* squelch bogus compiler warning */ |
1050 | unsigned long offsets_length; |
1111 | unsigned long offsets_length; |
1051 | unsigned int i; |
1112 | unsigned int i; |
1052 | const unsigned long *string_offsets = NULL; |
1113 | const unsigned long *string_offsets = NULL; |
Line 1053... | Line 1114... | ||
1053 | unsigned long num_strings = 0; |
1114 | unsigned long num_strings = 0; |
1054 | 1115 | ||
1055 | status = _cairo_truetype_font_create (font_subset, &font); |
1116 | status = _cairo_truetype_font_create (font_subset, is_pdf, &font); |
Line 1056... | Line 1117... | ||
1056 | if (unlikely (status)) |
1117 | if (unlikely (status)) |
1057 | return status; |
1118 | return status; |
Line 1074... | Line 1135... | ||
1074 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1135 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1075 | goto fail1; |
1136 | goto fail1; |
1076 | } |
1137 | } |
Line 1077... | Line 1138... | ||
1077 | 1138 | ||
1078 | if (font->base.font_name != NULL) { |
1139 | if (font->base.font_name != NULL) { |
1079 | truetype_subset->font_name = strdup (font->base.font_name); |
1140 | truetype_subset->family_name_utf8 = strdup (font->base.font_name); |
1080 | if (unlikely (truetype_subset->font_name == NULL)) { |
1141 | if (unlikely (truetype_subset->family_name_utf8 == NULL)) { |
1081 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1142 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1082 | goto fail2; |
1143 | goto fail2; |
1083 | } |
1144 | } |
1084 | } else { |
1145 | } else { |
1085 | truetype_subset->font_name = NULL; |
1146 | truetype_subset->family_name_utf8 = NULL; |
Line 1086... | Line 1147... | ||
1086 | } |
1147 | } |
1087 | 1148 | ||
1088 | /* The widths array returned must contain only widths for the |
1149 | /* The widths array returned must contain only widths for the |
Line 1138... | Line 1199... | ||
1138 | fail5: |
1199 | fail5: |
1139 | free (truetype_subset->data); |
1200 | free (truetype_subset->data); |
1140 | fail4: |
1201 | fail4: |
1141 | free (truetype_subset->widths); |
1202 | free (truetype_subset->widths); |
1142 | fail3: |
1203 | fail3: |
1143 | if (truetype_subset->font_name) |
- | |
1144 | free (truetype_subset->font_name); |
1204 | free (truetype_subset->family_name_utf8); |
1145 | fail2: |
1205 | fail2: |
1146 | free (truetype_subset->ps_name); |
1206 | free (truetype_subset->ps_name); |
1147 | fail1: |
1207 | fail1: |
1148 | cairo_truetype_font_destroy (font); |
1208 | cairo_truetype_font_destroy (font); |
Line 1149... | Line 1209... | ||
1149 | 1209 | ||
1150 | return status; |
1210 | return status; |
Line -... | Line 1211... | ||
- | 1211 | } |
|
- | 1212 | ||
- | 1213 | cairo_status_t |
|
- | 1214 | _cairo_truetype_subset_init_ps (cairo_truetype_subset_t *truetype_subset, |
|
- | 1215 | cairo_scaled_font_subset_t *font_subset) |
|
- | 1216 | { |
|
- | 1217 | return cairo_truetype_subset_init_internal (truetype_subset, font_subset, FALSE); |
|
- | 1218 | } |
|
- | 1219 | ||
- | 1220 | cairo_status_t |
|
- | 1221 | _cairo_truetype_subset_init_pdf (cairo_truetype_subset_t *truetype_subset, |
|
- | 1222 | cairo_scaled_font_subset_t *font_subset) |
|
- | 1223 | { |
|
- | 1224 | return cairo_truetype_subset_init_internal (truetype_subset, font_subset, TRUE); |
|
1151 | } |
1225 | } |
1152 | 1226 | ||
1153 | void |
1227 | void |
1154 | _cairo_truetype_subset_fini (cairo_truetype_subset_t *subset) |
1228 | _cairo_truetype_subset_fini (cairo_truetype_subset_t *subset) |
1155 | { |
- | |
1156 | free (subset->ps_name); |
1229 | { |
1157 | if (subset->font_name) |
1230 | free (subset->ps_name); |
1158 | free (subset->font_name); |
1231 | free (subset->family_name_utf8); |
1159 | free (subset->widths); |
1232 | free (subset->widths); |
1160 | free (subset->data); |
1233 | free (subset->data); |
Line 1175... | Line 1248... | ||
1175 | unsigned long size; |
1248 | unsigned long size; |
1176 | uint16_t *start_code; |
1249 | uint16_t *start_code; |
1177 | uint16_t *end_code; |
1250 | uint16_t *end_code; |
1178 | uint16_t *delta; |
1251 | uint16_t *delta; |
1179 | uint16_t *range_offset; |
1252 | uint16_t *range_offset; |
1180 | uint16_t *glyph_array; |
- | |
1181 | uint16_t c; |
1253 | uint16_t c; |
Line 1182... | Line 1254... | ||
1182 | 1254 | ||
1183 | backend = scaled_font->backend; |
1255 | backend = scaled_font->backend; |
1184 | size = 4; |
1256 | size = 4; |
Line 1215... | Line 1287... | ||
1215 | 1287 | ||
1216 | end_code = map->endCount; |
1288 | end_code = map->endCount; |
1217 | start_code = &(end_code[num_segments + 1]); |
1289 | start_code = &(end_code[num_segments + 1]); |
1218 | delta = &(start_code[num_segments]); |
1290 | delta = &(start_code[num_segments]); |
1219 | range_offset = &(delta[num_segments]); |
- | |
Line 1220... | Line 1291... | ||
1220 | glyph_array = &(range_offset[num_segments]); |
1291 | range_offset = &(delta[num_segments]); |
1221 | 1292 | ||
1222 | /* search for glyph in segments with rangeOffset=0 */ |
1293 | /* search for glyph in segments with rangeOffset=0 */ |
1223 | for (i = 0; i < num_segments; i++) { |
1294 | for (i = 0; i < num_segments; i++) { |
Line 1268... | Line 1339... | ||
1268 | cairo_int_status_t |
1339 | cairo_int_status_t |
1269 | _cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font, |
1340 | _cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font, |
1270 | unsigned long index, |
1341 | unsigned long index, |
1271 | uint32_t *ucs4) |
1342 | uint32_t *ucs4) |
1272 | { |
1343 | { |
1273 | cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; |
1344 | cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; |
1274 | const cairo_scaled_font_backend_t *backend; |
1345 | const cairo_scaled_font_backend_t *backend; |
1275 | tt_cmap_t *cmap; |
1346 | tt_cmap_t *cmap; |
1276 | char buf[4]; |
1347 | char buf[4]; |
1277 | int num_tables, i; |
1348 | int num_tables, i; |
1278 | unsigned long size; |
1349 | unsigned long size; |
Line 1320... | Line 1391... | ||
1320 | free (cmap); |
1391 | free (cmap); |
Line 1321... | Line 1392... | ||
1321 | 1392 | ||
1322 | return status; |
1393 | return status; |
Line -... | Line 1394... | ||
- | 1394 | } |
|
- | 1395 | ||
- | 1396 | static cairo_status_t |
|
- | 1397 | find_name (tt_name_t *name, int name_id, int platform, int encoding, int language, char **str_out) |
|
- | 1398 | { |
|
- | 1399 | tt_name_record_t *record; |
|
- | 1400 | int i, len; |
|
- | 1401 | char *str; |
|
- | 1402 | char *p; |
|
- | 1403 | cairo_bool_t has_tag; |
|
- | 1404 | cairo_status_t status; |
|
- | 1405 | ||
- | 1406 | str = NULL; |
|
- | 1407 | for (i = 0; i < be16_to_cpu (name->num_records); i++) { |
|
- | 1408 | record = &(name->records[i]); |
|
- | 1409 | if (be16_to_cpu (record->name) == name_id && |
|
- | 1410 | be16_to_cpu (record->platform) == platform && |
|
- | 1411 | be16_to_cpu (record->encoding) == encoding && |
|
- | 1412 | (language == -1 || be16_to_cpu (record->language) == language)) { |
|
- | 1413 | ||
- | 1414 | str = malloc (be16_to_cpu (record->length) + 1); |
|
- | 1415 | if (str == NULL) |
|
- | 1416 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 1417 | ||
- | 1418 | len = be16_to_cpu (record->length); |
|
- | 1419 | memcpy (str, |
|
- | 1420 | ((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset), |
|
- | 1421 | len); |
|
- | 1422 | str[be16_to_cpu (record->length)] = 0; |
|
- | 1423 | break; |
|
- | 1424 | } |
|
- | 1425 | } |
|
- | 1426 | if (str == NULL) { |
|
- | 1427 | *str_out = NULL; |
|
- | 1428 | return CAIRO_STATUS_SUCCESS; |
|
- | 1429 | } |
|
- | 1430 | ||
- | 1431 | if (platform == 3) { /* Win platform, unicode encoding */ |
|
- | 1432 | /* convert to utf8 */ |
|
- | 1433 | int size = 0; |
|
- | 1434 | char *utf8; |
|
- | 1435 | uint16_t *u = (uint16_t *) str; |
|
- | 1436 | int u_len = len/2; |
|
- | 1437 | ||
- | 1438 | for (i = 0; i < u_len; i++) |
|
- | 1439 | size += _cairo_ucs4_to_utf8 (be16_to_cpu(u[i]), NULL); |
|
- | 1440 | ||
- | 1441 | utf8 = malloc (size + 1); |
|
- | 1442 | if (utf8 == NULL) { |
|
- | 1443 | status =_cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 1444 | goto fail; |
|
- | 1445 | } |
|
- | 1446 | p = utf8; |
|
- | 1447 | for (i = 0; i < u_len; i++) |
|
- | 1448 | p += _cairo_ucs4_to_utf8 (be16_to_cpu(u[i]), p); |
|
- | 1449 | *p = 0; |
|
- | 1450 | free (str); |
|
- | 1451 | str = utf8; |
|
- | 1452 | } else if (platform == 1) { /* Mac platform, Mac Roman encoding */ |
|
- | 1453 | /* Replace characters above 127 with underscores. We could use |
|
- | 1454 | * a lookup table to convert to unicode but since most fonts |
|
- | 1455 | * include a unicode name this is just a rarely used fallback. */ |
|
- | 1456 | for (i = 0; i < len; i++) { |
|
- | 1457 | if ((unsigned char)str[i] > 127) |
|
- | 1458 | str[i] = '_'; |
|
- | 1459 | } |
|
- | 1460 | } |
|
- | 1461 | ||
- | 1462 | /* If font name is prefixed with a PDF subset tag, strip it off. */ |
|
- | 1463 | p = str; |
|
- | 1464 | len = strlen (str); |
|
- | 1465 | has_tag = FALSE; |
|
- | 1466 | if (len > 7 && p[6] == '+') { |
|
- | 1467 | has_tag = TRUE; |
|
- | 1468 | for (i = 0; i < 6; i++) { |
|
- | 1469 | if (p[i] < 'A' || p[i] > 'Z') { |
|
- | 1470 | has_tag = FALSE; |
|
- | 1471 | break; |
|
- | 1472 | } |
|
- | 1473 | } |
|
- | 1474 | } |
|
- | 1475 | if (has_tag) { |
|
- | 1476 | p = malloc (len - 6); |
|
- | 1477 | if (unlikely (p == NULL)) { |
|
- | 1478 | status =_cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 1479 | goto fail; |
|
- | 1480 | } |
|
- | 1481 | memcpy (p, str + 7, len - 7); |
|
- | 1482 | p[len-7] = 0; |
|
- | 1483 | free (str); |
|
- | 1484 | str = p; |
|
- | 1485 | } |
|
- | 1486 | ||
- | 1487 | *str_out = str; |
|
- | 1488 | ||
- | 1489 | return CAIRO_STATUS_SUCCESS; |
|
- | 1490 | ||
- | 1491 | fail: |
|
- | 1492 | free (str); |
|
- | 1493 | ||
- | 1494 | return status; |
|
1323 | } |
1495 | } |
1324 | 1496 | ||
1325 | cairo_int_status_t |
1497 | cairo_int_status_t |
1326 | _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font, |
1498 | _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font, |
1327 | char **ps_name_out, |
1499 | char **ps_name_out, |
1328 | char **font_name_out) |
1500 | char **font_name_out) |
1329 | { |
1501 | { |
1330 | cairo_status_t status; |
1502 | cairo_status_t status; |
1331 | const cairo_scaled_font_backend_t *backend; |
- | |
1332 | tt_name_t *name; |
1503 | const cairo_scaled_font_backend_t *backend; |
1333 | tt_name_record_t *record; |
- | |
1334 | unsigned long size; |
1504 | tt_name_t *name; |
1335 | int i, j; |
1505 | unsigned long size; |
Line 1336... | Line 1506... | ||
1336 | char *ps_name = NULL; |
1506 | char *ps_name = NULL; |
1337 | char *font_name = NULL; |
1507 | char *family_name = NULL; |
1338 | 1508 | ||
Line 1357... | Line 1527... | ||
1357 | (unsigned char *) name, |
1527 | (unsigned char *) name, |
1358 | &size); |
1528 | &size); |
1359 | if (status) |
1529 | if (status) |
1360 | goto fail; |
1530 | goto fail; |
Line 1361... | Line 1531... | ||
1361 | 1531 | ||
1362 | /* Extract the font name and PS name from the name table. At |
1532 | /* Find PS Name (name_id = 6). OT spec says PS name must be one of |
1363 | * present this just looks for the Mac platform/Roman encoded font |
1533 | * the following two encodings */ |
1364 | * name. It should be extended to use any suitable font name in |
1534 | status = find_name (name, 6, 3, 1, 0x409, &ps_name); /* win, unicode, english-us */ |
1365 | * the name table. |
1535 | if (unlikely(status)) |
1366 | */ |
- | |
1367 | for (i = 0; i < be16_to_cpu(name->num_records); i++) { |
- | |
1368 | record = &(name->records[i]); |
- | |
1369 | if ((be16_to_cpu (record->platform) == 1) && |
- | |
Line 1370... | Line 1536... | ||
1370 | (be16_to_cpu (record->encoding) == 0)) { |
1536 | goto fail; |
1371 | 1537 | ||
1372 | if (be16_to_cpu (record->name) == 4) { |
1538 | if (!ps_name) { |
1373 | font_name = malloc (be16_to_cpu(record->length) + 1); |
- | |
1374 | if (font_name == NULL) { |
1539 | status = find_name (name, 6, 1, 0, 0, &ps_name); /* mac, roman, english */ |
1375 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1540 | if (unlikely(status)) |
1376 | goto fail; |
- | |
1377 | } |
- | |
1378 | strncpy(font_name, |
- | |
1379 | ((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset), |
- | |
1380 | be16_to_cpu (record->length)); |
- | |
Line 1381... | Line 1541... | ||
1381 | font_name[be16_to_cpu (record->length)] = 0; |
1541 | goto fail; |
1382 | } |
1542 | } |
- | 1543 | ||
- | 1544 | /* Find Family name (name_id = 1) */ |
|
- | 1545 | status = find_name (name, 1, 3, 1, 0x409, &family_name); /* win, unicode, english-us */ |
|
1383 | 1546 | if (unlikely(status)) |
|
1384 | if (be16_to_cpu (record->name) == 6) { |
1547 | goto fail; |
- | 1548 | ||
1385 | ps_name = malloc (be16_to_cpu(record->length) + 1); |
1549 | if (!family_name) { |
1386 | if (ps_name == NULL) { |
- | |
1387 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
1388 | goto fail; |
- | |
1389 | } |
- | |
1390 | strncpy(ps_name, |
- | |
1391 | ((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset), |
1550 | status = find_name (name, 1, 3, 0, 0x409, &family_name); /* win, symbol, english-us */ |
Line 1392... | Line 1551... | ||
1392 | be16_to_cpu (record->length)); |
1551 | if (unlikely(status)) |
- | 1552 | goto fail; |
|
- | 1553 | } |
|
1393 | ps_name[be16_to_cpu (record->length)] = 0; |
1554 | |
1394 | } |
1555 | if (!family_name) { |
- | 1556 | status = find_name (name, 1, 1, 0, 0, &family_name); /* mac, roman, english */ |
|
- | 1557 | if (unlikely(status)) |
|
- | 1558 | goto fail; |
|
- | 1559 | } |
|
- | 1560 | ||
1395 | 1561 | if (!family_name) { |
|
Line 1396... | Line 1562... | ||
1396 | if (font_name && ps_name) |
1562 | status = find_name (name, 1, 3, 1, -1, &family_name); /* win, unicode, any language */ |
Line 1397... | Line 1563... | ||
1397 | break; |
1563 | if (unlikely(status)) |
- | 1564 | goto fail; |
|
- | 1565 | } |
|
- | 1566 | ||
- | 1567 | free (name); |
|
1398 | } |
1568 | |
- | 1569 | /* Ensure PS name is a valid PDF/PS name object. In PDF names are |
|
- | 1570 | * treated as UTF8 and non ASCII bytes, ' ', and '#' are encoded |
|
- | 1571 | * as '#' followed by 2 hex digits that encode the byte. By also |
|
- | 1572 | * encoding the characters in the reserved string we ensure the |
|
- | 1573 | * name is also PS compatible. */ |
|
1399 | } |
1574 | if (ps_name) { |
- | 1575 | static const char *reserved = "()<>[]{}/%#\\"; |
|
- | 1576 | char buf[128]; /* max name length is 127 bytes */ |
|
1400 | 1577 | char *src = ps_name; |
|
- | 1578 | char *dst = buf; |
|
- | 1579 | ||
- | 1580 | while (*src && dst < buf + 127) { |
|
- | 1581 | unsigned char c = *src; |
|
1401 | free (name); |
1582 | if (c < 0x21 || c > 0x7e || strchr (reserved, c)) { |
- | 1583 | if (dst + 4 > buf + 127) |
|
- | 1584 | break; |
|
- | 1585 | ||
- | 1586 | snprintf (dst, 4, "#%02X", c); |
|
- | 1587 | src++; |
|
- | 1588 | dst += 3; |
|
- | 1589 | } else { |
|
1402 | 1590 | *dst++ = *src++; |
|
- | 1591 | } |
|
- | 1592 | } |
|
1403 | /* Ensure PS name does not contain any spaces */ |
1593 | *dst = 0; |
1404 | if (ps_name) { |
- | |
1405 | for (i = 0, j = 0; ps_name[j]; j++) { |
1594 | free (ps_name); |
Line 1406... | Line 1595... | ||
1406 | if (ps_name[j] == ' ') |
1595 | ps_name = strdup (buf); |
1407 | continue; |
1596 | if (ps_name == NULL) { |
Line 1408... | Line 1597... | ||
1408 | ps_name[i++] = ps_name[j]; |
1597 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
Line 1409... | Line 1598... | ||
1409 | } |
1598 | goto fail; |
1410 | ps_name[i] = '\0'; |
1599 | } |
1411 | } |
- | |
1412 | - | ||
1413 | *ps_name_out = ps_name; |
1600 | } |
1414 | *font_name_out = font_name; |
- | |
1415 | - | ||
1416 | return CAIRO_STATUS_SUCCESS; |
1601 | |
1417 | - | ||
1418 | fail: |
1602 | *ps_name_out = ps_name; |
1419 | free (name); |
1603 | *font_name_out = family_name; |
Line 1420... | Line 1604... | ||
1420 | 1604 | ||
1421 | if (ps_name != NULL) |
1605 | return CAIRO_STATUS_SUCCESS; |
Line -... | Line 1606... | ||
- | 1606 | ||
- | 1607 | fail: |
|
- | 1608 | free (name); |
|
- | 1609 | free (ps_name); |
|
- | 1610 | free (family_name); |
|
- | 1611 | *ps_name_out = NULL; |
|
- | 1612 | *font_name_out = NULL; |
|
- | 1613 | ||
- | 1614 | return status; |
|
- | 1615 | } |
|
- | 1616 | ||
- | 1617 | cairo_int_status_t |
|
- | 1618 | _cairo_truetype_get_style (cairo_scaled_font_t *scaled_font, |
|
- | 1619 | int *weight, |
|
- | 1620 | cairo_bool_t *bold, |
|
- | 1621 | cairo_bool_t *italic) |
|
- | 1622 | { |
|
- | 1623 | cairo_status_t status; |
|
- | 1624 | const cairo_scaled_font_backend_t *backend; |
|
- | 1625 | tt_os2_t os2; |
|
- | 1626 | unsigned long size; |
|
- | 1627 | uint16_t selection; |
|
- | 1628 | ||
- | 1629 | backend = scaled_font->backend; |
|
- | 1630 | if (!backend->load_truetype_table) |
|
- | 1631 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
- | 1632 | ||
- | 1633 | size = 0; |
|
- | 1634 | status = backend->load_truetype_table (scaled_font, |
|
- | 1635 | TT_TAG_OS2, 0, |
|
- | 1636 | NULL, |
|
- | 1637 | &size); |
|
- | 1638 | if (status) |
|
- | 1639 | return status; |
|
- | 1640 | ||
- | 1641 | if (size < sizeof(os2)) |
|
- | 1642 | return CAIRO_INT_STATUS_UNSUPPORTED; |
|
- | 1643 | ||
- | 1644 | size = sizeof (os2); |
|
- | 1645 | status = backend->load_truetype_table (scaled_font, |
|
- | 1646 | TT_TAG_OS2, 0, |
|
- | 1647 | (unsigned char *) &os2, |
|
- | 1648 | &size); |
|
1422 | free (ps_name); |
1649 | if (status) |