1 //========================================================================
5 // Copyright 1996 Derek B. Noonburg
7 //========================================================================
10 #pragma implementation
32 #include "Japan12CMapInfo.h"
34 #if CHINESE_GB_SUPPORT
35 #include "GB12CMapInfo.h"
37 #if CHINESE_CNS_SUPPORT
38 #include "CNS13CMapInfo.h"
41 //------------------------------------------------------------------------
44 static int CDECL
cmpWidthExcep(const void *w1
, const void *w2
);
45 static int CDECL
cmpWidthExcepV(const void *w1
, const void *w2
);
48 //------------------------------------------------------------------------
50 static Gushort
*defCharWidths
[12] = {
54 courierBoldObliqueWidths
,
56 helveticaObliqueWidths
,
58 helveticaBoldObliqueWidths
,
65 //------------------------------------------------------------------------
67 //------------------------------------------------------------------------
69 GfxFont::GfxFont(XRef
*xref
, char *tagA
, Ref idA
, Dict
*fontDict
) {
70 BuiltinFont
*builtinFont
;
71 Object obj1
, obj2
, obj3
, obj4
;
76 // get font tag and ID
77 tag
= new GString(tagA
);
81 type
= fontUnknownType
;
82 fontDict
->lookup("Subtype", &obj1
);
83 if (obj1
.isName("Type1"))
85 else if (obj1
.isName("Type1C"))
87 else if (obj1
.isName("Type3"))
89 else if (obj1
.isName("TrueType"))
91 else if (obj1
.isName("Type0"))
98 fontDict
->lookup("BaseFont", &obj1
);
100 name
= new GString(obj1
.getName());
103 // Newer Adobe tools are using Base14-compatible TrueType fonts
104 // without embedding them, so munge the names into the equivalent
105 // PostScript names. This is a kludge -- it would be nice if Adobe
106 // followed their own spec.
107 if (type
== fontTrueType
&& name
) {
108 p
= name
->getCString();
110 if (!strncmp(p
, "Arial", 5)) {
111 if (!strcmp(p
+5, ",Bold")) {
112 name2
= "Helvetica-Bold";
113 } else if (!strcmp(p
+5, ",Italic")) {
114 name2
= "Helvetica-Oblique";
115 } else if (!strcmp(p
+5, ",BoldItalic")) {
116 name2
= "Helvetica-BoldOblique";
120 } else if (!strncmp(p
, "TimesNewRoman", 13)) {
121 if (!strcmp(p
+13, ",Bold")) {
122 name2
= "Times-Bold";
123 } else if (!strcmp(p
+13, ",Italic")) {
124 name2
= "Times-Italic";
125 } else if (!strcmp(p
+13, ",BoldItalic")) {
126 name2
= "Times-BoldItalic";
128 name2
= "Times-Roman";
130 } else if (!strncmp(p
, "CourierNew", 10)) {
131 if (!strcmp(p
+10, ",Bold")) {
132 name2
= "Courier-Bold";
133 } else if (!strcmp(p
+10, ",Italic")) {
134 name2
= "Courier-Oblique";
135 } else if (!strcmp(p
+10, ",BoldItalic")) {
136 name2
= "Courier-BoldOblique";
143 name
= new GString(name2
);
147 // is it a built-in font?
150 for (i
= 0; i
< numBuiltinFonts
; ++i
) {
151 if (!strcmp(builtinFonts
[i
].name
, name
->getCString())) {
152 builtinFont
= &builtinFonts
[i
];
158 // assume Times-Roman by default (for substitution purposes)
161 // default ascent/descent values
163 ascent
= 0.001 * builtinFont
->ascent
;
164 descent
= 0.001 * builtinFont
->descent
;
170 // get info from font descriptor
175 if (type
== fontType0
) {
176 fontDict
->lookup("DescendantFonts", &obj2
);
177 if (obj2
.isArray()) {
178 obj2
.arrayGet(0, &obj3
);
180 obj3
.dictLookup("FontDescriptor", &obj1
);
182 error(-1, "Bad descendant font in Type 0 font");
187 error(-1, "Missing DescendantFonts entry in Type 0 font");
192 fontDict
->lookup("FontDescriptor", &obj1
);
197 obj1
.dictLookup("Flags", &obj2
);
199 flags
= obj2
.getInt();
203 obj1
.dictLookup("FontName", &obj2
);
205 embFontName
= new GString(obj2
.getName());
208 // look for embedded font file
209 if (type
== fontType1
) {
210 obj1
.dictLookupNF("FontFile", &obj2
);
212 embFontID
= obj2
.getRef();
215 if (embFontID
.num
== -1 && type
== fontTrueType
) {
216 obj1
.dictLookupNF("FontFile2", &obj2
);
218 embFontID
= obj2
.getRef();
221 if (embFontID
.num
== -1) {
222 obj1
.dictLookupNF("FontFile3", &obj2
);
224 embFontID
= obj2
.getRef();
225 obj2
.fetch(xref
, &obj3
);
226 if (obj3
.isStream()) {
227 obj3
.streamGetDict()->lookup("Subtype", &obj4
);
228 if (obj4
.isName("Type1"))
230 else if (obj4
.isName("Type1C"))
232 else if (obj4
.isName("Type3"))
234 else if (obj4
.isName("TrueType"))
236 else if (obj4
.isName("Type0"))
245 // look for MissingWidth
246 obj1
.dictLookup("MissingWidth", &obj2
);
248 missingWidth
= obj2
.getInt();
252 // get Ascent and Descent
253 obj1
.dictLookup("Ascent", &obj2
);
255 ascent
= 0.001 * obj2
.getNum();
258 obj1
.dictLookup("Descent", &obj2
);
260 descent
= 0.001 * obj2
.getNum();
265 fontBBox
[0] = fontBBox
[1] = fontBBox
[2] = fontBBox
[3] = 0;
266 if (obj1
.dictLookup("FontBBox", &obj2
)->isArray()) {
267 for (i
= 0; i
< 4 && i
< obj2
.arrayGetLength(); ++i
) {
268 if (obj2
.arrayGet(i
, &obj3
)->isNum()) {
269 fontBBox
[i
] = obj3
.getNum();
278 // get Type3 font definition
279 if (type
== fontType3
) {
280 fontDict
->lookup("CharProcs", &charProcs
);
281 if (!charProcs
.isDict()) {
282 error(-1, "Missing or invalid CharProcs dictionary in Type 3 font");
287 // look for an external font file
289 if (type
== fontType1
&& name
)
293 fontMat
[0] = fontMat
[3] = 1;
294 fontMat
[1] = fontMat
[2] = fontMat
[4] = fontMat
[5] = 0;
295 if (fontDict
->lookup("FontMatrix", &obj1
)->isArray()) {
296 for (i
= 0; i
< 6 && i
< obj1
.arrayGetLength(); ++i
) {
297 if (obj1
.arrayGet(i
, &obj2
)->isNum())
298 fontMat
[i
] = obj2
.getNum();
304 // get encoding and character widths
305 if (type
== fontType0
) {
306 getType0EncAndWidths(fontDict
);
308 getEncAndWidths(xref
, fontDict
, builtinFont
, missingWidth
);
312 GfxFont::~GfxFont() {
317 if (!is16
&& encoding
) {
326 if (charProcs
.isDict()) {
330 gfree(widths16
.exceps
);
331 gfree(widths16
.excepsV
);
335 double GfxFont::getWidth(GString
*s
) {
340 for (i
= 0; i
< s
->getLength(); ++i
)
341 w
+= widths
[s
->getChar(i
) & 0xff];
345 double GfxFont::getWidth16(int c
) {
349 w
= widths16
.defWidth
;
351 b
= widths16
.numExceps
;
352 // invariant: widths16.exceps[a].last < c < widths16.exceps[b].first
355 if (widths16
.exceps
[m
].last
< c
) {
357 } else if (c
< widths16
.exceps
[m
].first
) {
360 w
= widths16
.exceps
[m
].width
;
367 double GfxFont::getHeight16(int c
) {
371 h
= widths16
.defHeight
;
373 b
= widths16
.numExcepsV
;
374 // invariant: widths16.excepsV[a].last < c < widths16.excepsV[b].first
377 if (widths16
.excepsV
[m
].last
< c
) {
379 } else if (c
< widths16
.excepsV
[m
].first
) {
382 h
= widths16
.excepsV
[m
].height
;
389 double GfxFont::getOriginX16(int c
) {
393 vx
= widths16
.defWidth
/ 2;
395 b
= widths16
.numExcepsV
;
396 // invariant: widths16.excepsV[a].last < c < widths16.excepsV[b].first
399 if (widths16
.excepsV
[m
].last
< c
) {
401 } else if (c
< widths16
.excepsV
[m
].first
) {
404 vx
= widths16
.excepsV
[m
].vx
;
411 double GfxFont::getOriginY16(int c
) {
417 b
= widths16
.numExcepsV
;
418 // invariant: widths16.excepsV[a].last < c < widths16.excepsV[b].first
421 if (widths16
.excepsV
[m
].last
< c
) {
423 } else if (c
< widths16
.excepsV
[m
].first
) {
426 vy
= widths16
.excepsV
[m
].vy
;
433 Object
*GfxFont::getCharProc(int code
, Object
*proc
) {
434 if (charProcs
.isDict()) {
435 charProcs
.dictLookup(encoding
->getCharName(code
), proc
);
442 void GfxFont::getEncAndWidths(XRef
*xref
, Dict
*fontDict
,
443 BuiltinFont
*builtinFont
, int missingWidth
) {
444 Object obj1
, obj2
, obj3
;
450 // Encodings start with a base encoding, which can come from
451 // (in order of priority):
452 // 1. FontDict.Encoding or FontDict.Encoding.BaseEncoding
453 // - MacRoman / WinAnsi / Standard
454 // 2. embedded font file
456 // - builtin --> builtin encoding
457 // - TrueType --> MacRomanEncoding
458 // - others --> StandardEncoding
459 // and then add a list of differences from
460 // FontDict.Encoding.Differences.
462 // check FontDict for base encoding
464 fontDict
->lookup("Encoding", &obj1
);
466 obj1
.dictLookup("BaseEncoding", &obj2
);
467 if (obj2
.isName("MacRomanEncoding")) {
468 encoding
= macRomanEncoding
.copy();
469 } else if (obj2
.isName("WinAnsiEncoding")) {
470 encoding
= winAnsiEncoding
.copy();
471 } else if (obj2
.isName("StandardEncoding")) {
472 encoding
= standardEncoding
.copy();
475 } else if (obj1
.isName("MacRomanEncoding")) {
476 encoding
= macRomanEncoding
.copy();
477 } else if (obj1
.isName("WinAnsiEncoding")) {
478 encoding
= winAnsiEncoding
.copy();
479 } else if (obj1
.isName("StandardEncoding")) {
480 encoding
= standardEncoding
.copy();
484 // check embedded or external font file for base encoding
485 if ((type
== fontType1
|| type
== fontType1C
|| type
== fontTrueType
) &&
486 (extFontFile
|| embFontID
.num
>= 0)) {
488 buf
= readExtFontFile(&len
);
490 buf
= readEmbFontFile(xref
, &len
);
493 if (type
== fontType1
) {
494 fontFile
= new Type1FontFile(buf
, len
);
495 } else if (type
== fontType1C
) {
496 fontFile
= new Type1CFontFile(buf
, len
);
498 fontFile
= new TrueTypeFontFile(buf
, len
);
500 if (fontFile
->getName()) {
503 embFontName
= new GString(fontFile
->getName());
506 encoding
= fontFile
->getEncoding(gTrue
);
513 // get default base encoding
516 encoding
= builtinFont
->encoding
->copy();
517 else if (type
== fontTrueType
)
518 encoding
= macRomanEncoding
.copy();
520 encoding
= standardEncoding
.copy();
523 // merge differences into encoding
524 fontDict
->lookup("Encoding", &obj1
);
526 obj1
.dictLookup("Differences", &obj2
);
527 if (obj2
.isArray()) {
529 for (i
= 0; i
< obj2
.arrayGetLength(); ++i
) {
530 obj2
.arrayGet(i
, &obj3
);
532 code
= obj3
.getInt();
533 } else if (obj3
.isName()) {
535 encoding
->addChar(code
, copyString(obj3
.getName()));
538 error(-1, "Wrong type in font encoding resource differences (%s)",
548 // get character widths
550 makeWidths(fontDict
, builtinFont
->encoding
, builtinFont
->widths
,
553 makeWidths(fontDict
, NULL
, NULL
, missingWidth
);
556 void GfxFont::findExtFontFile() {
560 for (path
= fontPath
; *path
; ++path
) {
561 extFontFile
= appendToPath(new GString(*path
), name
->getCString());
562 f
= fopen(extFontFile
->getCString(), "rb");
564 extFontFile
->append(".pfb");
565 f
= fopen(extFontFile
->getCString(), "rb");
568 extFontFile
->del(extFontFile
->getLength() - 4, 4);
569 extFontFile
->append(".pfa");
570 f
= fopen(extFontFile
->getCString(), "rb");
581 char *GfxFont::readExtFontFile(int *len
) {
585 if (!(f
= fopen(extFontFile
->getCString(), "rb"))) {
586 error(-1, "Internal: external font file '%s' vanished", extFontFile
);
589 fseek(f
, 0, SEEK_END
);
590 *len
= (int)ftell(f
);
591 fseek(f
, 0, SEEK_SET
);
592 buf
= (char *)gmalloc(*len
);
593 if ((int)fread(buf
, 1, *len
, f
) != *len
)
594 error(-1, "Error reading external font file '%s'", extFontFile
);
599 char *GfxFont::readEmbFontFile(XRef
*xref
, int *len
) {
606 obj1
.initRef(embFontID
.num
, embFontID
.gen
);
607 obj1
.fetch(xref
, &obj2
);
608 if (!obj2
.isStream()) {
609 error(-1, "Embedded font file is not a stream");
615 str
= obj2
.getStream();
620 while ((c
= str
->getChar()) != EOF
) {
623 buf
= (char *)grealloc(buf
, size
);
636 void GfxFont::makeWidths(Dict
*fontDict
, FontEncoding
*builtinEncoding
,
637 Gushort
*builtinWidths
, int missingWidth
) {
639 int firstChar
, lastChar
;
646 // initialize all widths
647 for (code
= 0; code
< 256; ++code
) {
648 widths
[code
] = missingWidth
* 0.001;
651 // use widths from font dict, if present
652 fontDict
->lookup("FirstChar", &obj1
);
653 firstChar
= obj1
.isInt() ? obj1
.getInt() : 0;
655 fontDict
->lookup("LastChar", &obj1
);
656 lastChar
= obj1
.isInt() ? obj1
.getInt() : 255;
658 if (type
== fontType3
)
662 fontDict
->lookup("Widths", &obj1
);
663 if (obj1
.isArray()) {
664 for (code
= firstChar
; code
<= lastChar
; ++code
) {
665 obj1
.arrayGet(code
- firstChar
, &obj2
);
667 widths
[code
] = obj2
.getNum() * mult
;
671 // use widths from built-in font
672 } else if (builtinEncoding
) {
673 code2
= 0; // to make gcc happy
674 for (code
= 0; code
< 256; ++code
) {
675 if ((charName
= encoding
->getCharName(code
)) &&
676 (code2
= builtinEncoding
->getCharCode(charName
)) >= 0) {
677 widths
[code
] = builtinWidths
[code2
] * 0.001;
678 } else if (code
== 32) {
679 // this is a kludge for broken PDF files that encode char 32
681 widths
[code
] = builtinWidths
[' '] * 0.001;
685 // couldn't find widths -- use defaults
688 //~ certain PDF generators apparently don't include widths
689 //~ for Arial and TimesNewRoman -- and this error message
691 error(-1, "No character widths resource for non-builtin font");
703 defWidths
= defCharWidths
[index
];
704 code2
= 0; // to make gcc happy
705 for (code
= 0; code
< 256; ++code
) {
706 if ((charName
= encoding
->getCharName(code
)) &&
707 (code2
= standardEncoding
.getCharCode(charName
)) >= 0)
708 widths
[code
] = defWidths
[code2
] * 0.001;
714 void GfxFont::getType0EncAndWidths(Dict
*fontDict
) {
715 Object obj1
, obj2
, obj3
, obj4
, obj5
, obj6
, obj7
, obj8
;
719 widths16
.exceps
= NULL
;
720 widths16
.excepsV
= NULL
;
723 fontDict
->lookup("DescendantFonts", &obj1
);
724 if (!obj1
.isArray() || obj1
.arrayGetLength() != 1) {
725 error(-1, "Bad DescendantFonts entry for Type 0 font");
728 obj1
.arrayGet(0, &obj2
);
729 if (!obj2
.isDict()) {
730 error(-1, "Bad descendant font of Type 0 font");
735 obj2
.dictLookup("CIDSystemInfo", &obj3
);
736 if (!obj3
.isDict()) {
737 error(-1, "Bad CIDSystemInfo in Type 0 font descendant");
740 obj3
.dictLookup("Registry", &obj4
);
741 obj3
.dictLookup("Ordering", &obj5
);
742 if (obj4
.isString() && obj5
.isString()) {
743 if (obj4
.getString()->cmp("Adobe") == 0 &&
744 obj5
.getString()->cmp("Japan1") == 0) {
747 enc16
.charSet
= font16AdobeJapan12
;
749 error(-1, "Xpdf was compiled without Japanese font support");
752 } else if (obj4
.getString()->cmp("Adobe") == 0 &&
753 obj5
.getString()->cmp("GB1") == 0) {
754 #if CHINESE_GB_SUPPORT
756 enc16
.charSet
= font16AdobeGB12
;
758 error(-1, "Xpdf was compiled without Chinese GB font support");
761 } else if (obj4
.getString()->cmp("Adobe") == 0 &&
762 obj5
.getString()->cmp("CNS1") == 0) {
763 #if CHINESE_CNS_SUPPORT
765 enc16
.charSet
= font16AdobeCNS13
;
767 error(-1, "Xpdf was compiled without Chinese CNS font support");
771 error(-1, "Unknown Type 0 character set: %s-%s",
772 obj4
.getString()->getCString(), obj5
.getString()->getCString());
776 error(-1, "Unknown Type 0 character set");
783 // get default char width
784 obj2
.dictLookup("DW", &obj3
);
786 widths16
.defWidth
= obj3
.getInt() * 0.001;
788 widths16
.defWidth
= 1.0;
791 // get default char metrics for vertical font
792 obj2
.dictLookup("DW2", &obj3
);
793 widths16
.defVY
= 0.880;
794 widths16
.defHeight
= -1;
795 if (obj3
.isArray() && obj3
.arrayGetLength() == 2) {
796 obj3
.arrayGet(0, &obj4
);
798 widths16
.defVY
= obj4
.getInt() * 0.001;
801 obj3
.arrayGet(1, &obj4
);
803 widths16
.defHeight
= obj4
.getInt() * 0.001;
809 // get char width exceptions
810 widths16
.exceps
= NULL
;
811 widths16
.numExceps
= 0;
812 obj2
.dictLookup("W", &obj3
);
813 if (obj3
.isArray()) {
817 while (i
+1 < obj3
.arrayGetLength()) {
818 obj3
.arrayGet(i
, &obj4
);
819 obj3
.arrayGet(i
+1, &obj5
);
820 if (obj4
.isInt() && obj5
.isInt()) {
821 obj3
.arrayGet(i
+2, &obj6
);
823 error(-1, "Bad widths array in Type 0 font");
829 if (k
== excepsSize
) {
831 widths16
.exceps
= (GfxFontWidthExcep
*)
832 grealloc(widths16
.exceps
,
833 excepsSize
* sizeof(GfxFontWidthExcep
));
835 widths16
.exceps
[k
].first
= obj4
.getInt();
836 widths16
.exceps
[k
].last
= obj5
.getInt();
837 widths16
.exceps
[k
].width
= obj6
.getNum() * 0.001;
841 } else if (obj4
.isInt() && obj5
.isArray()) {
842 if (k
+ obj5
.arrayGetLength() >= excepsSize
) {
843 excepsSize
= (k
+ obj5
.arrayGetLength() + 15) & ~15;
844 widths16
.exceps
= (GfxFontWidthExcep
*)
845 grealloc(widths16
.exceps
,
846 excepsSize
* sizeof(GfxFontWidthExcep
));
849 for (j
= 0; j
< obj5
.arrayGetLength(); ++j
) {
850 obj5
.arrayGet(j
, &obj6
);
852 error(-1, "Bad widths array in Type 0 font");
856 widths16
.exceps
[k
].first
= widths16
.exceps
[k
].last
= n
++;
857 widths16
.exceps
[k
].width
= obj6
.getNum() * 0.001;
863 error(-1, "Bad widths array in Type 0 font");
872 widths16
.numExceps
= k
;
874 qsort(widths16
.exceps
, k
, sizeof(GfxFontWidthExcep
), &cmpWidthExcep
);
878 // get char metric exceptions for vertical font
879 widths16
.excepsV
= NULL
;
880 widths16
.numExcepsV
= 0;
881 obj2
.dictLookup("W2", &obj3
);
882 if (obj3
.isArray()) {
886 while (i
+1 < obj3
.arrayGetLength()) {
887 obj3
.arrayGet(i
, &obj4
);
888 obj3
.arrayGet(i
+1, &obj5
);
889 if (obj4
.isInt() && obj5
.isInt()) {
890 obj3
.arrayGet(i
+2, &obj6
);
891 obj3
.arrayGet(i
+3, &obj7
);
892 obj3
.arrayGet(i
+4, &obj8
);
893 if (!obj6
.isNum() || !obj7
.isNum() || !obj8
.isNum()) {
894 error(-1, "Bad widths (W2) array in Type 0 font");
902 if (k
== excepsSize
) {
904 widths16
.excepsV
= (GfxFontWidthExcepV
*)
905 grealloc(widths16
.excepsV
,
906 excepsSize
* sizeof(GfxFontWidthExcepV
));
908 widths16
.excepsV
[k
].first
= obj4
.getInt();
909 widths16
.excepsV
[k
].last
= obj5
.getInt();
910 widths16
.excepsV
[k
].height
= obj6
.getNum() * 0.001;
911 widths16
.excepsV
[k
].vx
= obj7
.getNum() * 0.001;
912 widths16
.excepsV
[k
].vy
= obj8
.getNum() * 0.001;
918 } else if (obj4
.isInt() && obj5
.isArray()) {
919 if (k
+ obj5
.arrayGetLength() / 3 >= excepsSize
) {
920 excepsSize
= (k
+ obj5
.arrayGetLength() / 3 + 15) & ~15;
921 widths16
.excepsV
= (GfxFontWidthExcepV
*)
922 grealloc(widths16
.excepsV
,
923 excepsSize
* sizeof(GfxFontWidthExcepV
));
926 for (j
= 0; j
< obj5
.arrayGetLength(); j
+= 3) {
927 obj5
.arrayGet(j
, &obj6
);
928 obj5
.arrayGet(j
+1, &obj7
);
929 obj5
.arrayGet(j
+1, &obj8
);
930 if (!obj6
.isNum() || !obj7
.isNum() || !obj8
.isNum()) {
931 error(-1, "Bad widths (W2) array in Type 0 font");
935 widths16
.excepsV
[k
].first
= widths16
.exceps
[k
].last
= n
++;
936 widths16
.excepsV
[k
].height
= obj6
.getNum() * 0.001;
937 widths16
.excepsV
[k
].vx
= obj7
.getNum() * 0.001;
938 widths16
.excepsV
[k
].vy
= obj8
.getNum() * 0.001;
946 error(-1, "Bad widths array in Type 0 font");
954 widths16
.numExcepsV
= k
;
956 qsort(widths16
.excepsV
, k
, sizeof(GfxFontWidthExcepV
), &cmpWidthExcepV
);
964 // get encoding (CMap)
965 fontDict
->lookup("Encoding", &obj1
);
966 if (!obj1
.isName()) {
967 error(-1, "Bad encoding for Type 0 font");
971 if (enc16
.charSet
== font16AdobeJapan12
) {
972 for (i
= 0; gfxJapan12Tab
[i
].name
; ++i
) {
973 if (!strcmp(obj1
.getName(), gfxJapan12Tab
[i
].name
))
976 if (!gfxJapan12Tab
[i
].name
) {
977 error(-1, "Unknown encoding '%s' for Adobe-Japan1-2 font",
981 enc16
.enc
= gfxJapan12Tab
[i
].enc
;
984 #if CHINESE_GB_SUPPORT
985 if (enc16
.charSet
== font16AdobeGB12
) {
986 for (i
= 0; gfxGB12Tab
[i
].name
; ++i
) {
987 if (!strcmp(obj1
.getName(), gfxGB12Tab
[i
].name
))
990 if (!gfxGB12Tab
[i
].name
) {
991 error(-1, "Unknown encoding '%s' for Adobe-GB1-2 font",
995 enc16
.enc
= gfxGB12Tab
[i
].enc
;
998 #if CHINESE_CNS_SUPPORT
999 if (enc16
.charSet
== font16AdobeCNS13
) {
1000 for (i
= 0; gfxCNS13Tab
[i
].name
; ++i
) {
1001 if (!strcmp(obj1
.getName(), gfxCNS13Tab
[i
].name
))
1004 if (!gfxCNS13Tab
[i
].name
) {
1005 error(-1, "Unknown encoding '%s' for Adobe-CNS1-3 font",
1009 enc16
.enc
= gfxCNS13Tab
[i
].enc
;
1025 //~ fix this --> add 16-bit font support to FontFile
1026 encoding
= new FontEncoding();
1027 makeWidths(fontDict
, NULL
, NULL
, 0);
1031 static int CDECL
cmpWidthExcep(const void *w1
, const void *w2
) {
1032 return ((GfxFontWidthExcep
*)w1
)->first
- ((GfxFontWidthExcep
*)w2
)->first
;
1035 static int CDECL
cmpWidthExcepV(const void *w1
, const void *w2
) {
1036 return ((GfxFontWidthExcepV
*)w1
)->first
- ((GfxFontWidthExcepV
*)w2
)->first
;
1040 //------------------------------------------------------------------------
1042 //------------------------------------------------------------------------
1044 GfxFontDict::GfxFontDict(XRef
*xref
, Dict
*fontDict
) {
1048 numFonts
= fontDict
->getLength();
1049 fonts
= (GfxFont
**)gmalloc(numFonts
* sizeof(GfxFont
*));
1050 for (i
= 0; i
< numFonts
; ++i
) {
1051 fontDict
->getValNF(i
, &obj1
);
1052 obj1
.fetch(xref
, &obj2
);
1053 if (obj1
.isRef() && obj2
.isDict()) {
1054 fonts
[i
] = new GfxFont(xref
, fontDict
->getKey(i
),
1055 obj1
.getRef(), obj2
.getDict());
1057 error(-1, "font resource is not a dictionary");
1065 GfxFontDict::~GfxFontDict() {
1068 for (i
= 0; i
< numFonts
; ++i
)
1073 GfxFont
*GfxFontDict::lookup(char *tag
) {
1076 for (i
= 0; i
< numFonts
; ++i
) {
1077 if (fonts
[i
]->matches(tag
))