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