Coverage Report

Created: 2023-06-07 06:20

/src/mupdf/source/pdf/pdf-font-add.c
Line
Count
Source (jump to first uncovered line)
1
// Copyright (C) 2004-2021 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/pdf.h"
25
26
#include <ft2build.h>
27
#include FT_FREETYPE_H
28
#ifdef FT_FONT_FORMATS_H
29
#include FT_FONT_FORMATS_H
30
#else
31
#include FT_XFREE86_H
32
#endif
33
#include FT_TRUETYPE_TABLES_H
34
35
#ifndef FT_SFNT_HEAD
36
0
#define FT_SFNT_HEAD ft_sfnt_head
37
#endif
38
39
static int ft_font_file_kind(FT_Face face)
40
351
{
41
351
#ifdef FT_FONT_FORMATS_H
42
351
  const char *kind = FT_Get_Font_Format(face);
43
#else
44
  const char *kind = FT_Get_X11_Font_Format(face);
45
#endif
46
351
  if (!strcmp(kind, "TrueType")) return 2;
47
351
  if (!strcmp(kind, "Type 1")) return 1;
48
351
  if (!strcmp(kind, "CFF")) return 3;
49
0
  if (!strcmp(kind, "CID Type 1")) return 1;
50
0
  return 0;
51
0
}
52
53
static int is_ttc(fz_font *font)
54
0
{
55
0
  if (!font || !font->buffer || font->buffer->len < 4)
56
0
    return 0;
57
0
  return !memcmp(font->buffer->data, "ttcf", 4);
58
0
}
59
60
static int is_truetype(FT_Face face)
61
351
{
62
351
  return ft_font_file_kind(face) == 2;
63
351
}
64
65
static int is_postscript(FT_Face face)
66
0
{
67
0
  int kind = ft_font_file_kind(face);
68
0
  return (kind == 1 || kind == 3);
69
0
}
70
71
static int is_builtin_font(fz_context *ctx, fz_font *font)
72
351
{
73
351
  int size;
74
351
  unsigned char *data;
75
351
  if (!font->buffer)
76
0
    return 0;
77
351
  fz_buffer_storage(ctx, font->buffer, &data);
78
351
  return fz_lookup_base14_font(ctx, pdf_clean_font_name(font->name), &size) == data;
79
351
}
80
81
static pdf_obj*
82
pdf_add_font_file(fz_context *ctx, pdf_document *doc, fz_font *font)
83
0
{
84
0
  fz_buffer *buf = font->buffer;
85
0
  pdf_obj *obj = NULL;
86
0
  pdf_obj *ref = NULL;
87
0
  int drop_buf = 0;
88
89
0
  fz_var(obj);
90
0
  fz_var(ref);
91
92
  /* Check for substitute fonts */
93
0
  if (font->flags.ft_substitute)
94
0
    return NULL;
95
96
0
  if (is_ttc(font))
97
0
  {
98
0
    buf = NULL;
99
0
    drop_buf = 1;
100
0
    buf = fz_extract_ttf_from_ttc(ctx, font);
101
0
  }
102
103
0
  fz_try(ctx)
104
0
  {
105
0
    size_t len = fz_buffer_storage(ctx, buf, NULL);
106
0
    obj = pdf_new_dict(ctx, doc, 3);
107
0
    pdf_dict_put_int(ctx, obj, PDF_NAME(Length1), (int)len);
108
0
    switch (ft_font_file_kind(font->ft_face))
109
0
    {
110
0
    case 1:
111
      /* TODO: these may not be the correct values, but I doubt it matters */
112
0
      pdf_dict_put_int(ctx, obj, PDF_NAME(Length2), len);
113
0
      pdf_dict_put_int(ctx, obj, PDF_NAME(Length3), 0);
114
0
      break;
115
0
    case 2:
116
0
      break;
117
0
    case 3:
118
0
      if (FT_Get_Sfnt_Table(font->ft_face, FT_SFNT_HEAD))
119
0
        pdf_dict_put(ctx, obj, PDF_NAME(Subtype), PDF_NAME(OpenType));
120
0
      else
121
0
        pdf_dict_put(ctx, obj, PDF_NAME(Subtype), PDF_NAME(CIDFontType0C));
122
0
      break;
123
0
    }
124
0
    ref = pdf_add_object(ctx, doc, obj);
125
0
    pdf_update_stream(ctx, doc, ref, buf, 0);
126
0
  }
127
0
  fz_always(ctx)
128
0
  {
129
0
    pdf_drop_obj(ctx, obj);
130
0
    if (drop_buf)
131
0
      fz_drop_buffer(ctx, buf);
132
0
  }
133
0
  fz_catch(ctx)
134
0
  {
135
0
    pdf_drop_obj(ctx, ref);
136
0
    fz_rethrow(ctx);
137
0
  }
138
0
  return ref;
139
0
}
140
141
static void
142
pdf_add_font_descriptor(fz_context *ctx, pdf_document *doc, pdf_obj *fobj, fz_font *font)
143
0
{
144
0
  FT_Face face = font->ft_face;
145
0
  pdf_obj *fdobj = NULL;
146
0
  pdf_obj *fileref;
147
0
  fz_rect bbox;
148
149
0
  fdobj = pdf_new_dict(ctx, doc, 10);
150
0
  fz_try(ctx)
151
0
  {
152
0
    pdf_dict_put(ctx, fdobj, PDF_NAME(Type), PDF_NAME(FontDescriptor));
153
0
    pdf_dict_put_name(ctx, fdobj, PDF_NAME(FontName), font->name);
154
155
0
    bbox.x0 = font->bbox.x0 * 1000;
156
0
    bbox.y0 = font->bbox.y0 * 1000;
157
0
    bbox.x1 = font->bbox.x1 * 1000;
158
0
    bbox.y1 = font->bbox.y1 * 1000;
159
0
    pdf_dict_put_rect(ctx, fdobj, PDF_NAME(FontBBox), bbox);
160
161
0
    pdf_dict_put_int(ctx, fdobj, PDF_NAME(ItalicAngle), 0);
162
0
    pdf_dict_put_int(ctx, fdobj, PDF_NAME(Ascent), face->ascender * 1000.0f / face->units_per_EM);
163
0
    pdf_dict_put_int(ctx, fdobj, PDF_NAME(Descent), face->descender * 1000.0f / face->units_per_EM);
164
0
    pdf_dict_put_int(ctx, fdobj, PDF_NAME(StemV), 80);
165
0
    pdf_dict_put_int(ctx, fdobj, PDF_NAME(Flags), PDF_FD_NONSYMBOLIC);
166
167
0
    fileref = pdf_add_font_file(ctx, doc, font);
168
0
    if (fileref)
169
0
    {
170
0
      switch (ft_font_file_kind(face))
171
0
      {
172
0
      default:
173
0
      case 1: pdf_dict_put_drop(ctx, fdobj, PDF_NAME(FontFile), fileref); break;
174
0
      case 2: pdf_dict_put_drop(ctx, fdobj, PDF_NAME(FontFile2), fileref); break;
175
0
      case 3: pdf_dict_put_drop(ctx, fdobj, PDF_NAME(FontFile3), fileref); break;
176
0
      }
177
0
    }
178
179
0
    pdf_dict_put_drop(ctx, fobj, PDF_NAME(FontDescriptor), pdf_add_object(ctx, doc, fdobj));
180
0
  }
181
0
  fz_always(ctx)
182
0
    pdf_drop_obj(ctx, fdobj);
183
0
  fz_catch(ctx)
184
0
    fz_rethrow(ctx);
185
0
}
186
187
static void
188
pdf_add_simple_font_widths(fz_context *ctx, pdf_document *doc, pdf_obj *fobj, fz_font *font, const char * const encoding[])
189
3
{
190
3
  int width_table[256];
191
3
  pdf_obj *widths;
192
3
  int i, first, last;
193
194
3
  first = 0;
195
3
  last = 0;
196
197
771
  for (i = 0; i < 256; ++i)
198
768
  {
199
768
    int glyph = 0;
200
768
    if (encoding[i])
201
576
    {
202
576
      glyph = fz_encode_character_by_glyph_name(ctx, font, encoding[i]);
203
576
    }
204
768
    if (glyph > 0)
205
546
    {
206
546
      if (!first)
207
3
        first = i;
208
546
      last = i;
209
546
      width_table[i] = fz_advance_glyph(ctx, font, glyph, 0) * 1000;
210
546
    }
211
222
    else
212
222
      width_table[i] = 0;
213
768
  }
214
215
3
  widths = pdf_new_array(ctx, doc, last - first + 1);
216
3
  pdf_dict_put_drop(ctx, fobj, PDF_NAME(Widths), widths);
217
675
  for (i = first; i <= last; ++i)
218
672
    pdf_array_push_int(ctx, widths, width_table[i]);
219
3
  pdf_dict_put_int(ctx, fobj, PDF_NAME(FirstChar), first);
220
3
  pdf_dict_put_int(ctx, fobj, PDF_NAME(LastChar), last);
221
3
}
222
223
static void
224
pdf_add_cid_system_info(fz_context *ctx, pdf_document *doc, pdf_obj *fobj, const char *reg, const char *ord, int supp)
225
63
{
226
63
  pdf_obj *csi = pdf_dict_put_dict(ctx, fobj, PDF_NAME(CIDSystemInfo), 3);
227
63
  pdf_dict_put_string(ctx, csi, PDF_NAME(Registry), reg, strlen(reg));
228
63
  pdf_dict_put_string(ctx, csi, PDF_NAME(Ordering), ord, strlen(ord));
229
63
  pdf_dict_put_int(ctx, csi, PDF_NAME(Supplement), supp);
230
63
}
231
232
/* Different states of starting, same width as last, or consecutive glyph */
233
enum { FW_START = 0, FW_SAME, FW_DIFFER };
234
235
/* ToDo: Ignore the default sized characters */
236
static void
237
pdf_add_cid_font_widths(fz_context *ctx, pdf_document *doc, pdf_obj *fobj, fz_font *font)
238
0
{
239
0
  FT_Face face = font->ft_face;
240
0
  pdf_obj *run_obj = NULL;
241
0
  pdf_obj *fw;
242
0
  int curr_code;
243
0
  int curr_size;
244
0
  int first_code;
245
0
  int state = FW_START;
246
247
0
  fz_var(run_obj);
248
249
0
  fw = pdf_add_new_array(ctx, doc, 10);
250
0
  fz_try(ctx)
251
0
  {
252
0
    curr_code = 0;
253
0
    curr_size = fz_advance_glyph(ctx, font, 0, 0) * 1000;
254
0
    first_code = 0;
255
256
0
    for (curr_code = 1; curr_code < face->num_glyphs; curr_code++)
257
0
    {
258
0
      int prev_size = curr_size;
259
260
0
      curr_size = fz_advance_glyph(ctx, font, curr_code, 0) * 1000;
261
262
      /* So each time around the loop when we reach here, we have sizes
263
       * for curr_code-1 (prev_size) and curr_code (curr_size), neither
264
       * of which have been published yet. By the time we reach the end
265
       * of the loop we must have disposed of prev_size. */
266
0
      switch (state)
267
0
      {
268
0
      case FW_SAME:
269
        /* Until now, we've been in a run of identical values, extending
270
         * from first_code to curr_code-1. If the current and prev sizes
271
         * match, then this now extends from first_code to curr_code and
272
         * we don't need to do anything. If not, we need to flush and
273
         * restart. */
274
0
        if (curr_size != prev_size)
275
0
        {
276
          /* Add three entries. First cid, last cid and width */
277
0
          pdf_array_push_int(ctx, fw, first_code);
278
0
          pdf_array_push_int(ctx, fw, curr_code-1);
279
0
          pdf_array_push_int(ctx, fw, prev_size);
280
          /* And the new first code is our current code. */
281
0
          first_code = curr_code;
282
0
          state = FW_START;
283
0
        }
284
0
        break;
285
0
      case FW_DIFFER:
286
        /* Until now, we've been in a run of differing values, extending
287
         * from first_code to curr_code-1 (though prev_size, the size for
288
         * curr_code-1 has not yet been pushed). */
289
0
        if (curr_size == prev_size)
290
0
        {
291
          /* Same width, so flush the run of differences. */
292
0
          pdf_array_push_int(ctx, fw, first_code);
293
0
          pdf_array_push(ctx, fw, run_obj);
294
0
          pdf_drop_obj(ctx, run_obj);
295
0
          run_obj = NULL;
296
          /* Start a new 'same' entry starting with curr_code-1.
297
           * i.e. the prev size is not put in the run. */
298
0
          state = FW_SAME;
299
0
          first_code = curr_code-1;
300
0
        }
301
0
        else
302
0
        {
303
          /* Continue our differing run by adding prev size to run_obj. */
304
0
          pdf_array_push_int(ctx, run_obj, prev_size);
305
0
        }
306
0
        break;
307
0
      case FW_START:
308
        /* Starting fresh. Determine our state. */
309
0
        if (curr_size == prev_size)
310
0
        {
311
0
          state = FW_SAME;
312
0
        }
313
0
        else
314
0
        {
315
0
          run_obj = pdf_new_array(ctx, doc, 10);
316
0
          pdf_array_push_int(ctx, run_obj, prev_size);
317
0
          state = FW_DIFFER;
318
0
        }
319
0
        break;
320
0
      }
321
0
    }
322
323
    /* So curr_code-1 is the last valid char, and curr_size was its size. */
324
0
    switch (state)
325
0
    {
326
0
    case FW_SAME:
327
      /* We have an unflushed run of same entries. */
328
0
      if (first_code != curr_code-1)
329
0
      {
330
0
        pdf_array_push_int(ctx, fw, first_code);
331
0
        pdf_array_push_int(ctx, fw, curr_code-1);
332
0
        pdf_array_push_int(ctx, fw, curr_size);
333
0
      }
334
0
      break;
335
0
    case FW_DIFFER:
336
      /* We have not yet pushed curr_size to the object. */
337
0
      pdf_array_push_int(ctx, fw, first_code);
338
0
      pdf_array_push_int(ctx, run_obj, curr_size);
339
0
      pdf_array_push(ctx, fw, run_obj);
340
0
      pdf_drop_obj(ctx, run_obj);
341
0
      run_obj = NULL;
342
0
      break;
343
0
    case FW_START:
344
      /* Lone wolf! */
345
0
      pdf_array_push_int(ctx, fw, curr_code-1);
346
0
      pdf_array_push_int(ctx, fw, curr_code-1);
347
0
      pdf_array_push_int(ctx, fw, curr_size);
348
0
      break;
349
0
    }
350
351
0
    if (font->width_table != NULL)
352
0
      pdf_dict_put_int(ctx, fobj, PDF_NAME(DW), font->width_default);
353
0
    if (pdf_array_len(ctx, fw) > 0)
354
0
      pdf_dict_put(ctx, fobj, PDF_NAME(W), fw);
355
0
  }
356
0
  fz_always(ctx)
357
0
  {
358
0
    pdf_drop_obj(ctx, fw);
359
0
    pdf_drop_obj(ctx, run_obj);
360
0
  }
361
0
  fz_catch(ctx)
362
0
    fz_rethrow(ctx);
363
0
}
364
365
/* Descendant font construction used for CID font creation from ttf or Adobe type1 */
366
static pdf_obj*
367
pdf_add_descendant_cid_font(fz_context *ctx, pdf_document *doc, fz_font *font)
368
0
{
369
0
  FT_Face face = font->ft_face;
370
0
  pdf_obj *fobj, *fref;
371
0
  const char *ps_name;
372
373
0
  fobj = pdf_new_dict(ctx, doc, 3);
374
0
  fz_try(ctx)
375
0
  {
376
0
    pdf_dict_put(ctx, fobj, PDF_NAME(Type), PDF_NAME(Font));
377
0
    if (is_truetype(face))
378
0
      pdf_dict_put(ctx, fobj, PDF_NAME(Subtype), PDF_NAME(CIDFontType2));
379
0
    else
380
0
      pdf_dict_put(ctx, fobj, PDF_NAME(Subtype), PDF_NAME(CIDFontType0));
381
382
0
    pdf_add_cid_system_info(ctx, doc, fobj, "Adobe", "Identity", 0);
383
384
0
    ps_name = FT_Get_Postscript_Name(face);
385
0
    if (ps_name)
386
0
      pdf_dict_put_name(ctx, fobj, PDF_NAME(BaseFont), ps_name);
387
0
    else
388
0
      pdf_dict_put_name(ctx, fobj, PDF_NAME(BaseFont), font->name);
389
390
0
    pdf_add_font_descriptor(ctx, doc, fobj, font);
391
392
    /* We may have a cid font already with width info in source font and no cmap in the ft face */
393
0
    pdf_add_cid_font_widths(ctx, doc, fobj, font);
394
395
0
    fref = pdf_add_object(ctx, doc, fobj);
396
0
  }
397
0
  fz_always(ctx)
398
0
    pdf_drop_obj(ctx, fobj);
399
0
  fz_catch(ctx)
400
0
    fz_rethrow(ctx);
401
0
  return fref;
402
0
}
403
404
static int next_range(int *table, int size, int k)
405
0
{
406
0
  int n;
407
0
  for (n = 1; k + n < size; ++n)
408
0
  {
409
0
    if ((k & 0xFF00) != ((k+n) & 0xFF00)) /* high byte changes */
410
0
      break;
411
0
    if (table[k] + n != table[k+n])
412
0
      break;
413
0
  }
414
0
  return n;
415
0
}
416
417
/* Create the ToUnicode CMap. */
418
static void
419
pdf_add_to_unicode(fz_context *ctx, pdf_document *doc, pdf_obj *fobj, fz_font *font)
420
0
{
421
0
  FT_Face face = font->ft_face;
422
0
  fz_buffer *buf;
423
424
0
  int *table;
425
0
  int num_seq = 0;
426
0
  int num_chr = 0;
427
0
  int n, k;
428
429
  /* Populate reverse cmap table */
430
0
  {
431
0
    FT_ULong ucs;
432
0
    FT_UInt gid;
433
434
0
    table = fz_calloc(ctx, face->num_glyphs, sizeof *table);
435
0
    fz_lock(ctx, FZ_LOCK_FREETYPE);
436
0
    ucs = FT_Get_First_Char(face, &gid);
437
0
    while (gid > 0)
438
0
    {
439
0
      if (gid < (FT_ULong)face->num_glyphs && face->num_glyphs > 0)
440
0
        table[gid] = ucs;
441
0
      ucs = FT_Get_Next_Char(face, ucs, &gid);
442
0
    }
443
0
    fz_unlock(ctx, FZ_LOCK_FREETYPE);
444
0
  }
445
446
0
  for (k = 0; k < face->num_glyphs; k += n)
447
0
  {
448
0
    n = next_range(table, face->num_glyphs, k);
449
0
    if (n > 1)
450
0
      ++num_seq;
451
0
    else if (table[k] > 0)
452
0
      ++num_chr;
453
0
  }
454
455
  /* No mappings available... */
456
0
  if (num_seq + num_chr == 0)
457
0
  {
458
0
    fz_warn(ctx, "cannot create ToUnicode mapping for %s", font->name);
459
0
    fz_free(ctx, table);
460
0
    return;
461
0
  }
462
463
0
  buf = fz_new_buffer(ctx, 0);
464
0
  fz_try(ctx)
465
0
  {
466
    /* Header boiler plate */
467
0
    fz_append_string(ctx, buf, "/CIDInit /ProcSet findresource begin\n");
468
0
    fz_append_string(ctx, buf, "12 dict begin\n");
469
0
    fz_append_string(ctx, buf, "begincmap\n");
470
0
    fz_append_string(ctx, buf, "/CIDSystemInfo <</Registry(Adobe)/Ordering(UCS)/Supplement 0>> def\n");
471
0
    fz_append_string(ctx, buf, "/CMapName /Adobe-Identity-UCS def\n");
472
0
    fz_append_string(ctx, buf, "/CMapType 2 def\n");
473
0
    fz_append_string(ctx, buf, "1 begincodespacerange\n");
474
0
    fz_append_string(ctx, buf, "<0000> <FFFF>\n");
475
0
    fz_append_string(ctx, buf, "endcodespacerange\n");
476
477
    /* Note to have a valid CMap, the number of entries in table set can
478
     * not exceed 100, so we have to break into multiple tables. Also, note
479
     * that to reduce the file size we should be looking for sequential
480
     * ranges. Per Adobe technical note #5411, we can't have a range
481
     * cross a boundary where the high order byte changes */
482
483
    /* First the ranges */
484
0
    if (num_seq > 0)
485
0
    {
486
0
      int count = 0;
487
0
      if (num_seq > 100)
488
0
      {
489
0
        fz_append_string(ctx, buf, "100 beginbfrange\n");
490
0
        num_seq -= 100;
491
0
      }
492
0
      else
493
0
        fz_append_printf(ctx, buf, "%d beginbfrange\n", num_seq);
494
0
      for (k = 0; k < face->num_glyphs; k += n)
495
0
      {
496
0
        n = next_range(table, face->num_glyphs, k);
497
0
        if (n > 1)
498
0
        {
499
0
          if (count == 100)
500
0
          {
501
0
            fz_append_string(ctx, buf, "endbfrange\n");
502
0
            if (num_seq > 100)
503
0
            {
504
0
              fz_append_string(ctx, buf, "100 beginbfrange\n");
505
0
              num_seq -= 100;
506
0
            }
507
0
            else
508
0
              fz_append_printf(ctx, buf, "%d beginbfrange\n", num_seq);
509
0
            count = 0;
510
0
          }
511
0
          fz_append_printf(ctx, buf, "<%04x> <%04x> <%04x>\n", k, k+n-1, table[k]);
512
0
          ++count;
513
0
        }
514
0
      }
515
0
      fz_append_string(ctx, buf, "endbfrange\n");
516
0
    }
517
518
    /* Then the singles */
519
0
    if (num_chr > 0)
520
0
    {
521
0
      int count = 0;
522
0
      if (num_chr > 100)
523
0
      {
524
0
        fz_append_string(ctx, buf, "100 beginbfchar\n");
525
0
        num_chr -= 100;
526
0
      }
527
0
      else
528
0
        fz_append_printf(ctx, buf, "%d beginbfchar\n", num_chr);
529
0
      for (k = 0; k < face->num_glyphs; k += n)
530
0
      {
531
0
        n = next_range(table, face->num_glyphs, k);
532
0
        if (n == 1 && table[k] > 0)
533
0
        {
534
0
          if (count == 100)
535
0
          {
536
0
            fz_append_string(ctx, buf, "endbfchar\n");
537
0
            if (num_chr > 100)
538
0
            {
539
0
              fz_append_string(ctx, buf, "100 beginbfchar\n");
540
0
              num_chr -= 100;
541
0
            }
542
0
            else
543
0
              fz_append_printf(ctx, buf, "%d beginbfchar\n", num_chr);
544
0
            count = 0;
545
0
          }
546
0
          fz_append_printf(ctx, buf, "<%04x> <%04x>\n", k, table[k]);
547
0
          ++count;
548
0
        }
549
0
      }
550
0
      fz_append_string(ctx, buf, "endbfchar\n");
551
0
    }
552
553
    /* Trailer boiler plate */
554
0
    fz_append_string(ctx, buf, "endcmap\n");
555
0
    fz_append_string(ctx, buf, "CMapName currentdict /CMap defineresource pop\n");
556
0
    fz_append_string(ctx, buf, "end\nend\n");
557
558
0
    pdf_dict_put_drop(ctx, fobj, PDF_NAME(ToUnicode), pdf_add_stream(ctx, doc, buf, NULL, 0));
559
0
  }
560
0
  fz_always(ctx)
561
0
  {
562
0
    fz_free(ctx, table);
563
0
    fz_drop_buffer(ctx, buf);
564
0
  }
565
0
  fz_catch(ctx)
566
0
    fz_rethrow(ctx);
567
0
}
568
569
pdf_obj *
570
pdf_add_cid_font(fz_context *ctx, pdf_document *doc, fz_font *font)
571
0
{
572
0
  pdf_obj *fobj = NULL;
573
0
  pdf_obj *fref = NULL;
574
0
  pdf_obj *dfonts = NULL;
575
0
  pdf_font_resource_key key;
576
577
0
  fref = pdf_find_font_resource(ctx, doc, PDF_CID_FONT_RESOURCE, 0, font, &key);
578
0
  if (fref)
579
0
    return fref;
580
581
0
  fobj = pdf_add_new_dict(ctx, doc, 10);
582
0
  fz_try(ctx)
583
0
  {
584
0
    pdf_dict_put(ctx, fobj, PDF_NAME(Type), PDF_NAME(Font));
585
0
    pdf_dict_put(ctx, fobj, PDF_NAME(Subtype), PDF_NAME(Type0));
586
0
    pdf_dict_put_name(ctx, fobj, PDF_NAME(BaseFont), font->name);
587
0
    pdf_dict_put(ctx, fobj, PDF_NAME(Encoding), PDF_NAME(Identity_H));
588
0
    pdf_add_to_unicode(ctx, doc, fobj, font);
589
590
0
    dfonts = pdf_dict_put_array(ctx, fobj, PDF_NAME(DescendantFonts), 1);
591
0
    pdf_array_push_drop(ctx, dfonts, pdf_add_descendant_cid_font(ctx, doc, font));
592
593
0
    fref = pdf_insert_font_resource(ctx, doc, &key, fobj);
594
0
  }
595
0
  fz_always(ctx)
596
0
    pdf_drop_obj(ctx, fobj);
597
0
  fz_catch(ctx)
598
0
    fz_rethrow(ctx);
599
0
  return fref;
600
0
}
601
602
/* Create simple (8-bit encoding) fonts */
603
604
static void
605
pdf_add_simple_font_encoding_imp(fz_context *ctx, pdf_document *doc, pdf_obj *font, const char *glyph_names[])
606
3
{
607
3
  pdf_obj *enc, *diff;
608
3
  int i, last;
609
610
3
  enc = pdf_dict_put_dict(ctx, font, PDF_NAME(Encoding), 2);
611
3
  pdf_dict_put(ctx, enc, PDF_NAME(BaseEncoding), PDF_NAME(WinAnsiEncoding));
612
3
  diff = pdf_dict_put_array(ctx, enc, PDF_NAME(Differences), 129);
613
3
  last = 0;
614
387
  for (i = 128; i < 256; ++i)
615
384
  {
616
384
    const char *glyph = glyph_names[i];
617
384
    if (glyph)
618
288
    {
619
288
      if (last != i-1)
620
24
        pdf_array_push_int(ctx, diff, i);
621
288
      last = i;
622
288
      pdf_array_push_name(ctx, diff, glyph);
623
288
    }
624
384
  }
625
3
}
626
627
static void
628
pdf_add_simple_font_encoding(fz_context *ctx, pdf_document *doc, pdf_obj *fobj, int encoding)
629
351
{
630
351
  switch (encoding)
631
351
  {
632
0
  default:
633
348
  case PDF_SIMPLE_ENCODING_LATIN:
634
348
    pdf_dict_put(ctx, fobj, PDF_NAME(Encoding), PDF_NAME(WinAnsiEncoding));
635
348
    break;
636
0
  case PDF_SIMPLE_ENCODING_GREEK:
637
0
    pdf_add_simple_font_encoding_imp(ctx, doc, fobj, fz_glyph_name_from_iso8859_7);
638
0
    break;
639
3
  case PDF_SIMPLE_ENCODING_CYRILLIC:
640
3
    pdf_add_simple_font_encoding_imp(ctx, doc, fobj, fz_glyph_name_from_koi8u);
641
3
    break;
642
351
  }
643
351
}
644
645
pdf_obj *
646
pdf_add_simple_font(fz_context *ctx, pdf_document *doc, fz_font *font, int encoding)
647
6.46k
{
648
6.46k
  FT_Face face = font->ft_face;
649
6.46k
  pdf_obj *fobj = NULL;
650
6.46k
  pdf_obj *fref = NULL;
651
6.46k
  const char **enc;
652
6.46k
  pdf_font_resource_key key;
653
654
6.46k
  fref = pdf_find_font_resource(ctx, doc, PDF_SIMPLE_FONT_RESOURCE, encoding, font, &key);
655
6.46k
  if (fref)
656
6.11k
    return fref;
657
658
351
  switch (encoding)
659
351
  {
660
0
  default:
661
348
  case PDF_SIMPLE_ENCODING_LATIN: enc = fz_glyph_name_from_windows_1252; break;
662
0
  case PDF_SIMPLE_ENCODING_GREEK: enc = fz_glyph_name_from_iso8859_7; break;
663
3
  case PDF_SIMPLE_ENCODING_CYRILLIC: enc = fz_glyph_name_from_koi8u; break;
664
351
  }
665
666
351
  fobj = pdf_add_new_dict(ctx, doc, 10);
667
702
  fz_try(ctx)
668
702
  {
669
351
    pdf_dict_put(ctx, fobj, PDF_NAME(Type), PDF_NAME(Font));
670
351
    if (is_truetype(face))
671
0
      pdf_dict_put(ctx, fobj, PDF_NAME(Subtype), PDF_NAME(TrueType));
672
351
    else
673
351
      pdf_dict_put(ctx, fobj, PDF_NAME(Subtype), PDF_NAME(Type1));
674
675
351
    if (!is_builtin_font(ctx, font))
676
0
    {
677
0
      const char *ps_name = FT_Get_Postscript_Name(face);
678
0
      if (!ps_name)
679
0
        ps_name = font->name;
680
0
      pdf_dict_put_name(ctx, fobj, PDF_NAME(BaseFont), ps_name);
681
0
      pdf_add_simple_font_encoding(ctx, doc, fobj, encoding);
682
0
      pdf_add_simple_font_widths(ctx, doc, fobj, font, enc);
683
0
      pdf_add_font_descriptor(ctx, doc, fobj, font);
684
0
    }
685
351
    else
686
351
    {
687
351
      pdf_dict_put_name(ctx, fobj, PDF_NAME(BaseFont), pdf_clean_font_name(font->name));
688
351
      pdf_add_simple_font_encoding(ctx, doc, fobj, encoding);
689
351
      if (encoding != PDF_SIMPLE_ENCODING_LATIN)
690
3
        pdf_add_simple_font_widths(ctx, doc, fobj, font, enc);
691
351
    }
692
693
351
    fref = pdf_insert_font_resource(ctx, doc, &key, fobj);
694
351
  }
695
702
  fz_always(ctx)
696
351
  {
697
351
    pdf_drop_obj(ctx, fobj);
698
351
  }
699
351
  fz_catch(ctx)
700
0
    fz_rethrow(ctx);
701
351
  return fref;
702
351
}
703
704
int
705
pdf_font_writing_supported(fz_font *font)
706
0
{
707
0
  if (font->ft_face == NULL || font->buffer == NULL || font->buffer->len < 4 || !font->flags.embed || font->flags.never_embed)
708
0
    return 0;
709
0
  if (is_ttc(font))
710
0
    return 1;
711
0
  if (is_truetype(font->ft_face))
712
0
    return 1;
713
0
  if (is_postscript(font->ft_face))
714
0
    return 1;
715
0
  return 0;
716
0
}
717
718
pdf_obj *
719
pdf_add_cjk_font(fz_context *ctx, pdf_document *doc, fz_font *fzfont, int script, int wmode, int serif)
720
63
{
721
63
  pdf_obj *fref, *font, *subfont, *fontdesc;
722
63
  pdf_obj *dfonts;
723
63
  fz_rect bbox = { -200, -200, 1200, 1200 };
724
63
  pdf_font_resource_key key;
725
63
  int flags;
726
727
63
  const char *basefont, *encoding, *ordering;
728
63
  int supplement;
729
730
63
  switch (script)
731
63
  {
732
0
  default:
733
0
    script = FZ_ADOBE_CNS;
734
    /* fall through */
735
19
  case FZ_ADOBE_CNS: /* traditional chinese */
736
19
    basefont = serif ? "Ming" : "Fangti";
737
19
    encoding = wmode ? "UniCNS-UTF16-V" : "UniCNS-UTF16-H";
738
19
    ordering = "CNS1";
739
19
    supplement = 7;
740
19
    break;
741
0
  case FZ_ADOBE_GB: /* simplified chinese */
742
0
    basefont = serif ? "Song" : "Heiti";
743
0
    encoding = wmode ? "UniGB-UTF16-V" : "UniGB-UTF16-H";
744
0
    ordering = "GB1";
745
0
    supplement = 5;
746
0
    break;
747
26
  case FZ_ADOBE_JAPAN:
748
26
    basefont = serif ? "Mincho" : "Gothic";
749
26
    encoding = wmode ? "UniJIS-UTF16-V" : "UniJIS-UTF16-H";
750
26
    ordering = "Japan1";
751
26
    supplement = 6;
752
26
    break;
753
18
  case FZ_ADOBE_KOREA:
754
18
    basefont = serif ? "Batang" : "Dotum";
755
18
    encoding = wmode ? "UniKS-UTF16-V" : "UniKS-UTF16-H";
756
18
    ordering = "Korea1";
757
18
    supplement = 2;
758
18
    break;
759
63
  }
760
761
63
  flags = PDF_FD_SYMBOLIC;
762
63
  if (serif)
763
63
    flags |= PDF_FD_SERIF;
764
765
63
  fref = pdf_find_font_resource(ctx, doc, PDF_CJK_FONT_RESOURCE, script, fzfont, &key);
766
63
  if (fref)
767
0
    return fref;
768
769
63
  font = pdf_add_new_dict(ctx, doc, 5);
770
126
  fz_try(ctx)
771
126
  {
772
63
    pdf_dict_put(ctx, font, PDF_NAME(Type), PDF_NAME(Font));
773
63
    pdf_dict_put(ctx, font, PDF_NAME(Subtype), PDF_NAME(Type0));
774
63
    pdf_dict_put_name(ctx, font, PDF_NAME(BaseFont), basefont);
775
63
    pdf_dict_put_name(ctx, font, PDF_NAME(Encoding), encoding);
776
63
    dfonts = pdf_dict_put_array(ctx, font, PDF_NAME(DescendantFonts), 1);
777
63
    pdf_array_push_drop(ctx, dfonts, subfont = pdf_add_new_dict(ctx, doc, 5));
778
63
    {
779
63
      pdf_dict_put(ctx, subfont, PDF_NAME(Type), PDF_NAME(Font));
780
63
      pdf_dict_put(ctx, subfont, PDF_NAME(Subtype), PDF_NAME(CIDFontType0));
781
63
      pdf_dict_put_name(ctx, subfont, PDF_NAME(BaseFont), basefont);
782
63
      pdf_add_cid_system_info(ctx, doc, subfont, "Adobe", ordering, supplement);
783
63
      fontdesc = pdf_add_new_dict(ctx, doc, 8);
784
63
      pdf_dict_put_drop(ctx, subfont, PDF_NAME(FontDescriptor), fontdesc);
785
63
      {
786
63
        pdf_dict_put(ctx, fontdesc, PDF_NAME(Type), PDF_NAME(FontDescriptor));
787
63
        pdf_dict_put_text_string(ctx, fontdesc, PDF_NAME(FontName), basefont);
788
63
        pdf_dict_put_rect(ctx, fontdesc, PDF_NAME(FontBBox), bbox);
789
63
        pdf_dict_put_int(ctx, fontdesc, PDF_NAME(Flags), flags);
790
63
        pdf_dict_put_int(ctx, fontdesc, PDF_NAME(ItalicAngle), 0);
791
63
        pdf_dict_put_int(ctx, fontdesc, PDF_NAME(Ascent), 1000);
792
63
        pdf_dict_put_int(ctx, fontdesc, PDF_NAME(Descent), -200);
793
63
        pdf_dict_put_int(ctx, fontdesc, PDF_NAME(StemV), 80);
794
63
      }
795
63
    }
796
797
63
    fref = pdf_insert_font_resource(ctx, doc, &key, font);
798
63
  }
799
126
  fz_always(ctx)
800
63
    pdf_drop_obj(ctx, font);
801
63
  fz_catch(ctx)
802
0
    fz_rethrow(ctx);
803
804
63
  return fref;
805
63
}
806
807
pdf_obj *
808
pdf_add_substitute_font(fz_context *ctx, pdf_document *doc, fz_font *font)
809
0
{
810
0
  fz_throw(ctx, FZ_ERROR_GENERIC, "substitute font creation is not implemented yet");
811
0
  return NULL;
812
0
}