3 This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
5 Copyright (C) 2002-2012 by Jin-Hwan Cho and Shunsaku Hirata,
6 the dvipdfmx project team.
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.
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.
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.
24 * CID-keyed font support:
26 * See also, cidtype0, and cidtype2
47 #define CIDFONT_DEBUG 3
48 #define CIDFONT_DEBUG_STR "CIDFont"
50 #define PDF_CID_SUPPORT_MIN 2
51 #define PDF_CID_SUPPORT_MAX 6
54 * Unicode and PDF Standard Character Collections.
56 * Adobe-Identity is only for TrueType fonts and it means font's
57 * internal glyph ordering.
62 /* Heighest Supplement values supported by PDF-1.0, 1.1, ...; see
63 * also http://partners.adobe.com/public/developer/font/index.html#ckf
66 } CIDFont_stdcc_def[] = {
67 {"Adobe", "UCS", {-1, -1, 0, 0, 0, 0, 0, 0}},
68 {"Adobe", "GB1", {-1, -1, 0, 2, 4, 4, 4, 4}},
69 {"Adobe", "CNS1", {-1, -1, 0, 0, 3, 4, 4, 4}},
70 {"Adobe", "Japan1", {-1, -1, 2, 2, 4, 5, 6, 6}},
71 {"Adobe", "Korea1", {-1, -1, 1, 1, 2, 2, 2, 2}},
72 {"Adobe", "Identity", {-1, -1, 0, 0, 0, 0, 0, 0}},
73 {NULL, NULL, { 0, 0, 0, 0, 0, 0, 0, 0}}
79 static char registry_Adobe[] = "Adobe";
80 static char ordering_Identity[] = "Identity";
81 static char ordering_UCS[] = "UCS";
83 CIDSysInfo CSI_IDENTITY = {
89 CIDSysInfo CSI_UNICODE = {
96 * Optional supplement after alias name.
101 } CIDFont_stdcc_alias[] = {
102 {"AU", 0}, {"AG1", 1}, {"AC1", 2}, {"AJ1", 3}, {"AK1", 4}, {"AI", 5},
103 {"UCS", 0}, {"GB1", 1}, {"CNS1", 2}, {"Japan1", 3}, {"Korea1", 4}, {"Identity", 5},
104 {"U", 0}, {"G", 1}, {"C", 2}, {"J", 3}, {"K", 4}, {"I", 5},
108 static void release_opt (cid_opt *opt);
109 static CIDSysInfo *get_cidsysinfo (const char *map_name, fontmap_opt *fmap_opt);
111 static int __verbose = 0;
112 static long cidoptflags = 0;
115 CIDFont_set_verbose (void)
117 CIDFont_type0_set_verbose();
118 CIDFont_type2_set_verbose();
124 CIDFont_require_version (void)
126 return PDF_CID_SUPPORT_MIN;
133 CIDFont *font = NULL;
135 font = NEW(1, struct CIDFont);
138 font->fontname = NULL;
142 font->ft_face = NULL;
143 font->ft_to_gid = NULL;
150 font->flags = FONT_FLAG_NONE;
152 font->options = NULL;
153 (font->parent)[0] = -1; /* Horizontal */
154 (font->parent)[1] = -1; /* Vertical */
159 font->indirect = NULL;
160 font->fontdict = NULL;
161 font->descriptor = NULL;
166 /* It does write PDF objects. */
168 CIDFont_flush (CIDFont *font)
171 if (font->indirect) pdf_release_obj(font->indirect);
172 font->indirect = NULL;
173 if (font->fontdict) pdf_release_obj(font->fontdict);
174 font->fontdict = NULL;
175 if (font->descriptor) pdf_release_obj(font->descriptor);
176 font->descriptor = NULL;
181 CIDFont_release (CIDFont *font)
184 switch(font->subtype) {
186 CIDFont_type0_release(font);
189 CIDFont_type2_release(font);
193 ERROR("%s: Object not flushed.", CIDFONT_DEBUG_STR);
195 ERROR("%s: Object not flushed.", CIDFONT_DEBUG_STR);
196 if (font->descriptor)
197 ERROR("%s: Object not flushed.", CIDFONT_DEBUG_STR);
199 if (font->fontname) RELEASE(font->fontname);
200 if (font->name) RELEASE(font->name);
201 if (font->ident) RELEASE(font->ident);
203 if (font->csi->registry)
204 RELEASE(font->csi->registry);
205 if (font->csi->ordering)
206 RELEASE(font->csi->ordering);
210 release_opt(font->options);
216 CIDFont_get_ft_to_gid(CIDFont *font)
219 return font->ft_to_gid;
224 CIDFont_get_fontname (CIDFont *font)
227 return font->fontname;
231 CIDFont_get_ident (CIDFont *font)
238 CIDFont_get_opt_index (CIDFont *font)
245 opt_index = font->options->index;
255 CIDFont_get_ft_face(CIDFont *font)
258 return font->ft_face;
263 CIDFont_get_subtype (CIDFont *font)
266 return font->subtype;
270 CIDFont_get_embedding (CIDFont *font)
273 return font->options->embed;
277 CIDFont_get_CIDSysInfo (CIDFont *font)
285 * Returns ID of parent Type0 font
286 * wmode: 0 for horizontal, 1 for vertical
289 CIDFont_get_parent_id (CIDFont *font, int wmode)
293 if (wmode < 0 || wmode > 1)
294 ERROR("%s: Invalid wmode value.", CIDFONT_DEBUG_STR);
296 return (font->parent)[wmode];
300 CIDFont_get_resource (CIDFont *font)
305 font->indirect = pdf_ref_obj(font->fontdict);
307 return pdf_link_obj(font->indirect);
311 * Set parent Type0 font.
314 CIDFont_attach_parent (CIDFont *font, int parent_id, int wmode)
318 if (wmode < 0 || wmode > 1)
319 ERROR("%s: Invalid wmode value.", CIDFONT_DEBUG_STR);
321 if (font->parent[wmode] >= 0)
322 WARN("%s: CIDFont already have a parent Type1 font.", CIDFONT_DEBUG_STR);
324 font->parent[wmode] = parent_id;
328 CIDFont_is_ACCFont (CIDFont *font)
335 ERROR("%s: CIDSystemInfo undefined.", CIDFONT_DEBUG_STR);
337 for (i = ACC_START; i <= ACC_END ; i++) {
338 if (!strcmp(font->csi->registry, CIDFont_stdcc_def[i].registry) &&
339 !strcmp(font->csi->ordering, CIDFont_stdcc_def[i].ordering))
347 CIDFont_is_UCSFont (CIDFont *font)
350 if (!strcmp(font->csi->ordering, "UCS") ||
351 !strcmp(font->csi->ordering, "UCS2"))
358 CIDFont_get_flag (CIDFont *font, int mask)
361 return ((font->flags & mask) ? 1 : 0);
365 CIDFont_dofont (CIDFont *font)
367 if (!font || !font->indirect)
371 MESG(":%s", font->ident);
374 MESG("[%s]", font->fontname);
377 switch (font->subtype) {
380 MESG("[CIDFontType0]");
381 if (CIDFont_get_flag(font, CIDFONT_FLAG_TYPE1))
382 CIDFont_type0_t1dofont(font);
383 else if (CIDFont_get_flag(font, CIDFONT_FLAG_TYPE1C))
384 CIDFont_type0_t1cdofont(font);
386 CIDFont_type0_dofont(font);
390 MESG("[CIDFontType2]");
391 CIDFont_type2_dofont(font);
394 ERROR("%s: Unknown CIDFontType %d.", CIDFONT_DEBUG_STR, font->subtype);
404 CIDFont_is_BaseFont (CIDFont *font)
407 return (font->flags & FONT_FLAG_BASEFONT) ? 1 : 0;
410 #include "pdfparse.h"
411 #include "cid_basefont.h"
413 static int CIDFont_base_open (CIDFont *font,
414 const char *name, CIDSysInfo *cmap_csi, cid_opt *opt);
417 CIDFont_base_open (CIDFont *font, const char *name, CIDSysInfo *cmap_csi, cid_opt *opt)
419 pdf_obj *fontdict, *descriptor;
420 char *fontname = NULL;
425 for (idx = 0; cid_basefont[idx].fontname != NULL; idx++) {
426 if (!strcmp(name, cid_basefont[idx].fontname) ||
427 (strlen(name) == strlen(cid_basefont[idx].fontname) - strlen("-Acro") &&
428 !strncmp(name, cid_basefont[idx].fontname,
429 strlen(cid_basefont[idx].fontname)-strlen("-Acro")))
434 if (cid_basefont[idx].fontname == NULL)
437 fontname = NEW(strlen(name)+12, char);
438 memset(fontname, 0, strlen(name)+12);
439 strcpy(fontname, name);
441 switch (opt->style) {
442 case FONT_STYLE_BOLD:
443 strcat(fontname, ",Bold");
445 case FONT_STYLE_ITALIC:
446 strcat(fontname, ",Italic");
448 case FONT_STYLE_BOLDITALIC:
449 strcat(fontname, ",BoldItalic");
456 start = cid_basefont[idx].fontdict;
457 end = start + strlen(start);
458 fontdict = parse_pdf_dict(&start, end, NULL);
459 start = cid_basefont[idx].descriptor;
460 end = start + strlen(start);
461 descriptor = parse_pdf_dict(&start, end, NULL);
463 ASSERT(fontdict && descriptor);
466 font->fontname = fontname;
467 font->flags |= FONT_FLAG_BASEFONT;
469 char *registry, *ordering;
473 tmp = pdf_lookup_dict(fontdict, "CIDSystemInfo");
475 ASSERT( tmp && pdf_obj_typeof(tmp) == PDF_DICT );
477 registry = pdf_string_value(pdf_lookup_dict(tmp, "Registry"));
478 ordering = pdf_string_value(pdf_lookup_dict(tmp, "Ordering"));
479 supplement = pdf_number_value(pdf_lookup_dict(tmp, "Supplement"));
480 if (cmap_csi) { /* NULL for accept any */
481 if (strcmp(registry, cmap_csi->registry) ||
482 strcmp(ordering, cmap_csi->ordering))
483 ERROR("Inconsistent CMap used for CID-keyed font %s.",
484 cid_basefont[idx].fontname);
485 else if (supplement < cmap_csi->supplement) {
486 WARN("CMap has higher supplement number than CIDFont: %s", fontname);
487 WARN("Some chracters may not be displayed or printed.");
490 font->csi = NEW(1, CIDSysInfo);
491 font->csi->registry = NEW(strlen(registry)+1, char);
492 font->csi->ordering = NEW(strlen(ordering)+1, char);
493 strcpy(font->csi->registry, registry);
494 strcpy(font->csi->ordering, ordering);
495 font->csi->supplement = supplement;
502 tmp = pdf_lookup_dict(fontdict, "Subtype");
503 ASSERT( tmp != NULL && pdf_obj_typeof(tmp) == PDF_NAME );
505 type = pdf_name_value(tmp);
506 if (!strcmp(type, "CIDFontType0"))
507 font->subtype = CIDFONT_TYPE0;
508 else if (!strcmp(type, "CIDFontType2"))
509 font->subtype = CIDFONT_TYPE2;
511 ERROR("Unknown CIDFontType \"%s\"", type);
515 if (cidoptflags & CIDFONT_FORCE_FIXEDPITCH) {
516 if (pdf_lookup_dict(fontdict, "W")) {
517 pdf_remove_dict(fontdict, "W");
519 if (pdf_lookup_dict(fontdict, "W2")) {
520 pdf_remove_dict(fontdict, "W2");
524 pdf_add_dict(fontdict, pdf_new_name("Type"), pdf_new_name("Font"));
525 pdf_add_dict(fontdict, pdf_new_name("BaseFont"), pdf_new_name(fontname));
526 pdf_add_dict(descriptor, pdf_new_name("Type"), pdf_new_name("FontDescriptor"));
527 pdf_add_dict(descriptor, pdf_new_name("FontName"), pdf_new_name(fontname));
529 font->fontdict = fontdict;
530 font->descriptor = descriptor;
539 #define CACHE_ALLOC_SIZE 16u
547 static struct FontCache *__cache = NULL;
549 #define CHECK_ID(n) do {\
551 ERROR("%s: CIDFont cache not initialized.", CIDFONT_DEBUG_STR);\
552 if ((n) < 0 || (n) >= __cache->num)\
553 ERROR("%s: Invalid ID %d", CIDFONT_DEBUG_STR, (n));\
557 CIDFont_cache_init (void)
560 ERROR("%s: Already initialized.", CIDFONT_DEBUG_STR);
562 __cache = NEW(1, struct FontCache);
564 __cache->max = CACHE_ALLOC_SIZE;
565 __cache->fonts = NEW(__cache->max, struct CIDFont *);
570 CIDFont_cache_get (int font_id)
573 return __cache->fonts[font_id];
577 * cmap_csi is NULL if CMap is Identity.
580 CIDFont_cache_find (const char *map_name,
581 CIDSysInfo *cmap_csi, fontmap_opt *fmap_opt)
584 CIDFont *font = NULL;
588 CIDFont_cache_init();
590 opt = NEW(1, cid_opt);
591 opt->style = fmap_opt->style;
592 opt->index = fmap_opt->index;
593 opt->embed = (fmap_opt->flags & FONTMAP_OPT_NOEMBED) ? 0 : 1;
595 opt->csi = get_cidsysinfo(map_name, fmap_opt);
596 opt->stemv = fmap_opt->stemv;
598 if (!opt->csi && cmap_csi) {
600 * No CIDSystemInfo supplied explicitly. Copy from CMap's one if available.
601 * It is not neccesary for CID-keyed fonts. But TrueType requires them.
603 opt->csi = NEW(1, CIDSysInfo);
604 opt->csi->registry = NEW(strlen(cmap_csi->registry)+1, char);
605 strcpy(opt->csi->registry, cmap_csi->registry);
606 opt->csi->ordering = NEW(strlen(cmap_csi->ordering)+1, char);
607 strcpy(opt->csi->ordering, cmap_csi->ordering);
608 opt->csi->supplement = cmap_csi->supplement;
611 * Here, we do not compare font->ident and map_name because of
612 * implicit CIDSystemInfo supplied by CMap for TrueType.
614 for (font_id = 0; font_id < __cache->num; font_id++) {
615 font = __cache->fonts[font_id];
616 if (!strcmp(font->name, map_name) &&
617 font->options->style == opt->style &&
618 font->options->index == opt->index) {
619 if (font->options->embed == opt->embed) {
621 * Case 1: CSI not available (Identity CMap)
622 * Font is TrueType --> continue
623 * Font is CIDFont --> break
624 * Case 2: CSI matched --> break
627 if (font->subtype == CIDFONT_TYPE2)
631 } else if (!strcmp(font->csi->registry, opt->csi->registry) &&
632 !strcmp(font->csi->ordering, opt->csi->ordering)) {
633 if (font->subtype == CIDFONT_TYPE2)
634 font->csi->supplement =
635 MAX(opt->csi->supplement, font->csi->supplement);
638 } else if (CIDFont_is_BaseFont(font)) {
645 if (font_id < __cache->num && cmap_csi) {
646 if (strcmp(font->csi->registry, cmap_csi->registry) ||
647 strcmp(font->csi->ordering, cmap_csi->ordering))
648 ERROR("%s: Incompatible CMap for CIDFont \"%s\"",
649 CIDFONT_DEBUG_STR, map_name);
652 if (font_id == __cache->num) {
653 font = CIDFont_new();
655 font->ft_face = fmap_opt->ft_face;
657 if (CIDFont_type0_open(font, map_name, cmap_csi, opt) < 0 &&
658 CIDFont_type2_open(font, map_name, cmap_csi, opt) < 0 &&
659 CIDFont_type0_t1open(font, map_name, cmap_csi, opt) < 0 &&
660 CIDFont_type0_t1copen(font, map_name, cmap_csi, opt) < 0 &&
661 CIDFont_base_open (font, map_name, cmap_csi, opt) < 0
663 CIDFont_release(font);
667 if (__cache->num >= __cache->max) {
668 __cache->max += CACHE_ALLOC_SIZE;
669 __cache->fonts = RENEW(__cache->fonts,
670 __cache->max, struct CIDFont *);
672 font->name = NEW(strlen(map_name)+1, char);
673 strcpy(font->name, map_name);
674 font->ident = NEW(strlen(map_name)+1, char);
675 strcpy(font->ident, map_name);
677 __cache->fonts[font_id] = font;
688 CIDFont_cache_close (void)
694 font_id < __cache->num; font_id++) {
697 font = __cache->fonts[font_id];
702 CIDFont_dofont (font);
703 CIDFont_flush (font);
704 CIDFont_release(font);
711 RELEASE(__cache->fonts);
717 /******************************* OPTIONS *******************************/
722 * (:int:)?!?string(/string)?(,string)?
726 release_opt (cid_opt *opt)
729 if (opt->csi->registry)
730 RELEASE(opt->csi->registry);
731 if (opt->csi->ordering)
732 RELEASE(opt->csi->ordering);
739 get_cidsysinfo (const char *map_name, fontmap_opt *fmap_opt)
741 CIDSysInfo *csi = NULL;
743 int i, csi_idx = -1, n, m;
745 pdf_ver = pdf_get_version();
747 if (!fmap_opt || !fmap_opt->charcoll)
750 /* First try alias for standard one. */
751 for (i = 0; CIDFont_stdcc_alias[i].name != NULL; i++) {
752 n = strlen(CIDFont_stdcc_alias[i].name);
753 if (!strncmp(fmap_opt->charcoll,
754 CIDFont_stdcc_alias[i].name, n)) {
755 csi_idx = CIDFont_stdcc_alias[i].index;
756 csi = NEW(1, CIDSysInfo);
757 csi->registry = NEW(strlen(CIDFont_stdcc_def[csi_idx].registry)+1, char);
758 strcpy(csi->registry, CIDFont_stdcc_def[csi_idx].registry);
759 csi->ordering = NEW(strlen(CIDFont_stdcc_def[csi_idx].ordering)+1, char);
760 strcpy(csi->ordering, CIDFont_stdcc_def[csi_idx].ordering);
761 if (strlen(fmap_opt->charcoll) > n) {
762 csi->supplement = (int) strtoul(&(fmap_opt->charcoll[n]), NULL, 10);
763 } else { /* Use heighest supported value for current output PDF version. */
764 csi->supplement = CIDFont_stdcc_def[csi_idx].supplement[pdf_ver];
772 p = (char *) fmap_opt->charcoll;
773 csi = NEW(1, CIDSysInfo);
775 /* Full REGISTRY-ORDERING-SUPPLEMENT */
776 p = strchr(fmap_opt->charcoll, '-');
777 if (!p || p[1] == '\0')
778 ERROR("%s: String can't be converted to REGISTRY-ORDERING-SUPPLEMENT: %s",
779 CIDFONT_DEBUG_STR, fmap_opt->charcoll);
783 if (!q || q[1] == '\0')
784 ERROR("%s: String can't be converted to REGISTRY-ORDERING-SUPPLEMENT: %s",
785 CIDFONT_DEBUG_STR, fmap_opt->charcoll);
789 ERROR("%s: String can't be converted to REGISTRY-ORDERING-SUPPLEMENT: %s",
790 CIDFONT_DEBUG_STR, fmap_opt->charcoll);
792 n = strlen(fmap_opt->charcoll) - strlen(p) - 1;
793 csi->registry = NEW(n+1, char);
794 memcpy(csi->registry, fmap_opt->charcoll, n);
795 csi->registry[n] = '\0';
797 m = strlen(p) - strlen(q) - 1;
798 csi->ordering = NEW(m+1, char);
799 memcpy(csi->ordering, p, m);
800 csi->ordering[m] = '\0';
802 csi->supplement = (int) strtoul(q, NULL, 10);
804 /* Check for standart character collections. */
805 for (i = 0; CIDFont_stdcc_def[i].ordering != NULL; i++) {
806 if ((CIDFont_stdcc_def[i].registry &&
807 !strcmp(csi->registry, CIDFont_stdcc_def[i].registry)) &&
808 !strcmp(csi->ordering, CIDFont_stdcc_def[i].ordering)) {
815 if (csi && csi_idx >= 0) {
816 if (csi->supplement > CIDFont_stdcc_def[csi_idx].supplement[pdf_ver]
817 && (fmap_opt->flags & FONTMAP_OPT_NOEMBED)) {
818 WARN("%s: Heighest supplement number supported in PDF-1.%d for %s-%s is %d.",
819 CIDFONT_DEBUG_STR, pdf_ver, csi->registry, csi->ordering,
820 CIDFont_stdcc_def[csi_idx].supplement[pdf_ver]);
821 WARN("%s: Some character may not shown without embedded font (--> %s).",
822 CIDFONT_DEBUG_STR, map_name);
830 CIDFont_set_flags (long flags)
832 CIDFont_type0_set_flags(flags);
833 CIDFont_type2_set_flags(flags);
834 cidoptflags |= flags;