fix getsup (HH)
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-truetype-subset.c
blob9137ef3aa38ae5e82b9e8362d63f8a3c3eb105f9
1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2004 Red Hat, Inc
5 * This library is free software; you can redistribute it and/or
6 * modify it either under the terms of the GNU Lesser General Public
7 * License version 2.1 as published by the Free Software Foundation
8 * (the "LGPL") or, at your option, under the terms of the Mozilla
9 * Public License Version 1.1 (the "MPL"). If you do not alter this
10 * notice, a recipient may use your version of this file under either
11 * the MPL or the LGPL.
13 * You should have received a copy of the LGPL along with this library
14 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
19 * The contents of this file are subject to the Mozilla Public License
20 * Version 1.1 (the "License"); you may not use this file except in
21 * compliance with the License. You may obtain a copy of the License at
22 * http://www.mozilla.org/MPL/
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 * the specific language governing rights and limitations.
28 * The Original Code is the cairo graphics library.
30 * The Initial Developer of the Original Code is Red Hat, Inc.
32 * Contributor(s):
33 * Kristian Høgsberg <krh@redhat.com>
34 * Adrian Johnson <ajohnson@redneon.com>
38 * Useful links:
39 * http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6.html
40 * http://www.microsoft.com/typography/specs/default.htm
43 #define _BSD_SOURCE /* for snprintf(), strdup() */
44 #include "cairoint.h"
46 #include "cairo-array-private.h"
47 #include "cairo-error-private.h"
49 #if CAIRO_HAS_FONT_SUBSET
51 #include "cairo-scaled-font-subsets-private.h"
52 #include "cairo-truetype-subset-private.h"
55 typedef struct subset_glyph subset_glyph_t;
56 struct subset_glyph {
57 int parent_index;
58 unsigned long location;
61 typedef struct _cairo_truetype_font cairo_truetype_font_t;
63 typedef struct table table_t;
64 struct table {
65 unsigned long tag;
66 cairo_status_t (*write) (cairo_truetype_font_t *font, unsigned long tag);
67 int pos; /* position in the font directory */
70 struct _cairo_truetype_font {
72 cairo_scaled_font_subset_t *scaled_font_subset;
74 table_t truetype_tables[10];
75 int num_tables;
77 struct {
78 char *font_name;
79 char *ps_name;
80 unsigned int num_glyphs;
81 int *widths;
82 long x_min, y_min, x_max, y_max;
83 long ascent, descent;
84 int units_per_em;
85 } base;
87 subset_glyph_t *glyphs;
88 const cairo_scaled_font_backend_t *backend;
89 int num_glyphs_in_face;
90 int checksum_index;
91 cairo_array_t output;
92 cairo_array_t string_offsets;
93 unsigned long last_offset;
94 unsigned long last_boundary;
95 int *parent_to_subset;
96 cairo_status_t status;
97 cairo_bool_t is_pdf;
101 * Test that the structs we define for TrueType tables have the
102 * correct size, ie. they are not padded.
104 #define check(T, S) COMPILE_TIME_ASSERT (sizeof (T) == (S))
105 check (tt_head_t, 54);
106 check (tt_hhea_t, 36);
107 check (tt_maxp_t, 32);
108 check (tt_name_record_t, 12);
109 check (tt_name_t, 18);
110 check (tt_name_t, 18);
111 check (tt_composite_glyph_t, 16);
112 check (tt_glyph_data_t, 26);
113 #undef check
115 static cairo_status_t
116 cairo_truetype_font_use_glyph (cairo_truetype_font_t *font,
117 unsigned short glyph,
118 unsigned short *out);
120 #define SFNT_VERSION 0x00010000
121 #define SFNT_STRING_MAX_LENGTH 65535
123 static cairo_status_t
124 _cairo_truetype_font_set_error (cairo_truetype_font_t *font,
125 cairo_status_t status)
127 if (status == CAIRO_STATUS_SUCCESS ||
128 status == (int)CAIRO_INT_STATUS_UNSUPPORTED)
129 return status;
131 _cairo_status_set_error (&font->status, status);
133 return _cairo_error (status);
136 static cairo_status_t
137 _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
138 cairo_bool_t is_pdf,
139 cairo_truetype_font_t **font_return)
141 cairo_status_t status;
142 cairo_truetype_font_t *font;
143 const cairo_scaled_font_backend_t *backend;
144 tt_head_t head;
145 tt_hhea_t hhea;
146 tt_maxp_t maxp;
147 unsigned long size;
149 backend = scaled_font_subset->scaled_font->backend;
150 if (!backend->load_truetype_table)
151 return CAIRO_INT_STATUS_UNSUPPORTED;
153 /* FIXME: We should either support subsetting vertical fonts, or fail on
154 * vertical. Currently font_options_t doesn't have vertical flag, but
155 * it should be added in the future. For now, the freetype backend
156 * returns UNSUPPORTED in load_truetype_table if the font is vertical.
158 * if (cairo_font_options_get_vertical_layout (scaled_font_subset->scaled_font))
159 * return CAIRO_INT_STATUS_UNSUPPORTED;
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;
166 size = sizeof (tt_head_t);
167 status = backend->load_truetype_table (scaled_font_subset->scaled_font,
168 TT_TAG_head, 0,
169 (unsigned char *) &head,
170 &size);
171 if (unlikely (status))
172 return status;
174 size = sizeof (tt_maxp_t);
175 status = backend->load_truetype_table (scaled_font_subset->scaled_font,
176 TT_TAG_maxp, 0,
177 (unsigned char *) &maxp,
178 &size);
179 if (unlikely (status))
180 return status;
182 size = sizeof (tt_hhea_t);
183 status = backend->load_truetype_table (scaled_font_subset->scaled_font,
184 TT_TAG_hhea, 0,
185 (unsigned char *) &hhea,
186 &size);
187 if (unlikely (status))
188 return status;
190 font = malloc (sizeof (cairo_truetype_font_t));
191 if (unlikely (font == NULL))
192 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
194 font->backend = backend;
195 font->num_glyphs_in_face = be16_to_cpu (maxp.num_glyphs);
196 font->scaled_font_subset = scaled_font_subset;
198 font->last_offset = 0;
199 font->last_boundary = 0;
200 _cairo_array_init (&font->output, sizeof (char));
201 status = _cairo_array_grow_by (&font->output, 4096);
202 if (unlikely (status))
203 goto fail1;
205 font->glyphs = calloc (font->num_glyphs_in_face + 1, sizeof (subset_glyph_t));
206 if (unlikely (font->glyphs == NULL)) {
207 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
208 goto fail1;
211 font->parent_to_subset = calloc (font->num_glyphs_in_face, sizeof (int));
212 if (unlikely (font->parent_to_subset == NULL)) {
213 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
214 goto fail2;
217 font->is_pdf = is_pdf;
218 font->base.num_glyphs = 0;
219 font->base.x_min = (int16_t) be16_to_cpu (head.x_min);
220 font->base.y_min = (int16_t) be16_to_cpu (head.y_min);
221 font->base.x_max = (int16_t) be16_to_cpu (head.x_max);
222 font->base.y_max = (int16_t) be16_to_cpu (head.y_max);
223 font->base.ascent = (int16_t) be16_to_cpu (hhea.ascender);
224 font->base.descent = (int16_t) be16_to_cpu (hhea.descender);
225 font->base.units_per_em = (int16_t) be16_to_cpu (head.units_per_em);
226 if (font->base.units_per_em == 0)
227 font->base.units_per_em = 2048;
229 font->base.ps_name = NULL;
230 font->base.font_name = NULL;
231 status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font,
232 &font->base.ps_name,
233 &font->base.font_name);
234 if (_cairo_status_is_error (status))
235 goto fail3;
237 /* If the PS name is not found, create a CairoFont-x-y name. */
238 if (font->base.ps_name == NULL) {
239 font->base.ps_name = malloc (30);
240 if (unlikely (font->base.ps_name == NULL)) {
241 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
242 goto fail3;
245 snprintf(font->base.ps_name, 30, "CairoFont-%u-%u",
246 scaled_font_subset->font_id,
247 scaled_font_subset->subset_id);
250 font->base.widths = calloc (font->num_glyphs_in_face, sizeof (int));
251 if (unlikely (font->base.widths == NULL)) {
252 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
253 goto fail4;
256 _cairo_array_init (&font->string_offsets, sizeof (unsigned long));
257 status = _cairo_array_grow_by (&font->string_offsets, 10);
258 if (unlikely (status))
259 goto fail5;
261 font->status = CAIRO_STATUS_SUCCESS;
263 *font_return = font;
265 return CAIRO_STATUS_SUCCESS;
267 fail5:
268 _cairo_array_fini (&font->string_offsets);
269 free (font->base.widths);
270 fail4:
271 free (font->base.ps_name);
272 fail3:
273 free (font->parent_to_subset);
274 free (font->base.font_name);
275 fail2:
276 free (font->glyphs);
277 fail1:
278 _cairo_array_fini (&font->output);
279 free (font);
281 return status;
284 static void
285 cairo_truetype_font_destroy (cairo_truetype_font_t *font)
287 _cairo_array_fini (&font->string_offsets);
288 free (font->base.widths);
289 free (font->base.ps_name);
290 free (font->base.font_name);
291 free (font->parent_to_subset);
292 free (font->glyphs);
293 _cairo_array_fini (&font->output);
294 free (font);
297 static cairo_status_t
298 cairo_truetype_font_allocate_write_buffer (cairo_truetype_font_t *font,
299 size_t length,
300 unsigned char **buffer)
302 cairo_status_t status;
304 if (font->status)
305 return font->status;
307 status = _cairo_array_allocate (&font->output, length, (void **) buffer);
308 if (unlikely (status))
309 return _cairo_truetype_font_set_error (font, status);
311 return CAIRO_STATUS_SUCCESS;
314 static void
315 cairo_truetype_font_write (cairo_truetype_font_t *font,
316 const void *data,
317 size_t length)
319 cairo_status_t status;
321 if (font->status)
322 return;
324 status = _cairo_array_append_multiple (&font->output, data, length);
325 if (unlikely (status))
326 status = _cairo_truetype_font_set_error (font, status);
329 static void
330 cairo_truetype_font_write_be16 (cairo_truetype_font_t *font,
331 uint16_t value)
333 uint16_t be16_value;
335 if (font->status)
336 return;
338 be16_value = cpu_to_be16 (value);
339 cairo_truetype_font_write (font, &be16_value, sizeof be16_value);
342 static void
343 cairo_truetype_font_write_be32 (cairo_truetype_font_t *font,
344 uint32_t value)
346 uint32_t be32_value;
348 if (font->status)
349 return;
351 be32_value = cpu_to_be32 (value);
352 cairo_truetype_font_write (font, &be32_value, sizeof be32_value);
355 static cairo_status_t
356 cairo_truetype_font_align_output (cairo_truetype_font_t *font,
357 unsigned long *aligned)
359 int length, pad;
360 unsigned char *padding;
362 length = _cairo_array_num_elements (&font->output);
363 *aligned = (length + 3) & ~3;
364 pad = *aligned - length;
366 if (pad) {
367 cairo_status_t status;
369 status = cairo_truetype_font_allocate_write_buffer (font, pad,
370 &padding);
371 if (unlikely (status))
372 return status;
374 memset (padding, 0, pad);
377 return CAIRO_STATUS_SUCCESS;
380 static cairo_status_t
381 cairo_truetype_font_check_boundary (cairo_truetype_font_t *font,
382 unsigned long boundary)
384 cairo_status_t status;
386 if (font->status)
387 return font->status;
389 if (boundary - font->last_offset > SFNT_STRING_MAX_LENGTH)
391 status = _cairo_array_append (&font->string_offsets,
392 &font->last_boundary);
393 if (unlikely (status))
394 return _cairo_truetype_font_set_error (font, status);
396 font->last_offset = font->last_boundary;
398 font->last_boundary = boundary;
400 return CAIRO_STATUS_SUCCESS;
403 typedef struct _cmap_unicode_range {
404 unsigned int start;
405 unsigned int end;
406 } cmap_unicode_range_t;
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 },
425 static cairo_status_t
426 cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font,
427 unsigned long tag)
429 int i;
430 unsigned int j;
431 int range_offset;
432 int num_ranges;
433 int entry_selector;
434 int length;
436 num_ranges = ARRAY_LENGTH (winansi_unicode_ranges);
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;
442 entry_selector = 0;
443 while ((1 << entry_selector) <= (num_ranges + 1))
444 entry_selector++;
446 entry_selector--;
448 cairo_truetype_font_write_be16 (font, 0); /* Table version */
449 cairo_truetype_font_write_be16 (font, 1); /* Num tables */
451 cairo_truetype_font_write_be16 (font, 3); /* Platform */
452 cairo_truetype_font_write_be16 (font, 1); /* Encoding */
453 cairo_truetype_font_write_be32 (font, 12); /* Offset to start of table */
455 /* Output a format 4 encoding table for the winansi encoding */
457 cairo_truetype_font_write_be16 (font, 4); /* Format */
458 cairo_truetype_font_write_be16 (font, length); /* Length */
459 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 */
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++)
465 cairo_truetype_font_write_be16 (font, winansi_unicode_ranges[i].end); /* end count[] */
466 cairo_truetype_font_write_be16 (font, 0xffff); /* end count[] */
468 cairo_truetype_font_write_be16 (font, 0); /* reserved */
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[] */
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[] */
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[] */
481 range_offset += (winansi_unicode_ranges[i].end - winansi_unicode_ranges[i].start + 1)*2 - 2;
483 cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[] */
485 for (i = 0; i < num_ranges; i++) {
486 for (j = winansi_unicode_ranges[i].start; j < winansi_unicode_ranges[i].end + 1; j++) {
487 int ch = _cairo_unicode_to_winansi (j);
488 int glyph;
490 if (ch > 0)
491 glyph = font->scaled_font_subset->latin_to_subset_glyph_index[ch];
492 else
493 glyph = 0;
494 cairo_truetype_font_write_be16 (font, glyph);
498 return font->status;
501 static cairo_status_t
502 cairo_truetype_font_write_generic_table (cairo_truetype_font_t *font,
503 unsigned long tag)
505 cairo_status_t status;
506 unsigned char *buffer;
507 unsigned long size;
509 if (font->status)
510 return font->status;
512 size = 0;
513 status = font->backend->load_truetype_table(font->scaled_font_subset->scaled_font,
514 tag, 0, NULL, &size);
515 if (unlikely (status))
516 return _cairo_truetype_font_set_error (font, status);
518 status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
519 if (unlikely (status))
520 return _cairo_truetype_font_set_error (font, status);
522 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
523 tag, 0, buffer, &size);
524 if (unlikely (status))
525 return _cairo_truetype_font_set_error (font, status);
527 return CAIRO_STATUS_SUCCESS;
530 static cairo_status_t
531 cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font,
532 unsigned char *buffer,
533 unsigned long size)
535 tt_glyph_data_t *glyph_data;
536 tt_composite_glyph_t *composite_glyph;
537 int num_args;
538 int has_more_components;
539 unsigned short flags;
540 unsigned short index;
541 cairo_status_t status;
542 unsigned char *end = buffer + size;
544 if (font->status)
545 return font->status;
547 glyph_data = (tt_glyph_data_t *) buffer;
548 if ((unsigned char *)(&glyph_data->data) >= end)
549 return CAIRO_INT_STATUS_UNSUPPORTED;
551 if ((int16_t)be16_to_cpu (glyph_data->num_contours) >= 0)
552 return CAIRO_STATUS_SUCCESS;
554 composite_glyph = &glyph_data->glyph;
555 do {
556 if ((unsigned char *)(&composite_glyph->args[1]) > end)
557 return CAIRO_INT_STATUS_UNSUPPORTED;
559 flags = be16_to_cpu (composite_glyph->flags);
560 has_more_components = flags & TT_MORE_COMPONENTS;
561 status = cairo_truetype_font_use_glyph (font, be16_to_cpu (composite_glyph->index), &index);
562 if (unlikely (status))
563 return status;
565 composite_glyph->index = cpu_to_be16 (index);
566 num_args = 1;
567 if (flags & TT_ARG_1_AND_2_ARE_WORDS)
568 num_args += 1;
570 if (flags & TT_WE_HAVE_A_SCALE)
571 num_args += 1;
572 else if (flags & TT_WE_HAVE_AN_X_AND_Y_SCALE)
573 num_args += 2;
574 else if (flags & TT_WE_HAVE_A_TWO_BY_TWO)
575 num_args += 4;
577 composite_glyph = (tt_composite_glyph_t *) &(composite_glyph->args[num_args]);
578 } while (has_more_components);
580 return CAIRO_STATUS_SUCCESS;
583 static cairo_status_t
584 cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
585 unsigned long tag)
587 unsigned long start_offset, index, size, next;
588 tt_head_t header;
589 unsigned long begin, end;
590 unsigned char *buffer;
591 unsigned int i;
592 union {
593 unsigned char *bytes;
594 uint16_t *short_offsets;
595 uint32_t *long_offsets;
596 } u;
597 cairo_status_t status;
599 if (font->status)
600 return font->status;
602 size = sizeof (tt_head_t);
603 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
604 TT_TAG_head, 0,
605 (unsigned char*) &header, &size);
606 if (unlikely (status))
607 return _cairo_truetype_font_set_error (font, status);
609 if (be16_to_cpu (header.index_to_loc_format) == 0)
610 size = sizeof (int16_t) * (font->num_glyphs_in_face + 1);
611 else
612 size = sizeof (int32_t) * (font->num_glyphs_in_face + 1);
614 u.bytes = malloc (size);
615 if (unlikely (u.bytes == NULL))
616 return _cairo_truetype_font_set_error (font, CAIRO_STATUS_NO_MEMORY);
618 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
619 TT_TAG_loca, 0, u.bytes, &size);
620 if (unlikely (status))
621 return _cairo_truetype_font_set_error (font, status);
623 start_offset = _cairo_array_num_elements (&font->output);
624 for (i = 0; i < font->base.num_glyphs; i++) {
625 index = font->glyphs[i].parent_index;
626 if (be16_to_cpu (header.index_to_loc_format) == 0) {
627 begin = be16_to_cpu (u.short_offsets[index]) * 2;
628 end = be16_to_cpu (u.short_offsets[index + 1]) * 2;
630 else {
631 begin = be32_to_cpu (u.long_offsets[index]);
632 end = be32_to_cpu (u.long_offsets[index + 1]);
635 /* quick sanity check... */
636 if (end < begin) {
637 status = CAIRO_INT_STATUS_UNSUPPORTED;
638 goto FAIL;
641 size = end - begin;
642 status = cairo_truetype_font_align_output (font, &next);
643 if (unlikely (status))
644 goto FAIL;
646 status = cairo_truetype_font_check_boundary (font, next);
647 if (unlikely (status))
648 goto FAIL;
650 font->glyphs[i].location = next - start_offset;
652 status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
653 if (unlikely (status))
654 goto FAIL;
656 if (size > 1) {
657 tt_glyph_data_t *glyph_data;
658 int num_contours;
660 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
661 TT_TAG_glyf, begin, buffer, &size);
662 if (unlikely (status))
663 goto FAIL;
665 glyph_data = (tt_glyph_data_t *) buffer;
666 num_contours = (int16_t)be16_to_cpu (glyph_data->num_contours);
667 if (num_contours < 0) {
668 status = cairo_truetype_font_remap_composite_glyph (font, buffer, size);
669 if (unlikely (status))
670 goto FAIL;
671 } else if (num_contours == 0) {
672 /* num_contours == 0 is undefined in the Opentype
673 * spec. There are some embedded fonts that have a
674 * space glyph with num_contours = 0 that fails on
675 * some printers. The spec requires glyphs without
676 * contours to have a 0 size glyph entry in the loca
677 * table.
679 * If num_contours == 0, truncate the glyph to 0 size.
681 _cairo_array_truncate (&font->output, _cairo_array_num_elements (&font->output) - size);
686 status = cairo_truetype_font_align_output (font, &next);
687 if (unlikely (status))
688 goto FAIL;
690 font->glyphs[i].location = next - start_offset;
692 status = font->status;
693 FAIL:
694 free (u.bytes);
696 return _cairo_truetype_font_set_error (font, status);
699 static cairo_status_t
700 cairo_truetype_font_write_head_table (cairo_truetype_font_t *font,
701 unsigned long tag)
703 unsigned char *buffer;
704 unsigned long size;
705 cairo_status_t status;
707 if (font->status)
708 return font->status;
710 size = 0;
711 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
712 tag, 0, NULL, &size);
713 if (unlikely (status))
714 return _cairo_truetype_font_set_error (font, status);
716 font->checksum_index = _cairo_array_num_elements (&font->output) + 8;
717 status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
718 if (unlikely (status))
719 return _cairo_truetype_font_set_error (font, status);
721 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
722 tag, 0, buffer, &size);
723 if (unlikely (status))
724 return _cairo_truetype_font_set_error (font, status);
726 /* set checkSumAdjustment to 0 for table checksum calculation */
727 *(uint32_t *)(buffer + 8) = 0;
729 return CAIRO_STATUS_SUCCESS;
732 static cairo_status_t
733 cairo_truetype_font_write_hhea_table (cairo_truetype_font_t *font, unsigned long tag)
735 tt_hhea_t *hhea;
736 unsigned long size;
737 cairo_status_t status;
739 if (font->status)
740 return font->status;
742 size = sizeof (tt_hhea_t);
743 status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &hhea);
744 if (unlikely (status))
745 return _cairo_truetype_font_set_error (font, status);
747 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
748 tag, 0, (unsigned char *) hhea, &size);
749 if (unlikely (status))
750 return _cairo_truetype_font_set_error (font, status);
752 hhea->num_hmetrics = cpu_to_be16 ((uint16_t)(font->base.num_glyphs));
754 return CAIRO_STATUS_SUCCESS;
757 static cairo_status_t
758 cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
759 unsigned long tag)
761 unsigned long size;
762 unsigned long long_entry_size;
763 unsigned long short_entry_size;
764 short *p;
765 unsigned int i;
766 tt_hhea_t hhea;
767 int num_hmetrics;
768 cairo_status_t status;
770 if (font->status)
771 return font->status;
773 size = sizeof (tt_hhea_t);
774 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
775 TT_TAG_hhea, 0,
776 (unsigned char*) &hhea, &size);
777 if (unlikely (status))
778 return _cairo_truetype_font_set_error (font, status);
780 num_hmetrics = be16_to_cpu(hhea.num_hmetrics);
782 for (i = 0; i < font->base.num_glyphs; i++) {
783 long_entry_size = 2 * sizeof (int16_t);
784 short_entry_size = sizeof (int16_t);
785 status = cairo_truetype_font_allocate_write_buffer (font,
786 long_entry_size,
787 (unsigned char **) &p);
788 if (unlikely (status))
789 return _cairo_truetype_font_set_error (font, status);
791 if (font->glyphs[i].parent_index < num_hmetrics) {
792 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
793 TT_TAG_hmtx,
794 font->glyphs[i].parent_index * long_entry_size,
795 (unsigned char *) p, &long_entry_size);
796 if (unlikely (status))
797 return _cairo_truetype_font_set_error (font, status);
799 else
801 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
802 TT_TAG_hmtx,
803 (num_hmetrics - 1) * long_entry_size,
804 (unsigned char *) p, &short_entry_size);
805 if (unlikely (status))
806 return _cairo_truetype_font_set_error (font, status);
808 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
809 TT_TAG_hmtx,
810 num_hmetrics * long_entry_size +
811 (font->glyphs[i].parent_index - num_hmetrics) * short_entry_size,
812 (unsigned char *) (p + 1), &short_entry_size);
813 if (unlikely (status))
814 return _cairo_truetype_font_set_error (font, status);
816 font->base.widths[i] = be16_to_cpu (p[0]);
819 return CAIRO_STATUS_SUCCESS;
822 static cairo_status_t
823 cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font,
824 unsigned long tag)
826 unsigned int i;
827 tt_head_t header;
828 unsigned long size;
829 cairo_status_t status;
831 if (font->status)
832 return font->status;
834 size = sizeof(tt_head_t);
835 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
836 TT_TAG_head, 0,
837 (unsigned char*) &header, &size);
838 if (unlikely (status))
839 return _cairo_truetype_font_set_error (font, status);
841 if (be16_to_cpu (header.index_to_loc_format) == 0)
843 for (i = 0; i < font->base.num_glyphs + 1; i++)
844 cairo_truetype_font_write_be16 (font, font->glyphs[i].location / 2);
845 } else {
846 for (i = 0; i < font->base.num_glyphs + 1; i++)
847 cairo_truetype_font_write_be32 (font, font->glyphs[i].location);
850 return font->status;
853 static cairo_status_t
854 cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font,
855 unsigned long tag)
857 tt_maxp_t *maxp;
858 unsigned long size;
859 cairo_status_t status;
861 if (font->status)
862 return font->status;
864 size = sizeof (tt_maxp_t);
865 status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &maxp);
866 if (unlikely (status))
867 return _cairo_truetype_font_set_error (font, status);
869 status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
870 tag, 0, (unsigned char *) maxp, &size);
871 if (unlikely (status))
872 return _cairo_truetype_font_set_error (font, status);
874 maxp->num_glyphs = cpu_to_be16 (font->base.num_glyphs);
876 return CAIRO_STATUS_SUCCESS;
879 static cairo_status_t
880 cairo_truetype_font_write_offset_table (cairo_truetype_font_t *font)
882 cairo_status_t status;
883 unsigned char *table_buffer;
884 size_t table_buffer_length;
885 unsigned short search_range, entry_selector, range_shift;
887 if (font->status)
888 return font->status;
890 search_range = 1;
891 entry_selector = 0;
892 while (search_range * 2 <= font->num_tables) {
893 search_range *= 2;
894 entry_selector++;
896 search_range *= 16;
897 range_shift = font->num_tables * 16 - search_range;
899 cairo_truetype_font_write_be32 (font, SFNT_VERSION);
900 cairo_truetype_font_write_be16 (font, font->num_tables);
901 cairo_truetype_font_write_be16 (font, search_range);
902 cairo_truetype_font_write_be16 (font, entry_selector);
903 cairo_truetype_font_write_be16 (font, range_shift);
905 /* Allocate space for the table directory. Each directory entry
906 * will be filled in by cairo_truetype_font_update_entry() after
907 * the table is written. */
908 table_buffer_length = font->num_tables * 16;
909 status = cairo_truetype_font_allocate_write_buffer (font, table_buffer_length,
910 &table_buffer);
911 if (unlikely (status))
912 return _cairo_truetype_font_set_error (font, status);
914 return CAIRO_STATUS_SUCCESS;
917 static uint32_t
918 cairo_truetype_font_calculate_checksum (cairo_truetype_font_t *font,
919 unsigned long start,
920 unsigned long end)
922 uint32_t *padded_end;
923 uint32_t *p;
924 uint32_t checksum;
925 char *data;
927 checksum = 0;
928 data = _cairo_array_index (&font->output, 0);
929 p = (uint32_t *) (data + start);
930 padded_end = (uint32_t *) (data + ((end + 3) & ~3));
931 while (p < padded_end)
932 checksum += be32_to_cpu(*p++);
934 return checksum;
937 static void
938 cairo_truetype_font_update_entry (cairo_truetype_font_t *font,
939 int index,
940 unsigned long tag,
941 unsigned long start,
942 unsigned long end)
944 uint32_t *entry;
946 entry = _cairo_array_index (&font->output, 12 + 16 * index);
947 entry[0] = cpu_to_be32 ((uint32_t)tag);
948 entry[1] = cpu_to_be32 (cairo_truetype_font_calculate_checksum (font, start, end));
949 entry[2] = cpu_to_be32 ((uint32_t)start);
950 entry[3] = cpu_to_be32 ((uint32_t)(end - start));
953 static cairo_status_t
954 cairo_truetype_font_generate (cairo_truetype_font_t *font,
955 const char **data,
956 unsigned long *length,
957 const unsigned long **string_offsets,
958 unsigned long *num_strings)
960 cairo_status_t status;
961 unsigned long start, end, next;
962 uint32_t checksum, *checksum_location;
963 int i;
965 if (font->status)
966 return font->status;
968 status = cairo_truetype_font_write_offset_table (font);
969 if (unlikely (status))
970 goto FAIL;
972 status = cairo_truetype_font_align_output (font, &start);
973 if (unlikely (status))
974 goto FAIL;
976 end = 0;
977 for (i = 0; i < font->num_tables; i++) {
978 status = font->truetype_tables[i].write (font, font->truetype_tables[i].tag);
979 if (unlikely (status))
980 goto FAIL;
982 end = _cairo_array_num_elements (&font->output);
983 status = cairo_truetype_font_align_output (font, &next);
984 if (unlikely (status))
985 goto FAIL;
987 cairo_truetype_font_update_entry (font, font->truetype_tables[i].pos,
988 font->truetype_tables[i].tag, start, end);
989 status = cairo_truetype_font_check_boundary (font, next);
990 if (unlikely (status))
991 goto FAIL;
993 start = next;
996 checksum =
997 0xb1b0afba - cairo_truetype_font_calculate_checksum (font, 0, end);
998 checksum_location = _cairo_array_index (&font->output, font->checksum_index);
999 *checksum_location = cpu_to_be32 (checksum);
1001 *data = _cairo_array_index (&font->output, 0);
1002 *length = _cairo_array_num_elements (&font->output);
1003 *num_strings = _cairo_array_num_elements (&font->string_offsets);
1004 if (*num_strings != 0)
1005 *string_offsets = _cairo_array_index (&font->string_offsets, 0);
1006 else
1007 *string_offsets = NULL;
1009 FAIL:
1010 return _cairo_truetype_font_set_error (font, status);
1013 static cairo_status_t
1014 cairo_truetype_font_use_glyph (cairo_truetype_font_t *font,
1015 unsigned short glyph,
1016 unsigned short *out)
1018 if (glyph >= font->num_glyphs_in_face)
1019 return CAIRO_INT_STATUS_UNSUPPORTED;
1021 if (font->parent_to_subset[glyph] == 0) {
1022 font->parent_to_subset[glyph] = font->base.num_glyphs;
1023 font->glyphs[font->base.num_glyphs].parent_index = glyph;
1024 font->base.num_glyphs++;
1027 *out = font->parent_to_subset[glyph];
1028 return CAIRO_STATUS_SUCCESS;
1031 static void
1032 cairo_truetype_font_add_truetype_table (cairo_truetype_font_t *font,
1033 unsigned long tag,
1034 cairo_status_t (*write) (cairo_truetype_font_t *font, unsigned long tag),
1035 int pos)
1037 font->truetype_tables[font->num_tables].tag = tag;
1038 font->truetype_tables[font->num_tables].write = write;
1039 font->truetype_tables[font->num_tables].pos = pos;
1040 font->num_tables++;
1043 /* cairo_truetype_font_create_truetype_table_list() builds the list of
1044 * truetype tables to be embedded in the subsetted font. Each call to
1045 * cairo_truetype_font_add_truetype_table() adds a table, the callback
1046 * for generating the table, and the position in the table directory
1047 * to the truetype_tables array.
1049 * As we write out the glyf table we remap composite glyphs.
1050 * Remapping composite glyphs will reference the sub glyphs the
1051 * composite glyph is made up of. The "glyf" table callback needs to
1052 * be called first so we have all the glyphs in the subset before
1053 * going further.
1055 * The order in which tables are added to the truetype_table array
1056 * using cairo_truetype_font_add_truetype_table() specifies the order
1057 * in which the callback functions will be called.
1059 * The tables in the table directory must be listed in alphabetical
1060 * order. The "cvt", "fpgm", and "prep" are optional tables. They
1061 * will only be embedded in the subset if they exist in the source
1062 * font. "cmap" is only embedded for latin fonts. The pos parameter of
1063 * cairo_truetype_font_add_truetype_table() specifies the position of
1064 * the table in the table directory.
1066 static void
1067 cairo_truetype_font_create_truetype_table_list (cairo_truetype_font_t *font)
1069 cairo_bool_t has_cvt = FALSE;
1070 cairo_bool_t has_fpgm = FALSE;
1071 cairo_bool_t has_prep = FALSE;
1072 unsigned long size;
1073 int pos;
1075 size = 0;
1076 if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
1077 TT_TAG_cvt, 0, NULL,
1078 &size) == CAIRO_INT_STATUS_SUCCESS)
1079 has_cvt = TRUE;
1081 size = 0;
1082 if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
1083 TT_TAG_fpgm, 0, NULL,
1084 &size) == CAIRO_INT_STATUS_SUCCESS)
1085 has_fpgm = TRUE;
1087 size = 0;
1088 if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
1089 TT_TAG_prep, 0, NULL,
1090 &size) == CAIRO_INT_STATUS_SUCCESS)
1091 has_prep = TRUE;
1093 font->num_tables = 0;
1094 pos = 0;
1095 if (font->is_pdf && font->scaled_font_subset->is_latin)
1096 pos++;
1097 if (has_cvt)
1098 pos++;
1099 if (has_fpgm)
1100 pos++;
1101 cairo_truetype_font_add_truetype_table (font, TT_TAG_glyf, cairo_truetype_font_write_glyf_table, pos);
1103 pos = 0;
1104 if (font->is_pdf && font->scaled_font_subset->is_latin)
1105 cairo_truetype_font_add_truetype_table (font, TT_TAG_cmap, cairo_truetype_font_write_cmap_table, pos++);
1106 if (has_cvt)
1107 cairo_truetype_font_add_truetype_table (font, TT_TAG_cvt, cairo_truetype_font_write_generic_table, pos++);
1108 if (has_fpgm)
1109 cairo_truetype_font_add_truetype_table (font, TT_TAG_fpgm, cairo_truetype_font_write_generic_table, pos++);
1110 pos++;
1111 cairo_truetype_font_add_truetype_table (font, TT_TAG_head, cairo_truetype_font_write_head_table, pos++);
1112 cairo_truetype_font_add_truetype_table (font, TT_TAG_hhea, cairo_truetype_font_write_hhea_table, pos++);
1113 cairo_truetype_font_add_truetype_table (font, TT_TAG_hmtx, cairo_truetype_font_write_hmtx_table, pos++);
1114 cairo_truetype_font_add_truetype_table (font, TT_TAG_loca, cairo_truetype_font_write_loca_table, pos++);
1115 cairo_truetype_font_add_truetype_table (font, TT_TAG_maxp, cairo_truetype_font_write_maxp_table, pos++);
1116 if (has_prep)
1117 cairo_truetype_font_add_truetype_table (font, TT_TAG_prep, cairo_truetype_font_write_generic_table, pos);
1120 static cairo_status_t
1121 cairo_truetype_subset_init_internal (cairo_truetype_subset_t *truetype_subset,
1122 cairo_scaled_font_subset_t *font_subset,
1123 cairo_bool_t is_pdf)
1125 cairo_truetype_font_t *font = NULL;
1126 cairo_status_t status;
1127 const char *data = NULL; /* squelch bogus compiler warning */
1128 unsigned long length = 0; /* squelch bogus compiler warning */
1129 unsigned long offsets_length;
1130 unsigned int i;
1131 const unsigned long *string_offsets = NULL;
1132 unsigned long num_strings = 0;
1134 status = _cairo_truetype_font_create (font_subset, is_pdf, &font);
1135 if (unlikely (status))
1136 return status;
1138 for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
1139 unsigned short parent_glyph = font->scaled_font_subset->glyphs[i];
1140 status = cairo_truetype_font_use_glyph (font, parent_glyph, &parent_glyph);
1141 if (unlikely (status))
1142 goto fail1;
1145 cairo_truetype_font_create_truetype_table_list (font);
1146 status = cairo_truetype_font_generate (font, &data, &length,
1147 &string_offsets, &num_strings);
1148 if (unlikely (status))
1149 goto fail1;
1151 truetype_subset->ps_name = strdup (font->base.ps_name);
1152 if (unlikely (truetype_subset->ps_name == NULL)) {
1153 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1154 goto fail1;
1157 if (font->base.font_name != NULL) {
1158 truetype_subset->family_name_utf8 = strdup (font->base.font_name);
1159 if (unlikely (truetype_subset->family_name_utf8 == NULL)) {
1160 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1161 goto fail2;
1163 } else {
1164 truetype_subset->family_name_utf8 = NULL;
1167 /* The widths array returned must contain only widths for the
1168 * glyphs in font_subset. Any subglyphs appended after
1169 * font_subset->num_glyphs are omitted. */
1170 truetype_subset->widths = calloc (sizeof (double),
1171 font->scaled_font_subset->num_glyphs);
1172 if (unlikely (truetype_subset->widths == NULL)) {
1173 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1174 goto fail3;
1176 for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
1177 truetype_subset->widths[i] = (double)font->base.widths[i]/font->base.units_per_em;
1179 truetype_subset->x_min = (double)font->base.x_min/font->base.units_per_em;
1180 truetype_subset->y_min = (double)font->base.y_min/font->base.units_per_em;
1181 truetype_subset->x_max = (double)font->base.x_max/font->base.units_per_em;
1182 truetype_subset->y_max = (double)font->base.y_max/font->base.units_per_em;
1183 truetype_subset->ascent = (double)font->base.ascent/font->base.units_per_em;
1184 truetype_subset->descent = (double)font->base.descent/font->base.units_per_em;
1186 if (length) {
1187 truetype_subset->data = malloc (length);
1188 if (unlikely (truetype_subset->data == NULL)) {
1189 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1190 goto fail4;
1193 memcpy (truetype_subset->data, data, length);
1194 } else
1195 truetype_subset->data = NULL;
1196 truetype_subset->data_length = length;
1198 if (num_strings) {
1199 offsets_length = num_strings * sizeof (unsigned long);
1200 truetype_subset->string_offsets = malloc (offsets_length);
1201 if (unlikely (truetype_subset->string_offsets == NULL)) {
1202 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1203 goto fail5;
1206 memcpy (truetype_subset->string_offsets, string_offsets, offsets_length);
1207 truetype_subset->num_string_offsets = num_strings;
1208 } else {
1209 truetype_subset->string_offsets = NULL;
1210 truetype_subset->num_string_offsets = 0;
1213 cairo_truetype_font_destroy (font);
1215 return CAIRO_STATUS_SUCCESS;
1217 fail5:
1218 free (truetype_subset->data);
1219 fail4:
1220 free (truetype_subset->widths);
1221 fail3:
1222 free (truetype_subset->family_name_utf8);
1223 fail2:
1224 free (truetype_subset->ps_name);
1225 fail1:
1226 cairo_truetype_font_destroy (font);
1228 return status;
1231 cairo_status_t
1232 _cairo_truetype_subset_init_ps (cairo_truetype_subset_t *truetype_subset,
1233 cairo_scaled_font_subset_t *font_subset)
1235 return cairo_truetype_subset_init_internal (truetype_subset, font_subset, FALSE);
1238 cairo_status_t
1239 _cairo_truetype_subset_init_pdf (cairo_truetype_subset_t *truetype_subset,
1240 cairo_scaled_font_subset_t *font_subset)
1242 return cairo_truetype_subset_init_internal (truetype_subset, font_subset, TRUE);
1245 void
1246 _cairo_truetype_subset_fini (cairo_truetype_subset_t *subset)
1248 free (subset->ps_name);
1249 free (subset->family_name_utf8);
1250 free (subset->widths);
1251 free (subset->data);
1252 free (subset->string_offsets);
1255 static cairo_int_status_t
1256 _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
1257 unsigned long table_offset,
1258 unsigned long index,
1259 uint32_t *ucs4)
1261 cairo_status_t status;
1262 const cairo_scaled_font_backend_t *backend;
1263 tt_segment_map_t *map;
1264 char buf[4];
1265 unsigned int num_segments, i;
1266 unsigned long size;
1267 uint16_t *start_code;
1268 uint16_t *end_code;
1269 uint16_t *delta;
1270 uint16_t *range_offset;
1271 uint16_t c;
1273 backend = scaled_font->backend;
1274 size = 4;
1275 status = backend->load_truetype_table (scaled_font,
1276 TT_TAG_cmap, table_offset,
1277 (unsigned char *) &buf,
1278 &size);
1279 if (unlikely (status))
1280 return status;
1282 /* All table formats have the same first two words */
1283 map = (tt_segment_map_t *) buf;
1284 if (be16_to_cpu (map->format) != 4)
1285 return CAIRO_INT_STATUS_UNSUPPORTED;
1287 size = be16_to_cpu (map->length);
1288 map = malloc (size);
1289 if (unlikely (map == NULL))
1290 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1292 status = backend->load_truetype_table (scaled_font,
1293 TT_TAG_cmap, table_offset,
1294 (unsigned char *) map,
1295 &size);
1296 if (unlikely (status))
1297 goto fail;
1299 num_segments = be16_to_cpu (map->segCountX2)/2;
1301 /* A Format 4 cmap contains 8 uint16_t numbers and 4 arrays of
1302 * uint16_t each num_segments long. */
1303 if (size < (8 + 4*num_segments)*sizeof(uint16_t))
1304 return CAIRO_INT_STATUS_UNSUPPORTED;
1306 end_code = map->endCount;
1307 start_code = &(end_code[num_segments + 1]);
1308 delta = &(start_code[num_segments]);
1309 range_offset = &(delta[num_segments]);
1311 /* search for glyph in segments with rangeOffset=0 */
1312 for (i = 0; i < num_segments; i++) {
1313 c = index - be16_to_cpu (delta[i]);
1314 if (range_offset[i] == 0 &&
1315 c >= be16_to_cpu (start_code[i]) &&
1316 c <= be16_to_cpu (end_code[i]))
1318 *ucs4 = c;
1319 goto found;
1323 /* search for glyph in segments with rangeOffset=1 */
1324 for (i = 0; i < num_segments; i++) {
1325 if (range_offset[i] != 0) {
1326 uint16_t *glyph_ids = &range_offset[i] + be16_to_cpu (range_offset[i])/2;
1327 int range_size = be16_to_cpu (end_code[i]) - be16_to_cpu (start_code[i]) + 1;
1328 uint16_t g_id_be = cpu_to_be16 (index);
1329 int j;
1331 if (range_size > 0) {
1332 if ((char*)glyph_ids + 2*range_size > (char*)map + size)
1333 return CAIRO_INT_STATUS_UNSUPPORTED;
1335 for (j = 0; j < range_size; j++) {
1336 if (glyph_ids[j] == g_id_be) {
1337 *ucs4 = be16_to_cpu (start_code[i]) + j;
1338 goto found;
1345 /* glyph not found */
1346 *ucs4 = -1;
1348 found:
1349 status = CAIRO_STATUS_SUCCESS;
1351 fail:
1352 free (map);
1354 return status;
1357 cairo_int_status_t
1358 _cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
1359 unsigned long index,
1360 uint32_t *ucs4)
1362 cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
1363 const cairo_scaled_font_backend_t *backend;
1364 tt_cmap_t *cmap;
1365 char buf[4];
1366 int num_tables, i;
1367 unsigned long size;
1369 backend = scaled_font->backend;
1370 if (!backend->load_truetype_table)
1371 return CAIRO_INT_STATUS_UNSUPPORTED;
1373 size = 4;
1374 status = backend->load_truetype_table (scaled_font,
1375 TT_TAG_cmap, 0,
1376 (unsigned char *) &buf,
1377 &size);
1378 if (unlikely (status))
1379 return status;
1381 cmap = (tt_cmap_t *) buf;
1382 num_tables = be16_to_cpu (cmap->num_tables);
1383 size = 4 + num_tables*sizeof(tt_cmap_index_t);
1384 cmap = _cairo_malloc_ab_plus_c (num_tables, sizeof (tt_cmap_index_t), 4);
1385 if (unlikely (cmap == NULL))
1386 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1388 status = backend->load_truetype_table (scaled_font,
1389 TT_TAG_cmap, 0,
1390 (unsigned char *) cmap,
1391 &size);
1392 if (unlikely (status))
1393 goto cleanup;
1395 /* Find a table with Unicode mapping */
1396 for (i = 0; i < num_tables; i++) {
1397 if (be16_to_cpu (cmap->index[i].platform) == 3 &&
1398 be16_to_cpu (cmap->index[i].encoding) == 1) {
1399 status = _cairo_truetype_reverse_cmap (scaled_font,
1400 be32_to_cpu (cmap->index[i].offset),
1401 index,
1402 ucs4);
1403 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1404 break;
1408 cleanup:
1409 free (cmap);
1411 return status;
1414 static cairo_status_t
1415 find_name (tt_name_t *name, int name_id, int platform, int encoding, int language, char **str_out)
1417 tt_name_record_t *record;
1418 int i, len;
1419 char *str;
1420 char *p;
1421 cairo_bool_t has_tag;
1422 cairo_status_t status;
1424 str = NULL;
1425 for (i = 0; i < be16_to_cpu (name->num_records); i++) {
1426 record = &(name->records[i]);
1427 if (be16_to_cpu (record->name) == name_id &&
1428 be16_to_cpu (record->platform) == platform &&
1429 be16_to_cpu (record->encoding) == encoding &&
1430 (language == -1 || be16_to_cpu (record->language) == language)) {
1432 str = malloc (be16_to_cpu (record->length) + 1);
1433 if (str == NULL)
1434 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1436 len = be16_to_cpu (record->length);
1437 memcpy (str,
1438 ((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset),
1439 len);
1440 str[be16_to_cpu (record->length)] = 0;
1441 break;
1444 if (str == NULL) {
1445 *str_out = NULL;
1446 return CAIRO_STATUS_SUCCESS;
1449 if (platform == 3) { /* Win platform, unicode encoding */
1450 /* convert to utf8 */
1451 int size = 0;
1452 char *utf8;
1453 uint16_t *u = (uint16_t *) str;
1454 int u_len = len/2;
1456 for (i = 0; i < u_len; i++)
1457 size += _cairo_ucs4_to_utf8 (be16_to_cpu(u[i]), NULL);
1459 utf8 = malloc (size + 1);
1460 if (utf8 == NULL) {
1461 status =_cairo_error (CAIRO_STATUS_NO_MEMORY);
1462 goto fail;
1464 p = utf8;
1465 for (i = 0; i < u_len; i++)
1466 p += _cairo_ucs4_to_utf8 (be16_to_cpu(u[i]), p);
1467 *p = 0;
1468 free (str);
1469 str = utf8;
1470 } else if (platform == 1) { /* Mac platform, Mac Roman encoding */
1471 /* Replace characters above 127 with underscores. We could use
1472 * a lookup table to convert to unicode but since most fonts
1473 * include a unicode name this is just a rarely used fallback. */
1474 for (i = 0; i < len; i++) {
1475 if ((unsigned char)str[i] > 127)
1476 str[i] = '_';
1480 /* If font name is prefixed with a PDF subset tag, strip it off. */
1481 p = str;
1482 len = strlen (str);
1483 has_tag = FALSE;
1484 if (len > 7 && p[6] == '+') {
1485 has_tag = TRUE;
1486 for (i = 0; i < 6; i++) {
1487 if (p[i] < 'A' || p[i] > 'Z') {
1488 has_tag = FALSE;
1489 break;
1493 if (has_tag) {
1494 p = malloc (len - 6);
1495 if (unlikely (p == NULL)) {
1496 status =_cairo_error (CAIRO_STATUS_NO_MEMORY);
1497 goto fail;
1499 memcpy (p, str + 7, len - 7);
1500 p[len-7] = 0;
1501 free (str);
1502 str = p;
1505 *str_out = str;
1507 return CAIRO_STATUS_SUCCESS;
1509 fail:
1510 free (str);
1512 return status;
1515 cairo_int_status_t
1516 _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font,
1517 char **ps_name_out,
1518 char **font_name_out)
1520 cairo_status_t status;
1521 const cairo_scaled_font_backend_t *backend;
1522 tt_name_t *name;
1523 unsigned long size;
1524 char *ps_name = NULL;
1525 char *family_name = NULL;
1527 backend = scaled_font->backend;
1528 if (!backend->load_truetype_table)
1529 return CAIRO_INT_STATUS_UNSUPPORTED;
1531 size = 0;
1532 status = backend->load_truetype_table (scaled_font,
1533 TT_TAG_name, 0,
1534 NULL,
1535 &size);
1536 if (status)
1537 return status;
1539 name = malloc (size);
1540 if (name == NULL)
1541 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1543 status = backend->load_truetype_table (scaled_font,
1544 TT_TAG_name, 0,
1545 (unsigned char *) name,
1546 &size);
1547 if (status)
1548 goto fail;
1550 /* Find PS Name (name_id = 6). OT spec says PS name must be one of
1551 * the following two encodings */
1552 status = find_name (name, 6, 3, 1, 0x409, &ps_name); /* win, unicode, english-us */
1553 if (unlikely(status))
1554 goto fail;
1556 if (!ps_name) {
1557 status = find_name (name, 6, 1, 0, 0, &ps_name); /* mac, roman, english */
1558 if (unlikely(status))
1559 goto fail;
1562 /* Find Family name (name_id = 1) */
1563 status = find_name (name, 1, 3, 1, 0x409, &family_name); /* win, unicode, english-us */
1564 if (unlikely(status))
1565 goto fail;
1567 if (!family_name) {
1568 status = find_name (name, 1, 3, 0, 0x409, &family_name); /* win, symbol, english-us */
1569 if (unlikely(status))
1570 goto fail;
1573 if (!family_name) {
1574 status = find_name (name, 1, 1, 0, 0, &family_name); /* mac, roman, english */
1575 if (unlikely(status))
1576 goto fail;
1579 if (!family_name) {
1580 status = find_name (name, 1, 3, 1, -1, &family_name); /* win, unicode, any language */
1581 if (unlikely(status))
1582 goto fail;
1585 status = _cairo_escape_ps_name (&ps_name);
1586 if (unlikely(status))
1587 goto fail;
1589 free (name);
1591 *ps_name_out = ps_name;
1592 *font_name_out = family_name;
1594 return CAIRO_STATUS_SUCCESS;
1596 fail:
1597 free (name);
1598 free (ps_name);
1599 free (family_name);
1600 *ps_name_out = NULL;
1601 *font_name_out = NULL;
1603 return status;
1606 cairo_int_status_t
1607 _cairo_truetype_get_style (cairo_scaled_font_t *scaled_font,
1608 int *weight,
1609 cairo_bool_t *bold,
1610 cairo_bool_t *italic)
1612 cairo_status_t status;
1613 const cairo_scaled_font_backend_t *backend;
1614 tt_os2_t os2;
1615 unsigned long size;
1616 uint16_t selection;
1618 backend = scaled_font->backend;
1619 if (!backend->load_truetype_table)
1620 return CAIRO_INT_STATUS_UNSUPPORTED;
1622 size = 0;
1623 status = backend->load_truetype_table (scaled_font,
1624 TT_TAG_OS2, 0,
1625 NULL,
1626 &size);
1627 if (status)
1628 return status;
1630 if (size < sizeof(os2))
1631 return CAIRO_INT_STATUS_UNSUPPORTED;
1633 size = sizeof (os2);
1634 status = backend->load_truetype_table (scaled_font,
1635 TT_TAG_OS2, 0,
1636 (unsigned char *) &os2,
1637 &size);
1638 if (status)
1639 return status;
1641 *weight = be16_to_cpu (os2.usWeightClass);
1642 selection = be16_to_cpu (os2.fsSelection);
1643 *bold = (selection & TT_FS_SELECTION_BOLD) ? TRUE : FALSE;
1644 *italic = (selection & TT_FS_SELECTION_ITALIC) ? TRUE : FALSE;
1646 return CAIRO_STATUS_SUCCESS;
1649 #endif /* CAIRO_HAS_FONT_SUBSET */