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 <time.h>
29
30 #include "system.h"
31 #include "error.h"
32 #include "mem.h"
33
34 #include "dpxfile.h"
35 #include "dpxutil.h"
36
37 #include "pdfobj.h"
38
39 #include "agl.h"
40 #include "pdfencoding.h"
41 #include "cmap.h"
42 #include "unicode.h"
43
44 #include "type1.h"
45 #include "type1c.h"
46 #include "truetype.h"
47
48 #include "pkfont.h"
49
50 #include "type0.h"
51 #include "tt_cmap.h"
52 #include "cidtype0.h"
53 #include "otl_conf.h"
54
55 #include "pdffont.h"
56
57 static int __verbose = 0;
58
59 #define MREC_HAS_TOUNICODE(m) ((m) && (m)->opt.tounicode)
60
61 void
pdf_font_set_verbose(void)62 pdf_font_set_verbose (void)
63 {
64 __verbose++;
65 CMap_set_verbose();
66 Type0Font_set_verbose();
67 CIDFont_set_verbose ();
68 pdf_encoding_set_verbose();
69 UC_set_verbose ();
70 agl_set_verbose();
71 otl_conf_set_verbose();
72 otf_cmap_set_verbose ();
73 }
74
75 int
pdf_font_get_verbose(void)76 pdf_font_get_verbose (void)
77 {
78 return __verbose;
79 }
80
81 void
pdf_font_set_dpi(int font_dpi)82 pdf_font_set_dpi (int font_dpi)
83 {
84 PKFont_set_dpi(font_dpi);
85 }
86
87 void
pdf_font_make_uniqueTag(char * tag)88 pdf_font_make_uniqueTag (char *tag)
89 {
90 int i;
91 char ch;
92 static char first = 1;
93
94 if (first) {
95 srand(time(NULL));
96 first = 0;
97 }
98
99 for (i = 0; i < 6; i++) {
100 ch = rand() % 26;
101 tag[i] = ch + 'A';
102 }
103 tag[6] = '\0';
104 }
105
106
107 struct pdf_font
108 {
109 char *ident;
110 int subtype;
111
112 char *map_name;
113
114 int encoding_id; /* encoding or CMap */
115
116 /*
117 * If subtype is Type0, it simply points font_id
118 * of Type0 font. Type0 and simple font is not
119 * unified yet.
120 */
121 int font_id;
122
123 /* For simple font */
124 int index;
125 char *fontname;
126 char uniqueID[7];
127
128 /*
129 * PDF font resource objects
130 */
131 pdf_obj *reference;
132 pdf_obj *resource;
133 pdf_obj *descriptor;
134
135 /*
136 * Font format specific data
137 */
138 char *usedchars;
139 int flags;
140
141 /* PK font */
142 double point_size;
143 double design_size;
144 };
145
146 static void
pdf_init_font_struct(pdf_font * font)147 pdf_init_font_struct (pdf_font *font)
148 {
149 ASSERT(font);
150
151 font->ident = NULL;
152 font->map_name = NULL;
153 font->subtype = -1;
154 font->font_id = -1; /* Type0 ID */
155 font->fontname = NULL;
156 memset(font->uniqueID, 0, 7);
157 font->index = 0;
158
159 font->encoding_id = -1;
160
161 font->reference = NULL;
162 font->resource = NULL;
163 font->descriptor = NULL;
164
165 font->point_size = 0;
166 font->design_size = 0;
167
168 font->usedchars = NULL;
169 font->flags = 0;
170
171 return;
172 }
173
174 static void
pdf_flush_font(pdf_font * font)175 pdf_flush_font (pdf_font *font)
176 {
177 char *fontname, *uniqueTag;
178
179 if (!font) {
180 return;
181 }
182
183 if (font->resource && font->reference) {
184 if (font->subtype != PDF_FONT_FONTTYPE_TYPE3) {
185 if (pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED)) {
186 pdf_add_dict(font->resource,
187 pdf_new_name("BaseFont"), pdf_new_name(font->fontname));
188 if (font->descriptor) {
189 pdf_add_dict(font->descriptor,
190 pdf_new_name("FontName"), pdf_new_name(font->fontname));
191 }
192 } else {
193 if (!font->fontname) {
194 ERROR("Undefined in fontname... (%s)", font->ident);
195 }
196 fontname = NEW(7+strlen(font->fontname)+1, char);
197 uniqueTag = pdf_font_get_uniqueTag(font);
198 sprintf(fontname, "%6s+%s", uniqueTag, font->fontname);
199 pdf_add_dict(font->resource,
200 pdf_new_name("BaseFont"), pdf_new_name(fontname));
201 if (font->descriptor) {
202 pdf_add_dict(font->descriptor,
203 pdf_new_name("FontName"), pdf_new_name(fontname));
204 }
205 RELEASE(fontname);
206 }
207 if (font->descriptor) {
208 pdf_add_dict(font->resource,
209 pdf_new_name("FontDescriptor"), pdf_ref_obj(font->descriptor));
210 }
211 }
212 }
213
214 if (font->resource)
215 pdf_release_obj(font->resource);
216 if (font->descriptor)
217 pdf_release_obj(font->descriptor);
218 if (font->reference)
219 pdf_release_obj(font->reference);
220
221 font->reference = NULL;
222 font->resource = NULL;
223 font->descriptor = NULL;
224
225 return;
226 }
227
228 static void
pdf_clean_font_struct(pdf_font * font)229 pdf_clean_font_struct (pdf_font *font)
230 {
231 if (font) {
232 if (font->ident)
233 RELEASE(font->ident);
234 if (font->map_name)
235 RELEASE(font->map_name);
236 if (font->fontname)
237 RELEASE(font->fontname);
238 if (font->usedchars)
239 RELEASE(font->usedchars);
240
241 if (font->reference)
242 ERROR("pdf_font>> Object not flushed.");
243 if (font->resource)
244 ERROR("pdf_font> Object not flushed.");
245 if (font->descriptor)
246 ERROR("pdf_font>> Object not flushed.");
247
248 font->ident = NULL;
249 font->map_name = NULL;
250 font->fontname = NULL;
251 font->usedchars = NULL;
252 }
253
254 return;
255 }
256
257 #define CACHE_ALLOC_SIZE 16u
258
259 static struct {
260 int count;
261 int capacity;
262 pdf_font *fonts;
263 } font_cache = {
264 0, 0, NULL
265 };
266
267 void
pdf_init_fonts(void)268 pdf_init_fonts (void)
269 {
270 ASSERT(font_cache.fonts == NULL);
271
272 agl_init_map();
273 otl_init_conf();
274
275 CMap_cache_init();
276 pdf_init_encodings();
277
278 Type0Font_cache_init();
279
280 font_cache.count = 0;
281 font_cache.capacity = CACHE_ALLOC_SIZE;
282 font_cache.fonts = NEW(font_cache.capacity, pdf_font);
283 }
284
285 #define CHECK_ID(n) do {\
286 if ((n) < 0 || (n) >= font_cache.count) {\
287 ERROR("Invalid font ID: %d", (n));\
288 }\
289 } while (0)
290 #define GET_FONT(n) (&(font_cache.fonts[(n)]))
291
292
293 pdf_obj *
pdf_get_font_reference(int font_id)294 pdf_get_font_reference (int font_id)
295 {
296 pdf_font *font;
297
298 CHECK_ID(font_id);
299
300 font = GET_FONT(font_id);
301 if (font->subtype == PDF_FONT_FONTTYPE_TYPE0) {
302 Type0Font *t0font;
303
304 t0font = Type0Font_cache_get(font->font_id);
305 return Type0Font_get_resource(t0font);
306 } else {
307 if (!font->reference) {
308 font->reference = pdf_ref_obj(pdf_font_get_resource(font));
309 }
310 }
311
312 return pdf_link_obj(font->reference);
313 }
314
315 char *
pdf_get_font_usedchars(int font_id)316 pdf_get_font_usedchars (int font_id)
317 {
318 pdf_font *font;
319
320 CHECK_ID(font_id);
321
322 font = GET_FONT(font_id);
323 if (font->subtype == PDF_FONT_FONTTYPE_TYPE0) {
324 Type0Font *t0font;
325
326 t0font = Type0Font_cache_get(font->font_id);
327 return Type0Font_get_usedchars(t0font);
328 } else {
329 if (!font->usedchars) {
330 font->usedchars = NEW(256, char);
331 memset(font->usedchars, 0, 256 * sizeof(char));
332 }
333 return font->usedchars;
334 }
335 }
336
337 int
pdf_get_font_wmode(int font_id)338 pdf_get_font_wmode (int font_id)
339 {
340 pdf_font *font;
341
342 CHECK_ID(font_id);
343
344 font = GET_FONT(font_id);
345 if (font->subtype == PDF_FONT_FONTTYPE_TYPE0) {
346 Type0Font *t0font;
347
348 t0font = Type0Font_cache_get(font->font_id);
349 return Type0Font_get_wmode(t0font);
350 } else {
351 return 0;
352 }
353 }
354
355 int
pdf_get_font_subtype(int font_id)356 pdf_get_font_subtype (int font_id)
357 {
358 pdf_font *font;
359
360 CHECK_ID(font_id);
361
362 font = GET_FONT(font_id);
363
364 return font->subtype;
365 }
366
367 #if 0
368 char *
369 pdf_get_font_fontname (int font_id)
370 {
371 pdf_font *font;
372
373 CHECK_ID(font_id);
374
375 font = GET_FONT(font_id);
376
377 return font->fontname;
378 }
379 #endif /* 0 */
380
381 int
pdf_get_font_encoding(int font_id)382 pdf_get_font_encoding (int font_id)
383 {
384 pdf_font *font;
385
386 CHECK_ID(font_id);
387
388 font = GET_FONT(font_id);
389
390 return font->encoding_id;
391 }
392
393 /* The rule for ToUnicode creation is:
394 *
395 * If "tounicode" option is specified in fontmap, use that.
396 * If there is ToUnicode CMap with same name as TFM, use that.
397 * If no "tounicode" option is used and no ToUnicode CMap with
398 * same name as TFM is found, create ToUnicode CMap from glyph
399 * names and AGL file.
400 */
401 static int
try_load_ToUnicode_CMap(pdf_font * font)402 try_load_ToUnicode_CMap (pdf_font *font)
403 {
404 pdf_obj *fontdict;
405 pdf_obj *tounicode;
406 const char *cmap_name = NULL;
407 fontmap_rec *mrec; /* Be sure fontmap is still alive here */
408
409 ASSERT(font);
410
411 /* We are using different encoding for Type0 font.
412 * This feature is unavailable for them.
413 */
414 if (font->subtype == PDF_FONT_FONTTYPE_TYPE0)
415 return 0;
416
417 ASSERT(font->map_name);
418
419 mrec = pdf_lookup_fontmap_record(font->map_name);
420 if (MREC_HAS_TOUNICODE(mrec))
421 cmap_name = mrec->opt.tounicode;
422 else {
423 cmap_name = font->map_name;
424 }
425
426 fontdict = pdf_font_get_resource(font);
427 tounicode = pdf_load_ToUnicode_stream(cmap_name);
428 if (!tounicode && MREC_HAS_TOUNICODE(mrec))
429 WARN("Failed to read ToUnicode mapping \"%s\"...", mrec->opt.tounicode);
430 else if (tounicode) {
431 if (pdf_obj_typeof(tounicode) != PDF_STREAM)
432 ERROR("Object returned by pdf_load_ToUnicode_stream() not stream object! (This must be bug)");
433 else if (pdf_stream_length(tounicode) > 0) {
434 pdf_add_dict(fontdict,
435 pdf_new_name("ToUnicode"),
436 pdf_ref_obj (tounicode)); /* _FIXME_ */
437 if (__verbose)
438 MESG("pdf_font>> ToUnicode CMap \"%s\" attached to font id=\"%s\".\n",
439 cmap_name, font->map_name);
440 }
441 pdf_release_obj(tounicode);
442 }
443
444 return 0;
445 }
446
447 void
pdf_close_fonts(void)448 pdf_close_fonts (void)
449 {
450 int font_id;
451
452 for (font_id = 0;
453 font_id < font_cache.count; font_id++) {
454 pdf_font *font;
455
456 font = GET_FONT(font_id);
457
458 if (__verbose) {
459 if (font->subtype != PDF_FONT_FONTTYPE_TYPE0) {
460 MESG("(%s", pdf_font_get_ident(font));
461 if (__verbose > 2 &&
462 !pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED)) {
463 MESG("[%s+%s]",
464 pdf_font_get_uniqueTag(font),
465 pdf_font_get_fontname(font));
466 } else if (__verbose > 1) {
467 MESG("[%s]",
468 pdf_font_get_fontname(font));
469 }
470 if (__verbose > 1) {
471 if (pdf_font_get_encoding(font) >= 0) {
472 MESG("[%s]",
473 pdf_encoding_get_name(pdf_font_get_encoding(font)));
474 } else {
475 MESG("[built-in]");
476 }
477 }
478
479 }
480 }
481
482 /* Must come before load_xxx */
483 try_load_ToUnicode_CMap(font);
484
485 /* Type 0 is handled separately... */
486 switch (font->subtype) {
487 case PDF_FONT_FONTTYPE_TYPE1:
488 if (__verbose)
489 MESG("[Type1]");
490 if (!pdf_font_get_flag(font, PDF_FONT_FLAG_BASEFONT))
491 pdf_font_load_type1(font);
492 break;
493 case PDF_FONT_FONTTYPE_TYPE1C:
494 if (__verbose)
495 MESG("[Type1C]");
496 pdf_font_load_type1c(font);
497 break;
498 case PDF_FONT_FONTTYPE_TRUETYPE:
499 if (__verbose)
500 MESG("[TrueType]");
501 pdf_font_load_truetype(font);
502 break;
503 case PDF_FONT_FONTTYPE_TYPE3:
504 if (__verbose)
505 MESG("[Type3/PK]");
506 pdf_font_load_pkfont (font);
507 break;
508 case PDF_FONT_FONTTYPE_TYPE0:
509 break;
510 default:
511 ERROR("Unknown font type: %d", font->subtype);
512 break;
513 }
514
515 if (font->encoding_id >= 0 && font->subtype != PDF_FONT_FONTTYPE_TYPE0)
516 pdf_encoding_add_usedchars(font->encoding_id, font->usedchars);
517
518 if (__verbose) {
519 if (font->subtype != PDF_FONT_FONTTYPE_TYPE0)
520 MESG(")");
521 }
522 }
523
524 pdf_encoding_complete();
525
526 for (font_id = 0; font_id < font_cache.count; font_id++) {
527 pdf_font *font = GET_FONT(font_id);
528
529 if (font->encoding_id >= 0 && font->subtype != PDF_FONT_FONTTYPE_TYPE0) {
530 pdf_obj *enc_obj = pdf_get_encoding_obj(font->encoding_id);
531 pdf_obj *tounicode;
532
533 /* Predefined encodings (and those simplified to them) are embedded
534 as direct objects, but this is purely a matter of taste. */
535 if (enc_obj)
536 pdf_add_dict(font->resource,
537 pdf_new_name("Encoding"),
538 PDF_OBJ_NAMETYPE(enc_obj) ? pdf_link_obj(enc_obj) : pdf_ref_obj(enc_obj));
539
540 if (!pdf_lookup_dict(font->resource, "ToUnicode")
541 && (tounicode = pdf_encoding_get_tounicode(font->encoding_id)))
542 pdf_add_dict(font->resource,
543 pdf_new_name("ToUnicode"), pdf_ref_obj(tounicode));
544 } else if (font->subtype == PDF_FONT_FONTTYPE_TRUETYPE) {
545 /* encoding_id < 0 means MacRoman here (but not really)
546 * We use MacRoman as "default" encoding. */
547 pdf_add_dict(font->resource,
548 pdf_new_name("Encoding"),
549 pdf_new_name("MacRomanEncoding"));
550 }
551
552 pdf_flush_font(font);
553 pdf_clean_font_struct(font);
554 }
555 RELEASE(font_cache.fonts);
556 font_cache.fonts = NULL;
557 font_cache.count = 0;
558 font_cache.capacity = 0;
559
560 Type0Font_cache_close();
561
562 CMap_cache_close();
563 pdf_close_encodings();
564
565 otl_close_conf();
566 agl_close_map (); /* After encoding */
567
568 return;
569 }
570
571 int
pdf_font_findresource(const char * tex_name,double font_scale,fontmap_rec * mrec)572 pdf_font_findresource (const char *tex_name,
573 double font_scale, fontmap_rec *mrec)
574 {
575 int font_id = -1;
576 pdf_font *font;
577 int encoding_id = -1, cmap_id = -1;
578 const char *fontname;
579
580 /*
581 * Get appropriate info from map file. (PK fonts at two different
582 * point sizes would be looked up twice unecessarily.)
583 */
584 fontname = mrec ? mrec->font_name : tex_name;
585 if (mrec && mrec->enc_name) {
586 #define MAYBE_CMAP(s) (!strstr((s), ".enc") || strstr((s), ".cmap"))
587 if (MAYBE_CMAP(mrec->enc_name)) {
588 cmap_id = CMap_cache_find(mrec->enc_name);
589 if (cmap_id >= 0) {
590 CMap *cmap;
591 int cmap_type, minbytes;
592
593 cmap = CMap_cache_get(cmap_id);
594 cmap_type = CMap_get_type (cmap);
595 minbytes = CMap_get_profile(cmap, CMAP_PROF_TYPE_INBYTES_MIN);
596 /*
597 * Check for output encoding.
598 */
599 if (cmap_type != CMAP_TYPE_IDENTITY &&
600 cmap_type != CMAP_TYPE_CODE_TO_CID &&
601 cmap_type != CMAP_TYPE_TO_UNICODE) {
602 WARN("Only 16-bit encoding supported for output encoding.");
603 }
604 /*
605 * Turn on map option.
606 */
607 if (minbytes == 2 && mrec->opt.mapc < 0) {
608 if (__verbose) {
609 MESG("\n");
610 MESG("pdf_font>> Input encoding \"%s\" requires at least 2 bytes.\n",
611 CMap_get_name(cmap));
612 MESG("pdf_font>> The -m <00> option will be assumed for \"%s\".\n", mrec->font_name);
613 }
614 mrec->opt.mapc = 0; /* _FIXME_ */
615 }
616 } else if (!strcmp(mrec->enc_name, "unicode")) {
617 cmap_id = otf_load_Unicode_CMap(mrec->font_name,
618 mrec->opt.index, mrec->opt.otl_tags,
619 ((mrec->opt.flags & FONTMAP_OPT_VERT) ? 1 : 0));
620 if (cmap_id < 0) {
621 cmap_id = t1_load_UnicodeCMap(mrec->font_name, mrec->opt.otl_tags,
622 ((mrec->opt.flags & FONTMAP_OPT_VERT) ? 1 : 0));
623 }
624 if (cmap_id < 0)
625 ERROR("Failed to read UCS2/UCS4 TrueType cmap...");
626 }
627 }
628 if (cmap_id < 0) {
629 encoding_id = pdf_encoding_findresource(mrec->enc_name);
630 if (encoding_id < 0)
631 ERROR("Could not find encoding file \"%s\".", mrec->enc_name);
632 }
633 }
634
635 if (mrec && cmap_id >= 0) {
636 /*
637 * Composite Font
638 */
639 int type0_id, found = 0;
640
641 type0_id = Type0Font_cache_find(mrec->font_name, cmap_id, &mrec->opt);
642 if (type0_id < 0) {
643 return -1;
644 }
645
646 for (font_id = 0;
647 font_id < font_cache.count; font_id++) {
648 font = GET_FONT(font_id);
649 if (font->subtype == PDF_FONT_FONTTYPE_TYPE0 &&
650 font->font_id == type0_id &&
651 font->encoding_id == cmap_id) {
652 found = 1;
653 if (__verbose) {
654 MESG("\npdf_font>> Type0 font \"%s\" (cmap_id=%d) found at font_id=%d.\n",
655 mrec->font_name, cmap_id, font_id);
656 }
657 break;
658 }
659 }
660
661 if (!found) {
662 font_id = font_cache.count;
663 if (font_cache.count >= font_cache.capacity) {
664 font_cache.capacity += CACHE_ALLOC_SIZE;
665 font_cache.fonts = RENEW(font_cache.fonts, font_cache.capacity, pdf_font);
666 }
667 font = GET_FONT(font_id);
668 pdf_init_font_struct(font);
669
670 font->font_id = type0_id;
671 font->subtype = PDF_FONT_FONTTYPE_TYPE0;
672 font->encoding_id = cmap_id;
673
674 font_cache.count++;
675
676 if (__verbose) {
677 MESG("\npdf_font>> Type0 font \"%s\"", fontname);
678 MESG(" cmap_id=<%s,%d>", mrec->enc_name, font->encoding_id);
679 MESG(" opened at font_id=<%s,%d>.\n", tex_name, font_id);
680 }
681
682 }
683 } else {
684 /*
685 * Simple Font - always embed.
686 */
687 int found = 0;
688
689 for (font_id = 0;
690 font_id < font_cache.count; font_id++) {
691 font = GET_FONT(font_id);
692 switch (font->subtype) {
693 case PDF_FONT_FONTTYPE_TYPE1:
694 case PDF_FONT_FONTTYPE_TYPE1C:
695 case PDF_FONT_FONTTYPE_TRUETYPE:
696 /* fontname here is font file name.
697 * We must compare both font file name and encoding
698 *
699 * TODO: Embed a font only once if it is used
700 * with two different encodings
701 */
702 if (!strcmp(fontname, font->ident) &&
703 encoding_id == font->encoding_id) {
704 if (mrec && mrec->opt.index == font->index)
705 found = 1;
706 }
707 break;
708 case PDF_FONT_FONTTYPE_TYPE3:
709 /* There shouldn't be any encoding specified for PK font.
710 * It must be always font's build-in encoding.
711 *
712 * TODO: a PK font with two encodings makes no sense. Change?
713 */
714 if (!strcmp(fontname, font->ident) &&
715 font_scale == font->point_size) {
716 found = 1;
717 }
718 break;
719 case PDF_FONT_FONTTYPE_TYPE0:
720 break;
721 default:
722 ERROR("Unknown font type: %d", font->subtype);
723 break;
724 }
725
726 if (found) {
727 if (__verbose) {
728 MESG("\npdf_font>> Simple font \"%s\" (enc_id=%d) found at id=%d.\n",
729 fontname, encoding_id, font_id);
730 }
731 break;
732 }
733 }
734
735
736 if (!found) {
737 font_id = font_cache.count;
738 if (font_cache.count >= font_cache.capacity) {
739 font_cache.capacity += CACHE_ALLOC_SIZE;
740 font_cache.fonts = RENEW(font_cache.fonts, font_cache.capacity, pdf_font);
741 }
742
743 font = GET_FONT(font_id);
744
745 pdf_init_font_struct(font);
746
747 font->point_size = font_scale;
748 font->encoding_id = encoding_id;
749 font->ident = NEW(strlen(fontname) + 1, char);
750 strcpy(font->ident, fontname);
751 font->map_name = NEW(strlen(tex_name) + 1, char);
752 strcpy(font->map_name, tex_name);
753 font->index = (mrec && mrec->opt.index) ? mrec->opt.index : 0;
754
755 if (pdf_font_open_type1(font) >= 0) {
756 font->subtype = PDF_FONT_FONTTYPE_TYPE1;
757 } else if (pdf_font_open_type1c(font) >= 0) {
758 font->subtype = PDF_FONT_FONTTYPE_TYPE1C;
759 } else if (pdf_font_open_truetype(font) >= 0) {
760 font->subtype = PDF_FONT_FONTTYPE_TRUETYPE;
761 } else if (pdf_font_open_pkfont(font) >= 0) {
762 font->subtype = PDF_FONT_FONTTYPE_TYPE3;
763 } else {
764 pdf_clean_font_struct(font);
765 return -1;
766 }
767
768 font_cache.count++;
769
770 if (__verbose) {
771 MESG("\npdf_font>> Simple font \"%s\"", fontname);
772 MESG(" enc_id=<%s,%d>",
773 (mrec && mrec->enc_name) ? mrec->enc_name : "builtin", font->encoding_id);
774 MESG(" opened at font_id=<%s,%d>.\n", tex_name, font_id);
775 }
776 }
777 }
778
779 return font_id;
780 }
781
782 int
pdf_font_is_in_use(pdf_font * font)783 pdf_font_is_in_use (pdf_font *font)
784 {
785 ASSERT(font);
786
787 return ((font->reference) ? 1 : 0);
788 }
789
790 int
pdf_font_get_index(pdf_font * font)791 pdf_font_get_index (pdf_font *font)
792 {
793 ASSERT(font);
794
795 return font->index;
796 }
797
798 char *
pdf_font_get_ident(pdf_font * font)799 pdf_font_get_ident (pdf_font *font)
800 {
801 ASSERT(font);
802
803 return font->ident;
804 }
805
806 char *
pdf_font_get_mapname(pdf_font * font)807 pdf_font_get_mapname (pdf_font *font)
808 {
809 ASSERT(font);
810
811 return font->map_name;
812 }
813
814 char *
pdf_font_get_fontname(pdf_font * font)815 pdf_font_get_fontname (pdf_font *font)
816 {
817 ASSERT(font);
818
819 return font->fontname;
820 }
821
822 pdf_obj *
pdf_font_get_resource(pdf_font * font)823 pdf_font_get_resource (pdf_font *font)
824 {
825 ASSERT(font);
826
827 if (!font->resource) {
828 font->resource = pdf_new_dict();
829 pdf_add_dict(font->resource,
830 pdf_new_name("Type"), pdf_new_name("Font"));
831 switch (font->subtype) {
832 case PDF_FONT_FONTTYPE_TYPE1:
833 case PDF_FONT_FONTTYPE_TYPE1C:
834 pdf_add_dict(font->resource,
835 pdf_new_name("Subtype"), pdf_new_name("Type1"));
836 break;
837 case PDF_FONT_FONTTYPE_TYPE3:
838 pdf_add_dict(font->resource,
839 pdf_new_name("Subtype"), pdf_new_name("Type3"));
840 break;
841 case PDF_FONT_FONTTYPE_TRUETYPE:
842 pdf_add_dict(font->resource,
843 pdf_new_name("Subtype"), pdf_new_name("TrueType"));
844 break;
845 default:
846 break;
847 }
848 }
849
850 return font->resource;
851 }
852
853 pdf_obj *
pdf_font_get_descriptor(pdf_font * font)854 pdf_font_get_descriptor (pdf_font *font)
855 {
856 ASSERT(font);
857
858 if (!font->descriptor) {
859 font->descriptor = pdf_new_dict();
860 pdf_add_dict(font->descriptor,
861 pdf_new_name("Type"), pdf_new_name("FontDescriptor"));
862 }
863
864 return font->descriptor;
865 }
866
867 char *
pdf_font_get_usedchars(pdf_font * font)868 pdf_font_get_usedchars (pdf_font *font)
869 {
870 ASSERT(font);
871
872 return font->usedchars;
873 }
874
875 int
pdf_font_get_encoding(pdf_font * font)876 pdf_font_get_encoding (pdf_font *font)
877 {
878 ASSERT(font);
879
880 return font->encoding_id;
881 }
882
883 int
pdf_font_get_flag(pdf_font * font,int mask)884 pdf_font_get_flag (pdf_font *font, int mask)
885 {
886 ASSERT(font);
887
888 return ((font->flags & mask) ? 1 : 0);
889 }
890
891 #if 0
892 int
893 pdf_font_get_flags (pdf_font *font)
894 {
895 ASSERT(font);
896
897 return font->flags;
898 }
899 #endif /* 0 */
900
901 double
pdf_font_get_param(pdf_font * font,int param_type)902 pdf_font_get_param (pdf_font *font, int param_type)
903 {
904 double param = 0.0;
905
906 ASSERT(font);
907
908 switch (param_type) {
909 case PDF_FONT_PARAM_DESIGN_SIZE:
910 param = font->design_size;
911 break;
912 case PDF_FONT_PARAM_POINT_SIZE:
913 param = font->point_size;
914 break;
915 default:
916 break;
917 }
918
919 return param;
920 }
921
922 char *
pdf_font_get_uniqueTag(pdf_font * font)923 pdf_font_get_uniqueTag (pdf_font *font)
924 {
925 ASSERT(font);
926
927 if (font->uniqueID[0] == '\0') {
928 pdf_font_make_uniqueTag(font->uniqueID);
929 }
930
931 return font->uniqueID;
932 }
933
934 int
pdf_font_set_fontname(pdf_font * font,const char * fontname)935 pdf_font_set_fontname (pdf_font *font, const char *fontname)
936 {
937 ASSERT(font && fontname);
938
939 if (strlen(fontname) > PDF_NAME_LEN_MAX) {
940 ERROR("Unexpected error...");
941 return -1;
942 }
943 if (font->fontname) {
944 RELEASE(font->fontname);
945 }
946 font->fontname = NEW(strlen(fontname)+1, char);
947 strcpy(font->fontname, fontname);
948
949 return 0;
950 }
951
952 int
pdf_font_set_subtype(pdf_font * font,int subtype)953 pdf_font_set_subtype (pdf_font *font, int subtype)
954 {
955 ASSERT(font);
956
957 font->subtype = subtype;
958
959 return 0;
960 }
961
962 int
pdf_font_set_flags(pdf_font * font,int flags)963 pdf_font_set_flags (pdf_font *font, int flags)
964 {
965 ASSERT(font);
966
967 font->flags |= flags;
968
969 return 0;
970 }
971
972