summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfm-x/type0.c
blob: afb4bbbc1bc6b8a8ee1fa7d8267eb7dd4267c624 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
/* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.

    Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
    the dvipdfmx project team.
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/

/*
 * Type0 font support:
 * 
 * TODO:
 *
 *  Composite font (multiple descendants) - not supported in PDF
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <string.h>

#include "system.h"
#include "mem.h"
#include "error.h"
#include "dpxconf.h"
#include "dpxfile.h"

#include "pdfobj.h"
#include "fontmap.h"

#include "cmap.h"
#include "cidtype0.h"
#include "cid.h"

#include "type0.h"


static pdf_obj *pdf_read_ToUnicode_file (const char *cmap_name);

/* PLEASE FIX THIS */
#include "tt_cmap.h"

/* Try to load ToUnicode CMap from file system first, if not found fallback to
 * font CMap reverse lookup.
 * CHANGED: CMap here is not always Unicode to CID mapping. Don't use reverse lookup.
 */
static pdf_obj *
try_load_ToUnicode_file (char *cmap_base)
{
  pdf_obj *tounicode;
  char    *cmap_name;

  cmap_name = NEW(strlen(cmap_base)+strlen("-UTF16")+1, char);
  sprintf(cmap_name, "%s-UTF16", cmap_base);
  tounicode = pdf_read_ToUnicode_file(cmap_name);
  if (!tounicode) {
    sprintf(cmap_name, "%s-UCS2", cmap_base);
    tounicode = pdf_read_ToUnicode_file(cmap_name);
  }
  RELEASE(cmap_name);

  return tounicode;
}

static void
Type0Font_attach_ToUnicode_stream (pdf_font *font)
{
  pdf_obj    *tounicode;
  pdf_font   *cidfont = pdf_get_font_data(font->type0.descendant);
  CIDSysInfo *csi;
  char       *fontname;

  /*
   * ToUnicode CMap:
   *
   *  ToUnicode CMaps are usually not required for standard character
   *  collections such as Adobe-Japan1. Identity-H is used for UCS
   *  ordering CID-keyed fonts. External resource must be loaded for
   *  others.
   */
  ASSERT(cidfont);

  if (CIDFont_is_ACCFont(cidfont)) {
    /* No need to embed ToUnicode */
    return;
  } else if (CIDFont_is_UCSFont(cidfont)) {
    /*
     * Old version of dvipdfmx mistakenly used Adobe-Identity as Unicode.
     */
    /* ref returned */
    tounicode = pdf_read_ToUnicode_file("Adobe-Identity-UCS2");
    if (!tounicode) { /* This should work */
      tounicode = pdf_new_name("Identity-H");      
    }
    pdf_add_dict(font->resource, pdf_new_name("ToUnicode"), tounicode);
    return;
  }

  tounicode = NULL;
  csi       = &cidfont->cid.csi;
  if (cidfont->cid.options.embed) {
    fontname = NEW(strlen(cidfont->fontname)+8, char);
    sprintf(fontname, "%s+%s", cidfont->uniqueID, cidfont->fontname);
  } else {
    fontname = NEW(strlen(cidfont->fontname)+1, char);
    strcpy(fontname, cidfont->fontname);
  }

  switch (cidfont->subtype) {
  case PDF_FONT_FONTTYPE_CIDTYPE2:
    if (!strcmp(csi->registry, "Adobe") && !strcmp(csi->ordering, "Identity")) {
      tounicode = otf_create_ToUnicode_stream(cidfont->ident, cidfont->index,
                                              fontname, font->usedchars);
    } else {
      char *cmap_base = NEW(strlen(csi->registry) + strlen(csi->ordering) + 2, char);
      sprintf(cmap_base, "%s-%s", csi->registry, csi->ordering);
      tounicode = try_load_ToUnicode_file(cmap_base);
      RELEASE(cmap_base);
      /* In this case glyphs are re-ordered hance otf_create... won't work */
    }
    break;
  default:
    if (cidfont->flags & CIDFONT_FLAG_TYPE1C) {
      tounicode = otf_create_ToUnicode_stream(cidfont->ident, cidfont->index,
                                              fontname, font->usedchars);
    } else if (cidfont->flags & CIDFONT_FLAG_TYPE1) {
      tounicode = CIDFont_type0_t1create_ToUnicode_stream(cidfont->ident, fontname, font->usedchars);
    } else {
      tounicode = try_load_ToUnicode_file(cidfont->fontname);
      if (!tounicode) {
        tounicode = otf_create_ToUnicode_stream(cidfont->ident, cidfont->index,
                                                fontname, font->usedchars);
      }
    }
  }
  RELEASE(fontname);

  if (tounicode) {
    pdf_add_dict(font->resource, pdf_new_name("ToUnicode"), tounicode);
  } else {
#if defined(LIBDPX)
    if (dpx_conf.verbose_level > 0)
      WARN("Failed to load ToUnicode CMap for font \"%s\"", cidfont->fontname);
#else
    WARN("Failed to load ToUnicode CMap for font \"%s\"", cidfont->filename);
#endif /* LIBDPX */
  }

  return;
}

