1 //========================================================================
5 // Copyright 1999-2003 Glyph & Cog, LLC
7 //========================================================================
9 //========================================================================
11 // Modified under the Poppler project - http://poppler.freedesktop.org
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
16 // Copyright (C) 2009, 2010 Albert Astals Cid <aacid@kde.org>
17 // Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
19 // To see a description of the changes please see the Changelog file that
20 // came with your tarball or type make ChangeLog if you are building from git
22 //========================================================================
26 #ifdef USE_GCC_PRAGMAS
27 #pragma implementation
34 #include "goo/gstrtod.h"
35 #include "goo/GooString.h"
36 #include "FoFiEncodings.h"
37 #include "FoFiType1C.h"
39 //------------------------------------------------------------------------
41 static char hexChars
[17] = "0123456789ABCDEF";
43 //------------------------------------------------------------------------
45 //------------------------------------------------------------------------
47 FoFiType1C
*FoFiType1C::make(char *fileA
, int lenA
) {
50 ff
= new FoFiType1C(fileA
, lenA
, gFalse
);
58 FoFiType1C
*FoFiType1C::load(char *fileName
) {
63 if (!(fileA
= FoFiBase::readFile(fileName
, &lenA
))) {
66 ff
= new FoFiType1C(fileA
, lenA
, gTrue
);
74 FoFiType1C::FoFiType1C(char *fileA
, int lenA
, GBool freeFileDataA
):
75 FoFiBase(fileA
, lenA
, freeFileDataA
)
85 FoFiType1C::~FoFiType1C() {
92 encoding
!= fofiType1StandardEncoding
&&
93 encoding
!= fofiType1ExpertEncoding
) {
94 for (i
= 0; i
< 256; ++i
) {
106 charset
!= fofiType1CISOAdobeCharset
&&
107 charset
!= fofiType1CExpertCharset
&&
108 charset
!= fofiType1CExpertSubsetCharset
) {
113 char *FoFiType1C::getName() {
114 return name
? name
->getCString() : (char *)NULL
;
117 char **FoFiType1C::getEncoding() {
121 GooString
*FoFiType1C::getGlyphName(int gid
) {
126 if (gid
< 0 || gid
>= charsetLength
)
128 getString(charset
[gid
], buf
, &ok
);
132 return new GooString(buf
);
135 int *FoFiType1C::getCIDToGIDMap(int *nCIDs
) {
139 // a CID font's top dict has ROS as the first operator
140 if (topDict
.firstOp
!= 0x0c1e) {
145 // in a CID font, the charset data is the GID-to-CID mapping, so all
146 // we have to do is reverse it
148 for (i
= 0; i
< nGlyphs
&& i
< charsetLength
; ++i
) {
149 if (charset
[i
] > n
) {
154 map
= (int *)gmallocn(n
, sizeof(int));
155 memset(map
, 0, n
* sizeof(int));
156 for (i
= 0; i
< nGlyphs
; ++i
) {
163 void FoFiType1C::getFontMatrix(double *mat
) {
166 if (topDict
.firstOp
== 0x0c1e && privateDicts
[0].hasFontMatrix
) {
167 if (topDict
.hasFontMatrix
) {
168 mat
[0] = topDict
.fontMatrix
[0] * privateDicts
[0].fontMatrix
[0] +
169 topDict
.fontMatrix
[1] * privateDicts
[0].fontMatrix
[2];
170 mat
[1] = topDict
.fontMatrix
[0] * privateDicts
[0].fontMatrix
[1] +
171 topDict
.fontMatrix
[1] * privateDicts
[0].fontMatrix
[3];
172 mat
[2] = topDict
.fontMatrix
[2] * privateDicts
[0].fontMatrix
[0] +
173 topDict
.fontMatrix
[3] * privateDicts
[0].fontMatrix
[2];
174 mat
[3] = topDict
.fontMatrix
[2] * privateDicts
[0].fontMatrix
[1] +
175 topDict
.fontMatrix
[3] * privateDicts
[0].fontMatrix
[3];
176 mat
[4] = topDict
.fontMatrix
[4] * privateDicts
[0].fontMatrix
[0] +
177 topDict
.fontMatrix
[5] * privateDicts
[0].fontMatrix
[2];
178 mat
[5] = topDict
.fontMatrix
[4] * privateDicts
[0].fontMatrix
[1] +
179 topDict
.fontMatrix
[5] * privateDicts
[0].fontMatrix
[3];
181 for (i
= 0; i
< 6; ++i
) {
182 mat
[i
] = privateDicts
[0].fontMatrix
[i
];
186 for (i
= 0; i
< 6; ++i
) {
187 mat
[i
] = topDict
.fontMatrix
[i
];
192 void FoFiType1C::convertToType1(char *psName
, const char **newEncoding
, GBool ascii
,
193 FoFiOutputFunc outputFunc
,
194 void *outputStream
) {
206 psNameLen
= strlen(psName
);
208 psName
= name
->getCString();
209 psNameLen
= name
->getLength();
212 // write header and font dictionary, up to encoding
214 (*outputFunc
)(outputStream
, "%!FontType1-1.0: ", 17);
215 (*outputFunc
)(outputStream
, psName
, psNameLen
);
216 if (topDict
.versionSID
!= 0) {
217 getString(topDict
.versionSID
, buf2
, &ok
);
218 (*outputFunc
)(outputStream
, buf2
, strlen(buf2
));
220 (*outputFunc
)(outputStream
, "\n", 1);
221 // the dictionary needs room for 12 entries: the following 9, plus
222 // Private and CharStrings (in the eexec section) and FID (which is
223 // added by definefont)
224 (*outputFunc
)(outputStream
, "12 dict begin\n", 14);
225 (*outputFunc
)(outputStream
, "/FontInfo 10 dict dup begin\n", 28);
226 if (topDict
.versionSID
!= 0) {
227 (*outputFunc
)(outputStream
, "/version ", 9);
228 writePSString(buf2
, outputFunc
, outputStream
);
229 (*outputFunc
)(outputStream
, " readonly def\n", 14);
231 if (topDict
.noticeSID
!= 0) {
232 getString(topDict
.noticeSID
, buf2
, &ok
);
233 (*outputFunc
)(outputStream
, "/Notice ", 8);
234 writePSString(buf2
, outputFunc
, outputStream
);
235 (*outputFunc
)(outputStream
, " readonly def\n", 14);
237 if (topDict
.copyrightSID
!= 0) {
238 getString(topDict
.copyrightSID
, buf2
, &ok
);
239 (*outputFunc
)(outputStream
, "/Copyright ", 11);
240 writePSString(buf2
, outputFunc
, outputStream
);
241 (*outputFunc
)(outputStream
, " readonly def\n", 14);
243 if (topDict
.fullNameSID
!= 0) {
244 getString(topDict
.fullNameSID
, buf2
, &ok
);
245 (*outputFunc
)(outputStream
, "/FullName ", 10);
246 writePSString(buf2
, outputFunc
, outputStream
);
247 (*outputFunc
)(outputStream
, " readonly def\n", 14);
249 if (topDict
.familyNameSID
!= 0) {
250 getString(topDict
.familyNameSID
, buf2
, &ok
);
251 (*outputFunc
)(outputStream
, "/FamilyName ", 12);
252 writePSString(buf2
, outputFunc
, outputStream
);
253 (*outputFunc
)(outputStream
, " readonly def\n", 14);
255 if (topDict
.weightSID
!= 0) {
256 getString(topDict
.weightSID
, buf2
, &ok
);
257 (*outputFunc
)(outputStream
, "/Weight ", 8);
258 writePSString(buf2
, outputFunc
, outputStream
);
259 (*outputFunc
)(outputStream
, " readonly def\n", 14);
261 if (topDict
.isFixedPitch
) {
262 (*outputFunc
)(outputStream
, "/isFixedPitch true def\n", 23);
264 (*outputFunc
)(outputStream
, "/isFixedPitch false def\n", 24);
266 buf
= GooString::format("/ItalicAngle {0:.4g} def\n", topDict
.italicAngle
);
267 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
269 buf
= GooString::format("/UnderlinePosition {0:.4g} def\n",
270 topDict
.underlinePosition
);
271 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
273 buf
= GooString::format("/UnderlineThickness {0:.4g} def\n",
274 topDict
.underlineThickness
);
275 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
277 (*outputFunc
)(outputStream
, "end readonly def\n", 17);
278 (*outputFunc
)(outputStream
, "/FontName /", 11);
279 (*outputFunc
)(outputStream
, psName
, psNameLen
);
280 (*outputFunc
)(outputStream
, " def\n", 5);
281 buf
= GooString::format("/PaintType {0:d} def\n", topDict
.paintType
);
282 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
284 (*outputFunc
)(outputStream
, "/FontType 1 def\n", 16);
285 buf
= GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] readonly def\n",
286 topDict
.fontMatrix
[0], topDict
.fontMatrix
[1],
287 topDict
.fontMatrix
[2], topDict
.fontMatrix
[3],
288 topDict
.fontMatrix
[4], topDict
.fontMatrix
[5]);
289 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
291 buf
= GooString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] readonly def\n",
292 topDict
.fontBBox
[0], topDict
.fontBBox
[1],
293 topDict
.fontBBox
[2], topDict
.fontBBox
[3]);
294 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
296 buf
= GooString::format("/StrokeWidth {0:.4g} def\n", topDict
.strokeWidth
);
297 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
299 if (topDict
.uniqueID
!= 0) {
300 buf
= GooString::format("/UniqueID {0:d} def\n", topDict
.uniqueID
);
301 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
305 // write the encoding
306 (*outputFunc
)(outputStream
, "/Encoding ", 10);
307 if (!newEncoding
&& encoding
== fofiType1StandardEncoding
) {
308 (*outputFunc
)(outputStream
, "StandardEncoding def\n", 21);
310 (*outputFunc
)(outputStream
, "256 array\n", 10);
311 (*outputFunc
)(outputStream
,
312 "0 1 255 {1 index exch /.notdef put} for\n", 40);
313 enc
= newEncoding
? newEncoding
: (const char **)encoding
;
314 for (i
= 0; i
< 256; ++i
) {
316 buf
= GooString::format("dup {0:d} /{1:s} put\n", i
, enc
[i
]);
317 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
321 (*outputFunc
)(outputStream
, "readonly def\n", 13);
323 (*outputFunc
)(outputStream
, "currentdict end\n", 16);
325 // start the binary section
326 (*outputFunc
)(outputStream
, "currentfile eexec\n", 18);
327 eb
.outputFunc
= outputFunc
;
328 eb
.outputStream
= outputStream
;
333 // write the private dictionary
334 eexecWrite(&eb
, "\x83\xca\x73\xd5");
335 eexecWrite(&eb
, "dup /Private 32 dict dup begin\n");
336 eexecWrite(&eb
, "/RD {string currentfile exch readstring pop}"
337 " executeonly def\n");
338 eexecWrite(&eb
, "/ND {noaccess def} executeonly def\n");
339 eexecWrite(&eb
, "/NP {noaccess put} executeonly def\n");
340 eexecWrite(&eb
, "/MinFeature {16 16} def\n");
341 eexecWrite(&eb
, "/password 5839 def\n");
342 if (privateDicts
[0].nBlueValues
) {
343 eexecWrite(&eb
, "/BlueValues [");
344 for (i
= 0; i
< privateDicts
[0].nBlueValues
; ++i
) {
345 buf
= GooString::format("{0:s}{1:d}",
346 i
> 0 ? " " : "", privateDicts
[0].blueValues
[i
]);
347 eexecWrite(&eb
, buf
->getCString());
350 eexecWrite(&eb
, "] def\n");
352 if (privateDicts
[0].nOtherBlues
) {
353 eexecWrite(&eb
, "/OtherBlues [");
354 for (i
= 0; i
< privateDicts
[0].nOtherBlues
; ++i
) {
355 buf
= GooString::format("{0:s}{1:d}",
356 i
> 0 ? " " : "", privateDicts
[0].otherBlues
[i
]);
357 eexecWrite(&eb
, buf
->getCString());
360 eexecWrite(&eb
, "] def\n");
362 if (privateDicts
[0].nFamilyBlues
) {
363 eexecWrite(&eb
, "/FamilyBlues [");
364 for (i
= 0; i
< privateDicts
[0].nFamilyBlues
; ++i
) {
365 buf
= GooString::format("{0:s}{1:d}",
366 i
> 0 ? " " : "", privateDicts
[0].familyBlues
[i
]);
367 eexecWrite(&eb
, buf
->getCString());
370 eexecWrite(&eb
, "] def\n");
372 if (privateDicts
[0].nFamilyOtherBlues
) {
373 eexecWrite(&eb
, "/FamilyOtherBlues [");
374 for (i
= 0; i
< privateDicts
[0].nFamilyOtherBlues
; ++i
) {
375 buf
= GooString::format("{0:s}{1:d}", i
> 0 ? " " : "",
376 privateDicts
[0].familyOtherBlues
[i
]);
377 eexecWrite(&eb
, buf
->getCString());
380 eexecWrite(&eb
, "] def\n");
382 if (privateDicts
[0].blueScale
!= 0.039625) {
383 buf
= GooString::format("/BlueScale {0:.4g} def\n",
384 privateDicts
[0].blueScale
);
385 eexecWrite(&eb
, buf
->getCString());
388 if (privateDicts
[0].blueShift
!= 7) {
389 buf
= GooString::format("/BlueShift {0:d} def\n", privateDicts
[0].blueShift
);
390 eexecWrite(&eb
, buf
->getCString());
393 if (privateDicts
[0].blueFuzz
!= 1) {
394 buf
= GooString::format("/BlueFuzz {0:d} def\n", privateDicts
[0].blueFuzz
);
395 eexecWrite(&eb
, buf
->getCString());
398 if (privateDicts
[0].hasStdHW
) {
399 buf
= GooString::format("/StdHW [{0:.4g}] def\n", privateDicts
[0].stdHW
);
400 eexecWrite(&eb
, buf
->getCString());
403 if (privateDicts
[0].hasStdVW
) {
404 buf
= GooString::format("/StdVW [{0:.4g}] def\n", privateDicts
[0].stdVW
);
405 eexecWrite(&eb
, buf
->getCString());
408 if (privateDicts
[0].nStemSnapH
) {
409 eexecWrite(&eb
, "/StemSnapH [");
410 for (i
= 0; i
< privateDicts
[0].nStemSnapH
; ++i
) {
411 buf
= GooString::format("{0:s}{1:.4g}",
412 i
> 0 ? " " : "", privateDicts
[0].stemSnapH
[i
]);
413 eexecWrite(&eb
, buf
->getCString());
416 eexecWrite(&eb
, "] def\n");
418 if (privateDicts
[0].nStemSnapV
) {
419 eexecWrite(&eb
, "/StemSnapV [");
420 for (i
= 0; i
< privateDicts
[0].nStemSnapV
; ++i
) {
421 buf
= GooString::format("{0:s}{1:.4g}",
422 i
> 0 ? " " : "", privateDicts
[0].stemSnapV
[i
]);
423 eexecWrite(&eb
, buf
->getCString());
426 eexecWrite(&eb
, "] def\n");
428 if (privateDicts
[0].hasForceBold
) {
429 buf
= GooString::format("/ForceBold {0:s} def\n",
430 privateDicts
[0].forceBold
? "true" : "false");
431 eexecWrite(&eb
, buf
->getCString());
434 if (privateDicts
[0].forceBoldThreshold
!= 0) {
435 buf
= GooString::format("/ForceBoldThreshold {0:.4g} def\n",
436 privateDicts
[0].forceBoldThreshold
);
437 eexecWrite(&eb
, buf
->getCString());
440 if (privateDicts
[0].languageGroup
!= 0) {
441 buf
= GooString::format("/LanguageGroup {0:d} def\n",
442 privateDicts
[0].languageGroup
);
443 eexecWrite(&eb
, buf
->getCString());
446 if (privateDicts
[0].expansionFactor
!= 0.06) {
447 buf
= GooString::format("/ExpansionFactor {0:.4g} def\n",
448 privateDicts
[0].expansionFactor
);
449 eexecWrite(&eb
, buf
->getCString());
453 // set up subroutines
455 getIndex(privateDicts
[0].subrsOffset
, &subrIdx
, &ok
);
460 // write the CharStrings
461 buf
= GooString::format("2 index /CharStrings {0:d} dict dup begin\n",
463 eexecWrite(&eb
, buf
->getCString());
465 for (i
= 0; i
< nGlyphs
; ++i
) {
467 getIndexVal(&charStringsIdx
, i
, &val
, &ok
);
468 if (ok
&& i
< charsetLength
) {
469 getString(charset
[i
], buf2
, &ok
);
471 eexecCvtGlyph(&eb
, buf2
, val
.pos
, val
.len
, &subrIdx
, &privateDicts
[0]);
475 eexecWrite(&eb
, "end\n");
476 eexecWrite(&eb
, "end\n");
477 eexecWrite(&eb
, "readonly put\n");
478 eexecWrite(&eb
, "noaccess put\n");
479 eexecWrite(&eb
, "dup /FontName get exch definefont pop\n");
480 eexecWrite(&eb
, "mark currentfile closefile\n");
483 if (ascii
&& eb
.line
> 0) {
484 (*outputFunc
)(outputStream
, "\n", 1);
486 for (i
= 0; i
< 8; ++i
) {
487 (*outputFunc
)(outputStream
, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
489 (*outputFunc
)(outputStream
, "cleartomark\n", 12);
492 void FoFiType1C::convertToCIDType0(char *psName
, int *codeMap
, int nCodes
,
493 FoFiOutputFunc outputFunc
,
494 void *outputStream
) {
496 GooString
*charStrings
;
497 int *charStringOffsets
;
504 int gid
, offset
, n
, i
, j
, k
;
506 // compute the CID count and build the CID-to-GID mapping
509 cidMap
= (int *)gmallocn(nCIDs
, sizeof(int));
510 for (i
= 0; i
< nCodes
; ++i
) {
511 if (codeMap
[i
] >= 0 && codeMap
[i
] < nGlyphs
) {
512 cidMap
[i
] = codeMap
[i
];
517 } else if (topDict
.firstOp
== 0x0c1e) {
519 for (i
= 0; i
< nGlyphs
&& i
< charsetLength
; ++i
) {
520 if (charset
[i
] >= nCIDs
) {
521 nCIDs
= charset
[i
] + 1;
524 cidMap
= (int *)gmallocn(nCIDs
, sizeof(int));
525 for (i
= 0; i
< nCIDs
; ++i
) {
528 for (i
= 0; i
< nGlyphs
&& i
< charsetLength
; ++i
) {
529 cidMap
[charset
[i
]] = i
;
533 cidMap
= (int *)gmallocn(nCIDs
, sizeof(int));
534 for (i
= 0; i
< nCIDs
; ++i
) {
539 // build the charstrings
540 charStrings
= new GooString();
541 charStringOffsets
= (int *)gmallocn(nCIDs
+ 1, sizeof(int));
542 for (i
= 0; i
< nCIDs
; ++i
) {
543 charStringOffsets
[i
] = charStrings
->getLength();
544 if ((gid
= cidMap
[i
]) >= 0) {
546 getIndexVal(&charStringsIdx
, gid
, &val
, &ok
);
548 getIndex(privateDicts
[fdSelect
? fdSelect
[gid
] : 0].subrsOffset
,
553 cvtGlyph(val
.pos
, val
.len
, charStrings
,
554 &subrIdx
, &privateDicts
[fdSelect
? fdSelect
[gid
] : 0], gTrue
);
558 charStringOffsets
[nCIDs
] = charStrings
->getLength();
560 // compute gdBytes = number of bytes needed for charstring offsets
561 // (offset size needs to account for the charstring offset table,
562 // with a worst case of five bytes per entry, plus the charstrings
564 i
= (nCIDs
+ 1) * 5 + charStrings
->getLength();
567 } else if (i
< 0x10000) {
569 } else if (i
< 0x1000000) {
575 // begin the font dictionary
576 (*outputFunc
)(outputStream
, "/CIDInit /ProcSet findresource begin\n", 37);
577 (*outputFunc
)(outputStream
, "20 dict begin\n", 14);
578 (*outputFunc
)(outputStream
, "/CIDFontName /", 14);
579 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
580 (*outputFunc
)(outputStream
, " def\n", 5);
581 (*outputFunc
)(outputStream
, "/CIDFontType 0 def\n", 19);
582 (*outputFunc
)(outputStream
, "/CIDSystemInfo 3 dict dup begin\n", 32);
583 if (topDict
.registrySID
> 0 && topDict
.orderingSID
> 0) {
585 getString(topDict
.registrySID
, buf2
, &ok
);
587 (*outputFunc
)(outputStream
, " /Registry (", 13);
588 (*outputFunc
)(outputStream
, buf2
, strlen(buf2
));
589 (*outputFunc
)(outputStream
, ") def\n", 6);
592 getString(topDict
.orderingSID
, buf2
, &ok
);
594 (*outputFunc
)(outputStream
, " /Ordering (", 13);
595 (*outputFunc
)(outputStream
, buf2
, strlen(buf2
));
596 (*outputFunc
)(outputStream
, ") def\n", 6);
599 (*outputFunc
)(outputStream
, " /Registry (Adobe) def\n", 24);
600 (*outputFunc
)(outputStream
, " /Ordering (Identity) def\n", 27);
602 buf
= GooString::format(" /Supplement {0:d} def\n", topDict
.supplement
);
603 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
605 (*outputFunc
)(outputStream
, "end def\n", 8);
606 if (topDict
.hasFontMatrix
) {
607 buf
= GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
608 topDict
.fontMatrix
[0], topDict
.fontMatrix
[1],
609 topDict
.fontMatrix
[2], topDict
.fontMatrix
[3],
610 topDict
.fontMatrix
[4], topDict
.fontMatrix
[5]);
611 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
613 } else if (privateDicts
[0].hasFontMatrix
) {
614 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
616 (*outputFunc
)(outputStream
,
617 "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
619 buf
= GooString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
620 topDict
.fontBBox
[0], topDict
.fontBBox
[1],
621 topDict
.fontBBox
[2], topDict
.fontBBox
[3]);
622 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
624 (*outputFunc
)(outputStream
, "/FontInfo 1 dict dup begin\n", 27);
625 (*outputFunc
)(outputStream
, " /FSType 8 def\n", 16);
626 (*outputFunc
)(outputStream
, "end def\n", 8);
628 // CIDFont-specific entries
629 buf
= GooString::format("/CIDCount {0:d} def\n", nCIDs
);
630 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
632 (*outputFunc
)(outputStream
, "/FDBytes 1 def\n", 15);
633 buf
= GooString::format("/GDBytes {0:d} def\n", gdBytes
);
634 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
636 (*outputFunc
)(outputStream
, "/CIDMapOffset 0 def\n", 20);
637 if (topDict
.paintType
!= 0) {
638 buf
= GooString::format("/PaintType {0:d} def\n", topDict
.paintType
);
639 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
641 buf
= GooString::format("/StrokeWidth {0:.4g} def\n", topDict
.strokeWidth
);
642 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
647 buf
= GooString::format("/FDArray {0:d} array\n", nFDs
);
648 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
650 for (i
= 0; i
< nFDs
; ++i
) {
651 buf
= GooString::format("dup {0:d} 10 dict begin\n", i
);
652 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
654 (*outputFunc
)(outputStream
, "/FontType 1 def\n", 16);
655 if (privateDicts
[i
].hasFontMatrix
) {
656 buf
= GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
657 privateDicts
[i
].fontMatrix
[0],
658 privateDicts
[i
].fontMatrix
[1],
659 privateDicts
[i
].fontMatrix
[2],
660 privateDicts
[i
].fontMatrix
[3],
661 privateDicts
[i
].fontMatrix
[4],
662 privateDicts
[i
].fontMatrix
[5]);
663 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
666 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
668 buf
= GooString::format("/PaintType {0:d} def\n", topDict
.paintType
);
669 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
671 (*outputFunc
)(outputStream
, "/Private 32 dict begin\n", 23);
672 if (privateDicts
[i
].nBlueValues
) {
673 (*outputFunc
)(outputStream
, "/BlueValues [", 13);
674 for (j
= 0; j
< privateDicts
[i
].nBlueValues
; ++j
) {
675 buf
= GooString::format("{0:s}{1:d}",
676 j
> 0 ? " " : "", privateDicts
[i
].blueValues
[j
]);
677 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
680 (*outputFunc
)(outputStream
, "] def\n", 6);
682 if (privateDicts
[i
].nOtherBlues
) {
683 (*outputFunc
)(outputStream
, "/OtherBlues [", 13);
684 for (j
= 0; j
< privateDicts
[i
].nOtherBlues
; ++j
) {
685 buf
= GooString::format("{0:s}{1:d}",
686 j
> 0 ? " " : "", privateDicts
[i
].otherBlues
[j
]);
687 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
690 (*outputFunc
)(outputStream
, "] def\n", 6);
692 if (privateDicts
[i
].nFamilyBlues
) {
693 (*outputFunc
)(outputStream
, "/FamilyBlues [", 14);
694 for (j
= 0; j
< privateDicts
[i
].nFamilyBlues
; ++j
) {
695 buf
= GooString::format("{0:s}{1:d}",
697 privateDicts
[i
].familyBlues
[j
]);
698 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
701 (*outputFunc
)(outputStream
, "] def\n", 6);
703 if (privateDicts
[i
].nFamilyOtherBlues
) {
704 (*outputFunc
)(outputStream
, "/FamilyOtherBlues [", 19);
705 for (j
= 0; j
< privateDicts
[i
].nFamilyOtherBlues
; ++j
) {
706 buf
= GooString::format("{0:s}{1:d}", j
> 0 ? " " : "",
707 privateDicts
[i
].familyOtherBlues
[j
]);
708 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
711 (*outputFunc
)(outputStream
, "] def\n", 6);
713 if (privateDicts
[i
].blueScale
!= 0.039625) {
714 buf
= GooString::format("/BlueScale {0:.4g} def\n",
715 privateDicts
[i
].blueScale
);
716 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
719 if (privateDicts
[i
].blueShift
!= 7) {
720 buf
= GooString::format("/BlueShift {0:d} def\n",
721 privateDicts
[i
].blueShift
);
722 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
725 if (privateDicts
[i
].blueFuzz
!= 1) {
726 buf
= GooString::format("/BlueFuzz {0:d} def\n", privateDicts
[i
].blueFuzz
);
727 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
730 if (privateDicts
[i
].hasStdHW
) {
731 buf
= GooString::format("/StdHW [{0:.4g}] def\n", privateDicts
[i
].stdHW
);
732 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
735 if (privateDicts
[i
].hasStdVW
) {
736 buf
= GooString::format("/StdVW [{0:.4g}] def\n", privateDicts
[i
].stdVW
);
737 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
740 if (privateDicts
[i
].nStemSnapH
) {
741 (*outputFunc
)(outputStream
, "/StemSnapH [", 12);
742 for (j
= 0; j
< privateDicts
[i
].nStemSnapH
; ++j
) {
743 buf
= GooString::format("{0:s}{1:.4g}",
744 j
> 0 ? " " : "", privateDicts
[i
].stemSnapH
[j
]);
745 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
748 (*outputFunc
)(outputStream
, "] def\n", 6);
750 if (privateDicts
[i
].nStemSnapV
) {
751 (*outputFunc
)(outputStream
, "/StemSnapV [", 12);
752 for (j
= 0; j
< privateDicts
[i
].nStemSnapV
; ++j
) {
753 buf
= GooString::format("{0:s}{1:.4g}",
754 j
> 0 ? " " : "", privateDicts
[i
].stemSnapV
[j
]);
755 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
758 (*outputFunc
)(outputStream
, "] def\n", 6);
760 if (privateDicts
[i
].hasForceBold
) {
761 buf
= GooString::format("/ForceBold {0:s} def\n",
762 privateDicts
[i
].forceBold
? "true" : "false");
763 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
766 if (privateDicts
[i
].forceBoldThreshold
!= 0) {
767 buf
= GooString::format("/ForceBoldThreshold {0:.4g} def\n",
768 privateDicts
[i
].forceBoldThreshold
);
769 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
772 if (privateDicts
[i
].languageGroup
!= 0) {
773 buf
= GooString::format("/LanguageGroup {0:d} def\n",
774 privateDicts
[i
].languageGroup
);
775 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
778 if (privateDicts
[i
].expansionFactor
!= 0.06) {
779 buf
= GooString::format("/ExpansionFactor {0:.4g} def\n",
780 privateDicts
[i
].expansionFactor
);
781 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
784 (*outputFunc
)(outputStream
, "currentdict end def\n", 20);
785 (*outputFunc
)(outputStream
, "currentdict end put\n", 20);
787 (*outputFunc
)(outputStream
, "def\n", 4);
789 // start the binary section
790 offset
= (nCIDs
+ 1) * (1 + gdBytes
);
791 buf
= GooString::format("(Hex) {0:d} StartData\n",
792 offset
+ charStrings
->getLength());
793 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
796 // write the charstring offset (CIDMap) table
797 for (i
= 0; i
<= nCIDs
; i
+= 6) {
798 for (j
= 0; j
< 6 && i
+j
<= nCIDs
; ++j
) {
799 if (i
+j
< nCIDs
&& cidMap
[i
+j
] >= 0 && fdSelect
) {
800 buf2
[0] = (char)fdSelect
[cidMap
[i
+j
]];
804 n
= offset
+ charStringOffsets
[i
+j
];
805 for (k
= gdBytes
; k
>= 1; --k
) {
806 buf2
[k
] = (char)(n
& 0xff);
809 for (k
= 0; k
<= gdBytes
; ++k
) {
810 buf
= GooString::format("{0:02x}", buf2
[k
] & 0xff);
811 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
815 (*outputFunc
)(outputStream
, "\n", 1);
818 // write the charstring data
819 n
= charStrings
->getLength();
820 for (i
= 0; i
< n
; i
+= 32) {
821 for (j
= 0; j
< 32 && i
+j
< n
; ++j
) {
822 buf
= GooString::format("{0:02x}", charStrings
->getChar(i
+j
) & 0xff);
823 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
827 (*outputFunc
)(outputStream
, ">", 1);
829 (*outputFunc
)(outputStream
, "\n", 1);
832 gfree(charStringOffsets
);
837 void FoFiType1C::convertToType0(char *psName
, int *codeMap
, int nCodes
,
838 FoFiOutputFunc outputFunc
,
839 void *outputStream
) {
849 // compute the CID count and build the CID-to-GID mapping
852 cidMap
= (int *)gmallocn(nCIDs
, sizeof(int));
853 for (i
= 0; i
< nCodes
; ++i
) {
854 if (codeMap
[i
] >= 0 && codeMap
[i
] < nGlyphs
) {
855 cidMap
[i
] = codeMap
[i
];
860 } else if (topDict
.firstOp
== 0x0c1e) {
862 for (i
= 0; i
< nGlyphs
&& i
< charsetLength
; ++i
) {
863 if (charset
[i
] >= nCIDs
) {
864 nCIDs
= charset
[i
] + 1;
867 cidMap
= (int *)gmallocn(nCIDs
, sizeof(int));
868 for (i
= 0; i
< nCIDs
; ++i
) {
871 for (i
= 0; i
< nGlyphs
&& i
< charsetLength
; ++i
) {
872 cidMap
[charset
[i
]] = i
;
876 cidMap
= (int *)gmallocn(nCIDs
, sizeof(int));
877 for (i
= 0; i
< nCIDs
; ++i
) {
882 // write the descendant Type 1 fonts
883 for (i
= 0; i
< nCIDs
; i
+= 256) {
885 //~ this assumes that all CIDs in this block have the same FD --
886 //~ to handle multiple FDs correctly, need to somehow divide the
887 //~ font up by FD; as a kludge we ignore CID 0, which is .notdef
889 // if fdSelect is NULL, we have an 8-bit font, so just leave fd=0
891 for (j
= i
==0 ? 1 : 0; j
< 256 && i
+j
< nCIDs
; ++j
) {
892 if (cidMap
[i
+j
] >= 0) {
893 fd
= fdSelect
[cidMap
[i
+j
]];
899 // font dictionary (unencrypted section)
900 (*outputFunc
)(outputStream
, "16 dict begin\n", 14);
901 (*outputFunc
)(outputStream
, "/FontName /", 11);
902 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
903 buf
= GooString::format("_{0:02x} def\n", i
>> 8);
904 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
906 (*outputFunc
)(outputStream
, "/FontType 1 def\n", 16);
907 if (privateDicts
[fd
].hasFontMatrix
) {
908 buf
= GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
909 privateDicts
[fd
].fontMatrix
[0],
910 privateDicts
[fd
].fontMatrix
[1],
911 privateDicts
[fd
].fontMatrix
[2],
912 privateDicts
[fd
].fontMatrix
[3],
913 privateDicts
[fd
].fontMatrix
[4],
914 privateDicts
[fd
].fontMatrix
[5]);
915 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
917 } else if (topDict
.hasFontMatrix
) {
918 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
920 (*outputFunc
)(outputStream
,
921 "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
923 buf
= GooString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
924 topDict
.fontBBox
[0], topDict
.fontBBox
[1],
925 topDict
.fontBBox
[2], topDict
.fontBBox
[3]);
926 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
928 buf
= GooString::format("/PaintType {0:d} def\n", topDict
.paintType
);
929 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
931 if (topDict
.paintType
!= 0) {
932 buf
= GooString::format("/StrokeWidth {0:.4g} def\n", topDict
.strokeWidth
);
933 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
936 (*outputFunc
)(outputStream
, "/Encoding 256 array\n", 20);
937 for (j
= 0; j
< 256 && i
+j
< nCIDs
; ++j
) {
938 buf
= GooString::format("dup {0:d} /c{1:02x} put\n", j
, j
);
939 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
943 buf
= GooString::format("{0:d} 1 255 {{ 1 index exch /.notdef put }} for\n",
945 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
948 (*outputFunc
)(outputStream
, "readonly def\n", 13);
949 (*outputFunc
)(outputStream
, "currentdict end\n", 16);
951 // start the binary section
952 (*outputFunc
)(outputStream
, "currentfile eexec\n", 18);
953 eb
.outputFunc
= outputFunc
;
954 eb
.outputStream
= outputStream
;
959 // start the private dictionary
960 eexecWrite(&eb
, "\x83\xca\x73\xd5");
961 eexecWrite(&eb
, "dup /Private 32 dict dup begin\n");
962 eexecWrite(&eb
, "/RD {string currentfile exch readstring pop}"
963 " executeonly def\n");
964 eexecWrite(&eb
, "/ND {noaccess def} executeonly def\n");
965 eexecWrite(&eb
, "/NP {noaccess put} executeonly def\n");
966 eexecWrite(&eb
, "/MinFeature {16 16} def\n");
967 eexecWrite(&eb
, "/password 5839 def\n");
968 if (privateDicts
[fd
].nBlueValues
) {
969 eexecWrite(&eb
, "/BlueValues [");
970 for (k
= 0; k
< privateDicts
[fd
].nBlueValues
; ++k
) {
971 buf
= GooString::format("{0:s}{1:d}",
973 privateDicts
[fd
].blueValues
[k
]);
974 eexecWrite(&eb
, buf
->getCString());
977 eexecWrite(&eb
, "] def\n");
979 if (privateDicts
[fd
].nOtherBlues
) {
980 eexecWrite(&eb
, "/OtherBlues [");
981 for (k
= 0; k
< privateDicts
[fd
].nOtherBlues
; ++k
) {
982 buf
= GooString::format("{0:s}{1:d}",
984 privateDicts
[fd
].otherBlues
[k
]);
985 eexecWrite(&eb
, buf
->getCString());
988 eexecWrite(&eb
, "] def\n");
990 if (privateDicts
[fd
].nFamilyBlues
) {
991 eexecWrite(&eb
, "/FamilyBlues [");
992 for (k
= 0; k
< privateDicts
[fd
].nFamilyBlues
; ++k
) {
993 buf
= GooString::format("{0:s}{1:d}", k
> 0 ? " " : "",
994 privateDicts
[fd
].familyBlues
[k
]);
995 eexecWrite(&eb
, buf
->getCString());
998 eexecWrite(&eb
, "] def\n");
1000 if (privateDicts
[fd
].nFamilyOtherBlues
) {
1001 eexecWrite(&eb
, "/FamilyOtherBlues [");
1002 for (k
= 0; k
< privateDicts
[fd
].nFamilyOtherBlues
; ++k
) {
1003 buf
= GooString::format("{0:s}{1:d}", k
> 0 ? " " : "",
1004 privateDicts
[fd
].familyOtherBlues
[k
]);
1005 eexecWrite(&eb
, buf
->getCString());
1008 eexecWrite(&eb
, "] def\n");
1010 if (privateDicts
[fd
].blueScale
!= 0.039625) {
1011 buf
= GooString::format("/BlueScale {0:.4g} def\n",
1012 privateDicts
[fd
].blueScale
);
1013 eexecWrite(&eb
, buf
->getCString());
1016 if (privateDicts
[fd
].blueShift
!= 7) {
1017 buf
= GooString::format("/BlueShift {0:d} def\n",
1018 privateDicts
[fd
].blueShift
);
1019 eexecWrite(&eb
, buf
->getCString());
1022 if (privateDicts
[fd
].blueFuzz
!= 1) {
1023 buf
= GooString::format("/BlueFuzz {0:d} def\n",
1024 privateDicts
[fd
].blueFuzz
);
1025 eexecWrite(&eb
, buf
->getCString());
1028 if (privateDicts
[fd
].hasStdHW
) {
1029 buf
= GooString::format("/StdHW [{0:.4g}] def\n", privateDicts
[fd
].stdHW
);
1030 eexecWrite(&eb
, buf
->getCString());
1033 if (privateDicts
[fd
].hasStdVW
) {
1034 buf
= GooString::format("/StdVW [{0:.4g}] def\n", privateDicts
[fd
].stdVW
);
1035 eexecWrite(&eb
, buf
->getCString());
1038 if (privateDicts
[fd
].nStemSnapH
) {
1039 eexecWrite(&eb
, "/StemSnapH [");
1040 for (k
= 0; k
< privateDicts
[fd
].nStemSnapH
; ++k
) {
1041 buf
= GooString::format("{0:s}{1:.4g}",
1042 k
> 0 ? " " : "", privateDicts
[fd
].stemSnapH
[k
]);
1043 eexecWrite(&eb
, buf
->getCString());
1046 eexecWrite(&eb
, "] def\n");
1048 if (privateDicts
[fd
].nStemSnapV
) {
1049 eexecWrite(&eb
, "/StemSnapV [");
1050 for (k
= 0; k
< privateDicts
[fd
].nStemSnapV
; ++k
) {
1051 buf
= GooString::format("{0:s}{1:.4g}",
1052 k
> 0 ? " " : "", privateDicts
[fd
].stemSnapV
[k
]);
1053 eexecWrite(&eb
, buf
->getCString());
1056 eexecWrite(&eb
, "] def\n");
1058 if (privateDicts
[fd
].hasForceBold
) {
1059 buf
= GooString::format("/ForceBold {0:s} def\n",
1060 privateDicts
[fd
].forceBold
? "true" : "false");
1061 eexecWrite(&eb
, buf
->getCString());
1064 if (privateDicts
[fd
].forceBoldThreshold
!= 0) {
1065 buf
= GooString::format("/ForceBoldThreshold {0:.4g} def\n",
1066 privateDicts
[fd
].forceBoldThreshold
);
1067 eexecWrite(&eb
, buf
->getCString());
1070 if (privateDicts
[fd
].languageGroup
!= 0) {
1071 buf
= GooString::format("/LanguageGroup {0:d} def\n",
1072 privateDicts
[fd
].languageGroup
);
1073 eexecWrite(&eb
, buf
->getCString());
1076 if (privateDicts
[fd
].expansionFactor
!= 0.06) {
1077 buf
= GooString::format("/ExpansionFactor {0:.4g} def\n",
1078 privateDicts
[fd
].expansionFactor
);
1079 eexecWrite(&eb
, buf
->getCString());
1083 // set up the subroutines
1085 getIndex(privateDicts
[fd
].subrsOffset
, &subrIdx
, &ok
);
1090 // start the CharStrings
1091 eexecWrite(&eb
, "2 index /CharStrings 256 dict dup begin\n");
1093 // write the .notdef CharString
1095 getIndexVal(&charStringsIdx
, 0, &val
, &ok
);
1097 eexecCvtGlyph(&eb
, ".notdef", val
.pos
, val
.len
,
1098 &subrIdx
, &privateDicts
[fd
]);
1101 // write the CharStrings
1102 for (j
= 0; j
< 256 && i
+j
< nCIDs
; ++j
) {
1103 if (cidMap
[i
+j
] >= 0) {
1105 getIndexVal(&charStringsIdx
, cidMap
[i
+j
], &val
, &ok
);
1107 buf
= GooString::format("c{0:02x}", j
);
1108 eexecCvtGlyph(&eb
, buf
->getCString(), val
.pos
, val
.len
,
1109 &subrIdx
, &privateDicts
[fd
]);
1114 eexecWrite(&eb
, "end\n");
1115 eexecWrite(&eb
, "end\n");
1116 eexecWrite(&eb
, "readonly put\n");
1117 eexecWrite(&eb
, "noaccess put\n");
1118 eexecWrite(&eb
, "dup /FontName get exch definefont pop\n");
1119 eexecWrite(&eb
, "mark currentfile closefile\n");
1123 (*outputFunc
)(outputStream
, "\n", 1);
1125 for (j
= 0; j
< 8; ++j
) {
1126 (*outputFunc
)(outputStream
, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
1128 (*outputFunc
)(outputStream
, "cleartomark\n", 12);
1131 // write the Type 0 parent font
1132 (*outputFunc
)(outputStream
, "16 dict begin\n", 14);
1133 (*outputFunc
)(outputStream
, "/FontName /", 11);
1134 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
1135 (*outputFunc
)(outputStream
, " def\n", 5);
1136 (*outputFunc
)(outputStream
, "/FontType 0 def\n", 16);
1137 if (topDict
.hasFontMatrix
) {
1138 buf
= GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
1139 topDict
.fontMatrix
[0], topDict
.fontMatrix
[1],
1140 topDict
.fontMatrix
[2], topDict
.fontMatrix
[3],
1141 topDict
.fontMatrix
[4], topDict
.fontMatrix
[5]);
1142 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
1145 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
1147 (*outputFunc
)(outputStream
, "/FMapType 2 def\n", 16);
1148 (*outputFunc
)(outputStream
, "/Encoding [\n", 12);
1149 for (i
= 0; i
< nCIDs
; i
+= 256) {
1150 buf
= GooString::format("{0:d}\n", i
>> 8);
1151 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
1154 (*outputFunc
)(outputStream
, "] def\n", 6);
1155 (*outputFunc
)(outputStream
, "/FDepVector [\n", 14);
1156 for (i
= 0; i
< nCIDs
; i
+= 256) {
1157 (*outputFunc
)(outputStream
, "/", 1);
1158 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
1159 buf
= GooString::format("_{0:02x} findfont\n", i
>> 8);
1160 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
1163 (*outputFunc
)(outputStream
, "] def\n", 6);
1164 (*outputFunc
)(outputStream
, "FontName currentdict end definefont pop\n", 40);
1169 void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf
*eb
, const char *glyphName
,
1170 int offset
, int nBytes
,
1171 Type1CIndex
*subrIdx
,
1172 Type1CPrivateDict
*pDict
) {
1176 // generate the charstring
1177 charBuf
= new GooString();
1178 cvtGlyph(offset
, nBytes
, charBuf
, subrIdx
, pDict
, gTrue
);
1180 buf
= GooString::format("/{0:s} {1:d} RD ", glyphName
, charBuf
->getLength());
1181 eexecWrite(eb
, buf
->getCString());
1183 eexecWriteCharstring(eb
, (Guchar
*)charBuf
->getCString(),
1184 charBuf
->getLength());
1185 eexecWrite(eb
, " ND\n");
1190 void FoFiType1C::cvtGlyph(int offset
, int nBytes
, GooString
*charBuf
,
1191 Type1CIndex
*subrIdx
, Type1CPrivateDict
*pDict
,
1198 int pos
, subrBias
, start
, i
, k
;
1200 start
= charBuf
->getLength();
1202 charBuf
->append((char)73);
1203 charBuf
->append((char)58);
1204 charBuf
->append((char)147);
1205 charBuf
->append((char)134);
1213 while (pos
< offset
+ nBytes
) {
1215 pos
= getOp(pos
, gTrue
, &ok
);
1219 if (!ops
[nOps
- 1].isNum
) {
1220 --nOps
; // drop the operator
1221 switch (ops
[nOps
].op
) {
1222 case 0x0001: // hstem
1224 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1228 //~ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
1232 for (k
= 0; k
< nOps
; k
+= 2) {
1233 // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1234 if (ops
[k
+1].num
< 0) {
1235 d
+= ops
[k
].num
+ ops
[k
+1].num
;
1236 dFP
|= ops
[k
].isFP
| ops
[k
+1].isFP
;
1237 cvtNum(d
, dFP
, charBuf
);
1238 cvtNum(-ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1242 cvtNum(d
, dFP
, charBuf
);
1243 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1245 dFP
|= ops
[k
+1].isFP
;
1247 charBuf
->append((char)1);
1252 case 0x0003: // vstem
1254 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1258 //~ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
1262 for (k
= 0; k
< nOps
; k
+= 2) {
1263 // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1264 if (ops
[k
+1].num
< 0) {
1265 d
+= ops
[k
].num
+ ops
[k
+1].num
;
1266 dFP
|= ops
[k
].isFP
| ops
[k
+1].isFP
;
1267 cvtNum(d
, dFP
, charBuf
);
1268 cvtNum(-ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1272 cvtNum(d
, dFP
, charBuf
);
1273 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1275 dFP
|= ops
[k
+1].isFP
;
1277 charBuf
->append((char)3);
1282 case 0x0004: // vmoveto
1284 cvtGlyphWidth(nOps
== 2, charBuf
, pDict
);
1288 charBuf
->append((char)9);
1292 //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1294 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1295 charBuf
->append((char)4);
1298 case 0x0005: // rlineto
1299 if (nOps
< 2 || nOps
% 2 != 0) {
1300 //~ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1302 for (k
= 0; k
< nOps
; k
+= 2) {
1303 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1304 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1305 charBuf
->append((char)5);
1310 case 0x0006: // hlineto
1312 //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1314 for (k
= 0; k
< nOps
; ++k
) {
1315 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1316 charBuf
->append((char)((k
& 1) ? 7 : 6));
1321 case 0x0007: // vlineto
1323 //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1325 for (k
= 0; k
< nOps
; ++k
) {
1326 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1327 charBuf
->append((char)((k
& 1) ? 6 : 7));
1332 case 0x0008: // rrcurveto
1333 if (nOps
< 6 || nOps
% 6 != 0) {
1334 //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1336 for (k
= 0; k
< nOps
; k
+= 6) {
1337 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1338 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1339 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1340 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1341 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1342 cvtNum(ops
[k
+5].num
, ops
[k
+5].isFP
, charBuf
);
1343 charBuf
->append((char)8);
1348 case 0x000a: // callsubr
1350 subrBias
= (subrIdx
->len
< 1240)
1351 ? 107 : (subrIdx
->len
< 33900) ? 1131 : 32768;
1352 k
= subrBias
+ (int)ops
[nOps
- 1].num
;
1355 getIndexVal(subrIdx
, k
, &val
, &ok
);
1357 cvtGlyph(val
.pos
, val
.len
, charBuf
, subrIdx
, pDict
, gFalse
);
1360 //~ error(-1, "Too few args to Type 2 callsubr");
1362 // don't clear the stack
1364 case 0x000b: // return
1365 // don't clear the stack
1367 case 0x000e: // endchar / seac
1369 cvtGlyphWidth(nOps
== 1 || nOps
== 5, charBuf
, pDict
);
1373 charBuf
->append((char)9);
1377 cvtNum(0, gFalse
, charBuf
);
1378 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1379 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1380 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1381 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1382 charBuf
->append((char)12)->append((char)6);
1383 } else if (nOps
== 0) {
1384 charBuf
->append((char)14);
1386 //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1390 case 0x000f: // (obsolete)
1391 // this op is ignored, but we need the glyph width
1393 cvtGlyphWidth(nOps
> 0, charBuf
, pDict
);
1398 case 0x0010: // blend
1399 //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
1402 case 0x0012: // hstemhm
1405 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1409 //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1414 case 0x0013: // hintmask
1417 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1422 //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1427 pos
+= (nHints
+ 7) >> 3;
1430 case 0x0014: // cntrmask
1433 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1438 //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1443 pos
+= (nHints
+ 7) >> 3;
1446 case 0x0015: // rmoveto
1448 cvtGlyphWidth(nOps
== 3, charBuf
, pDict
);
1452 charBuf
->append((char)9);
1456 //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1458 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1459 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1460 charBuf
->append((char)21);
1463 case 0x0016: // hmoveto
1465 cvtGlyphWidth(nOps
== 2, charBuf
, pDict
);
1469 charBuf
->append((char)9);
1473 //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1475 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1476 charBuf
->append((char)22);
1479 case 0x0017: // vstemhm
1482 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1486 //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1491 case 0x0018: // rcurveline
1492 if (nOps
< 8 || (nOps
- 2) % 6 != 0) {
1493 //~ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1495 for (k
= 0; k
< nOps
- 2; k
+= 6) {
1496 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1497 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1498 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1499 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1500 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1501 cvtNum(ops
[k
+5].num
, ops
[k
+5].isFP
, charBuf
);
1502 charBuf
->append((char)8);
1504 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1505 cvtNum(ops
[k
+1].num
, ops
[k
].isFP
, charBuf
);
1506 charBuf
->append((char)5);
1510 case 0x0019: // rlinecurve
1511 if (nOps
< 8 || (nOps
- 6) % 2 != 0) {
1512 //~ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1514 for (k
= 0; k
< nOps
- 6; k
+= 2) {
1515 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1516 cvtNum(ops
[k
+1].num
, ops
[k
].isFP
, charBuf
);
1517 charBuf
->append((char)5);
1519 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1520 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1521 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1522 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1523 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1524 cvtNum(ops
[k
+5].num
, ops
[k
+5].isFP
, charBuf
);
1525 charBuf
->append((char)8);
1529 case 0x001a: // vvcurveto
1530 if (nOps
< 4 || !(nOps
% 4 == 0 || (nOps
-1) % 4 == 0)) {
1531 //~ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1533 if (nOps
% 2 == 1) {
1534 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1535 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1536 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1537 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1538 cvtNum(0, gFalse
, charBuf
);
1539 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1540 charBuf
->append((char)8);
1545 for (; k
< nOps
; k
+= 4) {
1546 cvtNum(0, gFalse
, charBuf
);
1547 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1548 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1549 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1550 cvtNum(0, gFalse
, charBuf
);
1551 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1552 charBuf
->append((char)8);
1557 case 0x001b: // hhcurveto
1558 if (nOps
< 4 || !(nOps
% 4 == 0 || (nOps
-1) % 4 == 0)) {
1559 //~ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1561 if (nOps
% 2 == 1) {
1562 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1563 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1564 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1565 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1566 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1567 cvtNum(0, gFalse
, charBuf
);
1568 charBuf
->append((char)8);
1573 for (; k
< nOps
; k
+= 4) {
1574 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1575 cvtNum(0, gFalse
, charBuf
);
1576 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1577 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1578 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1579 cvtNum(0, gFalse
, charBuf
);
1580 charBuf
->append((char)8);
1585 case 0x001d: // callgsubr
1587 k
= gsubrBias
+ (int)ops
[nOps
- 1].num
;
1590 getIndexVal(&gsubrIdx
, k
, &val
, &ok
);
1592 cvtGlyph(val
.pos
, val
.len
, charBuf
, subrIdx
, pDict
, gFalse
);
1595 //~ error(-1, "Too few args to Type 2 callgsubr");
1597 // don't clear the stack
1599 case 0x001e: // vhcurveto
1600 if (nOps
< 4 || !(nOps
% 4 == 0 || (nOps
-1) % 4 == 0)) {
1601 //~ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1603 for (k
= 0; k
< nOps
&& k
!= nOps
-5; k
+= 4) {
1605 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1606 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1607 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1608 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1609 charBuf
->append((char)30);
1611 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1612 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1613 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1614 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1615 charBuf
->append((char)31);
1620 cvtNum(0, gFalse
, charBuf
);
1621 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1622 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1623 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1624 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1625 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1627 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1628 cvtNum(0, gFalse
, charBuf
);
1629 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1630 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1631 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1632 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1634 charBuf
->append((char)8);
1639 case 0x001f: // hvcurveto
1640 if (nOps
< 4 || !(nOps
% 4 == 0 || (nOps
-1) % 4 == 0)) {
1641 //~ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1643 for (k
= 0; k
< nOps
&& k
!= nOps
-5; k
+= 4) {
1645 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1646 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1647 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1648 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1649 charBuf
->append((char)31);
1651 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1652 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1653 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1654 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1655 charBuf
->append((char)30);
1660 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1661 cvtNum(0, gFalse
, charBuf
);
1662 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1663 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1664 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1665 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1667 cvtNum(0, gFalse
, charBuf
);
1668 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1669 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1670 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1671 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1672 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1674 charBuf
->append((char)8);
1679 case 0x0c00: // dotsection (should be Type 1 only?)
1686 case 0x0c08: // store
1691 case 0x0c0d: // load
1694 case 0x0c12: // drop
1697 case 0x0c16: // ifelse
1698 case 0x0c17: // random
1700 case 0x0c1a: // sqrt
1702 case 0x0c1c: // exch
1703 case 0x0c1d: // index
1704 case 0x0c1e: // roll
1705 //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
1708 case 0x0c22: // hflex
1710 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1712 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1713 cvtNum(0, gFalse
, charBuf
);
1714 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1715 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1716 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1717 cvtNum(0, gFalse
, charBuf
);
1718 charBuf
->append((char)8);
1719 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1720 cvtNum(0, gFalse
, charBuf
);
1721 cvtNum(ops
[5].num
, ops
[5].isFP
, charBuf
);
1722 cvtNum(-ops
[2].num
, ops
[2].isFP
, charBuf
);
1723 cvtNum(ops
[6].num
, ops
[6].isFP
, charBuf
);
1724 cvtNum(0, gFalse
, charBuf
);
1725 charBuf
->append((char)8);
1729 case 0x0c23: // flex
1731 //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1733 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1734 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1735 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1736 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1737 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1738 cvtNum(ops
[5].num
, ops
[5].isFP
, charBuf
);
1739 charBuf
->append((char)8);
1740 cvtNum(ops
[6].num
, ops
[6].isFP
, charBuf
);
1741 cvtNum(ops
[7].num
, ops
[7].isFP
, charBuf
);
1742 cvtNum(ops
[8].num
, ops
[8].isFP
, charBuf
);
1743 cvtNum(ops
[9].num
, ops
[9].isFP
, charBuf
);
1744 cvtNum(ops
[10].num
, ops
[10].isFP
, charBuf
);
1745 cvtNum(ops
[11].num
, ops
[11].isFP
, charBuf
);
1746 charBuf
->append((char)8);
1750 case 0x0c24: // hflex1
1752 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1754 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1755 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1756 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1757 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1758 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1759 cvtNum(0, gFalse
, charBuf
);
1760 charBuf
->append((char)8);
1761 cvtNum(ops
[5].num
, ops
[5].isFP
, charBuf
);
1762 cvtNum(0, gFalse
, charBuf
);
1763 cvtNum(ops
[6].num
, ops
[6].isFP
, charBuf
);
1764 cvtNum(ops
[7].num
, ops
[7].isFP
, charBuf
);
1765 cvtNum(ops
[8].num
, ops
[8].isFP
, charBuf
);
1766 cvtNum(-(ops
[1].num
+ ops
[3].num
+ ops
[7].num
),
1767 ops
[1].isFP
| ops
[3].isFP
| ops
[7].isFP
, charBuf
);
1768 charBuf
->append((char)8);
1772 case 0x0c25: // flex1
1774 //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1776 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1777 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1778 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1779 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1780 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1781 cvtNum(ops
[5].num
, ops
[5].isFP
, charBuf
);
1782 charBuf
->append((char)8);
1783 cvtNum(ops
[6].num
, ops
[6].isFP
, charBuf
);
1784 cvtNum(ops
[7].num
, ops
[7].isFP
, charBuf
);
1785 cvtNum(ops
[8].num
, ops
[8].isFP
, charBuf
);
1786 cvtNum(ops
[9].num
, ops
[9].isFP
, charBuf
);
1787 dx
= ops
[0].num
+ ops
[2].num
+ ops
[4].num
+ ops
[6].num
+ ops
[8].num
;
1788 dy
= ops
[1].num
+ ops
[3].num
+ ops
[5].num
+ ops
[7].num
+ ops
[9].num
;
1789 if (fabs(dx
) > fabs(dy
)) {
1790 cvtNum(ops
[10].num
, ops
[10].isFP
, charBuf
);
1791 cvtNum(-dy
, ops
[1].isFP
| ops
[3].isFP
| ops
[5].isFP
|
1792 ops
[7].isFP
| ops
[9].isFP
, charBuf
);
1794 cvtNum(-dx
, ops
[0].isFP
| ops
[2].isFP
| ops
[4].isFP
|
1795 ops
[6].isFP
| ops
[8].isFP
, charBuf
);
1796 cvtNum(ops
[10].num
, ops
[10].isFP
, charBuf
);
1798 charBuf
->append((char)8);
1803 //~ error(-1, "Illegal Type 2 charstring op: %04x",
1811 // charstring encryption
1814 for (i
= start
; i
< charBuf
->getLength(); ++i
) {
1815 byte
= charBuf
->getChar(i
) ^ (r2
>> 8);
1816 charBuf
->setChar(i
, byte
);
1817 r2
= (byte
+ r2
) * 52845 + 22719;
1822 void FoFiType1C::cvtGlyphWidth(GBool useOp
, GooString
*charBuf
,
1823 Type1CPrivateDict
*pDict
) {
1829 w
= pDict
->nominalWidthX
+ ops
[0].num
;
1830 wFP
= pDict
->nominalWidthXFP
| ops
[0].isFP
;
1831 for (i
= 1; i
< nOps
; ++i
) {
1836 w
= pDict
->defaultWidthX
;
1837 wFP
= pDict
->defaultWidthXFP
;
1839 cvtNum(0, gFalse
, charBuf
);
1840 cvtNum(w
, wFP
, charBuf
);
1841 charBuf
->append((char)13);
1844 void FoFiType1C::cvtNum(double x
, GBool isFP
, GooString
*charBuf
) {
1850 if (x
>= -32768 && x
< 32768) {
1851 y
= (int)(x
* 256.0);
1853 buf
[1] = (Guchar
)(y
>> 24);
1854 buf
[2] = (Guchar
)(y
>> 16);
1855 buf
[3] = (Guchar
)(y
>> 8);
1866 //~ error(-1, "Type 2 fixed point constant out of range");
1870 if (y
>= -107 && y
<= 107) {
1871 buf
[0] = (Guchar
)(y
+ 139);
1873 } else if (y
> 107 && y
<= 1131) {
1875 buf
[0] = (Guchar
)((y
>> 8) + 247);
1876 buf
[1] = (Guchar
)(y
& 0xff);
1878 } else if (y
< -107 && y
>= -1131) {
1880 buf
[0] = (Guchar
)((y
>> 8) + 251);
1881 buf
[1] = (Guchar
)(y
& 0xff);
1885 buf
[1] = (Guchar
)(y
>> 24);
1886 buf
[2] = (Guchar
)(y
>> 16);
1887 buf
[3] = (Guchar
)(y
>> 8);
1892 charBuf
->append((char *)buf
, n
);
1895 void FoFiType1C::eexecWrite(Type1CEexecBuf
*eb
, const char *s
) {
1899 for (p
= (Guchar
*)s
; *p
; ++p
) {
1900 x
= *p
^ (eb
->r1
>> 8);
1901 eb
->r1
= (x
+ eb
->r1
) * 52845 + 22719;
1903 (*eb
->outputFunc
)(eb
->outputStream
, &hexChars
[x
>> 4], 1);
1904 (*eb
->outputFunc
)(eb
->outputStream
, &hexChars
[x
& 0x0f], 1);
1906 if (eb
->line
== 64) {
1907 (*eb
->outputFunc
)(eb
->outputStream
, "\n", 1);
1911 (*eb
->outputFunc
)(eb
->outputStream
, (char *)&x
, 1);
1916 void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf
*eb
,
1922 for (i
= 0; i
< n
; ++i
) {
1923 x
= s
[i
] ^ (eb
->r1
>> 8);
1924 eb
->r1
= (x
+ eb
->r1
) * 52845 + 22719;
1926 (*eb
->outputFunc
)(eb
->outputStream
, &hexChars
[x
>> 4], 1);
1927 (*eb
->outputFunc
)(eb
->outputStream
, &hexChars
[x
& 0x0f], 1);
1929 if (eb
->line
== 64) {
1930 (*eb
->outputFunc
)(eb
->outputStream
, "\n", 1);
1934 (*eb
->outputFunc
)(eb
->outputStream
, (char *)&x
, 1);
1939 void FoFiType1C::writePSString(char *s
, FoFiOutputFunc outputFunc
,
1940 void *outputStream
) {
1947 for (p
= s
; *p
; ++p
) {
1949 if (c
== '(' || c
== ')' || c
== '\\') {
1952 } else if (c
< 0x20 || c
>= 0x80) {
1954 buf
[i
++] = '0' + ((c
>> 6) & 7);
1955 buf
[i
++] = '0' + ((c
>> 3) & 7);
1956 buf
[i
++] = '0' + (c
& 7);
1963 (*outputFunc
)(outputStream
, buf
, i
);
1968 (*outputFunc
)(outputStream
, buf
, i
);
1971 GBool
FoFiType1C::parse() {
1978 // some tools embed Type 1C fonts with an extra whitespace char at
1980 if (len
> 0 && file
[0] != '\x01') {
1986 getIndex(getU8(2, &parsedOk
), &nameIdx
, &parsedOk
);
1987 getIndex(nameIdx
.endPos
, &topDictIdx
, &parsedOk
);
1988 getIndex(topDictIdx
.endPos
, &stringIdx
, &parsedOk
);
1989 getIndex(stringIdx
.endPos
, &gsubrIdx
, &parsedOk
);
1993 gsubrBias
= (gsubrIdx
.len
< 1240) ? 107
1994 : (gsubrIdx
.len
< 33900) ? 1131 : 32768;
1996 // read the first font name
1997 getIndexVal(&nameIdx
, 0, &val
, &parsedOk
);
2001 name
= new GooString((char *)&file
[val
.pos
], val
.len
);
2003 // read the top dict for the first font
2006 // for CID fonts: read the FDArray dicts and private dicts
2007 if (topDict
.firstOp
== 0x0c1e) {
2008 if (topDict
.fdArrayOffset
== 0) {
2010 privateDicts
= (Type1CPrivateDict
*)gmalloc(sizeof(Type1CPrivateDict
));
2011 readPrivateDict(0, 0, &privateDicts
[0]);
2013 getIndex(topDict
.fdArrayOffset
, &fdIdx
, &parsedOk
);
2018 privateDicts
= (Type1CPrivateDict
*)
2019 gmallocn(nFDs
, sizeof(Type1CPrivateDict
));
2020 for (i
= 0; i
< nFDs
; ++i
) {
2021 getIndexVal(&fdIdx
, i
, &val
, &parsedOk
);
2025 readFD(val
.pos
, val
.len
, &privateDicts
[i
]);
2029 // for 8-bit fonts: read the private dict
2032 privateDicts
= (Type1CPrivateDict
*)gmalloc(sizeof(Type1CPrivateDict
));
2033 readPrivateDict(topDict
.privateOffset
, topDict
.privateSize
,
2037 // check for parse errors in the private dict(s)
2042 // get the charstrings index
2043 if (topDict
.charStringsOffset
<= 0) {
2047 getIndex(topDict
.charStringsOffset
, &charStringsIdx
, &parsedOk
);
2051 nGlyphs
= charStringsIdx
.len
;
2053 // for CID fonts: read the FDSelect table
2054 if (topDict
.firstOp
== 0x0c1e) {
2062 if (!readCharset()) {
2067 // for 8-bit fonts: build the encoding
2068 if (topDict
.firstOp
!= 0x0c14 && topDict
.firstOp
!= 0x0c1e) {
2078 void FoFiType1C::readTopDict() {
2079 Type1CIndexVal topDictPtr
;
2082 topDict
.firstOp
= -1;
2083 topDict
.versionSID
= 0;
2084 topDict
.noticeSID
= 0;
2085 topDict
.copyrightSID
= 0;
2086 topDict
.fullNameSID
= 0;
2087 topDict
.familyNameSID
= 0;
2088 topDict
.weightSID
= 0;
2089 topDict
.isFixedPitch
= 0;
2090 topDict
.italicAngle
= 0;
2091 topDict
.underlinePosition
= -100;
2092 topDict
.underlineThickness
= 50;
2093 topDict
.paintType
= 0;
2094 topDict
.charstringType
= 2;
2095 topDict
.fontMatrix
[0] = 0.001;
2096 topDict
.fontMatrix
[1] = 0;
2097 topDict
.fontMatrix
[2] = 0;
2098 topDict
.fontMatrix
[3] = 0.001;
2099 topDict
.fontMatrix
[4] = 0;
2100 topDict
.fontMatrix
[5] = 0;
2101 topDict
.hasFontMatrix
= gFalse
;
2102 topDict
.uniqueID
= 0;
2103 topDict
.fontBBox
[0] = 0;
2104 topDict
.fontBBox
[1] = 0;
2105 topDict
.fontBBox
[2] = 0;
2106 topDict
.fontBBox
[3] = 0;
2107 topDict
.strokeWidth
= 0;
2108 topDict
.charsetOffset
= 0;
2109 topDict
.encodingOffset
= 0;
2110 topDict
.charStringsOffset
= 0;
2111 topDict
.privateSize
= 0;
2112 topDict
.privateOffset
= 0;
2113 topDict
.registrySID
= 0;
2114 topDict
.orderingSID
= 0;
2115 topDict
.supplement
= 0;
2116 topDict
.fdArrayOffset
= 0;
2117 topDict
.fdSelectOffset
= 0;
2119 getIndexVal(&topDictIdx
, 0, &topDictPtr
, &parsedOk
);
2120 pos
= topDictPtr
.pos
;
2122 while (pos
< topDictPtr
.pos
+ topDictPtr
.len
) {
2123 pos
= getOp(pos
, gFalse
, &parsedOk
);
2127 if (!ops
[nOps
- 1].isNum
) {
2128 --nOps
; // drop the operator
2129 if (topDict
.firstOp
< 0) {
2130 topDict
.firstOp
= ops
[nOps
].op
;
2132 switch (ops
[nOps
].op
) {
2133 case 0x0000: topDict
.versionSID
= (int)ops
[0].num
; break;
2134 case 0x0001: topDict
.noticeSID
= (int)ops
[0].num
; break;
2135 case 0x0c00: topDict
.copyrightSID
= (int)ops
[0].num
; break;
2136 case 0x0002: topDict
.fullNameSID
= (int)ops
[0].num
; break;
2137 case 0x0003: topDict
.familyNameSID
= (int)ops
[0].num
; break;
2138 case 0x0004: topDict
.weightSID
= (int)ops
[0].num
; break;
2139 case 0x0c01: topDict
.isFixedPitch
= (int)ops
[0].num
; break;
2140 case 0x0c02: topDict
.italicAngle
= ops
[0].num
; break;
2141 case 0x0c03: topDict
.underlinePosition
= ops
[0].num
; break;
2142 case 0x0c04: topDict
.underlineThickness
= ops
[0].num
; break;
2143 case 0x0c05: topDict
.paintType
= (int)ops
[0].num
; break;
2144 case 0x0c06: topDict
.charstringType
= (int)ops
[0].num
; break;
2145 case 0x0c07: topDict
.fontMatrix
[0] = ops
[0].num
;
2146 topDict
.fontMatrix
[1] = ops
[1].num
;
2147 topDict
.fontMatrix
[2] = ops
[2].num
;
2148 topDict
.fontMatrix
[3] = ops
[3].num
;
2149 topDict
.fontMatrix
[4] = ops
[4].num
;
2150 topDict
.fontMatrix
[5] = ops
[5].num
;
2151 topDict
.hasFontMatrix
= gTrue
; break;
2152 case 0x000d: topDict
.uniqueID
= (int)ops
[0].num
; break;
2153 case 0x0005: topDict
.fontBBox
[0] = ops
[0].num
;
2154 topDict
.fontBBox
[1] = ops
[1].num
;
2155 topDict
.fontBBox
[2] = ops
[2].num
;
2156 topDict
.fontBBox
[3] = ops
[3].num
; break;
2157 case 0x0c08: topDict
.strokeWidth
= ops
[0].num
; break;
2158 case 0x000f: topDict
.charsetOffset
= (int)ops
[0].num
; break;
2159 case 0x0010: topDict
.encodingOffset
= (int)ops
[0].num
; break;
2160 case 0x0011: topDict
.charStringsOffset
= (int)ops
[0].num
; break;
2161 case 0x0012: topDict
.privateSize
= (int)ops
[0].num
;
2162 topDict
.privateOffset
= (int)ops
[1].num
; break;
2163 case 0x0c1e: topDict
.registrySID
= (int)ops
[0].num
;
2164 topDict
.orderingSID
= (int)ops
[1].num
;
2165 topDict
.supplement
= (int)ops
[2].num
; break;
2166 case 0x0c24: topDict
.fdArrayOffset
= (int)ops
[0].num
; break;
2167 case 0x0c25: topDict
.fdSelectOffset
= (int)ops
[0].num
; break;
2174 // Read a CID font dict (FD) - this pulls out the private dict
2175 // pointer, and reads the private dict. It also pulls the FontMatrix
2176 // (if any) out of the FD.
2177 void FoFiType1C::readFD(int offset
, int length
, Type1CPrivateDict
*pDict
) {
2178 int pos
, pSize
, pOffset
;
2179 double fontMatrix
[6] = {0};
2180 GBool hasFontMatrix
;
2182 hasFontMatrix
= gFalse
;
2183 fontMatrix
[0] = fontMatrix
[1] = fontMatrix
[2] = 0; // make gcc happy
2184 fontMatrix
[3] = fontMatrix
[4] = fontMatrix
[5] = 0;
2185 pSize
= pOffset
= 0;
2188 while (pos
< offset
+ length
) {
2189 pos
= getOp(pos
, gFalse
, &parsedOk
);
2193 if (!ops
[nOps
- 1].isNum
) {
2194 if (ops
[nOps
- 1].op
== 0x0012) {
2199 pSize
= (int)ops
[0].num
;
2200 pOffset
= (int)ops
[1].num
;
2202 } else if (ops
[nOps
- 1].op
== 0x0c07) {
2203 fontMatrix
[0] = ops
[0].num
;
2204 fontMatrix
[1] = ops
[1].num
;
2205 fontMatrix
[2] = ops
[2].num
;
2206 fontMatrix
[3] = ops
[3].num
;
2207 fontMatrix
[4] = ops
[4].num
;
2208 fontMatrix
[5] = ops
[5].num
;
2209 hasFontMatrix
= gTrue
;
2214 readPrivateDict(pOffset
, pSize
, pDict
);
2215 if (hasFontMatrix
) {
2216 pDict
->fontMatrix
[0] = fontMatrix
[0];
2217 pDict
->fontMatrix
[1] = fontMatrix
[1];
2218 pDict
->fontMatrix
[2] = fontMatrix
[2];
2219 pDict
->fontMatrix
[3] = fontMatrix
[3];
2220 pDict
->fontMatrix
[4] = fontMatrix
[4];
2221 pDict
->fontMatrix
[5] = fontMatrix
[5];
2222 pDict
->hasFontMatrix
= gTrue
;
2226 void FoFiType1C::readPrivateDict(int offset
, int length
,
2227 Type1CPrivateDict
*pDict
) {
2230 pDict
->hasFontMatrix
= gFalse
;
2231 pDict
->nBlueValues
= 0;
2232 pDict
->nOtherBlues
= 0;
2233 pDict
->nFamilyBlues
= 0;
2234 pDict
->nFamilyOtherBlues
= 0;
2235 pDict
->blueScale
= 0.039625;
2236 pDict
->blueShift
= 7;
2237 pDict
->blueFuzz
= 1;
2238 pDict
->hasStdHW
= gFalse
;
2239 pDict
->hasStdVW
= gFalse
;
2240 pDict
->nStemSnapH
= 0;
2241 pDict
->nStemSnapV
= 0;
2242 pDict
->hasForceBold
= gFalse
;
2243 pDict
->forceBoldThreshold
= 0;
2244 pDict
->languageGroup
= 0;
2245 pDict
->expansionFactor
= 0.06;
2246 pDict
->initialRandomSeed
= 0;
2247 pDict
->subrsOffset
= 0;
2248 pDict
->defaultWidthX
= 0;
2249 pDict
->defaultWidthXFP
= gFalse
;
2250 pDict
->nominalWidthX
= 0;
2251 pDict
->nominalWidthXFP
= gFalse
;
2254 if (offset
== 0 || length
== 0) {
2260 while (pos
< offset
+ length
) {
2261 pos
= getOp(pos
, gFalse
, &parsedOk
);
2265 if (!ops
[nOps
- 1].isNum
) {
2266 --nOps
; // drop the operator
2267 switch (ops
[nOps
].op
) {
2269 pDict
->nBlueValues
= getDeltaIntArray(pDict
->blueValues
,
2270 type1CMaxBlueValues
);
2273 pDict
->nOtherBlues
= getDeltaIntArray(pDict
->otherBlues
,
2274 type1CMaxOtherBlues
);
2277 pDict
->nFamilyBlues
= getDeltaIntArray(pDict
->familyBlues
,
2278 type1CMaxBlueValues
);
2281 pDict
->nFamilyOtherBlues
= getDeltaIntArray(pDict
->familyOtherBlues
,
2282 type1CMaxOtherBlues
);
2285 pDict
->blueScale
= ops
[0].num
;
2288 pDict
->blueShift
= (int)ops
[0].num
;
2291 pDict
->blueFuzz
= (int)ops
[0].num
;
2294 pDict
->stdHW
= ops
[0].num
;
2295 pDict
->hasStdHW
= gTrue
;
2298 pDict
->stdVW
= ops
[0].num
;
2299 pDict
->hasStdVW
= gTrue
;
2302 pDict
->nStemSnapH
= getDeltaFPArray(pDict
->stemSnapH
,
2306 pDict
->nStemSnapV
= getDeltaFPArray(pDict
->stemSnapV
,
2310 pDict
->forceBold
= ops
[0].num
!= 0;
2311 pDict
->hasForceBold
= gTrue
;
2314 pDict
->forceBoldThreshold
= ops
[0].num
;
2317 pDict
->languageGroup
= (int)ops
[0].num
;
2320 pDict
->expansionFactor
= ops
[0].num
;
2323 pDict
->initialRandomSeed
= (int)ops
[0].num
;
2326 pDict
->subrsOffset
= offset
+ (int)ops
[0].num
;
2329 pDict
->defaultWidthX
= ops
[0].num
;
2330 pDict
->defaultWidthXFP
= ops
[0].isFP
;
2333 pDict
->nominalWidthX
= ops
[0].num
;
2334 pDict
->nominalWidthXFP
= ops
[0].isFP
;
2342 void FoFiType1C::readFDSelect() {
2343 int fdSelectFmt
, pos
, nRanges
, gid0
, gid1
, fd
, i
, j
;
2345 fdSelect
= (Guchar
*)gmalloc(nGlyphs
);
2346 if (topDict
.fdSelectOffset
== 0) {
2347 for (i
= 0; i
< nGlyphs
; ++i
) {
2351 pos
= topDict
.fdSelectOffset
;
2352 fdSelectFmt
= getU8(pos
++, &parsedOk
);
2356 if (fdSelectFmt
== 0) {
2357 if (!checkRegion(pos
, nGlyphs
)) {
2361 memcpy(fdSelect
, file
+ pos
, nGlyphs
);
2362 } else if (fdSelectFmt
== 3) {
2363 nRanges
= getU16BE(pos
, &parsedOk
);
2365 gid0
= getU16BE(pos
, &parsedOk
);
2367 for (i
= 1; i
<= nRanges
; ++i
) {
2368 fd
= getU8(pos
++, &parsedOk
);
2369 gid1
= getU16BE(pos
, &parsedOk
);
2374 if (gid0
> gid1
|| gid1
> nGlyphs
) {
2375 //~ error(-1, "Bad FDSelect table in CID font");
2379 for (j
= gid0
; j
< gid1
; ++j
) {
2385 //~ error(-1, "Unknown FDSelect table format in CID font");
2386 for (i
= 0; i
< nGlyphs
; ++i
) {
2393 void FoFiType1C::buildEncoding() {
2395 int nCodes
, nRanges
, encFormat
;
2396 int pos
, c
, sid
, nLeft
, nSups
, i
, j
;
2398 if (topDict
.encodingOffset
== 0) {
2399 encoding
= (char **)fofiType1StandardEncoding
;
2401 } else if (topDict
.encodingOffset
== 1) {
2402 encoding
= (char **)fofiType1ExpertEncoding
;
2405 encoding
= (char **)gmallocn(256, sizeof(char *));
2406 for (i
= 0; i
< 256; ++i
) {
2409 pos
= topDict
.encodingOffset
;
2410 encFormat
= getU8(pos
++, &parsedOk
);
2414 if ((encFormat
& 0x7f) == 0) {
2415 nCodes
= 1 + getU8(pos
++, &parsedOk
);
2419 if (nCodes
> nGlyphs
) {
2422 for (i
= 1; i
< nCodes
&& i
< charsetLength
; ++i
) {
2423 c
= getU8(pos
++, &parsedOk
);
2430 encoding
[c
] = copyString(getString(charset
[i
], buf
, &parsedOk
));
2432 } else if ((encFormat
& 0x7f) == 1) {
2433 nRanges
= getU8(pos
++, &parsedOk
);
2438 for (i
= 0; i
< nRanges
; ++i
) {
2439 c
= getU8(pos
++, &parsedOk
);
2440 nLeft
= getU8(pos
++, &parsedOk
);
2444 for (j
= 0; j
<= nLeft
&& nCodes
< nGlyphs
&& nCodes
< charsetLength
; ++j
) {
2449 encoding
[c
] = copyString(getString(charset
[nCodes
], buf
,
2457 if (encFormat
& 0x80) {
2458 nSups
= getU8(pos
++, &parsedOk
);
2462 for (i
= 0; i
< nSups
; ++i
) {
2463 c
= getU8(pos
++, &parsedOk
);;
2467 sid
= getU16BE(pos
, &parsedOk
);
2475 encoding
[c
] = copyString(getString(sid
, buf
, &parsedOk
));
2481 GBool
FoFiType1C::readCharset() {
2482 int charsetFormat
, c
, pos
;
2485 if (topDict
.charsetOffset
== 0) {
2486 charset
= fofiType1CISOAdobeCharset
;
2487 charsetLength
= sizeof(fofiType1CISOAdobeCharset
) / sizeof(Gushort
);
2488 } else if (topDict
.charsetOffset
== 1) {
2489 charset
= fofiType1CExpertCharset
;
2490 charsetLength
= sizeof(fofiType1CExpertCharset
) / sizeof(Gushort
);
2491 } else if (topDict
.charsetOffset
== 2) {
2492 charset
= fofiType1CExpertSubsetCharset
;
2493 charsetLength
= sizeof(fofiType1CExpertSubsetCharset
) / sizeof(Gushort
);
2495 charset
= (Gushort
*)gmallocn(nGlyphs
, sizeof(Gushort
));
2496 charsetLength
= nGlyphs
;
2497 for (i
= 0; i
< nGlyphs
; ++i
) {
2500 pos
= topDict
.charsetOffset
;
2501 charsetFormat
= getU8(pos
++, &parsedOk
);
2502 if (charsetFormat
== 0) {
2503 for (i
= 1; i
< nGlyphs
; ++i
) {
2504 charset
[i
] = (Gushort
)getU16BE(pos
, &parsedOk
);
2510 } else if (charsetFormat
== 1) {
2512 while (i
< nGlyphs
) {
2513 c
= getU16BE(pos
, &parsedOk
);
2515 nLeft
= getU8(pos
++, &parsedOk
);
2519 for (j
= 0; j
<= nLeft
&& i
< nGlyphs
; ++j
) {
2520 charset
[i
++] = (Gushort
)c
++;
2523 } else if (charsetFormat
== 2) {
2525 while (i
< nGlyphs
) {
2526 c
= getU16BE(pos
, &parsedOk
);
2528 nLeft
= getU16BE(pos
, &parsedOk
);
2533 for (j
= 0; j
<= nLeft
&& i
< nGlyphs
; ++j
) {
2534 charset
[i
++] = (Gushort
)c
++;
2548 int FoFiType1C::getOp(int pos
, GBool charstring
, GBool
*ok
) {
2549 static char nybChars
[16] = "0123456789.ee -";
2552 int b0
, b1
, nyb0
, nyb1
, x
, i
;
2554 b0
= getU8(pos
++, ok
);
2559 x
= getU8(pos
++, ok
);
2560 x
= (x
<< 8) | getU8(pos
++, ok
);
2566 } else if (!charstring
&& b0
== 29) {
2567 x
= getU8(pos
++, ok
);
2568 x
= (x
<< 8) | getU8(pos
++, ok
);
2569 x
= (x
<< 8) | getU8(pos
++, ok
);
2570 x
= (x
<< 8) | getU8(pos
++, ok
);
2571 if (x
& 0x80000000) {
2576 } else if (!charstring
&& b0
== 30) {
2579 b1
= getU8(pos
++, ok
);
2585 buf
[i
++] = nybChars
[nyb0
];
2598 buf
[i
++] = nybChars
[nyb1
];
2607 op
.num
= gatof(buf
);
2610 } else if (b0
>= 32 && b0
<= 246) {
2613 } else if (b0
>= 247 && b0
<= 250) {
2614 op
.num
= ((b0
- 247) << 8) + getU8(pos
++, ok
) + 108;
2616 } else if (b0
>= 251 && b0
<= 254) {
2617 op
.num
= -((b0
- 251) << 8) - getU8(pos
++, ok
) - 108;
2619 } else if (charstring
&& b0
== 255) {
2620 x
= getU8(pos
++, ok
);
2621 x
= (x
<< 8) | getU8(pos
++, ok
);
2622 x
= (x
<< 8) | getU8(pos
++, ok
);
2623 x
= (x
<< 8) | getU8(pos
++, ok
);
2624 if (x
& 0x80000000) {
2627 op
.num
= (double)x
/ 65536.0;
2630 } else if (b0
== 12) {
2632 op
.op
= 0x0c00 + getU8(pos
++, ok
);
2646 // Convert the delta-encoded ops array to an array of ints.
2647 int FoFiType1C::getDeltaIntArray(int *arr
, int maxLen
) {
2651 if ((n
= nOps
) > maxLen
) {
2655 for (i
= 0; i
< n
; ++i
) {
2656 x
+= (int)ops
[i
].num
;
2662 // Convert the delta-encoded ops array to an array of doubles.
2663 int FoFiType1C::getDeltaFPArray(double *arr
, int maxLen
) {
2667 if ((n
= nOps
) > maxLen
) {
2671 for (i
= 0; i
< n
; ++i
) {
2678 void FoFiType1C::getIndex(int pos
, Type1CIndex
*idx
, GBool
*ok
) {
2680 idx
->len
= getU16BE(pos
, ok
);
2681 if (idx
->len
== 0) {
2682 // empty indexes are legal and contain just the length field
2684 idx
->startPos
= idx
->endPos
= pos
+ 2;
2686 idx
->offSize
= getU8(pos
+ 2, ok
);
2687 if (idx
->offSize
< 1 || idx
->offSize
> 4) {
2690 idx
->startPos
= pos
+ 3 + (idx
->len
+ 1) * idx
->offSize
- 1;
2691 if (idx
->startPos
< 0 || idx
->startPos
>= len
) {
2694 idx
->endPos
= idx
->startPos
+ getUVarBE(pos
+ 3 + idx
->len
* idx
->offSize
,
2696 if (idx
->endPos
< idx
->startPos
|| idx
->endPos
> len
) {
2702 void FoFiType1C::getIndexVal(Type1CIndex
*idx
, int i
,
2703 Type1CIndexVal
*val
, GBool
*ok
) {
2706 if (i
< 0 || i
>= idx
->len
) {
2710 pos0
= idx
->startPos
+ getUVarBE(idx
->pos
+ 3 + i
* idx
->offSize
,
2712 pos1
= idx
->startPos
+ getUVarBE(idx
->pos
+ 3 + (i
+ 1) * idx
->offSize
,
2714 if (pos0
< idx
->startPos
|| pos0
> idx
->endPos
||
2715 pos1
<= idx
->startPos
|| pos1
> idx
->endPos
||
2720 val
->len
= pos1
- pos0
;
2723 char *FoFiType1C::getString(int sid
, char *buf
, GBool
*ok
) {
2729 } else if (sid
< 391) {
2730 strcpy(buf
, fofiType1CStdStrings
[sid
]);
2733 getIndexVal(&stringIdx
, sid
, &val
, ok
);
2735 if ((n
= val
.len
) > 255) {
2738 strncpy(buf
, (char *)&file
[val
.pos
], n
);