1 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
2
3 Copyright (C) 2008-2014 by Jin-Hwan Cho, Matthias Franz, and Shunsaku Hirata,
4 the dvipdfmx project team.
5
6 Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
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 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <string.h>
28 #include <math.h>
29
30 #include "system.h"
31 #include "mem.h"
32 #include "error.h"
33
34 #include "dpxfile.h"
35
36 #include "numbers.h"
37
38 #include "pdfobj.h"
39 #include "pdffont.h"
40
41 #include "pdfencoding.h"
42 #include "unicode.h"
43
44 #include "dpxutil.h"
45
46 #include "pst_obj.h"
47 #include "pst.h"
48
49 #include "cff_limits.h"
50 #include "cff_types.h"
51 #include "cff_dict.h"
52 #include "cff.h"
53
54 #include "t1_load.h"
55 #include "t1_char.h"
56
57 #include "type1.h"
58
59 #include "tfm.h"
60
61 #define FONT_FLAG_FIXEDPITCH (1 << 0) /* Fixed-width font */
62 #define FONT_FLAG_SERIF (1 << 1) /* Serif font */
63 #define FONT_FLAG_SYMBOLIC (1 << 2) /* Symbolic font */
64 #define FONT_FLAG_SCRIPT (1 << 3) /* Script font */
65 #define FONT_FLAG_STANDARD (1 << 5) /* Adobe Standard Character Set */
66 #define FONT_FLAG_ITALIC (1 << 6) /* Italic */
67 #define FONT_FLAG_ALLCAP (1 << 16) /* All-cap font */
68 #define FONT_FLAG_SMALLCAP (1 << 17) /* Small-cap font */
69 #define FONT_FLAG_FORCEBOLD (1 << 18) /* Force bold at small text sizes */
70
71 static int
is_basefont(const char * name)72 is_basefont (const char *name)
73 {
74 static const char *basefonts[] = {
75 "Courier", "Courier-Bold", "Courier-Oblique",
76 "Courier-BoldOblique", "Helvetica", "Helvetica-Bold",
77 "Helvetica-Oblique", "Helvetica-BoldOblique", "Symbol",
78 "Times-Roman", "Times-Bold", "Times-Italic",
79 "Times-BoldItalic", "ZapfDingbats"
80 };
81 int i;
82
83 for (i = 0; i < 14; i++) {
84 if (!strcmp(name, basefonts[i]))
85 return 1;
86 }
87
88 return 0;
89 }
90
91 int
pdf_font_open_type1(pdf_font * font)92 pdf_font_open_type1 (pdf_font *font)
93 {
94 char *ident;
95 FILE *fp;
96 char fontname[PDF_NAME_LEN_MAX+1];
97
98 ASSERT(font);
99
100 ident = pdf_font_get_ident(font);
101
102 if (is_basefont(ident)) {
103 pdf_font_set_fontname(font, ident);
104 pdf_font_set_subtype (font, PDF_FONT_FONTTYPE_TYPE1);
105 pdf_font_set_flags (font,
106 (PDF_FONT_FLAG_NOEMBED|PDF_FONT_FLAG_BASEFONT));
107 } else {
108 fp = DPXFOPEN(ident, DPX_RES_TYPE_T1FONT);
109 if (!fp)
110 return -1;
111
112 memset(fontname, 0, PDF_NAME_LEN_MAX+1);
113 if (!is_pfb(fp) || t1_get_fontname(fp, fontname) < 0) {
114 ERROR("Failed to read Type 1 font \"%s\".", ident);
115 }
116 DPXFCLOSE(fp);
117
118 pdf_font_set_fontname(font, fontname);
119 pdf_font_set_subtype (font, PDF_FONT_FONTTYPE_TYPE1);
120 }
121
122 return 0;
123 }
124
125 static void
get_font_attr(pdf_font * font,cff_font * cffont)126 get_font_attr (pdf_font *font, cff_font *cffont)
127 {
128 char *fontname;
129 pdf_obj *descriptor;
130 double capheight, ascent, descent;
131 double italicangle, stemv;
132 double defaultwidth, nominalwidth;
133 long flags = 0, gid, i;
134 static const char *L_c[] = {
135 "H", "P", "Pi", "Rho", NULL
136 };
137 static const char *L_d[] = {
138 "p", "q", "mu", "eta", NULL
139 };
140 static const char *L_a[] = {
141 "b", "h", "lambda", NULL
142 };
143 t1_ginfo gm;
144
145 defaultwidth = 500.0;
146 nominalwidth = 0.0;
147
148 /*
149 * CapHeight, Ascent, and Descent is meaningfull only for Latin/Greek/Cyrillic.
150 * The BlueValues and OtherBlues also have those information.
151 */
152 if (cff_dict_known(cffont->topdict, "FontBBox")) {
153 /* Default values */
154 capheight = ascent = cff_dict_get(cffont->topdict, "FontBBox", 3);
155 descent = cff_dict_get(cffont->topdict, "FontBBox", 1);
156 } else {
157 capheight = 680.0;
158 ascent = 690.0;
159 descent = -190.0;
160 }
161 if (cff_dict_known(cffont->private[0], "StdVW")) {
162 stemv = cff_dict_get(cffont->private[0], "StdVW", 0);
163 } else {
164 /*
165 * We may use the following values for StemV:
166 * Thin - ExtraLight: <= 50
167 * Light: 71
168 * Regular(Normal): 88
169 * Medium: 109
170 * SemiBold(DemiBold): 135
171 * Bold - Heavy: >= 166
172 */
173 stemv = 88.0;
174 }
175 if (cff_dict_known(cffont->topdict, "ItalicAngle")) {
176 italicangle = cff_dict_get(cffont->topdict, "ItalicAngle", 0);
177 if (italicangle != 0.0)
178 flags |= FONT_FLAG_ITALIC;
179 } else {
180 italicangle = 0.0;
181 }
182
183 /*
184 * Use "space", "H", "p", and "b" for various values.
185 * Those characters should not "seac". (no accent)
186 */
187 gid = cff_glyph_lookup(cffont, "space");
188 if (gid >= 0 && gid < cffont->cstrings->count) {
189 t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1,
190 cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid],
191 cffont->subrs[0], &gm);
192 defaultwidth = gm.wx;
193 }
194
195 for (i = 0; L_c[i] != NULL; i++) {
196 gid = cff_glyph_lookup(cffont, L_c[i]);
197 if (gid >= 0 && gid < cffont->cstrings->count) {
198 t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1,
199 cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid],
200 cffont->subrs[0], &gm);
201 capheight = gm.bbox.ury;
202 break;
203 }
204 }
205
206 for (i = 0; L_d[i] != NULL; i++) {
207 gid = cff_glyph_lookup(cffont, L_d[i]);
208 if (gid >= 0 && gid < cffont->cstrings->count) {
209 t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1,
210 cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid],
211 cffont->subrs[0], &gm);
212 descent = gm.bbox.lly;
213 break;
214 }
215 }
216
217 for (i = 0; L_a[i] != NULL; i++) {
218 gid = cff_glyph_lookup(cffont, L_a[i]);
219 if (gid >= 0 && gid < cffont->cstrings->count) {
220 t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1,
221 cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid],
222 cffont->subrs[0], &gm);
223 ascent = gm.bbox.ury;
224 break;
225 }
226 }
227
228 if (defaultwidth != 0.0) {
229 cff_dict_add(cffont->private[0], "defaultWidthX", 1);
230 cff_dict_set(cffont->private[0], "defaultWidthX", 0, defaultwidth);
231 }
232 if (nominalwidth != 0.0) {
233 cff_dict_add(cffont->private[0], "nominalWidthX", 1);
234 cff_dict_set(cffont->private[0], "nominalWidthX", 0, nominalwidth);
235 }
236 if (cff_dict_known(cffont->private[0], "ForceBold") &&
237 cff_dict_get(cffont->private[0], "ForceBold", 0)) {
238 flags |= FONT_FLAG_FORCEBOLD;
239 }
240 if (cff_dict_known(cffont->private[0], "IsFixedPitch") &&
241 cff_dict_get(cffont->private[0], "IsFixedPitch", 0)) {
242 flags |= FONT_FLAG_FIXEDPITCH;
243 }
244
245 fontname = pdf_font_get_fontname (font);
246 descriptor = pdf_font_get_descriptor(font);
247
248 if (fontname && !strstr(fontname, "Sans")) {
249 flags |= FONT_FLAG_SERIF;
250 }
251 if (fontname && strstr(fontname, "Caps")) {
252 flags |= FONT_FLAG_SMALLCAP;
253 }
254 flags |= FONT_FLAG_SYMBOLIC; /* FIXME */
255
256 pdf_add_dict(descriptor,
257 pdf_new_name("CapHeight"), pdf_new_number(capheight));
258 pdf_add_dict(descriptor,
259 pdf_new_name("Ascent"), pdf_new_number(ascent));
260 pdf_add_dict(descriptor,
261 pdf_new_name("Descent"), pdf_new_number(descent));
262 pdf_add_dict(descriptor,
263 pdf_new_name("ItalicAngle"), pdf_new_number(italicangle));
264 pdf_add_dict(descriptor,
265 pdf_new_name("StemV"), pdf_new_number(stemv));
266 pdf_add_dict(descriptor,
267 pdf_new_name("Flags"), pdf_new_number(flags));
268 }
269
270 static void
add_metrics(pdf_font * font,cff_font * cffont,char ** enc_vec,double * widths,long num_glyphs)271 add_metrics (pdf_font *font, cff_font *cffont, char **enc_vec, double *widths, long num_glyphs)
272 {
273 pdf_obj *fontdict, *descriptor;
274 pdf_obj *tmp_array;
275 int code, firstchar, lastchar;
276 double val;
277 int i, tfm_id;
278 char *usedchars;
279 double scaling;
280
281 fontdict = pdf_font_get_resource (font);
282 descriptor = pdf_font_get_descriptor(font);
283 usedchars = pdf_font_get_usedchars (font);
284
285 /*
286 * The original FontBBox of the font is preserved, instead
287 * of replacing it with tight bounding box calculated from
288 * charstrings, to prevent Acrobat 4 from greeking text as
289 * much as possible.
290 */
291 if (!cff_dict_known(cffont->topdict, "FontBBox")) {
292 ERROR("No FontBBox?");
293 }
294
295 /* The widhts array in the font dictionary must be given relative
296 * to the default scaling of 1000:1, not relative to the scaling
297 * given by the font matrix.
298 */
299 if (cff_dict_known(cffont->topdict, "FontMatrix"))
300 scaling = 1000*cff_dict_get(cffont->topdict, "FontMatrix", 0);
301 else
302 scaling = 1;
303
304 tmp_array = pdf_new_array();
305 for (i = 0; i < 4; i++) {
306 val = cff_dict_get(cffont->topdict, "FontBBox", i);
307 pdf_add_array(tmp_array, pdf_new_number(ROUND(val, 1.0)));
308 }
309 pdf_add_dict(descriptor, pdf_new_name("FontBBox"), tmp_array);
310
311 tmp_array = pdf_new_array();
312 if (num_glyphs <= 1) { /* This must be an error. */
313 firstchar = lastchar = 0;
314 pdf_add_array(tmp_array, pdf_new_number(0.0));
315 } else {
316 for (firstchar = 255, lastchar = 0, code = 0; code < 256; code++) {
317 if (usedchars[code]) {
318 if (code < firstchar) firstchar = code;
319 if (code > lastchar) lastchar = code;
320 }
321 }
322 if (firstchar > lastchar) {
323 WARN("No glyphs actually used???");
324 pdf_release_obj(tmp_array);
325 return;
326 }
327 tfm_id = tfm_open(pdf_font_get_mapname(font), 0);
328 for (code = firstchar; code <= lastchar; code++) {
329 if (usedchars[code]) {
330 double width;
331 if (tfm_id < 0) /* tfm is not found */
332 width = scaling * widths[cff_glyph_lookup(cffont, enc_vec[code])];
333 else
334 width = 1000. * tfm_get_width(tfm_id, code);
335 pdf_add_array(tmp_array,
336 pdf_new_number(ROUND(width, 0.1)));
337 } else {
338 pdf_add_array(tmp_array, pdf_new_number(0.0));
339 }
340 }
341 }
342
343 if (pdf_array_length(tmp_array) > 0) {
344 pdf_add_dict(fontdict,
345 pdf_new_name("Widths"), pdf_ref_obj(tmp_array));
346 }
347 pdf_release_obj(tmp_array);
348
349 pdf_add_dict(fontdict,
350 pdf_new_name("FirstChar"), pdf_new_number(firstchar));
351 pdf_add_dict(fontdict,
352 pdf_new_name("LastChar"), pdf_new_number(lastchar));
353
354 return;
355 }
356
357
358 static long
write_fontfile(pdf_font * font,cff_font * cffont)359 write_fontfile (pdf_font *font, cff_font *cffont)
360 {
361 pdf_obj *descriptor;
362 pdf_obj *fontfile, *stream_dict;
363 cff_index *topdict;
364 long private_size, stream_data_len, charstring_len;
365 long topdict_offset, offset;
366 #define WBUF_SIZE 1024
367 card8 *stream_data_ptr, wbuf[WBUF_SIZE];
368
369 descriptor = pdf_font_get_descriptor(font);
370
371 topdict = cff_new_index(1);
372 /*
373 * Force existence of Encoding.
374 */
375 if (!cff_dict_known(cffont->topdict, "CharStrings"))
376 cff_dict_add(cffont->topdict, "CharStrings", 1);
377 if (!cff_dict_known(cffont->topdict, "charset"))
378 cff_dict_add(cffont->topdict, "charset", 1);
379 if (!cff_dict_known(cffont->topdict, "Encoding"))
380 cff_dict_add(cffont->topdict, "Encoding", 1);
381 private_size = cff_dict_pack((cffont->private)[0], wbuf, WBUF_SIZE);
382 /* Private dict is required (but may have size 0) */
383 if (!cff_dict_known(cffont->topdict, "Private"))
384 cff_dict_add(cffont->topdict, "Private", 2);
385 topdict->offset[1] = cff_dict_pack(cffont->topdict, wbuf, WBUF_SIZE) + 1;
386
387 /*
388 * Estimate total size of fontfile.
389 */
390 charstring_len = cff_index_size(cffont->cstrings);
391
392 stream_data_len = 4; /* header size */
393 stream_data_len += cff_index_size(cffont->name);
394 stream_data_len += cff_index_size(topdict);
395 stream_data_len += cff_index_size(cffont->string);
396 stream_data_len += cff_index_size(cffont->gsubr);
397 /* We are using format 1 for Encoding and format 0 for charset.
398 * TODO: Should implement cff_xxx_size().
399 */
400 stream_data_len += 2 + (cffont->encoding->num_entries)*2 + 1 + (cffont->encoding->num_supps)*3;
401 stream_data_len += 1 + (cffont->charsets->num_entries)*2;
402 stream_data_len += charstring_len;
403 stream_data_len += private_size;
404
405 /*
406 * Now we create FontFile data.
407 */
408 stream_data_ptr = NEW(stream_data_len, card8);
409 /*
410 * Data Layout order as described in CFF spec., sec 2 "Data Layout".
411 */
412 offset = 0;
413 /* Header */
414 offset += cff_put_header(cffont,
415 stream_data_ptr + offset, stream_data_len - offset);
416 /* Name */
417 offset += cff_pack_index(cffont->name,
418 stream_data_ptr + offset, stream_data_len - offset);
419 /* Top DICT */
420 topdict_offset = offset;
421 offset += cff_index_size(topdict);
422 /* Strings */
423 offset += cff_pack_index(cffont->string,
424 stream_data_ptr + offset, stream_data_len - offset);
425 /* Global Subrs */
426 offset += cff_pack_index(cffont->gsubr,
427 stream_data_ptr + offset, stream_data_len - offset);
428 /* Encoding */
429 /* TODO: don't write Encoding entry if the font is always used
430 * with PDF Encoding information. Applies to type1c.c as well.
431 */
432 cff_dict_set(cffont->topdict, "Encoding", 0, offset);
433 offset += cff_pack_encoding(cffont,
434 stream_data_ptr + offset, stream_data_len - offset);
435 /* charset */
436 cff_dict_set(cffont->topdict, "charset", 0, offset);
437 offset += cff_pack_charsets(cffont,
438 stream_data_ptr + offset, stream_data_len - offset);
439 /* CharStrings */
440 cff_dict_set(cffont->topdict, "CharStrings", 0, offset);
441 offset += cff_pack_index(cffont->cstrings,
442 stream_data_ptr + offset, charstring_len);
443 /* Private */
444 if ((cffont->private)[0] && private_size > 0) {
445 private_size = cff_dict_pack(cffont->private[0],
446 stream_data_ptr + offset, private_size);
447 cff_dict_set(cffont->topdict, "Private", 1, offset);
448 cff_dict_set(cffont->topdict, "Private", 0, private_size);
449 }
450 offset += private_size;
451
452 /* Finally Top DICT */
453 topdict->data = NEW(topdict->offset[1] - 1, card8);
454 cff_dict_pack (cffont->topdict, topdict->data, topdict->offset[1] - 1);
455 cff_pack_index(topdict,
456 stream_data_ptr + topdict_offset, cff_index_size(topdict));
457 cff_release_index(topdict);
458
459 /* Copyright and Trademark Notice ommited. */
460
461 /* Flush Font File */
462 fontfile = pdf_new_stream(STREAM_COMPRESS);
463 stream_dict = pdf_stream_dict(fontfile);
464 pdf_add_dict(descriptor,
465 pdf_new_name("FontFile3"), pdf_ref_obj (fontfile));
466 pdf_add_dict(stream_dict,
467 pdf_new_name("Subtype"), pdf_new_name("Type1C"));
468 pdf_add_stream (fontfile, (void *) stream_data_ptr, offset);
469 pdf_release_obj(fontfile);
470
471 RELEASE(stream_data_ptr);
472
473 return offset;
474 }
475
476
477 int
pdf_font_load_type1(pdf_font * font)478 pdf_font_load_type1 (pdf_font *font)
479 {
480 pdf_obj *fontdict;
481 int encoding_id;
482 char *usedchars, *ident;
483 char *fontname, *uniqueTag;
484 char *fullname; /* With pseudo unique tag */
485 cff_font *cffont;
486 cff_charsets *charset;
487 char **enc_vec;
488 double defaultwidth, nominalwidth;
489 double *widths;
490 card16 *GIDMap, num_glyphs = 0;
491 FILE *fp;
492 long offset;
493 int code, verbose;
494
495 ASSERT(font);
496
497 if (!pdf_font_is_in_use(font)) {
498 return 0;
499 }
500
501 verbose = pdf_font_get_verbose();
502
503 encoding_id = pdf_font_get_encoding (font);
504 fontdict = pdf_font_get_resource (font);
505
506 pdf_font_get_descriptor(font);
507 usedchars = pdf_font_get_usedchars (font);
508 ident = pdf_font_get_ident (font);
509 fontname = pdf_font_get_fontname (font);
510 uniqueTag = pdf_font_get_uniqueTag (font);
511 if (!usedchars || !ident || !fontname) {
512 ERROR("Type1: Unexpected error.");
513 }
514
515 fp = DPXFOPEN(ident, DPX_RES_TYPE_T1FONT);
516 if (!fp) {
517 ERROR("Type1: Could not open Type1 font: %s", ident);
518 }
519
520 GIDMap = NULL;
521 num_glyphs = 0;
522
523 if (encoding_id >= 0) {
524 enc_vec = NULL;
525 } else {
526 enc_vec = NEW(256, char *);
527 for (code = 0; code <= 0xff; code++) {
528 enc_vec[code] = NULL;
529 }
530 }
531
532 cffont = t1_load_font(enc_vec, 0, fp);
533 if (!cffont) {
534 ERROR("Could not load Type 1 font: %s", ident);
535 }
536 DPXFCLOSE(fp);
537
538 fullname = NEW(strlen(fontname) + 8, char);
539 sprintf(fullname, "%6s+%s", uniqueTag, fontname);
540
541 /*
542 * Encoding related things.
543 */
544 if (encoding_id >= 0) {
545 enc_vec = pdf_encoding_get_encoding(encoding_id);
546 } else {
547 pdf_obj *tounicode;
548
549 /*
550 * Create enc_vec and ToUnicode CMap for built-in encoding.
551 */
552 if (!pdf_lookup_dict(fontdict, "ToUnicode")) {
553 tounicode = pdf_create_ToUnicode_CMap(fullname,
554 enc_vec, usedchars);
555 if (tounicode) {
556 pdf_add_dict(fontdict,
557 pdf_new_name("ToUnicode"),
558 pdf_ref_obj (tounicode));
559 pdf_release_obj(tounicode);
560 }
561 }
562 }
563
564 cff_set_name(cffont, fullname);
565 RELEASE(fullname);
566
567 /* defaultWidthX, CapHeight, etc. */
568 get_font_attr(font, cffont);
569 if (cff_dict_known(cffont->private[0], "defaultWidthX")) {
570 defaultwidth = cff_dict_get(cffont->private[0], "defaultWidthX", 0);
571 } else {
572 defaultwidth = 0.0;
573 }
574 if (cff_dict_known(cffont->private[0], "nominalWidthX")) {
575 nominalwidth = cff_dict_get(cffont->private[0], "nominalWidthX", 0);
576 } else {
577 nominalwidth = 0.0;
578 }
579
580 /* Create CFF encoding, charset, sort glyphs */
581 #define MAX_GLYPHS 1024
582 GIDMap = NEW(MAX_GLYPHS, card16);
583 {
584 int prev, duplicate;
585 long gid;
586 char *glyph;
587 s_SID sid;
588
589 cffont->encoding = NEW(1, cff_encoding);
590 cffont->encoding->format = 1;
591 cffont->encoding->num_entries = 0;
592 cffont->encoding->data.range1 = NEW(256, cff_range1);
593 cffont->encoding->num_supps = 0;
594 cffont->encoding->supp = NEW(256, cff_map);
595
596 charset = NEW(1, cff_charsets);
597 charset->format = 0;
598 charset->num_entries = 0;
599 charset->data.glyphs = NEW(MAX_GLYPHS, s_SID);
600
601 gid = cff_glyph_lookup(cffont, ".notdef");
602 if (gid < 0)
603 ERROR("Type 1 font with no \".notdef\" glyph???");
604 GIDMap[0] = (card16) gid;
605 if (verbose > 2)
606 MESG("[glyphs:/.notdef");
607 num_glyphs = 1;
608 for (prev = -2, code = 0; code <= 0xff; code++) {
609 glyph = enc_vec[code];
610
611 if (!usedchars[code])
612 continue;
613 if (glyph && !strcmp(glyph, ".notdef")) {
614 WARN("Character mapped to .notdef used in font: %s",
615 fontname);
616 usedchars[code] = 0;
617 continue;
618 }
619
620 gid = cff_glyph_lookup(cffont, glyph);
621 if (gid < 1 || gid >= cffont->cstrings->count) {
622 WARN("Glyph \"%s\" missing in font \"%s\".", glyph, fontname);
623 usedchars[code] = 0;
624 continue;
625 }
626
627 for (duplicate = 0; duplicate < code; duplicate++) {
628 if (usedchars[duplicate] &&
629 enc_vec[duplicate] && !strcmp(enc_vec[duplicate], glyph))
630 break;
631 }
632
633 sid = cff_add_string(cffont, glyph, 1); /* FIXME */
634 if (duplicate < code) { /* found duplicates */
635 cffont->encoding->supp[cffont->encoding->num_supps].code = duplicate;
636 cffont->encoding->supp[cffont->encoding->num_supps].glyph = sid;
637 cffont->encoding->num_supps += 1;
638 } else {
639 GIDMap[num_glyphs] = (card16) gid;
640 charset->data.glyphs[charset->num_entries] = sid;
641 charset->num_entries += 1;
642 if (code != prev + 1) {
643 cffont->encoding->num_entries += 1;
644 cffont->encoding->data.range1[cffont->encoding->num_entries-1].first = code;
645 cffont->encoding->data.range1[cffont->encoding->num_entries-1].n_left = 0;
646 } else {
647 cffont->encoding->data.range1[cffont->encoding->num_entries-1].n_left += 1;
648 }
649 prev = code;
650 num_glyphs++;
651
652 if (verbose > 2) {
653 MESG("/%s", glyph);
654 }
655
656 }
657 }
658 if (cffont->encoding->num_supps > 0) {
659 cffont->encoding->format |= 0x80;
660 } else {
661 RELEASE(cffont->encoding->supp); /* FIXME */
662 cffont->encoding->supp = NULL;
663 }
664 }
665
666 widths = NEW(cffont->cstrings->count, double);
667 /*
668 * No more string will be added.
669 * The Type 1 seac operator may add another glyph but the glyph name of
670 * those glyphs are contained in standard string. The String Index will
671 * not be modified after here.
672 * BUT: We cannot update the String Index yet because then we wouldn't be
673 * able to find the GIDs of the base and accent characters (unless they
674 * have been used already).
675 */
676
677 {
678 cff_index *cstring;
679 t1_ginfo gm;
680 card16 gid, gid_orig;
681 long dstlen_max, srclen;
682 card8 *srcptr, *dstptr;
683
684 offset = dstlen_max = 0L;
685 cstring = cff_new_index(cffont->cstrings->count);
686 cstring->data = NULL;
687 cstring->offset[0] = 1;
688
689 /* The num_glyphs increases if "seac" operators are used. */
690 for (gid = 0; gid < num_glyphs; gid++) {
691 if (offset + CS_STR_LEN_MAX >= dstlen_max) {
692 dstlen_max += CS_STR_LEN_MAX * 2;
693 cstring->data = RENEW(cstring->data, dstlen_max, card8);
694 }
695 gid_orig = GIDMap[gid];
696
697 dstptr = cstring->data + cstring->offset[gid] - 1;
698 srcptr = cffont->cstrings->data + cffont->cstrings->offset[gid_orig] - 1;
699 srclen = cffont->cstrings->offset[gid_orig + 1] - cffont->cstrings->offset[gid_orig];
700
701 offset += t1char_convert_charstring(dstptr, CS_STR_LEN_MAX,
702 srcptr, srclen,
703 cffont->subrs[0], defaultwidth, nominalwidth, &gm);
704 cstring->offset[gid + 1] = offset + 1;
705 if (gm.use_seac) {
706 long bchar_gid, achar_gid, i;
707 const char *bchar_name, *achar_name;
708
709 /*
710 * NOTE:
711 * 1. seac.achar and seac.bchar must be contained in the CFF standard string.
712 * 2. Those characters need not to be encoded.
713 * 3. num_glyphs == charsets->num_entries + 1.
714 */
715 achar_name = t1_get_standard_glyph(gm.seac.achar);
716 achar_gid = cff_glyph_lookup(cffont, achar_name);
717 bchar_name = t1_get_standard_glyph(gm.seac.bchar);
718 bchar_gid = cff_glyph_lookup(cffont, bchar_name);
719 if (achar_gid < 0) {
720 WARN("Accent char \"%s\" not found. Invalid use of \"seac\" operator.",
721 achar_name);
722 continue;
723 }
724 if (bchar_gid < 0) {
725 WARN("Base char \"%s\" not found. Invalid use of \"seac\" operator.",
726 bchar_name);
727 continue;
728 }
729
730 for (i = 0; i < num_glyphs; i++) {
731 if (GIDMap[i] == achar_gid)
732 break;
733 }
734 if (i == num_glyphs) {
735 if (verbose > 2)
736 MESG("/%s", achar_name);
737 GIDMap[num_glyphs++] = achar_gid;
738 charset->data.glyphs[charset->num_entries] = cff_get_seac_sid(cffont, achar_name);
739 charset->num_entries += 1;
740 }
741
742 for (i = 0; i < num_glyphs; i++) {
743 if (GIDMap[i] == bchar_gid)
744 break;
745 }
746 if (i == num_glyphs) {
747 if (verbose > 2)
748 MESG("/%s", bchar_name);
749 GIDMap[num_glyphs++] = bchar_gid;
750 charset->data.glyphs[charset->num_entries] = cff_get_seac_sid(cffont, bchar_name);
751 charset->num_entries += 1;
752 }
753 }
754 widths[gid] = gm.wx;
755 }
756 cstring->count = num_glyphs;
757
758 cff_release_index(cffont->subrs[0]);
759 cffont->subrs[0] = NULL;
760 RELEASE(cffont->subrs);
761 cffont->subrs = NULL;
762
763 cff_release_index(cffont->cstrings);
764 cffont->cstrings = cstring;
765
766 cff_release_charsets(cffont->charsets);
767 cffont->charsets = charset;
768 }
769 if (verbose > 2)
770 MESG("]");
771
772 /* Now we can update the String Index */
773 cff_dict_update (cffont->topdict, cffont);
774 cff_dict_update (cffont->private[0], cffont);
775 cff_update_string(cffont);
776
777 add_metrics(font, cffont, enc_vec, widths, num_glyphs);
778
779 offset = write_fontfile(font, cffont);
780 if (verbose > 1)
781 MESG("[%u glyphs][%ld bytes]", num_glyphs, offset);
782
783 cff_close(cffont);
784
785 /* Cleanup */
786 if (encoding_id < 0 && enc_vec) {
787 for (code = 0; code < 256; code++) {
788 if (enc_vec[code])
789 RELEASE(enc_vec[code]);
790 enc_vec[code] = NULL;
791 }
792 RELEASE(enc_vec);
793 }
794 if (widths)
795 RELEASE(widths);
796 if (GIDMap)
797 RELEASE(GIDMap);
798
799 /*
800 * Maybe writing Charset is recommended for subsetted font.
801 */
802
803 return 0;
804 }
805