void
pdf_font_load_type0 (pdf_font *font)
{
  if (!font || !font->reference)
    return;

  /* FIXME: Should move to pdffont.c */
  if (!pdf_lookup_dict(font->resource, "ToUnicode")) {
    Type0Font_attach_ToUnicode_stream(font);
  }
}

int
pdf_font_open_type0 (pdf_font *font, int cid_id, int wmode)
{
  pdf_font   *cidfont;
  CIDSysInfo *csi;
  char       *fontname = NULL;

  if (cid_id < 0) 
    return -1;

  cidfont = pdf_get_font_data(cid_id);

  font->type0.wmode      = wmode;
  font->type0.descendant = cid_id;

  /*
   * PostScript Font name:
   *
   *  Type0 font's fontname is usually descendant CID-keyed font's font name 
   *  appended by -ENCODING.
   */
  if (cidfont->cid.options.embed) {
    fontname = NEW(strlen(cidfont->fontname)+8, char);
    sprintf(fontname, "%s+%s", cidfont->uniqueID, cidfont->fontname);
  } else {
    fontname = NEW(strlen(cidfont->fontname)+1, char);
    strcpy(fontname, cidfont->fontname);
  }

  if (dpx_conf.verbose_level > 0) {
    MESG("(CID:%s)", cidfont->fontname);
  }

  switch (cidfont->subtype) {
  case PDF_FONT_FONTTYPE_CIDTYPE0:
    font->fontname  = NEW(strlen(fontname)+strlen("Identity-V")+2, char);
    sprintf(font->fontname, "%s-%s", fontname, wmode ? "Identity-V" : "Identity-H");
    font->usedchars = CIDFont_get_usedchars(cidfont);
    font->flags    |= PDF_FONT_FLAG_USEDCHAR_SHARED;
    break;
  case PDF_FONT_FONTTYPE_CIDTYPE2:
    font->fontname = NEW(strlen(fontname)+1, char);
    strcpy(font->fontname, fontname);
    /* Adobe-Identity here means use GID as CID directly. No need to use GSUB for finding
     * vertical glyphs hence separate used_chars for H and V instances are not needed.
     */
    csi = &cidfont->cid.csi;
    if (!csi || (!strcmp(csi->registry, "Adobe") && !strcmp(csi->ordering, "Identity"))) {
      font->usedchars  = CIDFont_get_usedchars(cidfont);
      font->flags     |= PDF_FONT_FLAG_USEDCHAR_SHARED;
    } else {
      font->usedchars  = wmode ? CIDFont_get_usedchars_v(cidfont) : CIDFont_get_usedchars(cidfont);
      font->flags     |= PDF_FONT_FLAG_USEDCHAR_SHARED;
    }
    break;
  }

  font->resource = pdf_new_dict();
  pdf_add_dict(font->resource, pdf_new_name ("Type"),    pdf_new_name ("Font"));
  pdf_add_dict(font->resource, pdf_new_name ("Subtype"), pdf_new_name ("Type0"));
  pdf_add_dict(font->resource,
               pdf_new_name("BaseFont"), pdf_new_name(font->fontname));
  pdf_add_dict(font->resource,
               pdf_new_name("Encoding"), pdf_new_name(wmode ? "Identity-V" : "Identity-H"));

  return 0;
}

/******************************** COMPAT ********************************/

#ifndef WITHOUT_COMPAT

