00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <aconf.h>
00010
00011 #ifdef USE_GCC_PRAGMAS
00012 #pragma implementation
00013 #endif
00014
00015 #include <math.h>
00016 #include <stdlib.h>
00017 #include <stddef.h>
00018 #include <stdarg.h>
00019 #include <string.h>
00020 #include <ctype.h>
00021 #include "gmem.h"
00022 #include "Error.h"
00023 #include "GlobalParams.h"
00024 #include "CharCodeToUnicode.h"
00025 #include "FontEncodingTables.h"
00026 #include "FontFile.h"
00027
00028 #include "CompactFontTables.h"
00029
00030
00031
00032 static inline const char *nextLine(const char *line, const char *end) {
00033 while (line < end && *line != '\n' && *line != '\r')
00034 ++line;
00035 while (line < end && *line == '\n' || *line == '\r')
00036 ++line;
00037 return line;
00038 }
00039
00040 static const char hexChars[17] = "0123456789ABCDEF";
00041
00042
00043
00044
00045
00046 FontFile::FontFile() {
00047 }
00048
00049 FontFile::~FontFile() {
00050 }
00051
00052
00053
00054
00055
00056 Type1FontFile::Type1FontFile(const char *file, int len) {
00057 const char *line, *line1;
00058 char *p, *p2;
00059 GBool haveEncoding;
00060 char buf[256];
00061 char c;
00062 int n, code, i, j;
00063
00064 name = NULL;
00065 encoding = (char **)gmalloc(256 * sizeof(char *));
00066 for (i = 0; i < 256; ++i) {
00067 encoding[i] = NULL;
00068 }
00069 haveEncoding = gFalse;
00070
00071 for (i = 1, line = file;
00072 i <= 100 && line < file + len && !haveEncoding;
00073 ++i) {
00074
00075
00076 if (!strncmp(line, "/FontName", 9)) {
00077 strncpy(buf, line, 255);
00078 buf[255] = '\0';
00079 if ((p = strchr(buf+9, '/')) &&
00080 (p = strtok(p+1, " \t\n\r"))) {
00081 name = copyString(p);
00082 }
00083 line = nextLine(line, file + len);
00084
00085
00086 } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
00087 for (j = 0; j < 256; ++j) {
00088 if (standardEncoding[j]) {
00089 encoding[j] = copyString(standardEncoding[j]);
00090 }
00091 }
00092 haveEncoding = gTrue;
00093 } else if (!strncmp(line, "/Encoding 256 array", 19)) {
00094 for (j = 0; j < 300; ++j) {
00095 line1 = nextLine(line, file + len);
00096 if ((n = line1 - line) > 255) {
00097 n = 255;
00098 }
00099 strncpy(buf, line, n);
00100 buf[n] = '\0';
00101 for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
00102 if (!strncmp(p, "dup", 3)) {
00103 for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
00104 for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
00105 if (*p2) {
00106 c = *p2;
00107 *p2 = '\0';
00108 if ((code = atoi(p)) < 256) {
00109 *p2 = c;
00110 for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
00111 if (*p == '/') {
00112 ++p;
00113 for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
00114 *p2 = '\0';
00115 encoding[code] = copyString(p);
00116 }
00117 }
00118 }
00119 } else {
00120 if (strtok(buf, " \t") &&
00121 (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
00122 break;
00123 }
00124 }
00125 line = line1;
00126 }
00127
00128 haveEncoding = gTrue;
00129
00130 } else {
00131 line = nextLine(line, file + len);
00132 }
00133 }
00134 }
00135
00136 Type1FontFile::~Type1FontFile() {
00137 int i;
00138
00139 if (name) {
00140 gfree(name);
00141 }
00142 for (i = 0; i < 256; ++i) {
00143 gfree(encoding[i]);
00144 }
00145 gfree(encoding);
00146 }
00147
00148
00149
00150
00151
00152 struct Type1CTopDict {
00153 int version;
00154 int notice;
00155 int copyright;
00156 int fullName;
00157 int familyName;
00158 int weight;
00159 int isFixedPitch;
00160 double italicAngle;
00161 double underlinePosition;
00162 double underlineThickness;
00163 int paintType;
00164 int charstringType;
00165 double fontMatrix[6];
00166 int uniqueID;
00167 double fontBBox[4];
00168 double strokeWidth;
00169 int charset;
00170 int encoding;
00171 int charStrings;
00172 int privateSize;
00173 int privateOffset;
00174
00175
00176 int registry;
00177 int ordering;
00178 int supplement;
00179 int fdArrayOffset;
00180 int fdSelectOffset;
00181 };
00182
00183 struct Type1CPrivateDict {
00184 GString *dictData;
00185 int subrsOffset;
00186 double defaultWidthX;
00187 GBool defaultWidthXFP;
00188 double nominalWidthX;
00189 GBool nominalWidthXFP;
00190 };
00191
00192 Type1CFontFile::Type1CFontFile(const char *fileA, int lenA) {
00193 Guchar *nameIdxPtr, *idxPtr0, *idxPtr1;
00194
00195 file = fileA;
00196 len = lenA;
00197 name = NULL;
00198 encoding = NULL;
00199
00200
00201
00202 if (file[0] != '\x01') {
00203 ++file;
00204 }
00205
00206
00207 topOffSize = file[3] & 0xff;
00208
00209
00210 nameIdxPtr = (Guchar *)file + (file[2] & 0xff);
00211 idxPtr0 = getIndexValPtr(nameIdxPtr, 0);
00212 idxPtr1 = getIndexValPtr(nameIdxPtr, 1);
00213 name = new GString((char *)idxPtr0, idxPtr1 - idxPtr0);
00214
00215 topDictIdxPtr = getIndexEnd(nameIdxPtr);
00216 stringIdxPtr = getIndexEnd(topDictIdxPtr);
00217 gsubrIdxPtr = getIndexEnd(stringIdxPtr);
00218 }
00219
00220 Type1CFontFile::~Type1CFontFile() {
00221 int i;
00222
00223 delete name;
00224 if (encoding) {
00225 for (i = 0; i < 256; ++i) {
00226 gfree(encoding[i]);
00227 }
00228 gfree(encoding);
00229 }
00230 }
00231
00232 const char *Type1CFontFile::getName() {
00233 return name->getCString();
00234 }
00235
00236 char **Type1CFontFile::getEncoding() {
00237 if (!encoding) {
00238 readNameAndEncoding();
00239 }
00240 return encoding;
00241 }
00242
00243 void Type1CFontFile::readNameAndEncoding() {
00244 char buf[256];
00245 Guchar *idxPtr0, *idxPtr1, *ptr;
00246 int nGlyphs;
00247 int nCodes, nRanges, nLeft, nSups;
00248 Gushort *glyphNames;
00249 int charset, enc, charstrings;
00250 int encFormat;
00251 int c, sid;
00252 double x;
00253 GBool isFP;
00254 int key;
00255 int i, j;
00256
00257 encoding = (char **)gmalloc(256 * sizeof(char *));
00258 for (i = 0; i < 256; ++i) {
00259 encoding[i] = NULL;
00260 }
00261
00262
00263 idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
00264 idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
00265 charset = enc = charstrings = 0;
00266 i = 0;
00267 ptr = idxPtr0;
00268 while (ptr < idxPtr1) {
00269 if (*ptr <= 27 || *ptr == 31) {
00270 key = *ptr++;
00271 if (key == 0x0c) {
00272 key = (key << 8) | *ptr++;
00273 }
00274 if (key == 0x0f) {
00275 charset = (int)op[0];
00276 } else if (key == 0x10) {
00277 enc = (int)op[0];
00278 } else if (key == 0x11) {
00279 charstrings = (int)op[0];
00280 }
00281 i = 0;
00282 } else {
00283 x = getNum(&ptr, &isFP);
00284 if (i < 48) {
00285 op[i++] = x;
00286 }
00287 }
00288 }
00289
00290
00291 nGlyphs = getIndexLen((Guchar *)file + charstrings);
00292
00293
00294 glyphNames = readCharset(charset, nGlyphs);
00295
00296
00297 if (enc == 0) {
00298 for (i = 0; i < 256; ++i) {
00299 if (standardEncoding[i]) {
00300 encoding[i] = copyString(standardEncoding[i]);
00301 }
00302 }
00303 } else if (enc == 1) {
00304 for (i = 0; i < 256; ++i) {
00305 if (expertEncoding[i]) {
00306 encoding[i] = copyString(expertEncoding[i]);
00307 }
00308 }
00309 } else {
00310 ptr = (Guchar *)file + enc;
00311 encFormat = *ptr++;
00312 if ((encFormat & 0x7f) == 0) {
00313 nCodes = 1 + *ptr++;
00314 if (nCodes > nGlyphs) {
00315 nCodes = nGlyphs;
00316 }
00317 for (i = 1; i < nCodes; ++i) {
00318 c = *ptr++;
00319 encoding[c] = copyString(getString(glyphNames[i], buf));
00320 }
00321 } else if ((encFormat & 0x7f) == 1) {
00322 nRanges = *ptr++;
00323 nCodes = 1;
00324 for (i = 0; i < nRanges; ++i) {
00325 c = *ptr++;
00326 nLeft = *ptr++;
00327 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
00328 encoding[c] = copyString(getString(glyphNames[nCodes], buf));
00329 ++nCodes;
00330 ++c;
00331 }
00332 }
00333 }
00334 if (encFormat & 0x80) {
00335 nSups = *ptr++;
00336 for (i = 0; i < nSups; ++i) {
00337 c = *ptr++;
00338 sid = getWord(ptr, 2);
00339 ptr += 2;
00340 encoding[c] = copyString(getString(sid, buf));
00341 }
00342 }
00343 }
00344
00345 if (charset > 2) {
00346 gfree(glyphNames);
00347 }
00348 }
00349
00350 void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
00351 void *outputStreamA) {
00352 Type1CTopDict dict;
00353 Type1CPrivateDict privateDict;
00354 char buf[512], eBuf[256];
00355 Guchar *idxPtr0, *idxPtr1, *subrsIdxPtr, *charStringsIdxPtr, *ptr;
00356 int nGlyphs, nCodes, nRanges, nLeft, nSups;
00357 Gushort *glyphNames;
00358 int encFormat, nSubrs, nCharStrings;
00359 int c, sid;
00360 int i, j, n;
00361
00362 outputFunc = outputFuncA;
00363 outputStream = outputStreamA;
00364
00365
00366 readTopDict(&dict);
00367
00368
00369
00370
00371
00372 (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
00373 (*outputFunc)(outputStream, name->getCString(), name->getLength());
00374 if (dict.version != 0) {
00375 getString(dict.version, buf);
00376 (*outputFunc)(outputStream, buf, strlen(buf));
00377 }
00378 (*outputFunc)(outputStream, "\n", 1);
00379 (*outputFunc)(outputStream, "11 dict begin\n", 14);
00380 (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
00381 if (dict.version != 0) {
00382 (*outputFunc)(outputStream, "/version (", 10);
00383 (*outputFunc)(outputStream, buf, strlen(buf));
00384 (*outputFunc)(outputStream, ") readonly def\n", 15);
00385 }
00386 if (dict.notice != 0) {
00387 getString(dict.notice, buf);
00388 (*outputFunc)(outputStream, "/Notice (", 9);
00389 (*outputFunc)(outputStream, buf, strlen(buf));
00390 (*outputFunc)(outputStream, ") readonly def\n", 15);
00391 }
00392 if (dict.copyright != 0) {
00393 getString(dict.copyright, buf);
00394 (*outputFunc)(outputStream, "/Copyright (", 12);
00395 (*outputFunc)(outputStream, buf, strlen(buf));
00396 (*outputFunc)(outputStream, ") readonly def\n", 15);
00397 }
00398 if (dict.fullName != 0) {
00399 getString(dict.fullName, buf);
00400 (*outputFunc)(outputStream, "/FullName (", 11);
00401 (*outputFunc)(outputStream, buf, strlen(buf));
00402 (*outputFunc)(outputStream, ") readonly def\n", 15);
00403 }
00404 if (dict.familyName != 0) {
00405 getString(dict.familyName, buf);
00406 (*outputFunc)(outputStream, "/FamilyName (", 13);
00407 (*outputFunc)(outputStream, buf, strlen(buf));
00408 (*outputFunc)(outputStream, ") readonly def\n", 15);
00409 }
00410 if (dict.weight != 0) {
00411 getString(dict.weight, buf);
00412 (*outputFunc)(outputStream, "/Weight (", 9);
00413 (*outputFunc)(outputStream, buf, strlen(buf));
00414 (*outputFunc)(outputStream, ") readonly def\n", 15);
00415 }
00416 if (dict.isFixedPitch) {
00417 (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
00418 } else {
00419 (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
00420 }
00421 sprintf(buf, "/ItalicAngle %g def\n", dict.italicAngle);
00422 (*outputFunc)(outputStream, buf, strlen(buf));
00423 sprintf(buf, "/UnderlinePosition %g def\n", dict.underlinePosition);
00424 (*outputFunc)(outputStream, buf, strlen(buf));
00425 sprintf(buf, "/UnderlineThickness %g def\n", dict.underlineThickness);
00426 (*outputFunc)(outputStream, buf, strlen(buf));
00427 (*outputFunc)(outputStream, "end readonly def\n", 17);
00428 (*outputFunc)(outputStream, "/FontName /", 11);
00429 (*outputFunc)(outputStream, name->getCString(), name->getLength());
00430 (*outputFunc)(outputStream, " def\n", 5);
00431 sprintf(buf, "/PaintType %d def\n", dict.paintType);
00432 (*outputFunc)(outputStream, buf, strlen(buf));
00433 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
00434 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
00435 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
00436 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
00437 (*outputFunc)(outputStream, buf, strlen(buf));
00438 sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
00439 dict.fontBBox[0], dict.fontBBox[1],
00440 dict.fontBBox[2], dict.fontBBox[3]);
00441 (*outputFunc)(outputStream, buf, strlen(buf));
00442 sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
00443 (*outputFunc)(outputStream, buf, strlen(buf));
00444 if (dict.uniqueID != 0) {
00445 sprintf(buf, "/UniqueID %d def\n", dict.uniqueID);
00446 (*outputFunc)(outputStream, buf, strlen(buf));
00447 }
00448
00449
00450 nGlyphs = getIndexLen((Guchar *)file + dict.charStrings);
00451
00452
00453 glyphNames = readCharset(dict.charset, nGlyphs);
00454
00455
00456 (*outputFunc)(outputStream, "/Encoding ", 10);
00457 if (dict.encoding == 0) {
00458 (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
00459 } else {
00460 (*outputFunc)(outputStream, "256 array\n", 10);
00461 (*outputFunc)(outputStream,
00462 "0 1 255 {1 index exch /.notdef put} for\n", 40);
00463 if (dict.encoding == 1) {
00464 for (i = 0; i < 256; ++i) {
00465 if (expertEncoding[i]) {
00466 sprintf(buf, "dup %d /%s put\n", i, expertEncoding[i]);
00467 (*outputFunc)(outputStream, buf, strlen(buf));
00468 }
00469 }
00470 } else {
00471 ptr = (Guchar *)file + dict.encoding;
00472 encFormat = *ptr++;
00473 if ((encFormat & 0x7f) == 0) {
00474 nCodes = 1 + *ptr++;
00475 if (nCodes > nGlyphs) {
00476 nCodes = nGlyphs;
00477 }
00478 for (i = 1; i < nCodes; ++i) {
00479 c = *ptr++;
00480 sprintf(buf, "dup %d /", c);
00481 (*outputFunc)(outputStream, buf, strlen(buf));
00482 getString(glyphNames[i], buf);
00483 (*outputFunc)(outputStream, buf, strlen(buf));
00484 (*outputFunc)(outputStream, " put\n", 5);
00485 }
00486 } else if ((encFormat & 0x7f) == 1) {
00487 nRanges = *ptr++;
00488 nCodes = 1;
00489 for (i = 0; i < nRanges; ++i) {
00490 c = *ptr++;
00491 nLeft = *ptr++;
00492 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
00493 sprintf(buf, "dup %d /", c);
00494 (*outputFunc)(outputStream, buf, strlen(buf));
00495 getString(glyphNames[nCodes], buf);
00496 (*outputFunc)(outputStream, buf, strlen(buf));
00497 (*outputFunc)(outputStream, " put\n", 5);
00498 ++nCodes;
00499 ++c;
00500 }
00501 }
00502 }
00503 if (encFormat & 0x80) {
00504 nSups = *ptr++;
00505 for (i = 0; i < nSups; ++i) {
00506 c = *ptr++;
00507 sid = getWord(ptr, 2);
00508 ptr += 2;
00509 sprintf(buf, "dup %d /", c);
00510 (*outputFunc)(outputStream, buf, strlen(buf));
00511 getString(sid, buf);
00512 (*outputFunc)(outputStream, buf, strlen(buf));
00513 (*outputFunc)(outputStream, " put\n", 5);
00514 }
00515 }
00516 }
00517 (*outputFunc)(outputStream, "readonly def\n", 13);
00518 }
00519 (*outputFunc)(outputStream, "currentdict end\n", 16);
00520
00521
00522 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
00523 r1 = 55665;
00524 line = 0;
00525
00526
00527 eexecWrite("\x83\xca\x73\xd5");
00528 eexecWrite("dup /Private 32 dict dup begin\n");
00529 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
00530 eexecWrite("/ND {noaccess def} executeonly def\n");
00531 eexecWrite("/NP {noaccess put} executeonly def\n");
00532 eexecWrite("/MinFeature {16 16} ND\n");
00533 readPrivateDict(&privateDict, dict.privateOffset, dict.privateSize);
00534 eexecWrite(privateDict.dictData->getCString());
00535 defaultWidthX = privateDict.defaultWidthX;
00536 defaultWidthXFP = privateDict.defaultWidthXFP;
00537 nominalWidthX = privateDict.nominalWidthX;
00538 nominalWidthXFP = privateDict.nominalWidthXFP;
00539
00540
00541 if (privateDict.subrsOffset != 0) {
00542 subrsIdxPtr = (Guchar *)file + dict.privateOffset +
00543 privateDict.subrsOffset;
00544 nSubrs = getIndexLen(subrsIdxPtr);
00545 sprintf(eBuf, "/Subrs %d array\n", nSubrs);
00546 eexecWrite(eBuf);
00547 idxPtr1 = getIndexValPtr(subrsIdxPtr, 0);
00548 for (i = 0; i < nSubrs; ++i) {
00549 idxPtr0 = idxPtr1;
00550 idxPtr1 = getIndexValPtr(subrsIdxPtr, i+1);
00551 n = idxPtr1 - idxPtr0;
00552 #if 1 //~ Type 2 subrs are unimplemented
00553 error(-1, "Unimplemented Type 2 subrs");
00554 #else
00555 sprintf(eBuf, "dup %d %d RD ", i, n);
00556 eexecWrite(eBuf);
00557 eexecCvtGlyph(idxPtr0, n);
00558 eexecWrite(" NP\n");
00559 #endif
00560 }
00561 eexecWrite("ND\n");
00562 }
00563
00564
00565 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
00566 nCharStrings = getIndexLen(charStringsIdxPtr);
00567 sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
00568 eexecWrite(eBuf);
00569 idxPtr1 = getIndexValPtr(charStringsIdxPtr, 0);
00570 for (i = 0; i < nCharStrings; ++i) {
00571 idxPtr0 = idxPtr1;
00572 idxPtr1 = getIndexValPtr(charStringsIdxPtr, i+1);
00573 n = idxPtr1 - idxPtr0;
00574 eexecCvtGlyph(getString(glyphNames[i], buf), idxPtr0, n);
00575 }
00576 eexecWrite("end\n");
00577 eexecWrite("end\n");
00578 eexecWrite("readonly put\n");
00579 eexecWrite("noaccess put\n");
00580 eexecWrite("dup /FontName get exch definefont pop\n");
00581 eexecWrite("mark currentfile closefile\n");
00582
00583
00584 if (line > 0) {
00585 (*outputFunc)(outputStream, "\n", 1);
00586 }
00587 for (i = 0; i < 8; ++i) {
00588 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
00589 }
00590 (*outputFunc)(outputStream, "cleartomark\n", 12);
00591
00592
00593 delete privateDict.dictData;
00594 if (dict.charset > 2) {
00595 gfree(glyphNames);
00596 }
00597 }
00598
00599 void Type1CFontFile::convertToCIDType0(const char *psName,
00600 FontFileOutputFunc outputFuncA,
00601 void *outputStreamA) {
00602 Type1CTopDict dict;
00603 Type1CPrivateDict *privateDicts;
00604 GString *charStrings;
00605 int *charStringOffsets;
00606 Gushort *charset;
00607 int *cidMap;
00608 Guchar *fdSelect;
00609 Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
00610 char buf[512], buf2[16];
00611 int nGlyphs, nCIDs, gdBytes, nFDs;
00612 int fdSelectFmt, nRanges, gid0, gid1, fd, offset;
00613 int key;
00614 double x;
00615 GBool isFP;
00616 int i, j, k, n;
00617
00618 outputFunc = outputFuncA;
00619 outputStream = outputStreamA;
00620
00621 (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
00622
00623
00624 readTopDict(&dict);
00625
00626
00627 if (dict.fdArrayOffset == 0) {
00628 nFDs = 1;
00629 privateDicts = (Type1CPrivateDict *)
00630 gmalloc(nFDs * sizeof(Type1CPrivateDict));
00631 privateDicts[0].dictData = new GString();
00632 privateDicts[0].subrsOffset = 0;
00633 privateDicts[0].defaultWidthX = 0;
00634 privateDicts[0].defaultWidthXFP = gFalse;
00635 privateDicts[0].nominalWidthX = 0;
00636 privateDicts[0].nominalWidthXFP = gFalse;
00637 } else {
00638 fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
00639 nFDs = getIndexLen(fdArrayIdx);
00640 privateDicts = (Type1CPrivateDict *)
00641 gmalloc(nFDs * sizeof(Type1CPrivateDict));
00642 idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
00643 for (i = 0; i < nFDs; ++i) {
00644 privateDicts[i].dictData = NULL;
00645 idxPtr0 = idxPtr1;
00646 idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
00647 ptr = idxPtr0;
00648 j = 0;
00649 while (ptr < idxPtr1) {
00650 if (*ptr <= 27 || *ptr == 31) {
00651 key = *ptr++;
00652 if (key == 0x0c) {
00653 key = (key << 8) | *ptr++;
00654 }
00655 if (key == 0x0012) {
00656 readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
00657 }
00658 j = 0;
00659 } else {
00660 x = getNum(&ptr, &isFP);
00661 if (j < 48) {
00662 op[j] = x;
00663 fp[j++] = isFP;
00664 }
00665 }
00666 }
00667 if (!privateDicts[i].dictData) {
00668 privateDicts[i].dictData = new GString();
00669 privateDicts[i].subrsOffset = 0;
00670 privateDicts[i].defaultWidthX = 0;
00671 privateDicts[i].defaultWidthXFP = gFalse;
00672 privateDicts[i].nominalWidthX = 0;
00673 privateDicts[i].nominalWidthXFP = gFalse;
00674 }
00675 }
00676 }
00677
00678
00679 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
00680 nGlyphs = getIndexLen(charStringsIdxPtr);
00681
00682
00683 fdSelect = (Guchar *)gmalloc(nGlyphs);
00684 if (dict.fdSelectOffset == 0) {
00685 for (i = 0; i < nGlyphs; ++i) {
00686 fdSelect[i] = 0;
00687 }
00688 } else {
00689 ptr = (Guchar *)file + dict.fdSelectOffset;
00690 fdSelectFmt = *ptr++;
00691 if (fdSelectFmt == 0) {
00692 memcpy(fdSelect, ptr, nGlyphs);
00693 } else if (fdSelectFmt == 3) {
00694 nRanges = getWord(ptr, 2);
00695 ptr += 2;
00696 gid0 = getWord(ptr, 2);
00697 ptr += 2;
00698 for (i = 1; i <= nRanges; ++i) {
00699 fd = *ptr++;
00700 gid1 = getWord(ptr, 2);
00701 ptr += 2;
00702 for (j = gid0; j < gid1; ++j) {
00703 fdSelect[j] = fd;
00704 }
00705 gid0 = gid1;
00706 }
00707 } else {
00708 error(-1, "Unknown FDSelect table format in CID font");
00709 for (i = 0; i < nGlyphs; ++i) {
00710 fdSelect[i] = 0;
00711 }
00712 }
00713 }
00714
00715
00716 charset = readCharset(dict.charset, nGlyphs);
00717 nCIDs = 0;
00718 for (i = 0; i < nGlyphs; ++i) {
00719 if (charset[i] >= nCIDs) {
00720 nCIDs = charset[i] + 1;
00721 }
00722 }
00723 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
00724 for (i = 0; i < nCIDs; ++i) {
00725 cidMap[i] = -1;
00726 }
00727 for (i = 0; i < nGlyphs; ++i) {
00728 cidMap[charset[i]] = i;
00729 }
00730
00731
00732 charStrings = new GString();
00733 charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
00734 for (i = 0; i < nCIDs; ++i) {
00735 charStringOffsets[i] = charStrings->getLength();
00736 if (cidMap[i] >= 0) {
00737 idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i]);
00738 idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i]+1);
00739 n = idxPtr1 - idxPtr0;
00740 j = fdSelect[cidMap[i]];
00741 defaultWidthX = privateDicts[j].defaultWidthX;
00742 defaultWidthXFP = privateDicts[j].defaultWidthXFP;
00743 nominalWidthX = privateDicts[j].nominalWidthX;
00744 nominalWidthXFP = privateDicts[j].nominalWidthXFP;
00745 cvtGlyph(idxPtr0, n);
00746 charStrings->append(charBuf);
00747 delete charBuf;
00748 }
00749 }
00750 charStringOffsets[nCIDs] = charStrings->getLength();
00751
00752
00753
00754
00755
00756 i = (nCIDs + 1) * 5 + charStrings->getLength();
00757 if (i < 0x100) {
00758 gdBytes = 1;
00759 } else if (i < 0x10000) {
00760 gdBytes = 2;
00761 } else if (i < 0x1000000) {
00762 gdBytes = 3;
00763 } else {
00764 gdBytes = 4;
00765 }
00766
00767
00768 (*outputFunc)(outputStream, "20 dict begin\n", 14);
00769 (*outputFunc)(outputStream, "/CIDFontName /", 14);
00770 (*outputFunc)(outputStream, psName, strlen(psName));
00771 (*outputFunc)(outputStream, " def\n", 5);
00772 (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
00773 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
00774 if (dict.registry > 0 && dict.ordering > 0) {
00775 getString(dict.registry, buf);
00776 (*outputFunc)(outputStream, " /Registry (", 13);
00777 (*outputFunc)(outputStream, buf, strlen(buf));
00778 (*outputFunc)(outputStream, ") def\n", 6);
00779 getString(dict.ordering, buf);
00780 (*outputFunc)(outputStream, " /Ordering (", 13);
00781 (*outputFunc)(outputStream, buf, strlen(buf));
00782 (*outputFunc)(outputStream, ") def\n", 6);
00783 } else {
00784 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
00785 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
00786 }
00787 sprintf(buf, " /Supplement %d def\n", dict.supplement);
00788 (*outputFunc)(outputStream, buf, strlen(buf));
00789 (*outputFunc)(outputStream, "end def\n", 8);
00790 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
00791 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
00792 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
00793 (*outputFunc)(outputStream, buf, strlen(buf));
00794 sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
00795 dict.fontBBox[0], dict.fontBBox[1],
00796 dict.fontBBox[2], dict.fontBBox[3]);
00797 (*outputFunc)(outputStream, buf, strlen(buf));
00798 (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
00799 (*outputFunc)(outputStream, " /FSType 8 def\n", 16);
00800 (*outputFunc)(outputStream, "end def\n", 8);
00801
00802
00803 sprintf(buf, "/CIDCount %d def\n", nCIDs);
00804 (*outputFunc)(outputStream, buf, strlen(buf));
00805 (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
00806 sprintf(buf, "/GDBytes %d def\n", gdBytes);
00807 (*outputFunc)(outputStream, buf, strlen(buf));
00808 (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
00809 if (dict.paintType != 0) {
00810 sprintf(buf, "/PaintType %d def\n", dict.paintType);
00811 (*outputFunc)(outputStream, buf, strlen(buf));
00812 sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
00813 (*outputFunc)(outputStream, buf, strlen(buf));
00814 }
00815
00816
00817 sprintf(buf, "/FDArray %d array\n", nFDs);
00818 (*outputFunc)(outputStream, buf, strlen(buf));
00819 for (i = 0; i < nFDs; ++i) {
00820 sprintf(buf, "dup %d 10 dict begin\n", i);
00821 (*outputFunc)(outputStream, buf, strlen(buf));
00822 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
00823 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
00824 sprintf(buf, "/PaintType %d def\n", dict.paintType);
00825 (*outputFunc)(outputStream, buf, strlen(buf));
00826 (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
00827 (*outputFunc)(outputStream, privateDicts[i].dictData->getCString(),
00828 privateDicts[i].dictData->getLength());
00829 (*outputFunc)(outputStream, "currentdict end def\n", 20);
00830 (*outputFunc)(outputStream, "currentdict end put\n", 20);
00831 }
00832 (*outputFunc)(outputStream, "def\n", 4);
00833
00834
00835
00836
00837 offset = (nCIDs + 1) * (1 + gdBytes);
00838 sprintf(buf, "(Hex) %d StartData\n",
00839 offset + charStrings->getLength());
00840 (*outputFunc)(outputStream, buf, strlen(buf));
00841
00842
00843 for (i = 0; i <= nCIDs; i += 6) {
00844 for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
00845 if (i+j < nCIDs && cidMap[i+j] >= 0) {
00846 buf[0] = (char)fdSelect[cidMap[i+j]];
00847 } else {
00848 buf[0] = (char)0;
00849 }
00850 n = offset + charStringOffsets[i+j];
00851 for (k = gdBytes; k >= 1; --k) {
00852 buf[k] = (char)(n & 0xff);
00853 n >>= 8;
00854 }
00855 for (k = 0; k <= gdBytes; ++k) {
00856 sprintf(buf2, "%02x", buf[k] & 0xff);
00857 (*outputFunc)(outputStream, buf2, 2);
00858 }
00859 }
00860 (*outputFunc)(outputStream, "\n", 1);
00861 }
00862
00863
00864 n = charStrings->getLength();
00865 for (i = 0; i < n; i += 32) {
00866 for (j = 0; j < 32 && i+j < n; ++j) {
00867 sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
00868 (*outputFunc)(outputStream, buf, strlen(buf));
00869 }
00870 if (i + 32 >= n) {
00871 (*outputFunc)(outputStream, ">", 1);
00872 }
00873 (*outputFunc)(outputStream, "\n", 1);
00874 }
00875
00876 for (i = 0; i < nFDs; ++i) {
00877 delete privateDicts[i].dictData;
00878 }
00879 gfree(privateDicts);
00880 gfree(cidMap);
00881 gfree(charset);
00882 gfree(charStringOffsets);
00883 delete charStrings;
00884 gfree(fdSelect);
00885 }
00886
00887 void Type1CFontFile::convertToType0(const char *psName,
00888 FontFileOutputFunc outputFuncA,
00889 void *outputStreamA) {
00890 Type1CTopDict dict;
00891 Type1CPrivateDict *privateDicts;
00892 Gushort *charset;
00893 int *cidMap;
00894 Guchar *fdSelect;
00895 Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
00896 char buf[512];
00897 char eBuf[256];
00898 int nGlyphs, nCIDs, nFDs;
00899 int fdSelectFmt, nRanges, gid0, gid1, fd;
00900 int key;
00901 double x;
00902 GBool isFP;
00903 int i, j, n;
00904
00905 outputFunc = outputFuncA;
00906 outputStream = outputStreamA;
00907
00908
00909 readTopDict(&dict);
00910
00911
00912 if (dict.fdArrayOffset == 0) {
00913 nFDs = 1;
00914 privateDicts = (Type1CPrivateDict *)
00915 gmalloc(nFDs * sizeof(Type1CPrivateDict));
00916 privateDicts[0].dictData = new GString();
00917 privateDicts[0].subrsOffset = 0;
00918 privateDicts[0].defaultWidthX = 0;
00919 privateDicts[0].defaultWidthXFP = gFalse;
00920 privateDicts[0].nominalWidthX = 0;
00921 privateDicts[0].nominalWidthXFP = gFalse;
00922 } else {
00923 fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
00924 nFDs = getIndexLen(fdArrayIdx);
00925 privateDicts = (Type1CPrivateDict *)
00926 gmalloc(nFDs * sizeof(Type1CPrivateDict));
00927 idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
00928 for (i = 0; i < nFDs; ++i) {
00929 privateDicts[i].dictData = NULL;
00930 idxPtr0 = idxPtr1;
00931 idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
00932 ptr = idxPtr0;
00933 j = 0;
00934 while (ptr < idxPtr1) {
00935 if (*ptr <= 27 || *ptr == 31) {
00936 key = *ptr++;
00937 if (key == 0x0c) {
00938 key = (key << 8) | *ptr++;
00939 }
00940 if (key == 0x0012) {
00941 readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
00942 }
00943 j = 0;
00944 } else {
00945 x = getNum(&ptr, &isFP);
00946 if (j < 48) {
00947 op[j] = x;
00948 fp[j++] = isFP;
00949 }
00950 }
00951 }
00952 if (!privateDicts[i].dictData) {
00953 privateDicts[i].dictData = new GString();
00954 privateDicts[i].subrsOffset = 0;
00955 privateDicts[i].defaultWidthX = 0;
00956 privateDicts[i].defaultWidthXFP = gFalse;
00957 privateDicts[i].nominalWidthX = 0;
00958 privateDicts[i].nominalWidthXFP = gFalse;
00959 }
00960 }
00961 }
00962
00963
00964 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
00965 nGlyphs = getIndexLen(charStringsIdxPtr);
00966
00967
00968 fdSelect = (Guchar *)gmalloc(nGlyphs);
00969 if (dict.fdSelectOffset == 0) {
00970 for (i = 0; i < nGlyphs; ++i) {
00971 fdSelect[i] = 0;
00972 }
00973 } else {
00974 ptr = (Guchar *)file + dict.fdSelectOffset;
00975 fdSelectFmt = *ptr++;
00976 if (fdSelectFmt == 0) {
00977 memcpy(fdSelect, ptr, nGlyphs);
00978 } else if (fdSelectFmt == 3) {
00979 nRanges = getWord(ptr, 2);
00980 ptr += 2;
00981 gid0 = getWord(ptr, 2);
00982 ptr += 2;
00983 for (i = 1; i <= nRanges; ++i) {
00984 fd = *ptr++;
00985 gid1 = getWord(ptr, 2);
00986 ptr += 2;
00987 for (j = gid0; j < gid1; ++j) {
00988 fdSelect[j] = fd;
00989 }
00990 gid0 = gid1;
00991 }
00992 } else {
00993 error(-1, "Unknown FDSelect table format in CID font");
00994 for (i = 0; i < nGlyphs; ++i) {
00995 fdSelect[i] = 0;
00996 }
00997 }
00998 }
00999
01000
01001 charset = readCharset(dict.charset, nGlyphs);
01002 nCIDs = 0;
01003 for (i = 0; i < nGlyphs; ++i) {
01004 if (charset[i] >= nCIDs) {
01005 nCIDs = charset[i] + 1;
01006 }
01007 }
01008 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
01009 for (i = 0; i < nCIDs; ++i) {
01010 cidMap[i] = -1;
01011 }
01012 for (i = 0; i < nGlyphs; ++i) {
01013 cidMap[charset[i]] = i;
01014 }
01015
01016
01017 for (i = 0; i < nCIDs; i += 256) {
01018
01019
01020
01021
01022 fd = 0;
01023 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
01024 if (cidMap[i+j] >= 0) {
01025 fd = fdSelect[cidMap[i+j]];
01026 break;
01027 }
01028 }
01029
01030
01031 (*outputFunc)(outputStream, "16 dict begin\n", 14);
01032 (*outputFunc)(outputStream, "/FontName /", 11);
01033 (*outputFunc)(outputStream, psName, strlen(psName));
01034 sprintf(buf, "_%02x def\n", i >> 8);
01035 (*outputFunc)(outputStream, buf, strlen(buf));
01036 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
01037 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
01038 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
01039 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
01040 (*outputFunc)(outputStream, buf, strlen(buf));
01041 sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
01042 dict.fontBBox[0], dict.fontBBox[1],
01043 dict.fontBBox[2], dict.fontBBox[3]);
01044 (*outputFunc)(outputStream, buf, strlen(buf));
01045 sprintf(buf, "/PaintType %d def\n", dict.paintType);
01046 (*outputFunc)(outputStream, buf, strlen(buf));
01047 if (dict.paintType != 0) {
01048 sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
01049 (*outputFunc)(outputStream, buf, strlen(buf));
01050 }
01051 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
01052 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
01053 sprintf(buf, "dup %d /c%02x put\n", j, j);
01054 (*outputFunc)(outputStream, buf, strlen(buf));
01055 }
01056 (*outputFunc)(outputStream, "readonly def\n", 13);
01057 (*outputFunc)(outputStream, "currentdict end\n", 16);
01058
01059
01060 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
01061 r1 = 55665;
01062 line = 0;
01063
01064
01065 eexecWrite("\x83\xca\x73\xd5");
01066 eexecWrite("dup /Private 32 dict dup begin\n");
01067 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
01068 eexecWrite("/ND {noaccess def} executeonly def\n");
01069 eexecWrite("/NP {noaccess put} executeonly def\n");
01070 eexecWrite("/MinFeature {16 16} ND\n");
01071 eexecWrite(privateDicts[fd].dictData->getCString());
01072 defaultWidthX = privateDicts[fd].defaultWidthX;
01073 defaultWidthXFP = privateDicts[fd].defaultWidthXFP;
01074 nominalWidthX = privateDicts[fd].nominalWidthX;
01075 nominalWidthXFP = privateDicts[fd].nominalWidthXFP;
01076
01077
01078 sprintf(eBuf, "2 index /CharStrings 256 dict dup begin\n");
01079 eexecWrite(eBuf);
01080
01081
01082 idxPtr0 = getIndexValPtr(charStringsIdxPtr, 0);
01083 idxPtr1 = getIndexValPtr(charStringsIdxPtr, 1);
01084 n = idxPtr1 - idxPtr0;
01085 eexecCvtGlyph(".notdef", idxPtr0, n);
01086
01087
01088 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
01089 if (cidMap[i+j] >= 0) {
01090 idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]);
01091 idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]+1);
01092 n = idxPtr1 - idxPtr0;
01093 sprintf(buf, "c%02x", j);
01094 eexecCvtGlyph(buf, idxPtr0, n);
01095 }
01096 }
01097 eexecWrite("end\n");
01098 eexecWrite("end\n");
01099 eexecWrite("readonly put\n");
01100 eexecWrite("noaccess put\n");
01101 eexecWrite("dup /FontName get exch definefont pop\n");
01102 eexecWrite("mark currentfile closefile\n");
01103
01104
01105 if (line > 0) {
01106 (*outputFunc)(outputStream, "\n", 1);
01107 }
01108 for (j = 0; j < 8; ++j) {
01109 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
01110 }
01111 (*outputFunc)(outputStream, "cleartomark\n", 12);
01112 }
01113
01114
01115 (*outputFunc)(outputStream, "16 dict begin\n", 14);
01116 (*outputFunc)(outputStream, "/FontName /", 11);
01117 (*outputFunc)(outputStream, psName, strlen(psName));
01118 (*outputFunc)(outputStream, " def\n", 5);
01119 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
01120 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
01121 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
01122 (*outputFunc)(outputStream, "/Encoding [\n", 12);
01123 for (i = 0; i < nCIDs; i += 256) {
01124 sprintf(buf, "%d\n", i >> 8);
01125 (*outputFunc)(outputStream, buf, strlen(buf));
01126 }
01127 (*outputFunc)(outputStream, "] def\n", 6);
01128 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
01129 for (i = 0; i < nCIDs; i += 256) {
01130 (*outputFunc)(outputStream, "/", 1);
01131 (*outputFunc)(outputStream, psName, strlen(psName));
01132 sprintf(buf, "_%02x findfont\n", i >> 8);
01133 (*outputFunc)(outputStream, buf, strlen(buf));
01134 }
01135 (*outputFunc)(outputStream, "] def\n", 6);
01136 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
01137
01138
01139 for (i = 0; i < nFDs; ++i) {
01140 delete privateDicts[i].dictData;
01141 }
01142 gfree(privateDicts);
01143 gfree(cidMap);
01144 gfree(charset);
01145 gfree(fdSelect);
01146 }
01147
01148 void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
01149 Guchar *idxPtr0, *idxPtr1, *ptr;
01150 double x;
01151 GBool isFP;
01152 int key;
01153 int i;
01154
01155 idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
01156 idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
01157 dict->version = 0;
01158 dict->notice = 0;
01159 dict->copyright = 0;
01160 dict->fullName = 0;
01161 dict->familyName = 0;
01162 dict->weight = 0;
01163 dict->isFixedPitch = 0;
01164 dict->italicAngle = 0;
01165 dict->underlinePosition = -100;
01166 dict->underlineThickness = 50;
01167 dict->paintType = 0;
01168 dict->charstringType = 2;
01169 dict->fontMatrix[0] = 0.001;
01170 dict->fontMatrix[1] = 0;
01171 dict->fontMatrix[2] = 0;
01172 dict->fontMatrix[3] = 0.001;
01173 dict->fontMatrix[4] = 0;
01174 dict->fontMatrix[5] = 0;
01175 dict->uniqueID = 0;
01176 dict->fontBBox[0] = 0;
01177 dict->fontBBox[1] = 0;
01178 dict->fontBBox[2] = 0;
01179 dict->fontBBox[3] = 0;
01180 dict->strokeWidth = 0;
01181 dict->charset = 0;
01182 dict->encoding = 0;
01183 dict->charStrings = 0;
01184 dict->privateSize = 0;
01185 dict->privateOffset = 0;
01186 dict->registry = 0;
01187 dict->ordering = 0;
01188 dict->supplement = 0;
01189 dict->fdArrayOffset = 0;
01190 dict->fdSelectOffset = 0;
01191 i = 0;
01192 ptr = idxPtr0;
01193 while (ptr < idxPtr1) {
01194 if (*ptr <= 27 || *ptr == 31) {
01195 key = *ptr++;
01196 if (key == 0x0c) {
01197 key = (key << 8) | *ptr++;
01198 }
01199 switch (key) {
01200 case 0x0000: dict->version = (int)op[0]; break;
01201 case 0x0001: dict->notice = (int)op[0]; break;
01202 case 0x0c00: dict->copyright = (int)op[0]; break;
01203 case 0x0002: dict->fullName = (int)op[0]; break;
01204 case 0x0003: dict->familyName = (int)op[0]; break;
01205 case 0x0004: dict->weight = (int)op[0]; break;
01206 case 0x0c01: dict->isFixedPitch = (int)op[0]; break;
01207 case 0x0c02: dict->italicAngle = op[0]; break;
01208 case 0x0c03: dict->underlinePosition = op[0]; break;
01209 case 0x0c04: dict->underlineThickness = op[0]; break;
01210 case 0x0c05: dict->paintType = (int)op[0]; break;
01211 case 0x0c06: dict->charstringType = (int)op[0]; break;
01212 case 0x0c07: dict->fontMatrix[0] = op[0];
01213 dict->fontMatrix[1] = op[1];
01214 dict->fontMatrix[2] = op[2];
01215 dict->fontMatrix[3] = op[3];
01216 dict->fontMatrix[4] = op[4];
01217 dict->fontMatrix[5] = op[5]; break;
01218 case 0x000d: dict->uniqueID = (int)op[0]; break;
01219 case 0x0005: dict->fontBBox[0] = op[0];
01220 dict->fontBBox[1] = op[1];
01221 dict->fontBBox[2] = op[2];
01222 dict->fontBBox[3] = op[3]; break;
01223 case 0x0c08: dict->strokeWidth = op[0]; break;
01224 case 0x000f: dict->charset = (int)op[0]; break;
01225 case 0x0010: dict->encoding = (int)op[0]; break;
01226 case 0x0011: dict->charStrings = (int)op[0]; break;
01227 case 0x0012: dict->privateSize = (int)op[0];
01228 dict->privateOffset = (int)op[1]; break;
01229 case 0x0c1e: dict->registry = (int)op[0];
01230 dict->ordering = (int)op[1];
01231 dict->supplement = (int)op[2]; break;
01232 case 0x0c24: dict->fdArrayOffset = (int)op[0]; break;
01233 case 0x0c25: dict->fdSelectOffset = (int)op[0]; break;
01234 }
01235 i = 0;
01236 } else {
01237 x = getNum(&ptr, &isFP);
01238 if (i < 48) {
01239 op[i] = x;
01240 fp[i++] = isFP;
01241 }
01242 }
01243 }
01244 }
01245
01246 void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
01247 int offset, int size) {
01248 Guchar *idxPtr0, *idxPtr1, *ptr;
01249 char eBuf[256];
01250 int key;
01251 double x;
01252 GBool isFP;
01253 int i;
01254
01255 privateDict->dictData = new GString();
01256 privateDict->subrsOffset = 0;
01257 privateDict->defaultWidthX = 0;
01258 privateDict->defaultWidthXFP = gFalse;
01259 privateDict->nominalWidthX = 0;
01260 privateDict->nominalWidthXFP = gFalse;
01261 idxPtr0 = (Guchar *)file + offset;
01262 idxPtr1 = idxPtr0 + size;
01263 ptr = idxPtr0;
01264 i = 0;
01265 while (ptr < idxPtr1) {
01266 if (*ptr <= 27 || *ptr == 31) {
01267 key = *ptr++;
01268 if (key == 0x0c) {
01269 key = (key << 8) | *ptr++;
01270 }
01271 switch (key) {
01272 case 0x0006:
01273 getDeltaInt(eBuf, "BlueValues", op, i);
01274 privateDict->dictData->append(eBuf);
01275 break;
01276 case 0x0007:
01277 getDeltaInt(eBuf, "OtherBlues", op, i);
01278 privateDict->dictData->append(eBuf);
01279 break;
01280 case 0x0008:
01281 getDeltaInt(eBuf, "FamilyBlues", op, i);
01282 privateDict->dictData->append(eBuf);
01283 break;
01284 case 0x0009:
01285 getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
01286 privateDict->dictData->append(eBuf);
01287 break;
01288 case 0x0c09:
01289 sprintf(eBuf, "/BlueScale %g def\n", op[0]);
01290 privateDict->dictData->append(eBuf);
01291 break;
01292 case 0x0c0a:
01293 sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
01294 privateDict->dictData->append(eBuf);
01295 break;
01296 case 0x0c0b:
01297 sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
01298 privateDict->dictData->append(eBuf);
01299 break;
01300 case 0x000a:
01301 sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
01302 privateDict->dictData->append(eBuf);
01303 break;
01304 case 0x000b:
01305 sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
01306 privateDict->dictData->append(eBuf);
01307 break;
01308 case 0x0c0c:
01309 getDeltaReal(eBuf, "StemSnapH", op, i);
01310 privateDict->dictData->append(eBuf);
01311 break;
01312 case 0x0c0d:
01313 getDeltaReal(eBuf, "StemSnapV", op, i);
01314 privateDict->dictData->append(eBuf);
01315 break;
01316 case 0x0c0e:
01317 sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
01318 privateDict->dictData->append(eBuf);
01319 break;
01320 case 0x0c0f:
01321 sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
01322 privateDict->dictData->append(eBuf);
01323 break;
01324 case 0x0c11:
01325 sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
01326 privateDict->dictData->append(eBuf);
01327 break;
01328 case 0x0c12:
01329 sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
01330 privateDict->dictData->append(eBuf);
01331 break;
01332 case 0x0c13:
01333 error(-1, "Got Type 1C InitialRandomSeed");
01334 break;
01335 case 0x0013:
01336 privateDict->subrsOffset = (int)op[0];
01337 break;
01338 case 0x0014:
01339 privateDict->defaultWidthX = op[0];
01340 privateDict->defaultWidthXFP = fp[0];
01341 break;
01342 case 0x0015:
01343 privateDict->nominalWidthX = op[0];
01344 privateDict->nominalWidthXFP = fp[0];
01345 break;
01346 default:
01347 error(-1, "Unknown Type 1C private dict entry %04x", key);
01348 break;
01349 }
01350 i = 0;
01351 } else {
01352 x = getNum(&ptr, &isFP);
01353 if (i < 48) {
01354 op[i] = x;
01355 fp[i++] = isFP;
01356 }
01357 }
01358 }
01359 }
01360
01361 Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
01362 Gushort *glyphNames;
01363 Guchar *ptr;
01364 int charsetFormat, c;
01365 int nLeft, i, j;
01366
01367 if (charset == 0) {
01368 glyphNames = type1CISOAdobeCharset;
01369 } else if (charset == 1) {
01370 glyphNames = type1CExpertCharset;
01371 } else if (charset == 2) {
01372 glyphNames = type1CExpertSubsetCharset;
01373 } else {
01374 glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
01375 glyphNames[0] = 0;
01376 ptr = (Guchar *)file + charset;
01377 charsetFormat = *ptr++;
01378 if (charsetFormat == 0) {
01379 for (i = 1; i < nGlyphs; ++i) {
01380 glyphNames[i] = getWord(ptr, 2);
01381 ptr += 2;
01382 }
01383 } else if (charsetFormat == 1) {
01384 i = 1;
01385 while (i < nGlyphs) {
01386 c = getWord(ptr, 2);
01387 ptr += 2;
01388 nLeft = *ptr++;
01389 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
01390 glyphNames[i++] = c++;
01391 }
01392 }
01393 } else if (charsetFormat == 2) {
01394 i = 1;
01395 while (i < nGlyphs) {
01396 c = getWord(ptr, 2);
01397 ptr += 2;
01398 nLeft = getWord(ptr, 2);
01399 ptr += 2;
01400 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
01401 glyphNames[i++] = c++;
01402 }
01403 }
01404 }
01405 }
01406 return glyphNames;
01407 }
01408
01409 void Type1CFontFile::eexecWrite(const char *s) {
01410 const Guchar *p;
01411 Guchar x;
01412
01413 for (p = (const Guchar *)s; *p; ++p) {
01414 x = *p ^ (r1 >> 8);
01415 r1 = (x + r1) * 52845 + 22719;
01416 (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
01417 (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
01418 line += 2;
01419 if (line == 64) {
01420 (*outputFunc)(outputStream, "\n", 1);
01421 line = 0;
01422 }
01423 }
01424 }
01425
01426 void Type1CFontFile::eexecCvtGlyph(const char *glyphName, const Guchar *s, int n) {
01427 char eBuf[256];
01428
01429 cvtGlyph(s, n);
01430 sprintf(eBuf, "/%s %d RD ", glyphName, charBuf->getLength());
01431 eexecWrite(eBuf);
01432 eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
01433 eexecWrite(" ND\n");
01434 delete charBuf;
01435 }
01436
01437 void Type1CFontFile::cvtGlyph(const Guchar *s, int n) {
01438 int nHints;
01439 int x;
01440 GBool first = gTrue;
01441 double d, dx, dy;
01442 GBool dFP;
01443 Gushort r2;
01444 Guchar byte;
01445 int i, k;
01446
01447 charBuf = new GString();
01448 charBuf->append((char)73);
01449 charBuf->append((char)58);
01450 charBuf->append((char)147);
01451 charBuf->append((char)134);
01452
01453 i = 0;
01454 nOps = 0;
01455 nHints = 0;
01456 while (i < n) {
01457 if (s[i] == 12) {
01458 switch (s[i+1]) {
01459 case 0:
01460
01461 break;
01462 case 34:
01463 if (nOps != 7) {
01464 error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
01465 }
01466 eexecDumpNum(op[0], fp[0]);
01467 eexecDumpNum(0, gFalse);
01468 eexecDumpNum(op[1], fp[1]);
01469 eexecDumpNum(op[2], fp[2]);
01470 eexecDumpNum(op[3], fp[3]);
01471 eexecDumpNum(0, gFalse);
01472 eexecDumpOp1(8);
01473 eexecDumpNum(op[4], fp[4]);
01474 eexecDumpNum(0, gFalse);
01475 eexecDumpNum(op[5], fp[5]);
01476 eexecDumpNum(-op[2], fp[2]);
01477 eexecDumpNum(op[6], fp[6]);
01478 eexecDumpNum(0, gFalse);
01479 eexecDumpOp1(8);
01480 break;
01481 case 35:
01482 if (nOps != 13) {
01483 error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
01484 }
01485 eexecDumpNum(op[0], fp[0]);
01486 eexecDumpNum(op[1], fp[1]);
01487 eexecDumpNum(op[2], fp[2]);
01488 eexecDumpNum(op[3], fp[3]);
01489 eexecDumpNum(op[4], fp[4]);
01490 eexecDumpNum(op[5], fp[5]);
01491 eexecDumpOp1(8);
01492 eexecDumpNum(op[6], fp[6]);
01493 eexecDumpNum(op[7], fp[7]);
01494 eexecDumpNum(op[8], fp[8]);
01495 eexecDumpNum(op[9], fp[9]);
01496 eexecDumpNum(op[10], fp[10]);
01497 eexecDumpNum(op[11], fp[11]);
01498 eexecDumpOp1(8);
01499 break;
01500 case 36:
01501 if (nOps != 9) {
01502 error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
01503 }
01504 eexecDumpNum(op[0], fp[0]);
01505 eexecDumpNum(op[1], fp[1]);
01506 eexecDumpNum(op[2], fp[2]);
01507 eexecDumpNum(op[3], fp[3]);
01508 eexecDumpNum(op[4], fp[4]);
01509 eexecDumpNum(0, gFalse);
01510 eexecDumpOp1(8);
01511 eexecDumpNum(op[5], fp[5]);
01512 eexecDumpNum(0, gFalse);
01513 eexecDumpNum(op[6], fp[6]);
01514 eexecDumpNum(op[7], fp[7]);
01515 eexecDumpNum(op[8], fp[8]);
01516 eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
01517 eexecDumpOp1(8);
01518 break;
01519 case 37:
01520 if (nOps != 11) {
01521 error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
01522 }
01523 eexecDumpNum(op[0], fp[0]);
01524 eexecDumpNum(op[1], fp[1]);
01525 eexecDumpNum(op[2], fp[2]);
01526 eexecDumpNum(op[3], fp[3]);
01527 eexecDumpNum(op[4], fp[4]);
01528 eexecDumpNum(op[5], fp[5]);
01529 eexecDumpOp1(8);
01530 eexecDumpNum(op[6], fp[6]);
01531 eexecDumpNum(op[7], fp[7]);
01532 eexecDumpNum(op[8], fp[8]);
01533 eexecDumpNum(op[9], fp[9]);
01534 dx = op[0] + op[2] + op[4] + op[6] + op[8];
01535 dy = op[1] + op[3] + op[5] + op[7] + op[9];
01536 if (fabs(dx) > fabs(dy)) {
01537 eexecDumpNum(op[10], fp[10]);
01538 eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
01539 } else {
01540 eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
01541 eexecDumpNum(op[10], fp[10]);
01542 }
01543 eexecDumpOp1(8);
01544 break;
01545 case 3:
01546 case 4:
01547 case 5:
01548 case 8:
01549 case 9:
01550 case 10:
01551 case 11:
01552 case 12:
01553 case 13:
01554 case 14:
01555 case 15:
01556 case 18:
01557 case 20:
01558 case 21:
01559 case 22:
01560 case 23:
01561 case 24:
01562 case 26:
01563 case 27:
01564 case 28:
01565 case 29:
01566 case 30:
01567 error(-1, "Unimplemented Type 2 charstring op: 12.%d", s[i+1]);
01568 break;
01569 default:
01570 error(-1, "Illegal Type 2 charstring op: 12.%d", s[i+1]);
01571 break;
01572 }
01573 i += 2;
01574 nOps = 0;
01575 } else if (s[i] == 19) {
01576
01577 if (first) {
01578 cvtGlyphWidth(nOps == 1);
01579 first = gFalse;
01580 }
01581 if (nOps > 0) {
01582 if (nOps & 1) {
01583 error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
01584 nOps);
01585 }
01586 nHints += nOps / 2;
01587 }
01588 i += 1 + ((nHints + 7) >> 3);
01589 nOps = 0;
01590 } else if (s[i] == 20) {
01591
01592 if (first) {
01593 cvtGlyphWidth(nOps == 1);
01594 first = gFalse;
01595 }
01596 if (nOps > 0) {
01597 if (nOps & 1) {
01598 error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
01599 nOps);
01600 }
01601 nHints += nOps / 2;
01602 }
01603 i += 1 + ((nHints + 7) >> 3);
01604 nOps = 0;
01605 } else if (s[i] == 28) {
01606 x = (s[i+1] << 8) + s[i+2];
01607 if (x & 0x8000) {
01608 x |= -1 << 15;
01609 }
01610 if (nOps < 48) {
01611 fp[nOps] = gFalse;
01612 op[nOps++] = x;
01613 }
01614 i += 3;
01615 } else if (s[i] <= 31) {
01616 switch (s[i]) {
01617 case 4:
01618 if (first) {
01619 cvtGlyphWidth(nOps == 2);
01620 first = gFalse;
01621 }
01622 if (nOps != 1) {
01623 error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
01624 }
01625 eexecDumpNum(op[0], fp[0]);
01626 eexecDumpOp1(4);
01627 break;
01628 case 5:
01629 if (nOps < 2 || nOps % 2 != 0) {
01630 error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
01631 }
01632 for (k = 0; k < nOps; k += 2) {
01633 eexecDumpNum(op[k], fp[k]);
01634 eexecDumpNum(op[k+1], fp[k+1]);
01635 eexecDumpOp1(5);
01636 }
01637 break;
01638 case 6:
01639 if (nOps < 1) {
01640 error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
01641 }
01642 for (k = 0; k < nOps; ++k) {
01643 eexecDumpNum(op[k], fp[k]);
01644 eexecDumpOp1((k & 1) ? 7 : 6);
01645 }
01646 break;
01647 case 7:
01648 if (nOps < 1) {
01649 error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
01650 }
01651 for (k = 0; k < nOps; ++k) {
01652 eexecDumpNum(op[k], fp[k]);
01653 eexecDumpOp1((k & 1) ? 6 : 7);
01654 }
01655 break;
01656 case 8:
01657 if (nOps < 6 || nOps % 6 != 0) {
01658 error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
01659 }
01660 for (k = 0; k < nOps; k += 6) {
01661 eexecDumpNum(op[k], fp[k]);
01662 eexecDumpNum(op[k+1], fp[k+1]);
01663 eexecDumpNum(op[k+2], fp[k+2]);
01664 eexecDumpNum(op[k+3], fp[k+3]);
01665 eexecDumpNum(op[k+4], fp[k+4]);
01666 eexecDumpNum(op[k+5], fp[k+5]);
01667 eexecDumpOp1(8);
01668 }
01669 break;
01670 case 14:
01671 if (first) {
01672 cvtGlyphWidth(nOps == 1 || nOps == 5);
01673 first = gFalse;
01674 }
01675 if (nOps == 4) {
01676 eexecDumpNum(0, 0);
01677 eexecDumpNum(op[0], fp[0]);
01678 eexecDumpNum(op[1], fp[1]);
01679 eexecDumpNum(op[2], fp[2]);
01680 eexecDumpNum(op[3], fp[3]);
01681 eexecDumpOp2(6);
01682 } else if (nOps == 0) {
01683 eexecDumpOp1(14);
01684 } else {
01685 error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
01686 }
01687 break;
01688 case 21:
01689 if (first) {
01690 cvtGlyphWidth(nOps == 3);
01691 first = gFalse;
01692 }
01693 if (nOps != 2) {
01694 error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
01695 }
01696 eexecDumpNum(op[0], fp[0]);
01697 eexecDumpNum(op[1], fp[1]);
01698 eexecDumpOp1(21);
01699 break;
01700 case 22:
01701 if (first) {
01702 cvtGlyphWidth(nOps == 2);
01703 first = gFalse;
01704 }
01705 if (nOps != 1) {
01706 error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
01707 }
01708 eexecDumpNum(op[0], fp[0]);
01709 eexecDumpOp1(22);
01710 break;
01711 case 24:
01712 if (nOps < 8 || (nOps - 2) % 6 != 0) {
01713 error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
01714 }
01715 for (k = 0; k < nOps - 2; k += 6) {
01716 eexecDumpNum(op[k], fp[k]);
01717 eexecDumpNum(op[k+1], fp[k+1]);
01718 eexecDumpNum(op[k+2], fp[k+2]);
01719 eexecDumpNum(op[k+3], fp[k+3]);
01720 eexecDumpNum(op[k+4], fp[k+4]);
01721 eexecDumpNum(op[k+5], fp[k+5]);
01722 eexecDumpOp1(8);
01723 }
01724 eexecDumpNum(op[k], fp[k]);
01725 eexecDumpNum(op[k+1], fp[k]);
01726 eexecDumpOp1(5);
01727 break;
01728 case 25:
01729 if (nOps < 8 || (nOps - 6) % 2 != 0) {
01730 error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
01731 }
01732 for (k = 0; k < nOps - 6; k += 2) {
01733 eexecDumpNum(op[k], fp[k]);
01734 eexecDumpNum(op[k+1], fp[k]);
01735 eexecDumpOp1(5);
01736 }
01737 eexecDumpNum(op[k], fp[k]);
01738 eexecDumpNum(op[k+1], fp[k+1]);
01739 eexecDumpNum(op[k+2], fp[k+2]);
01740 eexecDumpNum(op[k+3], fp[k+3]);
01741 eexecDumpNum(op[k+4], fp[k+4]);
01742 eexecDumpNum(op[k+5], fp[k+5]);
01743 eexecDumpOp1(8);
01744 break;
01745 case 26:
01746 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
01747 error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
01748 }
01749 if (nOps % 2 == 1) {
01750 eexecDumpNum(op[0], fp[0]);
01751 eexecDumpNum(op[1], fp[1]);
01752 eexecDumpNum(op[2], fp[2]);
01753 eexecDumpNum(op[3], fp[3]);
01754 eexecDumpNum(0, gFalse);
01755 eexecDumpNum(op[4], fp[4]);
01756 eexecDumpOp1(8);
01757 k = 5;
01758 } else {
01759 k = 0;
01760 }
01761 for (; k < nOps; k += 4) {
01762 eexecDumpNum(0, gFalse);
01763 eexecDumpNum(op[k], fp[k]);
01764 eexecDumpNum(op[k+1], fp[k+1]);
01765 eexecDumpNum(op[k+2], fp[k+2]);
01766 eexecDumpNum(0, gFalse);
01767 eexecDumpNum(op[k+3], fp[k+3]);
01768 eexecDumpOp1(8);
01769 }
01770 break;
01771 case 27:
01772 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
01773 error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
01774 }
01775 if (nOps % 2 == 1) {
01776 eexecDumpNum(op[1], fp[1]);
01777 eexecDumpNum(op[0], fp[0]);
01778 eexecDumpNum(op[2], fp[2]);
01779 eexecDumpNum(op[3], fp[3]);
01780 eexecDumpNum(op[4], fp[4]);
01781 eexecDumpNum(0, gFalse);
01782 eexecDumpOp1(8);
01783 k = 5;
01784 } else {
01785 k = 0;
01786 }
01787 for (; k < nOps; k += 4) {
01788 eexecDumpNum(op[k], fp[k]);
01789 eexecDumpNum(0, gFalse);
01790 eexecDumpNum(op[k+1], fp[k+1]);
01791 eexecDumpNum(op[k+2], fp[k+2]);
01792 eexecDumpNum(op[k+3], fp[k+3]);
01793 eexecDumpNum(0, gFalse);
01794 eexecDumpOp1(8);
01795 }
01796 break;
01797 case 30:
01798 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
01799 error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
01800 }
01801 for (k = 0; k < nOps && k != nOps-5; k += 4) {
01802 if (k % 8 == 0) {
01803 eexecDumpNum(op[k], fp[k]);
01804 eexecDumpNum(op[k+1], fp[k+1]);
01805 eexecDumpNum(op[k+2], fp[k+2]);
01806 eexecDumpNum(op[k+3], fp[k+3]);
01807 eexecDumpOp1(30);
01808 } else {
01809 eexecDumpNum(op[k], fp[k]);
01810 eexecDumpNum(op[k+1], fp[k+1]);
01811 eexecDumpNum(op[k+2], fp[k+2]);
01812 eexecDumpNum(op[k+3], fp[k+3]);
01813 eexecDumpOp1(31);
01814 }
01815 }
01816 if (k == nOps-5) {
01817 if (k % 8 == 0) {
01818 eexecDumpNum(0, gFalse);
01819 eexecDumpNum(op[k], fp[k]);
01820 eexecDumpNum(op[k+1], fp[k+1]);
01821 eexecDumpNum(op[k+2], fp[k+2]);
01822 eexecDumpNum(op[k+3], fp[k+3]);
01823 eexecDumpNum(op[k+4], fp[k+4]);
01824 } else {
01825 eexecDumpNum(op[k], fp[k]);
01826 eexecDumpNum(0, gFalse);
01827 eexecDumpNum(op[k+1], fp[k+1]);
01828 eexecDumpNum(op[k+2], fp[k+2]);
01829 eexecDumpNum(op[k+4], fp[k+4]);
01830 eexecDumpNum(op[k+3], fp[k+3]);
01831 }
01832 eexecDumpOp1(8);
01833 }
01834 break;
01835 case 31:
01836 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
01837 error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
01838 }
01839 for (k = 0; k < nOps && k != nOps-5; k += 4) {
01840 if (k % 8 == 0) {
01841 eexecDumpNum(op[k], fp[k]);
01842 eexecDumpNum(op[k+1], fp[k+1]);
01843 eexecDumpNum(op[k+2], fp[k+2]);
01844 eexecDumpNum(op[k+3], fp[k+3]);
01845 eexecDumpOp1(31);
01846 } else {
01847 eexecDumpNum(op[k], fp[k]);
01848 eexecDumpNum(op[k+1], fp[k+1]);
01849 eexecDumpNum(op[k+2], fp[k+2]);
01850 eexecDumpNum(op[k+3], fp[k+3]);
01851 eexecDumpOp1(30);
01852 }
01853 }
01854 if (k == nOps-5) {
01855 if (k % 8 == 0) {
01856 eexecDumpNum(op[k], fp[k]);
01857 eexecDumpNum(0, gFalse);
01858 eexecDumpNum(op[k+1], fp[k+1]);
01859 eexecDumpNum(op[k+2], fp[k+2]);
01860 eexecDumpNum(op[k+4], fp[k+4]);
01861 eexecDumpNum(op[k+3], fp[k+3]);
01862 } else {
01863 eexecDumpNum(0, gFalse);
01864 eexecDumpNum(op[k], fp[k]);
01865 eexecDumpNum(op[k+1], fp[k+1]);
01866 eexecDumpNum(op[k+2], fp[k+2]);
01867 eexecDumpNum(op[k+3], fp[k+3]);
01868 eexecDumpNum(op[k+4], fp[k+4]);
01869 }
01870 eexecDumpOp1(8);
01871 }
01872 break;
01873 case 1:
01874 if (first) {
01875 cvtGlyphWidth(nOps & 1);
01876 first = gFalse;
01877 }
01878 if (nOps & 1) {
01879 error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
01880 }
01881 d = 0;
01882 dFP = gFalse;
01883 for (k = 0; k < nOps; k += 2) {
01884 if (op[k+1] < 0) {
01885 d += op[k] + op[k+1];
01886 dFP |= fp[k] | fp[k+1];
01887 eexecDumpNum(d, dFP);
01888 eexecDumpNum(-op[k+1], fp[k+1]);
01889 } else {
01890 d += op[k];
01891 dFP |= fp[k];
01892 eexecDumpNum(d, dFP);
01893 eexecDumpNum(op[k+1], fp[k+1]);
01894 d += op[k+1];
01895 dFP |= fp[k+1];
01896 }
01897 eexecDumpOp1(1);
01898 }
01899 nHints += nOps / 2;
01900 break;
01901 case 3:
01902 if (first) {
01903 cvtGlyphWidth(nOps & 1);
01904 first = gFalse;
01905 }
01906 if (nOps & 1) {
01907 error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
01908 }
01909 d = 0;
01910 dFP = gFalse;
01911 for (k = 0; k < nOps; k += 2) {
01912 if (op[k+1] < 0) {
01913 d += op[k] + op[k+1];
01914 dFP |= fp[k] | fp[k+1];
01915 eexecDumpNum(d, dFP);
01916 eexecDumpNum(-op[k+1], fp[k+1]);
01917 } else {
01918 d += op[k];
01919 dFP |= fp[k];
01920 eexecDumpNum(d, dFP);
01921 eexecDumpNum(op[k+1], fp[k+1]);
01922 d += op[k+1];
01923 dFP |= fp[k+1];
01924 }
01925 eexecDumpOp1(3);
01926 }
01927 nHints += nOps / 2;
01928 break;
01929 case 18:
01930
01931 if (first) {
01932 cvtGlyphWidth(nOps & 1);
01933 first = gFalse;
01934 }
01935 if (nOps & 1) {
01936 error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
01937 }
01938 nHints += nOps / 2;
01939 break;
01940 case 23:
01941
01942 if (first) {
01943 cvtGlyphWidth(nOps & 1);
01944 first = gFalse;
01945 }
01946 if (nOps & 1) {
01947 error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
01948 }
01949 nHints += nOps / 2;
01950 break;
01951 case 10:
01952 case 11:
01953 case 16:
01954 case 29:
01955 error(-1, "Unimplemented Type 2 charstring op: %d", s[i]);
01956 break;
01957 default:
01958 error(-1, "Illegal Type 2 charstring op: %d", s[i]);
01959 break;
01960 }
01961 ++i;
01962 nOps = 0;
01963 } else if (s[i] <= 246) {
01964 if (nOps < 48) {
01965 fp[nOps] = gFalse;
01966 op[nOps++] = (int)s[i] - 139;
01967 }
01968 ++i;
01969 } else if (s[i] <= 250) {
01970 if (nOps < 48) {
01971 fp[nOps] = gFalse;
01972 op[nOps++] = (((int)s[i] - 247) << 8) + (int)s[i+1] + 108;
01973 }
01974 i += 2;
01975 } else if (s[i] <= 254) {
01976 if (nOps < 48) {
01977 fp[nOps] = gFalse;
01978 op[nOps++] = -(((int)s[i] - 251) << 8) - (int)s[i+1] - 108;
01979 }
01980 i += 2;
01981 } else {
01982 x = (s[i+1] << 24) | (s[i+2] << 16) | (s[i+3] << 8) | s[i+4];
01983 if (x & 0x80000000)
01984 x |= -1 << 31;
01985 if (nOps < 48) {
01986 fp[nOps] = gTrue;
01987 op[nOps++] = (double)x / 65536.0;
01988 }
01989 i += 5;
01990 }
01991 }
01992
01993
01994 r2 = 4330;
01995 for (i = 0; i < charBuf->getLength(); ++i) {
01996 byte = charBuf->getChar(i) ^ (r2 >> 8);
01997 charBuf->setChar(i, byte);
01998 r2 = (byte + r2) * 52845 + 22719;
01999 }
02000 }
02001
02002 void Type1CFontFile::cvtGlyphWidth(GBool useOp) {
02003 double w;
02004 GBool wFP;
02005 int i;
02006
02007 if (useOp) {
02008 w = nominalWidthX + op[0];
02009 wFP = nominalWidthXFP | fp[0];
02010 for (i = 1; i < nOps; ++i) {
02011 op[i-1] = op[i];
02012 fp[i-1] = fp[i];
02013 }
02014 --nOps;
02015 } else {
02016 w = defaultWidthX;
02017 wFP = defaultWidthXFP;
02018 }
02019 eexecDumpNum(0, gFalse);
02020 eexecDumpNum(w, wFP);
02021 eexecDumpOp1(13);
02022 }
02023
02024 void Type1CFontFile::eexecDumpNum(double x, GBool fpA) {
02025 Guchar buf[12];
02026 int y, n;
02027
02028 n = 0;
02029 if (fpA) {
02030 if (x >= -32768 && x < 32768) {
02031 y = (int)(x * 256.0);
02032 buf[0] = 255;
02033 buf[1] = (Guchar)(y >> 24);
02034 buf[2] = (Guchar)(y >> 16);
02035 buf[3] = (Guchar)(y >> 8);
02036 buf[4] = (Guchar)y;
02037 buf[5] = 255;
02038 buf[6] = 0;
02039 buf[7] = 0;
02040 buf[8] = 1;
02041 buf[9] = 0;
02042 buf[10] = 12;
02043 buf[11] = 12;
02044 n = 12;
02045 } else {
02046 error(-1, "Type 2 fixed point constant out of range");
02047 }
02048 } else {
02049 y = (int)x;
02050 if (y >= -107 && y <= 107) {
02051 buf[0] = (Guchar)(y + 139);
02052 n = 1;
02053 } else if (y > 107 && y <= 1131) {
02054 y -= 108;
02055 buf[0] = (Guchar)((y >> 8) + 247);
02056 buf[1] = (Guchar)(y & 0xff);
02057 n = 2;
02058 } else if (y < -107 && y >= -1131) {
02059 y = -y - 108;
02060 buf[0] = (Guchar)((y >> 8) + 251);
02061 buf[1] = (Guchar)(y & 0xff);
02062 n = 2;
02063 } else {
02064 buf[0] = 255;
02065 buf[1] = (Guchar)(y >> 24);
02066 buf[2] = (Guchar)(y >> 16);
02067 buf[3] = (Guchar)(y >> 8);
02068 buf[4] = (Guchar)y;
02069 n = 5;
02070 }
02071 }
02072 charBuf->append((char *)buf, n);
02073 }
02074
02075 void Type1CFontFile::eexecDumpOp1(int opA) {
02076 charBuf->append((char)opA);
02077 }
02078
02079 void Type1CFontFile::eexecDumpOp2(int opA) {
02080 charBuf->append((char)12);
02081 charBuf->append((char)opA);
02082 }
02083
02084 void Type1CFontFile::eexecWriteCharstring(const Guchar *s, int n) {
02085 Guchar x;
02086 int i;
02087
02088
02089 for (i = 0; i < n; ++i) {
02090 x = s[i] ^ (r1 >> 8);
02091 r1 = (x + r1) * 52845 + 22719;
02092 (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
02093 (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
02094 line += 2;
02095 if (line == 64) {
02096 (*outputFunc)(outputStream, "\n", 1);
02097 line = 0;
02098 }
02099 }
02100 }
02101
02102 void Type1CFontFile::getDeltaInt(char *buf, const char *key, const double *opA,
02103 int n) {
02104 int x, i;
02105
02106 sprintf(buf, "/%s [", key);
02107 buf += strlen(buf);
02108 x = 0;
02109 for (i = 0; i < n; ++i) {
02110 x += (int)opA[i];
02111 sprintf(buf, "%s%d", i > 0 ? " " : "", x);
02112 buf += strlen(buf);
02113 }
02114 sprintf(buf, "] def\n");
02115 }
02116
02117 void Type1CFontFile::getDeltaReal(char *buf, const char *key, const double *opA,
02118 int n) {
02119 double x;
02120 int i;
02121
02122 sprintf(buf, "/%s [", key);
02123 buf += strlen(buf);
02124 x = 0;
02125 for (i = 0; i < n; ++i) {
02126 x += opA[i];
02127 sprintf(buf, "%s%g", i > 0 ? " " : "", x);
02128 buf += strlen(buf);
02129 }
02130 sprintf(buf, "] def\n");
02131 }
02132
02133 int Type1CFontFile::getIndexLen(Guchar *indexPtr) {
02134 return (int)getWord(indexPtr, 2);
02135 }
02136
02137 Guchar *Type1CFontFile::getIndexValPtr(Guchar *indexPtr, int i) {
02138 int n, offSize;
02139 Guchar *idxStartPtr;
02140
02141 n = (int)getWord(indexPtr, 2);
02142 offSize = indexPtr[2];
02143 idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
02144 return idxStartPtr + getWord(indexPtr + 3 + i * offSize, offSize);
02145 }
02146
02147 Guchar *Type1CFontFile::getIndexEnd(Guchar *indexPtr) {
02148 int n, offSize;
02149 Guchar *idxStartPtr;
02150
02151 n = (int)getWord(indexPtr, 2);
02152 offSize = indexPtr[2];
02153 idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
02154 return idxStartPtr + getWord(indexPtr + 3 + n * offSize, offSize);
02155 }
02156
02157 Guint Type1CFontFile::getWord(Guchar *ptr, int size) {
02158 Guint x;
02159 int i;
02160
02161 x = 0;
02162 for (i = 0; i < size; ++i) {
02163 x = (x << 8) + *ptr++;
02164 }
02165 return x;
02166 }
02167
02168 double Type1CFontFile::getNum(Guchar **ptr, GBool *isFP) {
02169 static char nybChars[16] = "0123456789.ee -";
02170 int b0, b, nyb0, nyb1;
02171 double x;
02172 char buf[65];
02173 int i;
02174
02175 x = 0;
02176 *isFP = gFalse;
02177 b0 = (*ptr)[0];
02178 if (b0 < 28) {
02179 x = 0;
02180 } else if (b0 == 28) {
02181 x = ((*ptr)[1] << 8) + (*ptr)[2];
02182 *ptr += 3;
02183 } else if (b0 == 29) {
02184 x = ((*ptr)[1] << 24) + ((*ptr)[2] << 16) + ((*ptr)[3] << 8) + (*ptr)[4];
02185 *ptr += 5;
02186 } else if (b0 == 30) {
02187 *ptr += 1;
02188 i = 0;
02189 do {
02190 b = *(*ptr)++;
02191 nyb0 = b >> 4;
02192 nyb1 = b & 0x0f;
02193 if (nyb0 == 0xf) {
02194 break;
02195 }
02196 buf[i++] = nybChars[nyb0];
02197 if (i == 64) {
02198 break;
02199 }
02200 if (nyb0 == 0xc) {
02201 buf[i++] = '-';
02202 }
02203 if (i == 64) {
02204 break;
02205 }
02206 if (nyb1 == 0xf) {
02207 break;
02208 }
02209 buf[i++] = nybChars[nyb1];
02210 if (i == 64) {
02211 break;
02212 }
02213 if (nyb1 == 0xc) {
02214 buf[i++] = '-';
02215 }
02216 } while (i < 64);
02217 buf[i] = '\0';
02218 x = atof(buf);
02219 *isFP = gTrue;
02220 } else if (b0 == 31) {
02221 x = 0;
02222 } else if (b0 < 247) {
02223 x = b0 - 139;
02224 *ptr += 1;
02225 } else if (b0 < 251) {
02226 x = ((b0 - 247) << 8) + (*ptr)[1] + 108;
02227 *ptr += 2;
02228 } else {
02229 x = -((b0 - 251) << 8) - (*ptr)[1] - 108;
02230 *ptr += 2;
02231 }
02232 return x;
02233 }
02234
02235 char *Type1CFontFile::getString(int sid, char *buf) {
02236 Guchar *idxPtr0, *idxPtr1;
02237 int n;
02238
02239 if (sid < 391) {
02240 strcpy(buf, type1CStdStrings[sid]);
02241 } else {
02242 sid -= 391;
02243 idxPtr0 = getIndexValPtr(stringIdxPtr, sid);
02244 idxPtr1 = getIndexValPtr(stringIdxPtr, sid + 1);
02245 if ((n = idxPtr1 - idxPtr0) > 255) {
02246 n = 255;
02247 }
02248 strncpy(buf, (char *)idxPtr0, n);
02249 buf[n] = '\0';
02250 }
02251 return buf;
02252 }
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314 struct TTFontTableHdr {
02315 char tag[4];
02316 Guint checksum;
02317 Guint offset;
02318 Guint length;
02319 };
02320
02321 struct T42Table {
02322 const char *tag;
02323 GBool required;
02324 };
02325
02326
02327
02328 #define nT42Tables 11
02329 static T42Table t42Tables[nT42Tables] = {
02330 { "cvt ", gTrue },
02331 { "fpgm", gTrue },
02332 { "glyf", gTrue },
02333 { "head", gTrue },
02334 { "hhea", gTrue },
02335 { "hmtx", gTrue },
02336 { "loca", gTrue },
02337 { "maxp", gTrue },
02338 { "prep", gTrue },
02339 { "vhea", gFalse },
02340 { "vmtx", gFalse }
02341 };
02342 #define t42HeadTable 3
02343 #define t42LocaTable 6
02344 #define t42GlyfTable 2
02345
02346
02347
02348 static const char *macGlyphNames[258] = {
02349 ".notdef",
02350 "null",
02351 "CR",
02352 "space",
02353 "exclam",
02354 "quotedbl",
02355 "numbersign",
02356 "dollar",
02357 "percent",
02358 "ampersand",
02359 "quotesingle",
02360 "parenleft",
02361 "parenright",
02362 "asterisk",
02363 "plus",
02364 "comma",
02365 "hyphen",
02366 "period",
02367 "slash",
02368 "zero",
02369 "one",
02370 "two",
02371 "three",
02372 "four",
02373 "five",
02374 "six",
02375 "seven",
02376 "eight",
02377 "nine",
02378 "colon",
02379 "semicolon",
02380 "less",
02381 "equal",
02382 "greater",
02383 "question",
02384 "at",
02385 "A",
02386 "B",
02387 "C",
02388 "D",
02389 "E",
02390 "F",
02391 "G",
02392 "H",
02393 "I",
02394 "J",
02395 "K",
02396 "L",
02397 "M",
02398 "N",
02399 "O",
02400 "P",
02401 "Q",
02402 "R",
02403 "S",
02404 "T",
02405 "U",
02406 "V",
02407 "W",
02408 "X",
02409 "Y",
02410 "Z",
02411 "bracketleft",
02412 "backslash",
02413 "bracketright",
02414 "asciicircum",
02415 "underscore",
02416 "grave",
02417 "a",
02418 "b",
02419 "c",
02420 "d",
02421 "e",
02422 "f",
02423 "g",
02424 "h",
02425 "i",
02426 "j",
02427 "k",
02428 "l",
02429 "m",
02430 "n",
02431 "o",
02432 "p",
02433 "q",
02434 "r",
02435 "s",
02436 "t",
02437 "u",
02438 "v",
02439 "w",
02440 "x",
02441 "y",
02442 "z",
02443 "braceleft",
02444 "bar",
02445 "braceright",
02446 "asciitilde",
02447 "Adieresis",
02448 "Aring",
02449 "Ccedilla",
02450 "Eacute",
02451 "Ntilde",
02452 "Odieresis",
02453 "Udieresis",
02454 "aacute",
02455 "agrave",
02456 "acircumflex",
02457 "adieresis",
02458 "atilde",
02459 "aring",
02460 "ccedilla",
02461 "eacute",
02462 "egrave",
02463 "ecircumflex",
02464 "edieresis",
02465 "iacute",
02466 "igrave",
02467 "icircumflex",
02468 "idieresis",
02469 "ntilde",
02470 "oacute",
02471 "ograve",
02472 "ocircumflex",
02473 "odieresis",
02474 "otilde",
02475 "uacute",
02476 "ugrave",
02477 "ucircumflex",
02478 "udieresis",
02479 "dagger",
02480 "degree",
02481 "cent",
02482 "sterling",
02483 "section",
02484 "bullet",
02485 "paragraph",
02486 "germandbls",
02487 "registered",
02488 "copyright",
02489 "trademark",
02490 "acute",
02491 "dieresis",
02492 "notequal",
02493 "AE",
02494 "Oslash",
02495 "infinity",
02496 "plusminus",
02497 "lessequal",
02498 "greaterequal",
02499 "yen",
02500 "mu1",
02501 "partialdiff",
02502 "summation",
02503 "product",
02504 "pi",
02505 "integral",
02506 "ordfeminine",
02507 "ordmasculine",
02508 "Ohm",
02509 "ae",
02510 "oslash",
02511 "questiondown",
02512 "exclamdown",
02513 "logicalnot",
02514 "radical",
02515 "florin",
02516 "approxequal",
02517 "increment",
02518 "guillemotleft",
02519 "guillemotright",
02520 "ellipsis",
02521 "nbspace",
02522 "Agrave",
02523 "Atilde",
02524 "Otilde",
02525 "OE",
02526 "oe",
02527 "endash",
02528 "emdash",
02529 "quotedblleft",
02530 "quotedblright",
02531 "quoteleft",
02532 "quoteright",
02533 "divide",
02534 "lozenge",
02535 "ydieresis",
02536 "Ydieresis",
02537 "fraction",
02538 "currency",
02539 "guilsinglleft",
02540 "guilsinglright",
02541 "fi",
02542 "fl",
02543 "daggerdbl",
02544 "periodcentered",
02545 "quotesinglbase",
02546 "quotedblbase",
02547 "perthousand",
02548 "Acircumflex",
02549 "Ecircumflex",
02550 "Aacute",
02551 "Edieresis",
02552 "Egrave",
02553 "Iacute",
02554 "Icircumflex",
02555 "Idieresis",
02556 "Igrave",
02557 "Oacute",
02558 "Ocircumflex",
02559 "applelogo",
02560 "Ograve",
02561 "Uacute",
02562 "Ucircumflex",
02563 "Ugrave",
02564 "dotlessi",
02565 "circumflex",
02566 "tilde",
02567 "overscore",
02568 "breve",
02569 "dotaccent",
02570 "ring",
02571 "cedilla",
02572 "hungarumlaut",
02573 "ogonek",
02574 "caron",
02575 "Lslash",
02576 "lslash",
02577 "Scaron",
02578 "scaron",
02579 "Zcaron",
02580 "zcaron",
02581 "brokenbar",
02582 "Eth",
02583 "eth",
02584 "Yacute",
02585 "yacute",
02586 "Thorn",
02587 "thorn",
02588 "minus",
02589 "multiply",
02590 "onesuperior",
02591 "twosuperior",
02592 "threesuperior",
02593 "onehalf",
02594 "onequarter",
02595 "threequarters",
02596 "franc",
02597 "Gbreve",
02598 "gbreve",
02599 "Idot",
02600 "Scedilla",
02601 "scedilla",
02602 "Cacute",
02603 "cacute",
02604 "Ccaron",
02605 "ccaron",
02606 "dmacron"
02607 };
02608
02609 enum T42FontIndexMode {
02610 t42FontModeUnicode,
02611 t42FontModeCharCode,
02612 t42FontModeCharCodeOffset,
02613 t42FontModeMacRoman
02614 };
02615
02616 TrueTypeFontFile::TrueTypeFontFile(const char *fileA, int lenA) {
02617 int pos, i, idx, n, length;
02618 Guint size, startPos, endPos;
02619
02620 file = fileA;
02621 len = lenA;
02622
02623 encoding = NULL;
02624
02625
02626 nTables = getUShort(4);
02627 tableHdrs = (TTFontTableHdr *)gmalloc(nTables * sizeof(TTFontTableHdr));
02628 pos = 12;
02629 for (i = 0; i < nTables; ++i) {
02630 tableHdrs[i].tag[0] = getByte(pos+0);
02631 tableHdrs[i].tag[1] = getByte(pos+1);
02632 tableHdrs[i].tag[2] = getByte(pos+2);
02633 tableHdrs[i].tag[3] = getByte(pos+3);
02634 tableHdrs[i].checksum = getULong(pos+4);
02635 tableHdrs[i].offset = getULong(pos+8);
02636 tableHdrs[i].length = getULong(pos+12);
02637 pos += 16;
02638 }
02639
02640
02641
02642 if (seekTable("head") < 0 ||
02643 seekTable("hhea") < 0 ||
02644 seekTable("loca") < 0 ||
02645 seekTable("maxp") < 0 ||
02646 seekTable("glyf") < 0 ||
02647 seekTable("hmtx") < 0) {
02648 error(-1, "TrueType font file is missing a required table");
02649 return;
02650 }
02651
02652
02653
02654 idx = seekTableIdx("cmap");
02655 if (idx >= 0) {
02656 pos = tableHdrs[idx].offset;
02657 n = getUShort(pos + 2);
02658 size = (Guint)(4 + 8 * n);
02659 for (i = 0; i < n; ++i) {
02660 startPos = getULong(pos + 4 + 8*i + 4);
02661 length = getUShort(pos + startPos + 2);
02662 endPos = startPos + length;
02663 if (endPos > size) {
02664 size = endPos;
02665 }
02666 }
02667 if ((mungedCmapSize = size > tableHdrs[idx].length)) {
02668 #if 0 // don't bother printing this error message - it's too common
02669 error(-1, "Bad cmap table size in TrueType font");
02670 #endif
02671 tableHdrs[idx].length = size;
02672 }
02673 } else {
02674 mungedCmapSize = gFalse;
02675 }
02676
02677
02678 pos = seekTable("head");
02679 bbox[0] = getShort(pos + 36);
02680 bbox[1] = getShort(pos + 38);
02681 bbox[2] = getShort(pos + 40);
02682 bbox[3] = getShort(pos + 42);
02683 locaFmt = getShort(pos + 50);
02684
02685
02686 pos = seekTable("maxp");
02687 nGlyphs = getUShort(pos + 4);
02688 }
02689
02690 TrueTypeFontFile::~TrueTypeFontFile() {
02691 int i;
02692
02693 if (encoding) {
02694 for (i = 0; i < 256; ++i) {
02695 gfree(encoding[i]);
02696 }
02697 gfree(encoding);
02698 }
02699 gfree(tableHdrs);
02700 }
02701
02702 const char *TrueTypeFontFile::getName() {
02703 return NULL;
02704 }
02705
02706 char **TrueTypeFontFile::getEncoding() {
02707 int cmap[256];
02708 int nCmaps, cmapPlatform, cmapEncoding, cmapFmt;
02709 int cmapLen, cmapOffset, cmapFirst;
02710 int segCnt, segStart, segEnd, segDelta, segOffset;
02711 int pos, i, j, k;
02712 Guint fmt;
02713 GString *s;
02714 int stringIdx, stringPos, n;
02715
02716 if (encoding) {
02717 return encoding;
02718 }
02719
02720
02721
02722
02723 for (i = 0; i < 256; ++i) {
02724 cmap[i] = 0;
02725 }
02726
02727
02728 if ((pos = seekTable("cmap")) >= 0) {
02729 nCmaps = getUShort(pos+2);
02730
02731
02732
02733 for (i = 0; i < nCmaps; ++i) {
02734 cmapPlatform = getUShort(pos + 4 + 8*i);
02735 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
02736 if (cmapPlatform == 3 && cmapEncoding == 0) {
02737 break;
02738 }
02739 }
02740 if (i >= nCmaps) {
02741 i = 0;
02742 cmapPlatform = getUShort(pos + 4);
02743 cmapEncoding = getUShort(pos + 4 + 2);
02744 }
02745 pos += getULong(pos + 4 + 8*i + 4);
02746
02747
02748 cmapFmt = getUShort(pos);
02749 switch (cmapFmt) {
02750 case 0:
02751 cmapLen = getUShort(pos + 2);
02752 for (i = 0; i < cmapLen && i < 256; ++i) {
02753 cmap[i] = getByte(pos + 6 + i);
02754 }
02755 break;
02756 case 4:
02757 if (cmapPlatform == 3 && cmapEncoding == 0) {
02758
02759 cmapOffset = 0xf000;
02760 } else {
02761 cmapOffset = 0;
02762 }
02763 segCnt = getUShort(pos + 6) / 2;
02764 for (i = 0; i < segCnt; ++i) {
02765 segEnd = getUShort(pos + 14 + 2*i);
02766 segStart = getUShort(pos + 16 + 2*segCnt + 2*i);
02767 segDelta = getUShort(pos + 16 + 4*segCnt + 2*i);
02768 segOffset = getUShort(pos + 16 + 6*segCnt + 2*i);
02769 if (segStart - cmapOffset <= 0xff &&
02770 segEnd - cmapOffset >= 0) {
02771 for (j = (segStart - cmapOffset >= 0) ? segStart : cmapOffset;
02772 j <= segEnd && j - cmapOffset <= 0xff;
02773 ++j) {
02774 if (segOffset == 0) {
02775 k = (j + segDelta) & 0xffff;
02776 } else {
02777 k = getUShort(pos + 16 + 6*segCnt + 2*i +
02778 segOffset + 2 * (j - segStart));
02779 if (k != 0) {
02780 k = (k + segDelta) & 0xffff;
02781 }
02782 }
02783 cmap[j - cmapOffset] = k;
02784 }
02785 }
02786 }
02787 break;
02788 case 6:
02789 cmapFirst = getUShort(pos + 6);
02790 cmapLen = getUShort(pos + 8);
02791 for (i = cmapFirst; i < 256 && i < cmapFirst + cmapLen; ++i) {
02792 cmap[i] = getUShort(pos + 10 + 2*i);
02793 }
02794 break;
02795 default:
02796 error(-1, "Unimplemented cmap format (%d) in TrueType font file",
02797 cmapFmt);
02798 break;
02799 }
02800 }
02801
02802
02803
02804
02805 encoding = (char **)gmalloc(256 * sizeof(char *));
02806 for (i = 0; i < 256; ++i) {
02807 encoding[i] = NULL;
02808 }
02809
02810 if ((pos = seekTable("post")) >= 0) {
02811 fmt = getULong(pos);
02812
02813
02814 if (fmt == 0x00010000) {
02815 for (i = 0; i < 256; ++i) {
02816 j = (cmap[i] < 258) ? cmap[i] : 0;
02817 encoding[i] = copyString(macGlyphNames[j]);
02818 }
02819
02820
02821 } else if (fmt == 0x00020000) {
02822 stringIdx = 0;
02823 stringPos = pos + 34 + 2*nGlyphs;
02824 for (i = 0; i < 256; ++i) {
02825 if (cmap[i] < nGlyphs) {
02826 j = getUShort(pos + 34 + 2 * cmap[i]);
02827 if (j < 258) {
02828 encoding[i] = copyString(macGlyphNames[j]);
02829 } else {
02830 j -= 258;
02831 if (j != stringIdx) {
02832 for (stringIdx = 0, stringPos = pos + 34 + 2*nGlyphs;
02833 stringIdx < j;
02834 ++stringIdx, stringPos += 1 + getByte(stringPos)) ;
02835 }
02836 n = getByte(stringPos);
02837 s = new GString(file + stringPos + 1, n);
02838 encoding[i] = copyString(s->getCString());
02839 delete s;
02840 ++stringIdx;
02841 stringPos += 1 + n;
02842 }
02843 } else {
02844 encoding[i] = copyString(macGlyphNames[0]);
02845 }
02846 }
02847
02848
02849 } else if (fmt == 0x000280000) {
02850 for (i = 0; i < 256; ++i) {
02851 if (cmap[i] < nGlyphs) {
02852 j = i + getChar(pos + 32 + cmap[i]);
02853 } else {
02854 j = 0;
02855 }
02856 encoding[i] = copyString(macGlyphNames[j]);
02857 }
02858
02859
02860 } else {
02861 for (i = 0; i < 256; ++i) {
02862 j = (cmap[i] < 258) ? cmap[i] : 0;
02863 encoding[i] = copyString(macGlyphNames[j]);
02864 }
02865 }
02866
02867
02868 } else {
02869 for (i = 0; i < 256; ++i) {
02870 j = (cmap[i] < 258) ? cmap[i] : 0;
02871 encoding[i] = copyString(macGlyphNames[j]);
02872 }
02873 }
02874
02875 return encoding;
02876 }
02877
02878 void TrueTypeFontFile::convertToType42(const char *name, const char **encodingA,
02879 CharCodeToUnicode *toUnicode,
02880 GBool pdfFontHasEncoding,
02881 FontFileOutputFunc outputFunc,
02882 void *outputStream) {
02883 char buf[512];
02884
02885
02886 sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
02887 (*outputFunc)(outputStream, buf, strlen(buf));
02888
02889
02890 (*outputFunc)(outputStream, "10 dict begin\n", 14);
02891 (*outputFunc)(outputStream, "/FontName /", 11);
02892 (*outputFunc)(outputStream, name, strlen(name));
02893 (*outputFunc)(outputStream, " def\n", 5);
02894 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
02895 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
02896 sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
02897 bbox[0], bbox[1], bbox[2], bbox[3]);
02898 (*outputFunc)(outputStream, buf, strlen(buf));
02899 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
02900
02901
02902 cvtEncoding(encodingA, pdfFontHasEncoding, outputFunc, outputStream);
02903 cvtCharStrings(encodingA, toUnicode, pdfFontHasEncoding,
02904 outputFunc, outputStream);
02905 cvtSfnts(outputFunc, outputStream, NULL);
02906
02907
02908 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
02909 }
02910
02911 void TrueTypeFontFile::convertToCIDType2(const char *name, const Gushort *cidMap,
02912 int nCIDs,
02913 FontFileOutputFunc outputFunc,
02914 void *outputStream) {
02915 char buf[512];
02916 Gushort cid;
02917 int i, j, k;
02918
02919
02920 sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
02921 (*outputFunc)(outputStream, buf, strlen(buf));
02922
02923
02924 (*outputFunc)(outputStream, "20 dict begin\n", 14);
02925 (*outputFunc)(outputStream, "/CIDFontName /", 14);
02926 (*outputFunc)(outputStream, name, strlen(name));
02927 (*outputFunc)(outputStream, " def\n", 5);
02928 (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
02929 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
02930 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
02931 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
02932 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
02933 (*outputFunc)(outputStream, " /Supplement 0 def\n", 20);
02934 (*outputFunc)(outputStream, " end def\n", 10);
02935 (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
02936 if (cidMap) {
02937 sprintf(buf, "/CIDCount %d def\n", nCIDs);
02938 (*outputFunc)(outputStream, buf, strlen(buf));
02939 if (nCIDs > 32767) {
02940 (*outputFunc)(outputStream, "/CIDMap [", 9);
02941 for (i = 0; i < nCIDs; i += 32768 - 16) {
02942 (*outputFunc)(outputStream, "<\n", 2);
02943 for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
02944 (*outputFunc)(outputStream, " ", 2);
02945 for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
02946 cid = cidMap[i+j+k];
02947 sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
02948 (*outputFunc)(outputStream, buf, strlen(buf));
02949 }
02950 (*outputFunc)(outputStream, "\n", 1);
02951 }
02952 (*outputFunc)(outputStream, " >", 3);
02953 }
02954 (*outputFunc)(outputStream, "\n", 1);
02955 (*outputFunc)(outputStream, "] def\n", 6);
02956 } else {
02957 (*outputFunc)(outputStream, "/CIDMap <\n", 10);
02958 for (i = 0; i < nCIDs; i += 16) {
02959 (*outputFunc)(outputStream, " ", 2);
02960 for (j = 0; j < 16 && i+j < nCIDs; ++j) {
02961 cid = cidMap[i+j];
02962 sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
02963 (*outputFunc)(outputStream, buf, strlen(buf));
02964 }
02965 (*outputFunc)(outputStream, "\n", 1);
02966 }
02967 (*outputFunc)(outputStream, "> def\n", 6);
02968 }
02969 } else {
02970
02971 sprintf(buf, "/CIDCount %d def\n", nGlyphs);
02972 (*outputFunc)(outputStream, buf, strlen(buf));
02973 if (nGlyphs > 32767) {
02974 (*outputFunc)(outputStream, "/CIDMap [\n", 10);
02975 for (i = 0; i < nGlyphs; i += 32767) {
02976 j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
02977 sprintf(buf, " %d string 0 1 %d {\n", 2 * j, j - 1);
02978 (*outputFunc)(outputStream, buf, strlen(buf));
02979 sprintf(buf, " 2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
02980 (*outputFunc)(outputStream, buf, strlen(buf));
02981 sprintf(buf, " 1 index exch dup 2 mul 1 add exch %d add"
02982 " 255 and put\n", i);
02983 (*outputFunc)(outputStream, buf, strlen(buf));
02984 (*outputFunc)(outputStream, " } for\n", 8);
02985 }
02986 (*outputFunc)(outputStream, "] def\n", 6);
02987 } else {
02988 sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
02989 (*outputFunc)(outputStream, buf, strlen(buf));
02990 sprintf(buf, " 0 1 %d {\n", nGlyphs - 1);
02991 (*outputFunc)(outputStream, buf, strlen(buf));
02992 (*outputFunc)(outputStream,
02993 " 2 copy dup 2 mul exch -8 bitshift put\n", 42);
02994 (*outputFunc)(outputStream,
02995 " 1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
02996 (*outputFunc)(outputStream, " } for\n", 8);
02997 (*outputFunc)(outputStream, "def\n", 4);
02998 }
02999 }
03000 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
03001 sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
03002 bbox[0], bbox[1], bbox[2], bbox[3]);
03003 (*outputFunc)(outputStream, buf, strlen(buf));
03004 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
03005 (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
03006 (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
03007 (*outputFunc)(outputStream, " /.notdef 0 def\n", 17);
03008 (*outputFunc)(outputStream, " end readonly def\n", 19);
03009
03010
03011 cvtSfnts(outputFunc, outputStream, NULL);
03012
03013
03014 (*outputFunc)(outputStream,
03015 "CIDFontName currentdict end /CIDFont defineresource pop\n",
03016 56);
03017 }
03018
03019 void TrueTypeFontFile::convertToType0(const char *name, const Gushort *cidMap,
03020 int nCIDs,
03021 FontFileOutputFunc outputFunc,
03022 void *outputStream) {
03023 char buf[512];
03024 GString *sfntsName;
03025 int n, i, j;
03026
03027
03028 sfntsName = (new GString(name))->append("_sfnts");
03029 cvtSfnts(outputFunc, outputStream, sfntsName);
03030 delete sfntsName;
03031
03032
03033 n = cidMap ? nCIDs : nGlyphs;
03034 for (i = 0; i < n; i += 256) {
03035 (*outputFunc)(outputStream, "10 dict begin\n", 14);
03036 (*outputFunc)(outputStream, "/FontName /", 11);
03037 (*outputFunc)(outputStream, name, strlen(name));
03038 sprintf(buf, "_%02x def\n", i >> 8);
03039 (*outputFunc)(outputStream, buf, strlen(buf));
03040 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
03041 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
03042 sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
03043 bbox[0], bbox[1], bbox[2], bbox[3]);
03044 (*outputFunc)(outputStream, buf, strlen(buf));
03045 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
03046 (*outputFunc)(outputStream, "/sfnts ", 7);
03047 (*outputFunc)(outputStream, name, strlen(name));
03048 (*outputFunc)(outputStream, "_sfnts def\n", 11);
03049 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
03050 for (j = 0; j < 256 && i+j < n; ++j) {
03051 sprintf(buf, "dup %d /c%02x put\n", j, j);
03052 (*outputFunc)(outputStream, buf, strlen(buf));
03053 }
03054 (*outputFunc)(outputStream, "readonly def\n", 13);
03055 (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
03056 (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
03057 for (j = 0; j < 256 && i+j < n; ++j) {
03058 sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
03059 (*outputFunc)(outputStream, buf, strlen(buf));
03060 }
03061 (*outputFunc)(outputStream, "end readonly def\n", 17);
03062 (*outputFunc)(outputStream,
03063 "FontName currentdict end definefont pop\n", 40);
03064 }
03065
03066
03067 (*outputFunc)(outputStream, "16 dict begin\n", 14);
03068 (*outputFunc)(outputStream, "/FontName /", 11);
03069 (*outputFunc)(outputStream, name, strlen(name));
03070 (*outputFunc)(outputStream, " def\n", 5);
03071 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
03072 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
03073 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
03074 (*outputFunc)(outputStream, "/Encoding [\n", 12);
03075 for (i = 0; i < n; i += 256) {
03076 sprintf(buf, "%d\n", i >> 8);
03077 (*outputFunc)(outputStream, buf, strlen(buf));
03078 }
03079 (*outputFunc)(outputStream, "] def\n", 6);
03080 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
03081 for (i = 0; i < n; i += 256) {
03082 (*outputFunc)(outputStream, "/", 1);
03083 (*outputFunc)(outputStream, name, strlen(name));
03084 sprintf(buf, "_%02x findfont\n", i >> 8);
03085 (*outputFunc)(outputStream, buf, strlen(buf));
03086 }
03087 (*outputFunc)(outputStream, "] def\n", 6);
03088 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
03089 }
03090
03091 int TrueTypeFontFile::getByte(int pos) {
03092 if (pos < 0 || pos >= len) {
03093 return 0;
03094 }
03095 return file[pos] & 0xff;
03096 }
03097
03098 int TrueTypeFontFile::getChar(int pos) {
03099 int x;
03100
03101 if (pos < 0 || pos >= len) {
03102 return 0;
03103 }
03104 x = file[pos] & 0xff;
03105 if (x & 0x80)
03106 x |= 0xffffff00;
03107 return x;
03108 }
03109
03110 int TrueTypeFontFile::getUShort(int pos) {
03111 int x;
03112
03113 if (pos < 0 || pos+1 >= len) {
03114 return 0;
03115 }
03116 x = file[pos] & 0xff;
03117 x = (x << 8) + (file[pos+1] & 0xff);
03118 return x;
03119 }
03120
03121 int TrueTypeFontFile::getShort(int pos) {
03122 int x;
03123
03124 if (pos < 0 || pos+1 >= len) {
03125 return 0;
03126 }
03127 x = file[pos] & 0xff;
03128 x = (x << 8) + (file[pos+1] & 0xff);
03129 if (x & 0x8000)
03130 x |= 0xffff0000;
03131 return x;
03132 }
03133
03134 Guint TrueTypeFontFile::getULong(int pos) {
03135 int x;
03136
03137 if (pos < 0 || pos+3 >= len) {
03138 return 0;
03139 }
03140 x = file[pos] & 0xff;
03141 x = (x << 8) + (file[pos+1] & 0xff);
03142 x = (x << 8) + (file[pos+2] & 0xff);
03143 x = (x << 8) + (file[pos+3] & 0xff);
03144 return x;
03145 }
03146
03147 double TrueTypeFontFile::getFixed(int pos) {
03148 int x, y;
03149
03150 x = getShort(pos);
03151 y = getUShort(pos+2);
03152 return (double)x + (double)y / 65536;
03153 }
03154
03155 int TrueTypeFontFile::seekTable(const char *tag) {
03156 int i;
03157
03158 for (i = 0; i < nTables; ++i) {
03159 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
03160 return tableHdrs[i].offset;
03161 }
03162 }
03163 return -1;
03164 }
03165
03166 int TrueTypeFontFile::seekTableIdx(const char *tag) {
03167 int i;
03168
03169 for (i = 0; i < nTables; ++i) {
03170 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
03171 return i;
03172 }
03173 }
03174 return -1;
03175 }
03176
03177 void TrueTypeFontFile::cvtEncoding(const char **encodingA, GBool pdfFontHasEncoding,
03178 FontFileOutputFunc outputFunc,
03179 void *outputStream) {
03180 const char *name;
03181 char buf[64];
03182 int i;
03183
03184 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
03185 if (pdfFontHasEncoding) {
03186 for (i = 0; i < 256; ++i) {
03187 if (!(name = encodingA[i])) {
03188 name = ".notdef";
03189 }
03190 sprintf(buf, "dup %d /", i);
03191 (*outputFunc)(outputStream, buf, strlen(buf));
03192 (*outputFunc)(outputStream, name, strlen(name));
03193 (*outputFunc)(outputStream, " put\n", 5);
03194 }
03195 } else {
03196 for (i = 0; i < 256; ++i) {
03197 sprintf(buf, "dup %d /c%02x put\n", i, i);
03198 (*outputFunc)(outputStream, buf, strlen(buf));
03199 }
03200 }
03201 (*outputFunc)(outputStream, "readonly def\n", 13);
03202 }
03203
03204 void TrueTypeFontFile::cvtCharStrings(const char **encodingA,
03205 CharCodeToUnicode *toUnicode,
03206 GBool pdfFontHasEncoding,
03207 FontFileOutputFunc outputFunc,
03208 void *outputStream) {
03209 int unicodeCmap, macRomanCmap, msSymbolCmap;
03210 int nCmaps, cmapPlatform, cmapEncoding, cmapFmt, cmapOffset;
03211 T42FontIndexMode mode;
03212 const char *name;
03213 char buf[64], buf2[16];
03214 Unicode u;
03215 int pos, i, j, k;
03216
03217
03218 (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
03219 (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
03220
03221
03222 if ((pos = seekTable("cmap")) < 0) {
03223 goto err;
03224 }
03225
03226
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241 nCmaps = getUShort(pos+2);
03242 unicodeCmap = macRomanCmap = msSymbolCmap = -1;
03243 cmapOffset = 0;
03244 for (i = 0; i < nCmaps; ++i) {
03245 cmapPlatform = getUShort(pos + 4 + 8*i);
03246 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
03247 if (cmapPlatform == 3 && cmapEncoding == 1) {
03248 unicodeCmap = i;
03249 } else if (cmapPlatform == 1 && cmapEncoding == 0) {
03250 macRomanCmap = i;
03251 } else if (cmapPlatform == 3 && cmapEncoding == 0) {
03252 msSymbolCmap = i;
03253 }
03254 }
03255 i = 0;
03256 mode = t42FontModeCharCode;
03257 if (pdfFontHasEncoding) {
03258 if (unicodeCmap >= 0) {
03259 i = unicodeCmap;
03260 mode = t42FontModeUnicode;
03261 } else if (macRomanCmap >= 0) {
03262 i = macRomanCmap;
03263 mode = t42FontModeMacRoman;
03264 }
03265 } else {
03266 if (macRomanCmap >= 0) {
03267 i = macRomanCmap;
03268 mode = t42FontModeCharCode;
03269 } else if (msSymbolCmap >= 0) {
03270 i = msSymbolCmap;
03271 mode = t42FontModeCharCodeOffset;
03272 cmapOffset = 0xf000;
03273 }
03274 }
03275 cmapPlatform = getUShort(pos + 4 + 8*i);
03276 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
03277 pos += getULong(pos + 4 + 8*i + 4);
03278 cmapFmt = getUShort(pos);
03279 if (cmapFmt != 0 && cmapFmt != 4 && cmapFmt != 6) {
03280 error(-1, "Unimplemented cmap format (%d) in TrueType font file",
03281 cmapFmt);
03282 goto err;
03283 }
03284
03285
03286
03287
03288 j = 0;
03289 for (i = 0; i < 256; ++i) {
03290 if (pdfFontHasEncoding) {
03291 name = encodingA[i];
03292 } else {
03293 sprintf(buf2, "c%02x", i);
03294 name = buf2;
03295 }
03296 if (name && strcmp(name, ".notdef")) {
03297 switch (mode) {
03298 case t42FontModeUnicode:
03299 toUnicode->mapToUnicode((CharCode)i, &u, 1);
03300 j = (int)u;
03301 break;
03302 case t42FontModeCharCode:
03303 j = i;
03304 break;
03305 case t42FontModeCharCodeOffset:
03306 j = cmapOffset + i;
03307 break;
03308 case t42FontModeMacRoman:
03309 j = globalParams->getMacRomanCharCode(name);
03310 break;
03311 }
03312
03313
03314
03315
03316 if ((k = getCmapEntry(cmapFmt, pos, j)) > 0 &&
03317 k < nGlyphs) {
03318 (*outputFunc)(outputStream, "/", 1);
03319 (*outputFunc)(outputStream, name, strlen(name));
03320 sprintf(buf, " %d def\n", k);
03321 (*outputFunc)(outputStream, buf, strlen(buf));
03322 }
03323 }
03324 }
03325
03326 err:
03327 (*outputFunc)(outputStream, "end readonly def\n", 17);
03328 }
03329
03330 int TrueTypeFontFile::getCmapEntry(int cmapFmt, int pos, int code) {
03331 int cmapLen, cmapFirst;
03332 int segCnt, segEnd, segStart, segDelta, segOffset;
03333 int a, b, m, i;
03334
03335 switch (cmapFmt) {
03336 case 0:
03337 cmapLen = getUShort(pos + 2);
03338 if (code >= cmapLen) {
03339 return 0;
03340 }
03341 return getByte(pos + 6 + code);
03342
03343 case 4:
03344 segCnt = getUShort(pos + 6) / 2;
03345 a = -1;
03346 b = segCnt - 1;
03347 segEnd = getUShort(pos + 14 + 2*b);
03348 if (code > segEnd) {
03349
03350
03351 return 0;
03352 }
03353
03354 while (b - a > 1) {
03355 m = (a + b) / 2;
03356 segEnd = getUShort(pos + 14 + 2*m);
03357 if (segEnd < code) {
03358 a = m;
03359 } else {
03360 b = m;
03361 }
03362 }
03363 segStart = getUShort(pos + 16 + 2*segCnt + 2*b);
03364 segDelta = getUShort(pos + 16 + 4*segCnt + 2*b);
03365 segOffset = getUShort(pos + 16 + 6*segCnt + 2*b);
03366 if (segOffset == 0) {
03367 i = (code + segDelta) & 0xffff;
03368 } else {
03369 i = getUShort(pos + 16 + 6*segCnt + 2*b +
03370 segOffset + 2 * (code - segStart));
03371 if (i != 0) {
03372 i = (i + segDelta) & 0xffff;
03373 }
03374 }
03375 return i;
03376
03377 case 6:
03378 cmapFirst = getUShort(pos + 6);
03379 cmapLen = getUShort(pos + 8);
03380 if (code < cmapFirst || code >= cmapFirst + cmapLen) {
03381 return 0;
03382 }
03383 return getUShort(pos + 10 + 2*(code - cmapFirst));
03384
03385 default:
03386
03387 break;
03388 }
03389 return 0;
03390 }
03391
03392 void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
03393 void *outputStream, GString *name) {
03394 TTFontTableHdr newTableHdrs[nT42Tables];
03395 char tableDir[12 + nT42Tables*16];
03396 char headTable[54];
03397 int *origLocaTable;
03398 char *locaTable;
03399 int nNewTables;
03400 Guint checksum;
03401 int pos, glyfPos, length, glyphLength, pad;
03402 int i, j, k;
03403
03404
03405 memcpy(headTable, file + seekTable("head"), 54);
03406 headTable[8] = headTable[9] = headTable[10] = headTable[11] = (char)0;
03407
03408
03409
03410 origLocaTable = (int *)gmalloc((nGlyphs + 1) * sizeof(int));
03411 pos = seekTable("loca");
03412 for (i = 0; i <= nGlyphs; ++i) {
03413 if (locaFmt) {
03414 origLocaTable[i] = getULong(pos + 4*i);
03415 } else {
03416 origLocaTable[i] = 2 * getUShort(pos + 2*i);
03417 }
03418 }
03419 locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
03420 if (locaFmt) {
03421 locaTable[0] = locaTable[1] = locaTable[2] = locaTable[3] = 0;
03422 } else {
03423 locaTable[0] = locaTable[1] = 0;
03424 }
03425 pos = 0;
03426 for (i = 1; i <= nGlyphs; ++i) {
03427 length = origLocaTable[i] - origLocaTable[i-1];
03428 if (length & 3) {
03429 length += 4 - (length & 3);
03430 }
03431 pos += length;
03432 if (locaFmt) {
03433 locaTable[4*i ] = (char)(pos >> 24);
03434 locaTable[4*i+1] = (char)(pos >> 16);
03435 locaTable[4*i+2] = (char)(pos >> 8);
03436 locaTable[4*i+3] = (char) pos;
03437 } else {
03438 locaTable[2*i ] = (char)(pos >> 9);
03439 locaTable[2*i+1] = (char)(pos >> 1);
03440 }
03441 }
03442
03443
03444 nNewTables = 0;
03445 for (i = 0; i < nT42Tables; ++i) {
03446 if (t42Tables[i].required ||
03447 seekTable(t42Tables[i].tag) >= 0) {
03448 ++nNewTables;
03449 }
03450 }
03451
03452
03453
03454 pos = 12 + nNewTables*16;
03455 k = 0;
03456 for (i = 0; i < nT42Tables; ++i) {
03457 length = -1;
03458 checksum = 0;
03459 if (i == t42HeadTable) {
03460 length = 54;
03461 checksum = computeTableChecksum(headTable, 54);
03462 } else if (i == t42LocaTable) {
03463 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
03464 checksum = computeTableChecksum(locaTable, length);
03465 } else if (i == t42GlyfTable) {
03466 length = 0;
03467 checksum = 0;
03468 glyfPos = seekTable("glyf");
03469 for (j = 0; j < nGlyphs; ++j) {
03470 glyphLength = origLocaTable[j+1] - origLocaTable[j];
03471 pad = (glyphLength & 3) ? 4 - (glyphLength & 3) : 0;
03472 length += glyphLength + pad;
03473 checksum += computeTableChecksum(file + glyfPos + origLocaTable[j],
03474 glyphLength);
03475 }
03476 } else {
03477 if ((j = seekTableIdx(t42Tables[i].tag)) >= 0) {
03478 length = tableHdrs[j].length;
03479 checksum = computeTableChecksum(file + tableHdrs[j].offset, length);
03480 } else if (t42Tables[i].required) {
03481 error(-1, "Embedded TrueType font is missing a required table ('%s')",
03482 t42Tables[i].tag);
03483 length = 0;
03484 checksum = 0;
03485 }
03486 }
03487 if (length >= 0) {
03488 strncpy(newTableHdrs[k].tag, t42Tables[i].tag, 4);
03489 newTableHdrs[k].checksum = checksum;
03490 newTableHdrs[k].offset = pos;
03491 newTableHdrs[k].length = length;
03492 pad = (length & 3) ? 4 - (length & 3) : 0;
03493 pos += length + pad;
03494 ++k;
03495 }
03496 }
03497
03498
03499 tableDir[0] = 0x00;
03500 tableDir[1] = 0x01;
03501 tableDir[2] = 0x00;
03502 tableDir[3] = 0x00;
03503 tableDir[4] = 0;
03504 tableDir[5] = nNewTables;
03505 tableDir[6] = 0;
03506 tableDir[7] = (char)128;
03507 tableDir[8] = 0;
03508 tableDir[9] = 3;
03509 tableDir[10] = 0;
03510 tableDir[11] = (char)(16 * nNewTables - 128);
03511 pos = 12;
03512 for (i = 0; i < nNewTables; ++i) {
03513 tableDir[pos ] = newTableHdrs[i].tag[0];
03514 tableDir[pos+ 1] = newTableHdrs[i].tag[1];
03515 tableDir[pos+ 2] = newTableHdrs[i].tag[2];
03516 tableDir[pos+ 3] = newTableHdrs[i].tag[3];
03517 tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
03518 tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
03519 tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >> 8);
03520 tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
03521 tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
03522 tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
03523 tableDir[pos+10] = (char)(newTableHdrs[i].offset >> 8);
03524 tableDir[pos+11] = (char) newTableHdrs[i].offset;
03525 tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
03526 tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
03527 tableDir[pos+14] = (char)(newTableHdrs[i].length >> 8);
03528 tableDir[pos+15] = (char) newTableHdrs[i].length;
03529 pos += 16;
03530 }
03531
03532
03533 checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
03534 for (i = 0; i < nNewTables; ++i) {
03535 checksum += newTableHdrs[i].checksum;
03536 }
03537 checksum = 0xb1b0afba - checksum;
03538 headTable[ 8] = (char)(checksum >> 24);
03539 headTable[ 9] = (char)(checksum >> 16);
03540 headTable[10] = (char)(checksum >> 8);
03541 headTable[11] = (char) checksum;
03542
03543
03544 if (name) {
03545 (*outputFunc)(outputStream, "/", 1);
03546 (*outputFunc)(outputStream, name->getCString(), name->getLength());
03547 (*outputFunc)(outputStream, " [\n", 3);
03548 } else {
03549 (*outputFunc)(outputStream, "/sfnts [\n", 9);
03550 }
03551
03552
03553 dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
03554
03555
03556 for (i = 0; i < nNewTables; ++i) {
03557 if (i == t42HeadTable) {
03558 dumpString(headTable, 54, outputFunc, outputStream);
03559 } else if (i == t42LocaTable) {
03560 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
03561 dumpString(locaTable, length, outputFunc, outputStream);
03562 } else if (i == t42GlyfTable) {
03563 glyfPos = seekTable("glyf");
03564 for (j = 0; j < nGlyphs; ++j) {
03565 length = origLocaTable[j+1] - origLocaTable[j];
03566 if (length > 0) {
03567 dumpString(file + glyfPos + origLocaTable[j], length,
03568 outputFunc, outputStream);
03569 }
03570 }
03571 } else {
03572
03573
03574
03575 if ((length = newTableHdrs[i].length) > 0) {
03576 dumpString(file + seekTable(t42Tables[i].tag), length,
03577 outputFunc, outputStream);
03578 }
03579 }
03580 }
03581
03582
03583 (*outputFunc)(outputStream, "] def\n", 6);
03584
03585 gfree(origLocaTable);
03586 gfree(locaTable);
03587 }
03588
03589 void TrueTypeFontFile::dumpString(const char *s, int length,
03590 FontFileOutputFunc outputFunc,
03591 void *outputStream) {
03592 char buf[64];
03593 int pad, i, j;
03594
03595 (*outputFunc)(outputStream, "<", 1);
03596 for (i = 0; i < length; i += 32) {
03597 for (j = 0; j < 32 && i+j < length; ++j) {
03598 sprintf(buf, "%02X", s[i+j] & 0xff);
03599 (*outputFunc)(outputStream, buf, strlen(buf));
03600 }
03601 if (i % (65536 - 32) == 65536 - 64) {
03602 (*outputFunc)(outputStream, ">\n<", 3);
03603 } else if (i+32 < length) {
03604 (*outputFunc)(outputStream, "\n", 1);
03605 }
03606 }
03607 if (length & 3) {
03608 pad = 4 - (length & 3);
03609 for (i = 0; i < pad; ++i) {
03610 (*outputFunc)(outputStream, "00", 2);
03611 }
03612 }
03613
03614 (*outputFunc)(outputStream, "00>\n", 4);
03615 }
03616
03617 Guint TrueTypeFontFile::computeTableChecksum(const char *data, int length) {
03618 Guint checksum, word;
03619 int i;
03620
03621 checksum = 0;
03622 for (i = 0; i+3 < length; i += 4) {
03623 word = ((data[i ] & 0xff) << 24) +
03624 ((data[i+1] & 0xff) << 16) +
03625 ((data[i+2] & 0xff) << 8) +
03626 (data[i+3] & 0xff);
03627 checksum += word;
03628 }
03629 if (length & 3) {
03630 word = 0;
03631 i = length & ~3;
03632 switch (length & 3) {
03633 case 3:
03634 word |= (data[i+2] & 0xff) << 8;
03635 case 2:
03636 word |= (data[i+1] & 0xff) << 16;
03637 case 1:
03638 word |= (data[i ] & 0xff) << 24;
03639 break;
03640 }
03641 checksum += word;
03642 }
03643 return checksum;
03644 }
03645
03646 void TrueTypeFontFile::writeTTF(FILE *out) {
03647 static char cmapTab[20] = {
03648 0, 0,
03649 0, 1,
03650 0, 1,
03651 0, 0,
03652 0, 0, 0, 12,
03653 0, 0,
03654 0, 1,
03655 0, 1,
03656 0,
03657 0
03658 };
03659 static char nameTab[8] = {
03660 0, 0,
03661 0, 0,
03662 0, 6,
03663 0, 0
03664 };
03665 static char postTab[32] = {
03666 0, 1, 0, 0,
03667 0, 0, 0, 0,
03668 0, 0,
03669 0, 0,
03670 0, 0, 0, 0,
03671 0, 0, 0, 0,
03672 0, 0, 0, 0,
03673 0, 0, 0, 0,
03674 0, 0, 0, 0
03675 };
03676 GBool haveCmap, haveName, havePost;
03677 GBool dirCmap, dirName, dirPost;
03678 int nNewTables, nAllTables, pad;
03679 char *tableDir;
03680 Guint t, pos;
03681 int i, j;
03682
03683
03684 haveCmap = seekTable("cmap") >= 0;
03685 haveName = seekTable("name") >= 0;
03686 havePost = seekTable("post") >= 0;
03687 nNewTables = (haveCmap ? 0 : 1) + (haveName ? 0 : 1) + (havePost ? 0 : 1);
03688 if (!nNewTables && !mungedCmapSize) {
03689
03690 fwrite(file, 1, len, out);
03691 return;
03692 }
03693
03694
03695 nAllTables = nTables + nNewTables;
03696 tableDir = (char *)gmalloc(12 + nAllTables * 16);
03697 memcpy(tableDir, file, 12 + nTables * 16);
03698 tableDir[4] = (char)((nAllTables >> 8) & 0xff);
03699 tableDir[5] = (char)(nAllTables & 0xff);
03700 for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
03701 t = 1 << (4 + i);
03702 tableDir[6] = (char)((t >> 8) & 0xff);
03703 tableDir[7] = (char)(t & 0xff);
03704 tableDir[8] = (char)((i >> 8) & 0xff);
03705 tableDir[9] = (char)(i & 0xff);
03706 t = nAllTables * 16 - t;
03707 tableDir[10] = (char)((t >> 8) & 0xff);
03708 tableDir[11] = (char)(t & 0xff);
03709 dirCmap = haveCmap;
03710 dirName = haveName;
03711 dirPost = havePost;
03712 j = 0;
03713 pad = (len & 3) ? 4 - (len & 3) : 0;
03714 pos = len + pad + 16 * nNewTables;
03715 for (i = 0; i < nTables; ++i) {
03716 if (!dirCmap && strncmp(tableHdrs[i].tag, "cmap", 4) > 0) {
03717 tableDir[12 + 16*j ] = 'c';
03718 tableDir[12 + 16*j + 1] = 'm';
03719 tableDir[12 + 16*j + 2] = 'a';
03720 tableDir[12 + 16*j + 3] = 'p';
03721 tableDir[12 + 16*j + 4] = (char)0;
03722 tableDir[12 + 16*j + 5] = (char)0;
03723 tableDir[12 + 16*j + 6] = (char)0;
03724 tableDir[12 + 16*j + 7] = (char)0;
03725 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
03726 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
03727 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
03728 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
03729 tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
03730 tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
03731 tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >> 8) & 0xff);
03732 tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab) & 0xff);
03733 pos += sizeof(cmapTab);
03734 ++j;
03735 dirCmap = gTrue;
03736 }
03737 if (!dirName && strncmp(tableHdrs[i].tag, "name", 4) > 0) {
03738 tableDir[12 + 16*j ] = 'n';
03739 tableDir[12 + 16*j + 1] = 'a';
03740 tableDir[12 + 16*j + 2] = 'm';
03741 tableDir[12 + 16*j + 3] = 'e';
03742 tableDir[12 + 16*j + 4] = (char)0;
03743 tableDir[12 + 16*j + 5] = (char)0;
03744 tableDir[12 + 16*j + 6] = (char)0;
03745 tableDir[12 + 16*j + 7] = (char)0;
03746 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
03747 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
03748 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
03749 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
03750 tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
03751 tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
03752 tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >> 8) & 0xff);
03753 tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab) & 0xff);
03754 pos += sizeof(nameTab);
03755 ++j;
03756 dirName = gTrue;
03757 }
03758 if (!dirName && strncmp(tableHdrs[i].tag, "post", 4) > 0) {
03759 tableDir[12 + 16*j ] = 'p';
03760 tableDir[12 + 16*j + 1] = 'o';
03761 tableDir[12 + 16*j + 2] = 's';
03762 tableDir[12 + 16*j + 3] = 't';
03763 tableDir[12 + 16*j + 4] = (char)0;
03764 tableDir[12 + 16*j + 5] = (char)0;
03765 tableDir[12 + 16*j + 6] = (char)0;
03766 tableDir[12 + 16*j + 7] = (char)0;
03767 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
03768 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
03769 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
03770 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
03771 tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
03772 tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
03773 tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >> 8) & 0xff);
03774 tableDir[12 + 16*j + 15] = (char)( sizeof(postTab) & 0xff);
03775 pos += sizeof(postTab);
03776 ++j;
03777 dirPost = gTrue;
03778 }
03779 tableDir[12 + 16*j ] = tableHdrs[i].tag[0];
03780 tableDir[12 + 16*j + 1] = tableHdrs[i].tag[1];
03781 tableDir[12 + 16*j + 2] = tableHdrs[i].tag[2];
03782 tableDir[12 + 16*j + 3] = tableHdrs[i].tag[3];
03783 tableDir[12 + 16*j + 4] = (char)((tableHdrs[i].checksum >> 24) & 0xff);
03784 tableDir[12 + 16*j + 5] = (char)((tableHdrs[i].checksum >> 16) & 0xff);
03785 tableDir[12 + 16*j + 6] = (char)((tableHdrs[i].checksum >> 8) & 0xff);
03786 tableDir[12 + 16*j + 7] = (char)( tableHdrs[i].checksum & 0xff);
03787 t = tableHdrs[i].offset + nNewTables * 16;
03788 tableDir[12 + 16*j + 8] = (char)((t >> 24) & 0xff);
03789 tableDir[12 + 16*j + 9] = (char)((t >> 16) & 0xff);
03790 tableDir[12 + 16*j + 10] = (char)((t >> 8) & 0xff);
03791 tableDir[12 + 16*j + 11] = (char)( t & 0xff);
03792 tableDir[12 + 16*j + 12] = (char)((tableHdrs[i].length >> 24) & 0xff);
03793 tableDir[12 + 16*j + 13] = (char)((tableHdrs[i].length >> 16) & 0xff);
03794 tableDir[12 + 16*j + 14] = (char)((tableHdrs[i].length >> 8) & 0xff);
03795 tableDir[12 + 16*j + 15] = (char)( tableHdrs[i].length & 0xff);
03796 ++j;
03797 }
03798 if (!dirCmap) {
03799 tableDir[12 + 16*j ] = 'c';
03800 tableDir[12 + 16*j + 1] = 'm';
03801 tableDir[12 + 16*j + 2] = 'a';
03802 tableDir[12 + 16*j + 3] = 'p';
03803 tableDir[12 + 16*j + 4] = (char)0;
03804 tableDir[12 + 16*j + 5] = (char)0;
03805 tableDir[12 + 16*j + 6] = (char)0;
03806 tableDir[12 + 16*j + 7] = (char)0;
03807 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
03808 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
03809 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
03810 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
03811 tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
03812 tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
03813 tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >> 8) & 0xff);
03814 tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab) & 0xff);
03815 pos += sizeof(cmapTab);
03816 ++j;
03817 dirCmap = gTrue;
03818 }
03819 if (!dirName) {
03820 tableDir[12 + 16*j ] = 'n';
03821 tableDir[12 + 16*j + 1] = 'a';
03822 tableDir[12 + 16*j + 2] = 'm';
03823 tableDir[12 + 16*j + 3] = 'e';
03824 tableDir[12 + 16*j + 4] = (char)0;
03825 tableDir[12 + 16*j + 5] = (char)0;
03826 tableDir[12 + 16*j + 6] = (char)0;
03827 tableDir[12 + 16*j + 7] = (char)0;
03828 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
03829 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
03830 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
03831 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
03832 tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
03833 tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
03834 tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >> 8) & 0xff);
03835 tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab) & 0xff);
03836 pos += sizeof(nameTab);
03837 ++j;
03838 dirName = gTrue;
03839 }
03840 if (!dirPost) {
03841 tableDir[12 + 16*j ] = 'p';
03842 tableDir[12 + 16*j + 1] = 'o';
03843 tableDir[12 + 16*j + 2] = 's';
03844 tableDir[12 + 16*j + 3] = 't';
03845 tableDir[12 + 16*j + 4] = (char)0;
03846 tableDir[12 + 16*j + 5] = (char)0;
03847 tableDir[12 + 16*j + 6] = (char)0;
03848 tableDir[12 + 16*j + 7] = (char)0;
03849 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
03850 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
03851 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
03852 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
03853 tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
03854 tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
03855 tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >> 8) & 0xff);
03856 tableDir[12 + 16*j + 15] = (char)( sizeof(postTab) & 0xff);
03857 pos += sizeof(postTab);
03858 ++j;
03859 dirPost = gTrue;
03860 }
03861
03862
03863 fwrite(tableDir, 1, 12 + 16 * nAllTables, out);
03864
03865
03866 fwrite(file + 12 + 16*nTables, 1, len - (12 + 16*nTables), out);
03867
03868
03869 for (i = 0; i < pad; ++i) {
03870 fputc((char)0, out);
03871 }
03872 if (!haveCmap) {
03873 fwrite(cmapTab, 1, sizeof(cmapTab), out);
03874 }
03875 if (!haveName) {
03876 fwrite(nameTab, 1, sizeof(nameTab), out);
03877 }
03878 if (!havePost) {
03879 fwrite(postTab, 1, sizeof(postTab), out);
03880 }
03881
03882 gfree(tableDir);
03883 }