~ubuntu-branches/ubuntu/jaunty/texlive-bin/jaunty

« back to all changes in this revision

Viewing changes to build/source/texk/xdvipdfmx/src/truetype.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2008-06-26 23:14:59 UTC
  • mfrom: (2.1.30 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080626231459-y02rjsrgtafu83yr
Tags: 2007.dfsg.2-3
add missing source roadmap.fig of roadmap.eps in fontinst documentation
(Closes: #482915) (urgency medium due to RC bug)
(new patch add-missing-fontinst-source)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  $Header: /home/cvsroot/dvipdfmx/src/truetype.c,v 1.5 2005/12/29 04:07:04 chofchof Exp $
 
2
    
 
3
    This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
 
4
 
 
5
    Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
 
6
    the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
 
7
    
 
8
    This program is free software; you can redistribute it and/or modify
 
9
    it under the terms of the GNU General Public License as published by
 
10
    the Free Software Foundation; either version 2 of the License, or
 
11
    (at your option) any later version.
 
12
    
 
13
    This program is distributed in the hope that it will be useful,
 
14
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
    GNU General Public License for more details.
 
17
    
 
18
    You should have received a copy of the GNU General Public License
 
19
    along with this program; if not, write to the Free Software
 
20
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 
21
*/
 
22
 
 
23
 
 
24
#if HAVE_CONFIG_H
 
25
#include "config.h"
 
26
#endif
 
27
 
 
28
#include "system.h"
 
29
 
 
30
#include "numbers.h"
 
31
#include "error.h"
 
32
#include "mem.h"
 
33
 
 
34
#include "dpxfile.h"
 
35
#include "dpxutil.h"
 
36
 
 
37
#include "pdfobj.h"
 
38
#include "pdfresource.h"
 
39
#include "pdffont.h"
 
40
 
 
41
#include "pdfencoding.h"
 
42
#include "unicode.h"
 
43
#include "agl.h"
 
44
 
 
45
/* TrueType */
 
46
#include "sfnt.h"
 
47
#include "tt_cmap.h"
 
48
#include "tt_table.h"
 
49
#include "tt_glyf.h"
 
50
#include "tt_post.h"
 
51
#include "tt_gsub.h"
 
52
#include "tt_aux.h"
 
53
 
 
54
#include "truetype.h"
 
55
 
 
56
/* Modifying this has no effect :P */
 
57
#ifdef ENABLE_NOEMBED
 
58
#  undef ENABLE_NOEMBED
 
59
#endif
 
60
 
 
61
int
 
62
pdf_font_open_truetype (pdf_font *font)
 
63
{
 
64
  char     *ident;
 
65
  int       encoding_id;
 
66
  pdf_obj  *fontdict, *descriptor;
 
67
  sfnt     *sfont;
 
68
  int       embedding = 1; /* Must be embedded. */
 
69
  FILE     *fp = NULL;
 
70
  int       length, error = 0;
 
71
 
 
72
  ASSERT( font );
 
73
 
 
74
  ident = pdf_font_get_ident(font);
 
75
 
 
76
  ASSERT( ident );
 
77
 
 
78
#ifdef XETEX
 
79
  sfont = sfnt_open(pdf_font_get_ft_face(font), SFNT_TYPE_TTC | SFNT_TYPE_TRUETYPE);
 
80
  if (!sfont)
 
81
    return -1;
 
82
#else
 
83
  fp = DPXFOPEN(ident, DPX_RES_TYPE_TTFONT);
 
84
  if (!fp)
 
85
    return  -1;
 
86
 
 
87
  sfont = sfnt_open(fp);
 
88
#endif
 
89
  if (!sfont) {
 
90
    WARN("Could not open TrueType font: %s", ident);
 
91
    if (fp)
 
92
      DPXFCLOSE(fp);
 
93
    return  -1;
 
94
  }
 
95
 
 
96
  if (sfont->type == SFNT_TYPE_TTC)
 
97
    error = sfnt_read_table_directory(sfont, ttc_read_offset(sfont, 0));
 
98
  else
 
99
    error = sfnt_read_table_directory(sfont, 0);
 
100
  if (error) {
 
101
    sfnt_close(sfont);
 
102
    if (fp)
 
103
      DPXFCLOSE(fp);
 
104
    return  -1; /* Silently */
 
105
  }
 
106
 
 
107
  /* Reading fontdict before checking fonttype conflicts with PKFONT
 
108
   * because pdf_font_get_resource() always makes a dictionary.
 
109
   */
 
110
  encoding_id = pdf_font_get_encoding(font);
 
111
  fontdict    = pdf_font_get_resource(font);
 
112
  descriptor  = pdf_font_get_descriptor(font);
 
113
#ifdef  ENABLE_NOEMBED
 
114
  embedding   = pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED) ? 0 : 1;
 
115
#endif /* ENABLE_NOEMBED */
 
116
 
 
117
  ASSERT( fontdict && descriptor );
 
118
 
 
119
  {
 
120
    pdf_obj  *tmp;
 
121
    tmp  = tt_get_fontdesc(sfont, &embedding, 1);
 
122
    if (!tmp) {
 
123
      ERROR("Could not obtain neccesary font info.");
 
124
      sfnt_close(sfont);
 
125
      if (fp)
 
126
        DPXFCLOSE(fp);
 
127
      return  -1;
 
128
    }
 
129
    ASSERT(pdf_obj_typeof(tmp) == PDF_DICT);
 
130
 
 
131
    pdf_merge_dict(descriptor, tmp);
 
132
    pdf_release_obj(tmp);
 
133
  }
 
134
 
 
135
  if (!embedding) {
 
136
    if (encoding_id >= 0 &&
 
137
        !pdf_encoding_is_predefined(encoding_id)) {
 
138
      ERROR("Custum encoding not allowed for non-embedded TrueType font.");
 
139
      sfnt_close(sfont);
 
140
      return -1;
 
141
    } else {
 
142
      /* There are basically no guarantee for font substitution
 
143
       * can work with "symblic" fonts. At least all glyphs
 
144
       * contained in the font must be identified; glyphs covers
 
145
       * by this instance of font should contain glyphs only from
 
146
       * Adobe Standard Latin Set. We allow non-embedded font
 
147
       * only to predefined encodings for this reason. Note that
 
148
       * "builtin" encoding means "MacRoman" here.
 
149
       */
 
150
      pdf_obj  *tmp;
 
151
      long      flags;
 
152
 
 
153
#ifndef  ENABLE_NOEMBED
 
154
      ERROR("Font file=\"%s\" can't be embedded due to liscence restrictions.", ident);
 
155
#endif /* ENABLE_NOEMBED */
 
156
      pdf_font_set_flags(font, PDF_FONT_FLAG_NOEMBED);
 
157
      tmp = pdf_lookup_dict(descriptor, "Flags");
 
158
      if (tmp && pdf_obj_typeof(tmp) == PDF_NUMBER) {
 
159
        flags  = (long) pdf_number_value(tmp);
 
160
        flags &= (1 << 2); /* clear Symbolic */
 
161
        flags |= (1 << 5); /* set Nonsymbolic */
 
162
        pdf_add_dict(descriptor, pdf_new_name("Flags"), pdf_new_number(flags));
 
163
      }
 
164
    }
 
165
  }
 
166
 
 
167
  {
 
168
    char  fontname[256];
 
169
    int   n;
 
170
 
 
171
    memset(fontname, 0, 256);
 
172
    length = tt_get_ps_fontname(sfont, fontname, 255);
 
173
    if (length < 1) {
 
174
      length = MIN(strlen(ident), 255);
 
175
      strncpy(fontname, ident, length);
 
176
    }
 
177
    fontname[length] = '\0';
 
178
    for (n = 0; n < length; n++) {
 
179
      if (fontname[n] == 0) {
 
180
        memmove(fontname + n, fontname + n + 1, length - n - 1);
 
181
      }
 
182
    }
 
183
    if (strlen(fontname) == 0)
 
184
      ERROR("Can't find valid fontname for \"%s\".", ident);
 
185
    pdf_font_set_fontname(font, fontname);
 
186
  }
 
187
 
 
188
  sfnt_close(sfont);
 
189
  if (fp)
 
190
    DPXFCLOSE(fp);
 
191
 
 
192
  pdf_add_dict(fontdict,
 
193
               pdf_new_name("Type"),    pdf_new_name("Font"));
 
194
  pdf_add_dict(fontdict,
 
195
               pdf_new_name("Subtype"), pdf_new_name("TrueType"));
 
196
 
 
197
  /*
 
198
   * We use MacRoman as "default" encoding.
 
199
   */
 
200
  if (encoding_id >= 0)
 
201
    pdf_add_dict(fontdict,
 
202
                 pdf_new_name("Encoding"),
 
203
                 pdf_new_name(pdf_encoding_get_name(encoding_id)));
 
204
  else {
 
205
    pdf_add_dict(fontdict,
 
206
                 pdf_new_name("Encoding"),
 
207
                 pdf_new_name("MacRomanEncoding"));
 
208
  }
 
209
 
 
210
  return  0;
 
211
}
 
212
 
 
213
/*
 
214
 * The 'name' table should be preserved since it contains copyright
 
215
 * information, but it might cause problem when there are invalid
 
216
 * table entries (wrongly encoded text which is often the case in
 
217
 * CJK fonts). Acrobat does not use 'name' table. Unicode TrueType
 
218
 * fonts may have 10K bytes 'name' table...
 
219
 *
 
220
 * We preserve the 'OS/2' table too, since it contains the license
 
221
 * information. PDF applications should use this table to decide
 
222
 * whether the font is embedded only for the purpose of preview &
 
223
 * printing. Otherwise, we must encrypt the document. Acrobat does
 
224
 * not use 'OS/2' table, though...
 
225
 */
 
226
static struct
 
227
{
 
228
  const char *name;
 
229
  int   must_exist;
 
230
} required_table[] = {
 
231
  {"OS/2", 1}, {"head", 1}, {"hhea", 1}, {"loca", 1}, {"maxp", 1},
 
232
  {"name", 1}, {"glyf", 1}, {"hmtx", 1}, {"fpgm", 0}, {"cvt ", 0},
 
233
  {"prep", 0}, {"cmap", 1}, {NULL, 0}
 
234
};
 
235
 
 
236
static void
 
237
do_widths (pdf_font *font, double *widths)
 
238
{
 
239
  pdf_obj  *fontdict  = pdf_font_get_resource (font);
 
240
  char     *usedchars = pdf_font_get_usedchars(font);
 
241
  pdf_obj  *tmparray;
 
242
  int       code, firstchar, lastchar;
 
243
 
 
244
  firstchar = 255; lastchar = 0;
 
245
  for (code = 0; code < 256; code++) {
 
246
    if (usedchars[code]) {
 
247
      if (code < firstchar) firstchar = code;
 
248
      if (code > lastchar)  lastchar  = code;
 
249
    }
 
250
  }
 
251
  if (firstchar > lastchar) {
 
252
    WARN("No glyphs actually used???");
 
253
    return;
 
254
  }
 
255
 
 
256
  tmparray = pdf_new_array();
 
257
  for (code = firstchar; code <= lastchar; code++) {
 
258
    if (usedchars[code])
 
259
      pdf_add_array(tmparray,
 
260
                    pdf_new_number(ROUND(widths[code], 1)));
 
261
    else {
 
262
      pdf_add_array(tmparray, pdf_new_number(0.0));
 
263
    }
 
264
  }
 
265
  if (pdf_array_length(tmparray) > 0) {
 
266
    pdf_add_dict(fontdict,
 
267
                 pdf_new_name("Widths"), pdf_ref_obj(tmparray)); /* _FIXME_ */
 
268
  }
 
269
  pdf_release_obj(tmparray);
 
270
  pdf_add_dict(fontdict,
 
271
               pdf_new_name("FirstChar"), pdf_new_number(firstchar));
 
272
  pdf_add_dict(fontdict,
 
273
               pdf_new_name("LastChar"),  pdf_new_number(lastchar));
 
274
 
 
275
  return;
 
276
}
 
277
 
 
278
static int verbose = 0;
 
279
 
 
280
#define PDFUNIT(v) ((double) (ROUND(1000.0*(v)/(glyphs->emsize), 1)))
 
281
 
 
282
/*
 
283
 * There are several issues in TrueType font support in PDF.
 
284
 * How PDF viewers select TrueType cmap table is not so clear.
 
285
 * Most reliable way seem to reencode font and sort glyphs as
 
286
 * charcode == gid and to use Mac-Roman format 0 subtable.
 
287
 * It does not work with encodings that uses full 256 range since
 
288
 * GID = 0 is reserved for .notdef, so GID = 256 is not accessible.
 
289
 */
 
290
static int
 
291
do_builtin_encoding (pdf_font *font, const char *usedchars, sfnt *sfont)
 
292
{
 
293
  struct tt_glyphs *glyphs;
 
294
  char             *cmap_table;
 
295
  tt_cmap          *ttcm;
 
296
  USHORT            gid, idx;
 
297
  int               code, count;
 
298
  double            widths[256];
 
299
 
 
300
  ttcm = tt_cmap_read(sfont, TT_MAC, TT_MAC_ROMAN);
 
301
  if (!ttcm) {
 
302
    WARN("Could not read Mac-Roman TrueType cmap table...");
 
303
    return  -1;
 
304
  }
 
305
 
 
306
  cmap_table = NEW(274, char);
 
307
  memset(cmap_table, 0, 274);
 
308
  sfnt_put_ushort(cmap_table,    0);            /* Version  */
 
309
  sfnt_put_ushort(cmap_table+2,  1);            /* Number of subtables */
 
310
  sfnt_put_ushort(cmap_table+4,  TT_MAC);       /* Platform ID */
 
311
  sfnt_put_ushort(cmap_table+6,  TT_MAC_ROMAN); /* Encoding ID */
 
312
  sfnt_put_ulong (cmap_table+8,  12);           /* Offset   */
 
313
  sfnt_put_ushort(cmap_table+12, 0);            /* Format   */
 
314
  sfnt_put_ushort(cmap_table+14, 262);          /* Length   */
 
315
  sfnt_put_ushort(cmap_table+16, 0);            /* Language */
 
316
 
 
317
  glyphs = tt_build_init();
 
318
 
 
319
  if (verbose > 2)
 
320
    MESG("[glyphs:/.notdef");
 
321
 
 
322
  count = 1; /* .notdef */
 
323
  for (code = 0; code < 256; code++) {
 
324
    if (!usedchars[code])
 
325
      continue;
 
326
 
 
327
    if (verbose > 2)
 
328
      MESG("/.c0x%02x", code);
 
329
 
 
330
    gid = tt_cmap_lookup(ttcm, code);
 
331
    if (gid == 0) {
 
332
      WARN("Glyph for character code=0x%02x missing in font font-file=\"%s\".",
 
333
           code, pdf_font_get_ident(font));
 
334
      idx = 0;
 
335
    } else {
 
336
      idx = tt_find_glyph(glyphs, gid);
 
337
      if (idx == 0)
 
338
        idx  = tt_add_glyph(glyphs, gid, count); /* count returned. */
 
339
    }
 
340
    cmap_table[18+code] = idx & 0xff; /* bug here */
 
341
    count++;
 
342
  }
 
343
  tt_cmap_release(ttcm);
 
344
 
 
345
  if (verbose > 2)
 
346
    MESG("]");
 
347
 
 
348
  if (tt_build_tables(sfont, glyphs) < 0) {
 
349
    WARN("Packing TrueType font into SFNT failed!");
 
350
    tt_build_finish(glyphs);
 
351
    RELEASE(cmap_table);
 
352
    return  -1;
 
353
  }
 
354
 
 
355
  for (code = 0; code < 256; code++) {
 
356
    if (usedchars[code]) {
 
357
      idx = tt_get_index(glyphs, (USHORT) cmap_table[18+code]);
 
358
      widths[code] = PDFUNIT(glyphs->gd[idx].advw);
 
359
    } else {
 
360
      widths[code] = 0.0;
 
361
    }
 
362
  }
 
363
  do_widths(font, widths);
 
364
 
 
365
  if (verbose > 1) 
 
366
    MESG("[%d glyphs]", glyphs->num_glyphs);
 
367
 
 
368
  tt_build_finish(glyphs);
 
369
 
 
370
  sfnt_set_table(sfont, "cmap", cmap_table, 274);
 
371
 
 
372
  return  0;
 
373
}
 
374
 
 
375
/* Order of lookup should be
 
376
 *  post, unicode+otl
 
377
 */
 
378
struct glyph_mapper
 
379
{
 
380
  tt_cmap  *codetogid;
 
381
  otl_gsub *gsub;
 
382
  sfnt     *sfont;
 
383
  struct tt_post_table *nametogid;
 
384
};
 
385
 
 
386
 
 
387
/* WARNING: This modifies glyphname itself */
 
388
static int
 
389
agl_decompose_glyphname (char *glyphname, char **nptrs, int size, char **suffix)
 
390
{
 
391
  char  *q, *p = glyphname;
 
392
  int    n;
 
393
 
 
394
  q = strchr(p, '.'); /* chop every thing after *first* dot */
 
395
  if (!q)
 
396
    *suffix = NULL;
 
397
  else {
 
398
    *q = '\0'; q++;
 
399
    *suffix = q;
 
400
  }
 
401
 
 
402
  nptrs[0] = p;
 
403
  for (n = 1; p && *p; n++) {
 
404
    p = strchr(p, '_');
 
405
    if (!p || p[1] == '\0')
 
406
      break;
 
407
    if (n >= size)
 
408
      ERROR("Uh ah..."); /* _FIXME_ */
 
409
    *p = '\0'; p++;
 
410
    nptrs[n] = p;
 
411
  }
 
412
 
 
413
  return  n;
 
414
}
 
415
 
 
416
static int
 
417
select_gsub (const char *feat, struct glyph_mapper *gm)
 
418
{
 
419
  int    idx, error = 0;
 
420
 
 
421
  if (!feat || *feat == 0 || !gm || !gm->gsub)
 
422
    return  -1;
 
423
 
 
424
  /* First treat as is */
 
425
  idx = otl_gsub_select(gm->gsub, "*", "*", feat);
 
426
  if (idx >= 0)
 
427
    return  0;
 
428
 
 
429
  if (verbose > 1)
 
430
    MESG("\ntrutype>> Try loading OTL GSUB for \"*.*.%s\"...", feat);
 
431
  error = otl_gsub_add_feat(gm->gsub, "*", "*", feat, gm->sfont);
 
432
  if (!error) {
 
433
    idx = otl_gsub_select(gm->gsub, "*", "*", feat);
 
434
    return  (idx >= 0 ? 0 : -1);
 
435
  }
 
436
 
 
437
  return  -1;
 
438
}
 
439
 
 
440
static int findparanoiac (const char *glyph_name, USHORT *gid, struct glyph_mapper *gm);
 
441
static int resolve_glyph (const char *glyph_name, USHORT *gid, struct glyph_mapper *gm);
 
442
 
 
443
/* Apply GSUB. This is a bit tricky... */
 
444
static int
 
445
selectglyph (USHORT in, const char *suffix, struct glyph_mapper *gm, USHORT *out)
 
446
{
 
447
  char  *s, *q, t[5];
 
448
  int    n, error = 0;
 
449
 
 
450
  ASSERT(suffix && gm && out);
 
451
  ASSERT(suffix && *suffix != 0);
 
452
 
 
453
  s = NEW(strlen(suffix) + 1, char);
 
454
  strcpy(s, suffix);
 
455
 
 
456
  /* First try converting suffix to feature tag.
 
457
   * agl.c currently only knows less ambiguos cases;
 
458
   * e.g., 'sc', 'superior', etc.
 
459
   */
 
460
  q = (char *) agl_suffix_to_otltag(s);
 
461
  if (q) { /* We found feature tag for 'suffix'. */
 
462
    error = select_gsub(q, gm); /* no fallback for this */
 
463
    if (!error)
 
464
      error = otl_gsub_apply(gm->gsub, &in);
 
465
  } else { /* 'suffix' may represent feature tag. */
 
466
    /* Try loading GSUB only when length of 'suffix' is less
 
467
     * than or equal to 4. tt_gsub give a warning otherwise.
 
468
     */
 
469
    if (strlen(s) > 4)
 
470
      error = -1; /* Uh */
 
471
    else if (strlen(s) == 4)
 
472
      error = select_gsub(s, gm);
 
473
    else { /* less than 4. pad ' '. */
 
474
      memset(t, ' ', 4); t[4] = '\0';
 
475
      memcpy(t, s, strlen(s));
 
476
      error = select_gsub(t, gm);
 
477
    }
 
478
    if (!error) /* 'suffix' represents feature tag. */
 
479
      error = otl_gsub_apply(gm->gsub, &in);
 
480
    else { /* other case: alt1, nalt10... (alternates) */
 
481
      for (q = s + strlen(s) - 1; q > s && *q >= '0' && *q <= '9'; q--);
 
482
      if (q == s)
 
483
        error = -1;
 
484
      else { /* starting at 1 */
 
485
        n = atoi(q + 1) - 1; q[1] = '\0';
 
486
        if (strlen(s) > 4)
 
487
          error = -1;
 
488
        else { /* This may be alternate substitution. */
 
489
          memset(t, ' ', 4); t[4] = '\0';
 
490
          memcpy(t, s, strlen(s));
 
491
          error = select_gsub(s, gm);
 
492
          if (!error)
 
493
            error = otl_gsub_apply_alt(gm->gsub, n, &in);
 
494
        }
 
495
      }
 
496
    }
 
497
  }
 
498
  RELEASE(s);
 
499
 
 
500
  *out = in;
 
501
  return  error;
 
502
}
 
503
 
 
504
 
 
505
/* Compose glyphs via ligature substitution. */
 
506
static int
 
507
composeglyph (USHORT *glyphs, int n_glyphs,
 
508
              const char *feat, struct glyph_mapper *gm, USHORT *gid)
 
509
{
 
510
  int   error = 0;
 
511
  char  t[5] = {' ', ' ', ' ', ' ', 0};
 
512
 
 
513
  ASSERT(glyphs && n_glyphs > 0 && gm && gid);
 
514
 
 
515
  if (!feat || feat[0] == '\0') /* meaning "Unknown" */
 
516
      error = select_gsub("(?lig|lig?|?cmp|cmp?|frac|afrc)", gm);
 
517
  else {
 
518
    if (strlen(feat) > 4)
 
519
      error = -1;
 
520
    else {
 
521
      memcpy(t, feat, strlen(feat));
 
522
      error = select_gsub(t, gm);
 
523
    }
 
524
  }
 
525
 
 
526
  if (!error)
 
527
    error = otl_gsub_apply_lig(gm->gsub, glyphs, n_glyphs, gid);
 
528
 
 
529
  return  error;
 
530
}
 
531
 
 
532
/* This may be called by findparanoiac(). */
 
533
static int
 
534
composeuchar (long *unicodes, int n_unicodes,
 
535
              const char *feat, struct glyph_mapper *gm, USHORT *gid)
 
536
{
 
537
  USHORT  *gids;
 
538
  int      i, error = 0;
 
539
 
 
540
  if (!gm->codetogid)
 
541
    return  -1;
 
542
 
 
543
  gids = NEW(n_unicodes, USHORT);
 
544
  for (i = 0;
 
545
       !error && i < n_unicodes; i++) {
 
546
    gids[i] = tt_cmap_lookup(gm->codetogid, unicodes[i]);
 
547
    error   = (gids[i] == 0) ? -1 : 0;
 
548
  }
 
549
 
 
550
  if (!error)
 
551
    error = composeglyph(gids, n_unicodes, feat, gm, gid);
 
552
 
 
553
  RELEASE(gids);
 
554
 
 
555
  return  error;
 
556
}
 
557
 
 
558
/* Search 'post' table. */
 
559
static int
 
560
findposttable (const char *glyph_name, USHORT *gid, struct glyph_mapper *gm)
 
561
{
 
562
  if (!gm->nametogid)
 
563
    return -1;
 
564
 
 
565
  *gid = tt_lookup_post_table(gm->nametogid, glyph_name);
 
566
#if  0
 
567
  if (verbose > 1)
 
568
  {
 
569
    if (*gid > 0)
 
570
      MESG("%s =post=> 0x%04X\n", glyph_name, *gid);
 
571
  }
 
572
#endif
 
573
 
 
574
  return (*gid == 0 ? -1 : 0);
 
575
}
 
576
 
 
577
/* This is wrong. We must care about '.'. */
 
578
#define is_comp(n) (strchr((n), '_') != NULL)
 
579
 
 
580
/* Glyph names are concatinated with '_'. */
 
581
static int
 
582
findcomposite (const char *glyphname, USHORT *gid, struct glyph_mapper *gm)
 
583
{
 
584
  char     *gname, *suffix = NULL;
 
585
  USHORT    gids[32];
 
586
  char     *nptrs[32];
 
587
  int       i, n_comp;
 
588
  int       error = 0;
 
589
 
 
590
  error = findposttable(glyphname, gid, gm);
 
591
  if (!error)
 
592
    return  0;
 
593
 
 
594
  gname = NEW(strlen(glyphname) + 1, char);
 
595
  strcpy(gname, glyphname);
 
596
 
 
597
  memset(gids, 0, 32 * sizeof(USHORT));
 
598
  n_comp = agl_decompose_glyphname(gname, nptrs, 32, &suffix);
 
599
  for (error = 0, i = 0; !error && i < n_comp; i++) {
 
600
    error = resolve_glyph(nptrs[i], &gids[i], gm);
 
601
    if (error)
 
602
      WARN("Could not resolve glyph \"%s\" (%dth component of glyph \"%s\").",
 
603
           nptrs[i], i, glyphname);
 
604
  }
 
605
 
 
606
  if (!error) {
 
607
    if (suffix &&
 
608
        (!strcmp(suffix, "liga") || !strcmp(suffix, "dlig") ||
 
609
         !strcmp(suffix, "hlig") || !strcmp(suffix, "frac") ||
 
610
         !strcmp(suffix, "ccmp") || !strcmp(suffix, "afrc")
 
611
        )
 
612
       ) {
 
613
      error = composeglyph(gids, n_comp, suffix, gm, gid);
 
614
    } else { /* first try composing glyph */
 
615
      error = composeglyph(gids, n_comp, NULL, gm, gid);
 
616
      if (!error && suffix) /* a_b_c.vert */
 
617
        error = selectglyph(*gid, suffix, gm, gid);
 
618
    }
 
619
  }
 
620
  RELEASE(gname);
 
621
 
 
622
  return  error;
 
623
}
 
624
 
 
625
/* glyphname should not have suffix here */
 
626
static int
 
627
findparanoiac (const char *glyphname, USHORT *gid, struct glyph_mapper *gm)
 
628
{
 
629
  agl_name  *agln;
 
630
  USHORT     idx   = 0U;
 
631
  int        error = 0;
 
632
 
 
633
  agln = agl_lookup_list(glyphname);
 
634
  while (agln && idx == 0) {
 
635
    if (agln->suffix) {
 
636
      error = findparanoiac(agln->name, &idx, gm);
 
637
      if (error)
 
638
        return error;
 
639
 
 
640
      error = selectglyph(idx, agln->suffix, gm, &idx);
 
641
      if (error) {
 
642
        WARN("Variant \"%s\" for glyph \"%s\" might not be found.",
 
643
             agln->suffix, agln->name);
 
644
        WARN("Using glyph name without suffix instead...");
 
645
        error = 0; /* ignore */
 
646
      }
 
647
    } else {
 
648
      if (agln->n_components == 1)
 
649
        idx = tt_cmap_lookup(gm->codetogid, agln->unicodes[0]);
 
650
      else if (agln->n_components > 1) {
 
651
        if (verbose >= 0) /* give warning */
 
652
          WARN("Glyph \"%s\" looks like a composite glyph...",
 
653
               agln->name);
 
654
        error = composeuchar(agln->unicodes, agln->n_components, NULL, gm, &idx);
 
655
        if (verbose >= 0) {
 
656
          if (error)
 
657
            WARN("Not found...");
 
658
          else {
 
659
            int   _i, _n = 0;
 
660
            char *_p, _buf[256];
 
661
            WARN(">> Composite glyph glyph-name=\"%s\" found at glyph-id=\"%u\".",
 
662
                  agln->name, idx);
 
663
            for (_p = _buf, _i = 0; _i < agln->n_components && _n < 245; _i++) {
 
664
              _p[_n++] = _i == 0 ? '<' : ' ';
 
665
              if (agln->unicodes[_i] >= 0x10000)
 
666
                _n += sprintf(_p+_n, "U+%06lX", agln->unicodes[_i]);
 
667
              else
 
668
                _n += sprintf(_p+_n, "U+%04lX", agln->unicodes[_i]);
 
669
              _p[_n++] = _i == agln->n_components - 1 ? '>' : ',';
 
670
            }
 
671
            _p[_n++] = '\0';
 
672
            WARN(">> Input Unicode seq.=\"%s\" ==> glyph-id=\"%u\" in font-file=\"_please_try_-v_\".", _buf, idx);
 
673
          }
 
674
        }
 
675
      } else ASSERT(0); /* Boooo */
 
676
    }
 
677
    agln = agln->alternate;
 
678
  }
 
679
 
 
680
  *gid = idx;
 
681
  return (idx == 0 ? -1 : 0);
 
682
}
 
683
 
 
684
static int
 
685
resolve_glyph (const char *glyphname, USHORT *gid, struct glyph_mapper *gm)
 
686
{
 
687
  int    error = 0;
 
688
  char  *name, *suffix = NULL;
 
689
  long   ucv;
 
690
 
 
691
  ASSERT(glyphname);
 
692
 
 
693
  /*
 
694
   * First we try glyph name to GID mapping using post table if post table
 
695
   * is available. If post table is not available or glyph is not listed 
 
696
   * in the post table, then we try Unicode if Windows-Unicode TrueType
 
697
   * cmap is available.
 
698
   */
 
699
  error = findposttable(glyphname, gid, gm);
 
700
  if (!error)
 
701
    return  0;
 
702
 
 
703
  if (!gm->codetogid)
 
704
    return  -1;
 
705
 
 
706
  name = agl_chop_suffix(glyphname, &suffix);
 
707
  if (!name) /* .notdef, .foo */
 
708
    error = -1;
 
709
  else if (agl_name_is_unicode(name)) {
 
710
    ucv  = agl_name_convert_unicode(name);
 
711
    *gid = tt_cmap_lookup(gm->codetogid, ucv);
 
712
    error = (*gid == 0) ? -1 : 0;
 
713
  } else {
 
714
    error = findparanoiac(name, gid, gm);
 
715
  }
 
716
  if (!error && suffix) {
 
717
    error = selectglyph(*gid, suffix, gm, gid);
 
718
    if (error) {
 
719
      WARN("Variant \"%s\" for glyph \"%s\" might not be found.",
 
720
           suffix, name);
 
721
      WARN("Using glyph name without suffix instead...");
 
722
      error = 0; /* ignore */
 
723
    }
 
724
  }
 
725
  if (suffix)
 
726
    RELEASE(suffix);
 
727
  if (name)
 
728
    RELEASE(name);
 
729
 
 
730
  return  error;
 
731
}
 
732
 
 
733
/* Things are complicated. We still need to use PostScript
 
734
 * glyph names. But OpenType fonts may not have PS name to
 
735
 * glyph mapping. We use Unicode plus OTL GSUB for finding
 
736
 * glyphs in this case.
 
737
 */
 
738
static int
 
739
setup_glyph_mapper (struct glyph_mapper *gm, sfnt *sfont)
 
740
{
 
741
  gm->sfont     = sfont;
 
742
  gm->nametogid = tt_read_post_table(sfont);
 
743
  gm->codetogid = tt_cmap_read(sfont, TT_WIN, TT_WIN_UCS4);
 
744
  if (!gm->codetogid)
 
745
    gm->codetogid = tt_cmap_read(sfont, TT_WIN, TT_WIN_UNICODE);
 
746
 
 
747
  if (!gm->nametogid && !gm->codetogid)
 
748
    return -1;
 
749
 
 
750
  gm->gsub = otl_gsub_new();
 
751
 
 
752
  return 0;
 
753
}
 
754
 
 
755
static void
 
756
clean_glyph_mapper (struct glyph_mapper *gm)
 
757
{
 
758
  if (gm->gsub)
 
759
    otl_gsub_release(gm->gsub);
 
760
  if (gm->codetogid)
 
761
    tt_cmap_release (gm->codetogid);
 
762
  if (gm->nametogid)
 
763
    tt_release_post_table(gm->nametogid);
 
764
 
 
765
  gm->gsub = NULL;
 
766
  gm->codetogid = NULL;
 
767
  gm->nametogid = NULL;
 
768
  gm->sfont = NULL;
 
769
 
 
770
  return;
 
771
}
 
772
 
 
773
static int
 
774
do_custum_encoding (pdf_font *font,
 
775
                    char **encoding, const char *usedchars, sfnt *sfont)
 
776
{
 
777
  struct tt_glyphs      *glyphs;
 
778
  char                  *cmap_table;
 
779
  int                    code, count;
 
780
  double                 widths[256];
 
781
  struct glyph_mapper    gm;
 
782
  USHORT                 idx, gid;
 
783
  int                    error = 0;
 
784
 
 
785
  ASSERT(font && encoding && usedchars && sfont);
 
786
 
 
787
  error = setup_glyph_mapper(&gm, sfont);
 
788
  if (error) {
 
789
    WARN("No post table nor Unicode cmap found in font: %s",
 
790
         pdf_font_get_ident(font));
 
791
    WARN(">> I can't find glyphs without this!");
 
792
    return  -1;
 
793
  }
 
794
 
 
795
  cmap_table = NEW(274, char);
 
796
  memset(cmap_table, 0, 274);
 
797
  sfnt_put_ushort(cmap_table,    0);            /* Version  */
 
798
  sfnt_put_ushort(cmap_table+2,  1);            /* Number of subtables */
 
799
  sfnt_put_ushort(cmap_table+4,  TT_MAC);       /* Platform ID */
 
800
  sfnt_put_ushort(cmap_table+6,  TT_MAC_ROMAN); /* Encoding ID */
 
801
  sfnt_put_ulong (cmap_table+8,  12);           /* Offset   */
 
802
  sfnt_put_ushort(cmap_table+12, 0);            /* Format   */
 
803
  sfnt_put_ushort(cmap_table+14, 262);          /* Length   */
 
804
  sfnt_put_ushort(cmap_table+16, 0);            /* Language */
 
805
 
 
806
  glyphs = tt_build_init();
 
807
 
 
808
  count = 1; /* +1 for .notdef */
 
809
  for (code = 0; code < 256; code++) {
 
810
    if (!usedchars[code])
 
811
      continue;
 
812
 
 
813
    if (!encoding[code] || !strcmp(encoding[code], ".notdef")) {
 
814
      WARN("Character code=\"0x%02X\" mapped to \".notdef\" glyph used in font font-file=\"%s\"",
 
815
           code, pdf_font_get_ident(font));
 
816
      WARN(">> Maybe incorrect encoding specified?");
 
817
      idx = 0;
 
818
    } else {
 
819
      if (is_comp(encoding[code]))
 
820
        error = findcomposite(encoding[code], &gid, &gm);
 
821
      else
 
822
        error = resolve_glyph(encoding[code], &gid, &gm);
 
823
 
 
824
      /*
 
825
       * Older versions of gs had problem with glyphs (other than .notdef)
 
826
       * mapped to gid = 0.
 
827
       */
 
828
      if (error) {
 
829
        WARN("Glyph \"%s\" not available in font \"%s\".",
 
830
             encoding[code], pdf_font_get_ident(font));
 
831
      } else {
 
832
        if (verbose > 1)
 
833
          MESG("truetype>> Glyph glyph-name=\"%s\" found at glyph-id=\"%u\".\n", encoding[code], gid);
 
834
      }
 
835
      idx = tt_find_glyph(glyphs, gid);
 
836
      if (idx == 0) {
 
837
        idx = tt_add_glyph(glyphs, gid, count); /* count returned. */
 
838
        count++;
 
839
      }
 
840
    }
 
841
    cmap_table[18 + code] = idx & 0xff; /* bug here */
 
842
  }
 
843
  clean_glyph_mapper(&gm);
 
844
 
 
845
  if (tt_build_tables(sfont, glyphs) < 0) {
 
846
    WARN("Packing TrueType font into SFNT file faild..."); /* _FIXME_: wrong message */
 
847
    tt_build_finish(glyphs);
 
848
    RELEASE(cmap_table);
 
849
    return  -1;
 
850
  }
 
851
 
 
852
  for (code = 0; code < 256; code++) {
 
853
    if (usedchars[code]) {
 
854
      idx = tt_get_index(glyphs, (USHORT) cmap_table[18+code]);
 
855
      widths[code] = PDFUNIT(glyphs->gd[idx].advw);
 
856
    } else {
 
857
      widths[code] = 0.0;
 
858
    }
 
859
  }
 
860
  do_widths(font, widths);
 
861
 
 
862
  if (verbose > 1) 
 
863
    MESG("[%d glyphs]", glyphs->num_glyphs);
 
864
 
 
865
  tt_build_finish(glyphs);
 
866
 
 
867
  sfnt_set_table(sfont, "cmap", cmap_table, 274);
 
868
 
 
869
  return  0;
 
870
}
 
871
 
 
872
int
 
873
pdf_font_load_truetype (pdf_font *font)
 
874
{
 
875
  pdf_obj   *fontdict    = pdf_font_get_resource(font);
 
876
  pdf_obj   *descriptor  = pdf_font_get_descriptor(font);
 
877
  char      *ident       = pdf_font_get_ident(font);
 
878
  int        encoding_id = pdf_font_get_encoding(font);
 
879
  char      *usedchars   = pdf_font_get_usedchars(font);
 
880
#ifdef  ENABLE_NOEMBED
 
881
  int        embedding   = pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED) ? 0 : 1;
 
882
#endif /* ENABLE_NOEMBED */
 
883
  char     **enc_vec;
 
884
  pdf_obj   *fontfile;
 
885
  FILE      *fp = NULL;
 
886
  sfnt      *sfont;
 
887
  int        i, error = 0;
 
888
 
 
889
  if (!pdf_font_is_in_use(font))
 
890
    return  0;
 
891
 
 
892
  verbose = pdf_font_get_verbose();
 
893
 
 
894
  if (!pdf_lookup_dict(fontdict, "ToUnicode")) {
 
895
    if (encoding_id >= 0)
 
896
      pdf_attach_ToUnicode_CMap(fontdict,
 
897
                                encoding_id, usedchars);
 
898
     /* encoding_id < 0 means MacRoman here (but not really) */
 
899
  }
 
900
 
 
901
#ifdef XETEX
 
902
  sfont = sfnt_open(pdf_font_get_ft_face(font), SFNT_TYPE_TTC | SFNT_TYPE_TRUETYPE);
 
903
#else
 
904
  fp = DPXFOPEN(ident, DPX_RES_TYPE_TTFONT);
 
905
  if (!fp)
 
906
    ERROR("Unable to open TrueType font file: %s", ident); /* Should find *truetype* here */
 
907
 
 
908
  sfont = sfnt_open(fp);
 
909
#endif
 
910
  if (!sfont) {
 
911
    ERROR("Unable to open TrueType file: %s", ident);
 
912
    if (fp)
 
913
      DPXFCLOSE(fp);
 
914
    return  -1;
 
915
  } else if (sfont->type != SFNT_TYPE_TRUETYPE &&
 
916
             sfont->type != SFNT_TYPE_TTC) { 
 
917
    ERROR("Font \"%s\" not a TrueType font?", ident);
 
918
    sfnt_close(sfont);
 
919
    if (fp)
 
920
      DPXFCLOSE(fp);
 
921
    return  -1;
 
922
  }
 
923
 
 
924
  if (sfont->type == SFNT_TYPE_TTC)
 
925
    error = sfnt_read_table_directory(sfont, ttc_read_offset(sfont, 0));
 
926
  else
 
927
    error = sfnt_read_table_directory(sfont, 0);
 
928
 
 
929
  if (error) {
 
930
    ERROR("Reading SFND table dir failed for font-file=\"%s\"... Not a TrueType font?", ident);
 
931
    sfnt_close(sfont);
 
932
    if (fp)
 
933
      DPXFCLOSE(fp);
 
934
    return  -1;
 
935
  }
 
936
 
 
937
  /*
 
938
   * Create new TrueType cmap table with MacRoman encoding.
 
939
   */
 
940
  if (encoding_id < 0)
 
941
    error = do_builtin_encoding(font, usedchars, sfont);
 
942
  else {
 
943
    enc_vec  = pdf_encoding_get_encoding(encoding_id);
 
944
    error = do_custum_encoding(font, enc_vec, usedchars, sfont);
 
945
  }
 
946
  if (error) {
 
947
    ERROR("Error occured while creating font subfont for \"%s\"", ident);
 
948
    sfnt_close(sfont);
 
949
    if (fp)
 
950
      DPXFCLOSE(fp);
 
951
    return  -1;
 
952
  }
 
953
 
 
954
#if  ENABLE_NOEMBED
 
955
  if (!embedding) {
 
956
    sfnt_close(sfont);
 
957
    if (fp)
 
958
      DPXFCLOSE(fp);
 
959
    return  0;
 
960
  }
 
961
#endif /* ENABLE_NOEMBED */
 
962
 
 
963
  /*
 
964
   * TODO: post table?
 
965
   */
 
966
 
 
967
  for (i = 0; required_table[i].name != NULL; i++) {
 
968
    if (sfnt_require_table(sfont,
 
969
                           required_table[i].name,
 
970
                           required_table[i].must_exist) < 0) {
 
971
      ERROR("Required TrueType table \"%s\" does not exist in font: %s",
 
972
            required_table[i].name, ident);
 
973
      sfnt_close(sfont);
 
974
      if (fp)
 
975
        DPXFCLOSE(fp);
 
976
      return  -1;
 
977
    }
 
978
  }
 
979
 
 
980
  /*
 
981
   * FontFile2
 
982
   */
 
983
  fontfile = sfnt_create_FontFile_stream(sfont);
 
984
  if (!fontfile)
 
985
    ERROR("Could not created FontFile stream for \"%s\".", ident);
 
986
 
 
987
  sfnt_close(sfont);
 
988
  if (fp)
 
989
    DPXFCLOSE(fp);
 
990
 
 
991
  if (verbose > 1)
 
992
    MESG("[%ld bytes]", pdf_stream_length(fontfile));
 
993
 
 
994
  pdf_add_dict(descriptor,
 
995
               pdf_new_name("FontFile2"), pdf_ref_obj(fontfile)); /* XXX */
 
996
  pdf_release_obj(fontfile);
 
997
 
 
998
  return  0;
 
999
}