1 //========================================================================
5 // Copyright 1999-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
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 *psName
, char **newEncoding
, GBool ascii
,
133 FoFiOutputFunc outputFunc
,
134 void *outputStream
) {
146 psNameLen
= strlen(psName
);
148 psName
= name
->getCString();
149 psNameLen
= name
->getLength();
152 // write header and font dictionary, up to encoding
154 (*outputFunc
)(outputStream
, "%!FontType1-1.0: ", 17);
155 (*outputFunc
)(outputStream
, psName
, psNameLen
);
156 if (topDict
.versionSID
!= 0) {
157 getString(topDict
.versionSID
, buf2
, &ok
);
158 (*outputFunc
)(outputStream
, buf2
, strlen(buf2
));
160 (*outputFunc
)(outputStream
, "\n", 1);
161 // the dictionary needs room for 12 entries: the following 9, plus
162 // Private and CharStrings (in the eexec section) and FID (which is
163 // added by definefont)
164 (*outputFunc
)(outputStream
, "12 dict begin\n", 14);
165 (*outputFunc
)(outputStream
, "/FontInfo 10 dict dup begin\n", 28);
166 if (topDict
.versionSID
!= 0) {
167 (*outputFunc
)(outputStream
, "/version (", 10);
168 (*outputFunc
)(outputStream
, buf2
, strlen(buf2
));
169 (*outputFunc
)(outputStream
, ") readonly def\n", 15);
171 if (topDict
.noticeSID
!= 0) {
172 getString(topDict
.noticeSID
, buf2
, &ok
);
173 (*outputFunc
)(outputStream
, "/Notice (", 9);
174 (*outputFunc
)(outputStream
, buf2
, strlen(buf2
));
175 (*outputFunc
)(outputStream
, ") readonly def\n", 15);
177 if (topDict
.copyrightSID
!= 0) {
178 getString(topDict
.copyrightSID
, buf2
, &ok
);
179 (*outputFunc
)(outputStream
, "/Copyright (", 12);
180 (*outputFunc
)(outputStream
, buf2
, strlen(buf2
));
181 (*outputFunc
)(outputStream
, ") readonly def\n", 15);
183 if (topDict
.fullNameSID
!= 0) {
184 getString(topDict
.fullNameSID
, buf2
, &ok
);
185 (*outputFunc
)(outputStream
, "/FullName (", 11);
186 (*outputFunc
)(outputStream
, buf2
, strlen(buf2
));
187 (*outputFunc
)(outputStream
, ") readonly def\n", 15);
189 if (topDict
.familyNameSID
!= 0) {
190 getString(topDict
.familyNameSID
, buf2
, &ok
);
191 (*outputFunc
)(outputStream
, "/FamilyName (", 13);
192 (*outputFunc
)(outputStream
, buf2
, strlen(buf2
));
193 (*outputFunc
)(outputStream
, ") readonly def\n", 15);
195 if (topDict
.weightSID
!= 0) {
196 getString(topDict
.weightSID
, buf2
, &ok
);
197 (*outputFunc
)(outputStream
, "/Weight (", 9);
198 (*outputFunc
)(outputStream
, buf2
, strlen(buf2
));
199 (*outputFunc
)(outputStream
, ") readonly def\n", 15);
201 if (topDict
.isFixedPitch
) {
202 (*outputFunc
)(outputStream
, "/isFixedPitch true def\n", 23);
204 (*outputFunc
)(outputStream
, "/isFixedPitch false def\n", 24);
206 buf
= GString::format("/ItalicAngle {0:.4g} def\n", topDict
.italicAngle
);
207 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
209 buf
= GString::format("/UnderlinePosition {0:.4g} def\n",
210 topDict
.underlinePosition
);
211 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
213 buf
= GString::format("/UnderlineThickness {0:.4g} def\n",
214 topDict
.underlineThickness
);
215 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
217 (*outputFunc
)(outputStream
, "end readonly def\n", 17);
218 (*outputFunc
)(outputStream
, "/FontName /", 11);
219 (*outputFunc
)(outputStream
, psName
, psNameLen
);
220 (*outputFunc
)(outputStream
, " def\n", 5);
221 buf
= GString::format("/PaintType {0:d} def\n", topDict
.paintType
);
222 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
224 (*outputFunc
)(outputStream
, "/FontType 1 def\n", 16);
225 buf
= GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] readonly def\n",
226 topDict
.fontMatrix
[0], topDict
.fontMatrix
[1],
227 topDict
.fontMatrix
[2], topDict
.fontMatrix
[3],
228 topDict
.fontMatrix
[4], topDict
.fontMatrix
[5]);
229 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
231 buf
= GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] readonly def\n",
232 topDict
.fontBBox
[0], topDict
.fontBBox
[1],
233 topDict
.fontBBox
[2], topDict
.fontBBox
[3]);
234 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
236 buf
= GString::format("/StrokeWidth {0:.4g} def\n", topDict
.strokeWidth
);
237 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
239 if (topDict
.uniqueID
!= 0) {
240 buf
= GString::format("/UniqueID {0:d} def\n", topDict
.uniqueID
);
241 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
245 // write the encoding
246 (*outputFunc
)(outputStream
, "/Encoding ", 10);
247 if (!newEncoding
&& encoding
== fofiType1StandardEncoding
) {
248 (*outputFunc
)(outputStream
, "StandardEncoding def\n", 21);
250 (*outputFunc
)(outputStream
, "256 array\n", 10);
251 (*outputFunc
)(outputStream
,
252 "0 1 255 {1 index exch /.notdef put} for\n", 40);
253 enc
= newEncoding
? newEncoding
: encoding
;
254 for (i
= 0; i
< 256; ++i
) {
256 buf
= GString::format("dup {0:d} /{1:s} put\n", i
, enc
[i
]);
257 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
261 (*outputFunc
)(outputStream
, "readonly def\n", 13);
263 (*outputFunc
)(outputStream
, "currentdict end\n", 16);
265 // start the binary section
266 (*outputFunc
)(outputStream
, "currentfile eexec\n", 18);
267 eb
.outputFunc
= outputFunc
;
268 eb
.outputStream
= outputStream
;
273 // write the private dictionary
274 eexecWrite(&eb
, "\x83\xca\x73\xd5");
275 eexecWrite(&eb
, "dup /Private 32 dict dup begin\n");
276 eexecWrite(&eb
, "/RD {string currentfile exch readstring pop}"
277 " executeonly def\n");
278 eexecWrite(&eb
, "/ND {noaccess def} executeonly def\n");
279 eexecWrite(&eb
, "/NP {noaccess put} executeonly def\n");
280 eexecWrite(&eb
, "/MinFeature {16 16} def\n");
281 eexecWrite(&eb
, "/password 5839 def\n");
282 if (privateDicts
[0].nBlueValues
) {
283 eexecWrite(&eb
, "/BlueValues [");
284 for (i
= 0; i
< privateDicts
[0].nBlueValues
; ++i
) {
285 buf
= GString::format("{0:s}{1:d}",
286 i
> 0 ? " " : "", privateDicts
[0].blueValues
[i
]);
287 eexecWrite(&eb
, buf
->getCString());
290 eexecWrite(&eb
, "] def\n");
292 if (privateDicts
[0].nOtherBlues
) {
293 eexecWrite(&eb
, "/OtherBlues [");
294 for (i
= 0; i
< privateDicts
[0].nOtherBlues
; ++i
) {
295 buf
= GString::format("{0:s}{1:d}",
296 i
> 0 ? " " : "", privateDicts
[0].otherBlues
[i
]);
297 eexecWrite(&eb
, buf
->getCString());
300 eexecWrite(&eb
, "] def\n");
302 if (privateDicts
[0].nFamilyBlues
) {
303 eexecWrite(&eb
, "/FamilyBlues [");
304 for (i
= 0; i
< privateDicts
[0].nFamilyBlues
; ++i
) {
305 buf
= GString::format("{0:s}{1:d}",
306 i
> 0 ? " " : "", privateDicts
[0].familyBlues
[i
]);
307 eexecWrite(&eb
, buf
->getCString());
310 eexecWrite(&eb
, "] def\n");
312 if (privateDicts
[0].nFamilyOtherBlues
) {
313 eexecWrite(&eb
, "/FamilyOtherBlues [");
314 for (i
= 0; i
< privateDicts
[0].nFamilyOtherBlues
; ++i
) {
315 buf
= GString::format("{0:s}{1:d}", i
> 0 ? " " : "",
316 privateDicts
[0].familyOtherBlues
[i
]);
317 eexecWrite(&eb
, buf
->getCString());
320 eexecWrite(&eb
, "] def\n");
322 if (privateDicts
[0].blueScale
!= 0.039625) {
323 buf
= GString::format("/BlueScale {0:.4g} def\n",
324 privateDicts
[0].blueScale
);
325 eexecWrite(&eb
, buf
->getCString());
328 if (privateDicts
[0].blueShift
!= 7) {
329 buf
= GString::format("/BlueShift {0:d} def\n", privateDicts
[0].blueShift
);
330 eexecWrite(&eb
, buf
->getCString());
333 if (privateDicts
[0].blueFuzz
!= 1) {
334 buf
= GString::format("/BlueFuzz {0:d} def\n", privateDicts
[0].blueFuzz
);
335 eexecWrite(&eb
, buf
->getCString());
338 if (privateDicts
[0].hasStdHW
) {
339 buf
= GString::format("/StdHW [{0:.4g}] def\n", privateDicts
[0].stdHW
);
340 eexecWrite(&eb
, buf
->getCString());
343 if (privateDicts
[0].hasStdVW
) {
344 buf
= GString::format("/StdVW [{0:.4g}] def\n", privateDicts
[0].stdVW
);
345 eexecWrite(&eb
, buf
->getCString());
348 if (privateDicts
[0].nStemSnapH
) {
349 eexecWrite(&eb
, "/StemSnapH [");
350 for (i
= 0; i
< privateDicts
[0].nStemSnapH
; ++i
) {
351 buf
= GString::format("{0:s}{1:.4g}",
352 i
> 0 ? " " : "", privateDicts
[0].stemSnapH
[i
]);
353 eexecWrite(&eb
, buf
->getCString());
356 eexecWrite(&eb
, "] def\n");
358 if (privateDicts
[0].nStemSnapV
) {
359 eexecWrite(&eb
, "/StemSnapV [");
360 for (i
= 0; i
< privateDicts
[0].nStemSnapV
; ++i
) {
361 buf
= GString::format("{0:s}{1:.4g}",
362 i
> 0 ? " " : "", privateDicts
[0].stemSnapV
[i
]);
363 eexecWrite(&eb
, buf
->getCString());
366 eexecWrite(&eb
, "] def\n");
368 if (privateDicts
[0].hasForceBold
) {
369 buf
= GString::format("/ForceBold {0:s} def\n",
370 privateDicts
[0].forceBold
? "true" : "false");
371 eexecWrite(&eb
, buf
->getCString());
374 if (privateDicts
[0].forceBoldThreshold
!= 0) {
375 buf
= GString::format("/ForceBoldThreshold {0:.4g} def\n",
376 privateDicts
[0].forceBoldThreshold
);
377 eexecWrite(&eb
, buf
->getCString());
380 if (privateDicts
[0].languageGroup
!= 0) {
381 buf
= GString::format("/LanguageGroup {0:d} def\n",
382 privateDicts
[0].languageGroup
);
383 eexecWrite(&eb
, buf
->getCString());
386 if (privateDicts
[0].expansionFactor
!= 0.06) {
387 buf
= GString::format("/ExpansionFactor {0:.4g} def\n",
388 privateDicts
[0].expansionFactor
);
389 eexecWrite(&eb
, buf
->getCString());
393 // set up subroutines
395 getIndex(privateDicts
[0].subrsOffset
, &subrIdx
, &ok
);
400 // write the CharStrings
401 buf
= GString::format("2 index /CharStrings {0:d} dict dup begin\n",
403 eexecWrite(&eb
, buf
->getCString());
405 for (i
= 0; i
< nGlyphs
; ++i
) {
407 getIndexVal(&charStringsIdx
, i
, &val
, &ok
);
409 getString(charset
[i
], buf2
, &ok
);
411 eexecCvtGlyph(&eb
, buf2
, val
.pos
, val
.len
, &subrIdx
, &privateDicts
[0]);
415 eexecWrite(&eb
, "end\n");
416 eexecWrite(&eb
, "end\n");
417 eexecWrite(&eb
, "readonly put\n");
418 eexecWrite(&eb
, "noaccess put\n");
419 eexecWrite(&eb
, "dup /FontName get exch definefont pop\n");
420 eexecWrite(&eb
, "mark currentfile closefile\n");
423 if (ascii
&& eb
.line
> 0) {
424 (*outputFunc
)(outputStream
, "\n", 1);
426 for (i
= 0; i
< 8; ++i
) {
427 (*outputFunc
)(outputStream
, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
429 (*outputFunc
)(outputStream
, "cleartomark\n", 12);
432 void FoFiType1C::convertToCIDType0(char *psName
,
433 FoFiOutputFunc outputFunc
,
434 void *outputStream
) {
436 GString
*charStrings
;
437 int *charStringOffsets
;
444 int gid
, offset
, n
, i
, j
, k
;
446 // compute the CID count and build the CID-to-GID mapping
448 for (i
= 0; i
< nGlyphs
; ++i
) {
449 if (charset
[i
] >= nCIDs
) {
450 nCIDs
= charset
[i
] + 1;
453 cidMap
= (int *)gmallocn(nCIDs
, sizeof(int));
454 for (i
= 0; i
< nCIDs
; ++i
) {
457 for (i
= 0; i
< nGlyphs
; ++i
) {
458 cidMap
[charset
[i
]] = i
;
461 // build the charstrings
462 charStrings
= new GString();
463 charStringOffsets
= (int *)gmallocn(nCIDs
+ 1, sizeof(int));
464 for (i
= 0; i
< nCIDs
; ++i
) {
465 charStringOffsets
[i
] = charStrings
->getLength();
466 if ((gid
= cidMap
[i
]) >= 0) {
468 getIndexVal(&charStringsIdx
, gid
, &val
, &ok
);
470 getIndex(privateDicts
[fdSelect
[gid
]].subrsOffset
, &subrIdx
, &ok
);
474 cvtGlyph(val
.pos
, val
.len
, charStrings
,
475 &subrIdx
, &privateDicts
[fdSelect
[gid
]], gTrue
);
479 charStringOffsets
[nCIDs
] = charStrings
->getLength();
481 // compute gdBytes = number of bytes needed for charstring offsets
482 // (offset size needs to account for the charstring offset table,
483 // with a worst case of five bytes per entry, plus the charstrings
485 i
= (nCIDs
+ 1) * 5 + charStrings
->getLength();
488 } else if (i
< 0x10000) {
490 } else if (i
< 0x1000000) {
496 // begin the font dictionary
497 (*outputFunc
)(outputStream
, "/CIDInit /ProcSet findresource begin\n", 37);
498 (*outputFunc
)(outputStream
, "20 dict begin\n", 14);
499 (*outputFunc
)(outputStream
, "/CIDFontName /", 14);
500 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
501 (*outputFunc
)(outputStream
, " def\n", 5);
502 (*outputFunc
)(outputStream
, "/CIDFontType 0 def\n", 19);
503 (*outputFunc
)(outputStream
, "/CIDSystemInfo 3 dict dup begin\n", 32);
504 if (topDict
.registrySID
> 0 && topDict
.orderingSID
> 0) {
506 getString(topDict
.registrySID
, buf2
, &ok
);
508 (*outputFunc
)(outputStream
, " /Registry (", 13);
509 (*outputFunc
)(outputStream
, buf2
, strlen(buf2
));
510 (*outputFunc
)(outputStream
, ") def\n", 6);
513 getString(topDict
.orderingSID
, buf2
, &ok
);
515 (*outputFunc
)(outputStream
, " /Ordering (", 13);
516 (*outputFunc
)(outputStream
, buf2
, strlen(buf2
));
517 (*outputFunc
)(outputStream
, ") def\n", 6);
520 (*outputFunc
)(outputStream
, " /Registry (Adobe) def\n", 24);
521 (*outputFunc
)(outputStream
, " /Ordering (Identity) def\n", 27);
523 buf
= GString::format(" /Supplement {0:d} def\n", topDict
.supplement
);
524 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
526 (*outputFunc
)(outputStream
, "end def\n", 8);
527 if (topDict
.hasFontMatrix
) {
528 buf
= GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
529 topDict
.fontMatrix
[0], topDict
.fontMatrix
[1],
530 topDict
.fontMatrix
[2], topDict
.fontMatrix
[3],
531 topDict
.fontMatrix
[4], topDict
.fontMatrix
[5]);
532 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
534 } else if (privateDicts
[0].hasFontMatrix
) {
535 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
537 (*outputFunc
)(outputStream
,
538 "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
540 buf
= GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
541 topDict
.fontBBox
[0], topDict
.fontBBox
[1],
542 topDict
.fontBBox
[2], topDict
.fontBBox
[3]);
543 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
545 (*outputFunc
)(outputStream
, "/FontInfo 1 dict dup begin\n", 27);
546 (*outputFunc
)(outputStream
, " /FSType 8 def\n", 16);
547 (*outputFunc
)(outputStream
, "end def\n", 8);
549 // CIDFont-specific entries
550 buf
= GString::format("/CIDCount {0:d} def\n", nCIDs
);
551 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
553 (*outputFunc
)(outputStream
, "/FDBytes 1 def\n", 15);
554 buf
= GString::format("/GDBytes {0:d} def\n", gdBytes
);
555 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
557 (*outputFunc
)(outputStream
, "/CIDMapOffset 0 def\n", 20);
558 if (topDict
.paintType
!= 0) {
559 buf
= GString::format("/PaintType {0:d} def\n", topDict
.paintType
);
560 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
562 buf
= GString::format("/StrokeWidth {0:.4g} def\n", topDict
.strokeWidth
);
563 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
568 buf
= GString::format("/FDArray {0:d} array\n", nFDs
);
569 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
571 for (i
= 0; i
< nFDs
; ++i
) {
572 buf
= GString::format("dup {0:d} 10 dict begin\n", i
);
573 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
575 (*outputFunc
)(outputStream
, "/FontType 1 def\n", 16);
576 if (privateDicts
[i
].hasFontMatrix
) {
577 buf
= GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
578 privateDicts
[i
].fontMatrix
[0],
579 privateDicts
[i
].fontMatrix
[1],
580 privateDicts
[i
].fontMatrix
[2],
581 privateDicts
[i
].fontMatrix
[3],
582 privateDicts
[i
].fontMatrix
[4],
583 privateDicts
[i
].fontMatrix
[5]);
584 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
587 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
589 buf
= GString::format("/PaintType {0:d} def\n", topDict
.paintType
);
590 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
592 (*outputFunc
)(outputStream
, "/Private 32 dict begin\n", 23);
593 if (privateDicts
[i
].nBlueValues
) {
594 (*outputFunc
)(outputStream
, "/BlueValues [", 13);
595 for (j
= 0; j
< privateDicts
[i
].nBlueValues
; ++j
) {
596 buf
= GString::format("{0:s}{1:d}",
597 j
> 0 ? " " : "", privateDicts
[i
].blueValues
[j
]);
598 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
601 (*outputFunc
)(outputStream
, "] def\n", 6);
603 if (privateDicts
[i
].nOtherBlues
) {
604 (*outputFunc
)(outputStream
, "/OtherBlues [", 13);
605 for (j
= 0; j
< privateDicts
[i
].nOtherBlues
; ++j
) {
606 buf
= GString::format("{0:s}{1:d}",
607 j
> 0 ? " " : "", privateDicts
[i
].otherBlues
[j
]);
608 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
611 (*outputFunc
)(outputStream
, "] def\n", 6);
613 if (privateDicts
[i
].nFamilyBlues
) {
614 (*outputFunc
)(outputStream
, "/FamilyBlues [", 14);
615 for (j
= 0; j
< privateDicts
[i
].nFamilyBlues
; ++j
) {
616 buf
= GString::format("{0:s}{1:d}",
618 privateDicts
[i
].familyBlues
[j
]);
619 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
622 (*outputFunc
)(outputStream
, "] def\n", 6);
624 if (privateDicts
[i
].nFamilyOtherBlues
) {
625 (*outputFunc
)(outputStream
, "/FamilyOtherBlues [", 19);
626 for (j
= 0; j
< privateDicts
[i
].nFamilyOtherBlues
; ++j
) {
627 buf
= GString::format("{0:s}{1:d}", j
> 0 ? " " : "",
628 privateDicts
[i
].familyOtherBlues
[j
]);
629 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
632 (*outputFunc
)(outputStream
, "] def\n", 6);
634 if (privateDicts
[i
].blueScale
!= 0.039625) {
635 buf
= GString::format("/BlueScale {0:.4g} def\n",
636 privateDicts
[i
].blueScale
);
637 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
640 if (privateDicts
[i
].blueShift
!= 7) {
641 buf
= GString::format("/BlueShift {0:d} def\n",
642 privateDicts
[i
].blueShift
);
643 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
646 if (privateDicts
[i
].blueFuzz
!= 1) {
647 buf
= GString::format("/BlueFuzz {0:d} def\n", privateDicts
[i
].blueFuzz
);
648 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
651 if (privateDicts
[i
].hasStdHW
) {
652 buf
= GString::format("/StdHW [{0:.4g}] def\n", privateDicts
[i
].stdHW
);
653 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
656 if (privateDicts
[i
].hasStdVW
) {
657 buf
= GString::format("/StdVW [{0:.4g}] def\n", privateDicts
[i
].stdVW
);
658 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
661 if (privateDicts
[i
].nStemSnapH
) {
662 (*outputFunc
)(outputStream
, "/StemSnapH [", 12);
663 for (j
= 0; j
< privateDicts
[i
].nStemSnapH
; ++j
) {
664 buf
= GString::format("{0:s}{1:.4g}",
665 j
> 0 ? " " : "", privateDicts
[i
].stemSnapH
[j
]);
666 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
669 (*outputFunc
)(outputStream
, "] def\n", 6);
671 if (privateDicts
[i
].nStemSnapV
) {
672 (*outputFunc
)(outputStream
, "/StemSnapV [", 12);
673 for (j
= 0; j
< privateDicts
[i
].nStemSnapV
; ++j
) {
674 buf
= GString::format("{0:s}{1:.4g}",
675 j
> 0 ? " " : "", privateDicts
[i
].stemSnapV
[j
]);
676 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
679 (*outputFunc
)(outputStream
, "] def\n", 6);
681 if (privateDicts
[i
].hasForceBold
) {
682 buf
= GString::format("/ForceBold {0:s} def\n",
683 privateDicts
[i
].forceBold
? "true" : "false");
684 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
687 if (privateDicts
[i
].forceBoldThreshold
!= 0) {
688 buf
= GString::format("/ForceBoldThreshold {0:.4g} def\n",
689 privateDicts
[i
].forceBoldThreshold
);
690 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
693 if (privateDicts
[i
].languageGroup
!= 0) {
694 buf
= GString::format("/LanguageGroup {0:d} def\n",
695 privateDicts
[i
].languageGroup
);
696 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
699 if (privateDicts
[i
].expansionFactor
!= 0.06) {
700 buf
= GString::format("/ExpansionFactor {0:.4g} def\n",
701 privateDicts
[i
].expansionFactor
);
702 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
705 (*outputFunc
)(outputStream
, "currentdict end def\n", 20);
706 (*outputFunc
)(outputStream
, "currentdict end put\n", 20);
708 (*outputFunc
)(outputStream
, "def\n", 4);
710 // start the binary section
711 offset
= (nCIDs
+ 1) * (1 + gdBytes
);
712 buf
= GString::format("(Hex) {0:d} StartData\n",
713 offset
+ charStrings
->getLength());
714 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
717 // write the charstring offset (CIDMap) table
718 for (i
= 0; i
<= nCIDs
; i
+= 6) {
719 for (j
= 0; j
< 6 && i
+j
<= nCIDs
; ++j
) {
720 if (i
+j
< nCIDs
&& cidMap
[i
+j
] >= 0) {
721 buf2
[0] = (char)fdSelect
[cidMap
[i
+j
]];
725 n
= offset
+ charStringOffsets
[i
+j
];
726 for (k
= gdBytes
; k
>= 1; --k
) {
727 buf2
[k
] = (char)(n
& 0xff);
730 for (k
= 0; k
<= gdBytes
; ++k
) {
731 buf
= GString::format("{0:02x}", buf2
[k
] & 0xff);
732 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
736 (*outputFunc
)(outputStream
, "\n", 1);
739 // write the charstring data
740 n
= charStrings
->getLength();
741 for (i
= 0; i
< n
; i
+= 32) {
742 for (j
= 0; j
< 32 && i
+j
< n
; ++j
) {
743 buf
= GString::format("{0:02x}", charStrings
->getChar(i
+j
) & 0xff);
744 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
748 (*outputFunc
)(outputStream
, ">", 1);
750 (*outputFunc
)(outputStream
, "\n", 1);
753 gfree(charStringOffsets
);
758 void FoFiType1C::convertToType0(char *psName
,
759 FoFiOutputFunc outputFunc
,
760 void *outputStream
) {
770 // compute the CID count and build the CID-to-GID mapping
772 for (i
= 0; i
< nGlyphs
; ++i
) {
773 if (charset
[i
] >= nCIDs
) {
774 nCIDs
= charset
[i
] + 1;
777 cidMap
= (int *)gmallocn(nCIDs
, sizeof(int));
778 for (i
= 0; i
< nCIDs
; ++i
) {
781 for (i
= 0; i
< nGlyphs
; ++i
) {
782 cidMap
[charset
[i
]] = i
;
785 // write the descendant Type 1 fonts
786 for (i
= 0; i
< nCIDs
; i
+= 256) {
788 //~ this assumes that all CIDs in this block have the same FD --
789 //~ to handle multiple FDs correctly, need to somehow divide the
790 //~ font up by FD; as a kludge we ignore CID 0, which is .notdef
792 for (j
= i
==0 ? 1 : 0; j
< 256 && i
+j
< nCIDs
; ++j
) {
793 if (cidMap
[i
+j
] >= 0) {
794 fd
= fdSelect
[cidMap
[i
+j
]];
799 // font dictionary (unencrypted section)
800 (*outputFunc
)(outputStream
, "16 dict begin\n", 14);
801 (*outputFunc
)(outputStream
, "/FontName /", 11);
802 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
803 buf
= GString::format("_{0:02x} def\n", i
>> 8);
804 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
806 (*outputFunc
)(outputStream
, "/FontType 1 def\n", 16);
807 if (privateDicts
[fd
].hasFontMatrix
) {
808 buf
= GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
809 privateDicts
[fd
].fontMatrix
[0],
810 privateDicts
[fd
].fontMatrix
[1],
811 privateDicts
[fd
].fontMatrix
[2],
812 privateDicts
[fd
].fontMatrix
[3],
813 privateDicts
[fd
].fontMatrix
[4],
814 privateDicts
[fd
].fontMatrix
[5]);
815 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
817 } else if (topDict
.hasFontMatrix
) {
818 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
820 (*outputFunc
)(outputStream
,
821 "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
823 buf
= GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
824 topDict
.fontBBox
[0], topDict
.fontBBox
[1],
825 topDict
.fontBBox
[2], topDict
.fontBBox
[3]);
826 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
828 buf
= GString::format("/PaintType {0:d} def\n", topDict
.paintType
);
829 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
831 if (topDict
.paintType
!= 0) {
832 buf
= GString::format("/StrokeWidth {0:.4g} def\n", topDict
.strokeWidth
);
833 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
836 (*outputFunc
)(outputStream
, "/Encoding 256 array\n", 20);
837 for (j
= 0; j
< 256 && i
+j
< nCIDs
; ++j
) {
838 buf
= GString::format("dup {0:d} /c{1:02x} put\n", j
, j
);
839 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
843 buf
= GString::format("{0:d} 1 255 {{ 1 index exch /.notdef put }} for\n",
845 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
848 (*outputFunc
)(outputStream
, "readonly def\n", 13);
849 (*outputFunc
)(outputStream
, "currentdict end\n", 16);
851 // start the binary section
852 (*outputFunc
)(outputStream
, "currentfile eexec\n", 18);
853 eb
.outputFunc
= outputFunc
;
854 eb
.outputStream
= outputStream
;
859 // start the private dictionary
860 eexecWrite(&eb
, "\x83\xca\x73\xd5");
861 eexecWrite(&eb
, "dup /Private 32 dict dup begin\n");
862 eexecWrite(&eb
, "/RD {string currentfile exch readstring pop}"
863 " executeonly def\n");
864 eexecWrite(&eb
, "/ND {noaccess def} executeonly def\n");
865 eexecWrite(&eb
, "/NP {noaccess put} executeonly def\n");
866 eexecWrite(&eb
, "/MinFeature {16 16} def\n");
867 eexecWrite(&eb
, "/password 5839 def\n");
868 if (privateDicts
[fd
].nBlueValues
) {
869 eexecWrite(&eb
, "/BlueValues [");
870 for (k
= 0; k
< privateDicts
[fd
].nBlueValues
; ++k
) {
871 buf
= GString::format("{0:s}{1:d}",
873 privateDicts
[fd
].blueValues
[k
]);
874 eexecWrite(&eb
, buf
->getCString());
877 eexecWrite(&eb
, "] def\n");
879 if (privateDicts
[fd
].nOtherBlues
) {
880 eexecWrite(&eb
, "/OtherBlues [");
881 for (k
= 0; k
< privateDicts
[fd
].nOtherBlues
; ++k
) {
882 buf
= GString::format("{0:s}{1:d}",
884 privateDicts
[fd
].otherBlues
[k
]);
885 eexecWrite(&eb
, buf
->getCString());
888 eexecWrite(&eb
, "] def\n");
890 if (privateDicts
[fd
].nFamilyBlues
) {
891 eexecWrite(&eb
, "/FamilyBlues [");
892 for (k
= 0; k
< privateDicts
[fd
].nFamilyBlues
; ++k
) {
893 buf
= GString::format("{0:s}{1:d}", k
> 0 ? " " : "",
894 privateDicts
[fd
].familyBlues
[k
]);
895 eexecWrite(&eb
, buf
->getCString());
898 eexecWrite(&eb
, "] def\n");
900 if (privateDicts
[fd
].nFamilyOtherBlues
) {
901 eexecWrite(&eb
, "/FamilyOtherBlues [");
902 for (k
= 0; k
< privateDicts
[fd
].nFamilyOtherBlues
; ++k
) {
903 buf
= GString::format("{0:s}{1:d}", k
> 0 ? " " : "",
904 privateDicts
[fd
].familyOtherBlues
[k
]);
905 eexecWrite(&eb
, buf
->getCString());
908 eexecWrite(&eb
, "] def\n");
910 if (privateDicts
[fd
].blueScale
!= 0.039625) {
911 buf
= GString::format("/BlueScale {0:.4g} def\n",
912 privateDicts
[fd
].blueScale
);
913 eexecWrite(&eb
, buf
->getCString());
916 if (privateDicts
[fd
].blueShift
!= 7) {
917 buf
= GString::format("/BlueShift {0:d} def\n",
918 privateDicts
[fd
].blueShift
);
919 eexecWrite(&eb
, buf
->getCString());
922 if (privateDicts
[fd
].blueFuzz
!= 1) {
923 buf
= GString::format("/BlueFuzz {0:d} def\n",
924 privateDicts
[fd
].blueFuzz
);
925 eexecWrite(&eb
, buf
->getCString());
928 if (privateDicts
[fd
].hasStdHW
) {
929 buf
= GString::format("/StdHW [{0:.4g}] def\n", privateDicts
[fd
].stdHW
);
930 eexecWrite(&eb
, buf
->getCString());
933 if (privateDicts
[fd
].hasStdVW
) {
934 buf
= GString::format("/StdVW [{0:.4g}] def\n", privateDicts
[fd
].stdVW
);
935 eexecWrite(&eb
, buf
->getCString());
938 if (privateDicts
[fd
].nStemSnapH
) {
939 eexecWrite(&eb
, "/StemSnapH [");
940 for (k
= 0; k
< privateDicts
[fd
].nStemSnapH
; ++k
) {
941 buf
= GString::format("{0:s}{1:.4g}",
942 k
> 0 ? " " : "", privateDicts
[fd
].stemSnapH
[k
]);
943 eexecWrite(&eb
, buf
->getCString());
946 eexecWrite(&eb
, "] def\n");
948 if (privateDicts
[fd
].nStemSnapV
) {
949 eexecWrite(&eb
, "/StemSnapV [");
950 for (k
= 0; k
< privateDicts
[fd
].nStemSnapV
; ++k
) {
951 buf
= GString::format("{0:s}{1:.4g}",
952 k
> 0 ? " " : "", privateDicts
[fd
].stemSnapV
[k
]);
953 eexecWrite(&eb
, buf
->getCString());
956 eexecWrite(&eb
, "] def\n");
958 if (privateDicts
[fd
].hasForceBold
) {
959 buf
= GString::format("/ForceBold {0:s} def\n",
960 privateDicts
[fd
].forceBold
? "true" : "false");
961 eexecWrite(&eb
, buf
->getCString());
964 if (privateDicts
[fd
].forceBoldThreshold
!= 0) {
965 buf
= GString::format("/ForceBoldThreshold {0:.4g} def\n",
966 privateDicts
[fd
].forceBoldThreshold
);
967 eexecWrite(&eb
, buf
->getCString());
970 if (privateDicts
[fd
].languageGroup
!= 0) {
971 buf
= GString::format("/LanguageGroup {0:d} def\n",
972 privateDicts
[fd
].languageGroup
);
973 eexecWrite(&eb
, buf
->getCString());
976 if (privateDicts
[fd
].expansionFactor
!= 0.06) {
977 buf
= GString::format("/ExpansionFactor {0:.4g} def\n",
978 privateDicts
[fd
].expansionFactor
);
979 eexecWrite(&eb
, buf
->getCString());
983 // set up the subroutines
985 getIndex(privateDicts
[fd
].subrsOffset
, &subrIdx
, &ok
);
990 // start the CharStrings
991 eexecWrite(&eb
, "2 index /CharStrings 256 dict dup begin\n");
993 // write the .notdef CharString
995 getIndexVal(&charStringsIdx
, 0, &val
, &ok
);
997 eexecCvtGlyph(&eb
, ".notdef", val
.pos
, val
.len
,
998 &subrIdx
, &privateDicts
[fd
]);
1001 // write the CharStrings
1002 for (j
= 0; j
< 256 && i
+j
< nCIDs
; ++j
) {
1003 if (cidMap
[i
+j
] >= 0) {
1005 getIndexVal(&charStringsIdx
, cidMap
[i
+j
], &val
, &ok
);
1007 buf
= GString::format("c{0:02x}", j
);
1008 eexecCvtGlyph(&eb
, buf
->getCString(), val
.pos
, val
.len
,
1009 &subrIdx
, &privateDicts
[fd
]);
1014 eexecWrite(&eb
, "end\n");
1015 eexecWrite(&eb
, "end\n");
1016 eexecWrite(&eb
, "readonly put\n");
1017 eexecWrite(&eb
, "noaccess put\n");
1018 eexecWrite(&eb
, "dup /FontName get exch definefont pop\n");
1019 eexecWrite(&eb
, "mark currentfile closefile\n");
1023 (*outputFunc
)(outputStream
, "\n", 1);
1025 for (j
= 0; j
< 8; ++j
) {
1026 (*outputFunc
)(outputStream
, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
1028 (*outputFunc
)(outputStream
, "cleartomark\n", 12);
1031 // write the Type 0 parent font
1032 (*outputFunc
)(outputStream
, "16 dict begin\n", 14);
1033 (*outputFunc
)(outputStream
, "/FontName /", 11);
1034 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
1035 (*outputFunc
)(outputStream
, " def\n", 5);
1036 (*outputFunc
)(outputStream
, "/FontType 0 def\n", 16);
1037 if (topDict
.hasFontMatrix
) {
1038 buf
= GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
1039 topDict
.fontMatrix
[0], topDict
.fontMatrix
[1],
1040 topDict
.fontMatrix
[2], topDict
.fontMatrix
[3],
1041 topDict
.fontMatrix
[4], topDict
.fontMatrix
[5]);
1042 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
1045 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
1047 (*outputFunc
)(outputStream
, "/FMapType 2 def\n", 16);
1048 (*outputFunc
)(outputStream
, "/Encoding [\n", 12);
1049 for (i
= 0; i
< nCIDs
; i
+= 256) {
1050 buf
= GString::format("{0:d}\n", i
>> 8);
1051 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
1054 (*outputFunc
)(outputStream
, "] def\n", 6);
1055 (*outputFunc
)(outputStream
, "/FDepVector [\n", 14);
1056 for (i
= 0; i
< nCIDs
; i
+= 256) {
1057 (*outputFunc
)(outputStream
, "/", 1);
1058 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
1059 buf
= GString::format("_{0:02x} findfont\n", i
>> 8);
1060 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
1063 (*outputFunc
)(outputStream
, "] def\n", 6);
1064 (*outputFunc
)(outputStream
, "FontName currentdict end definefont pop\n", 40);
1069 void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf
*eb
, char *glyphName
,
1070 int offset
, int nBytes
,
1071 Type1CIndex
*subrIdx
,
1072 Type1CPrivateDict
*pDict
) {
1076 // generate the charstring
1077 charBuf
= new GString();
1078 cvtGlyph(offset
, nBytes
, charBuf
, subrIdx
, pDict
, gTrue
);
1080 buf
= GString::format("/{0:s} {1:d} RD ", glyphName
, charBuf
->getLength());
1081 eexecWrite(eb
, buf
->getCString());
1083 eexecWriteCharstring(eb
, (Guchar
*)charBuf
->getCString(),
1084 charBuf
->getLength());
1085 eexecWrite(eb
, " ND\n");
1090 void FoFiType1C::cvtGlyph(int offset
, int nBytes
, GString
*charBuf
,
1091 Type1CIndex
*subrIdx
, Type1CPrivateDict
*pDict
,
1098 int pos
, subrBias
, start
, i
, k
;
1100 start
= charBuf
->getLength();
1102 charBuf
->append((char)73);
1103 charBuf
->append((char)58);
1104 charBuf
->append((char)147);
1105 charBuf
->append((char)134);
1113 while (pos
< offset
+ nBytes
) {
1115 pos
= getOp(pos
, gTrue
, &ok
);
1119 if (!ops
[nOps
- 1].isNum
) {
1120 --nOps
; // drop the operator
1121 switch (ops
[nOps
].op
) {
1122 case 0x0001: // hstem
1124 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1128 //~ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
1132 for (k
= 0; k
< nOps
; k
+= 2) {
1133 // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1134 if (ops
[k
+1].num
< 0) {
1135 d
+= ops
[k
].num
+ ops
[k
+1].num
;
1136 dFP
|= ops
[k
].isFP
| ops
[k
+1].isFP
;
1137 cvtNum(d
, dFP
, charBuf
);
1138 cvtNum(-ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1142 cvtNum(d
, dFP
, charBuf
);
1143 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1145 dFP
|= ops
[k
+1].isFP
;
1147 charBuf
->append((char)1);
1152 case 0x0003: // vstem
1154 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1158 //~ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
1162 for (k
= 0; k
< nOps
; k
+= 2) {
1163 // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1164 if (ops
[k
+1].num
< 0) {
1165 d
+= ops
[k
].num
+ ops
[k
+1].num
;
1166 dFP
|= ops
[k
].isFP
| ops
[k
+1].isFP
;
1167 cvtNum(d
, dFP
, charBuf
);
1168 cvtNum(-ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1172 cvtNum(d
, dFP
, charBuf
);
1173 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1175 dFP
|= ops
[k
+1].isFP
;
1177 charBuf
->append((char)3);
1182 case 0x0004: // vmoveto
1184 cvtGlyphWidth(nOps
== 2, charBuf
, pDict
);
1188 charBuf
->append((char)9);
1192 //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1194 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1195 charBuf
->append((char)4);
1198 case 0x0005: // rlineto
1199 if (nOps
< 2 || nOps
% 2 != 0) {
1200 //~ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1202 for (k
= 0; k
< nOps
; k
+= 2) {
1203 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1204 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1205 charBuf
->append((char)5);
1210 case 0x0006: // hlineto
1212 //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1214 for (k
= 0; k
< nOps
; ++k
) {
1215 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1216 charBuf
->append((char)((k
& 1) ? 7 : 6));
1221 case 0x0007: // vlineto
1223 //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1225 for (k
= 0; k
< nOps
; ++k
) {
1226 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1227 charBuf
->append((char)((k
& 1) ? 6 : 7));
1232 case 0x0008: // rrcurveto
1233 if (nOps
< 6 || nOps
% 6 != 0) {
1234 //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1236 for (k
= 0; k
< nOps
; k
+= 6) {
1237 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1238 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1239 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1240 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1241 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1242 cvtNum(ops
[k
+5].num
, ops
[k
+5].isFP
, charBuf
);
1243 charBuf
->append((char)8);
1248 case 0x000a: // callsubr
1250 subrBias
= (subrIdx
->len
< 1240)
1251 ? 107 : (subrIdx
->len
< 33900) ? 1131 : 32768;
1252 k
= subrBias
+ (int)ops
[nOps
- 1].num
;
1255 getIndexVal(subrIdx
, k
, &val
, &ok
);
1257 cvtGlyph(val
.pos
, val
.len
, charBuf
, subrIdx
, pDict
, gFalse
);
1260 //~ error(-1, "Too few args to Type 2 callsubr");
1262 // don't clear the stack
1264 case 0x000b: // return
1265 // don't clear the stack
1267 case 0x000e: // endchar / seac
1269 cvtGlyphWidth(nOps
== 1 || nOps
== 5, charBuf
, pDict
);
1273 charBuf
->append((char)9);
1277 cvtNum(0, gFalse
, charBuf
);
1278 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1279 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1280 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1281 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1282 charBuf
->append((char)12)->append((char)6);
1283 } else if (nOps
== 0) {
1284 charBuf
->append((char)14);
1286 //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1290 case 0x000f: // (obsolete)
1291 // this op is ignored, but we need the glyph width
1293 cvtGlyphWidth(nOps
> 0, charBuf
, pDict
);
1298 case 0x0010: // blend
1299 //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
1302 case 0x0012: // hstemhm
1305 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1309 //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1314 case 0x0013: // hintmask
1317 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1322 //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1327 pos
+= (nHints
+ 7) >> 3;
1330 case 0x0014: // cntrmask
1333 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1338 //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1343 pos
+= (nHints
+ 7) >> 3;
1346 case 0x0015: // rmoveto
1348 cvtGlyphWidth(nOps
== 3, charBuf
, pDict
);
1352 charBuf
->append((char)9);
1356 //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1358 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1359 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1360 charBuf
->append((char)21);
1363 case 0x0016: // hmoveto
1365 cvtGlyphWidth(nOps
== 2, charBuf
, pDict
);
1369 charBuf
->append((char)9);
1373 //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1375 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1376 charBuf
->append((char)22);
1379 case 0x0017: // vstemhm
1382 cvtGlyphWidth(nOps
& 1, charBuf
, pDict
);
1386 //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1391 case 0x0018: // rcurveline
1392 if (nOps
< 8 || (nOps
- 2) % 6 != 0) {
1393 //~ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1395 for (k
= 0; k
< nOps
- 2; k
+= 6) {
1396 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1397 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1398 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1399 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1400 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1401 cvtNum(ops
[k
+5].num
, ops
[k
+5].isFP
, charBuf
);
1402 charBuf
->append((char)8);
1404 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1405 cvtNum(ops
[k
+1].num
, ops
[k
].isFP
, charBuf
);
1406 charBuf
->append((char)5);
1410 case 0x0019: // rlinecurve
1411 if (nOps
< 8 || (nOps
- 6) % 2 != 0) {
1412 //~ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1414 for (k
= 0; k
< nOps
- 6; k
+= 2) {
1415 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1416 cvtNum(ops
[k
+1].num
, ops
[k
].isFP
, charBuf
);
1417 charBuf
->append((char)5);
1419 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1420 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1421 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1422 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1423 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1424 cvtNum(ops
[k
+5].num
, ops
[k
+5].isFP
, charBuf
);
1425 charBuf
->append((char)8);
1429 case 0x001a: // vvcurveto
1430 if (nOps
< 4 || !(nOps
% 4 == 0 || (nOps
-1) % 4 == 0)) {
1431 //~ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1433 if (nOps
% 2 == 1) {
1434 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1435 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1436 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1437 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1438 cvtNum(0, gFalse
, charBuf
);
1439 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1440 charBuf
->append((char)8);
1445 for (; k
< nOps
; k
+= 4) {
1446 cvtNum(0, gFalse
, charBuf
);
1447 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1448 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1449 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1450 cvtNum(0, gFalse
, charBuf
);
1451 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1452 charBuf
->append((char)8);
1457 case 0x001b: // hhcurveto
1458 if (nOps
< 4 || !(nOps
% 4 == 0 || (nOps
-1) % 4 == 0)) {
1459 //~ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1461 if (nOps
% 2 == 1) {
1462 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1463 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1464 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1465 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1466 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1467 cvtNum(0, gFalse
, charBuf
);
1468 charBuf
->append((char)8);
1473 for (; k
< nOps
; k
+= 4) {
1474 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1475 cvtNum(0, gFalse
, charBuf
);
1476 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1477 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1478 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1479 cvtNum(0, gFalse
, charBuf
);
1480 charBuf
->append((char)8);
1485 case 0x001d: // callgsubr
1487 k
= gsubrBias
+ (int)ops
[nOps
- 1].num
;
1490 getIndexVal(&gsubrIdx
, k
, &val
, &ok
);
1492 cvtGlyph(val
.pos
, val
.len
, charBuf
, subrIdx
, pDict
, gFalse
);
1495 //~ error(-1, "Too few args to Type 2 callgsubr");
1497 // don't clear the stack
1499 case 0x001e: // vhcurveto
1500 if (nOps
< 4 || !(nOps
% 4 == 0 || (nOps
-1) % 4 == 0)) {
1501 //~ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1503 for (k
= 0; k
< nOps
&& k
!= nOps
-5; k
+= 4) {
1505 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1506 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1507 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1508 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1509 charBuf
->append((char)30);
1511 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1512 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1513 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1514 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1515 charBuf
->append((char)31);
1520 cvtNum(0, gFalse
, charBuf
);
1521 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1522 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1523 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1524 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1525 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1527 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1528 cvtNum(0, gFalse
, charBuf
);
1529 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1530 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1531 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1532 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1534 charBuf
->append((char)8);
1539 case 0x001f: // hvcurveto
1540 if (nOps
< 4 || !(nOps
% 4 == 0 || (nOps
-1) % 4 == 0)) {
1541 //~ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1543 for (k
= 0; k
< nOps
&& k
!= nOps
-5; k
+= 4) {
1545 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1546 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1547 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1548 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1549 charBuf
->append((char)31);
1551 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1552 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1553 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1554 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1555 charBuf
->append((char)30);
1560 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1561 cvtNum(0, gFalse
, charBuf
);
1562 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1563 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1564 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1565 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1567 cvtNum(0, gFalse
, charBuf
);
1568 cvtNum(ops
[k
].num
, ops
[k
].isFP
, charBuf
);
1569 cvtNum(ops
[k
+1].num
, ops
[k
+1].isFP
, charBuf
);
1570 cvtNum(ops
[k
+2].num
, ops
[k
+2].isFP
, charBuf
);
1571 cvtNum(ops
[k
+3].num
, ops
[k
+3].isFP
, charBuf
);
1572 cvtNum(ops
[k
+4].num
, ops
[k
+4].isFP
, charBuf
);
1574 charBuf
->append((char)8);
1579 case 0x0c00: // dotsection (should be Type 1 only?)
1586 case 0x0c08: // store
1591 case 0x0c0d: // load
1594 case 0x0c12: // drop
1597 case 0x0c16: // ifelse
1598 case 0x0c17: // random
1600 case 0x0c1a: // sqrt
1602 case 0x0c1c: // exch
1603 case 0x0c1d: // index
1604 case 0x0c1e: // roll
1605 //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
1608 case 0x0c22: // hflex
1610 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1612 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1613 cvtNum(0, gFalse
, charBuf
);
1614 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1615 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1616 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1617 cvtNum(0, gFalse
, charBuf
);
1618 charBuf
->append((char)8);
1619 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1620 cvtNum(0, gFalse
, charBuf
);
1621 cvtNum(ops
[5].num
, ops
[5].isFP
, charBuf
);
1622 cvtNum(-ops
[2].num
, ops
[2].isFP
, charBuf
);
1623 cvtNum(ops
[6].num
, ops
[6].isFP
, charBuf
);
1624 cvtNum(0, gFalse
, charBuf
);
1625 charBuf
->append((char)8);
1629 case 0x0c23: // flex
1631 //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1633 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1634 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1635 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1636 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1637 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1638 cvtNum(ops
[5].num
, ops
[5].isFP
, charBuf
);
1639 charBuf
->append((char)8);
1640 cvtNum(ops
[6].num
, ops
[6].isFP
, charBuf
);
1641 cvtNum(ops
[7].num
, ops
[7].isFP
, charBuf
);
1642 cvtNum(ops
[8].num
, ops
[8].isFP
, charBuf
);
1643 cvtNum(ops
[9].num
, ops
[9].isFP
, charBuf
);
1644 cvtNum(ops
[10].num
, ops
[10].isFP
, charBuf
);
1645 cvtNum(ops
[11].num
, ops
[11].isFP
, charBuf
);
1646 charBuf
->append((char)8);
1650 case 0x0c24: // hflex1
1652 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1654 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1655 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1656 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1657 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1658 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1659 cvtNum(0, gFalse
, charBuf
);
1660 charBuf
->append((char)8);
1661 cvtNum(ops
[5].num
, ops
[5].isFP
, charBuf
);
1662 cvtNum(0, gFalse
, charBuf
);
1663 cvtNum(ops
[6].num
, ops
[6].isFP
, charBuf
);
1664 cvtNum(ops
[7].num
, ops
[7].isFP
, charBuf
);
1665 cvtNum(ops
[8].num
, ops
[8].isFP
, charBuf
);
1666 cvtNum(-(ops
[1].num
+ ops
[3].num
+ ops
[7].num
),
1667 ops
[1].isFP
| ops
[3].isFP
| ops
[7].isFP
, charBuf
);
1668 charBuf
->append((char)8);
1672 case 0x0c25: // flex1
1674 //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1676 cvtNum(ops
[0].num
, ops
[0].isFP
, charBuf
);
1677 cvtNum(ops
[1].num
, ops
[1].isFP
, charBuf
);
1678 cvtNum(ops
[2].num
, ops
[2].isFP
, charBuf
);
1679 cvtNum(ops
[3].num
, ops
[3].isFP
, charBuf
);
1680 cvtNum(ops
[4].num
, ops
[4].isFP
, charBuf
);
1681 cvtNum(ops
[5].num
, ops
[5].isFP
, charBuf
);
1682 charBuf
->append((char)8);
1683 cvtNum(ops
[6].num
, ops
[6].isFP
, charBuf
);
1684 cvtNum(ops
[7].num
, ops
[7].isFP
, charBuf
);
1685 cvtNum(ops
[8].num
, ops
[8].isFP
, charBuf
);
1686 cvtNum(ops
[9].num
, ops
[9].isFP
, charBuf
);
1687 dx
= ops
[0].num
+ ops
[2].num
+ ops
[4].num
+ ops
[6].num
+ ops
[8].num
;
1688 dy
= ops
[1].num
+ ops
[3].num
+ ops
[5].num
+ ops
[7].num
+ ops
[9].num
;
1689 if (fabs(dx
) > fabs(dy
)) {
1690 cvtNum(ops
[10].num
, ops
[10].isFP
, charBuf
);
1691 cvtNum(-dy
, ops
[1].isFP
| ops
[3].isFP
| ops
[5].isFP
|
1692 ops
[7].isFP
| ops
[9].isFP
, charBuf
);
1694 cvtNum(-dx
, ops
[0].isFP
| ops
[2].isFP
| ops
[4].isFP
|
1695 ops
[6].isFP
| ops
[8].isFP
, charBuf
);
1696 cvtNum(ops
[10].num
, ops
[10].isFP
, charBuf
);
1698 charBuf
->append((char)8);
1703 //~ error(-1, "Illegal Type 2 charstring op: %04x",
1711 // charstring encryption
1714 for (i
= start
; i
< charBuf
->getLength(); ++i
) {
1715 byte
= charBuf
->getChar(i
) ^ (r2
>> 8);
1716 charBuf
->setChar(i
, byte
);
1717 r2
= (byte
+ r2
) * 52845 + 22719;
1722 void FoFiType1C::cvtGlyphWidth(GBool useOp
, GString
*charBuf
,
1723 Type1CPrivateDict
*pDict
) {
1729 w
= pDict
->nominalWidthX
+ ops
[0].num
;
1730 wFP
= pDict
->nominalWidthXFP
| ops
[0].isFP
;
1731 for (i
= 1; i
< nOps
; ++i
) {
1736 w
= pDict
->defaultWidthX
;
1737 wFP
= pDict
->defaultWidthXFP
;
1739 cvtNum(0, gFalse
, charBuf
);
1740 cvtNum(w
, wFP
, charBuf
);
1741 charBuf
->append((char)13);
1744 void FoFiType1C::cvtNum(double x
, GBool isFP
, GString
*charBuf
) {
1750 if (x
>= -32768 && x
< 32768) {
1751 y
= (int)(x
* 256.0);
1753 buf
[1] = (Guchar
)(y
>> 24);
1754 buf
[2] = (Guchar
)(y
>> 16);
1755 buf
[3] = (Guchar
)(y
>> 8);
1766 //~ error(-1, "Type 2 fixed point constant out of range");
1770 if (y
>= -107 && y
<= 107) {
1771 buf
[0] = (Guchar
)(y
+ 139);
1773 } else if (y
> 107 && y
<= 1131) {
1775 buf
[0] = (Guchar
)((y
>> 8) + 247);
1776 buf
[1] = (Guchar
)(y
& 0xff);
1778 } else if (y
< -107 && y
>= -1131) {
1780 buf
[0] = (Guchar
)((y
>> 8) + 251);
1781 buf
[1] = (Guchar
)(y
& 0xff);
1785 buf
[1] = (Guchar
)(y
>> 24);
1786 buf
[2] = (Guchar
)(y
>> 16);
1787 buf
[3] = (Guchar
)(y
>> 8);
1792 charBuf
->append((char *)buf
, n
);
1795 void FoFiType1C::eexecWrite(Type1CEexecBuf
*eb
, char *s
) {
1799 for (p
= (Guchar
*)s
; *p
; ++p
) {
1800 x
= *p
^ (eb
->r1
>> 8);
1801 eb
->r1
= (x
+ eb
->r1
) * 52845 + 22719;
1803 (*eb
->outputFunc
)(eb
->outputStream
, &hexChars
[x
>> 4], 1);
1804 (*eb
->outputFunc
)(eb
->outputStream
, &hexChars
[x
& 0x0f], 1);
1806 if (eb
->line
== 64) {
1807 (*eb
->outputFunc
)(eb
->outputStream
, "\n", 1);
1811 (*eb
->outputFunc
)(eb
->outputStream
, (char *)&x
, 1);
1816 void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf
*eb
,
1822 for (i
= 0; i
< n
; ++i
) {
1823 x
= s
[i
] ^ (eb
->r1
>> 8);
1824 eb
->r1
= (x
+ eb
->r1
) * 52845 + 22719;
1826 (*eb
->outputFunc
)(eb
->outputStream
, &hexChars
[x
>> 4], 1);
1827 (*eb
->outputFunc
)(eb
->outputStream
, &hexChars
[x
& 0x0f], 1);
1829 if (eb
->line
== 64) {
1830 (*eb
->outputFunc
)(eb
->outputStream
, "\n", 1);
1834 (*eb
->outputFunc
)(eb
->outputStream
, (char *)&x
, 1);
1839 GBool
FoFiType1C::parse() {
1846 // some tools embed Type 1C fonts with an extra whitespace char at
1848 if (len
> 0 && file
[0] != '\x01') {
1854 getIndex(getU8(2, &parsedOk
), &nameIdx
, &parsedOk
);
1855 getIndex(nameIdx
.endPos
, &topDictIdx
, &parsedOk
);
1856 getIndex(topDictIdx
.endPos
, &stringIdx
, &parsedOk
);
1857 getIndex(stringIdx
.endPos
, &gsubrIdx
, &parsedOk
);
1861 gsubrBias
= (gsubrIdx
.len
< 1240) ? 107
1862 : (gsubrIdx
.len
< 33900) ? 1131 : 32768;
1864 // read the first font name
1865 getIndexVal(&nameIdx
, 0, &val
, &parsedOk
);
1869 name
= new GString((char *)&file
[val
.pos
], val
.len
);
1871 // read the top dict for the first font
1874 // for CID fonts: read the FDArray dicts and private dicts
1875 if (topDict
.firstOp
== 0x0c1e) {
1876 if (topDict
.fdArrayOffset
== 0) {
1878 privateDicts
= (Type1CPrivateDict
*)gmalloc(sizeof(Type1CPrivateDict
));
1879 readPrivateDict(0, 0, &privateDicts
[0]);
1881 getIndex(topDict
.fdArrayOffset
, &fdIdx
, &parsedOk
);
1886 privateDicts
= (Type1CPrivateDict
*)
1887 gmallocn(nFDs
, sizeof(Type1CPrivateDict
));
1888 for (i
= 0; i
< nFDs
; ++i
) {
1889 getIndexVal(&fdIdx
, i
, &val
, &parsedOk
);
1893 readFD(val
.pos
, val
.len
, &privateDicts
[i
]);
1897 // for 8-bit fonts: read the private dict
1899 privateDicts
= (Type1CPrivateDict
*)gmalloc(sizeof(Type1CPrivateDict
));
1900 readPrivateDict(topDict
.privateOffset
, topDict
.privateSize
,
1904 // check for parse errors in the private dict(s)
1909 // get the charstrings index
1910 if (topDict
.charStringsOffset
<= 0) {
1914 getIndex(topDict
.charStringsOffset
, &charStringsIdx
, &parsedOk
);
1918 nGlyphs
= charStringsIdx
.len
;
1920 // for CID fonts: read the FDSelect table
1921 if (topDict
.firstOp
== 0x0c1e) {
1929 if (!readCharset()) {
1934 // for 8-bit fonts: build the encoding
1935 if (topDict
.firstOp
!= 0x0c14 && topDict
.firstOp
!= 0x0c1e) {
1945 void FoFiType1C::readTopDict() {
1946 Type1CIndexVal topDictPtr
;
1949 topDict
.firstOp
= -1;
1950 topDict
.versionSID
= 0;
1951 topDict
.noticeSID
= 0;
1952 topDict
.copyrightSID
= 0;
1953 topDict
.fullNameSID
= 0;
1954 topDict
.familyNameSID
= 0;
1955 topDict
.weightSID
= 0;
1956 topDict
.isFixedPitch
= 0;
1957 topDict
.italicAngle
= 0;
1958 topDict
.underlinePosition
= -100;
1959 topDict
.underlineThickness
= 50;
1960 topDict
.paintType
= 0;
1961 topDict
.charstringType
= 2;
1962 topDict
.fontMatrix
[0] = 0.001;
1963 topDict
.fontMatrix
[1] = 0;
1964 topDict
.fontMatrix
[2] = 0;
1965 topDict
.fontMatrix
[3] = 0.001;
1966 topDict
.fontMatrix
[4] = 0;
1967 topDict
.fontMatrix
[5] = 0;
1968 topDict
.hasFontMatrix
= gFalse
;
1969 topDict
.uniqueID
= 0;
1970 topDict
.fontBBox
[0] = 0;
1971 topDict
.fontBBox
[1] = 0;
1972 topDict
.fontBBox
[2] = 0;
1973 topDict
.fontBBox
[3] = 0;
1974 topDict
.strokeWidth
= 0;
1975 topDict
.charsetOffset
= 0;
1976 topDict
.encodingOffset
= 0;
1977 topDict
.charStringsOffset
= 0;
1978 topDict
.privateSize
= 0;
1979 topDict
.privateOffset
= 0;
1980 topDict
.registrySID
= 0;
1981 topDict
.orderingSID
= 0;
1982 topDict
.supplement
= 0;
1983 topDict
.fdArrayOffset
= 0;
1984 topDict
.fdSelectOffset
= 0;
1986 getIndexVal(&topDictIdx
, 0, &topDictPtr
, &parsedOk
);
1987 pos
= topDictPtr
.pos
;
1989 while (pos
< topDictPtr
.pos
+ topDictPtr
.len
) {
1990 pos
= getOp(pos
, gFalse
, &parsedOk
);
1994 if (!ops
[nOps
- 1].isNum
) {
1995 --nOps
; // drop the operator
1996 if (topDict
.firstOp
< 0) {
1997 topDict
.firstOp
= ops
[nOps
].op
;
1999 switch (ops
[nOps
].op
) {
2000 case 0x0000: topDict
.versionSID
= (int)ops
[0].num
; break;
2001 case 0x0001: topDict
.noticeSID
= (int)ops
[0].num
; break;
2002 case 0x0c00: topDict
.copyrightSID
= (int)ops
[0].num
; break;
2003 case 0x0002: topDict
.fullNameSID
= (int)ops
[0].num
; break;
2004 case 0x0003: topDict
.familyNameSID
= (int)ops
[0].num
; break;
2005 case 0x0004: topDict
.weightSID
= (int)ops
[0].num
; break;
2006 case 0x0c01: topDict
.isFixedPitch
= (int)ops
[0].num
; break;
2007 case 0x0c02: topDict
.italicAngle
= ops
[0].num
; break;
2008 case 0x0c03: topDict
.underlinePosition
= ops
[0].num
; break;
2009 case 0x0c04: topDict
.underlineThickness
= ops
[0].num
; break;
2010 case 0x0c05: topDict
.paintType
= (int)ops
[0].num
; break;
2011 case 0x0c06: topDict
.charstringType
= (int)ops
[0].num
; break;
2012 case 0x0c07: topDict
.fontMatrix
[0] = ops
[0].num
;
2013 topDict
.fontMatrix
[1] = ops
[1].num
;
2014 topDict
.fontMatrix
[2] = ops
[2].num
;
2015 topDict
.fontMatrix
[3] = ops
[3].num
;
2016 topDict
.fontMatrix
[4] = ops
[4].num
;
2017 topDict
.fontMatrix
[5] = ops
[5].num
;
2018 topDict
.hasFontMatrix
= gTrue
; break;
2019 case 0x000d: topDict
.uniqueID
= (int)ops
[0].num
; break;
2020 case 0x0005: topDict
.fontBBox
[0] = ops
[0].num
;
2021 topDict
.fontBBox
[1] = ops
[1].num
;
2022 topDict
.fontBBox
[2] = ops
[2].num
;
2023 topDict
.fontBBox
[3] = ops
[3].num
; break;
2024 case 0x0c08: topDict
.strokeWidth
= ops
[0].num
; break;
2025 case 0x000f: topDict
.charsetOffset
= (int)ops
[0].num
; break;
2026 case 0x0010: topDict
.encodingOffset
= (int)ops
[0].num
; break;
2027 case 0x0011: topDict
.charStringsOffset
= (int)ops
[0].num
; break;
2028 case 0x0012: topDict
.privateSize
= (int)ops
[0].num
;
2029 topDict
.privateOffset
= (int)ops
[1].num
; break;
2030 case 0x0c1e: topDict
.registrySID
= (int)ops
[0].num
;
2031 topDict
.orderingSID
= (int)ops
[1].num
;
2032 topDict
.supplement
= (int)ops
[2].num
; break;
2033 case 0x0c24: topDict
.fdArrayOffset
= (int)ops
[0].num
; break;
2034 case 0x0c25: topDict
.fdSelectOffset
= (int)ops
[0].num
; break;
2041 // Read a CID font dict (FD) - this pulls out the private dict
2042 // pointer, and reads the private dict. It also pulls the FontMatrix
2043 // (if any) out of the FD.
2044 void FoFiType1C::readFD(int offset
, int length
, Type1CPrivateDict
*pDict
) {
2045 int pos
, pSize
, pOffset
;
2046 double fontMatrix
[6];
2047 GBool hasFontMatrix
;
2049 hasFontMatrix
= gFalse
;
2050 pSize
= pOffset
= 0;
2053 while (pos
< offset
+ length
) {
2054 pos
= getOp(pos
, gFalse
, &parsedOk
);
2058 if (!ops
[nOps
- 1].isNum
) {
2059 if (ops
[nOps
- 1].op
== 0x0012) {
2064 pSize
= (int)ops
[0].num
;
2065 pOffset
= (int)ops
[1].num
;
2067 } else if (ops
[nOps
- 1].op
== 0x0c07) {
2068 fontMatrix
[0] = ops
[0].num
;
2069 fontMatrix
[1] = ops
[1].num
;
2070 fontMatrix
[2] = ops
[2].num
;
2071 fontMatrix
[3] = ops
[3].num
;
2072 fontMatrix
[4] = ops
[4].num
;
2073 fontMatrix
[5] = ops
[5].num
;
2074 hasFontMatrix
= gTrue
;
2079 readPrivateDict(pOffset
, pSize
, pDict
);
2080 if (hasFontMatrix
) {
2081 pDict
->fontMatrix
[0] = fontMatrix
[0];
2082 pDict
->fontMatrix
[1] = fontMatrix
[1];
2083 pDict
->fontMatrix
[2] = fontMatrix
[2];
2084 pDict
->fontMatrix
[3] = fontMatrix
[3];
2085 pDict
->fontMatrix
[4] = fontMatrix
[4];
2086 pDict
->fontMatrix
[5] = fontMatrix
[5];
2087 pDict
->hasFontMatrix
= gTrue
;
2091 void FoFiType1C::readPrivateDict(int offset
, int length
,
2092 Type1CPrivateDict
*pDict
) {
2095 pDict
->hasFontMatrix
= gFalse
;
2096 pDict
->nBlueValues
= 0;
2097 pDict
->nOtherBlues
= 0;
2098 pDict
->nFamilyBlues
= 0;
2099 pDict
->nFamilyOtherBlues
= 0;
2100 pDict
->blueScale
= 0.039625;
2101 pDict
->blueShift
= 7;
2102 pDict
->blueFuzz
= 1;
2103 pDict
->hasStdHW
= gFalse
;
2104 pDict
->hasStdVW
= gFalse
;
2105 pDict
->nStemSnapH
= 0;
2106 pDict
->nStemSnapV
= 0;
2107 pDict
->hasForceBold
= gFalse
;
2108 pDict
->forceBoldThreshold
= 0;
2109 pDict
->languageGroup
= 0;
2110 pDict
->expansionFactor
= 0.06;
2111 pDict
->initialRandomSeed
= 0;
2112 pDict
->subrsOffset
= 0;
2113 pDict
->defaultWidthX
= 0;
2114 pDict
->defaultWidthXFP
= gFalse
;
2115 pDict
->nominalWidthX
= 0;
2116 pDict
->nominalWidthXFP
= gFalse
;
2119 if (offset
== 0 || length
== 0) {
2125 while (pos
< offset
+ length
) {
2126 pos
= getOp(pos
, gFalse
, &parsedOk
);
2130 if (!ops
[nOps
- 1].isNum
) {
2131 --nOps
; // drop the operator
2132 switch (ops
[nOps
].op
) {
2134 pDict
->nBlueValues
= getDeltaIntArray(pDict
->blueValues
,
2135 type1CMaxBlueValues
);
2138 pDict
->nOtherBlues
= getDeltaIntArray(pDict
->otherBlues
,
2139 type1CMaxOtherBlues
);
2142 pDict
->nFamilyBlues
= getDeltaIntArray(pDict
->familyBlues
,
2143 type1CMaxBlueValues
);
2146 pDict
->nFamilyOtherBlues
= getDeltaIntArray(pDict
->familyOtherBlues
,
2147 type1CMaxOtherBlues
);
2150 pDict
->blueScale
= ops
[0].num
;
2153 pDict
->blueShift
= (int)ops
[0].num
;
2156 pDict
->blueFuzz
= (int)ops
[0].num
;
2159 pDict
->stdHW
= ops
[0].num
;
2160 pDict
->hasStdHW
= gTrue
;
2163 pDict
->stdVW
= ops
[0].num
;
2164 pDict
->hasStdVW
= gTrue
;
2167 pDict
->nStemSnapH
= getDeltaFPArray(pDict
->stemSnapH
,
2171 pDict
->nStemSnapV
= getDeltaFPArray(pDict
->stemSnapV
,
2175 pDict
->forceBold
= ops
[0].num
!= 0;
2176 pDict
->hasForceBold
= gTrue
;
2179 pDict
->forceBoldThreshold
= ops
[0].num
;
2182 pDict
->languageGroup
= (int)ops
[0].num
;
2185 pDict
->expansionFactor
= ops
[0].num
;
2188 pDict
->initialRandomSeed
= (int)ops
[0].num
;
2191 pDict
->subrsOffset
= offset
+ (int)ops
[0].num
;
2194 pDict
->defaultWidthX
= ops
[0].num
;
2195 pDict
->defaultWidthXFP
= ops
[0].isFP
;
2198 pDict
->nominalWidthX
= ops
[0].num
;
2199 pDict
->nominalWidthXFP
= ops
[0].isFP
;
2207 void FoFiType1C::readFDSelect() {
2208 int fdSelectFmt
, pos
, nRanges
, gid0
, gid1
, fd
, i
, j
;
2210 fdSelect
= (Guchar
*)gmalloc(nGlyphs
);
2211 if (topDict
.fdSelectOffset
== 0) {
2212 for (i
= 0; i
< nGlyphs
; ++i
) {
2216 pos
= topDict
.fdSelectOffset
;
2217 fdSelectFmt
= getU8(pos
++, &parsedOk
);
2221 if (fdSelectFmt
== 0) {
2222 if (!checkRegion(pos
, nGlyphs
)) {
2226 memcpy(fdSelect
, file
+ pos
, nGlyphs
);
2227 } else if (fdSelectFmt
== 3) {
2228 nRanges
= getU16BE(pos
, &parsedOk
);
2230 gid0
= getU16BE(pos
, &parsedOk
);
2232 for (i
= 1; i
<= nRanges
; ++i
) {
2233 fd
= getU8(pos
++, &parsedOk
);
2234 gid1
= getU16BE(pos
, &parsedOk
);
2239 if (gid0
> gid1
|| gid1
> nGlyphs
) {
2240 //~ error(-1, "Bad FDSelect table in CID font");
2244 for (j
= gid0
; j
< gid1
; ++j
) {
2250 //~ error(-1, "Unknown FDSelect table format in CID font");
2251 for (i
= 0; i
< nGlyphs
; ++i
) {
2258 void FoFiType1C::buildEncoding() {
2260 int nCodes
, nRanges
, encFormat
;
2261 int pos
, c
, sid
, nLeft
, nSups
, i
, j
;
2263 if (topDict
.encodingOffset
== 0) {
2264 encoding
= (char**)fofiType1StandardEncoding
;
2266 } else if (topDict
.encodingOffset
== 1) {
2267 encoding
= (char**)fofiType1ExpertEncoding
;
2270 encoding
= (char **)gmallocn(256, sizeof(char *));
2271 for (i
= 0; i
< 256; ++i
) {
2274 pos
= topDict
.encodingOffset
;
2275 encFormat
= getU8(pos
++, &parsedOk
);
2279 if ((encFormat
& 0x7f) == 0) {
2280 nCodes
= 1 + getU8(pos
++, &parsedOk
);
2284 if (nCodes
> nGlyphs
) {
2287 for (i
= 1; i
< nCodes
; ++i
) {
2288 c
= getU8(pos
++, &parsedOk
);
2295 encoding
[c
] = copyString(getString(charset
[i
], buf
, &parsedOk
));
2297 } else if ((encFormat
& 0x7f) == 1) {
2298 nRanges
= getU8(pos
++, &parsedOk
);
2303 for (i
= 0; i
< nRanges
; ++i
) {
2304 c
= getU8(pos
++, &parsedOk
);
2305 nLeft
= getU8(pos
++, &parsedOk
);
2309 for (j
= 0; j
<= nLeft
&& nCodes
< nGlyphs
; ++j
) {
2314 encoding
[c
] = copyString(getString(charset
[nCodes
], buf
,
2322 if (encFormat
& 0x80) {
2323 nSups
= getU8(pos
++, &parsedOk
);
2327 for (i
= 0; i
< nSups
; ++i
) {
2328 c
= getU8(pos
++, &parsedOk
);;
2332 sid
= getU16BE(pos
, &parsedOk
);
2340 encoding
[c
] = copyString(getString(sid
, buf
, &parsedOk
));
2346 GBool
FoFiType1C::readCharset() {
2347 int charsetFormat
, c
, pos
;
2350 if (topDict
.charsetOffset
== 0) {
2351 charset
= fofiType1CISOAdobeCharset
;
2352 } else if (topDict
.charsetOffset
== 1) {
2353 charset
= fofiType1CExpertCharset
;
2354 } else if (topDict
.charsetOffset
== 2) {
2355 charset
= fofiType1CExpertSubsetCharset
;
2357 charset
= (Gushort
*)gmallocn(nGlyphs
, sizeof(Gushort
));
2358 for (i
= 0; i
< nGlyphs
; ++i
) {
2361 pos
= topDict
.charsetOffset
;
2362 charsetFormat
= getU8(pos
++, &parsedOk
);
2363 if (charsetFormat
== 0) {
2364 for (i
= 1; i
< nGlyphs
; ++i
) {
2365 charset
[i
] = (Gushort
)getU16BE(pos
, &parsedOk
);
2371 } else if (charsetFormat
== 1) {
2373 while (i
< nGlyphs
) {
2374 c
= getU16BE(pos
, &parsedOk
);
2376 nLeft
= getU8(pos
++, &parsedOk
);
2380 for (j
= 0; j
<= nLeft
&& i
< nGlyphs
; ++j
) {
2381 charset
[i
++] = (Gushort
)c
++;
2384 } else if (charsetFormat
== 2) {
2386 while (i
< nGlyphs
) {
2387 c
= getU16BE(pos
, &parsedOk
);
2389 nLeft
= getU16BE(pos
, &parsedOk
);
2394 for (j
= 0; j
<= nLeft
&& i
< nGlyphs
; ++j
) {
2395 charset
[i
++] = (Gushort
)c
++;
2408 int FoFiType1C::getOp(int pos
, GBool charstring
, GBool
*ok
) {
2409 static char nybChars
[16] = "0123456789.ee -";
2412 int b0
, b1
, nyb0
, nyb1
, x
, i
;
2414 b0
= getU8(pos
++, ok
);
2419 x
= getU8(pos
++, ok
);
2420 x
= (x
<< 8) | getU8(pos
++, ok
);
2426 } else if (!charstring
&& b0
== 29) {
2427 x
= getU8(pos
++, ok
);
2428 x
= (x
<< 8) | getU8(pos
++, ok
);
2429 x
= (x
<< 8) | getU8(pos
++, ok
);
2430 x
= (x
<< 8) | getU8(pos
++, ok
);
2431 if (x
& 0x80000000) {
2436 } else if (!charstring
&& b0
== 30) {
2439 b1
= getU8(pos
++, ok
);
2445 buf
[i
++] = nybChars
[nyb0
];
2458 buf
[i
++] = nybChars
[nyb1
];
2470 } else if (b0
>= 32 && b0
<= 246) {
2473 } else if (b0
>= 247 && b0
<= 250) {
2474 op
.num
= ((b0
- 247) << 8) + getU8(pos
++, ok
) + 108;
2476 } else if (b0
>= 251 && b0
<= 254) {
2477 op
.num
= -((b0
- 251) << 8) - getU8(pos
++, ok
) - 108;
2479 } else if (charstring
&& b0
== 255) {
2480 x
= getU8(pos
++, ok
);
2481 x
= (x
<< 8) | getU8(pos
++, ok
);
2482 x
= (x
<< 8) | getU8(pos
++, ok
);
2483 x
= (x
<< 8) | getU8(pos
++, ok
);
2484 if (x
& 0x80000000) {
2487 op
.num
= (double)x
/ 65536.0;
2490 } else if (b0
== 12) {
2492 op
.op
= 0x0c00 + getU8(pos
++, ok
);
2506 // Convert the delta-encoded ops array to an array of ints.
2507 int FoFiType1C::getDeltaIntArray(int *arr
, int maxLen
) {
2511 if ((n
= nOps
) > maxLen
) {
2515 for (i
= 0; i
< n
; ++i
) {
2516 x
+= (int)ops
[i
].num
;
2522 // Convert the delta-encoded ops array to an array of doubles.
2523 int FoFiType1C::getDeltaFPArray(double *arr
, int maxLen
) {
2527 if ((n
= nOps
) > maxLen
) {
2531 for (i
= 0; i
< n
; ++i
) {
2538 void FoFiType1C::getIndex(int pos
, Type1CIndex
*idx
, GBool
*ok
) {
2540 idx
->len
= getU16BE(pos
, ok
);
2541 if (idx
->len
== 0) {
2542 // empty indexes are legal and contain just the length field
2544 idx
->startPos
= idx
->endPos
= pos
+ 2;
2546 idx
->offSize
= getU8(pos
+ 2, ok
);
2547 if (idx
->offSize
< 1 || idx
->offSize
> 4) {
2550 idx
->startPos
= pos
+ 3 + (idx
->len
+ 1) * idx
->offSize
- 1;
2551 if (idx
->startPos
< 0 || idx
->startPos
>= len
) {
2554 idx
->endPos
= idx
->startPos
+ getUVarBE(pos
+ 3 + idx
->len
* idx
->offSize
,
2556 if (idx
->endPos
< idx
->startPos
|| idx
->endPos
> len
) {
2562 void FoFiType1C::getIndexVal(Type1CIndex
*idx
, int i
,
2563 Type1CIndexVal
*val
, GBool
*ok
) {
2566 if (i
< 0 || i
>= idx
->len
) {
2570 pos0
= idx
->startPos
+ getUVarBE(idx
->pos
+ 3 + i
* idx
->offSize
,
2572 pos1
= idx
->startPos
+ getUVarBE(idx
->pos
+ 3 + (i
+ 1) * idx
->offSize
,
2574 if (pos0
< idx
->startPos
|| pos0
> idx
->endPos
||
2575 pos1
<= idx
->startPos
|| pos1
> idx
->endPos
||
2580 val
->len
= pos1
- pos0
;
2583 char *FoFiType1C::getString(int sid
, char *buf
, GBool
*ok
) {
2588 strcpy(buf
, fofiType1CStdStrings
[sid
]);
2591 getIndexVal(&stringIdx
, sid
, &val
, ok
);
2593 if ((n
= val
.len
) > 255) {
2596 strncpy(buf
, (char *)&file
[val
.pos
], n
);