beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-scaled-font-subsets.c
blob196fa999aa727352f50e1af669ac6894b3164faa
1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2003 University of Southern California
4 * Copyright © 2005 Red Hat, Inc
5 * Copyright © 2006 Keith Packard
6 * Copyright © 2006 Red Hat, Inc
8 * This library is free software; you can redistribute it and/or
9 * modify it either under the terms of the GNU Lesser General Public
10 * License version 2.1 as published by the Free Software Foundation
11 * (the "LGPL") or, at your option, under the terms of the Mozilla
12 * Public License Version 1.1 (the "MPL"). If you do not alter this
13 * notice, a recipient may use your version of this file under either
14 * the MPL or the LGPL.
16 * You should have received a copy of the LGPL along with this library
17 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
19 * You should have received a copy of the MPL along with this library
20 * in the file COPYING-MPL-1.1
22 * The contents of this file are subject to the Mozilla Public License
23 * Version 1.1 (the "License"); you may not use this file except in
24 * compliance with the License. You may obtain a copy of the License at
25 * http://www.mozilla.org/MPL/
27 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
28 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
29 * the specific language governing rights and limitations.
31 * The Original Code is the cairo graphics library.
33 * The Initial Developer of the Original Code is University of Southern
34 * California.
36 * Contributor(s):
37 * Carl D. Worth <cworth@cworth.org>
38 * Kristian Høgsberg <krh@redhat.com>
39 * Keith Packard <keithp@keithp.com>
40 * Adrian Johnson <ajohnson@redneon.com>
43 #define _BSD_SOURCE /* for snprintf(), strdup() */
44 #include "cairoint.h"
45 #include "cairo-error-private.h"
47 #if CAIRO_HAS_FONT_SUBSET
49 #include "cairo-scaled-font-subsets-private.h"
50 #include "cairo-user-font-private.h"
52 #define MAX_GLYPHS_PER_SIMPLE_FONT 256
53 #define MAX_GLYPHS_PER_COMPOSITE_FONT 65536
55 typedef enum {
56 CAIRO_SUBSETS_SCALED,
57 CAIRO_SUBSETS_SIMPLE,
58 CAIRO_SUBSETS_COMPOSITE
59 } cairo_subsets_type_t;
61 typedef enum {
62 CAIRO_SUBSETS_FOREACH_UNSCALED,
63 CAIRO_SUBSETS_FOREACH_SCALED,
64 CAIRO_SUBSETS_FOREACH_USER
65 } cairo_subsets_foreach_type_t;
67 typedef struct _cairo_sub_font {
68 cairo_hash_entry_t base;
70 cairo_bool_t is_scaled;
71 cairo_bool_t is_composite;
72 cairo_bool_t is_user;
73 cairo_bool_t use_latin_subset;
74 cairo_scaled_font_subsets_t *parent;
75 cairo_scaled_font_t *scaled_font;
76 unsigned int font_id;
78 int current_subset;
79 int num_glyphs_in_current_subset;
80 int num_glyphs_in_latin_subset;
81 int max_glyphs_per_subset;
82 char latin_char_map[256];
84 cairo_hash_table_t *sub_font_glyphs;
85 struct _cairo_sub_font *next;
86 } cairo_sub_font_t;
88 struct _cairo_scaled_font_subsets {
89 cairo_subsets_type_t type;
90 cairo_bool_t use_latin_subset;
92 int max_glyphs_per_unscaled_subset_used;
93 cairo_hash_table_t *unscaled_sub_fonts;
94 cairo_sub_font_t *unscaled_sub_fonts_list;
95 cairo_sub_font_t *unscaled_sub_fonts_list_end;
97 int max_glyphs_per_scaled_subset_used;
98 cairo_hash_table_t *scaled_sub_fonts;
99 cairo_sub_font_t *scaled_sub_fonts_list;
100 cairo_sub_font_t *scaled_sub_fonts_list_end;
102 int num_sub_fonts;
105 typedef struct _cairo_sub_font_glyph {
106 cairo_hash_entry_t base;
108 unsigned int subset_id;
109 unsigned int subset_glyph_index;
110 double x_advance;
111 double y_advance;
113 cairo_bool_t is_latin;
114 int latin_character;
115 cairo_bool_t is_mapped;
116 uint32_t unicode;
117 char *utf8;
118 int utf8_len;
119 } cairo_sub_font_glyph_t;
121 typedef struct _cairo_sub_font_collection {
122 unsigned long *glyphs; /* scaled_font_glyph_index */
123 char **utf8;
124 unsigned int glyphs_size;
125 int *to_latin_char;
126 unsigned long *latin_to_subset_glyph_index;
127 unsigned int max_glyph;
128 unsigned int num_glyphs;
130 unsigned int subset_id;
132 cairo_status_t status;
133 cairo_scaled_font_subset_callback_func_t font_subset_callback;
134 void *font_subset_callback_closure;
135 } cairo_sub_font_collection_t;
137 typedef struct _cairo_string_entry {
138 cairo_hash_entry_t base;
139 char *string;
140 } cairo_string_entry_t;
142 static cairo_status_t
143 _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
144 unsigned long scaled_font_glyph_index,
145 const char * utf8,
146 int utf8_len,
147 cairo_scaled_font_subsets_glyph_t *subset_glyph);
149 static void
150 _cairo_sub_font_glyph_init_key (cairo_sub_font_glyph_t *sub_font_glyph,
151 unsigned long scaled_font_glyph_index)
153 sub_font_glyph->base.hash = scaled_font_glyph_index;
156 static cairo_sub_font_glyph_t *
157 _cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index,
158 unsigned int subset_id,
159 unsigned int subset_glyph_index,
160 double x_advance,
161 double y_advance,
162 int latin_character,
163 uint32_t unicode,
164 char *utf8,
165 int utf8_len)
167 cairo_sub_font_glyph_t *sub_font_glyph;
169 sub_font_glyph = malloc (sizeof (cairo_sub_font_glyph_t));
170 if (unlikely (sub_font_glyph == NULL)) {
171 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
172 return NULL;
175 _cairo_sub_font_glyph_init_key (sub_font_glyph, scaled_font_glyph_index);
176 sub_font_glyph->subset_id = subset_id;
177 sub_font_glyph->subset_glyph_index = subset_glyph_index;
178 sub_font_glyph->x_advance = x_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;
182 sub_font_glyph->is_mapped = FALSE;
183 sub_font_glyph->unicode = unicode;
184 sub_font_glyph->utf8 = utf8;
185 sub_font_glyph->utf8_len = utf8_len;
187 return sub_font_glyph;
190 static void
191 _cairo_sub_font_glyph_destroy (cairo_sub_font_glyph_t *sub_font_glyph)
193 free (sub_font_glyph->utf8);
195 free (sub_font_glyph);
198 static void
199 _cairo_sub_font_glyph_pluck (void *entry, void *closure)
201 cairo_sub_font_glyph_t *sub_font_glyph = entry;
202 cairo_hash_table_t *sub_font_glyphs = closure;
204 _cairo_hash_table_remove (sub_font_glyphs, &sub_font_glyph->base);
205 _cairo_sub_font_glyph_destroy (sub_font_glyph);
208 static void
209 _cairo_sub_font_glyph_collect (void *entry, void *closure)
211 cairo_sub_font_glyph_t *sub_font_glyph = entry;
212 cairo_sub_font_collection_t *collection = closure;
213 unsigned long scaled_font_glyph_index;
214 unsigned int subset_glyph_index;
216 if (sub_font_glyph->subset_id != collection->subset_id)
217 return;
219 scaled_font_glyph_index = sub_font_glyph->base.hash;
220 subset_glyph_index = sub_font_glyph->subset_glyph_index;
222 /* Ensure we don't exceed the allocated bounds. */
223 assert (subset_glyph_index < collection->glyphs_size);
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;
231 if (subset_glyph_index > collection->max_glyph)
232 collection->max_glyph = subset_glyph_index;
234 collection->num_glyphs++;
237 static cairo_bool_t
238 _cairo_sub_fonts_equal (const void *key_a, const void *key_b)
240 const cairo_sub_font_t *sub_font_a = key_a;
241 const cairo_sub_font_t *sub_font_b = key_b;
242 cairo_scaled_font_t *a = sub_font_a->scaled_font;
243 cairo_scaled_font_t *b = sub_font_b->scaled_font;
245 if (sub_font_a->is_scaled)
246 return a == b;
247 else
248 return a->font_face == b->font_face || a->original_font_face == b->original_font_face;
251 static void
252 _cairo_sub_font_init_key (cairo_sub_font_t *sub_font,
253 cairo_scaled_font_t *scaled_font)
255 if (sub_font->is_scaled)
257 sub_font->base.hash = (unsigned long) scaled_font;
258 sub_font->scaled_font = scaled_font;
260 else
262 sub_font->base.hash = (unsigned long) scaled_font->font_face;
263 sub_font->scaled_font = scaled_font;
267 static cairo_status_t
268 _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
269 cairo_scaled_font_t *scaled_font,
270 unsigned int font_id,
271 int max_glyphs_per_subset,
272 cairo_bool_t is_scaled,
273 cairo_bool_t is_composite,
274 cairo_sub_font_t **sub_font_out)
276 cairo_sub_font_t *sub_font;
277 int i;
279 sub_font = malloc (sizeof (cairo_sub_font_t));
280 if (unlikely (sub_font == NULL))
281 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
283 sub_font->is_scaled = is_scaled;
284 sub_font->is_composite = is_composite;
285 sub_font->is_user = _cairo_font_face_is_user (scaled_font->font_face);
286 _cairo_sub_font_init_key (sub_font, scaled_font);
288 sub_font->parent = parent;
289 sub_font->scaled_font = scaled_font;
290 sub_font->font_id = font_id;
292 sub_font->use_latin_subset = parent->use_latin_subset;
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) )
298 sub_font->use_latin_subset = FALSE;
301 if (sub_font->use_latin_subset)
302 sub_font->current_subset = 1; /* reserve subset 0 for latin glyphs */
303 else
304 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;
309 for (i = 0; i < 256; i++)
310 sub_font->latin_char_map[i] = FALSE;
312 sub_font->sub_font_glyphs = _cairo_hash_table_create (NULL);
313 if (unlikely (sub_font->sub_font_glyphs == NULL)) {
314 free (sub_font);
315 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
317 sub_font->next = NULL;
318 *sub_font_out = sub_font;
319 return CAIRO_STATUS_SUCCESS;
322 static void
323 _cairo_sub_font_destroy (cairo_sub_font_t *sub_font)
325 _cairo_hash_table_foreach (sub_font->sub_font_glyphs,
326 _cairo_sub_font_glyph_pluck,
327 sub_font->sub_font_glyphs);
328 _cairo_hash_table_destroy (sub_font->sub_font_glyphs);
329 cairo_scaled_font_destroy (sub_font->scaled_font);
330 free (sub_font);
333 static void
334 _cairo_sub_font_pluck (void *entry, void *closure)
336 cairo_sub_font_t *sub_font = entry;
337 cairo_hash_table_t *sub_fonts = closure;
339 _cairo_hash_table_remove (sub_fonts, &sub_font->base);
340 _cairo_sub_font_destroy (sub_font);
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
353 _cairo_unicode_to_winansi (unsigned long uni)
355 int i;
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;
363 for (i = 0; i < 32; i++)
364 if (_winansi_0x80_to_0x9f[i] == uni)
365 return i + 0x80;
367 return -1;
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,
373 uint32_t *unicode_out,
374 char **utf8_out,
375 int *utf8_len_out)
377 uint32_t unicode;
378 char buf[8];
379 int len;
380 cairo_status_t status;
382 /* Do a reverse lookup on the glyph index. unicode is -1 if the
383 * index could not be mapped to a unicode character. */
384 unicode = -1;
385 status = _cairo_truetype_index_to_ucs4 (scaled_font,
386 scaled_font_glyph_index,
387 &unicode);
388 if (_cairo_status_is_error (status))
389 return status;
391 if (unicode == (uint32_t)-1 && scaled_font->backend->index_to_ucs4) {
392 status = scaled_font->backend->index_to_ucs4 (scaled_font,
393 scaled_font_glyph_index,
394 &unicode);
395 if (unlikely (status))
396 return status;
399 *unicode_out = unicode;
400 *utf8_out = NULL;
401 *utf8_len_out = 0;
402 if (unicode != (uint32_t) -1) {
403 len = _cairo_ucs4_to_utf8 (unicode, buf);
404 if (len > 0) {
405 *utf8_out = malloc (len + 1);
406 if (unlikely (*utf8_out == NULL))
407 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
409 memcpy (*utf8_out, buf, len);
410 (*utf8_out)[len] = 0;
411 *utf8_len_out = len;
415 return CAIRO_STATUS_SUCCESS;
418 static cairo_status_t
419 _cairo_sub_font_glyph_map_to_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
420 const char *utf8,
421 int utf8_len,
422 cairo_bool_t *is_mapped)
424 *is_mapped = FALSE;
426 if (utf8_len < 0)
427 return CAIRO_STATUS_SUCCESS;
429 if (utf8 != NULL && utf8_len != 0 && utf8[utf8_len - 1] == '\0')
430 utf8_len--;
432 if (utf8 != NULL && utf8_len != 0) {
433 if (sub_font_glyph->utf8 != NULL) {
434 if (utf8_len == sub_font_glyph->utf8_len &&
435 memcmp (utf8, sub_font_glyph->utf8, utf8_len) == 0)
437 /* Requested utf8 mapping matches the existing mapping */
438 *is_mapped = TRUE;
440 } else {
441 /* No existing mapping. Use the requested mapping */
442 sub_font_glyph->utf8 = malloc (utf8_len + 1);
443 if (unlikely (sub_font_glyph->utf8 == NULL))
444 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
446 memcpy (sub_font_glyph->utf8, utf8, utf8_len);
447 sub_font_glyph->utf8[utf8_len] = 0;
448 sub_font_glyph->utf8_len = utf8_len;
449 *is_mapped = TRUE;
453 return CAIRO_STATUS_SUCCESS;
456 static cairo_int_status_t
457 _cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
458 unsigned long scaled_font_glyph_index,
459 const char *utf8,
460 int utf8_len,
461 cairo_scaled_font_subsets_glyph_t *subset_glyph)
463 cairo_sub_font_glyph_t key, *sub_font_glyph;
464 cairo_int_status_t status;
466 _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
467 sub_font_glyph = _cairo_hash_table_lookup (sub_font->sub_font_glyphs,
468 &key.base);
469 if (sub_font_glyph != NULL) {
470 subset_glyph->font_id = sub_font->font_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
475 subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index;
477 subset_glyph->is_scaled = sub_font->is_scaled;
478 subset_glyph->is_composite = sub_font->is_composite;
479 subset_glyph->is_latin = sub_font_glyph->is_latin;
480 subset_glyph->x_advance = sub_font_glyph->x_advance;
481 subset_glyph->y_advance = sub_font_glyph->y_advance;
482 status = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph,
483 utf8, utf8_len,
484 &subset_glyph->utf8_is_mapped);
485 subset_glyph->unicode = sub_font_glyph->unicode;
487 return status;
490 return CAIRO_INT_STATUS_UNSUPPORTED;
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,
497 int latin_character,
498 uint32_t unicode,
499 char *utf8,
500 int utf8_len,
501 cairo_sub_font_glyph_t **sub_font_glyph_out)
503 cairo_scaled_glyph_t *scaled_glyph;
504 cairo_sub_font_glyph_t *sub_font_glyph;
505 int *num_glyphs_in_subset_ptr;
506 double x_advance;
507 double y_advance;
508 cairo_int_status_t status;
510 _cairo_scaled_font_freeze_cache (sub_font->scaled_font);
511 status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
512 scaled_font_glyph_index,
513 CAIRO_SCALED_GLYPH_INFO_METRICS,
514 &scaled_glyph);
515 assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
516 if (unlikely (status)) {
517 _cairo_scaled_font_thaw_cache (sub_font->scaled_font);
518 return status;
521 x_advance = scaled_glyph->metrics.x_advance;
522 y_advance = scaled_glyph->metrics.y_advance;
523 _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)
527 sub_font->current_subset++;
528 sub_font->num_glyphs_in_current_subset = 0;
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;
536 /* Reserve first glyph in subset for the .notdef glyph except for
537 * Type 3 fonts */
538 if (*num_glyphs_in_subset_ptr == 0 &&
539 scaled_font_glyph_index != 0 &&
540 ! _cairo_font_face_is_user (sub_font->scaled_font->font_face))
542 status = _cairo_sub_font_add_glyph (sub_font,
544 is_latin,
547 NULL,
549 &sub_font_glyph);
550 if (unlikely (status))
551 return status;
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);
564 if (unlikely (sub_font_glyph == NULL))
565 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
567 status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base);
568 if (unlikely (status)) {
569 _cairo_sub_font_glyph_destroy (sub_font_glyph);
570 return status;
573 (*num_glyphs_in_subset_ptr)++;
574 if (sub_font->is_scaled) {
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;
582 *sub_font_glyph_out = sub_font_glyph;
584 return CAIRO_STATUS_SUCCESS;
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)
594 cairo_sub_font_glyph_t key, *sub_font_glyph;
595 cairo_status_t status;
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;
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;
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;
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);
632 memcpy (font_utf8, text_utf8, text_utf8_len);
633 font_utf8[text_utf8_len] = 0;
634 font_utf8_len = text_utf8_len;
636 free (ucs4);
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.
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)))
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))
655 if (!sub_font->latin_char_map[latin_character]) {
656 sub_font->latin_char_map[latin_character] = TRUE;
657 is_latin = TRUE;
662 status = _cairo_sub_font_add_glyph (sub_font,
663 scaled_font_glyph_index,
664 is_latin,
665 latin_character,
666 font_unicode,
667 font_utf8,
668 font_utf8_len,
669 &sub_font_glyph);
670 if (unlikely(status))
671 return status;
674 subset_glyph->font_id = sub_font->font_id;
675 subset_glyph->subset_id = sub_font_glyph->subset_id;
676 if (sub_font_glyph->is_latin)
677 subset_glyph->subset_glyph_index = sub_font_glyph->latin_character;
678 else
679 subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index;
681 subset_glyph->is_scaled = sub_font->is_scaled;
682 subset_glyph->is_composite = sub_font->is_composite;
683 subset_glyph->is_latin = sub_font_glyph->is_latin;
684 subset_glyph->x_advance = sub_font_glyph->x_advance;
685 subset_glyph->y_advance = sub_font_glyph->y_advance;
686 status = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph,
687 text_utf8, text_utf8_len,
688 &subset_glyph->utf8_is_mapped);
689 subset_glyph->unicode = sub_font_glyph->unicode;
691 return status;
694 static void
695 _cairo_sub_font_collect (void *entry, void *closure)
697 cairo_sub_font_t *sub_font = entry;
698 cairo_sub_font_collection_t *collection = closure;
699 cairo_scaled_font_subset_t subset;
700 int i;
701 unsigned int j;
703 if (collection->status)
704 return;
706 collection->status = sub_font->scaled_font->status;
707 if (collection->status)
708 return;
710 for (i = 0; i <= sub_font->current_subset; i++) {
711 collection->subset_id = i;
712 collection->num_glyphs = 0;
713 collection->max_glyph = 0;
714 memset (collection->latin_to_subset_glyph_index, 0, 256*sizeof(unsigned long));
716 _cairo_hash_table_foreach (sub_font->sub_font_glyphs,
717 _cairo_sub_font_glyph_collect, collection);
718 if (collection->status)
719 break;
720 if (collection->num_glyphs == 0)
721 continue;
723 /* Ensure the resulting array has no uninitialized holes */
724 assert (collection->num_glyphs == collection->max_glyph + 1);
726 subset.scaled_font = sub_font->scaled_font;
727 subset.is_composite = sub_font->is_composite;
728 subset.is_scaled = sub_font->is_scaled;
729 subset.font_id = sub_font->font_id;
730 subset.subset_id = i;
731 subset.glyphs = collection->glyphs;
732 subset.utf8 = collection->utf8;
733 subset.num_glyphs = collection->num_glyphs;
734 subset.glyph_names = NULL;
736 subset.is_latin = FALSE;
737 if (sub_font->use_latin_subset && i == 0) {
738 subset.is_latin = TRUE;
739 subset.to_latin_char = collection->to_latin_char;
740 subset.latin_to_subset_glyph_index = collection->latin_to_subset_glyph_index;
741 } else {
742 subset.to_latin_char = NULL;
743 subset.latin_to_subset_glyph_index = NULL;
746 collection->status = (collection->font_subset_callback) (&subset,
747 collection->font_subset_callback_closure);
749 if (subset.glyph_names != NULL) {
750 for (j = 0; j < collection->num_glyphs; j++)
751 free (subset.glyph_names[j]);
752 free (subset.glyph_names);
755 if (collection->status)
756 break;
760 static cairo_scaled_font_subsets_t *
761 _cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type)
763 cairo_scaled_font_subsets_t *subsets;
765 subsets = malloc (sizeof (cairo_scaled_font_subsets_t));
766 if (unlikely (subsets == NULL)) {
767 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
768 return NULL;
771 subsets->type = type;
772 subsets->use_latin_subset = FALSE;
773 subsets->max_glyphs_per_unscaled_subset_used = 0;
774 subsets->max_glyphs_per_scaled_subset_used = 0;
775 subsets->num_sub_fonts = 0;
777 subsets->unscaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
778 if (! subsets->unscaled_sub_fonts) {
779 free (subsets);
780 return NULL;
782 subsets->unscaled_sub_fonts_list = NULL;
783 subsets->unscaled_sub_fonts_list_end = NULL;
785 subsets->scaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
786 if (! subsets->scaled_sub_fonts) {
787 _cairo_hash_table_destroy (subsets->unscaled_sub_fonts);
788 free (subsets);
789 return NULL;
791 subsets->scaled_sub_fonts_list = NULL;
792 subsets->scaled_sub_fonts_list_end = NULL;
794 return subsets;
797 cairo_scaled_font_subsets_t *
798 _cairo_scaled_font_subsets_create_scaled (void)
800 return _cairo_scaled_font_subsets_create_internal (CAIRO_SUBSETS_SCALED);
803 cairo_scaled_font_subsets_t *
804 _cairo_scaled_font_subsets_create_simple (void)
806 return _cairo_scaled_font_subsets_create_internal (CAIRO_SUBSETS_SIMPLE);
809 cairo_scaled_font_subsets_t *
810 _cairo_scaled_font_subsets_create_composite (void)
812 return _cairo_scaled_font_subsets_create_internal (CAIRO_SUBSETS_COMPOSITE);
815 void
816 _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *subsets)
818 _cairo_hash_table_foreach (subsets->scaled_sub_fonts, _cairo_sub_font_pluck, subsets->scaled_sub_fonts);
819 _cairo_hash_table_destroy (subsets->scaled_sub_fonts);
821 _cairo_hash_table_foreach (subsets->unscaled_sub_fonts, _cairo_sub_font_pluck, subsets->unscaled_sub_fonts);
822 _cairo_hash_table_destroy (subsets->unscaled_sub_fonts);
824 free (subsets);
827 void
828 _cairo_scaled_font_subsets_enable_latin_subset (cairo_scaled_font_subsets_t *font_subsets,
829 cairo_bool_t use_latin)
831 font_subsets->use_latin_subset = use_latin;
834 cairo_status_t
835 _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
836 cairo_scaled_font_t *scaled_font,
837 unsigned long scaled_font_glyph_index,
838 const char * utf8,
839 int utf8_len,
840 cairo_scaled_font_subsets_glyph_t *subset_glyph)
842 cairo_sub_font_t key, *sub_font;
843 cairo_scaled_glyph_t *scaled_glyph;
844 cairo_font_face_t *font_face;
845 cairo_matrix_t identity;
846 cairo_font_options_t font_options;
847 cairo_scaled_font_t *unscaled_font;
848 cairo_int_status_t status;
849 int max_glyphs;
850 cairo_bool_t type1_font;
852 /* Lookup glyph in unscaled subsets */
853 if (subsets->type != CAIRO_SUBSETS_SCALED) {
854 key.is_scaled = FALSE;
855 _cairo_sub_font_init_key (&key, scaled_font);
856 sub_font = _cairo_hash_table_lookup (subsets->unscaled_sub_fonts,
857 &key.base);
858 if (sub_font != NULL) {
859 status = _cairo_sub_font_lookup_glyph (sub_font,
860 scaled_font_glyph_index,
861 utf8, utf8_len,
862 subset_glyph);
863 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
864 return status;
868 /* Lookup glyph in scaled subsets */
869 key.is_scaled = TRUE;
870 _cairo_sub_font_init_key (&key, scaled_font);
871 sub_font = _cairo_hash_table_lookup (subsets->scaled_sub_fonts,
872 &key.base);
873 if (sub_font != NULL) {
874 status = _cairo_sub_font_lookup_glyph (sub_font,
875 scaled_font_glyph_index,
876 utf8, utf8_len,
877 subset_glyph);
878 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
879 return status;
882 /* Glyph not found. Determine whether the glyph is outline or
883 * bitmap and add to the appropriate subset.
885 * glyph_index 0 (the .notdef glyph) is a special case. Some fonts
886 * will return CAIRO_INT_STATUS_UNSUPPORTED when doing a
887 * _scaled_glyph_lookup(_GLYPH_INFO_PATH). Type1-fallback creates
888 * empty glyphs in this case so we can put the glyph in a unscaled
889 * subset. */
890 if (scaled_font_glyph_index == 0 ||
891 _cairo_font_face_is_user (scaled_font->font_face)) {
892 status = CAIRO_STATUS_SUCCESS;
893 } else {
894 _cairo_scaled_font_freeze_cache (scaled_font);
895 status = _cairo_scaled_glyph_lookup (scaled_font,
896 scaled_font_glyph_index,
897 CAIRO_SCALED_GLYPH_INFO_PATH,
898 &scaled_glyph);
899 _cairo_scaled_font_thaw_cache (scaled_font);
901 if (_cairo_int_status_is_error (status))
902 return status;
904 if (status == CAIRO_INT_STATUS_SUCCESS &&
905 subsets->type != CAIRO_SUBSETS_SCALED &&
906 ! _cairo_font_face_is_user (scaled_font->font_face))
908 /* Path available. Add to unscaled subset. */
909 key.is_scaled = FALSE;
910 _cairo_sub_font_init_key (&key, scaled_font);
911 sub_font = _cairo_hash_table_lookup (subsets->unscaled_sub_fonts,
912 &key.base);
913 if (sub_font == NULL) {
914 font_face = cairo_scaled_font_get_font_face (scaled_font);
915 cairo_matrix_init_identity (&identity);
916 _cairo_font_options_init_default (&font_options);
917 cairo_font_options_set_hint_style (&font_options, CAIRO_HINT_STYLE_NONE);
918 cairo_font_options_set_hint_metrics (&font_options, CAIRO_HINT_METRICS_OFF);
919 unscaled_font = cairo_scaled_font_create (font_face,
920 &identity,
921 &identity,
922 &font_options);
923 if (unlikely (unscaled_font->status))
924 return unscaled_font->status;
926 subset_glyph->is_scaled = FALSE;
927 type1_font = _cairo_type1_scaled_font_is_type1 (unscaled_font);
928 if (subsets->type == CAIRO_SUBSETS_COMPOSITE && !type1_font) {
929 max_glyphs = MAX_GLYPHS_PER_COMPOSITE_FONT;
930 subset_glyph->is_composite = TRUE;
931 } else {
932 max_glyphs = MAX_GLYPHS_PER_SIMPLE_FONT;
933 subset_glyph->is_composite = FALSE;
936 status = _cairo_sub_font_create (subsets,
937 unscaled_font,
938 subsets->num_sub_fonts,
939 max_glyphs,
940 subset_glyph->is_scaled,
941 subset_glyph->is_composite,
942 &sub_font);
944 if (unlikely (status)) {
945 cairo_scaled_font_destroy (unscaled_font);
946 return status;
949 status = _cairo_hash_table_insert (subsets->unscaled_sub_fonts,
950 &sub_font->base);
952 if (unlikely (status)) {
953 _cairo_sub_font_destroy (sub_font);
954 return status;
956 if (!subsets->unscaled_sub_fonts_list)
957 subsets->unscaled_sub_fonts_list = sub_font;
958 else
959 subsets->unscaled_sub_fonts_list_end->next = sub_font;
960 subsets->unscaled_sub_fonts_list_end = sub_font;
961 subsets->num_sub_fonts++;
963 } else {
964 /* No path available. Add to scaled subset. */
965 key.is_scaled = TRUE;
966 _cairo_sub_font_init_key (&key, scaled_font);
967 sub_font = _cairo_hash_table_lookup (subsets->scaled_sub_fonts,
968 &key.base);
969 if (sub_font == NULL) {
970 subset_glyph->is_scaled = TRUE;
971 subset_glyph->is_composite = FALSE;
972 if (subsets->type == CAIRO_SUBSETS_SCALED)
973 max_glyphs = INT_MAX;
974 else
975 max_glyphs = MAX_GLYPHS_PER_SIMPLE_FONT;
977 status = _cairo_sub_font_create (subsets,
978 cairo_scaled_font_reference (scaled_font),
979 subsets->num_sub_fonts,
980 max_glyphs,
981 subset_glyph->is_scaled,
982 subset_glyph->is_composite,
983 &sub_font);
984 if (unlikely (status)) {
985 cairo_scaled_font_destroy (scaled_font);
986 return status;
989 status = _cairo_hash_table_insert (subsets->scaled_sub_fonts,
990 &sub_font->base);
991 if (unlikely (status)) {
992 _cairo_sub_font_destroy (sub_font);
993 return status;
995 if (!subsets->scaled_sub_fonts_list)
996 subsets->scaled_sub_fonts_list = sub_font;
997 else
998 subsets->scaled_sub_fonts_list_end->next = sub_font;
999 subsets->scaled_sub_fonts_list_end = sub_font;
1000 subsets->num_sub_fonts++;
1004 return _cairo_sub_font_map_glyph (sub_font,
1005 scaled_font_glyph_index,
1006 utf8, utf8_len,
1007 subset_glyph);
1010 static cairo_status_t
1011 _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t *font_subsets,
1012 cairo_scaled_font_subset_callback_func_t font_subset_callback,
1013 void *closure,
1014 cairo_subsets_foreach_type_t type)
1016 cairo_sub_font_collection_t collection;
1017 cairo_sub_font_t *sub_font;
1018 cairo_bool_t is_scaled, is_user;
1020 is_scaled = FALSE;
1021 is_user = FALSE;
1023 if (type == CAIRO_SUBSETS_FOREACH_USER)
1024 is_user = TRUE;
1026 if (type == CAIRO_SUBSETS_FOREACH_SCALED ||
1027 type == CAIRO_SUBSETS_FOREACH_USER)
1029 is_scaled = TRUE;
1032 if (is_scaled)
1033 collection.glyphs_size = font_subsets->max_glyphs_per_scaled_subset_used;
1034 else
1035 collection.glyphs_size = font_subsets->max_glyphs_per_unscaled_subset_used;
1037 if (! collection.glyphs_size)
1038 return CAIRO_STATUS_SUCCESS;
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));
1043 collection.latin_to_subset_glyph_index = _cairo_malloc_ab (256, sizeof(unsigned long));
1044 if (unlikely (collection.glyphs == NULL ||
1045 collection.utf8 == NULL ||
1046 collection.to_latin_char == NULL ||
1047 collection.latin_to_subset_glyph_index == NULL)) {
1048 free (collection.glyphs);
1049 free (collection.utf8);
1050 free (collection.to_latin_char);
1051 free (collection.latin_to_subset_glyph_index);
1053 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1056 collection.font_subset_callback = font_subset_callback;
1057 collection.font_subset_callback_closure = closure;
1058 collection.status = CAIRO_STATUS_SUCCESS;
1060 if (is_scaled)
1061 sub_font = font_subsets->scaled_sub_fonts_list;
1062 else
1063 sub_font = font_subsets->unscaled_sub_fonts_list;
1065 while (sub_font) {
1066 if (sub_font->is_user == is_user)
1067 _cairo_sub_font_collect (sub_font, &collection);
1069 sub_font = sub_font->next;
1071 free (collection.utf8);
1072 free (collection.glyphs);
1073 free (collection.to_latin_char);
1074 free (collection.latin_to_subset_glyph_index);
1076 return collection.status;
1079 cairo_status_t
1080 _cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t *font_subsets,
1081 cairo_scaled_font_subset_callback_func_t font_subset_callback,
1082 void *closure)
1084 return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
1085 font_subset_callback,
1086 closure,
1087 CAIRO_SUBSETS_FOREACH_SCALED);
1090 cairo_status_t
1091 _cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *font_subsets,
1092 cairo_scaled_font_subset_callback_func_t font_subset_callback,
1093 void *closure)
1095 return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
1096 font_subset_callback,
1097 closure,
1098 CAIRO_SUBSETS_FOREACH_UNSCALED);
1101 cairo_status_t
1102 _cairo_scaled_font_subsets_foreach_user (cairo_scaled_font_subsets_t *font_subsets,
1103 cairo_scaled_font_subset_callback_func_t font_subset_callback,
1104 void *closure)
1106 return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
1107 font_subset_callback,
1108 closure,
1109 CAIRO_SUBSETS_FOREACH_USER);
1112 static cairo_bool_t
1113 _cairo_string_equal (const void *key_a, const void *key_b)
1115 const cairo_string_entry_t *a = key_a;
1116 const cairo_string_entry_t *b = key_b;
1118 if (strcmp (a->string, b->string) == 0)
1119 return TRUE;
1120 else
1121 return FALSE;
1124 static void
1125 _cairo_string_init_key (cairo_string_entry_t *key, char *s)
1127 unsigned long sum = 0;
1128 unsigned int i;
1130 for (i = 0; i < strlen(s); i++)
1131 sum += s[i];
1132 key->base.hash = sum;
1133 key->string = s;
1136 static cairo_status_t
1137 create_string_entry (char *s, cairo_string_entry_t **entry)
1139 *entry = malloc (sizeof (cairo_string_entry_t));
1140 if (unlikely (*entry == NULL))
1141 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1143 _cairo_string_init_key (*entry, s);
1145 return CAIRO_STATUS_SUCCESS;
1148 static void
1149 _pluck_entry (void *entry, void *closure)
1151 _cairo_hash_table_remove (closure, entry);
1152 free (entry);
1155 cairo_int_status_t
1156 _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset)
1158 unsigned int i;
1159 cairo_hash_table_t *names;
1160 cairo_string_entry_t key, *entry;
1161 char buf[30];
1162 char *utf8;
1163 uint16_t *utf16;
1164 int utf16_len;
1165 cairo_status_t status = CAIRO_STATUS_SUCCESS;
1167 names = _cairo_hash_table_create (_cairo_string_equal);
1168 if (unlikely (names == NULL))
1169 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1171 subset->glyph_names = calloc (subset->num_glyphs, sizeof (char *));
1172 if (unlikely (subset->glyph_names == NULL)) {
1173 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1174 goto CLEANUP_HASH;
1177 i = 0;
1178 if (! subset->is_scaled) {
1179 subset->glyph_names[0] = strdup (".notdef");
1180 if (unlikely (subset->glyph_names[0] == NULL)) {
1181 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1182 goto CLEANUP_HASH;
1185 status = create_string_entry (subset->glyph_names[0], &entry);
1186 if (unlikely (status))
1187 goto CLEANUP_HASH;
1189 status = _cairo_hash_table_insert (names, &entry->base);
1190 if (unlikely (status)) {
1191 free (entry);
1192 goto CLEANUP_HASH;
1194 i++;
1197 for (; i < subset->num_glyphs; i++) {
1198 utf8 = subset->utf8[i];
1199 utf16 = NULL;
1200 utf16_len = 0;
1201 if (utf8 && *utf8) {
1202 status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
1203 if (unlikely (status))
1204 goto CLEANUP_HASH;
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));
1211 buf[sizeof (buf)-1] = '\0';
1212 } else {
1213 snprintf (buf, sizeof (buf), "uni%04X", (int) utf16[0]);
1216 _cairo_string_init_key (&key, buf);
1217 entry = _cairo_hash_table_lookup (names, &key.base);
1218 if (entry != NULL)
1219 snprintf (buf, sizeof (buf), "g%d", i);
1220 } else {
1221 snprintf (buf, sizeof (buf), "g%d", i);
1223 free (utf16);
1225 subset->glyph_names[i] = strdup (buf);
1226 if (unlikely (subset->glyph_names[i] == NULL)) {
1227 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1228 goto CLEANUP_HASH;
1231 status = create_string_entry (subset->glyph_names[i], &entry);
1232 if (unlikely (status))
1233 goto CLEANUP_HASH;
1235 status = _cairo_hash_table_insert (names, &entry->base);
1236 if (unlikely (status)) {
1237 free (entry);
1238 goto CLEANUP_HASH;
1242 CLEANUP_HASH:
1243 _cairo_hash_table_foreach (names, _pluck_entry, names);
1244 _cairo_hash_table_destroy (names);
1246 if (likely (status == CAIRO_STATUS_SUCCESS))
1247 return CAIRO_STATUS_SUCCESS;
1249 if (subset->glyph_names != NULL) {
1250 for (i = 0; i < subset->num_glyphs; i++) {
1251 free (subset->glyph_names[i]);
1254 free (subset->glyph_names);
1255 subset->glyph_names = NULL;
1258 return status;
1261 cairo_int_status_t
1262 _cairo_escape_ps_name (char **ps_name)
1264 cairo_status_t status = CAIRO_STATUS_SUCCESS;
1266 /* Ensure PS name is a valid PDF/PS name object. In PDF names are
1267 * treated as UTF8 and non ASCII bytes, ' ', and '#' are encoded
1268 * as '#' followed by 2 hex digits that encode the byte. By also
1269 * encoding the characters in the reserved string we ensure the
1270 * name is also PS compatible. */
1271 if (*ps_name) {
1272 static const char *reserved = "()<>[]{}/%#\\";
1273 char buf[128]; /* max name length is 127 bytes */
1274 char *src = *ps_name;
1275 char *dst = buf;
1277 while (*src && dst < buf + 127) {
1278 unsigned char c = *src;
1279 if (c < 0x21 || c > 0x7e || strchr (reserved, c)) {
1280 if (dst + 4 > buf + 127)
1281 break;
1283 snprintf (dst, 4, "#%02X", c);
1284 src++;
1285 dst += 3;
1286 } else {
1287 *dst++ = *src++;
1290 *dst = 0;
1291 free (*ps_name);
1292 *ps_name = strdup (buf);
1293 if (*ps_name == NULL) {
1294 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1298 return status;
1301 #endif /* CAIRO_HAS_FONT_SUBSET */