comparison mupdf-source/source/fitz/font.c @ 3:2c135c81b16c

MERGE: upstream PyMuPDF 1.26.4 with MuPDF 1.26.7
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:44:09 +0200
parents b50eed0cc0ef
children
comparison
equal deleted inserted replaced
0:6015a75abc2d 3:2c135c81b16c
1 // Copyright (C) 2004-2025 Artifex Software, Inc.
2 //
3 // This file is part of MuPDF.
4 //
5 // MuPDF is free software: you can redistribute it and/or modify it under the
6 // terms of the GNU Affero General Public License as published by the Free
7 // Software Foundation, either version 3 of the License, or (at your option)
8 // any later version.
9 //
10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU Affero General Public License
16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17 //
18 // Alternative licensing terms are available from the licensor.
19 // For commercial licensing, see <https://www.artifex.com/> or contact
20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21 // CA 94129, USA, for further information.
22
23 #include "mupdf/fitz.h"
24 #include "mupdf/ucdn.h"
25
26 #include "draw-imp.h"
27 #include "color-imp.h"
28 #include "glyph-imp.h"
29 #include "pixmap-imp.h"
30
31 #include <ft2build.h>
32
33 #include <assert.h>
34
35 #include FT_FREETYPE_H
36 #include FT_ADVANCES_H
37 #include FT_MODULE_H
38 #include FT_STROKER_H
39 #include FT_SYSTEM_H
40 #include FT_TRUETYPE_TABLES_H
41 #include FT_TRUETYPE_TAGS_H
42
43 #ifndef FT_SFNT_OS2
44 #define FT_SFNT_OS2 ft_sfnt_os2
45 #endif
46
47 /* 20 degrees */
48 #define SHEAR 0.36397f
49
50 int ft_char_index(void *face, int cid)
51 {
52 int gid = FT_Get_Char_Index(face, cid);
53 if (gid == 0)
54 gid = FT_Get_Char_Index(face, 0xf000 + cid);
55
56 /* some chinese fonts only ship the similarly looking 0x2026 */
57 if (gid == 0 && cid == 0x22ef)
58 gid = FT_Get_Char_Index(face, 0x2026);
59
60 return gid;
61 }
62
63 int ft_name_index(void *face, const char *name)
64 {
65 int code = FT_Get_Name_Index(face, (char*)name);
66 if (code == 0)
67 {
68 int unicode = fz_unicode_from_glyph_name(name);
69 if (unicode)
70 {
71 const char **dupnames = fz_duplicate_glyph_names_from_unicode(unicode);
72 while (*dupnames)
73 {
74 code = FT_Get_Name_Index(face, (char*)*dupnames);
75 if (code)
76 break;
77 dupnames++;
78 }
79 if (code == 0)
80 {
81 char buf[12];
82 sprintf(buf, "uni%04X", unicode);
83 code = FT_Get_Name_Index(face, buf);
84 }
85 }
86 }
87 return code;
88 }
89
90 static void fz_drop_freetype(fz_context *ctx);
91
92 static fz_font *
93 fz_new_font(fz_context *ctx, const char *name, int use_glyph_bbox, int glyph_count)
94 {
95 fz_font *font;
96
97 font = fz_malloc_struct(ctx, fz_font);
98 font->refs = 1;
99
100 if (name)
101 fz_strlcpy(font->name, name, sizeof font->name);
102 else
103 fz_strlcpy(font->name, "(null)", sizeof font->name);
104
105 font->ft_face = NULL;
106 font->flags.ft_substitute = 0;
107 font->flags.fake_bold = 0;
108 font->flags.fake_italic = 0;
109 font->flags.has_opentype = 0;
110 font->flags.embed = 0;
111 font->flags.never_embed = 0;
112
113 font->t3matrix = fz_identity;
114 font->t3resources = NULL;
115 font->t3procs = NULL;
116 font->t3lists = NULL;
117 font->t3widths = NULL;
118 font->t3flags = NULL;
119 font->t3doc = NULL;
120 font->t3run = NULL;
121
122 font->bbox.x0 = 0;
123 font->bbox.y0 = 0;
124 font->bbox.x1 = 1;
125 font->bbox.y1 = 1;
126
127 font->glyph_count = glyph_count;
128
129 font->bbox_table = NULL;
130 font->use_glyph_bbox = use_glyph_bbox;
131
132 font->width_count = 0;
133 font->width_table = NULL;
134
135 font->subfont = 0;
136
137 return font;
138 }
139
140 fz_font *
141 fz_keep_font(fz_context *ctx, fz_font *font)
142 {
143 return fz_keep_imp(ctx, font, &font->refs);
144 }
145
146 static void
147 free_resources(fz_context *ctx, fz_font *font)
148 {
149 int i;
150
151 if (font->t3resources)
152 {
153 font->t3freeres(ctx, font->t3doc, font->t3resources);
154 font->t3resources = NULL;
155 }
156
157 if (font->t3procs)
158 {
159 for (i = 0; i < 256; i++)
160 fz_drop_buffer(ctx, font->t3procs[i]);
161 }
162 fz_free(ctx, font->t3procs);
163 font->t3procs = NULL;
164 }
165
166 /*
167 Internal function to remove the
168 references to a document held by a Type3 font. This is
169 called during document destruction to ensure that Type3
170 fonts clean up properly.
171
172 Without this call being made, Type3 fonts can be left
173 holding pdf_obj references for the sake of interpretation
174 operations that will never come. These references
175 cannot be freed after the document, hence this function
176 forces them to be freed earlier in the process.
177
178 font: The font to decouple.
179
180 t3doc: The document to which the font may refer.
181 */
182 void fz_decouple_type3_font(fz_context *ctx, fz_font *font, void *t3doc)
183 {
184 if (!font || !t3doc || font->t3doc == NULL)
185 return;
186
187 if (font->t3doc != t3doc)
188 fz_throw(ctx, FZ_ERROR_ARGUMENT, "can't decouple type3 font from a different doc");
189
190 font->t3doc = NULL;
191 free_resources(ctx, font);
192 }
193
194 void
195 fz_drop_font(fz_context *ctx, fz_font *font)
196 {
197 int fterr;
198 int i;
199
200 if (!fz_drop_imp(ctx, font, &font->refs))
201 return;
202
203 free_resources(ctx, font);
204 if (font->t3lists)
205 for (i = 0; i < 256; i++)
206 fz_drop_display_list(ctx, font->t3lists[i]);
207 fz_free(ctx, font->t3procs);
208 fz_free(ctx, font->t3lists);
209 fz_free(ctx, font->t3widths);
210 fz_free(ctx, font->t3flags);
211
212 if (font->ft_face)
213 {
214 fz_ft_lock(ctx);
215 fterr = FT_Done_Face((FT_Face)font->ft_face);
216 fz_ft_unlock(ctx);
217 if (fterr)
218 fz_warn(ctx, "FT_Done_Face(%s): %s", font->name, ft_error_string(fterr));
219 fz_drop_freetype(ctx);
220 }
221
222 for (i = 0; i < 256; ++i)
223 fz_free(ctx, font->encoding_cache[i]);
224
225 fz_drop_buffer(ctx, font->buffer);
226 if (font->bbox_table)
227 {
228 int n = (font->glyph_count+255)/256;
229 for (i = 0; i < n; i++)
230 fz_free(ctx, font->bbox_table[i]);
231 fz_free(ctx, font->bbox_table);
232 }
233 fz_free(ctx, font->width_table);
234 if (font->advance_cache)
235 {
236 int n = (font->glyph_count+255)/256;
237 for (i = 0; i < n; i++)
238 fz_free(ctx, font->advance_cache[i]);
239 fz_free(ctx, font->advance_cache);
240 }
241 if (font->shaper_data.destroy && font->shaper_data.shaper_handle)
242 {
243 font->shaper_data.destroy(ctx, font->shaper_data.shaper_handle);
244 }
245 fz_free(ctx, font);
246 }
247
248 void
249 fz_set_font_bbox(fz_context *ctx, fz_font *font, float xmin, float ymin, float xmax, float ymax)
250 {
251 if (xmin >= xmax || ymin >= ymax)
252 {
253 /* Invalid bbox supplied. */
254 if (font->t3procs)
255 {
256 /* For type3 fonts we use the union of all the glyphs' bboxes. */
257 font->bbox = fz_empty_rect;
258 }
259 else
260 {
261 /* For other fonts it would be prohibitively slow to measure the true one, so make one up. */
262 font->bbox = fz_unit_rect;
263 }
264 font->flags.invalid_bbox = 1;
265 }
266 else
267 {
268 font->bbox.x0 = xmin;
269 font->bbox.y0 = ymin;
270 font->bbox.x1 = xmax;
271 font->bbox.y1 = ymax;
272 }
273 }
274
275 float fz_font_ascender(fz_context *ctx, fz_font *font)
276 {
277 return font->ascender;
278 }
279
280 float fz_font_descender(fz_context *ctx, fz_font *font)
281 {
282 return font->descender;
283 }
284
285 /*
286 * Freetype hooks
287 */
288
289 struct fz_font_context
290 {
291 int ctx_refs;
292 FT_Library ftlib;
293 struct FT_MemoryRec_ ftmemory;
294 int ftlib_refs;
295 fz_load_system_font_fn *load_font;
296 fz_load_system_cjk_font_fn *load_cjk_font;
297 fz_load_system_fallback_font_fn *load_fallback_font;
298
299 /* Cached fallback fonts */
300 fz_font *base14[14];
301 fz_font *cjk[4];
302 struct { fz_font *serif, *sans; } fallback[256];
303 fz_font *symbol1, *symbol2, *math, *music, *boxes;
304 fz_font *emoji;
305 };
306
307 #undef __FTERRORS_H__
308 #define FT_ERRORDEF(e, v, s) { (e), (s) },
309 #define FT_ERROR_START_LIST
310 #define FT_ERROR_END_LIST { 0, NULL }
311
312 struct ft_error
313 {
314 int err;
315 char *str;
316 };
317
318 static void *ft_alloc(FT_Memory memory, long size)
319 {
320 fz_context *ctx = (fz_context *) memory->user;
321 return Memento_label(fz_malloc_no_throw(ctx, size), "ft_alloc");
322 }
323
324 static void ft_free(FT_Memory memory, void *block)
325 {
326 fz_context *ctx = (fz_context *) memory->user;
327 fz_free(ctx, block);
328 }
329
330 static void *ft_realloc(FT_Memory memory, long cur_size, long new_size, void *block)
331 {
332 fz_context *ctx = (fz_context *) memory->user;
333 void *newblock = NULL;
334 if (new_size == 0)
335 {
336 fz_free(ctx, block);
337 return newblock;
338 }
339 if (block == NULL)
340 return ft_alloc(memory, new_size);
341 return fz_realloc_no_throw(ctx, block, new_size);
342 }
343
344 void
345 fz_ft_lock(fz_context *ctx)
346 {
347 fz_lock(ctx, FZ_LOCK_FREETYPE);
348 fz_lock(ctx, FZ_LOCK_ALLOC);
349 assert(ctx->font->ftmemory.user == NULL);
350 ctx->font->ftmemory.user = ctx;
351 fz_unlock(ctx, FZ_LOCK_ALLOC);
352 }
353
354 void
355 fz_ft_unlock(fz_context *ctx)
356 {
357 fz_lock(ctx, FZ_LOCK_ALLOC);
358 ctx->font->ftmemory.user = NULL;
359 fz_unlock(ctx, FZ_LOCK_ALLOC);
360 fz_unlock(ctx, FZ_LOCK_FREETYPE);
361 }
362
363 int
364 fz_ft_lock_held(fz_context *ctx)
365 {
366 /* If this thread has locked the freetype lock already, then
367 * the stored context will be this one. */
368 return (ctx->font->ftmemory.user == ctx);
369 }
370
371 void fz_new_font_context(fz_context *ctx)
372 {
373 ctx->font = fz_malloc_struct(ctx, fz_font_context);
374 ctx->font->ctx_refs = 1;
375 ctx->font->ftlib = NULL;
376 ctx->font->ftlib_refs = 0;
377 ctx->font->load_font = NULL;
378 ctx->font->ftmemory.user = NULL;
379 ctx->font->ftmemory.alloc = ft_alloc;
380 ctx->font->ftmemory.free = ft_free;
381 ctx->font->ftmemory.realloc = ft_realloc;
382 }
383
384 fz_font_context *
385 fz_keep_font_context(fz_context *ctx)
386 {
387 if (!ctx)
388 return NULL;
389 return fz_keep_imp(ctx, ctx->font, &ctx->font->ctx_refs);
390 }
391
392 void fz_drop_font_context(fz_context *ctx)
393 {
394 if (!ctx)
395 return;
396
397 if (fz_drop_imp(ctx, ctx->font, &ctx->font->ctx_refs))
398 {
399 int i;
400
401 for (i = 0; i < (int)nelem(ctx->font->base14); ++i)
402 fz_drop_font(ctx, ctx->font->base14[i]);
403 for (i = 0; i < (int)nelem(ctx->font->cjk); ++i)
404 fz_drop_font(ctx, ctx->font->cjk[i]);
405 for (i = 0; i < (int)nelem(ctx->font->fallback); ++i)
406 {
407 fz_drop_font(ctx, ctx->font->fallback[i].serif);
408 fz_drop_font(ctx, ctx->font->fallback[i].sans);
409 }
410 fz_drop_font(ctx, ctx->font->symbol1);
411 fz_drop_font(ctx, ctx->font->symbol2);
412 fz_drop_font(ctx, ctx->font->math);
413 fz_drop_font(ctx, ctx->font->music);
414 fz_drop_font(ctx, ctx->font->emoji);
415 fz_drop_font(ctx, ctx->font->boxes);
416 fz_free(ctx, ctx->font);
417 ctx->font = NULL;
418 }
419 }
420
421 void fz_install_load_system_font_funcs(fz_context *ctx,
422 fz_load_system_font_fn *f,
423 fz_load_system_cjk_font_fn *f_cjk,
424 fz_load_system_fallback_font_fn *f_back)
425 {
426 ctx->font->load_font = f;
427 ctx->font->load_cjk_font = f_cjk;
428 ctx->font->load_fallback_font = f_back;
429 }
430
431 /* fz_load_*_font returns NULL if no font could be loaded (also on error) */
432 fz_font *fz_load_system_font(fz_context *ctx, const char *name, int bold, int italic, int needs_exact_metrics)
433 {
434 fz_font *font = NULL;
435
436 if (ctx->font->load_font)
437 {
438 fz_try(ctx)
439 font = ctx->font->load_font(ctx, name, bold, italic, needs_exact_metrics);
440 fz_catch(ctx)
441 {
442 fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
443 fz_rethrow_if(ctx, FZ_ERROR_SYSTEM);
444 fz_report_error(ctx);
445 font = NULL;
446 }
447 }
448
449 return font;
450 }
451
452 fz_font *fz_load_system_cjk_font(fz_context *ctx, const char *name, int ros, int serif)
453 {
454 fz_font *font = NULL;
455
456 if (ctx->font->load_cjk_font)
457 {
458 fz_try(ctx)
459 font = ctx->font->load_cjk_font(ctx, name, ros, serif);
460 fz_catch(ctx)
461 {
462 fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
463 fz_rethrow_if(ctx, FZ_ERROR_SYSTEM);
464 fz_report_error(ctx);
465 font = NULL;
466 }
467 }
468
469 return font;
470 }
471
472 fz_font *fz_load_system_fallback_font(fz_context *ctx, int script, int language, int serif, int bold, int italic)
473 {
474 fz_font *font = NULL;
475
476 if (ctx->font->load_fallback_font)
477 {
478 fz_try(ctx)
479 font = ctx->font->load_fallback_font(ctx, script, language, serif, bold, italic);
480 fz_catch(ctx)
481 {
482 fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
483 fz_rethrow_if(ctx, FZ_ERROR_SYSTEM);
484 fz_report_error(ctx);
485 font = NULL;
486 }
487 }
488
489 return font;
490 }
491
492 fz_font *fz_load_fallback_font(fz_context *ctx, int script, int language, int serif, int bold, int italic)
493 {
494 fz_font **fontp;
495 const unsigned char *data;
496 int ordering = FZ_ADOBE_JAPAN;
497 int index;
498 int subfont;
499 int size;
500
501 if (script < 0 || script >= (int)nelem(ctx->font->fallback))
502 return NULL;
503
504 /* TODO: bold and italic */
505
506 index = script;
507 if (script == UCDN_SCRIPT_HAN)
508 {
509 switch (language)
510 {
511 case FZ_LANG_ja: index = UCDN_LAST_SCRIPT + 1; ordering = FZ_ADOBE_JAPAN; break;
512 case FZ_LANG_ko: index = UCDN_LAST_SCRIPT + 2; ordering = FZ_ADOBE_KOREA; break;
513 case FZ_LANG_zh_Hans: index = UCDN_LAST_SCRIPT + 3; ordering = FZ_ADOBE_GB; break;
514 case FZ_LANG_zh_Hant: index = UCDN_LAST_SCRIPT + 4; ordering = FZ_ADOBE_CNS; break;
515 }
516 }
517 if (script == UCDN_SCRIPT_ARABIC)
518 {
519 if (language == FZ_LANG_ur || language == FZ_LANG_urd)
520 index = UCDN_LAST_SCRIPT + 5;
521 }
522
523 if (serif)
524 fontp = &ctx->font->fallback[index].serif;
525 else
526 fontp = &ctx->font->fallback[index].sans;
527
528 if (!*fontp)
529 {
530 *fontp = fz_load_system_fallback_font(ctx, script, language, serif, bold, italic);
531 if (!*fontp)
532 {
533 data = fz_lookup_noto_font(ctx, script, language, &size, &subfont);
534 if (data)
535 {
536 *fontp = fz_new_font_from_memory(ctx, NULL, data, size, subfont, 0);
537 /* Noto fonts can be embedded. */
538 fz_set_font_embedding(ctx, *fontp, 1);
539 }
540 }
541 }
542
543 switch (script)
544 {
545 case UCDN_SCRIPT_HANGUL: script = UCDN_SCRIPT_HAN; ordering = FZ_ADOBE_KOREA; break;
546 case UCDN_SCRIPT_HIRAGANA: script = UCDN_SCRIPT_HAN; ordering = FZ_ADOBE_JAPAN; break;
547 case UCDN_SCRIPT_KATAKANA: script = UCDN_SCRIPT_HAN; ordering = FZ_ADOBE_JAPAN; break;
548 case UCDN_SCRIPT_BOPOMOFO: script = UCDN_SCRIPT_HAN; ordering = FZ_ADOBE_CNS; break;
549 }
550 if (*fontp && (script == UCDN_SCRIPT_HAN))
551 {
552 (*fontp)->flags.cjk = 1;
553 (*fontp)->flags.cjk_lang = ordering;
554 }
555
556 return *fontp;
557 }
558
559 static fz_font *fz_load_fallback_math_font(fz_context *ctx)
560 {
561 const unsigned char *data;
562 int size;
563 if (!ctx->font->math)
564 {
565 data = fz_lookup_noto_math_font(ctx, &size);
566 if (data)
567 ctx->font->math = fz_new_font_from_memory(ctx, NULL, data, size, 0, 0);
568 }
569 return ctx->font->math;
570 }
571
572 static fz_font *fz_load_fallback_music_font(fz_context *ctx)
573 {
574 const unsigned char *data;
575 int size;
576 if (!ctx->font->music)
577 {
578 data = fz_lookup_noto_music_font(ctx, &size);
579 if (data)
580 ctx->font->music = fz_new_font_from_memory(ctx, NULL, data, size, 0, 0);
581 }
582 return ctx->font->music;
583 }
584
585 static fz_font *fz_load_fallback_symbol1_font(fz_context *ctx)
586 {
587 const unsigned char *data;
588 int size;
589 if (!ctx->font->symbol1)
590 {
591 data = fz_lookup_noto_symbol1_font(ctx, &size);
592 if (data)
593 ctx->font->symbol1 = fz_new_font_from_memory(ctx, NULL, data, size, 0, 0);
594 }
595 return ctx->font->symbol1;
596 }
597
598 static fz_font *fz_load_fallback_symbol2_font(fz_context *ctx)
599 {
600 const unsigned char *data;
601 int size;
602 if (!ctx->font->symbol2)
603 {
604 data = fz_lookup_noto_symbol2_font(ctx, &size);
605 if (data)
606 ctx->font->symbol2 = fz_new_font_from_memory(ctx, NULL, data, size, 0, 0);
607 }
608 return ctx->font->symbol2;
609 }
610
611 static fz_font *fz_load_fallback_emoji_font(fz_context *ctx)
612 {
613 const unsigned char *data;
614 int size;
615 if (!ctx->font->emoji)
616 {
617 data = fz_lookup_noto_emoji_font(ctx, &size);
618 if (data)
619 ctx->font->emoji = fz_new_font_from_memory(ctx, NULL, data, size, 0, 0);
620 }
621 return ctx->font->emoji;
622 }
623
624 static fz_font *fz_load_fallback_boxes_font(fz_context *ctx)
625 {
626 const unsigned char *data;
627 int size;
628 if (!ctx->font->boxes)
629 {
630 data = fz_lookup_noto_boxes_font(ctx, &size);
631 if (data)
632 ctx->font->boxes = fz_new_font_from_memory(ctx, NULL, data, size, 0, 0);
633 }
634 return ctx->font->boxes;
635 }
636
637 static const struct ft_error ft_errors[] =
638 {
639 #include FT_ERRORS_H
640 };
641
642 const char *ft_error_string(int err)
643 {
644 const struct ft_error *e;
645
646 for (e = ft_errors; e->str; e++)
647 if (e->err == err)
648 return e->str;
649
650 return "Unknown error";
651 }
652
653 static void
654 fz_keep_freetype(fz_context *ctx)
655 {
656 int fterr;
657 int maj, min, pat;
658 fz_font_context *fct = ctx->font;
659
660 fz_ft_lock(ctx);
661 if (fct->ftlib)
662 {
663 fct->ftlib_refs++;
664 fz_ft_unlock(ctx);
665 return;
666 }
667
668 fterr = FT_New_Library(&fct->ftmemory, &fct->ftlib);
669 if (fterr)
670 {
671 const char *mess = ft_error_string(fterr);
672 fz_ft_unlock(ctx);
673 fz_throw(ctx, FZ_ERROR_LIBRARY, "cannot init freetype: %s", mess);
674 }
675
676 FT_Add_Default_Modules(fct->ftlib);
677
678 FT_Library_Version(fct->ftlib, &maj, &min, &pat);
679 if (maj == 2 && min == 1 && pat < 7)
680 {
681 fterr = FT_Done_Library(fct->ftlib);
682 if (fterr)
683 fz_warn(ctx, "FT_Done_Library(): %s", ft_error_string(fterr));
684 fz_ft_unlock(ctx);
685 fz_throw(ctx, FZ_ERROR_LIBRARY, "freetype version too old: %d.%d.%d", maj, min, pat);
686 }
687
688 fct->ftlib_refs++;
689 fz_ft_unlock(ctx);
690 }
691
692 static void
693 fz_drop_freetype(fz_context *ctx)
694 {
695 int fterr;
696 fz_font_context *fct = ctx->font;
697
698 fz_ft_lock(ctx);
699 if (--fct->ftlib_refs == 0)
700 {
701 fterr = FT_Done_Library(fct->ftlib);
702 if (fterr)
703 fz_warn(ctx, "FT_Done_Library(): %s", ft_error_string(fterr));
704 fct->ftlib = NULL;
705 }
706 fz_ft_unlock(ctx);
707 }
708
709 fz_font *
710 fz_new_font_from_buffer(fz_context *ctx, const char *name, fz_buffer *buffer, int index, int use_glyph_bbox)
711 {
712 FT_Face face;
713 TT_OS2 *os2;
714 fz_font *font;
715 int fterr;
716 FT_ULong tag, size, i, n;
717 FT_UShort flags;
718 char namebuf[sizeof(font->name)];
719 fz_ascdesc_source ascdesc_src = FZ_ASCDESC_FROM_FONT;
720
721 fz_keep_freetype(ctx);
722
723 fz_ft_lock(ctx);
724 fterr = FT_New_Memory_Face(ctx->font->ftlib, buffer->data, (FT_Long)buffer->len, index, &face);
725 fz_ft_unlock(ctx);
726 if (fterr)
727 {
728 fz_drop_freetype(ctx);
729 fz_throw(ctx, FZ_ERROR_LIBRARY, "FT_New_Memory_Face(%s): %s", name, ft_error_string(fterr));
730 }
731
732 if (!name)
733 {
734 if (!face->family_name)
735 {
736 name = face->style_name;
737 }
738 else if (!face->style_name)
739 {
740 name = face->family_name;
741 }
742 else if (strstr(face->style_name, face->family_name) == face->style_name)
743 {
744 name = face->style_name;
745 }
746 else
747 {
748 fz_strlcpy(namebuf, face->family_name, sizeof(namebuf));
749 fz_strlcat(namebuf, " ", sizeof(namebuf));
750 fz_strlcat(namebuf, face->style_name, sizeof(namebuf));
751 name = namebuf;
752 }
753 }
754
755 fz_try(ctx)
756 font = fz_new_font(ctx, name, use_glyph_bbox, face->num_glyphs);
757 fz_catch(ctx)
758 {
759 fz_ft_lock(ctx);
760 fterr = FT_Done_Face(face);
761 fz_ft_unlock(ctx);
762 if (fterr)
763 fz_warn(ctx, "FT_Done_Face(%s): %s", name, ft_error_string(fterr));
764 fz_drop_freetype(ctx);
765 fz_rethrow(ctx);
766 }
767
768 font->ft_face = face;
769 fz_set_font_bbox(ctx, font,
770 (float) face->bbox.xMin / face->units_per_EM,
771 (float) face->bbox.yMin / face->units_per_EM,
772 (float) face->bbox.xMax / face->units_per_EM,
773 (float) face->bbox.yMax / face->units_per_EM);
774
775 if (face->ascender <= 0 || face->ascender > FZ_MAX_TRUSTWORTHY_ASCENT * face->units_per_EM)
776 font->ascender = 0.8f, ascdesc_src = FZ_ASCDESC_DEFAULT;
777 else
778 font->ascender = (float)face->ascender / face->units_per_EM;
779
780 if (face->descender < FZ_MAX_TRUSTWORTHY_DESCENT * face->units_per_EM || face->descender > -FZ_MAX_TRUSTWORTHY_DESCENT * face->units_per_EM)
781 font->descender = -0.2f, ascdesc_src = FZ_ASCDESC_DEFAULT;
782 else
783 {
784 font->descender = (float)face->descender / face->units_per_EM;
785 if (font->descender > 0)
786 font->descender = -font->descender;
787 }
788
789 font->ascdesc_src = ascdesc_src;
790
791 font->subfont = index;
792
793 font->flags.is_mono = !!(face->face_flags & FT_FACE_FLAG_FIXED_WIDTH);
794 font->flags.is_serif = 1;
795 font->flags.is_bold = !!(face->style_flags & FT_STYLE_FLAG_BOLD);
796 font->flags.is_italic = !!(face->style_flags & FT_STYLE_FLAG_ITALIC);
797 font->flags.embed = 1;
798 font->flags.never_embed = 0;
799
800 if (FT_IS_SFNT(face))
801 {
802 fz_ft_lock(ctx);
803 os2 = FT_Get_Sfnt_Table(face, FT_SFNT_OS2);
804 if (os2)
805 font->flags.is_serif = !(os2->sFamilyClass & 2048); /* Class 8 is sans-serif */
806
807 flags = FT_Get_FSType_Flags(face);
808 if (flags & (FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING |
809 FT_FSTYPE_BITMAP_EMBEDDING_ONLY))
810 {
811 font->flags.never_embed = 1;
812 font->flags.embed = 0;
813 }
814
815 FT_Sfnt_Table_Info(face, 0, NULL, &n);
816 for (i = 0; i < n; ++i)
817 {
818 FT_Sfnt_Table_Info(face, i, &tag, &size);
819 if (tag == TTAG_GDEF || tag == TTAG_GPOS || tag == TTAG_GSUB)
820 font->flags.has_opentype = 1;
821 }
822 fz_ft_unlock(ctx);
823 }
824
825 if (name)
826 {
827 if (!font->flags.is_bold)
828 {
829 if (strstr(name, "Semibold")) font->flags.is_bold = 1;
830 if (strstr(name, "Bold")) font->flags.is_bold = 1;
831 }
832 if (!font->flags.is_italic)
833 {
834 if (strstr(name, "Italic")) font->flags.is_italic = 1;
835 if (strstr(name, "Oblique")) font->flags.is_italic = 1;
836 }
837 }
838
839 font->buffer = fz_keep_buffer(ctx, buffer);
840
841 return font;
842 }
843
844 fz_font *
845 fz_new_font_from_memory(fz_context *ctx, const char *name, const unsigned char *data, int len, int index, int use_glyph_bbox)
846 {
847 fz_buffer *buffer = fz_new_buffer_from_shared_data(ctx, data, len);
848 fz_font *font = NULL;
849 fz_try(ctx)
850 font = fz_new_font_from_buffer(ctx, name, buffer, index, use_glyph_bbox);
851 fz_always(ctx)
852 fz_drop_buffer(ctx, buffer);
853 fz_catch(ctx)
854 fz_rethrow(ctx);
855 return font;
856 }
857
858 fz_font *
859 fz_new_font_from_file(fz_context *ctx, const char *name, const char *path, int index, int use_glyph_bbox)
860 {
861 fz_buffer *buffer = fz_read_file(ctx, path);
862 fz_font *font = NULL;
863 fz_try(ctx)
864 font = fz_new_font_from_buffer(ctx, name, buffer, index, use_glyph_bbox);
865 fz_always(ctx)
866 fz_drop_buffer(ctx, buffer);
867 fz_catch(ctx)
868 fz_rethrow(ctx);
869 return font;
870 }
871
872 void fz_set_font_embedding(fz_context *ctx, fz_font *font, int embed)
873 {
874 if (!font)
875 return;
876 if (embed)
877 {
878 if (font->flags.never_embed)
879 fz_warn(ctx, "not allowed to embed font: %s", font->name);
880 else
881 font->flags.embed = 1;
882 }
883 else
884 {
885 font->flags.embed = 0;
886 }
887 }
888
889 static int
890 find_base14_index(const char *name)
891 {
892 if (!strcmp(name, "Courier")) return 0;
893 if (!strcmp(name, "Courier-Oblique")) return 1;
894 if (!strcmp(name, "Courier-Bold")) return 2;
895 if (!strcmp(name, "Courier-BoldOblique")) return 3;
896 if (!strcmp(name, "Helvetica")) return 4;
897 if (!strcmp(name, "Helvetica-Oblique")) return 5;
898 if (!strcmp(name, "Helvetica-Bold")) return 6;
899 if (!strcmp(name, "Helvetica-BoldOblique")) return 7;
900 if (!strcmp(name, "Times-Roman")) return 8;
901 if (!strcmp(name, "Times-Italic")) return 9;
902 if (!strcmp(name, "Times-Bold")) return 10;
903 if (!strcmp(name, "Times-BoldItalic")) return 11;
904 if (!strcmp(name, "Symbol")) return 12;
905 if (!strcmp(name, "ZapfDingbats")) return 13;
906 return -1;
907 }
908
909 fz_font *
910 fz_new_base14_font(fz_context *ctx, const char *name)
911 {
912 const unsigned char *data;
913 int size;
914 int x = find_base14_index(name);
915 if (x >= 0)
916 {
917 if (ctx->font->base14[x])
918 return fz_keep_font(ctx, ctx->font->base14[x]);
919 data = fz_lookup_base14_font(ctx, name, &size);
920 if (data)
921 {
922 ctx->font->base14[x] = fz_new_font_from_memory(ctx, name, data, size, 0, 1);
923 ctx->font->base14[x]->flags.is_serif = (name[0] == 'T'); /* Times-Roman */
924 /* Ideally we should not embed base14 fonts by default, but we have to
925 * allow it for now until we have written code in pdf-device to output
926 * base14s in a 'special' manner. */
927 fz_set_font_embedding(ctx, ctx->font->base14[x], 1);
928 return fz_keep_font(ctx, ctx->font->base14[x]);
929 }
930 }
931 fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot find builtin font with name '%s'", name);
932 }
933
934 fz_font *
935 fz_new_cjk_font(fz_context *ctx, int ordering)
936 {
937 const unsigned char *data;
938 int size, index;
939 fz_font *font;
940 if (ordering >= 0 && ordering < (int)nelem(ctx->font->cjk))
941 {
942 if (ctx->font->cjk[ordering])
943 return fz_keep_font(ctx, ctx->font->cjk[ordering]);
944 data = fz_lookup_cjk_font(ctx, ordering, &size, &index);
945 if (data)
946 font = fz_new_font_from_memory(ctx, NULL, data, size, index, 0);
947 else
948 font = fz_load_system_cjk_font(ctx, "SourceHanSerif", ordering, 1);
949 /* FIXME: Currently the builtin one at least will be set to embed. Is that right? */
950 if (font)
951 {
952 font->flags.cjk = 1;
953 font->flags.cjk_lang = ordering;
954 ctx->font->cjk[ordering] = font;
955 return fz_keep_font(ctx, ctx->font->cjk[ordering]);
956 }
957 }
958 fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot find builtin CJK font");
959 }
960
961 fz_font *
962 fz_new_builtin_font(fz_context *ctx, const char *name, int is_bold, int is_italic)
963 {
964 const unsigned char *data;
965 int size;
966 fz_font *font;
967 data = fz_lookup_builtin_font(ctx, name, is_bold, is_italic, &size);
968 if (!data)
969 fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot find builtin font with name '%s'", name);
970 font = fz_new_font_from_memory(ctx, NULL, data, size, 0, 0);
971
972 /* Don't embed builtin fonts. */
973 fz_set_font_embedding(ctx, font, 0);
974
975 return font;
976 }
977
978 static fz_matrix *
979 fz_adjust_ft_glyph_width(fz_context *ctx, fz_font *font, int gid, fz_matrix *trm)
980 {
981 /* Fudge the font matrix to stretch the glyph if we've substituted the font. */
982 if (font->flags.ft_stretch && font->width_table /* && font->wmode == 0 */)
983 {
984 FT_Error fterr;
985 FT_Fixed adv = 0;
986 float subw;
987 float realw;
988
989 fz_ft_lock(ctx);
990 fterr = FT_Get_Advance(font->ft_face, gid, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_IGNORE_TRANSFORM, &adv);
991 fz_ft_unlock(ctx);
992 if (fterr && fterr != FT_Err_Invalid_Argument)
993 fz_warn(ctx, "FT_Get_Advance(%s,%d): %s", font->name, gid, ft_error_string(fterr));
994
995 realw = adv * 1000.0f / ((FT_Face)font->ft_face)->units_per_EM;
996 if (gid < font->width_count)
997 subw = font->width_table[gid];
998 else
999 subw = font->width_default;
1000
1001 /* Sanity check scaling in case of broken metrics. */
1002 if (realw > 0 && subw > 0)
1003 *trm = fz_pre_scale(*trm, subw / realw, 1);
1004 }
1005
1006 return trm;
1007 }
1008
1009 static fz_glyph *
1010 glyph_from_ft_bitmap(fz_context *ctx, int left, int top, FT_Bitmap *bitmap)
1011 {
1012 (void)Memento_label(bitmap->buffer, "ft_bitmap");
1013 if (bitmap->pixel_mode == FT_PIXEL_MODE_MONO)
1014 return fz_new_glyph_from_1bpp_data(ctx, left, top - bitmap->rows, bitmap->width, bitmap->rows, bitmap->buffer + (bitmap->rows-1)*bitmap->pitch, -bitmap->pitch);
1015 else
1016 return fz_new_glyph_from_8bpp_data(ctx, left, top - bitmap->rows, bitmap->width, bitmap->rows, bitmap->buffer + (bitmap->rows-1)*bitmap->pitch, -bitmap->pitch);
1017 }
1018
1019 static fz_pixmap *
1020 pixmap_from_ft_bitmap(fz_context *ctx, int left, int top, FT_Bitmap *bitmap)
1021 {
1022 (void)Memento_label(bitmap->buffer, "ft_bitmap");
1023 if (bitmap->pixel_mode == FT_PIXEL_MODE_MONO)
1024 return fz_new_pixmap_from_1bpp_data(ctx, left, top - bitmap->rows, bitmap->width, bitmap->rows, bitmap->buffer + (bitmap->rows-1)*bitmap->pitch, -bitmap->pitch);
1025 else
1026 return fz_new_pixmap_from_8bpp_data(ctx, left, top - bitmap->rows, bitmap->width, bitmap->rows, bitmap->buffer + (bitmap->rows-1)*bitmap->pitch, -bitmap->pitch);
1027 }
1028
1029 /* Takes the freetype lock, and returns with it held */
1030 static FT_GlyphSlot
1031 do_ft_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, int aa)
1032 {
1033 FT_Face face = font->ft_face;
1034 FT_Matrix m;
1035 FT_Vector v;
1036 FT_Error fterr;
1037
1038 float strength = fz_matrix_expansion(trm) * 0.02f;
1039
1040 fz_adjust_ft_glyph_width(ctx, font, gid, &trm);
1041
1042 if (font->flags.fake_italic)
1043 trm = fz_pre_shear(trm, SHEAR, 0);
1044
1045 fz_ft_lock(ctx);
1046
1047 if (aa == 0)
1048 {
1049 /* enable grid fitting for non-antialiased rendering */
1050 float scale = fz_matrix_expansion(trm);
1051 m.xx = trm.a * 65536 / scale;
1052 m.yx = trm.b * 65536 / scale;
1053 m.xy = trm.c * 65536 / scale;
1054 m.yy = trm.d * 65536 / scale;
1055 v.x = 0;
1056 v.y = 0;
1057
1058 fterr = FT_Set_Char_Size(face, 64 * scale, 64 * scale, 72, 72);
1059 if (fterr)
1060 fz_warn(ctx, "FT_Set_Char_Size(%s,%d,72): %s", font->name, (int)(64*scale), ft_error_string(fterr));
1061 FT_Set_Transform(face, &m, &v);
1062 fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_TARGET_MONO);
1063 if (fterr)
1064 {
1065 fz_warn(ctx, "FT_Load_Glyph(%s,%d,FT_LOAD_TARGET_MONO): %s", font->name, gid, ft_error_string(fterr));
1066 goto retry_unhinted;
1067 }
1068 }
1069 else
1070 {
1071 retry_unhinted:
1072 /*
1073 * Freetype mutilates complex glyphs if they are loaded with
1074 * FT_Set_Char_Size 1.0. It rounds the coordinates before applying
1075 * transformation. To get more precision in freetype, we shift part of
1076 * the scale in the matrix into FT_Set_Char_Size instead.
1077 */
1078
1079 /* Check for overflow; FreeType matrices use 16.16 fixed-point numbers */
1080 if (trm.a < -512 || trm.a > 512) return NULL;
1081 if (trm.b < -512 || trm.b > 512) return NULL;
1082 if (trm.c < -512 || trm.c > 512) return NULL;
1083 if (trm.d < -512 || trm.d > 512) return NULL;
1084
1085 m.xx = trm.a * 64; /* should be 65536 */
1086 m.yx = trm.b * 64;
1087 m.xy = trm.c * 64;
1088 m.yy = trm.d * 64;
1089 v.x = trm.e * 64;
1090 v.y = trm.f * 64;
1091
1092 fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */
1093 if (fterr)
1094 fz_warn(ctx, "FT_Set_Char_Size(%s,65536,72): %s", font->name, ft_error_string(fterr));
1095 FT_Set_Transform(face, &m, &v);
1096 fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);
1097 if (fterr)
1098 {
1099 fz_warn(ctx, "FT_Load_Glyph(%s,%d,FT_LOAD_NO_HINTING): %s", font->name, gid, ft_error_string(fterr));
1100 return NULL;
1101 }
1102 }
1103
1104 if (font->flags.fake_bold)
1105 {
1106 FT_Outline_Embolden(&face->glyph->outline, strength * 64);
1107 FT_Outline_Translate(&face->glyph->outline, -strength * 32, -strength * 32);
1108 }
1109
1110 fterr = FT_Render_Glyph(face->glyph, aa > 0 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
1111 if (fterr)
1112 {
1113 if (aa > 0)
1114 fz_warn(ctx, "FT_Render_Glyph(%s,%d,FT_RENDER_MODE_NORMAL): %s", font->name, gid, ft_error_string(fterr));
1115 else
1116 fz_warn(ctx, "FT_Render_Glyph(%s,%d,FT_RENDER_MODE_MONO): %s", font->name, gid, ft_error_string(fterr));
1117 return NULL;
1118 }
1119 return face->glyph;
1120 }
1121
1122 fz_pixmap *
1123 fz_render_ft_glyph_pixmap(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, int aa)
1124 {
1125 FT_GlyphSlot slot = do_ft_render_glyph(ctx, font, gid, trm, aa);
1126 fz_pixmap *pixmap = NULL;
1127
1128 if (slot == NULL)
1129 {
1130 fz_ft_unlock(ctx);
1131 return NULL;
1132 }
1133
1134 fz_try(ctx)
1135 {
1136 pixmap = pixmap_from_ft_bitmap(ctx, slot->bitmap_left, slot->bitmap_top, &slot->bitmap);
1137 }
1138 fz_always(ctx)
1139 {
1140 fz_ft_unlock(ctx);
1141 }
1142 fz_catch(ctx)
1143 {
1144 fz_rethrow(ctx);
1145 }
1146
1147 return pixmap;
1148 }
1149
1150 /* The glyph cache lock is always taken when this is called. */
1151 fz_glyph *
1152 fz_render_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, int aa)
1153 {
1154 FT_GlyphSlot slot = do_ft_render_glyph(ctx, font, gid, trm, aa);
1155 fz_glyph *glyph = NULL;
1156
1157 if (slot == NULL)
1158 {
1159 fz_ft_unlock(ctx);
1160 return NULL;
1161 }
1162
1163 fz_try(ctx)
1164 {
1165 glyph = glyph_from_ft_bitmap(ctx, slot->bitmap_left, slot->bitmap_top, &slot->bitmap);
1166 }
1167 fz_always(ctx)
1168 {
1169 fz_ft_unlock(ctx);
1170 }
1171 fz_catch(ctx)
1172 {
1173 fz_rethrow(ctx);
1174 }
1175
1176 return glyph;
1177 }
1178
1179 /* Takes the freetype lock, and returns with it held */
1180 static FT_Glyph
1181 do_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, const fz_stroke_state *state, int aa)
1182 {
1183 FT_Face face = font->ft_face;
1184 float expansion = fz_matrix_expansion(ctm);
1185 int linewidth = state->linewidth * expansion * 64 / 2;
1186 FT_Matrix m;
1187 FT_Vector v;
1188 FT_Error fterr;
1189 FT_Stroker stroker;
1190 FT_Glyph glyph;
1191 FT_Stroker_LineJoin line_join;
1192 FT_Stroker_LineCap line_cap;
1193
1194 fz_adjust_ft_glyph_width(ctx, font, gid, &trm);
1195
1196 if (font->flags.fake_italic)
1197 trm = fz_pre_shear(trm, SHEAR, 0);
1198
1199 m.xx = trm.a * 64; /* should be 65536 */
1200 m.yx = trm.b * 64;
1201 m.xy = trm.c * 64;
1202 m.yy = trm.d * 64;
1203 v.x = trm.e * 64;
1204 v.y = trm.f * 64;
1205
1206 fz_ft_lock(ctx);
1207 fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */
1208 if (fterr)
1209 {
1210 fz_warn(ctx, "FT_Set_Char_Size(%s,65536,72): %s", font->name, ft_error_string(fterr));
1211 return NULL;
1212 }
1213
1214 FT_Set_Transform(face, &m, &v);
1215
1216 fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);
1217 if (fterr)
1218 {
1219 fz_warn(ctx, "FT_Load_Glyph(%s,%d,FT_LOAD_NO_HINTING): %s", font->name, gid, ft_error_string(fterr));
1220 return NULL;
1221 }
1222
1223 fterr = FT_Stroker_New(ctx->font->ftlib, &stroker);
1224 if (fterr)
1225 {
1226 fz_warn(ctx, "FT_Stroker_New(): %s", ft_error_string(fterr));
1227 return NULL;
1228 }
1229
1230 line_join =
1231 state->linejoin == FZ_LINEJOIN_MITER ? FT_STROKER_LINEJOIN_MITER_FIXED :
1232 state->linejoin == FZ_LINEJOIN_ROUND ? FT_STROKER_LINEJOIN_ROUND :
1233 state->linejoin == FZ_LINEJOIN_BEVEL ? FT_STROKER_LINEJOIN_BEVEL :
1234 FT_STROKER_LINEJOIN_MITER_VARIABLE;
1235 line_cap =
1236 state->start_cap == FZ_LINECAP_BUTT ? FT_STROKER_LINECAP_BUTT :
1237 state->start_cap == FZ_LINECAP_ROUND ? FT_STROKER_LINECAP_ROUND :
1238 state->start_cap == FZ_LINECAP_SQUARE ? FT_STROKER_LINECAP_SQUARE :
1239 state->start_cap == FZ_LINECAP_TRIANGLE ? FT_STROKER_LINECAP_BUTT :
1240 FT_STROKER_LINECAP_BUTT;
1241
1242 FT_Stroker_Set(stroker, linewidth, line_cap, line_join, state->miterlimit * 65536);
1243
1244 fterr = FT_Get_Glyph(face->glyph, &glyph);
1245 if (fterr)
1246 {
1247 fz_warn(ctx, "FT_Get_Glyph(): %s", ft_error_string(fterr));
1248 FT_Stroker_Done(stroker);
1249 return NULL;
1250 }
1251
1252 fterr = FT_Glyph_Stroke(&glyph, stroker, 1);
1253 if (fterr)
1254 {
1255 fz_warn(ctx, "FT_Glyph_Stroke(): %s", ft_error_string(fterr));
1256 FT_Done_Glyph(glyph);
1257 FT_Stroker_Done(stroker);
1258 return NULL;
1259 }
1260
1261 FT_Stroker_Done(stroker);
1262
1263 fterr = FT_Glyph_To_Bitmap(&glyph, aa > 0 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, 0, 1);
1264 if (fterr)
1265 {
1266 fz_warn(ctx, "FT_Glyph_To_Bitmap(): %s", ft_error_string(fterr));
1267 FT_Done_Glyph(glyph);
1268 return NULL;
1269 }
1270 return glyph;
1271 }
1272
1273 fz_glyph *
1274 fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, const fz_stroke_state *state, int aa)
1275 {
1276 FT_Glyph glyph = do_render_ft_stroked_glyph(ctx, font, gid, trm, ctm, state, aa);
1277 FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
1278 fz_glyph *result = NULL;
1279
1280 if (bitmap == NULL)
1281 {
1282 fz_ft_unlock(ctx);
1283 return NULL;
1284 }
1285
1286 fz_try(ctx)
1287 {
1288 result = glyph_from_ft_bitmap(ctx, bitmap->left, bitmap->top, &bitmap->bitmap);
1289 }
1290 fz_always(ctx)
1291 {
1292 FT_Done_Glyph(glyph);
1293 fz_ft_unlock(ctx);
1294 }
1295 fz_catch(ctx)
1296 {
1297 fz_rethrow(ctx);
1298 }
1299
1300 return result;
1301 }
1302
1303 static fz_rect *
1304 get_gid_bbox(fz_context *ctx, fz_font *font, int gid)
1305 {
1306 int i;
1307
1308 if (gid < 0 || gid >= font->glyph_count || !font->use_glyph_bbox)
1309 return NULL;
1310
1311 if (font->bbox_table == NULL) {
1312 i = (font->glyph_count + 255)/256;
1313 font->bbox_table = Memento_label(fz_malloc_array(ctx, i, fz_rect *), "bbox_table(top)");
1314 memset(font->bbox_table, 0, sizeof(fz_rect *) * i);
1315 }
1316
1317 if (font->bbox_table[gid>>8] == NULL) {
1318 font->bbox_table[gid>>8] = Memento_label(fz_malloc_array(ctx, 256, fz_rect), "bbox_table");
1319 for (i = 0; i < 256; i++) {
1320 font->bbox_table[gid>>8][i] = fz_empty_rect;
1321 }
1322 }
1323
1324 return &font->bbox_table[gid>>8][gid & 255];
1325 }
1326
1327 static fz_rect *
1328 fz_bound_ft_glyph(fz_context *ctx, fz_font *font, int gid)
1329 {
1330 FT_Face face = font->ft_face;
1331 FT_Error fterr;
1332 FT_BBox cbox;
1333 FT_Matrix m;
1334 FT_Vector v;
1335 fz_rect *bounds = get_gid_bbox(ctx, font, gid);
1336
1337 // TODO: refactor loading into fz_load_ft_glyph
1338 // TODO: cache results
1339
1340 const int scale = face->units_per_EM;
1341 const float recip = 1.0f / scale;
1342 const float strength = 0.02f;
1343 fz_matrix trm = fz_identity;
1344
1345 fz_adjust_ft_glyph_width(ctx, font, gid, &trm);
1346
1347 if (font->flags.fake_italic)
1348 trm = fz_pre_shear(trm, SHEAR, 0);
1349
1350 m.xx = trm.a * 65536;
1351 m.yx = trm.b * 65536;
1352 m.xy = trm.c * 65536;
1353 m.yy = trm.d * 65536;
1354 v.x = trm.e * 65536;
1355 v.y = trm.f * 65536;
1356
1357 fz_ft_lock(ctx);
1358 /* Set the char size to scale=face->units_per_EM to effectively give
1359 * us unscaled results. This avoids quantisation. We then apply the
1360 * scale ourselves below. */
1361 fterr = FT_Set_Char_Size(face, scale, scale, 72, 72);
1362 if (fterr)
1363 fz_warn(ctx, "FT_Set_Char_Size(%s,%d,72): %s", font->name, scale, ft_error_string(fterr));
1364 FT_Set_Transform(face, &m, &v);
1365
1366 fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);
1367 if (fterr)
1368 {
1369 fz_warn(ctx, "FT_Load_Glyph(%s,%d,FT_LOAD_NO_HINTING): %s", font->name, gid, ft_error_string(fterr));
1370 fz_ft_unlock(ctx);
1371 bounds->x0 = bounds->x1 = trm.e;
1372 bounds->y0 = bounds->y1 = trm.f;
1373 return bounds;
1374 }
1375
1376 if (font->flags.fake_bold)
1377 {
1378 FT_Outline_Embolden(&face->glyph->outline, strength * scale);
1379 FT_Outline_Translate(&face->glyph->outline, -strength * 0.5f * scale, -strength * 0.5f * scale);
1380 }
1381
1382 FT_Outline_Get_CBox(&face->glyph->outline, &cbox);
1383 fz_ft_unlock(ctx);
1384 bounds->x0 = cbox.xMin * recip;
1385 bounds->y0 = cbox.yMin * recip;
1386 bounds->x1 = cbox.xMax * recip;
1387 bounds->y1 = cbox.yMax * recip;
1388
1389 if (fz_is_empty_rect(*bounds))
1390 {
1391 bounds->x0 = bounds->x1 = trm.e;
1392 bounds->y0 = bounds->y1 = trm.f;
1393 }
1394
1395 return bounds;
1396 }
1397
1398 /* Turn FT_Outline into a fz_path */
1399
1400 struct closure {
1401 fz_context *ctx;
1402 fz_path *path;
1403 fz_matrix trm;
1404 };
1405
1406 static int move_to(const FT_Vector *p, void *cc_)
1407 {
1408 struct closure *cc = (struct closure *)cc_;
1409 fz_context *ctx = cc->ctx;
1410 fz_path *path = cc->path;
1411 fz_point pt;
1412
1413 pt = fz_transform_point_xy(p->x, p->y, cc->trm);
1414 fz_moveto(ctx, path, pt.x, pt.y);
1415 return 0;
1416 }
1417
1418 static int line_to(const FT_Vector *p, void *cc_)
1419 {
1420 struct closure *cc = (struct closure *)cc_;
1421 fz_context *ctx = cc->ctx;
1422 fz_path *path = cc->path;
1423 fz_point pt;
1424
1425 pt = fz_transform_point_xy(p->x, p->y, cc->trm);
1426 fz_lineto(ctx, path, pt.x, pt.y);
1427 return 0;
1428 }
1429
1430 static int conic_to(const FT_Vector *c, const FT_Vector *p, void *cc_)
1431 {
1432 struct closure *cc = (struct closure *)cc_;
1433 fz_context *ctx = cc->ctx;
1434 fz_path *path = cc->path;
1435 fz_point ct, pt;
1436
1437 ct = fz_transform_point_xy(c->x, c->y, cc->trm);
1438 pt = fz_transform_point_xy(p->x, p->y, cc->trm);
1439
1440 fz_quadto(ctx, path, ct.x, ct.y, pt.x, pt.y);
1441 return 0;
1442 }
1443
1444 static int cubic_to(const FT_Vector *c1, const FT_Vector *c2, const FT_Vector *p, void *cc_)
1445 {
1446 struct closure *cc = (struct closure *)cc_;
1447 fz_context *ctx = cc->ctx;
1448 fz_path *path = cc->path;
1449 fz_point c1t, c2t, pt;
1450
1451 c1t = fz_transform_point_xy(c1->x, c1->y, cc->trm);
1452 c2t = fz_transform_point_xy(c2->x, c2->y, cc->trm);
1453 pt = fz_transform_point_xy(p->x, p->y, cc->trm);
1454
1455 fz_curveto(ctx, path, c1t.x, c1t.y, c2t.x, c2t.y, pt.x, pt.y);
1456 return 0;
1457 }
1458
1459 static const FT_Outline_Funcs outline_funcs = {
1460 move_to, line_to, conic_to, cubic_to, 0, 0
1461 };
1462
1463 fz_path *
1464 fz_outline_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm)
1465 {
1466 struct closure cc;
1467 FT_Face face = font->ft_face;
1468 int fterr;
1469
1470 const int scale = 65536;
1471 const float recip = 1.0f / scale;
1472 const float strength = 0.02f;
1473
1474 fz_adjust_ft_glyph_width(ctx, font, gid, &trm);
1475
1476 if (font->flags.fake_italic)
1477 trm = fz_pre_shear(trm, SHEAR, 0);
1478
1479 fz_ft_lock(ctx);
1480
1481 fterr = FT_Set_Char_Size(face, scale, scale, 72, 72);
1482 if (fterr)
1483 fz_warn(ctx, "FT_Set_Char_Size(%s,%d,72): %s", font->name, scale, ft_error_string(fterr));
1484
1485 fterr = FT_Load_Glyph(face, gid, FT_LOAD_IGNORE_TRANSFORM);
1486 if (fterr)
1487 {
1488 fz_warn(ctx, "FT_Load_Glyph(%s,%d,FT_LOAD_IGNORE_TRANSFORM): %s", font->name, gid, ft_error_string(fterr));
1489 fterr = FT_Load_Glyph(face, gid, FT_LOAD_IGNORE_TRANSFORM | FT_LOAD_NO_HINTING);
1490 }
1491 if (fterr)
1492 {
1493 fz_warn(ctx, "FT_Load_Glyph(%s,%d,FT_LOAD_IGNORE_TRANSFORM | FT_LOAD_NO_HINTING): %s", font->name, gid, ft_error_string(fterr));
1494 fz_ft_unlock(ctx);
1495 return NULL;
1496 }
1497
1498 if (font->flags.fake_bold)
1499 {
1500 FT_Outline_Embolden(&face->glyph->outline, strength * scale);
1501 FT_Outline_Translate(&face->glyph->outline, -strength * 0.5f * scale, -strength * 0.5f * scale);
1502 }
1503
1504 cc.path = NULL;
1505 fz_try(ctx)
1506 {
1507 cc.ctx = ctx;
1508 cc.path = fz_new_path(ctx);
1509 cc.trm = fz_concat(fz_scale(recip, recip), trm);
1510 fz_moveto(ctx, cc.path, cc.trm.e, cc.trm.f);
1511 FT_Outline_Decompose(&face->glyph->outline, &outline_funcs, &cc);
1512 fz_closepath(ctx, cc.path);
1513 }
1514 fz_always(ctx)
1515 {
1516 fz_ft_unlock(ctx);
1517 }
1518 fz_catch(ctx)
1519 {
1520 fz_warn(ctx, "freetype cannot decompose outline");
1521 fz_drop_path(ctx, cc.path);
1522 return NULL;
1523 }
1524
1525 return cc.path;
1526 }
1527
1528 /*
1529 Type 3 fonts...
1530 */
1531
1532 fz_font *
1533 fz_new_type3_font(fz_context *ctx, const char *name, fz_matrix matrix)
1534 {
1535 fz_font *font;
1536
1537 font = fz_new_font(ctx, name, 1, 256);
1538 fz_try(ctx)
1539 {
1540 font->t3procs = fz_calloc(ctx, 256, sizeof(fz_buffer*));
1541 font->t3lists = fz_calloc(ctx, 256, sizeof(fz_display_list*));
1542 font->t3widths = fz_calloc(ctx, 256, sizeof(float));
1543 font->t3flags = fz_calloc(ctx, 256, sizeof(unsigned short));
1544 }
1545 fz_catch(ctx)
1546 {
1547 fz_drop_font(ctx, font);
1548 fz_rethrow(ctx);
1549 }
1550
1551 font->t3matrix = matrix;
1552
1553 return font;
1554 }
1555
1556 static void
1557 fz_bound_t3_glyph(fz_context *ctx, fz_font *font, int gid)
1558 {
1559 fz_display_list *list;
1560 fz_device *dev;
1561 fz_rect *r = get_gid_bbox(ctx, font, gid);
1562
1563 list = font->t3lists[gid];
1564 if (!list)
1565 {
1566 *r = fz_empty_rect;
1567 return;
1568 }
1569
1570 dev = fz_new_bbox_device(ctx, r);
1571 fz_try(ctx)
1572 {
1573 fz_run_display_list(ctx, list, dev, font->t3matrix, fz_infinite_rect, NULL);
1574 fz_close_device(ctx, dev);
1575 }
1576 fz_always(ctx)
1577 {
1578 fz_drop_device(ctx, dev);
1579 }
1580 fz_catch(ctx)
1581 {
1582 fz_rethrow(ctx);
1583 }
1584
1585 /* Update font bbox with glyph's computed bbox if the font bbox is invalid */
1586 if (font->flags.invalid_bbox)
1587 font->bbox = fz_union_rect(font->bbox, *r);
1588 }
1589
1590 void
1591 fz_prepare_t3_glyph(fz_context *ctx, fz_font *font, int gid)
1592 {
1593 fz_device *dev;
1594 fz_rect d1_rect;
1595
1596 /* We've not already loaded this one! */
1597 assert(font->t3lists[gid] == NULL);
1598
1599 font->t3lists[gid] = fz_new_display_list(ctx, font->bbox);
1600
1601 dev = fz_new_list_device(ctx, font->t3lists[gid]);
1602 dev->flags = FZ_DEVFLAG_FILLCOLOR_UNDEFINED |
1603 FZ_DEVFLAG_STROKECOLOR_UNDEFINED |
1604 FZ_DEVFLAG_STARTCAP_UNDEFINED |
1605 FZ_DEVFLAG_DASHCAP_UNDEFINED |
1606 FZ_DEVFLAG_ENDCAP_UNDEFINED |
1607 FZ_DEVFLAG_LINEJOIN_UNDEFINED |
1608 FZ_DEVFLAG_MITERLIMIT_UNDEFINED |
1609 FZ_DEVFLAG_LINEWIDTH_UNDEFINED |
1610 FZ_DEVFLAG_DASH_PATTERN_UNDEFINED;
1611
1612 fz_try(ctx)
1613 {
1614 font->t3run(ctx, font->t3doc, font->t3resources, font->t3procs[gid], dev, fz_identity, NULL, NULL, NULL, NULL);
1615 fz_close_device(ctx, dev);
1616 font->t3flags[gid] = dev->flags;
1617 d1_rect = dev->d1_rect;
1618 }
1619 fz_always(ctx)
1620 {
1621 fz_drop_device(ctx, dev);
1622 }
1623 fz_catch(ctx)
1624 fz_rethrow(ctx);
1625 if (fz_display_list_is_empty(ctx, font->t3lists[gid]))
1626 {
1627 fz_rect *r = get_gid_bbox(ctx, font, gid);
1628 /* If empty, no need for a huge bbox, especially as the logic
1629 * in the 'else if' can make it huge. */
1630 r->x0 = font->flags.invalid_bbox ? 0 : font->bbox.x0;
1631 r->y0 = font->flags.invalid_bbox ? 0 : font->bbox.y0;
1632 r->x1 = r->x0 + .00001f;
1633 r->y1 = r->y0 + .00001f;
1634 }
1635 else if (font->t3flags[gid] & FZ_DEVFLAG_BBOX_DEFINED)
1636 {
1637 fz_rect *r = get_gid_bbox(ctx, font, gid);
1638 *r = fz_transform_rect(d1_rect, font->t3matrix);
1639
1640 if (font->flags.invalid_bbox || !fz_contains_rect(font->bbox, d1_rect))
1641 {
1642 /* Either the font bbox is invalid, or the d1_rect returned is
1643 * incompatible with it. Either way, don't trust the d1 rect
1644 * and calculate it from the contents. */
1645 fz_bound_t3_glyph(ctx, font, gid);
1646 }
1647 }
1648 else
1649 {
1650 /* No bbox has been defined for this glyph, so compute it. */
1651 fz_bound_t3_glyph(ctx, font, gid);
1652 }
1653 }
1654
1655 void
1656 fz_run_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_device *dev)
1657 {
1658 fz_display_list *list;
1659 fz_matrix ctm;
1660
1661 list = font->t3lists[gid];
1662 if (!list)
1663 return;
1664
1665 ctm = fz_concat(font->t3matrix, trm);
1666 fz_run_display_list(ctx, list, dev, ctm, fz_infinite_rect, NULL);
1667 }
1668
1669 fz_pixmap *
1670 fz_render_t3_glyph_pixmap(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_colorspace *model, const fz_irect *scissor, int aa)
1671 {
1672 fz_display_list *list;
1673 fz_rect bounds;
1674 fz_irect bbox;
1675 fz_device *dev = NULL;
1676 fz_pixmap *glyph;
1677 fz_pixmap *result = NULL;
1678
1679 if (gid < 0 || gid > 255)
1680 return NULL;
1681
1682 list = font->t3lists[gid];
1683 if (!list)
1684 return NULL;
1685
1686 if (font->t3flags[gid] & FZ_DEVFLAG_MASK)
1687 {
1688 if (font->t3flags[gid] & FZ_DEVFLAG_COLOR)
1689 fz_warn(ctx, "type3 glyph claims to be both masked and colored");
1690 model = NULL;
1691 }
1692 else if (font->t3flags[gid] & FZ_DEVFLAG_COLOR)
1693 {
1694 if (!model)
1695 fz_warn(ctx, "colored type3 glyph wanted in masked context");
1696 }
1697 else
1698 {
1699 fz_warn(ctx, "type3 glyph doesn't specify masked or colored");
1700 model = NULL; /* Treat as masked */
1701 }
1702
1703 bounds = fz_expand_rect(fz_bound_glyph(ctx, font, gid, trm), 1);
1704 bbox = fz_irect_from_rect(bounds);
1705 bbox = fz_intersect_irect(bbox, *scissor);
1706
1707 /* Glyphs must always have alpha */
1708 glyph = fz_new_pixmap_with_bbox(ctx, model, bbox, NULL/* FIXME */, 1);
1709
1710 fz_var(dev);
1711 fz_try(ctx)
1712 {
1713 fz_clear_pixmap(ctx, glyph);
1714 dev = fz_new_draw_device_type3(ctx, fz_identity, glyph);
1715 fz_run_t3_glyph(ctx, font, gid, trm, dev);
1716 fz_close_device(ctx, dev);
1717 }
1718 fz_always(ctx)
1719 {
1720 fz_drop_device(ctx, dev);
1721 }
1722 fz_catch(ctx)
1723 {
1724 fz_drop_pixmap(ctx, glyph);
1725 fz_rethrow(ctx);
1726 }
1727
1728 if (!model)
1729 {
1730 fz_try(ctx)
1731 {
1732 result = fz_alpha_from_gray(ctx, glyph);
1733 }
1734 fz_always(ctx)
1735 {
1736 fz_drop_pixmap(ctx, glyph);
1737 }
1738 fz_catch(ctx)
1739 {
1740 fz_rethrow(ctx);
1741 }
1742 }
1743 else
1744 result = glyph;
1745
1746 return result;
1747 }
1748
1749 fz_glyph *
1750 fz_render_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_colorspace *model, const fz_irect *scissor, int aa)
1751 {
1752 fz_pixmap *pixmap = fz_render_t3_glyph_pixmap(ctx, font, gid, trm, model, scissor, aa);
1753 return fz_new_glyph_from_pixmap(ctx, pixmap);
1754 }
1755
1756 void
1757 fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gid, fz_matrix trm, void *gstate, fz_default_colorspaces *def_cs, void *fill_gstate, void *stroke_gstate)
1758 {
1759 fz_matrix ctm;
1760
1761 if (gid < 0 || gid > 255)
1762 return;
1763
1764 if (font->t3flags[gid] & FZ_DEVFLAG_MASK)
1765 {
1766 if (font->t3flags[gid] & FZ_DEVFLAG_COLOR)
1767 fz_warn(ctx, "type3 glyph claims to be both masked and colored");
1768 }
1769 else if (!(font->t3flags[gid] & FZ_DEVFLAG_COLOR))
1770 {
1771 fz_warn(ctx, "type3 glyph doesn't specify masked or colored");
1772 }
1773
1774 ctm = fz_concat(font->t3matrix, trm);
1775 font->t3run(ctx, font->t3doc, font->t3resources, font->t3procs[gid], dev, ctm, gstate, def_cs, fill_gstate, stroke_gstate);
1776 }
1777
1778 fz_rect
1779 fz_bound_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm)
1780 {
1781 fz_rect rect;
1782 fz_rect *r = get_gid_bbox(ctx, font, gid);
1783 if (r)
1784 {
1785 /* If the bbox is infinite or empty, distrust it */
1786 if (fz_is_infinite_rect(*r) || fz_is_empty_rect(*r))
1787 {
1788 /* Get the real size from the glyph */
1789 if (font->ft_face)
1790 fz_bound_ft_glyph(ctx, font, gid);
1791 else if (font->t3lists)
1792 fz_bound_t3_glyph(ctx, font, gid);
1793 else
1794 /* If we can't get a real size, fall back to the font
1795 * bbox. */
1796 *r = font->bbox;
1797 /* If the real size came back as empty, then store it as
1798 * a very small rectangle to avoid us calling this same
1799 * check every time. */
1800 if (fz_is_empty_rect(*r))
1801 {
1802 r->x0 = 0;
1803 r->y0 = 0;
1804 r->x1 = 0.0000001f;
1805 r->y1 = 0.0000001f;
1806 }
1807 }
1808 rect = *r;
1809 }
1810 else
1811 {
1812 /* fall back to font bbox */
1813 rect = font->bbox;
1814 }
1815 return fz_transform_rect(rect, trm);
1816 }
1817
1818 fz_path *
1819 fz_outline_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm)
1820 {
1821 if (!font->ft_face)
1822 return NULL;
1823 return fz_outline_ft_glyph(ctx, font, gid, ctm);
1824 }
1825
1826 int fz_glyph_cacheable(fz_context *ctx, fz_font *font, int gid)
1827 {
1828 if (!font->t3procs || !font->t3flags || gid < 0 || gid >= font->glyph_count)
1829 return 1;
1830 return (font->t3flags[gid] & FZ_DEVFLAG_UNCACHEABLE) == 0;
1831 }
1832
1833 static float
1834 fz_advance_ft_glyph_aux(fz_context *ctx, fz_font *font, int gid, int wmode, int locked)
1835 {
1836 FT_Error fterr;
1837 FT_Fixed adv = 0;
1838 int mask;
1839
1840 if (gid < 0)
1841 {
1842 fz_warn(ctx, "FT_Get_Advance(%s,%d): %s", font->name, gid, ft_error_string(FT_Err_Invalid_Argument));
1843 return font->width_default / 1000.0f;
1844 }
1845
1846 /* PDF and substitute font widths. */
1847 if (font->flags.ft_stretch)
1848 {
1849 if (font->width_table)
1850 {
1851 if (gid < font->width_count)
1852 return font->width_table[gid] / 1000.0f;
1853 return font->width_default / 1000.0f;
1854 }
1855 }
1856
1857 mask = FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_IGNORE_TRANSFORM;
1858 if (wmode)
1859 mask |= FT_LOAD_VERTICAL_LAYOUT;
1860 if (!locked)
1861 fz_ft_lock(ctx);
1862 fterr = FT_Get_Advance(font->ft_face, gid, mask, &adv);
1863 if (!locked)
1864 fz_ft_unlock(ctx);
1865 if (fterr && fterr != FT_Err_Invalid_Argument)
1866 {
1867 fz_warn(ctx, "FT_Get_Advance(%s,%d): %s", font->name, gid, ft_error_string(fterr));
1868 if (font->width_table)
1869 {
1870 if (gid < font->width_count)
1871 return font->width_table[gid] / 1000.0f;
1872 return font->width_default / 1000.0f;
1873 }
1874 }
1875 return (float) adv / ((FT_Face)font->ft_face)->units_per_EM;
1876 }
1877
1878 static float
1879 fz_advance_ft_glyph(fz_context *ctx, fz_font *font, int gid, int wmode)
1880 {
1881 return fz_advance_ft_glyph_aux(ctx, font, gid, wmode, 0);
1882 }
1883
1884 static float
1885 fz_advance_t3_glyph(fz_context *ctx, fz_font *font, int gid)
1886 {
1887 if (gid < 0 || gid > 255)
1888 return 0;
1889 return font->t3widths[gid];
1890 }
1891
1892 void
1893 fz_get_glyph_name(fz_context *ctx, fz_font *font, int glyph, char *buf, int size)
1894 {
1895 FT_Face face = font->ft_face;
1896 if (face)
1897 {
1898 if (FT_HAS_GLYPH_NAMES(face))
1899 {
1900 int fterr;
1901 fz_ft_lock(ctx);
1902 fterr = FT_Get_Glyph_Name(face, glyph, buf, size);
1903 fz_ft_unlock(ctx);
1904 if (fterr)
1905 fz_warn(ctx, "FT_Get_Glyph_Name(%s,%d): %s", font->name, glyph, ft_error_string(fterr));
1906 }
1907 else
1908 fz_snprintf(buf, size, "%d", glyph);
1909 }
1910 else
1911 {
1912 fz_snprintf(buf, size, "%d", glyph);
1913 }
1914 }
1915
1916 float
1917 fz_advance_glyph(fz_context *ctx, fz_font *font, int gid, int wmode)
1918 {
1919 if (font->ft_face)
1920 {
1921 if (wmode)
1922 return fz_advance_ft_glyph(ctx, font, gid, 1);
1923 if (gid >= 0 && gid < font->glyph_count)
1924 {
1925 float f;
1926 int block = gid>>8;
1927 fz_ft_lock(ctx);
1928 if (!font->advance_cache)
1929 {
1930 int n = (font->glyph_count+255)/256;
1931 fz_try(ctx)
1932 font->advance_cache = Memento_label(fz_malloc_array(ctx, n, float *), "font_advance_cache");
1933 fz_catch(ctx)
1934 {
1935 fz_ft_unlock(ctx);
1936 fz_rethrow(ctx);
1937 }
1938 memset(font->advance_cache, 0, n * sizeof(float *));
1939 }
1940 if (!font->advance_cache[block])
1941 {
1942 int i, n;
1943 fz_try(ctx)
1944 font->advance_cache[block] = Memento_label(fz_malloc_array(ctx, 256, float), "font_advance_cache");
1945 fz_catch(ctx)
1946 {
1947 fz_ft_unlock(ctx);
1948 fz_rethrow(ctx);
1949 }
1950 n = (block<<8)+256;
1951 if (n > font->glyph_count)
1952 n = font->glyph_count;
1953 n -= (block<<8);
1954 for (i = 0; i < n; ++i)
1955 font->advance_cache[block][i] = fz_advance_ft_glyph_aux(ctx, font, (block<<8)+i, 0, 1);
1956 }
1957 f = font->advance_cache[block][gid & 255];
1958 fz_ft_unlock(ctx);
1959 return f;
1960 }
1961
1962 return fz_advance_ft_glyph(ctx, font, gid, 0);
1963 }
1964 if (font->t3procs)
1965 return fz_advance_t3_glyph(ctx, font, gid);
1966 return 0;
1967 }
1968
1969 int
1970 fz_encode_character(fz_context *ctx, fz_font *font, int ucs)
1971 {
1972 if (font->ft_face)
1973 {
1974 int idx;
1975 if (ucs >= 0 && ucs < 0x10000)
1976 {
1977 int pg = ucs >> 8;
1978 int ix = ucs & 0xFF;
1979 if (!font->encoding_cache[pg])
1980 {
1981 int i;
1982 font->encoding_cache[pg] = fz_malloc_array(ctx, 256, uint16_t);
1983 fz_ft_lock(ctx);
1984 for (i = 0; i < 256; ++i)
1985 font->encoding_cache[pg][i] = FT_Get_Char_Index(font->ft_face, (pg << 8) + i);
1986 fz_ft_unlock(ctx);
1987 }
1988 return font->encoding_cache[pg][ix];
1989 }
1990 fz_ft_lock(ctx);
1991 idx = FT_Get_Char_Index(font->ft_face, ucs);
1992 fz_ft_unlock(ctx);
1993 return idx;
1994 }
1995 return ucs;
1996 }
1997
1998 int
1999 fz_encode_character_sc(fz_context *ctx, fz_font *font, int unicode)
2000 {
2001 if (font->ft_face)
2002 {
2003 int cat = ucdn_get_general_category(unicode);
2004 if (cat == UCDN_GENERAL_CATEGORY_LL || cat == UCDN_GENERAL_CATEGORY_LT)
2005 {
2006 int glyph;
2007 const char *name;
2008 char buf[20];
2009
2010 name = fz_glyph_name_from_unicode_sc(unicode);
2011 if (name)
2012 {
2013 fz_ft_lock(ctx);
2014 glyph = FT_Get_Name_Index(font->ft_face, (char*)name);
2015 fz_ft_unlock(ctx);
2016 if (glyph > 0)
2017 return glyph;
2018 }
2019
2020 sprintf(buf, "uni%04X.sc", unicode);
2021 fz_ft_lock(ctx);
2022 glyph = FT_Get_Name_Index(font->ft_face, buf);
2023 fz_ft_unlock(ctx);
2024 if (glyph > 0)
2025 return glyph;
2026 }
2027 }
2028 return fz_encode_character(ctx, font, unicode);
2029 }
2030
2031 int
2032 fz_encode_character_by_glyph_name(fz_context *ctx, fz_font *font, const char *glyphname)
2033 {
2034 int glyph = 0;
2035 if (font->ft_face)
2036 {
2037 fz_ft_lock(ctx);
2038 glyph = ft_name_index(font->ft_face, glyphname);
2039 if (glyph == 0)
2040 glyph = ft_char_index(font->ft_face, fz_unicode_from_glyph_name(glyphname));
2041 fz_ft_unlock(ctx);
2042 }
2043 // TODO: type3 fonts (not needed for now)
2044 return glyph;
2045 }
2046
2047 /* FIXME: This should take language too eventually, to allow for fonts where we can select different
2048 * languages using opentype features. */
2049 int
2050 fz_encode_character_with_fallback(fz_context *ctx, fz_font *user_font, int unicode, int script, int language, fz_font **out_font)
2051 {
2052 fz_font *font;
2053 int is_serif = user_font->flags.is_serif;
2054 int is_italic = user_font->flags.is_italic | user_font->flags.fake_italic;
2055 int is_bold = user_font->flags.is_bold | user_font->flags.fake_bold;
2056 int gid;
2057
2058 gid = fz_encode_character(ctx, user_font, unicode);
2059 if (gid > 0)
2060 return *out_font = user_font, gid;
2061
2062 if (script == 0)
2063 script = ucdn_get_script(unicode);
2064
2065 /* Fix for ideographic/halfwidth/fullwidth punctuation forms. */
2066 if ((unicode >= 0x3000 && unicode <= 0x303F) || (unicode >= 0xFF00 && unicode <= 0xFFEF))
2067 {
2068 if (script != UCDN_SCRIPT_HANGUL &&
2069 script != UCDN_SCRIPT_HIRAGANA &&
2070 script != UCDN_SCRIPT_KATAKANA &&
2071 script != UCDN_SCRIPT_BOPOMOFO)
2072 script = UCDN_SCRIPT_HAN;
2073 }
2074
2075 font = fz_load_fallback_font(ctx, script, language, is_serif, is_bold, is_italic);
2076 if (font)
2077 {
2078 gid = fz_encode_character(ctx, font, unicode);
2079 if (gid > 0)
2080 return *out_font = font, gid;
2081 }
2082
2083 #ifndef TOFU_CJK_LANG
2084 if (script == UCDN_SCRIPT_HAN)
2085 {
2086 font = fz_load_fallback_font(ctx, script, FZ_LANG_zh_Hant, is_serif, is_bold, is_italic);
2087 if (font)
2088 {
2089 gid = fz_encode_character(ctx, font, unicode);
2090 if (gid > 0)
2091 return *out_font = font, gid;
2092 }
2093 font = fz_load_fallback_font(ctx, script, FZ_LANG_ja, is_serif, is_bold, is_italic);
2094 if (font)
2095 {
2096 gid = fz_encode_character(ctx, font, unicode);
2097 if (gid > 0)
2098 return *out_font = font, gid;
2099 }
2100 font = fz_load_fallback_font(ctx, script, FZ_LANG_ko, is_serif, is_bold, is_italic);
2101 if (font)
2102 {
2103 gid = fz_encode_character(ctx, font, unicode);
2104 if (gid > 0)
2105 return *out_font = font, gid;
2106 }
2107 font = fz_load_fallback_font(ctx, script, FZ_LANG_zh_Hans, is_serif, is_bold, is_italic);
2108 if (font)
2109 {
2110 gid = fz_encode_character(ctx, font, unicode);
2111 if (gid > 0)
2112 return *out_font = font, gid;
2113 }
2114 }
2115 #endif
2116
2117 font = fz_load_fallback_math_font(ctx);
2118 if (font)
2119 {
2120 gid = fz_encode_character(ctx, font, unicode);
2121 if (gid > 0)
2122 return *out_font = font, gid;
2123 }
2124
2125 font = fz_load_fallback_music_font(ctx);
2126 if (font)
2127 {
2128 gid = fz_encode_character(ctx, font, unicode);
2129 if (gid > 0)
2130 return *out_font = font, gid;
2131 }
2132
2133 font = fz_load_fallback_symbol1_font(ctx);
2134 if (font)
2135 {
2136 gid = fz_encode_character(ctx, font, unicode);
2137 if (gid > 0)
2138 return *out_font = font, gid;
2139 }
2140
2141 font = fz_load_fallback_symbol2_font(ctx);
2142 if (font)
2143 {
2144 gid = fz_encode_character(ctx, font, unicode);
2145 if (gid > 0)
2146 return *out_font = font, gid;
2147 }
2148
2149 font = fz_load_fallback_emoji_font(ctx);
2150 if (font)
2151 {
2152 gid = fz_encode_character(ctx, font, unicode);
2153 if (gid > 0)
2154 return *out_font = font, gid;
2155 }
2156
2157 font = fz_load_fallback_boxes_font(ctx);
2158 if (font)
2159 {
2160 gid = fz_encode_character(ctx, font, unicode);
2161 if (gid > 0)
2162 return *out_font = font, gid;
2163 }
2164
2165 font = fz_new_base14_font(ctx, "Symbol");
2166 if (font)
2167 {
2168 fz_drop_font(ctx, font); /* it's cached in the font context, return a borrowed pointer */
2169 gid = fz_encode_character(ctx, font, unicode);
2170 if (gid > 0)
2171 return *out_font = font, gid;
2172 }
2173
2174 return *out_font = user_font, 0;
2175 }
2176
2177 int fz_font_is_bold(fz_context *ctx, fz_font *font)
2178 {
2179 return font ? font->flags.is_bold : 0;
2180 }
2181
2182 int fz_font_is_italic(fz_context *ctx, fz_font *font)
2183 {
2184 return font ? font->flags.is_italic : 0;
2185 }
2186
2187 int fz_font_is_serif(fz_context *ctx, fz_font *font)
2188 {
2189 return font ? font->flags.is_serif : 0;
2190 }
2191
2192 int fz_font_is_monospaced(fz_context *ctx, fz_font *font)
2193 {
2194 return font ? font->flags.is_mono : 0;
2195 }
2196
2197 const char *fz_font_name(fz_context *ctx, fz_font *font)
2198 {
2199 return font ? font->name : "";
2200 }
2201
2202 fz_buffer **fz_font_t3_procs(fz_context *ctx, fz_font *font)
2203 {
2204 return font ? font->t3procs : NULL;
2205 }
2206
2207 fz_rect fz_font_bbox(fz_context *ctx, fz_font *font)
2208 {
2209 return font->bbox;
2210 }
2211
2212 void *fz_font_ft_face(fz_context *ctx, fz_font *font)
2213 {
2214 return font ? font->ft_face : NULL;
2215 }
2216
2217 fz_font_flags_t *fz_font_flags(fz_font *font)
2218 {
2219 return font ? &font->flags : NULL;
2220 }
2221
2222 fz_shaper_data_t *fz_font_shaper_data(fz_context *ctx, fz_font *font)
2223 {
2224 return font ? &font->shaper_data : NULL;
2225 }
2226
2227 void fz_font_digest(fz_context *ctx, fz_font *font, unsigned char digest[16])
2228 {
2229 if (!font->buffer)
2230 fz_throw(ctx, FZ_ERROR_ARGUMENT, "no font file for digest");
2231 if (!font->has_digest)
2232 {
2233 fz_md5_buffer(ctx, font->buffer, font->digest);
2234 font->has_digest = 1;
2235 }
2236 memcpy(digest, font->digest, 16);
2237 }
2238
2239 #define CHR(a,b,c,d) ((a<<24) | (b<<16) | (c<<8) | d)
2240
2241 typedef struct
2242 {
2243 uint32_t offset;
2244 uint32_t length;
2245 } ttc_block_details_t;
2246
2247 /* The operation of the following is largely based on the operation of
2248 * https://github.com/fontist/extract_ttc/blob/main/ext/stripttc/stripttc.c
2249 * released under a BSD 3-clause license.
2250 */
2251 fz_buffer *
2252 fz_extract_ttf_from_ttc(fz_context *ctx, fz_font *font)
2253 {
2254 fz_stream *stream;
2255 uint32_t tmp;
2256 int i, count;
2257 fz_buffer *buf = NULL;
2258 fz_output *out = NULL;
2259 ttc_block_details_t *bd = NULL;
2260 uint32_t start_pos;
2261 uint32_t csumpos = 0;
2262
2263 if (!font || !font->buffer)
2264 fz_throw(ctx, FZ_ERROR_ARGUMENT, "missing input");
2265
2266 stream = fz_open_buffer(ctx, font->buffer);
2267
2268 fz_var(buf);
2269 fz_var(out);
2270 fz_var(bd);
2271
2272 fz_try(ctx)
2273 {
2274 /* Signature */
2275 if (fz_read_uint32(ctx, stream) != CHR('t','t','c','f'))
2276 fz_throw(ctx, FZ_ERROR_FORMAT, "Not a ttc");
2277
2278 /* Version */
2279 tmp = fz_read_uint32(ctx, stream);
2280 if (tmp != 0x10000 && tmp != 0x20000)
2281 fz_throw(ctx, FZ_ERROR_FORMAT, "Unsupported TTC version");
2282
2283 /* How many subfonts are there? */
2284 tmp = fz_read_uint32(ctx, stream);
2285 if ((uint32_t)font->subfont >= tmp || font->subfont < 0)
2286 fz_throw(ctx, FZ_ERROR_FORMAT, "Bad subfont in TTC");
2287
2288 /* Read through the index table until we get the one for our subfont. */
2289 for (i = 0; i <= font->subfont; i++)
2290 tmp = fz_read_uint32(ctx, stream);
2291
2292 fz_seek(ctx, stream, tmp, SEEK_SET);
2293 buf = fz_new_buffer(ctx, 1);
2294 out = fz_new_output_with_buffer(ctx, buf);
2295
2296 fz_write_uint32_be(ctx, out, fz_read_uint32(ctx, stream)); /* sfnt version */
2297 fz_write_uint16_be(ctx, out, count = fz_read_uint16(ctx, stream)); /* table count */
2298 fz_write_uint16_be(ctx, out, fz_read_uint16(ctx, stream)); /* bsearch header */
2299 fz_write_uint16_be(ctx, out, fz_read_uint16(ctx, stream));
2300 fz_write_uint16_be(ctx, out, fz_read_uint16(ctx, stream));
2301
2302 /* We are currently here... */
2303 start_pos = 4+2+2+2+2;
2304 /* And after we've written the header, we will be here. */
2305 start_pos += count*4*4;
2306 bd = fz_malloc_array(ctx, count, ttc_block_details_t);
2307 for (i = 0; i < count; i++)
2308 {
2309 uint32_t tag;
2310
2311 fz_write_uint32_be(ctx, out, tag = fz_read_uint32(ctx, stream));
2312 fz_write_uint32_be(ctx, out, fz_read_uint32(ctx, stream)); /* checksum */
2313 bd[i].offset = fz_read_uint32(ctx, stream);
2314 fz_write_uint32_be(ctx, out, start_pos);
2315 if (tag == CHR('h','e','a','d'))
2316 csumpos = start_pos + 8;
2317 fz_write_uint32_be(ctx, out, bd[i].length = fz_read_uint32(ctx, stream));
2318 start_pos += (bd[i].length + 3) & ~3;
2319 }
2320
2321 for (i = 0; i < count; i++)
2322 {
2323 uint32_t j;
2324
2325 fz_seek(ctx, stream, bd[i].offset, SEEK_SET);
2326 for (j = 0; j < bd[i].length; j++)
2327 fz_write_byte(ctx, out, fz_read_byte(ctx, stream));
2328 if (bd[i].length & 1)
2329 {
2330 fz_write_byte(ctx, out, 0);
2331 bd[i].length++;
2332 }
2333 if (bd[i].length & 2)
2334 fz_write_uint16_be(ctx, out, 0);
2335 }
2336
2337 fz_close_output(ctx, out);
2338 }
2339 fz_always(ctx)
2340 {
2341 fz_free(ctx, bd);
2342 fz_drop_output(ctx, out);
2343 fz_drop_stream(ctx, stream);
2344 }
2345 fz_catch(ctx)
2346 {
2347 fz_drop_buffer(ctx, buf);
2348 fz_rethrow(ctx);
2349 }
2350
2351 /* Now fixup the checksum */
2352 if (csumpos)
2353 {
2354 unsigned char *data;
2355 uint32_t sum = 0;
2356 uint32_t j;
2357 size_t len = fz_buffer_storage(ctx, buf, &data);
2358
2359 /* First off, blat the old checksum */
2360 memset(data+csumpos, 0, 4);
2361
2362 /* Calculate the new sum. */
2363 for (j = 0; j < len; j += 4)
2364 {
2365 uint32_t v = (data[j]<<24) | (data[j+1]<<16) | (data[j+2]<<8) | (data[j+3]);
2366 sum += v;
2367 }
2368 sum = 0xb1b0afba-sum;
2369
2370 /* Insert it. */
2371 data[csumpos] = sum>>24;
2372 data[csumpos+1] = sum>>16;
2373 data[csumpos+2] = sum>>8;
2374 data[csumpos+3] = sum;
2375 }
2376
2377 return buf;
2378 }
2379
2380 void fz_enumerate_font_cmap(fz_context *ctx, fz_font *font, fz_cmap_callback *cb, void *opaque)
2381 {
2382 unsigned long ucs;
2383 unsigned int gid;
2384
2385 if (font == NULL || font->ft_face == NULL)
2386 return;
2387
2388 fz_ft_lock(ctx);
2389 for (ucs = FT_Get_First_Char(font->ft_face, &gid); gid > 0; ucs = FT_Get_Next_Char(font->ft_face, ucs, &gid))
2390 {
2391 fz_ft_unlock(ctx);
2392 cb(ctx, opaque, ucs, gid);
2393 fz_ft_lock(ctx);
2394 }
2395 fz_ft_unlock(ctx);
2396 }
2397
2398 void fz_calculate_font_ascender_descender(fz_context *ctx, fz_font *font)
2399 {
2400 int i, n;
2401 fz_rect bounds = fz_empty_rect;
2402 fz_matrix trm = { 1, 0, 0, 1, 0, 0 };
2403
2404 if (font == NULL)
2405 return;
2406
2407 if (font->ascdesc_src == FZ_ASCDESC_FROM_BOUNDS)
2408 return;
2409
2410 n = font->glyph_count;
2411 for (i = 0; i < n; i++)
2412 {
2413 bounds = fz_union_rect(bounds, fz_bound_glyph(ctx, font, i, trm));
2414 }
2415
2416 if (bounds.y1 > font->ascender)
2417 font->ascender = bounds.y1;
2418 if (bounds.y0 < font->descender)
2419 font->descender = bounds.y0;
2420 font->ascdesc_src = FZ_ASCDESC_FROM_BOUNDS;
2421 }