Coverage Report

Created: 2025-01-28 06:17

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