#include "cmap_read.h"
#include "cmap_write.h"
#include "pdfresource.h"
#include "pdfencoding.h"

static pdf_obj *
create_dummy_CMap (void)
{
  pdf_obj *stream;
  char     buf[32];
  int      i, n;

#define CMAP_PART0 "\
%!PS-Adobe-3.0 Resource-CMap\n\
%%DocumentNeededResources: ProcSet (CIDInit)\n\
%%IncludeResource: ProcSet (CIDInit)\n\
%%BeginResource: CMap (Adobe-Identity-UCS2)\n\
%%Title: (Adobe-Identity-UCS2 Adobe UCS2 0)\n\
%%Version: 1.0\n\
%%Copyright:\n\
%% ---\n\
%%EndComments\n\n\
"
#define CMAP_PART1 "\
/CIDInit /ProcSet findresource begin\n\
\n\
12 dict begin\n\nbegincmap\n\n\
/CIDSystemInfo 3 dict dup begin\n\
  /Registry (Adobe) def\n\
  /Ordering (UCS2) def\n\
  /Supplement 0 def\n\
end def\n\n\
/CMapName /Adobe-Identity-UCS2 def\n\
/CMapVersion 1.0 def\n\
/CMapType 2 def\n\n\
2 begincodespacerange\n\
<0000> <FFFF>\n\
endcodespacerange\n\
"
#define CMAP_PART3 "\
endcmap\n\n\
CMapName currentdict /CMap defineresource pop\n\n\
end\nend\n\n\
%%EndResource\n\
%%EOF\n\
"

  stream = pdf_new_stream(STREAM_COMPRESS);
  pdf_add_stream(stream, CMAP_PART0, strlen(CMAP_PART0));
  pdf_add_stream(stream, CMAP_PART1, strlen(CMAP_PART1));
  pdf_add_stream(stream, "\n100 beginbfrange\n", strlen("\n100 beginbfrange\n"));
  for (i = 0; i < 0x64; i++) {
    n = sprintf(buf,
                "<%02X00> <%02XFF> <%02X00>\n", i, i, i);
    pdf_add_stream(stream, buf, n);
  }
  pdf_add_stream(stream, "endbfrange\n\n", strlen("endbfrange\n\n"));

  pdf_add_stream(stream, "\n100 beginbfrange\n", strlen("\n100 beginbfrange\n"));
  for (i = 0x64; i < 0xc8; i++) {
    n = sprintf(buf,
                "<%02X00> <%02XFF> <%02X00>\n", i, i, i);
    pdf_add_stream(stream, buf, n);
  }
  pdf_add_stream(stream, "endbfrange\n\n", strlen("endbfrange\n\n"));

  pdf_add_stream(stream, "\n48 beginbfrange\n", strlen("\n48 beginbfrange\n"));
  for (i = 0xc8; i <= 0xd7; i++) {
    n = sprintf(buf,
                "<%02X00> <%02XFF> <%02X00>\n", i, i, i);
    pdf_add_stream(stream, buf, n);
  }
  for (i = 0xe0; i <= 0xff; i++) {
    n = sprintf(buf,
                "<%02X00> <%02XFF> <%02X00>\n", i, i, i);
    pdf_add_stream(stream, buf, n);
  }
  pdf_add_stream(stream, "endbfrange\n\n", strlen("endbfrange\n\n"));

  pdf_add_stream(stream, CMAP_PART3, strlen(CMAP_PART3));

  return  stream;
}

static pdf_obj *
pdf_read_ToUnicode_file (const char *cmap_name)
{
  pdf_obj *stream;
  int      res_id = -1;

  ASSERT(cmap_name);

  res_id = pdf_findresource("CMap", cmap_name);
  if (res_id < 0) {
    if (!strcmp(cmap_name, "Adobe-Identity-UCS2"))
      stream = create_dummy_CMap();
    else {
      stream = pdf_load_ToUnicode_stream(cmap_name);
    }
    if (stream) {
      res_id   = pdf_defineresource("CMap",
                                    cmap_name,
                                    stream, PDF_RES_FLUSH_IMMEDIATE);
    }
  }

  return  (res_id < 0 ? NULL : pdf_get_resource_reference(res_id));
}
#endif /* !WITHOUT_COMPAT */