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 68... | Line 68... | ||
68 | cairo_hash_entry_t base; |
68 | cairo_hash_entry_t base; |
Line 69... | Line 69... | ||
69 | 69 | ||
70 | cairo_bool_t is_scaled; |
70 | cairo_bool_t is_scaled; |
71 | cairo_bool_t is_composite; |
71 | cairo_bool_t is_composite; |
- | 72 | cairo_bool_t is_user; |
|
72 | cairo_bool_t is_user; |
73 | cairo_bool_t use_latin_subset; |
73 | cairo_scaled_font_subsets_t *parent; |
74 | cairo_scaled_font_subsets_t *parent; |
74 | cairo_scaled_font_t *scaled_font; |
75 | cairo_scaled_font_t *scaled_font; |
Line 75... | Line 76... | ||
75 | unsigned int font_id; |
76 | unsigned int font_id; |
76 | 77 | ||
- | 78 | int current_subset; |
|
77 | int current_subset; |
79 | int num_glyphs_in_current_subset; |
- | 80 | int num_glyphs_in_latin_subset; |
|
Line 78... | Line 81... | ||
78 | int num_glyphs_in_current_subset; |
81 | int max_glyphs_per_subset; |
79 | int max_glyphs_per_subset; |
82 | char latin_char_map[256]; |
80 | 83 | ||
Line 81... | Line 84... | ||
81 | cairo_hash_table_t *sub_font_glyphs; |
84 | cairo_hash_table_t *sub_font_glyphs; |
82 | struct _cairo_sub_font *next; |
85 | struct _cairo_sub_font *next; |
- | 86 | } cairo_sub_font_t; |
|
Line 83... | Line 87... | ||
83 | } cairo_sub_font_t; |
87 | |
84 | 88 | struct _cairo_scaled_font_subsets { |
|
85 | struct _cairo_scaled_font_subsets { |
89 | cairo_subsets_type_t type; |
86 | cairo_subsets_type_t type; |
90 | cairo_bool_t use_latin_subset; |
Line 104... | Line 108... | ||
104 | unsigned int subset_id; |
108 | unsigned int subset_id; |
105 | unsigned int subset_glyph_index; |
109 | unsigned int subset_glyph_index; |
106 | double x_advance; |
110 | double x_advance; |
107 | double y_advance; |
111 | double y_advance; |
Line -... | Line 112... | ||
- | 112 | ||
- | 113 | cairo_bool_t is_latin; |
|
108 | 114 | int latin_character; |
|
109 | cairo_bool_t is_mapped; |
115 | cairo_bool_t is_mapped; |
110 | uint32_t unicode; |
116 | uint32_t unicode; |
111 | char *utf8; |
117 | char *utf8; |
112 | int utf8_len; |
118 | int utf8_len; |
Line 113... | Line 119... | ||
113 | } cairo_sub_font_glyph_t; |
119 | } cairo_sub_font_glyph_t; |
114 | 120 | ||
115 | typedef struct _cairo_sub_font_collection { |
121 | typedef struct _cairo_sub_font_collection { |
116 | unsigned long *glyphs; /* scaled_font_glyph_index */ |
122 | unsigned long *glyphs; /* scaled_font_glyph_index */ |
- | 123 | char **utf8; |
|
- | 124 | unsigned int glyphs_size; |
|
117 | char **utf8; |
125 | int *to_latin_char; |
118 | unsigned int glyphs_size; |
126 | unsigned long *latin_to_subset_glyph_index; |
Line 119... | Line 127... | ||
119 | unsigned int max_glyph; |
127 | unsigned int max_glyph; |
Line 143... | Line 151... | ||
143 | unsigned long scaled_font_glyph_index) |
151 | unsigned long scaled_font_glyph_index) |
144 | { |
152 | { |
145 | sub_font_glyph->base.hash = scaled_font_glyph_index; |
153 | sub_font_glyph->base.hash = scaled_font_glyph_index; |
146 | } |
154 | } |
Line 147... | Line -... | ||
147 | - | ||
148 | static cairo_bool_t |
- | |
149 | _cairo_sub_font_glyphs_equal (const void *key_a, const void *key_b) |
- | |
150 | { |
- | |
151 | const cairo_sub_font_glyph_t *sub_font_glyph_a = key_a; |
- | |
152 | const cairo_sub_font_glyph_t *sub_font_glyph_b = key_b; |
- | |
153 | - | ||
154 | return sub_font_glyph_a->base.hash == sub_font_glyph_b->base.hash; |
- | |
155 | } |
- | |
156 | 155 | ||
157 | static cairo_sub_font_glyph_t * |
156 | static cairo_sub_font_glyph_t * |
158 | _cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index, |
157 | _cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index, |
159 | unsigned int subset_id, |
158 | unsigned int subset_id, |
160 | unsigned int subset_glyph_index, |
159 | unsigned int subset_glyph_index, |
161 | double x_advance, |
160 | double x_advance, |
- | 161 | double y_advance, |
|
- | 162 | int latin_character, |
|
- | 163 | uint32_t unicode, |
|
- | 164 | char *utf8, |
|
162 | double y_advance) |
165 | int utf8_len) |
163 | { |
166 | { |
Line 164... | Line 167... | ||
164 | cairo_sub_font_glyph_t *sub_font_glyph; |
167 | cairo_sub_font_glyph_t *sub_font_glyph; |
165 | 168 | ||
Line 172... | Line 175... | ||
172 | _cairo_sub_font_glyph_init_key (sub_font_glyph, scaled_font_glyph_index); |
175 | _cairo_sub_font_glyph_init_key (sub_font_glyph, scaled_font_glyph_index); |
173 | sub_font_glyph->subset_id = subset_id; |
176 | sub_font_glyph->subset_id = subset_id; |
174 | sub_font_glyph->subset_glyph_index = subset_glyph_index; |
177 | sub_font_glyph->subset_glyph_index = subset_glyph_index; |
175 | sub_font_glyph->x_advance = x_advance; |
178 | sub_font_glyph->x_advance = x_advance; |
176 | sub_font_glyph->y_advance = y_advance; |
179 | sub_font_glyph->y_advance = y_advance; |
- | 180 | sub_font_glyph->is_latin = (latin_character >= 0); |
|
- | 181 | sub_font_glyph->latin_character = latin_character; |
|
177 | sub_font_glyph->is_mapped = FALSE; |
182 | sub_font_glyph->is_mapped = FALSE; |
178 | sub_font_glyph->unicode = -1; |
183 | sub_font_glyph->unicode = unicode; |
179 | sub_font_glyph->utf8 = NULL; |
184 | sub_font_glyph->utf8 = utf8; |
180 | sub_font_glyph->utf8_len = 0; |
185 | sub_font_glyph->utf8_len = utf8_len; |
Line 181... | Line 186... | ||
181 | 186 | ||
182 | return sub_font_glyph; |
187 | return sub_font_glyph; |
Line 183... | Line 188... | ||
183 | } |
188 | } |
184 | 189 | ||
185 | static void |
190 | static void |
186 | _cairo_sub_font_glyph_destroy (cairo_sub_font_glyph_t *sub_font_glyph) |
- | |
187 | { |
191 | _cairo_sub_font_glyph_destroy (cairo_sub_font_glyph_t *sub_font_glyph) |
Line 188... | Line 192... | ||
188 | if (sub_font_glyph->utf8 != NULL) |
192 | { |
189 | free (sub_font_glyph->utf8); |
193 | free (sub_font_glyph->utf8); |
Line 218... | Line 222... | ||
218 | /* Ensure we don't exceed the allocated bounds. */ |
222 | /* Ensure we don't exceed the allocated bounds. */ |
219 | assert (subset_glyph_index < collection->glyphs_size); |
223 | assert (subset_glyph_index < collection->glyphs_size); |
Line 220... | Line 224... | ||
220 | 224 | ||
221 | collection->glyphs[subset_glyph_index] = scaled_font_glyph_index; |
225 | collection->glyphs[subset_glyph_index] = scaled_font_glyph_index; |
- | 226 | collection->utf8[subset_glyph_index] = sub_font_glyph->utf8; |
|
- | 227 | collection->to_latin_char[subset_glyph_index] = sub_font_glyph->latin_character; |
|
- | 228 | if (sub_font_glyph->is_latin) |
|
- | 229 | collection->latin_to_subset_glyph_index[sub_font_glyph->latin_character] = subset_glyph_index; |
|
222 | collection->utf8[subset_glyph_index] = sub_font_glyph->utf8; |
230 | |
223 | if (subset_glyph_index > collection->max_glyph) |
231 | if (subset_glyph_index > collection->max_glyph) |
Line 224... | Line 232... | ||
224 | collection->max_glyph = subset_glyph_index; |
232 | collection->max_glyph = subset_glyph_index; |
225 | 233 | ||
Line 264... | Line 272... | ||
264 | cairo_bool_t is_scaled, |
272 | cairo_bool_t is_scaled, |
265 | cairo_bool_t is_composite, |
273 | cairo_bool_t is_composite, |
266 | cairo_sub_font_t **sub_font_out) |
274 | cairo_sub_font_t **sub_font_out) |
267 | { |
275 | { |
268 | cairo_sub_font_t *sub_font; |
276 | cairo_sub_font_t *sub_font; |
269 | cairo_status_t status; |
277 | int i; |
270 | cairo_scaled_font_subsets_glyph_t subset_glyph; |
- | |
Line 271... | Line 278... | ||
271 | 278 | ||
272 | sub_font = malloc (sizeof (cairo_sub_font_t)); |
279 | sub_font = malloc (sizeof (cairo_sub_font_t)); |
273 | if (unlikely (sub_font == NULL)) |
280 | if (unlikely (sub_font == NULL)) |
Line 280... | Line 287... | ||
280 | 287 | ||
281 | sub_font->parent = parent; |
288 | sub_font->parent = parent; |
282 | sub_font->scaled_font = scaled_font; |
289 | sub_font->scaled_font = scaled_font; |
Line -... | Line 290... | ||
- | 290 | sub_font->font_id = font_id; |
|
- | 291 | ||
- | 292 | sub_font->use_latin_subset = parent->use_latin_subset; |
|
- | 293 | ||
- | 294 | /* latin subsets of Type 3 and CID CFF fonts are not supported */ |
|
- | 295 | if (sub_font->is_user || sub_font->is_scaled || |
|
- | 296 | _cairo_cff_scaled_font_is_cid_cff (scaled_font) ) |
|
- | 297 | { |
|
- | 298 | sub_font->use_latin_subset = FALSE; |
|
- | 299 | } |
|
- | 300 | ||
- | 301 | if (sub_font->use_latin_subset) |
|
283 | sub_font->font_id = font_id; |
302 | sub_font->current_subset = 1; /* reserve subset 0 for latin glyphs */ |
- | 303 | else |
|
284 | 304 | sub_font->current_subset = 0; |
|
- | 305 | ||
285 | sub_font->current_subset = 0; |
306 | sub_font->num_glyphs_in_current_subset = 0; |
- | 307 | sub_font->num_glyphs_in_latin_subset = 0; |
|
- | 308 | sub_font->max_glyphs_per_subset = max_glyphs_per_subset; |
|
Line 286... | Line 309... | ||
286 | sub_font->num_glyphs_in_current_subset = 0; |
309 | for (i = 0; i < 256; i++) |
287 | sub_font->max_glyphs_per_subset = max_glyphs_per_subset; |
310 | sub_font->latin_char_map[i] = FALSE; |
288 | 311 | ||
289 | sub_font->sub_font_glyphs = _cairo_hash_table_create (_cairo_sub_font_glyphs_equal); |
312 | sub_font->sub_font_glyphs = _cairo_hash_table_create (NULL); |
290 | if (unlikely (sub_font->sub_font_glyphs == NULL)) { |
313 | if (unlikely (sub_font->sub_font_glyphs == NULL)) { |
291 | free (sub_font); |
314 | free (sub_font); |
292 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
293 | } |
- | |
294 | sub_font->next = NULL; |
- | |
295 | - | ||
296 | /* Reserve first glyph in subset for the .notdef glyph except for |
- | |
297 | * Type 3 fonts */ |
- | |
298 | if (! is_scaled) { |
- | |
299 | status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &subset_glyph); |
- | |
300 | if (unlikely (status)) { |
- | |
301 | _cairo_hash_table_destroy (sub_font->sub_font_glyphs); |
- | |
302 | free (sub_font); |
- | |
303 | return status; |
- | |
304 | } |
315 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
305 | } |
316 | } |
306 | 317 | sub_font->next = NULL; |
|
Line 307... | Line 318... | ||
307 | *sub_font_out = sub_font; |
318 | *sub_font_out = sub_font; |
Line 327... | Line 338... | ||
327 | 338 | ||
328 | _cairo_hash_table_remove (sub_fonts, &sub_font->base); |
339 | _cairo_hash_table_remove (sub_fonts, &sub_font->base); |
329 | _cairo_sub_font_destroy (sub_font); |
340 | _cairo_sub_font_destroy (sub_font); |
Line -... | Line 341... | ||
- | 341 | } |
|
- | 342 | ||
- | 343 | /* Characters 0x80 to 0x9f in the winansi encoding. |
|
- | 344 | * All other characters in the range 0x00 to 0xff map 1:1 to unicode */ |
|
- | 345 | static unsigned int _winansi_0x80_to_0x9f[] = { |
|
- | 346 | 0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, |
|
- | 347 | 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017d, 0x0000, |
|
- | 348 | 0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, |
|
- | 349 | 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x0000, 0x017e, 0x0178 |
|
- | 350 | }; |
|
- | 351 | ||
- | 352 | int |
|
- | 353 | _cairo_unicode_to_winansi (unsigned long uni) |
|
- | 354 | { |
|
- | 355 | int i; |
|
- | 356 | ||
- | 357 | /* exclude the extra "hyphen" at 0xad to avoid duplicate glyphnames */ |
|
- | 358 | if ((uni >= 0x20 && uni <= 0x7e) || |
|
- | 359 | (uni >= 0xa1 && uni <= 0xff && uni != 0xad) || |
|
- | 360 | uni == 0) |
|
- | 361 | return uni; |
|
- | 362 | ||
- | 363 | for (i = 0; i < 32; i++) |
|
- | 364 | if (_winansi_0x80_to_0x9f[i] == uni) |
|
- | 365 | return i + 0x80; |
|
- | 366 | ||
- | 367 | return -1; |
|
330 | } |
368 | } |
331 | 369 | ||
332 | static cairo_status_t |
370 | static cairo_status_t |
- | 371 | _cairo_sub_font_glyph_lookup_unicode (cairo_scaled_font_t *scaled_font, |
|
- | 372 | unsigned long scaled_font_glyph_index, |
|
333 | _cairo_sub_font_glyph_lookup_unicode (cairo_sub_font_glyph_t *sub_font_glyph, |
373 | uint32_t *unicode_out, |
334 | cairo_scaled_font_t *scaled_font, |
374 | char **utf8_out, |
335 | unsigned long scaled_font_glyph_index) |
375 | int *utf8_len_out) |
336 | { |
376 | { |
337 | uint32_t unicode; |
377 | uint32_t unicode; |
338 | char buf[8]; |
378 | char buf[8]; |
Line 354... | Line 394... | ||
354 | &unicode); |
394 | &unicode); |
355 | if (unlikely (status)) |
395 | if (unlikely (status)) |
356 | return status; |
396 | return status; |
357 | } |
397 | } |
Line 358... | Line 398... | ||
358 | 398 | ||
359 | sub_font_glyph->unicode = unicode; |
399 | *unicode_out = unicode; |
360 | sub_font_glyph->utf8 = NULL; |
400 | *utf8_out = NULL; |
361 | sub_font_glyph->utf8_len = 0; |
401 | *utf8_len_out = 0; |
362 | if (unicode != (uint32_t) -1) { |
402 | if (unicode != (uint32_t) -1) { |
363 | len = _cairo_ucs4_to_utf8 (unicode, buf); |
403 | len = _cairo_ucs4_to_utf8 (unicode, buf); |
364 | if (len > 0) { |
404 | if (len > 0) { |
365 | sub_font_glyph->utf8 = malloc (len + 1); |
405 | *utf8_out = malloc (len + 1); |
366 | if (unlikely (sub_font_glyph->utf8 == NULL)) |
406 | if (unlikely (*utf8_out == NULL)) |
Line 367... | Line 407... | ||
367 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
407 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
368 | 408 | ||
369 | memcpy (sub_font_glyph->utf8, buf, len); |
409 | memcpy (*utf8_out, buf, len); |
370 | sub_font_glyph->utf8[len] = 0; |
410 | (*utf8_out)[len] = 0; |
371 | sub_font_glyph->utf8_len = len; |
411 | *utf8_len_out = len; |
Line 372... | Line 412... | ||
372 | } |
412 | } |
373 | } |
413 | } |
Line 427... | Line 467... | ||
427 | sub_font_glyph = _cairo_hash_table_lookup (sub_font->sub_font_glyphs, |
467 | sub_font_glyph = _cairo_hash_table_lookup (sub_font->sub_font_glyphs, |
428 | &key.base); |
468 | &key.base); |
429 | if (sub_font_glyph != NULL) { |
469 | if (sub_font_glyph != NULL) { |
430 | subset_glyph->font_id = sub_font->font_id; |
470 | subset_glyph->font_id = sub_font->font_id; |
431 | subset_glyph->subset_id = sub_font_glyph->subset_id; |
471 | subset_glyph->subset_id = sub_font_glyph->subset_id; |
- | 472 | if (sub_font_glyph->is_latin) |
|
- | 473 | subset_glyph->subset_glyph_index = sub_font_glyph->latin_character; |
|
- | 474 | else |
|
432 | subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index; |
475 | subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index; |
- | 476 | ||
433 | subset_glyph->is_scaled = sub_font->is_scaled; |
477 | subset_glyph->is_scaled = sub_font->is_scaled; |
434 | subset_glyph->is_composite = sub_font->is_composite; |
478 | subset_glyph->is_composite = sub_font->is_composite; |
- | 479 | subset_glyph->is_latin = sub_font_glyph->is_latin; |
|
435 | subset_glyph->x_advance = sub_font_glyph->x_advance; |
480 | subset_glyph->x_advance = sub_font_glyph->x_advance; |
436 | subset_glyph->y_advance = sub_font_glyph->y_advance; |
481 | subset_glyph->y_advance = sub_font_glyph->y_advance; |
437 | status = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph, |
482 | status = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph, |
438 | utf8, utf8_len, |
483 | utf8, utf8_len, |
439 | &subset_glyph->utf8_is_mapped); |
484 | &subset_glyph->utf8_is_mapped); |
Line 444... | Line 489... | ||
444 | 489 | ||
445 | return CAIRO_INT_STATUS_UNSUPPORTED; |
490 | return CAIRO_INT_STATUS_UNSUPPORTED; |
Line 446... | Line 491... | ||
446 | } |
491 | } |
447 | 492 | ||
448 | static cairo_status_t |
493 | static cairo_status_t |
- | 494 | _cairo_sub_font_add_glyph (cairo_sub_font_t *sub_font, |
|
- | 495 | unsigned long scaled_font_glyph_index, |
|
- | 496 | cairo_bool_t is_latin, |
|
449 | _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, |
497 | int latin_character, |
450 | unsigned long scaled_font_glyph_index, |
498 | uint32_t unicode, |
451 | const char *utf8, |
499 | char *utf8, |
452 | int utf8_len, |
500 | int utf8_len, |
453 | cairo_scaled_font_subsets_glyph_t *subset_glyph) |
- | |
454 | { |
- | |
455 | cairo_sub_font_glyph_t key, *sub_font_glyph; |
- | |
456 | cairo_status_t status; |
- | |
457 | - | ||
458 | _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index); |
- | |
459 | sub_font_glyph = _cairo_hash_table_lookup (sub_font->sub_font_glyphs, |
- | |
460 | &key.base); |
501 | cairo_sub_font_glyph_t **sub_font_glyph_out) |
461 | if (sub_font_glyph == NULL) { |
- | |
462 | cairo_scaled_glyph_t *scaled_glyph; |
- | |
463 | - | ||
464 | if (sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset) |
502 | { |
465 | { |
- | |
466 | cairo_scaled_font_subsets_glyph_t tmp_subset_glyph; |
- | |
467 | 503 | cairo_scaled_glyph_t *scaled_glyph; |
|
468 | sub_font->current_subset++; |
- | |
469 | sub_font->num_glyphs_in_current_subset = 0; |
- | |
470 | 504 | cairo_sub_font_glyph_t *sub_font_glyph; |
|
471 | /* Reserve first glyph in subset for the .notdef glyph |
- | |
472 | * except for Type 3 fonts */ |
- | |
473 | if (! _cairo_font_face_is_user (sub_font->scaled_font->font_face)) { |
505 | int *num_glyphs_in_subset_ptr; |
474 | status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &tmp_subset_glyph); |
506 | double x_advance; |
475 | if (unlikely (status)) |
- | |
476 | return status; |
- | |
Line 477... | Line 507... | ||
477 | } |
507 | double y_advance; |
478 | } |
508 | cairo_int_status_t status; |
479 | 509 | ||
480 | _cairo_scaled_font_freeze_cache (sub_font->scaled_font); |
510 | _cairo_scaled_font_freeze_cache (sub_font->scaled_font); |
Line 486... | Line 516... | ||
486 | if (unlikely (status)) { |
516 | if (unlikely (status)) { |
487 | _cairo_scaled_font_thaw_cache (sub_font->scaled_font); |
517 | _cairo_scaled_font_thaw_cache (sub_font->scaled_font); |
488 | return status; |
518 | return status; |
489 | } |
519 | } |
Line 490... | Line -... | ||
490 | - | ||
491 | sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index, |
- | |
492 | sub_font->current_subset, |
- | |
493 | sub_font->num_glyphs_in_current_subset, |
520 | |
494 | scaled_glyph->metrics.x_advance, |
521 | x_advance = scaled_glyph->metrics.x_advance; |
495 | scaled_glyph->metrics.y_advance); |
522 | y_advance = scaled_glyph->metrics.y_advance; |
Line -... | Line 523... | ||
- | 523 | _cairo_scaled_font_thaw_cache (sub_font->scaled_font); |
|
- | 524 | ||
496 | _cairo_scaled_font_thaw_cache (sub_font->scaled_font); |
525 | if (!is_latin && sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset) |
497 | 526 | { |
|
- | 527 | sub_font->current_subset++; |
|
Line -... | Line 528... | ||
- | 528 | sub_font->num_glyphs_in_current_subset = 0; |
|
- | 529 | } |
|
- | 530 | ||
- | 531 | if (is_latin) |
|
- | 532 | num_glyphs_in_subset_ptr = &sub_font->num_glyphs_in_latin_subset; |
|
- | 533 | else |
|
- | 534 | num_glyphs_in_subset_ptr = &sub_font->num_glyphs_in_current_subset; |
|
- | 535 | ||
- | 536 | /* Reserve first glyph in subset for the .notdef glyph except for |
|
- | 537 | * Type 3 fonts */ |
|
- | 538 | if (*num_glyphs_in_subset_ptr == 0 && |
|
498 | if (unlikely (sub_font_glyph == NULL)) |
539 | scaled_font_glyph_index != 0 && |
- | 540 | ! _cairo_font_face_is_user (sub_font->scaled_font->font_face)) |
|
499 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
541 | { |
- | 542 | status = _cairo_sub_font_add_glyph (sub_font, |
|
- | 543 | 0, |
|
- | 544 | is_latin, |
|
- | 545 | 0, |
|
500 | 546 | 0, |
|
501 | status = _cairo_sub_font_glyph_lookup_unicode (sub_font_glyph, |
547 | NULL, |
502 | sub_font->scaled_font, |
- | |
503 | scaled_font_glyph_index); |
548 | -1, |
504 | if (unlikely (status)) { |
549 | &sub_font_glyph); |
Line -... | Line 550... | ||
- | 550 | if (unlikely (status)) |
|
- | 551 | return status; |
|
- | 552 | } |
|
- | 553 | ||
- | 554 | sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index, |
|
- | 555 | is_latin ? 0 : sub_font->current_subset, |
|
- | 556 | *num_glyphs_in_subset_ptr, |
|
- | 557 | x_advance, |
|
- | 558 | y_advance, |
|
- | 559 | is_latin ? latin_character : -1, |
|
- | 560 | unicode, |
|
- | 561 | utf8, |
|
- | 562 | utf8_len); |
|
505 | _cairo_sub_font_glyph_destroy (sub_font_glyph); |
563 | |
506 | return status; |
564 | if (unlikely (sub_font_glyph == NULL)) |
507 | } |
565 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
508 | 566 | ||
509 | status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base); |
567 | status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base); |
Line 510... | Line 568... | ||
510 | if (unlikely (status)) { |
568 | if (unlikely (status)) { |
511 | _cairo_sub_font_glyph_destroy (sub_font_glyph); |
- | |
512 | return status; |
569 | _cairo_sub_font_glyph_destroy (sub_font_glyph); |
513 | } |
570 | return status; |
514 | 571 | } |
|
515 | sub_font->num_glyphs_in_current_subset++; |
572 | |
516 | 573 | (*num_glyphs_in_subset_ptr)++; |
|
517 | if (sub_font->is_scaled) { |
574 | if (sub_font->is_scaled) { |
518 | if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_scaled_subset_used) |
575 | if (*num_glyphs_in_subset_ptr > sub_font->parent->max_glyphs_per_scaled_subset_used) |
- | 576 | sub_font->parent->max_glyphs_per_scaled_subset_used = *num_glyphs_in_subset_ptr; |
|
- | 577 | } else { |
|
- | 578 | if (*num_glyphs_in_subset_ptr > sub_font->parent->max_glyphs_per_unscaled_subset_used) |
|
- | 579 | sub_font->parent->max_glyphs_per_unscaled_subset_used = *num_glyphs_in_subset_ptr; |
|
- | 580 | } |
|
- | 581 | ||
- | 582 | *sub_font_glyph_out = sub_font_glyph; |
|
- | 583 | ||
- | 584 | return CAIRO_STATUS_SUCCESS; |
|
- | 585 | } |
|
- | 586 | ||
- | 587 | static cairo_status_t |
|
- | 588 | _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, |
|
- | 589 | unsigned long scaled_font_glyph_index, |
|
- | 590 | const char *text_utf8, |
|
- | 591 | int text_utf8_len, |
|
- | 592 | cairo_scaled_font_subsets_glyph_t *subset_glyph) |
|
- | 593 | { |
|
- | 594 | cairo_sub_font_glyph_t key, *sub_font_glyph; |
|
- | 595 | cairo_status_t status; |
|
- | 596 | ||
- | 597 | _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index); |
|
- | 598 | sub_font_glyph = _cairo_hash_table_lookup (sub_font->sub_font_glyphs, |
|
- | 599 | &key.base); |
|
- | 600 | if (sub_font_glyph == NULL) { |
|
- | 601 | uint32_t font_unicode; |
|
- | 602 | char *font_utf8; |
|
- | 603 | int font_utf8_len; |
|
- | 604 | cairo_bool_t is_latin; |
|
- | 605 | int latin_character; |
|
- | 606 | ||
- | 607 | status = _cairo_sub_font_glyph_lookup_unicode (sub_font->scaled_font, |
|
- | 608 | scaled_font_glyph_index, |
|
- | 609 | &font_unicode, |
|
- | 610 | &font_utf8, |
|
- | 611 | &font_utf8_len); |
|
- | 612 | if (unlikely(status)) |
|
- | 613 | return status; |
|
- | 614 | ||
- | 615 | /* If the supplied utf8 is a valid single character, use it |
|
- | 616 | * instead of the font lookup */ |
|
- | 617 | if (text_utf8 != NULL && text_utf8_len > 0) { |
|
- | 618 | uint32_t *ucs4; |
|
- | 619 | int ucs4_len; |
|
- | 620 | ||
- | 621 | status = _cairo_utf8_to_ucs4 (text_utf8, text_utf8_len, |
|
- | 622 | &ucs4, &ucs4_len); |
|
- | 623 | if (status == CAIRO_STATUS_SUCCESS) { |
|
- | 624 | if (ucs4_len == 1) { |
|
- | 625 | font_unicode = ucs4[0]; |
|
- | 626 | free (font_utf8); |
|
- | 627 | font_utf8 = malloc (text_utf8_len + 1); |
|
- | 628 | if (font_utf8 == NULL) { |
|
- | 629 | free (ucs4); |
|
- | 630 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
|
- | 631 | } |
|
- | 632 | memcpy (font_utf8, text_utf8, text_utf8_len); |
|
- | 633 | font_utf8[text_utf8_len] = 0; |
|
- | 634 | font_utf8_len = text_utf8_len; |
|
- | 635 | } |
|
- | 636 | free (ucs4); |
|
- | 637 | } |
|
- | 638 | } |
|
- | 639 | ||
- | 640 | /* If glyph is in the winansi encoding and font is not a user |
|
- | 641 | * font, put glyph in the latin subset. If glyph is .notdef |
|
- | 642 | * the latin subset is preferred but only if the latin subset |
|
- | 643 | * already contains at least one glyph. We don't want to |
|
- | 644 | * create a separate subset just for the .notdef glyph. |
|
- | 645 | */ |
|
- | 646 | is_latin = FALSE; |
|
- | 647 | latin_character = -1; |
|
- | 648 | if (sub_font->use_latin_subset && |
|
- | 649 | (! _cairo_font_face_is_user (sub_font->scaled_font->font_face))) |
|
- | 650 | { |
|
- | 651 | latin_character = _cairo_unicode_to_winansi (font_unicode); |
|
- | 652 | if (latin_character > 0 || |
|
- | 653 | (latin_character == 0 && sub_font->num_glyphs_in_latin_subset > 0)) |
|
- | 654 | { |
|
- | 655 | if (!sub_font->latin_char_map[latin_character]) { |
|
- | 656 | sub_font->latin_char_map[latin_character] = TRUE; |
|
- | 657 | is_latin = TRUE; |
|
- | 658 | } |
|
- | 659 | } |
|
- | 660 | } |
|
- | 661 | ||
- | 662 | status = _cairo_sub_font_add_glyph (sub_font, |
|
- | 663 | scaled_font_glyph_index, |
|
- | 664 | is_latin, |
|
- | 665 | latin_character, |
|
- | 666 | font_unicode, |
|
519 | sub_font->parent->max_glyphs_per_scaled_subset_used = sub_font->num_glyphs_in_current_subset; |
667 | font_utf8, |
Line 520... | Line 668... | ||
520 | } else { |
668 | font_utf8_len, |
521 | if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_unscaled_subset_used) |
669 | &sub_font_glyph); |
- | 670 | if (unlikely(status)) |
|
- | 671 | return status; |
|
- | 672 | } |
|
522 | sub_font->parent->max_glyphs_per_unscaled_subset_used = sub_font->num_glyphs_in_current_subset; |
673 | |
- | 674 | subset_glyph->font_id = sub_font->font_id; |
|
523 | } |
675 | subset_glyph->subset_id = sub_font_glyph->subset_id; |
524 | } |
676 | if (sub_font_glyph->is_latin) |
- | 677 | subset_glyph->subset_glyph_index = sub_font_glyph->latin_character; |
|
525 | 678 | else |
|
526 | subset_glyph->font_id = sub_font->font_id; |
679 | subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index; |
527 | subset_glyph->subset_id = sub_font_glyph->subset_id; |
680 | |
528 | subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index; |
681 | subset_glyph->is_scaled = sub_font->is_scaled; |
529 | subset_glyph->is_scaled = sub_font->is_scaled; |
682 | subset_glyph->is_composite = sub_font->is_composite; |
530 | subset_glyph->is_composite = sub_font->is_composite; |
683 | subset_glyph->is_latin = sub_font_glyph->is_latin; |
Line 531... | Line 684... | ||
531 | subset_glyph->x_advance = sub_font_glyph->x_advance; |
684 | subset_glyph->x_advance = sub_font_glyph->x_advance; |
532 | subset_glyph->y_advance = sub_font_glyph->y_advance; |
685 | subset_glyph->y_advance = sub_font_glyph->y_advance; |
Line 556... | Line 709... | ||
556 | 709 | ||
557 | for (i = 0; i <= sub_font->current_subset; i++) { |
710 | for (i = 0; i <= sub_font->current_subset; i++) { |
558 | collection->subset_id = i; |
711 | collection->subset_id = i; |
559 | collection->num_glyphs = 0; |
712 | collection->num_glyphs = 0; |
- | 713 | collection->max_glyph = 0; |
|
Line 560... | Line 714... | ||
560 | collection->max_glyph = 0; |
714 | memset (collection->latin_to_subset_glyph_index, 0, 256*sizeof(unsigned long)); |
561 | 715 | ||
562 | _cairo_hash_table_foreach (sub_font->sub_font_glyphs, |
716 | _cairo_hash_table_foreach (sub_font->sub_font_glyphs, |
563 | _cairo_sub_font_glyph_collect, collection); |
717 | _cairo_sub_font_glyph_collect, collection); |
Line 576... | Line 730... | ||
576 | subset.subset_id = i; |
730 | subset.subset_id = i; |
577 | subset.glyphs = collection->glyphs; |
731 | subset.glyphs = collection->glyphs; |
578 | subset.utf8 = collection->utf8; |
732 | subset.utf8 = collection->utf8; |
579 | subset.num_glyphs = collection->num_glyphs; |
733 | subset.num_glyphs = collection->num_glyphs; |
580 | subset.glyph_names = NULL; |
734 | subset.glyph_names = NULL; |
581 | /* No need to check for out of memory here. If to_unicode is NULL, the PDF |
- | |
- | 735 | ||
582 | * surface does not emit an ToUnicode stream */ |
736 | subset.is_latin = FALSE; |
583 | subset.to_unicode = _cairo_malloc_ab (collection->num_glyphs, sizeof (unsigned long)); |
737 | if (sub_font->use_latin_subset && i == 0) { |
584 | if (subset.to_unicode) { |
738 | subset.is_latin = TRUE; |
585 | for (j = 0; j < collection->num_glyphs; j++) { |
739 | subset.to_latin_char = collection->to_latin_char; |
586 | /* default unicode character required when mapping fails */ |
740 | subset.latin_to_subset_glyph_index = collection->latin_to_subset_glyph_index; |
- | 741 | } else { |
|
587 | subset.to_unicode[j] = 0xfffd; |
742 | subset.to_latin_char = NULL; |
588 | } |
743 | subset.latin_to_subset_glyph_index = NULL; |
589 | } |
744 | } |
- | 745 | ||
590 | collection->status = (collection->font_subset_callback) (&subset, |
746 | collection->status = (collection->font_subset_callback) (&subset, |
591 | collection->font_subset_callback_closure); |
747 | collection->font_subset_callback_closure); |
Line 592... | Line -... | ||
592 | - | ||
593 | if (subset.to_unicode != NULL) |
- | |
594 | free (subset.to_unicode); |
- | |
595 | 748 | ||
596 | if (subset.glyph_names != NULL) { |
749 | if (subset.glyph_names != NULL) { |
597 | for (j = 0; j < collection->num_glyphs; j++) |
750 | for (j = 0; j < collection->num_glyphs; j++) |
598 | free (subset.glyph_names[j]); |
751 | free (subset.glyph_names[j]); |
599 | free (subset.glyph_names); |
752 | free (subset.glyph_names); |
Line 614... | Line 767... | ||
614 | _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); |
767 | _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); |
615 | return NULL; |
768 | return NULL; |
616 | } |
769 | } |
Line 617... | Line 770... | ||
617 | 770 | ||
- | 771 | subsets->type = type; |
|
618 | subsets->type = type; |
772 | subsets->use_latin_subset = FALSE; |
619 | subsets->max_glyphs_per_unscaled_subset_used = 0; |
773 | subsets->max_glyphs_per_unscaled_subset_used = 0; |
620 | subsets->max_glyphs_per_scaled_subset_used = 0; |
774 | subsets->max_glyphs_per_scaled_subset_used = 0; |
Line 621... | Line 775... | ||
621 | subsets->num_sub_fonts = 0; |
775 | subsets->num_sub_fonts = 0; |
Line 668... | Line 822... | ||
668 | _cairo_hash_table_destroy (subsets->unscaled_sub_fonts); |
822 | _cairo_hash_table_destroy (subsets->unscaled_sub_fonts); |
Line 669... | Line 823... | ||
669 | 823 | ||
670 | free (subsets); |
824 | free (subsets); |
Line -... | Line 825... | ||
- | 825 | } |
|
- | 826 | ||
- | 827 | void |
|
- | 828 | _cairo_scaled_font_subsets_enable_latin_subset (cairo_scaled_font_subsets_t *font_subsets, |
|
- | 829 | cairo_bool_t use_latin) |
|
- | 830 | { |
|
- | 831 | font_subsets->use_latin_subset = use_latin; |
|
671 | } |
832 | } |
672 | 833 | ||
673 | cairo_status_t |
834 | cairo_status_t |
674 | _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, |
835 | _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, |
675 | cairo_scaled_font_t *scaled_font, |
836 | cairo_scaled_font_t *scaled_font, |
Line 682... | Line 843... | ||
682 | cairo_scaled_glyph_t *scaled_glyph; |
843 | cairo_scaled_glyph_t *scaled_glyph; |
683 | cairo_font_face_t *font_face; |
844 | cairo_font_face_t *font_face; |
684 | cairo_matrix_t identity; |
845 | cairo_matrix_t identity; |
685 | cairo_font_options_t font_options; |
846 | cairo_font_options_t font_options; |
686 | cairo_scaled_font_t *unscaled_font; |
847 | cairo_scaled_font_t *unscaled_font; |
687 | cairo_status_t status; |
848 | cairo_int_status_t status; |
688 | int max_glyphs; |
849 | int max_glyphs; |
689 | cairo_bool_t type1_font; |
850 | cairo_bool_t type1_font; |
Line 690... | Line 851... | ||
690 | 851 | ||
691 | /* Lookup glyph in unscaled subsets */ |
852 | /* Lookup glyph in unscaled subsets */ |
Line 735... | Line 896... | ||
735 | scaled_font_glyph_index, |
896 | scaled_font_glyph_index, |
736 | CAIRO_SCALED_GLYPH_INFO_PATH, |
897 | CAIRO_SCALED_GLYPH_INFO_PATH, |
737 | &scaled_glyph); |
898 | &scaled_glyph); |
738 | _cairo_scaled_font_thaw_cache (scaled_font); |
899 | _cairo_scaled_font_thaw_cache (scaled_font); |
739 | } |
900 | } |
740 | if (_cairo_status_is_error (status)) |
901 | if (_cairo_int_status_is_error (status)) |
741 | return status; |
902 | return status; |
Line 742... | Line 903... | ||
742 | 903 | ||
743 | if (status == CAIRO_STATUS_SUCCESS && |
904 | if (status == CAIRO_INT_STATUS_SUCCESS && |
744 | subsets->type != CAIRO_SUBSETS_SCALED && |
905 | subsets->type != CAIRO_SUBSETS_SCALED && |
745 | ! _cairo_font_face_is_user (scaled_font->font_face)) |
906 | ! _cairo_font_face_is_user (scaled_font->font_face)) |
746 | { |
907 | { |
747 | /* Path available. Add to unscaled subset. */ |
908 | /* Path available. Add to unscaled subset. */ |
Line 761... | Line 922... | ||
761 | &font_options); |
922 | &font_options); |
762 | if (unlikely (unscaled_font->status)) |
923 | if (unlikely (unscaled_font->status)) |
763 | return unscaled_font->status; |
924 | return unscaled_font->status; |
Line 764... | Line 925... | ||
764 | 925 | ||
765 | subset_glyph->is_scaled = FALSE; |
- | |
766 | type1_font = FALSE; |
- | |
767 | #if CAIRO_HAS_FT_FONT |
926 | subset_glyph->is_scaled = FALSE; |
768 | type1_font = _cairo_type1_scaled_font_is_type1 (unscaled_font); |
- | |
769 | #endif |
927 | type1_font = _cairo_type1_scaled_font_is_type1 (unscaled_font); |
770 | if (subsets->type == CAIRO_SUBSETS_COMPOSITE && !type1_font) { |
928 | if (subsets->type == CAIRO_SUBSETS_COMPOSITE && !type1_font) { |
771 | max_glyphs = MAX_GLYPHS_PER_COMPOSITE_FONT; |
929 | max_glyphs = MAX_GLYPHS_PER_COMPOSITE_FONT; |
772 | subset_glyph->is_composite = TRUE; |
930 | subset_glyph->is_composite = TRUE; |
773 | } else { |
931 | } else { |
Line 879... | Line 1037... | ||
879 | if (! collection.glyphs_size) |
1037 | if (! collection.glyphs_size) |
880 | return CAIRO_STATUS_SUCCESS; |
1038 | return CAIRO_STATUS_SUCCESS; |
Line 881... | Line 1039... | ||
881 | 1039 | ||
882 | collection.glyphs = _cairo_malloc_ab (collection.glyphs_size, sizeof(unsigned long)); |
1040 | collection.glyphs = _cairo_malloc_ab (collection.glyphs_size, sizeof(unsigned long)); |
- | 1041 | collection.utf8 = _cairo_malloc_ab (collection.glyphs_size, sizeof(char *)); |
|
- | 1042 | collection.to_latin_char = _cairo_malloc_ab (collection.glyphs_size, sizeof(int)); |
|
883 | collection.utf8 = _cairo_malloc_ab (collection.glyphs_size, sizeof(char *)); |
1043 | collection.latin_to_subset_glyph_index = _cairo_malloc_ab (256, sizeof(unsigned long)); |
884 | if (unlikely (collection.glyphs == NULL || collection.utf8 == NULL)) { |
1044 | if (unlikely (collection.glyphs == NULL || |
- | 1045 | collection.utf8 == NULL || |
|
- | 1046 | collection.to_latin_char == NULL || |
|
885 | if (collection.glyphs != NULL) |
1047 | collection.latin_to_subset_glyph_index == NULL)) { |
886 | free (collection.glyphs); |
- | |
887 | if (collection.utf8 != NULL) |
1048 | free (collection.glyphs); |
- | 1049 | free (collection.utf8); |
|
- | 1050 | free (collection.to_latin_char); |
|
Line 888... | Line 1051... | ||
888 | free (collection.utf8); |
1051 | free (collection.latin_to_subset_glyph_index); |
889 | 1052 | ||
Line 890... | Line 1053... | ||
890 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1053 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
Line 905... | Line 1068... | ||
905 | 1068 | ||
906 | sub_font = sub_font->next; |
1069 | sub_font = sub_font->next; |
907 | } |
1070 | } |
908 | free (collection.utf8); |
1071 | free (collection.utf8); |
- | 1072 | free (collection.glyphs); |
|
- | 1073 | free (collection.to_latin_char); |
|
Line 909... | Line 1074... | ||
909 | free (collection.glyphs); |
1074 | free (collection.latin_to_subset_glyph_index); |
910 | 1075 | ||
Line 911... | Line 1076... | ||
911 | return collection.status; |
1076 | return collection.status; |
Line 1038... | Line 1203... | ||
1038 | if (unlikely (status)) |
1203 | if (unlikely (status)) |
1039 | goto CLEANUP_HASH; |
1204 | goto CLEANUP_HASH; |
1040 | } |
1205 | } |
Line 1041... | Line 1206... | ||
1041 | 1206 | ||
- | 1207 | if (utf16_len == 1) { |
|
- | 1208 | int ch = _cairo_unicode_to_winansi (utf16[0]); |
|
- | 1209 | if (ch > 0 && _cairo_winansi_to_glyphname (ch)) |
|
- | 1210 | strncpy (buf, _cairo_winansi_to_glyphname (ch), sizeof (buf)); |
|
1042 | if (utf16_len == 1) { |
1211 | else |
- | 1212 | snprintf (buf, sizeof (buf), "uni%04X", (int) utf16[0]); |
|
1043 | snprintf (buf, sizeof (buf), "uni%04X", (int) utf16[0]); |
1213 | |
1044 | _cairo_string_init_key (&key, buf); |
1214 | _cairo_string_init_key (&key, buf); |
1045 | entry = _cairo_hash_table_lookup (names, &key.base); |
1215 | entry = _cairo_hash_table_lookup (names, &key.base); |
1046 | if (entry != NULL) |
1216 | if (entry != NULL) |
1047 | snprintf (buf, sizeof (buf), "g%d", i); |
1217 | snprintf (buf, sizeof (buf), "g%d", i); |
1048 | } else { |
1218 | } else { |
1049 | snprintf (buf, sizeof (buf), "g%d", i); |
1219 | snprintf (buf, sizeof (buf), "g%d", i); |
1050 | } |
- | |
1051 | if (utf16) |
1220 | } |
Line 1052... | Line 1221... | ||
1052 | free (utf16); |
1221 | free (utf16); |
1053 | 1222 | ||
1054 | subset->glyph_names[i] = strdup (buf); |
1223 | subset->glyph_names[i] = strdup (buf); |
Line 1075... | Line 1244... | ||
1075 | if (likely (status == CAIRO_STATUS_SUCCESS)) |
1244 | if (likely (status == CAIRO_STATUS_SUCCESS)) |
1076 | return CAIRO_STATUS_SUCCESS; |
1245 | return CAIRO_STATUS_SUCCESS; |
Line 1077... | Line 1246... | ||
1077 | 1246 | ||
1078 | if (subset->glyph_names != NULL) { |
1247 | if (subset->glyph_names != NULL) { |
1079 | for (i = 0; i < subset->num_glyphs; i++) { |
- | |
1080 | if (subset->glyph_names[i] != NULL) |
1248 | for (i = 0; i < subset->num_glyphs; i++) { |
1081 | free (subset->glyph_names[i]); |
1249 | free (subset->glyph_names[i]); |
Line 1082... | Line 1250... | ||
1082 | } |
1250 | } |
1083 | 1251 |