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