1 //========================================================================
5 // Copyright 1999-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
19 #include "goo/GooString.h"
20 #include "FoFiEncodings.h"
21 #include "FoFiType1C.h"
23 //------------------------------------------------------------------------
25 static char hexChars
[17] = "0123456789ABCDEF";
27 //------------------------------------------------------------------------
29 //------------------------------------------------------------------------
31 FoFiType1C
*FoFiType1C::make(char *fileA
, int lenA
) {
34 ff
= new FoFiType1C(fileA
, lenA
, gFalse
);
42 FoFiType1C
*FoFiType1C::load(char *fileName
) {
47 if (!(fileA
= FoFiBase::readFile(fileName
, &lenA
))) {
50 ff
= new FoFiType1C(fileA
, lenA
, gTrue
);
58 FoFiType1C::FoFiType1C(char *fileA
, int lenA
, GBool freeFileDataA
):
59 FoFiBase(fileA
, lenA
, freeFileDataA
)
68 FoFiType1C::~FoFiType1C() {
75 encoding
!= fofiType1StandardEncoding
&&
76 encoding
!= fofiType1ExpertEncoding
) {
77 for (i
= 0; i
< 256; ++i
) {
89 charset
!= fofiType1CISOAdobeCharset
&&
90 charset
!= fofiType1CExpertCharset
&&
91 charset
!= fofiType1CExpertSubsetCharset
) {
96 char *FoFiType1C::getName() {
97 return name
? name
->getCString() : (char *)NULL
;
100 char **FoFiType1C::getEncoding() {
104 Gushort
*FoFiType1C::getCIDToGIDMap(int *nCIDs
) {
108 // a CID font's top dict has ROS as the first operator
109 if (topDict
.firstOp
!= 0x0c1e) {
114 // in a CID font, the charset data is the GID-to-CID mapping, so all
115 // we have to do is reverse it
117 for (i
= 0; i
< nGlyphs
; ++i
) {
118 if (charset
[i
] > n
) {
123 map
= (Gushort
*)gmallocn(n
, sizeof(Gushort
));
124 memset(map
, 0, n
* sizeof(Gushort
));
125 for (i
= 0; i
< nGlyphs
; ++i
) {
132 void FoFiType1C::convertToType1(char **newEncoding
, GBool ascii
,
133 FoFiOutputFunc outputFunc
,
134 void *outputStream
) {
143 // write header and font dictionary, up to encoding
145 (*outputFunc
)(outputStream
, "%!FontType1-1.0: ", 17);
146 (*outputFunc
)(outputStream
, name
->getCString(), name
->getLength());
147 if (topDict
.versionSID
!= 0) {
148 getString(topDict
.versionSID
, buf
, &ok
);
149 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
151 (*outputFunc
)(outputStream
, "\n", 1);
152 // the dictionary needs room for 12 entries: the following 9, plus
153 // Private and CharStrings (in the eexec section) and FID (which is
154 // added by definefont)
155 (*outputFunc
)(outputStream
, "12 dict begin\n", 14);
156 (*outputFunc
)(outputStream
, "/FontInfo 10 dict dup begin\n", 28);
157 if (topDict
.versionSID
!= 0) {
158 (*outputFunc
)(outputStream
, "/version (", 10);
159 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
160 (*outputFunc
)(outputStream
, ") readonly def\n", 15);
162 if (topDict
.noticeSID
!= 0) {
163 getString(topDict
.noticeSID
, buf
, &ok
);
164 (*outputFunc
)(outputStream
, "/Notice (", 9);
165 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
166 (*outputFunc
)(outputStream
, ") readonly def\n", 15);
168 if (topDict
.copyrightSID
!= 0) {
169 getString(topDict
.copyrightSID
, buf
, &ok
);
170 (*outputFunc
)(outputStream
, "/Copyright (", 12);
171 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
172 (*outputFunc
)(outputStream
, ") readonly def\n", 15);
174 if (topDict
.fullNameSID
!= 0) {
175 getString(topDict
.fullNameSID
, buf
, &ok
);
176 (*outputFunc
)(outputStream
, "/FullName (", 11);
177 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
178 (*outputFunc
)(outputStream
, ") readonly def\n", 15);
180 if (topDict
.familyNameSID
!= 0) {
181 getString(topDict
.familyNameSID
, buf
, &ok
);
182 (*outputFunc
)(outputStream
, "/FamilyName (", 13);
183 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
184 (*outputFunc
)(outputStream
, ") readonly def\n", 15);
186 if (topDict
.weightSID
!= 0) {
187 getString(topDict
.weightSID
, buf
, &ok
);
188 (*outputFunc
)(outputStream
, "/Weight (", 9);
189 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
190 (*outputFunc
)(outputStream
, ") readonly def\n", 15);
192 if (topDict
.isFixedPitch
) {
193 (*outputFunc
)(outputStream
, "/isFixedPitch true def\n", 23);
195 (*outputFunc
)(outputStream
, "/isFixedPitch false def\n", 24);
197 sprintf(buf
, "/ItalicAngle %g def\n", topDict
.italicAngle
);
198 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
199 sprintf(buf
, "/UnderlinePosition %g def\n", topDict
.underlinePosition
);
200 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
201 sprintf(buf
, "/UnderlineThickness %g def\n", topDict
.underlineThickness
);
202 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
203 (*outputFunc
)(outputStream
, "end readonly def\n", 17);
204 (*outputFunc
)(outputStream
, "/FontName /", 11);
205 (*outputFunc
)(outputStream
, name
->getCString(), name
->getLength());
206 (*outputFunc
)(outputStream
, " def\n", 5);
207 sprintf(buf
, "/PaintType %d def\n", topDict
.paintType
);
208 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
209 (*outputFunc
)(outputStream
, "/FontType 1 def\n", 16);
210 sprintf(buf
, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
211 topDict
.fontMatrix
[0], topDict
.fontMatrix
[1], topDict
.fontMatrix
[2],
212 topDict
.fontMatrix
[3], topDict
.fontMatrix
[4], topDict
.fontMatrix
[5]);
213 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
214 sprintf(buf
, "/FontBBox [%g %g %g %g] readonly def\n",
215 topDict
.fontBBox
[0], topDict
.fontBBox
[1],
216 topDict
.fontBBox
[2], topDict
.fontBBox
[3]);
217 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
218 sprintf(buf
, "/StrokeWidth %g def\n", topDict
.strokeWidth
);
219 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
220 if (topDict
.uniqueID
!= 0) {
221 sprintf(buf
, "/UniqueID %d def\n", topDict
.uniqueID
);
222 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
225 // write the encoding
226 (*outputFunc
)(outputStream
, "/Encoding ", 10);
227 if (!newEncoding
&& encoding
== fofiType1StandardEncoding
) {
228 (*outputFunc
)(outputStream
, "StandardEncoding def\n", 21);
230 (*outputFunc
)(outputStream
, "256 array\n", 10);
231 (*outputFunc
)(outputStream
,
232 "0 1 255 {1 index exch /.notdef put} for\n", 40);
233 enc
= newEncoding
? newEncoding
: encoding
;
234 for (i
= 0; i
< 256; ++i
) {
236 sprintf(buf
, "dup %d /%s put\n", i
, enc
[i
]);
237 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
240 (*outputFunc
)(outputStream
, "readonly def\n", 13);
242 (*outputFunc
)(outputStream
, "currentdict end\n", 16);
244 // start the binary section
245 (*outputFunc
)(outputStream
, "currentfile eexec\n", 18);
246 eb
.outputFunc
= outputFunc
;
247 eb
.outputStream
= outputStream
;
252 // write the private dictionary
253 eexecWrite(&eb
, "\x83\xca\x73\xd5");
254 eexecWrite(&eb
, "dup /Private 32 dict dup begin\n");
255 eexecWrite(&eb
, "/RD {string currentfile exch readstring pop}"
256 " executeonly def\n");
257 eexecWrite(&eb
, "/ND {noaccess def} executeonly def\n");
258 eexecWrite(&eb
, "/NP {noaccess put} executeonly def\n");
259 eexecWrite(&eb
, "/MinFeature {16 16} def\n");
260 eexecWrite(&eb
, "/password 5839 def\n");
261 if (privateDicts
[0].nBlueValues
) {
262 eexecWrite(&eb
, "/BlueValues [");
263 for (i
= 0; i
< privateDicts
[0].nBlueValues
; ++i
) {
264 sprintf(buf
, "%s%d", i
> 0 ? " " : "", privateDicts
[0].blueValues
[i
]);
265 eexecWrite(&eb
, buf
);
267 eexecWrite(&eb
, "] def\n");
269 if (privateDicts
[0].nOtherBlues
) {
270 eexecWrite(&eb
, "/OtherBlues [");
271 for (i
= 0; i
< privateDicts
[0].nOtherBlues
; ++i
) {
272 sprintf(buf
, "%s%d", i
> 0 ? " " : "", privateDicts
[0].otherBlues
[i
]);
273 eexecWrite(&eb
, buf
);
275 eexecWrite(&eb
, "] def\n");
277 if (privateDicts
[0].nFamilyBlues
) {
278 eexecWrite(&eb
, "/FamilyBlues [");
279 for (i
= 0; i
< privateDicts
[0].nFamilyBlues
; ++i
) {
280 sprintf(buf
, "%s%d", i
> 0 ? " " : "", privateDicts
[0].familyBlues
[i
]);
281 eexecWrite(&eb
, buf
);
283 eexecWrite(&eb
, "] def\n");
285 if (privateDicts
[0].nFamilyOtherBlues
) {
286 eexecWrite(&eb
, "/FamilyOtherBlues [");
287 for (i
= 0; i
< privateDicts
[0].nFamilyOtherBlues
; ++i
) {
288 sprintf(buf
, "%s%d", i
> 0 ? " " : "",
289 privateDicts
[0].familyOtherBlues
[i
]);
290 eexecWrite(&eb
, buf
);
292 eexecWrite(&eb
, "] def\n");
294 if (privateDicts
[0].blueScale
!= 0.039625) {
295 sprintf(buf
, "/BlueScale %g def\n", privateDicts
[0].blueScale
);
296 eexecWrite(&eb
, buf
);
298 if (privateDicts
[0].blueShift
!= 7) {
299 sprintf(buf
, "/BlueShift %d def\n", privateDicts
[0].blueShift
);
300 eexecWrite(&eb
, buf
);
302 if (privateDicts
[0].blueFuzz
!= 1) {
303 sprintf(buf
, "/BlueFuzz %d def\n", privateDicts
[0].blueFuzz
);
304 eexecWrite(&eb
, buf
);
306 if (privateDicts
[0].hasStdHW
) {
307 sprintf(buf
, "/StdHW [%g] def\n", privateDicts
[0].stdHW
);
308 eexecWrite(&eb
, buf
);
310 if (privateDicts
[0].hasStdVW
) {
311 sprintf(buf
, "/StdVW [%g] def\n", privateDicts
[0].stdVW
);
312 eexecWrite(&eb
, buf
);
314 if (privateDicts
[0].nStemSnapH
) {
315 eexecWrite(&eb
, "/StemSnapH [");
316 for (i
= 0; i
< privateDicts
[0].nStemSnapH
; ++i
) {
317 sprintf(buf
, "%s%g", i
> 0 ? " " : "", privateDicts
[0].stemSnapH
[i
]);
318 eexecWrite(&eb
, buf
);
320 eexecWrite(&eb
, "] def\n");
322 if (privateDicts
[0].nStemSnapV
) {
323 eexecWrite(&eb
, "/StemSnapV [");
324 for (i
= 0; i
< privateDicts
[0].nStemSnapV
; ++i
) {
325 sprintf(buf
, "%s%g", i
> 0 ? " " : "", privateDicts
[0].stemSnapV
[i
]);
326 eexecWrite(&eb
, buf
);
328 eexecWrite(&eb
, "] def\n");
330 if (privateDicts
[0].hasForceBold
) {
331 sprintf(buf
, "/ForceBold %s def\n",
332 privateDicts
[0].forceBold
? "true" : "false");
333 eexecWrite(&eb
, buf
);
335 if (privateDicts
[0].forceBoldThreshold
!= 0) {
336 sprintf(buf
, "/ForceBoldThreshold %g def\n",
337 privateDicts
[0].forceBoldThreshold
);
338 eexecWrite(&eb
, buf
);
340 if (privateDicts
[0].languageGroup
!= 0) {
341 sprintf(buf
, "/LanguageGroup %d def\n", privateDicts
[0].languageGroup
);
342 eexecWrite(&eb
, buf
);
344 if (privateDicts
[0].expansionFactor
!= 0.06) {
345 sprintf(buf
, "/ExpansionFactor %g def\n", privateDicts
[0].expansionFactor
);
346 eexecWrite(&eb
, buf
);
349 // set up subroutines
351 getIndex(privateDicts
[0].subrsOffset
, &subrIdx
, &ok
);
356 // write the CharStrings
357 sprintf(buf
, "2 index /CharStrings %d dict dup begin\n", nGlyphs
);
358 eexecWrite(&eb
, buf
);
359 for (i
= 0; i
< nGlyphs
; ++i
) {
361 getIndexVal(&charStringsIdx
, i
, &val
, &ok
);
363 getString(charset
[i
], buf
, &ok
);
365 eexecCvtGlyph(&eb
, buf
, val
.pos
, val
.len
, &subrIdx
, &privateDicts
[0]);
369 eexecWrite(&eb
, "end\n");
370 eexecWrite(&eb
, "end\n");
371 eexecWrite(&eb
, "readonly put\n");
372 eexecWrite(&eb
, "noaccess put\n");
373 eexecWrite(&eb
, "dup /FontName get exch definefont pop\n");
374 eexecWrite(&eb
, "mark currentfile closefile\n");
377 if (ascii
&& eb
.line
> 0) {
378 (*outputFunc
)(outputStream
, "\n", 1);
380 for (i
= 0; i
< 8; ++i
) {
381 (*outputFunc
)(outputStream
, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
383 (*outputFunc
)(outputStream
, "cleartomark\n", 12);
386 void FoFiType1C::convertToCIDType0(char *psName
,
387 FoFiOutputFunc outputFunc
,
388 void *outputStream
) {
390 GooString
*charStrings
;
391 int *charStringOffsets
;
395 char buf
[512], buf2
[512];
397 int gid
, offset
, n
, i
, j
, k
;
399 // compute the CID count and build the CID-to-GID mapping
401 for (i
= 0; i
< nGlyphs
; ++i
) {
402 if (charset
[i
] >= nCIDs
) {
403 nCIDs
= charset
[i
] + 1;
406 cidMap
= (int *)gmallocn(nCIDs
, sizeof(int));
407 for (i
= 0; i
< nCIDs
; ++i
) {
410 for (i
= 0; i
< nGlyphs
; ++i
) {
411 cidMap
[charset
[i
]] = i
;
414 // build the charstrings
415 charStrings
= new GooString();
416 charStringOffsets
= (int *)gmallocn(nCIDs
+ 1, sizeof(int));
417 for (i
= 0; i
< nCIDs
; ++i
) {
418 charStringOffsets
[i
] = charStrings
->getLength();
419 if ((gid
= cidMap
[i
]) >= 0) {
421 getIndexVal(&charStringsIdx
, gid
, &val
, &ok
);
423 getIndex(privateDicts
[fdSelect
[gid
]].subrsOffset
, &subrIdx
, &ok
);
427 cvtGlyph(val
.pos
, val
.len
, charStrings
,
428 &subrIdx
, &privateDicts
[fdSelect
[gid
]], gTrue
);
432 charStringOffsets
[nCIDs
] = charStrings
->getLength();
434 // compute gdBytes = number of bytes needed for charstring offsets
435 // (offset size needs to account for the charstring offset table,
436 // with a worst case of five bytes per entry, plus the charstrings
438 i
= (nCIDs
+ 1) * 5 + charStrings
->getLength();
441 } else if (i
< 0x10000) {
443 } else if (i
< 0x1000000) {
449 // begin the font dictionary
450 (*outputFunc
)(outputStream
, "/CIDInit /ProcSet findresource begin\n", 37);
451 (*outputFunc
)(outputStream
, "20 dict begin\n", 14);
452 (*outputFunc
)(outputStream
, "/CIDFontName /", 14);
453 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
454 (*outputFunc
)(outputStream
, " def\n", 5);
455 (*outputFunc
)(outputStream
, "/CIDFontType 0 def\n", 19);
456 (*outputFunc
)(outputStream
, "/CIDSystemInfo 3 dict dup begin\n", 32);
457 if (topDict
.registrySID
> 0 && topDict
.orderingSID
> 0) {
459 getString(topDict
.registrySID
, buf
, &ok
);
461 (*outputFunc
)(outputStream
, " /Registry (", 13);
462 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
463 (*outputFunc
)(outputStream
, ") def\n", 6);
466 getString(topDict
.orderingSID
, buf
, &ok
);
468 (*outputFunc
)(outputStream
, " /Ordering (", 13);
469 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
470 (*outputFunc
)(outputStream
, ") def\n", 6);
473 (*outputFunc
)(outputStream
, " /Registry (Adobe) def\n", 24);
474 (*outputFunc
)(outputStream
, " /Ordering (Identity) def\n", 27);
476 sprintf(buf
, " /Supplement %d def\n", topDict
.supplement
);
477 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
478 (*outputFunc
)(outputStream
, "end def\n", 8);
479 if (topDict
.hasFontMatrix
) {
480 sprintf(buf
, "/FontMatrix [%g %g %g %g %g %g] def\n",
481 topDict
.fontMatrix
[0], topDict
.fontMatrix
[1],
482 topDict
.fontMatrix
[2], topDict
.fontMatrix
[3],
483 topDict
.fontMatrix
[4], topDict
.fontMatrix
[5]);
484 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
485 } else if (privateDicts
[0].hasFontMatrix
) {
486 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
488 (*outputFunc
)(outputStream
,
489 "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
491 sprintf(buf
, "/FontBBox [%g %g %g %g] def\n",
492 topDict
.fontBBox
[0], topDict
.fontBBox
[1],
493 topDict
.fontBBox
[2], topDict
.fontBBox
[3]);
494 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
495 (*outputFunc
)(outputStream
, "/FontInfo 1 dict dup begin\n", 27);
496 (*outputFunc
)(outputStream
, " /FSType 8 def\n", 16);
497 (*outputFunc
)(outputStream
, "end def\n", 8);
499 // CIDFont-specific entries
500 sprintf(buf
, "/CIDCount %d def\n", nCIDs
);
501 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
502 (*outputFunc
)(outputStream
, "/FDBytes 1 def\n", 15);
503 sprintf(buf
, "/GDBytes %d def\n", gdBytes
);
504 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
505 (*outputFunc
)(outputStream
, "/CIDMapOffset 0 def\n", 20);
506 if (topDict
.paintType
!= 0) {
507 sprintf(buf
, "/PaintType %d def\n", topDict
.paintType
);
508 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
509 sprintf(buf
, "/StrokeWidth %g def\n", topDict
.strokeWidth
);
510 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
514 sprintf(buf
, "/FDArray %d array\n", nFDs
);
515 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
516 for (i
= 0; i
< nFDs
; ++i
) {
517 sprintf(buf
, "dup %d 10 dict begin\n", i
);
518 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
519 (*outputFunc
)(outputStream
, "/FontType 1 def\n", 16);
520 if (privateDicts
[i
].hasFontMatrix
) {
521 sprintf(buf
, "/FontMatrix [%g %g %g %g %g %g] def\n",
522 privateDicts
[i
].fontMatrix
[0],
523 privateDicts
[i
].fontMatrix
[1],
524 privateDicts
[i
].fontMatrix
[2],
525 privateDicts
[i
].fontMatrix
[3],
526 privateDicts
[i
].fontMatrix
[4],
527 privateDicts
[i
].fontMatrix
[5]);
528 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
530 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
532 sprintf(buf
, "/PaintType %d def\n", topDict
.paintType
);
533 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
534 (*outputFunc
)(outputStream
, "/Private 32 dict begin\n", 23);
535 if (privateDicts
[i
].nBlueValues
) {
536 (*outputFunc
)(outputStream
, "/BlueValues [", 13);
537 for (j
= 0; j
< privateDicts
[i
].nBlueValues
; ++j
) {
538 sprintf(buf
, "%s%d", j
> 0 ? " " : "", privateDicts
[i
].blueValues
[j
]);
539 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
541 (*outputFunc
)(outputStream
, "] def\n", 6);
543 if (privateDicts
[i
].nOtherBlues
) {
544 (*outputFunc
)(outputStream
, "/OtherBlues [", 13);
545 for (j
= 0; j
< privateDicts
[i
].nOtherBlues
; ++j
) {
546 sprintf(buf
, "%s%d", j
> 0 ? " " : "", privateDicts
[i
].otherBlues
[j
]);
547 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
549 (*outputFunc
)(outputStream
, "] def\n", 6);
551 if (privateDicts
[i
].nFamilyBlues
) {
552 (*outputFunc
)(outputStream
, "/FamilyBlues [", 14);
553 for (j
= 0; j
< privateDicts
[i
].nFamilyBlues
; ++j
) {
554 sprintf(buf
, "%s%d", j
> 0 ? " " : "", privateDicts
[i
].familyBlues
[j
]);
555 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
557 (*outputFunc
)(outputStream
, "] def\n", 6);
559 if (privateDicts
[i
].nFamilyOtherBlues
) {
560 (*outputFunc
)(outputStream
, "/FamilyOtherBlues [", 19);
561 for (j
= 0; j
< privateDicts
[i
].nFamilyOtherBlues
; ++j
) {
562 sprintf(buf
, "%s%d", j
> 0 ? " " : "",
563 privateDicts
[i
].familyOtherBlues
[j
]);
564 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
566 (*outputFunc
)(outputStream
, "] def\n", 6);
568 if (privateDicts
[i
].blueScale
!= 0.039625) {
569 sprintf(buf
, "/BlueScale %g def\n", privateDicts
[i
].blueScale
);
570 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
572 if (privateDicts
[i
].blueShift
!= 7) {
573 sprintf(buf
, "/BlueShift %d def\n", privateDicts
[i
].blueShift
);
574 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
576 if (privateDicts
[i
].blueFuzz
!= 1) {
577 sprintf(buf
, "/BlueFuzz %d def\n", privateDicts
[i
].blueFuzz
);
578 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
580 if (privateDicts
[i
].hasStdHW
) {
581 sprintf(buf
, "/StdHW [%g] def\n", privateDicts
[i
].stdHW
);
582 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
584 if (privateDicts
[i
].hasStdVW
) {
585 sprintf(buf
, "/StdVW [%g] def\n", privateDicts
[i
].stdVW
);
586 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
588 if (privateDicts
[i
].nStemSnapH
) {
589 (*outputFunc
)(outputStream
, "/StemSnapH [", 12);
590 for (j
= 0; j
< privateDicts
[i
].nStemSnapH
; ++j
) {
591 sprintf(buf
, "%s%g", j
> 0 ? " " : "", privateDicts
[i
].stemSnapH
[j
]);
592 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
594 (*outputFunc
)(outputStream
, "] def\n", 6);
596 if (privateDicts
[i
].nStemSnapV
) {
597 (*outputFunc
)(outputStream
, "/StemSnapV [", 12);
598 for (j
= 0; j
< privateDicts
[i
].nStemSnapV
; ++j
) {
599 sprintf(buf
, "%s%g", j
> 0 ? " " : "", privateDicts
[i
].stemSnapV
[j
]);
600 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
602 (*outputFunc
)(outputStream
, "] def\n", 6);
604 if (privateDicts
[i
].hasForceBold
) {
605 sprintf(buf
, "/ForceBold %s def\n",
606 privateDicts
[i
].forceBold
? "true" : "false");
607 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
609 if (privateDicts
[i
].forceBoldThreshold
!= 0) {
610 sprintf(buf
, "/ForceBoldThreshold %g def\n",
611 privateDicts
[i
].forceBoldThreshold
);
612 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
614 if (privateDicts
[i
].languageGroup
!= 0) {
615 sprintf(buf
, "/LanguageGroup %d def\n", privateDicts
[i
].languageGroup
);
616 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
618 if (privateDicts
[i
].expansionFactor
!= 0.06) {
619 sprintf(buf
, "/ExpansionFactor %g def\n",
620 privateDicts
[i
].expansionFactor
);
621 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
623 (*outputFunc
)(outputStream
, "currentdict end def\n", 20);
624 (*outputFunc
)(outputStream
, "currentdict end put\n", 20);
626 (*outputFunc
)(outputStream
, "def\n", 4);
628 // start the binary section
629 offset
= (nCIDs
+ 1) * (1 + gdBytes
);
630 sprintf(buf
, "(Hex) %d StartData\n",
631 offset
+ charStrings
->getLength());
632 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
634 // write the charstring offset (CIDMap) table
635 for (i
= 0; i
<= nCIDs
; i
+= 6) {
636 for (j
= 0; j
< 6 && i
+j
<= nCIDs
; ++j
) {
637 if (i
+j
< nCIDs
&& cidMap
[i
+j
] >= 0) {
638 buf
[0] = (char)fdSelect
[cidMap
[i
+j
]];
642 n
= offset
+ charStringOffsets
[i
+j
];
643 for (k
= gdBytes
; k
>= 1; --k
) {
644 buf
[k
] = (char)(n
& 0xff);
647 for (k
= 0; k
<= gdBytes
; ++k
) {
648 sprintf(buf2
, "%02x", buf
[k
] & 0xff);
649 (*outputFunc
)(outputStream
, buf2
, 2);
652 (*outputFunc
)(outputStream
, "\n", 1);
655 // write the charstring data
656 n
= charStrings
->getLength();
657 for (i
= 0; i
< n
; i
+= 32) {
658 for (j
= 0; j
< 32 && i
+j
< n
; ++j
) {
659 sprintf(buf
, "%02x", charStrings
->getChar(i
+j
) & 0xff);
660 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
663 (*outputFunc
)(outputStream
, ">", 1);
665 (*outputFunc
)(outputStream
, "\n", 1);
668 gfree(charStringOffsets
);
673 void FoFiType1C::convertToType0(char *psName
,
674 FoFiOutputFunc outputFunc
,
675 void *outputStream
) {
685 // compute the CID count and build the CID-to-GID mapping
687 for (i
= 0; i
< nGlyphs
; ++i
) {
688 if (charset
[i
] >= nCIDs
) {
689 nCIDs
= charset
[i
] + 1;
692 cidMap
= (int *)gmallocn(nCIDs
, sizeof(int));
693 for (i
= 0; i
< nCIDs
; ++i
) {
696 for (i
= 0; i
< nGlyphs
; ++i
) {
697 cidMap
[charset
[i
]] = i
;
700 // write the descendant Type 1 fonts
701 for (i
= 0; i
< nCIDs
; i
+= 256) {
703 //~ this assumes that all CIDs in this block have the same FD --
704 //~ to handle multiple FDs correctly, need to somehow divide the
707 for (j
= 0; j
< 256 && i
+j
< nCIDs
; ++j
) {
708 if (cidMap
[i
+j
] >= 0) {
709 fd
= fdSelect
[cidMap
[i
+j
]];
714 // font dictionary (unencrypted section)
715 (*outputFunc
)(outputStream
, "16 dict begin\n", 14);
716 (*outputFunc
)(outputStream
, "/FontName /", 11);
717 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
718 sprintf(buf
, "_%02x def\n", i
>> 8);
719 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
720 (*outputFunc
)(outputStream
, "/FontType 1 def\n", 16);
721 if (privateDicts
[fd
].hasFontMatrix
) {
722 sprintf(buf
, "/FontMatrix [%g %g %g %g %g %g] def\n",
723 privateDicts
[fd
].fontMatrix
[0],
724 privateDicts
[fd
].fontMatrix
[1],
725 privateDicts
[fd
].fontMatrix
[2],
726 privateDicts
[fd
].fontMatrix
[3],
727 privateDicts
[fd
].fontMatrix
[4],
728 privateDicts
[fd
].fontMatrix
[5]);
729 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
730 } else if (topDict
.hasFontMatrix
) {
731 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
733 (*outputFunc
)(outputStream
,
734 "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
736 sprintf(buf
, "/FontBBox [%g %g %g %g] def\n",
737 topDict
.fontBBox
[0], topDict
.fontBBox
[1],
738 topDict
.fontBBox
[2], topDict
.fontBBox
[3]);
739 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
740 sprintf(buf
, "/PaintType %d def\n", topDict
.paintType
);
741 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
742 if (topDict
.paintType
!= 0) {
743 sprintf(buf
, "/StrokeWidth %g def\n", topDict
.strokeWidth
);
744 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
746 (*outputFunc
)(outputStream
, "/Encoding 256 array\n", 20);
747 for (j
= 0; j
< 256 && i
+j
< nCIDs
; ++j
) {
748 sprintf(buf
, "dup %d /c%02x put\n", j
, j
);
749 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
752 sprintf(buf
, "%d 1 255 { 1 index exch /.notdef put } for\n", j
);
753 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
755 (*outputFunc
)(outputStream
, "readonly def\n", 13);
756 (*outputFunc
)(outputStream
, "currentdict end\n", 16);
758 // start the binary section
759 (*outputFunc
)(outputStream
, "currentfile eexec\n", 18);
760 eb
.outputFunc
= outputFunc
;
761 eb
.outputStream
= outputStream
;
766 // start the private dictionary
767 eexecWrite(&eb
, "\x83\xca\x73\xd5");
768 eexecWrite(&eb
, "dup /Private 32 dict dup begin\n");
769 eexecWrite(&eb
, "/RD {string currentfile exch readstring pop}"
770 " executeonly def\n");
771 eexecWrite(&eb
, "/ND {noaccess def} executeonly def\n");
772 eexecWrite(&eb
, "/NP {noaccess put} executeonly def\n");
773 eexecWrite(&eb
, "/MinFeature {16 16} def\n");
774 eexecWrite(&eb
, "/password 5839 def\n");
775 if (privateDicts
[fd
].nBlueValues
) {
776 eexecWrite(&eb
, "/BlueValues [");
777 for (k
= 0; k
< privateDicts
[fd
].nBlueValues
; ++k
) {
778 sprintf(buf
, "%s%d", k
> 0 ? " " : "", privateDicts
[fd
].blueValues
[k
]);
779 eexecWrite(&eb
, buf
);
781 eexecWrite(&eb
, "] def\n");
783 if (privateDicts
[fd
].nOtherBlues
) {
784 eexecWrite(&eb
, "/OtherBlues [");
785 for (k
= 0; k
< privateDicts
[fd
].nOtherBlues
; ++k
) {
786 sprintf(buf
, "%s%d", k
> 0 ? " " : "", privateDicts
[fd
].otherBlues
[k
]);
787 eexecWrite(&eb
, buf
);
789 eexecWrite(&eb
, "] def\n");
791 if (privateDicts
[fd
].nFamilyBlues
) {
792 eexecWrite(&eb
, "/FamilyBlues [");
793 for (k
= 0; k
< privateDicts
[fd
].nFamilyBlues
; ++k
) {
794 sprintf(buf
, "%s%d", k
> 0 ? " " : "",
795 privateDicts
[fd
].familyBlues
[k
]);
796 eexecWrite(&eb
, buf
);
798 eexecWrite(&eb
, "] def\n");
800 if (privateDicts
[fd
].nFamilyOtherBlues
) {
801 eexecWrite(&eb
, "/FamilyOtherBlues [");
802 for (k
= 0; k
< privateDicts
[fd
].nFamilyOtherBlues
; ++k
) {
803 sprintf(buf
, "%s%d", k
> 0 ? " " : "",
804 privateDicts
[fd
].familyOtherBlues
[k
]);
805 eexecWrite(&eb
, buf
);
807 eexecWrite(&eb
, "] def\n");
809 if (privateDicts
[fd
].blueScale
!= 0.039625) {
810 sprintf(buf
, "/BlueScale %g def\n", privateDicts
[fd
].blueScale
);
811 eexecWrite(&eb
, buf
);
813 if (privateDicts
[fd
].blueShift
!= 7) {
814 sprintf(buf
, "/BlueShift %d def\n", privateDicts
[fd
].blueShift
);
815 eexecWrite(&eb
, buf
);
817 if (privateDicts
[fd
].blueFuzz
!= 1) {
818 sprintf(buf
, "/BlueFuzz %d def\n", privateDicts
[fd
].blueFuzz
);
819 eexecWrite(&eb
, buf
);
821 if (privateDicts
[fd
].hasStdHW
) {
822 sprintf(buf
, "/StdHW [%g] def\n", privateDicts
[fd
].stdHW
);
823 eexecWrite(&eb
, buf
);
825 if (privateDicts
[fd
].hasStdVW
) {
826 sprintf(buf
, "/StdVW [%g] def\n", privateDicts
[fd
].stdVW
);
827 eexecWrite(&eb
, buf
);
829 if (privateDicts
[fd
].nStemSnapH
) {
830 eexecWrite(&eb
, "/StemSnapH [");
831 for (k
= 0; k
< privateDicts
[fd
].nStemSnapH
; ++k
) {
832 sprintf(buf
, "%s%g", k
> 0 ? " " : "", privateDicts
[fd
].stemSnapH
[k
]);
833 eexecWrite(&eb
, buf
);
835 eexecWrite(&eb
, "] def\n");
837 if (privateDicts
[fd
].nStemSnapV
) {
838 eexecWrite(&eb
, "/StemSnapV [");
839 for (k
= 0; k
< privateDicts
[fd
].nStemSnapV
; ++k
) {
840 sprintf(buf
, "%s%g", k
> 0 ? " " : "", privateDicts
[fd
].stemSnapV
[k
]);
841 eexecWrite(&eb
, buf
);
843 eexecWrite(&eb
, "] def\n");
845 if (privateDicts
[fd
].hasForceBold
) {
846 sprintf(buf
, "/ForceBold %s def\n",
847 privateDicts
[fd
].forceBold
? "true" : "false");
848 eexecWrite(&eb
, buf
);
850 if (privateDicts
[fd
].forceBoldThreshold
!= 0) {
851 sprintf(buf
, "/ForceBoldThreshold %g def\n",
852 privateDicts
[fd
].forceBoldThreshold
);
853 eexecWrite(&eb
, buf
);
855 if (privateDicts
[fd
].languageGroup
!= 0) {
856 sprintf(buf
, "/LanguageGroup %d def\n", privateDicts
[fd
].languageGroup
);
857 eexecWrite(&eb
, buf
);
859 if (privateDicts
[fd
].expansionFactor
!= 0.06) {
860 sprintf(buf
, "/ExpansionFactor %g def\n",
861 privateDicts
[fd
].expansionFactor
);
862 eexecWrite(&eb
, buf
);
865 // set up the subroutines
867 getIndex(privateDicts
[fd
].subrsOffset
, &subrIdx
, &ok
);
872 // start the CharStrings
873 sprintf(buf
, "2 index /CharStrings 256 dict dup begin\n");
874 eexecWrite(&eb
, buf
);
876 // write the .notdef CharString
878 getIndexVal(&charStringsIdx
, 0, &val
, &ok
);
880 eexecCvtGlyph(&eb
, ".notdef", val
.pos
, val
.len
,
881 &subrIdx
, &privateDicts
[fd
]);
884 // write the CharStrings
885 for (j
= 0; j
< 256 && i
+j
< nCIDs
; ++j
) {
886 if (cidMap
[i
+j
] >= 0) {
888 getIndexVal(&charStringsIdx
, cidMap
[i
+j
], &val
, &ok
);
890 sprintf(buf
, "c%02x", j
);
891 eexecCvtGlyph(&eb
, buf
, val
.pos
, val
.len
,
892 &subrIdx
, &privateDicts
[fd
]);
896 eexecWrite(&eb
, "end\n");
897 eexecWrite(&eb
, "end\n");
898 eexecWrite(&eb
, "readonly put\n");
899 eexecWrite(&eb
, "noaccess put\n");
900 eexecWrite(&eb
, "dup /FontName get exch definefont pop\n");
901 eexecWrite(&eb
, "mark currentfile closefile\n");
905 (*outputFunc
)(outputStream
, "\n", 1);
907 for (j
= 0; j
< 8; ++j
) {
908 (*outputFunc
)(outputStream
, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
910 (*outputFunc
)(outputStream
, "cleartomark\n", 12);
913 // write the Type 0 parent font
914 (*outputFunc
)(outputStream
, "16 dict begin\n", 14);
915 (*outputFunc
)(outputStream
, "/FontName /", 11);
916 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
917 (*outputFunc
)(outputStream
, " def\n", 5);
918 (*outputFunc
)(outputStream
, "/FontType 0 def\n", 16);
919 if (topDict
.hasFontMatrix
) {
920 sprintf(buf
, "/FontMatrix [%g %g %g %g %g %g] def\n",
921 topDict
.fontMatrix
[0], topDict
.fontMatrix
[1],
922 topDict
.fontMatrix
[2], topDict
.fontMatrix
[3],
923 topDict
.fontMatrix
[4], topDict
.fontMatrix
[5]);
924 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
926 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
928 (*outputFunc
)(outputStream
, "/FMapType 2 def\n", 16);
929 (*outputFunc
)(outputStream
, "/Encoding [\n", 12);
930 for (i
= 0; i
< nCIDs
; i
+= 256) {
931 sprintf(buf
, "%d\n", i
>> 8);
932 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
934 (*outputFunc
)(outputStream
, "] def\n", 6);
935 (*outputFunc
)(outputStream
, "/FDepVector [\n", 14);
936 for (i
= 0; i
< nCIDs
; i
+= 256) {
937 (*outputFunc
)(outputStream
, "/", 1);
938 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
939 sprintf(buf
, "_%02x findfont\n", i
>> 8);
940 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
942 (*outputFunc
)(outputStream
, "] def\n", 6);
943 (*outputFunc
)(outputStream
, "FontName currentdict end definefont pop\n", 40);
948 void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf
*eb
, char *glyphName
,
949 int offset
, int nBytes
,
950 Type1CIndex
*subrIdx
,
951 Type1CPrivateDict
*pDict
) {
955 // generate the charstring
956 charBuf
= new GooString();
957 cvtGlyph(offset
, nBytes
, charBuf
, subrIdx
, pDict
, gTrue
);
959 sprintf(buf
, "/%s %d RD ", glyphName
, charBuf
->getLength());
961 eexecWriteCharstring(eb
, (Guchar
*)charBuf
->getCString(),
962 charBuf
->getLength());
963 eexecWrite(eb
, " ND\n");
968 void FoFiType1C::cvtGlyph(int offset
, int nBytes
, GooString
*charBuf
,
969 Type1CIndex
*subrIdx
, Type1CPrivateDict
*pDict
,
976 int pos
, subrBias
, start
, i
, k
;
978 start
= charBuf
->getLength();
980 charBuf
->append((char)73);
981 charBuf
->append((char)58);
982 charBuf
->append((char)147);
983 charBuf
->append((char)134);
991 while (pos
< offset
+ nBytes
) {
993 pos
= getOp(pos
, gTrue
, &ok
);
997 if (!ops
[nOps
- 1].isNum
) {
998 --nOps
; // drop the operator
999 switch (ops
[nOps
].op
) {
1000 case 0x0001: // hstem
1002 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1006 //~ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
1010 for (k
= 0; k
< nOps
; k
+= 2) {
1011 // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1012 if (ops
[k
+1].num
< 0) {
1013 d
+= ops
[k
].num
+ ops
[k
+1].num
;
1014 dFP
|= ops
[k
].isFP
| ops
[k
+1].isFP
;
1015 cvtNum(d
, dFP
, charBuf
);
1016 cvtNum(-ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1020 cvtNum(d
, dFP
, charBuf
);
1021 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1023 dFP
|= ops
[k
+1].isFP
;
1025 charBuf
->append((char)1);
1030 case 0x0003: // vstem
1032 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1036 //~ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
1040 for (k
= 0; k
< nOps
; k
+= 2) {
1041 // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1042 if (ops
[k
+1].num
< 0) {
1043 d
+= ops
[k
].num
+ ops
[k
+1].num
;
1044 dFP
|= ops
[k
].isFP
| ops
[k
+1].isFP
;
1045 cvtNum(d
, dFP
, charBuf
);
1046 cvtNum(-ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1050 cvtNum(d
, dFP
, charBuf
);
1051 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1053 dFP
|= ops
[k
+1].isFP
;
1055 charBuf
->append((char)3);
1060 case 0x0004: // vmoveto
1062 cvtGlyphWidth(nOps
== 2, charBuf
, pDict
);
1066 charBuf
->append((char)9);
1070 //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1072 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1073 charBuf
->append((char)4);
1076 case 0x0005: // rlineto
1077 if (nOps
< 2 || nOps
% 2 != 0) {
1078 //~ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1080 for (k
= 0; k
< nOps
; k
+= 2) {
1081 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1082 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1083 charBuf
->append((char)5);
1088 case 0x0006: // hlineto
1090 //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1092 for (k
= 0; k
< nOps
; ++k
) {
1093 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1094 charBuf
->append((char)((k
& 1) ? 7 : 6));
1099 case 0x0007: // vlineto
1101 //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1103 for (k
= 0; k
< nOps
; ++k
) {
1104 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1105 charBuf
->append((char)((k
& 1) ? 6 : 7));
1110 case 0x0008: // rrcurveto
1111 if (nOps
< 6 || nOps
% 6 != 0) {
1112 //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1114 for (k
= 0; k
< nOps
; k
+= 6) {
1115 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1116 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1117 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1118 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1119 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1120 cvtNum(ops
[k
+5].num
, ops
[k
+5].isFP
, charBuf
);
1121 charBuf
->append((char)8);
1126 case 0x000a: // callsubr
1128 subrBias
= (subrIdx
->len
< 1240)
1129 ? 107 : (subrIdx
->len
< 33900) ? 1131 : 32768;
1130 k
= subrBias
+ (int)ops
[nOps
- 1].num
;
1133 getIndexVal(subrIdx
, k
, &val
, &ok
);
1135 cvtGlyph(val
.pos
, val
.len
, charBuf
, subrIdx
, pDict
, gFalse
);
1138 //~ error(-1, "Too few args to Type 2 callsubr");
1140 // don't clear the stack
1142 case 0x000b: // return
1143 // don't clear the stack
1145 case 0x000e: // endchar / seac
1147 cvtGlyphWidth(nOps
== 1 || nOps
== 5, charBuf
, pDict
);
1151 charBuf
->append((char)9);
1155 cvtNum(0, gFalse
, charBuf
);
1156 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1157 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1158 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1159 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1160 charBuf
->append((char)12)->append((char)6);
1161 } else if (nOps
== 0) {
1162 charBuf
->append((char)14);
1164 //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1168 case 0x000f: // (obsolete)
1169 // this op is ignored, but we need the glyph width
1171 cvtGlyphWidth(nOps
> 0, charBuf
, pDict
);
1176 case 0x0010: // blend
1177 //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
1180 case 0x0012: // hstemhm
1183 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1187 //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1192 case 0x0013: // hintmask
1195 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1200 //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1205 pos
+= (nHints
+ 7) >> 3;
1208 case 0x0014: // cntrmask
1211 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1216 //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1221 pos
+= (nHints
+ 7) >> 3;
1224 case 0x0015: // rmoveto
1226 cvtGlyphWidth(nOps
== 3, charBuf
, pDict
);
1230 charBuf
->append((char)9);
1234 //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1236 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1237 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1238 charBuf
->append((char)21);
1241 case 0x0016: // hmoveto
1243 cvtGlyphWidth(nOps
== 2, charBuf
, pDict
);
1247 charBuf
->append((char)9);
1251 //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1253 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1254 charBuf
->append((char)22);
1257 case 0x0017: // vstemhm
1260 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1264 //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1269 case 0x0018: // rcurveline
1270 if (nOps
< 8 || (nOps
- 2) % 6 != 0) {
1271 //~ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1273 for (k
= 0; k
< nOps
- 2; k
+= 6) {
1274 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1275 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1276 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1277 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1278 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1279 cvtNum(ops
[k
+5].num
, ops
[k
+5].isFP
, charBuf
);
1280 charBuf
->append((char)8);
1282 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1283 cvtNum(ops
[k
+1].num
, ops
[k
].isFP
, charBuf
);
1284 charBuf
->append((char)5);
1288 case 0x0019: // rlinecurve
1289 if (nOps
< 8 || (nOps
- 6) % 2 != 0) {
1290 //~ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1292 for (k
= 0; k
< nOps
- 6; k
+= 2) {
1293 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1294 cvtNum(ops
[k
+1].num
, ops
[k
].isFP
, charBuf
);
1295 charBuf
->append((char)5);
1297 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1298 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1299 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1300 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1301 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1302 cvtNum(ops
[k
+5].num
, ops
[k
+5].isFP
, charBuf
);
1303 charBuf
->append((char)8);
1307 case 0x001a: // vvcurveto
1308 if (nOps
< 4 || !(nOps
% 4 == 0 || (nOps
-1) % 4 == 0)) {
1309 //~ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1311 if (nOps
% 2 == 1) {
1312 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1313 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1314 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1315 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1316 cvtNum(0, gFalse
, charBuf
);
1317 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1318 charBuf
->append((char)8);
1323 for (; k
< nOps
; k
+= 4) {
1324 cvtNum(0, gFalse
, charBuf
);
1325 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1326 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1327 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1328 cvtNum(0, gFalse
, charBuf
);
1329 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1330 charBuf
->append((char)8);
1335 case 0x001b: // hhcurveto
1336 if (nOps
< 4 || !(nOps
% 4 == 0 || (nOps
-1) % 4 == 0)) {
1337 //~ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1339 if (nOps
% 2 == 1) {
1340 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1341 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1342 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1343 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1344 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1345 cvtNum(0, gFalse
, charBuf
);
1346 charBuf
->append((char)8);
1351 for (; k
< nOps
; k
+= 4) {
1352 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1353 cvtNum(0, gFalse
, charBuf
);
1354 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1355 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1356 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1357 cvtNum(0, gFalse
, charBuf
);
1358 charBuf
->append((char)8);
1363 case 0x001d: // callgsubr
1365 k
= gsubrBias
+ (int)ops
[nOps
- 1].num
;
1368 getIndexVal(&gsubrIdx
, k
, &val
, &ok
);
1370 cvtGlyph(val
.pos
, val
.len
, charBuf
, subrIdx
, pDict
, gFalse
);
1373 //~ error(-1, "Too few args to Type 2 callgsubr");
1375 // don't clear the stack
1377 case 0x001e: // vhcurveto
1378 if (nOps
< 4 || !(nOps
% 4 == 0 || (nOps
-1) % 4 == 0)) {
1379 //~ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1381 for (k
= 0; k
< nOps
&& k
!= nOps
-5; k
+= 4) {
1383 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1384 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1385 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1386 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1387 charBuf
->append((char)30);
1389 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1390 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1391 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1392 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1393 charBuf
->append((char)31);
1398 cvtNum(0, gFalse
, charBuf
);
1399 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1400 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1401 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1402 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1403 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1405 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1406 cvtNum(0, gFalse
, charBuf
);
1407 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1408 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1409 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1410 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1412 charBuf
->append((char)8);
1417 case 0x001f: // hvcurveto
1418 if (nOps
< 4 || !(nOps
% 4 == 0 || (nOps
-1) % 4 == 0)) {
1419 //~ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1421 for (k
= 0; k
< nOps
&& k
!= nOps
-5; k
+= 4) {
1423 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1424 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1425 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1426 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1427 charBuf
->append((char)31);
1429 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1430 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1431 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1432 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1433 charBuf
->append((char)30);
1438 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1439 cvtNum(0, gFalse
, charBuf
);
1440 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1441 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1442 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1443 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1445 cvtNum(0, gFalse
, charBuf
);
1446 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1447 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1448 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1449 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1450 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1452 charBuf
->append((char)8);
1457 case 0x0c00: // dotsection (should be Type 1 only?)
1464 case 0x0c08: // store
1469 case 0x0c0d: // load
1472 case 0x0c12: // drop
1475 case 0x0c16: // ifelse
1476 case 0x0c17: // random
1478 case 0x0c1a: // sqrt
1480 case 0x0c1c: // exch
1481 case 0x0c1d: // index
1482 case 0x0c1e: // roll
1483 //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
1486 case 0x0c22: // hflex
1488 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1490 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1491 cvtNum(0, gFalse
, charBuf
);
1492 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1493 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1494 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1495 cvtNum(0, gFalse
, charBuf
);
1496 charBuf
->append((char)8);
1497 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1498 cvtNum(0, gFalse
, charBuf
);
1499 cvtNum(ops
[5].num
, ops
[5].isFP
, charBuf
);
1500 cvtNum(-ops
[2].num
, ops
[2].isFP
, charBuf
);
1501 cvtNum(ops
[6].num
, ops
[6].isFP
, charBuf
);
1502 cvtNum(0, gFalse
, charBuf
);
1503 charBuf
->append((char)8);
1507 case 0x0c23: // flex
1509 //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1511 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1512 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1513 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1514 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1515 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1516 cvtNum(ops
[5].num
, ops
[5].isFP
, charBuf
);
1517 charBuf
->append((char)8);
1518 cvtNum(ops
[6].num
, ops
[6].isFP
, charBuf
);
1519 cvtNum(ops
[7].num
, ops
[7].isFP
, charBuf
);
1520 cvtNum(ops
[8].num
, ops
[8].isFP
, charBuf
);
1521 cvtNum(ops
[9].num
, ops
[9].isFP
, charBuf
);
1522 cvtNum(ops
[10].num
, ops
[10].isFP
, charBuf
);
1523 cvtNum(ops
[11].num
, ops
[11].isFP
, charBuf
);
1524 charBuf
->append((char)8);
1528 case 0x0c24: // hflex1
1530 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1532 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1533 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1534 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1535 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1536 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1537 cvtNum(0, gFalse
, charBuf
);
1538 charBuf
->append((char)8);
1539 cvtNum(ops
[5].num
, ops
[5].isFP
, charBuf
);
1540 cvtNum(0, gFalse
, charBuf
);
1541 cvtNum(ops
[6].num
, ops
[6].isFP
, charBuf
);
1542 cvtNum(ops
[7].num
, ops
[7].isFP
, charBuf
);
1543 cvtNum(ops
[8].num
, ops
[8].isFP
, charBuf
);
1544 cvtNum(-(ops
[1].num
+ ops
[3].num
+ ops
[7].num
),
1545 ops
[1].isFP
| ops
[3].isFP
| ops
[7].isFP
, charBuf
);
1546 charBuf
->append((char)8);
1550 case 0x0c25: // flex1
1552 //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1554 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1555 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1556 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1557 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1558 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1559 cvtNum(ops
[5].num
, ops
[5].isFP
, charBuf
);
1560 charBuf
->append((char)8);
1561 cvtNum(ops
[6].num
, ops
[6].isFP
, charBuf
);
1562 cvtNum(ops
[7].num
, ops
[7].isFP
, charBuf
);
1563 cvtNum(ops
[8].num
, ops
[8].isFP
, charBuf
);
1564 cvtNum(ops
[9].num
, ops
[9].isFP
, charBuf
);
1565 dx
= ops
[0].num
+ ops
[2].num
+ ops
[4].num
+ ops
[6].num
+ ops
[8].num
;
1566 dy
= ops
[1].num
+ ops
[3].num
+ ops
[5].num
+ ops
[7].num
+ ops
[9].num
;
1567 if (fabs(dx
) > fabs(dy
)) {
1568 cvtNum(ops
[10].num
, ops
[10].isFP
, charBuf
);
1569 cvtNum(-dy
, ops
[1].isFP
| ops
[3].isFP
| ops
[5].isFP
|
1570 ops
[7].isFP
| ops
[9].isFP
, charBuf
);
1572 cvtNum(-dx
, ops
[0].isFP
| ops
[2].isFP
| ops
[4].isFP
|
1573 ops
[6].isFP
| ops
[8].isFP
, charBuf
);
1574 cvtNum(ops
[10].num
, ops
[10].isFP
, charBuf
);
1576 charBuf
->append((char)8);
1581 //~ error(-1, "Illegal Type 2 charstring op: %04x",
1589 // charstring encryption
1592 for (i
= start
; i
< charBuf
->getLength(); ++i
) {
1593 byte
= charBuf
->getChar(i
) ^ (r2
>> 8);
1594 charBuf
->setChar(i
, byte
);
1595 r2
= (byte
+ r2
) * 52845 + 22719;
1600 void FoFiType1C::cvtGlyphWidth(GBool useOp
, GooString
*charBuf
,
1601 Type1CPrivateDict
*pDict
) {
1607 w
= pDict
->nominalWidthX
+ ops
[0].num
;
1608 wFP
= pDict
->nominalWidthXFP
| ops
[0].isFP
;
1609 for (i
= 1; i
< nOps
; ++i
) {
1614 w
= pDict
->defaultWidthX
;
1615 wFP
= pDict
->defaultWidthXFP
;
1617 cvtNum(0, gFalse
, charBuf
);
1618 cvtNum(w
, wFP
, charBuf
);
1619 charBuf
->append((char)13);
1622 void FoFiType1C::cvtNum(double x
, GBool isFP
, GooString
*charBuf
) {
1628 if (x
>= -32768 && x
< 32768) {
1629 y
= (int)(x
* 256.0);
1631 buf
[1] = (Guchar
)(y
>> 24);
1632 buf
[2] = (Guchar
)(y
>> 16);
1633 buf
[3] = (Guchar
)(y
>> 8);
1644 //~ error(-1, "Type 2 fixed point constant out of range");
1648 if (y
>= -107 && y
<= 107) {
1649 buf
[0] = (Guchar
)(y
+ 139);
1651 } else if (y
> 107 && y
<= 1131) {
1653 buf
[0] = (Guchar
)((y
>> 8) + 247);
1654 buf
[1] = (Guchar
)(y
& 0xff);
1656 } else if (y
< -107 && y
>= -1131) {
1658 buf
[0] = (Guchar
)((y
>> 8) + 251);
1659 buf
[1] = (Guchar
)(y
& 0xff);
1663 buf
[1] = (Guchar
)(y
>> 24);
1664 buf
[2] = (Guchar
)(y
>> 16);
1665 buf
[3] = (Guchar
)(y
>> 8);
1670 charBuf
->append((char *)buf
, n
);
1673 void FoFiType1C::eexecWrite(Type1CEexecBuf
*eb
, char *s
) {
1677 for (p
= (Guchar
*)s
; *p
; ++p
) {
1678 x
= *p
^ (eb
->r1
>> 8);
1679 eb
->r1
= (x
+ eb
->r1
) * 52845 + 22719;
1681 (*eb
->outputFunc
)(eb
->outputStream
, &hexChars
[x
>> 4], 1);
1682 (*eb
->outputFunc
)(eb
->outputStream
, &hexChars
[x
& 0x0f], 1);
1684 if (eb
->line
== 64) {
1685 (*eb
->outputFunc
)(eb
->outputStream
, "\n", 1);
1689 (*eb
->outputFunc
)(eb
->outputStream
, (char *)&x
, 1);
1694 void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf
*eb
,
1700 for (i
= 0; i
< n
; ++i
) {
1701 x
= s
[i
] ^ (eb
->r1
>> 8);
1702 eb
->r1
= (x
+ eb
->r1
) * 52845 + 22719;
1704 (*eb
->outputFunc
)(eb
->outputStream
, &hexChars
[x
>> 4], 1);
1705 (*eb
->outputFunc
)(eb
->outputStream
, &hexChars
[x
& 0x0f], 1);
1707 if (eb
->line
== 64) {
1708 (*eb
->outputFunc
)(eb
->outputStream
, "\n", 1);
1712 (*eb
->outputFunc
)(eb
->outputStream
, (char *)&x
, 1);
1717 GBool
FoFiType1C::parse() {
1724 // some tools embed Type 1C fonts with an extra whitespace char at
1726 if (len
> 0 && file
[0] != '\x01') {
1732 getIndex(getU8(2, &parsedOk
), &nameIdx
, &parsedOk
);
1733 getIndex(nameIdx
.endPos
, &topDictIdx
, &parsedOk
);
1734 getIndex(topDictIdx
.endPos
, &stringIdx
, &parsedOk
);
1735 getIndex(stringIdx
.endPos
, &gsubrIdx
, &parsedOk
);
1739 gsubrBias
= (gsubrIdx
.len
< 1240) ? 107
1740 : (gsubrIdx
.len
< 33900) ? 1131 : 32768;
1742 // read the first font name
1743 getIndexVal(&nameIdx
, 0, &val
, &parsedOk
);
1747 name
= new GooString((char *)&file
[val
.pos
], val
.len
);
1749 // read the top dict for the first font
1752 // for CID fonts: read the FDArray dicts and private dicts
1753 if (topDict
.firstOp
== 0x0c1e) {
1754 if (topDict
.fdArrayOffset
== 0) {
1756 privateDicts
= (Type1CPrivateDict
*)gmalloc(sizeof(Type1CPrivateDict
));
1757 readPrivateDict(0, 0, &privateDicts
[0]);
1759 getIndex(topDict
.fdArrayOffset
, &fdIdx
, &parsedOk
);
1764 privateDicts
= (Type1CPrivateDict
*)
1765 gmallocn(nFDs
, sizeof(Type1CPrivateDict
));
1766 for (i
= 0; i
< nFDs
; ++i
) {
1767 getIndexVal(&fdIdx
, i
, &val
, &parsedOk
);
1771 readFD(val
.pos
, val
.len
, &privateDicts
[i
]);
1775 // for 8-bit fonts: read the private dict
1777 privateDicts
= (Type1CPrivateDict
*)gmalloc(sizeof(Type1CPrivateDict
));
1778 readPrivateDict(topDict
.privateOffset
, topDict
.privateSize
,
1782 // check for parse errors in the private dict(s)
1787 // get the charstrings index
1788 if (topDict
.charStringsOffset
<= 0) {
1792 getIndex(topDict
.charStringsOffset
, &charStringsIdx
, &parsedOk
);
1796 nGlyphs
= charStringsIdx
.len
;
1798 // for CID fonts: read the FDSelect table
1799 if (topDict
.firstOp
== 0x0c1e) {
1807 if (!readCharset()) {
1812 // for 8-bit fonts: build the encoding
1813 if (topDict
.firstOp
!= 0x0c14 && topDict
.firstOp
!= 0x0c1e) {
1823 void FoFiType1C::readTopDict() {
1824 Type1CIndexVal topDictPtr
;
1827 topDict
.firstOp
= -1;
1828 topDict
.versionSID
= 0;
1829 topDict
.noticeSID
= 0;
1830 topDict
.copyrightSID
= 0;
1831 topDict
.fullNameSID
= 0;
1832 topDict
.familyNameSID
= 0;
1833 topDict
.weightSID
= 0;
1834 topDict
.isFixedPitch
= 0;
1835 topDict
.italicAngle
= 0;
1836 topDict
.underlinePosition
= -100;
1837 topDict
.underlineThickness
= 50;
1838 topDict
.paintType
= 0;
1839 topDict
.charstringType
= 2;
1840 topDict
.fontMatrix
[0] = 0.001;
1841 topDict
.fontMatrix
[1] = 0;
1842 topDict
.fontMatrix
[2] = 0;
1843 topDict
.fontMatrix
[3] = 0.001;
1844 topDict
.fontMatrix
[4] = 0;
1845 topDict
.fontMatrix
[5] = 0;
1846 topDict
.hasFontMatrix
= gFalse
;
1847 topDict
.uniqueID
= 0;
1848 topDict
.fontBBox
[0] = 0;
1849 topDict
.fontBBox
[1] = 0;
1850 topDict
.fontBBox
[2] = 0;
1851 topDict
.fontBBox
[3] = 0;
1852 topDict
.strokeWidth
= 0;
1853 topDict
.charsetOffset
= 0;
1854 topDict
.encodingOffset
= 0;
1855 topDict
.charStringsOffset
= 0;
1856 topDict
.privateSize
= 0;
1857 topDict
.privateOffset
= 0;
1858 topDict
.registrySID
= 0;
1859 topDict
.orderingSID
= 0;
1860 topDict
.supplement
= 0;
1861 topDict
.fdArrayOffset
= 0;
1862 topDict
.fdSelectOffset
= 0;
1864 getIndexVal(&topDictIdx
, 0, &topDictPtr
, &parsedOk
);
1865 pos
= topDictPtr
.pos
;
1867 while (pos
< topDictPtr
.pos
+ topDictPtr
.len
) {
1868 pos
= getOp(pos
, gFalse
, &parsedOk
);
1872 if (!ops
[nOps
- 1].isNum
) {
1873 --nOps
; // drop the operator
1874 if (topDict
.firstOp
< 0) {
1875 topDict
.firstOp
= ops
[nOps
].op
;
1877 switch (ops
[nOps
].op
) {
1878 case 0x0000: topDict
.versionSID
= (int)ops
[0].num
; break;
1879 case 0x0001: topDict
.noticeSID
= (int)ops
[0].num
; break;
1880 case 0x0c00: topDict
.copyrightSID
= (int)ops
[0].num
; break;
1881 case 0x0002: topDict
.fullNameSID
= (int)ops
[0].num
; break;
1882 case 0x0003: topDict
.familyNameSID
= (int)ops
[0].num
; break;
1883 case 0x0004: topDict
.weightSID
= (int)ops
[0].num
; break;
1884 case 0x0c01: topDict
.isFixedPitch
= (int)ops
[0].num
; break;
1885 case 0x0c02: topDict
.italicAngle
= ops
[0].num
; break;
1886 case 0x0c03: topDict
.underlinePosition
= ops
[0].num
; break;
1887 case 0x0c04: topDict
.underlineThickness
= ops
[0].num
; break;
1888 case 0x0c05: topDict
.paintType
= (int)ops
[0].num
; break;
1889 case 0x0c06: topDict
.charstringType
= (int)ops
[0].num
; break;
1890 case 0x0c07: topDict
.fontMatrix
[0] = ops
[0].num
;
1891 topDict
.fontMatrix
[1] = ops
[1].num
;
1892 topDict
.fontMatrix
[2] = ops
[2].num
;
1893 topDict
.fontMatrix
[3] = ops
[3].num
;
1894 topDict
.fontMatrix
[4] = ops
[4].num
;
1895 topDict
.fontMatrix
[5] = ops
[5].num
;
1896 topDict
.hasFontMatrix
= gTrue
; break;
1897 case 0x000d: topDict
.uniqueID
= (int)ops
[0].num
; break;
1898 case 0x0005: topDict
.fontBBox
[0] = ops
[0].num
;
1899 topDict
.fontBBox
[1] = ops
[1].num
;
1900 topDict
.fontBBox
[2] = ops
[2].num
;
1901 topDict
.fontBBox
[3] = ops
[3].num
; break;
1902 case 0x0c08: topDict
.strokeWidth
= ops
[0].num
; break;
1903 case 0x000f: topDict
.charsetOffset
= (int)ops
[0].num
; break;
1904 case 0x0010: topDict
.encodingOffset
= (int)ops
[0].num
; break;
1905 case 0x0011: topDict
.charStringsOffset
= (int)ops
[0].num
; break;
1906 case 0x0012: topDict
.privateSize
= (int)ops
[0].num
;
1907 topDict
.privateOffset
= (int)ops
[1].num
; break;
1908 case 0x0c1e: topDict
.registrySID
= (int)ops
[0].num
;
1909 topDict
.orderingSID
= (int)ops
[1].num
;
1910 topDict
.supplement
= (int)ops
[2].num
; break;
1911 case 0x0c24: topDict
.fdArrayOffset
= (int)ops
[0].num
; break;
1912 case 0x0c25: topDict
.fdSelectOffset
= (int)ops
[0].num
; break;
1919 // Read a CID font dict (FD) - this pulls out the private dict
1920 // pointer, and reads the private dict. It also pulls the FontMatrix
1921 // (if any) out of the FD.
1922 void FoFiType1C::readFD(int offset
, int length
, Type1CPrivateDict
*pDict
) {
1923 int pos
, pSize
, pOffset
;
1924 double fontMatrix
[6];
1925 GBool hasFontMatrix
;
1927 hasFontMatrix
= gFalse
;
1928 pSize
= pOffset
= 0;
1931 while (pos
< offset
+ length
) {
1932 pos
= getOp(pos
, gFalse
, &parsedOk
);
1936 if (!ops
[nOps
- 1].isNum
) {
1937 if (ops
[nOps
- 1].op
== 0x0012) {
1942 pSize
= (int)ops
[0].num
;
1943 pOffset
= (int)ops
[1].num
;
1945 } else if (ops
[nOps
- 1].op
== 0x0c07) {
1946 fontMatrix
[0] = ops
[0].num
;
1947 fontMatrix
[1] = ops
[1].num
;
1948 fontMatrix
[2] = ops
[2].num
;
1949 fontMatrix
[3] = ops
[3].num
;
1950 fontMatrix
[4] = ops
[4].num
;
1951 fontMatrix
[5] = ops
[5].num
;
1952 hasFontMatrix
= gTrue
;
1957 readPrivateDict(pOffset
, pSize
, pDict
);
1958 if (hasFontMatrix
) {
1959 pDict
->fontMatrix
[0] = fontMatrix
[0];
1960 pDict
->fontMatrix
[1] = fontMatrix
[1];
1961 pDict
->fontMatrix
[2] = fontMatrix
[2];
1962 pDict
->fontMatrix
[3] = fontMatrix
[3];
1963 pDict
->fontMatrix
[4] = fontMatrix
[4];
1964 pDict
->fontMatrix
[5] = fontMatrix
[5];
1965 pDict
->hasFontMatrix
= gTrue
;
1969 void FoFiType1C::readPrivateDict(int offset
, int length
,
1970 Type1CPrivateDict
*pDict
) {
1973 pDict
->hasFontMatrix
= gFalse
;
1974 pDict
->nBlueValues
= 0;
1975 pDict
->nOtherBlues
= 0;
1976 pDict
->nFamilyBlues
= 0;
1977 pDict
->nFamilyOtherBlues
= 0;
1978 pDict
->blueScale
= 0.039625;
1979 pDict
->blueShift
= 7;
1980 pDict
->blueFuzz
= 1;
1981 pDict
->hasStdHW
= gFalse
;
1982 pDict
->hasStdVW
= gFalse
;
1983 pDict
->nStemSnapH
= 0;
1984 pDict
->nStemSnapV
= 0;
1985 pDict
->hasForceBold
= gFalse
;
1986 pDict
->forceBoldThreshold
= 0;
1987 pDict
->languageGroup
= 0;
1988 pDict
->expansionFactor
= 0.06;
1989 pDict
->initialRandomSeed
= 0;
1990 pDict
->subrsOffset
= 0;
1991 pDict
->defaultWidthX
= 0;
1992 pDict
->defaultWidthXFP
= gFalse
;
1993 pDict
->nominalWidthX
= 0;
1994 pDict
->nominalWidthXFP
= gFalse
;
1997 if (offset
== 0 || length
== 0) {
2003 while (pos
< offset
+ length
) {
2004 pos
= getOp(pos
, gFalse
, &parsedOk
);
2008 if (!ops
[nOps
- 1].isNum
) {
2009 --nOps
; // drop the operator
2010 switch (ops
[nOps
].op
) {
2012 pDict
->nBlueValues
= getDeltaIntArray(pDict
->blueValues
,
2013 type1CMaxBlueValues
);
2016 pDict
->nOtherBlues
= getDeltaIntArray(pDict
->otherBlues
,
2017 type1CMaxOtherBlues
);
2020 pDict
->nFamilyBlues
= getDeltaIntArray(pDict
->familyBlues
,
2021 type1CMaxBlueValues
);
2024 pDict
->nFamilyOtherBlues
= getDeltaIntArray(pDict
->familyOtherBlues
,
2025 type1CMaxOtherBlues
);
2028 pDict
->blueScale
= ops
[0].num
;
2031 pDict
->blueShift
= (int)ops
[0].num
;
2034 pDict
->blueFuzz
= (int)ops
[0].num
;
2037 pDict
->stdHW
= ops
[0].num
;
2038 pDict
->hasStdHW
= gTrue
;
2041 pDict
->stdVW
= ops
[0].num
;
2042 pDict
->hasStdVW
= gTrue
;
2045 pDict
->nStemSnapH
= getDeltaFPArray(pDict
->stemSnapH
,
2049 pDict
->nStemSnapV
= getDeltaFPArray(pDict
->stemSnapV
,
2053 pDict
->forceBold
= ops
[0].num
!= 0;
2054 pDict
->hasForceBold
= gTrue
;
2057 pDict
->forceBoldThreshold
= ops
[0].num
;
2060 pDict
->languageGroup
= (int)ops
[0].num
;
2063 pDict
->expansionFactor
= ops
[0].num
;
2066 pDict
->initialRandomSeed
= (int)ops
[0].num
;
2069 pDict
->subrsOffset
= offset
+ (int)ops
[0].num
;
2072 pDict
->defaultWidthX
= ops
[0].num
;
2073 pDict
->defaultWidthXFP
= ops
[0].isFP
;
2076 pDict
->nominalWidthX
= ops
[0].num
;
2077 pDict
->nominalWidthXFP
= ops
[0].isFP
;
2085 void FoFiType1C::readFDSelect() {
2086 int fdSelectFmt
, pos
, nRanges
, gid0
, gid1
, fd
, i
, j
;
2088 fdSelect
= (Guchar
*)gmalloc(nGlyphs
);
2089 if (topDict
.fdSelectOffset
== 0) {
2090 for (i
= 0; i
< nGlyphs
; ++i
) {
2094 pos
= topDict
.fdSelectOffset
;
2095 fdSelectFmt
= getU8(pos
++, &parsedOk
);
2099 if (fdSelectFmt
== 0) {
2100 if (!checkRegion(pos
, nGlyphs
)) {
2104 memcpy(fdSelect
, file
+ pos
, nGlyphs
);
2105 } else if (fdSelectFmt
== 3) {
2106 nRanges
= getU16BE(pos
, &parsedOk
);
2108 gid0
= getU16BE(pos
, &parsedOk
);
2110 for (i
= 1; i
<= nRanges
; ++i
) {
2111 fd
= getU8(pos
++, &parsedOk
);
2112 gid1
= getU16BE(pos
, &parsedOk
);
2117 if (gid0
> gid1
|| gid1
> nGlyphs
) {
2118 //~ error(-1, "Bad FDSelect table in CID font");
2122 for (j
= gid0
; j
< gid1
; ++j
) {
2128 //~ error(-1, "Unknown FDSelect table format in CID font");
2129 for (i
= 0; i
< nGlyphs
; ++i
) {
2136 void FoFiType1C::buildEncoding() {
2138 int nCodes
, nRanges
, encFormat
;
2139 int pos
, c
, sid
, nLeft
, nSups
, i
, j
;
2141 if (topDict
.encodingOffset
== 0) {
2142 encoding
= fofiType1StandardEncoding
;
2144 } else if (topDict
.encodingOffset
== 1) {
2145 encoding
= fofiType1ExpertEncoding
;
2148 encoding
= (char **)gmallocn(256, sizeof(char *));
2149 for (i
= 0; i
< 256; ++i
) {
2152 pos
= topDict
.encodingOffset
;
2153 encFormat
= getU8(pos
++, &parsedOk
);
2157 if ((encFormat
& 0x7f) == 0) {
2158 nCodes
= 1 + getU8(pos
++, &parsedOk
);
2162 if (nCodes
> nGlyphs
) {
2165 for (i
= 1; i
< nCodes
; ++i
) {
2166 c
= getU8(pos
++, &parsedOk
);
2173 encoding
[c
] = copyString(getString(charset
[i
], buf
, &parsedOk
));
2175 } else if ((encFormat
& 0x7f) == 1) {
2176 nRanges
= getU8(pos
++, &parsedOk
);
2181 for (i
= 0; i
< nRanges
; ++i
) {
2182 c
= getU8(pos
++, &parsedOk
);
2183 nLeft
= getU8(pos
++, &parsedOk
);
2187 for (j
= 0; j
<= nLeft
&& nCodes
< nGlyphs
; ++j
) {
2192 encoding
[c
] = copyString(getString(charset
[nCodes
], buf
,
2200 if (encFormat
& 0x80) {
2201 nSups
= getU8(pos
++, &parsedOk
);
2205 for (i
= 0; i
< nSups
; ++i
) {
2206 c
= getU8(pos
++, &parsedOk
);;
2210 sid
= getU16BE(pos
, &parsedOk
);
2218 encoding
[c
] = copyString(getString(sid
, buf
, &parsedOk
));
2224 GBool
FoFiType1C::readCharset() {
2225 int charsetFormat
, c
, pos
;
2228 if (topDict
.charsetOffset
== 0) {
2229 charset
= fofiType1CISOAdobeCharset
;
2230 } else if (topDict
.charsetOffset
== 1) {
2231 charset
= fofiType1CExpertCharset
;
2232 } else if (topDict
.charsetOffset
== 2) {
2233 charset
= fofiType1CExpertSubsetCharset
;
2235 charset
= (Gushort
*)gmallocn(nGlyphs
, sizeof(Gushort
));
2236 for (i
= 0; i
< nGlyphs
; ++i
) {
2239 pos
= topDict
.charsetOffset
;
2240 charsetFormat
= getU8(pos
++, &parsedOk
);
2241 if (charsetFormat
== 0) {
2242 for (i
= 1; i
< nGlyphs
; ++i
) {
2243 charset
[i
] = (Gushort
)getU16BE(pos
, &parsedOk
);
2249 } else if (charsetFormat
== 1) {
2251 while (i
< nGlyphs
) {
2252 c
= getU16BE(pos
, &parsedOk
);
2254 nLeft
= getU8(pos
++, &parsedOk
);
2258 for (j
= 0; j
<= nLeft
&& i
< nGlyphs
; ++j
) {
2259 charset
[i
++] = (Gushort
)c
++;
2262 } else if (charsetFormat
== 2) {
2264 while (i
< nGlyphs
) {
2265 c
= getU16BE(pos
, &parsedOk
);
2267 nLeft
= getU16BE(pos
, &parsedOk
);
2272 for (j
= 0; j
<= nLeft
&& i
< nGlyphs
; ++j
) {
2273 charset
[i
++] = (Gushort
)c
++;
2286 int FoFiType1C::getOp(int pos
, GBool charstring
, GBool
*ok
) {
2287 static char nybChars
[16] = "0123456789.ee -";
2290 int b0
, b1
, nyb0
, nyb1
, x
, i
;
2292 b0
= getU8(pos
++, ok
);
2297 x
= getU8(pos
++, ok
);
2298 x
= (x
<< 8) | getU8(pos
++, ok
);
2304 } else if (!charstring
&& b0
== 29) {
2305 x
= getU8(pos
++, ok
);
2306 x
= (x
<< 8) | getU8(pos
++, ok
);
2307 x
= (x
<< 8) | getU8(pos
++, ok
);
2308 x
= (x
<< 8) | getU8(pos
++, ok
);
2309 if (x
& 0x80000000) {
2314 } else if (!charstring
&& b0
== 30) {
2317 b1
= getU8(pos
++, ok
);
2323 buf
[i
++] = nybChars
[nyb0
];
2336 buf
[i
++] = nybChars
[nyb1
];
2348 } else if (b0
>= 32 && b0
<= 246) {
2351 } else if (b0
>= 247 && b0
<= 250) {
2352 op
.num
= ((b0
- 247) << 8) + getU8(pos
++, ok
) + 108;
2354 } else if (b0
>= 251 && b0
<= 254) {
2355 op
.num
= -((b0
- 251) << 8) - getU8(pos
++, ok
) - 108;
2357 } else if (charstring
&& b0
== 255) {
2358 x
= getU8(pos
++, ok
);
2359 x
= (x
<< 8) | getU8(pos
++, ok
);
2360 x
= (x
<< 8) | getU8(pos
++, ok
);
2361 x
= (x
<< 8) | getU8(pos
++, ok
);
2362 if (x
& 0x80000000) {
2365 op
.num
= (double)x
/ 65536.0;
2368 } else if (b0
== 12) {
2370 op
.op
= 0x0c00 + getU8(pos
++, ok
);
2384 // Convert the delta-encoded ops array to an array of ints.
2385 int FoFiType1C::getDeltaIntArray(int *arr
, int maxLen
) {
2389 if ((n
= nOps
) > maxLen
) {
2393 for (i
= 0; i
< n
; ++i
) {
2394 x
+= (int)ops
[i
].num
;
2400 // Convert the delta-encoded ops array to an array of doubles.
2401 int FoFiType1C::getDeltaFPArray(double *arr
, int maxLen
) {
2405 if ((n
= nOps
) > maxLen
) {
2409 for (i
= 0; i
< n
; ++i
) {
2416 void FoFiType1C::getIndex(int pos
, Type1CIndex
*idx
, GBool
*ok
) {
2418 idx
->len
= getU16BE(pos
, ok
);
2419 if (idx
->len
== 0) {
2420 // empty indexes are legal and contain just the length field
2422 idx
->startPos
= idx
->endPos
= pos
+ 2;
2424 idx
->offSize
= getU8(pos
+ 2, ok
);
2425 if (idx
->offSize
< 1 || idx
->offSize
> 4) {
2428 idx
->startPos
= pos
+ 3 + (idx
->len
+ 1) * idx
->offSize
- 1;
2429 if (idx
->startPos
< 0 || idx
->startPos
>= len
) {
2432 idx
->endPos
= idx
->startPos
+ getUVarBE(pos
+ 3 + idx
->len
* idx
->offSize
,
2434 if (idx
->endPos
< idx
->startPos
|| idx
->endPos
> len
) {
2440 void FoFiType1C::getIndexVal(Type1CIndex
*idx
, int i
,
2441 Type1CIndexVal
*val
, GBool
*ok
) {
2444 if (i
< 0 || i
>= idx
->len
) {
2448 pos0
= idx
->startPos
+ getUVarBE(idx
->pos
+ 3 + i
* idx
->offSize
,
2450 pos1
= idx
->startPos
+ getUVarBE(idx
->pos
+ 3 + (i
+ 1) * idx
->offSize
,
2452 if (pos0
< idx
->startPos
|| pos0
> idx
->endPos
||
2453 pos1
<= idx
->startPos
|| pos1
> idx
->endPos
||
2458 val
->len
= pos1
- pos0
;
2461 char *FoFiType1C::getString(int sid
, char *buf
, GBool
*ok
) {
2466 strcpy(buf
, fofiType1CStdStrings
[sid
]);
2469 getIndexVal(&stringIdx
, sid
, &val
, ok
);
2471 if ((n
= val
.len
) > 255) {
2474 strncpy(buf
, (char *)&file
[val
.pos
], n
);