applied diff between xpdf-3.00-orig and xpdf-3.00-swftools
[swftools.git] / pdf2swf / xpdf / FoFiType1C.cc
index a1cec31..a173e7c 100644 (file)
@@ -120,7 +120,7 @@ Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
     }
   }
   ++n;
-  map = (Gushort *)gmalloc(n * sizeof(Gushort));
+  map = (Gushort *)gmallocn(n, sizeof(Gushort));
   memset(map, 0, n * sizeof(Gushort));
   for (i = 0; i < nGlyphs; ++i) {
     map[charset[i]] = i;
@@ -406,7 +406,7 @@ void FoFiType1C::convertToCIDType0(char *psName,
       nCIDs = charset[i] + 1;
     }
   }
-  cidMap = (int *)gmalloc(nCIDs * sizeof(int));
+  cidMap = (int *)gmallocn(nCIDs, sizeof(int));
   for (i = 0; i < nCIDs; ++i) {
     cidMap[i] = -1;
   }
@@ -416,7 +416,7 @@ void FoFiType1C::convertToCIDType0(char *psName,
 
   // build the charstrings
   charStrings = new GString();
-  charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
+  charStringOffsets = (int *)gmallocn(nCIDs + 1, sizeof(int));
   for (i = 0; i < nCIDs; ++i) {
     charStringOffsets[i] = charStrings->getLength();
     if ((gid = cidMap[i]) >= 0) {
@@ -479,10 +479,18 @@ void FoFiType1C::convertToCIDType0(char *psName,
   sprintf(buf, "  /Supplement %d def\n", topDict.supplement);
   (*outputFunc)(outputStream, buf, strlen(buf));
   (*outputFunc)(outputStream, "end def\n", 8);
-  sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
-         topDict.fontMatrix[0], topDict.fontMatrix[1], topDict.fontMatrix[2],
-         topDict.fontMatrix[3], topDict.fontMatrix[4], topDict.fontMatrix[5]);
-  (*outputFunc)(outputStream, buf, strlen(buf));
+  if (topDict.hasFontMatrix) {
+    sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
+           topDict.fontMatrix[0], topDict.fontMatrix[1],
+           topDict.fontMatrix[2], topDict.fontMatrix[3],
+           topDict.fontMatrix[4], topDict.fontMatrix[5]);
+    (*outputFunc)(outputStream, buf, strlen(buf));
+  } else if (privateDicts[0].hasFontMatrix) {
+    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+  } else {
+    (*outputFunc)(outputStream,
+                 "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
+  }
   sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
          topDict.fontBBox[0], topDict.fontBBox[1],
          topDict.fontBBox[2], topDict.fontBBox[3]);
@@ -512,7 +520,18 @@ void FoFiType1C::convertToCIDType0(char *psName,
     sprintf(buf, "dup %d 10 dict begin\n", i);
     (*outputFunc)(outputStream, buf, strlen(buf));
     (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
-    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+    if (privateDicts[i].hasFontMatrix) {
+      sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
+             privateDicts[i].fontMatrix[0],
+             privateDicts[i].fontMatrix[1],
+             privateDicts[i].fontMatrix[2],
+             privateDicts[i].fontMatrix[3],
+             privateDicts[i].fontMatrix[4],
+             privateDicts[i].fontMatrix[5]);
+      (*outputFunc)(outputStream, buf, strlen(buf));
+    } else {
+      (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+    }
     sprintf(buf, "/PaintType %d def\n", topDict.paintType);
     (*outputFunc)(outputStream, buf, strlen(buf));
     (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
@@ -673,7 +692,7 @@ void FoFiType1C::convertToType0(char *psName,
       nCIDs = charset[i] + 1;
     }
   }
-  cidMap = (int *)gmalloc(nCIDs * sizeof(int));
+  cidMap = (int *)gmallocn(nCIDs, sizeof(int));
   for (i = 0; i < nCIDs; ++i) {
     cidMap[i] = -1;
   }
@@ -702,11 +721,21 @@ void FoFiType1C::convertToType0(char *psName,
     sprintf(buf, "_%02x def\n", i >> 8);
     (*outputFunc)(outputStream, buf, strlen(buf));
     (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
-    sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
-           topDict.fontMatrix[0], topDict.fontMatrix[1],
-           topDict.fontMatrix[2], topDict.fontMatrix[3],
-           topDict.fontMatrix[4], topDict.fontMatrix[5]);
-    (*outputFunc)(outputStream, buf, strlen(buf));
+    if (privateDicts[fd].hasFontMatrix) {
+      sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
+             privateDicts[fd].fontMatrix[0],
+             privateDicts[fd].fontMatrix[1],
+             privateDicts[fd].fontMatrix[2],
+             privateDicts[fd].fontMatrix[3],
+             privateDicts[fd].fontMatrix[4],
+             privateDicts[fd].fontMatrix[5]);
+      (*outputFunc)(outputStream, buf, strlen(buf));
+    } else if (topDict.hasFontMatrix) {
+      (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+    } else {
+      (*outputFunc)(outputStream,
+                   "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
+    }
     sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
            topDict.fontBBox[0], topDict.fontBBox[1],
            topDict.fontBBox[2], topDict.fontBBox[3]);
@@ -890,7 +919,15 @@ void FoFiType1C::convertToType0(char *psName,
   (*outputFunc)(outputStream, psName, strlen(psName));
   (*outputFunc)(outputStream, " def\n", 5);
   (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
-  (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+  if (topDict.hasFontMatrix) {
+    sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
+           topDict.fontMatrix[0], topDict.fontMatrix[1],
+           topDict.fontMatrix[2], topDict.fontMatrix[3],
+           topDict.fontMatrix[4], topDict.fontMatrix[5]);
+    (*outputFunc)(outputStream, buf, strlen(buf));
+  } else {
+    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+  }
   (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
   (*outputFunc)(outputStream, "/Encoding [\n", 12);
   for (i = 0; i < nCIDs; i += 256) {
@@ -950,6 +987,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
     nOps = 0;
     nHints = 0;
     firstOp = gTrue;
+    openPath = gFalse;
   }
 
   pos = offset;
@@ -973,6 +1011,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
        d = 0;
        dFP = gFalse;
        for (k = 0; k < nOps; k += 2) {
+         // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
          if (ops[k+1].num < 0) {
            d += ops[k].num + ops[k+1].num;
            dFP |= ops[k].isFP | ops[k+1].isFP;
@@ -1002,6 +1041,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
        d = 0;
        dFP = gFalse;
        for (k = 0; k < nOps; k += 2) {
+         // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
          if (ops[k+1].num < 0) {
            d += ops[k].num + ops[k+1].num;
            dFP |= ops[k].isFP | ops[k+1].isFP;
@@ -1025,6 +1065,10 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
          cvtGlyphWidth(nOps == 2, charBuf, pDict);
          firstOp = gFalse;
        }
+       if (openPath) {
+         charBuf->append((char)9);
+         openPath = gFalse;
+       }
        if (nOps != 1) {
          //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
        }
@@ -1042,6 +1086,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
          charBuf->append((char)5);
        }
        nOps = 0;
+       openPath = gTrue;
        break;
       case 0x0006:             // hlineto
        if (nOps < 1) {
@@ -1052,6 +1097,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
          charBuf->append((char)((k & 1) ? 7 : 6));
        }
        nOps = 0;
+       openPath = gTrue;
        break;
       case 0x0007:             // vlineto
        if (nOps < 1) {
@@ -1062,6 +1108,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
          charBuf->append((char)((k & 1) ? 6 : 7));
        }
        nOps = 0;
+       openPath = gTrue;
        break;
       case 0x0008:             // rrcurveto
        if (nOps < 6 || nOps % 6 != 0) {
@@ -1077,6 +1124,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
          charBuf->append((char)8);
        }
        nOps = 0;
+       openPath = gTrue;
        break;
       case 0x000a:             // callsubr
        if (nOps >= 1) {
@@ -1102,6 +1150,10 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
          cvtGlyphWidth(nOps == 1 || nOps == 5, charBuf, pDict);
          firstOp = gFalse;
        }
+       if (openPath) {
+         charBuf->append((char)9);
+         openPath = gFalse;
+       }
        if (nOps == 4) {
          cvtNum(0, gFalse, charBuf);
          cvtNum(ops[0].num, ops[0].isFP, charBuf);
@@ -1177,6 +1229,10 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
          cvtGlyphWidth(nOps == 3, charBuf, pDict);
          firstOp = gFalse;
        }
+       if (openPath) {
+         charBuf->append((char)9);
+         openPath = gFalse;
+       }
        if (nOps != 2) {
          //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
        }
@@ -1190,6 +1246,10 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
          cvtGlyphWidth(nOps == 2, charBuf, pDict);
          firstOp = gFalse;
        }
+       if (openPath) {
+         charBuf->append((char)9);
+         openPath = gFalse;
+       }
        if (nOps != 1) {
          //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
        }
@@ -1226,6 +1286,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
        cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
        charBuf->append((char)5);
        nOps = 0;
+       openPath = gTrue;
        break;
       case 0x0019:             // rlinecurve
        if (nOps < 8 || (nOps - 6) % 2 != 0) {
@@ -1244,6 +1305,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
        cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
        charBuf->append((char)8);
        nOps = 0;
+       openPath = gTrue;
        break;
       case 0x001a:             // vvcurveto
        if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
@@ -1271,6 +1333,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
          charBuf->append((char)8);
        }
        nOps = 0;
+       openPath = gTrue;
        break;
       case 0x001b:             // hhcurveto
        if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
@@ -1298,6 +1361,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
          charBuf->append((char)8);
        }
        nOps = 0;
+       openPath = gTrue;
        break;
       case 0x001d:             // callgsubr
        if (nOps >= 1) {
@@ -1351,6 +1415,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
          charBuf->append((char)8);
        }
        nOps = 0;
+       openPath = gTrue;
        break;
       case 0x001f:             // hvcurveto
        if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
@@ -1390,6 +1455,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
          charBuf->append((char)8);
        }
        nOps = 0;
+       openPath = gTrue;
        break;
       case 0x0c00:             // dotsection (should be Type 1 only?)
        // ignored
@@ -1439,6 +1505,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
        cvtNum(0, gFalse, charBuf);
        charBuf->append((char)8);
        nOps = 0;
+       openPath = gTrue;
        break;
       case 0x0c23:             // flex
        if (nOps != 13) {
@@ -1459,6 +1526,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
        cvtNum(ops[11].num, ops[11].isFP, charBuf);
        charBuf->append((char)8);
        nOps = 0;
+       openPath = gTrue;
        break;
       case 0x0c24:             // hflex1
        if (nOps != 9) {
@@ -1480,6 +1548,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
               ops[1].isFP | ops[3].isFP | ops[7].isFP, charBuf);
        charBuf->append((char)8);
        nOps = 0;
+       openPath = gTrue;
        break;
       case 0x0c25:             // flex1
        if (nOps != 11) {
@@ -1509,6 +1578,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
        }
        charBuf->append((char)8);
        nOps = 0;
+       openPath = gTrue;
        break;
       default:
        //~ error(-1, "Illegal Type 2 charstring op: %04x",
@@ -1695,7 +1765,7 @@ GBool FoFiType1C::parse() {
       }
       nFDs = fdIdx.len;
       privateDicts = (Type1CPrivateDict *)
-                        gmalloc(nFDs * sizeof(Type1CPrivateDict));
+                        gmallocn(nFDs, sizeof(Type1CPrivateDict));
       for (i = 0; i < nFDs; ++i) {
        getIndexVal(&fdIdx, i, &val, &parsedOk);
        if (!parsedOk) {
@@ -1776,6 +1846,7 @@ void FoFiType1C::readTopDict() {
   topDict.fontMatrix[3] = 0.001;
   topDict.fontMatrix[4] = 0;
   topDict.fontMatrix[5] = 0;
+  topDict.hasFontMatrix = gFalse;
   topDict.uniqueID = 0;
   topDict.fontBBox[0] = 0;
   topDict.fontBBox[1] = 0;
@@ -1824,7 +1895,8 @@ void FoFiType1C::readTopDict() {
                   topDict.fontMatrix[2] = ops[2].num;
                   topDict.fontMatrix[3] = ops[3].num;
                   topDict.fontMatrix[4] = ops[4].num;
-                  topDict.fontMatrix[5] = ops[5].num; break;
+                  topDict.fontMatrix[5] = ops[5].num;
+                  topDict.hasFontMatrix = gTrue; break;
       case 0x000d: topDict.uniqueID = (int)ops[0].num; break;
       case 0x0005: topDict.fontBBox[0] = ops[0].num;
                   topDict.fontBBox[1] = ops[1].num;
@@ -1848,10 +1920,14 @@ void FoFiType1C::readTopDict() {
 }
 
 // Read a CID font dict (FD) - this pulls out the private dict
-// pointer, and reads the private dict.
+// pointer, and reads the private dict.  It also pulls the FontMatrix
+// (if any) out of the FD.
 void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
   int pos, pSize, pOffset;
+  double fontMatrix[6];
+  GBool hasFontMatrix;
 
+  hasFontMatrix = gFalse;
   pSize = pOffset = 0;
   pos = offset;
   nOps = 0;
@@ -1869,17 +1945,35 @@ void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
        pSize = (int)ops[0].num;
        pOffset = (int)ops[1].num;
        break;
+      } else if (ops[nOps - 1].op == 0x0c07) {
+       fontMatrix[0] = ops[0].num;
+       fontMatrix[1] = ops[1].num;
+       fontMatrix[2] = ops[2].num;
+       fontMatrix[3] = ops[3].num;
+       fontMatrix[4] = ops[4].num;
+       fontMatrix[5] = ops[5].num;
+       hasFontMatrix = gTrue;
       }
       nOps = 0;
     }
   }
   readPrivateDict(pOffset, pSize, pDict);
+  if (hasFontMatrix) {
+    pDict->fontMatrix[0] = fontMatrix[0];
+    pDict->fontMatrix[1] = fontMatrix[1];
+    pDict->fontMatrix[2] = fontMatrix[2];
+    pDict->fontMatrix[3] = fontMatrix[3];
+    pDict->fontMatrix[4] = fontMatrix[4];
+    pDict->fontMatrix[5] = fontMatrix[5];
+    pDict->hasFontMatrix = gTrue;
+  }
 }
 
 void FoFiType1C::readPrivateDict(int offset, int length,
                                 Type1CPrivateDict *pDict) {
   int pos;
 
+  pDict->hasFontMatrix = gFalse;
   pDict->nBlueValues = 0;
   pDict->nOtherBlues = 0;
   pDict->nFamilyBlues = 0;
@@ -1898,9 +1992,9 @@ void FoFiType1C::readPrivateDict(int offset, int length,
   pDict->initialRandomSeed = 0;
   pDict->subrsOffset = 0;
   pDict->defaultWidthX = 0;
-  pDict->defaultWidthXFP = 0;
+  pDict->defaultWidthXFP = gFalse;
   pDict->nominalWidthX = 0;
-  pDict->nominalWidthXFP = 0;
+  pDict->nominalWidthXFP = gFalse;
 
   // no dictionary
   if (offset == 0 || length == 0) {
@@ -1979,9 +2073,11 @@ void FoFiType1C::readPrivateDict(int offset, int length,
        break;
       case 0x0014:
        pDict->defaultWidthX = ops[0].num;
+       pDict->defaultWidthXFP = ops[0].isFP;
        break;
       case 0x0015:
        pDict->nominalWidthX = ops[0].num;
+       pDict->nominalWidthXFP = ops[0].isFP;
        break;
       }
       nOps = 0;
@@ -2052,7 +2148,7 @@ void FoFiType1C::buildEncoding() {
     encoding = fofiType1ExpertEncoding;
 
   } else {
-    encoding = (char **)gmalloc(256 * sizeof(char *));
+    encoding = (char **)gmallocn(256, sizeof(char *));
     for (i = 0; i < 256; ++i) {
       encoding[i] = NULL;
     }
@@ -2139,7 +2235,7 @@ GBool FoFiType1C::readCharset() {
   } else if (topDict.charsetOffset == 2) {
     charset = fofiType1CExpertSubsetCharset;
   } else {
-    charset = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
+    charset = (Gushort *)gmallocn(nGlyphs, sizeof(Gushort));
     for (i = 0; i < nGlyphs; ++i) {
       charset[i] = 0;
     }
@@ -2324,9 +2420,9 @@ void FoFiType1C::getIndex(int pos, Type1CIndex *idx, GBool *ok) {
   idx->pos = pos;
   idx->len = getU16BE(pos, ok);
   if (idx->len == 0) {
-    // empty indexes are legal
+    // empty indexes are legal and contain just the length field
     idx->offSize = 0;
-    idx->startPos = idx->endPos = 0;
+    idx->startPos = idx->endPos = pos + 2;
   } else {
     idx->offSize = getU8(pos + 2, ok);
     if (idx->offSize < 1 || idx->offSize > 4) {
@@ -2356,7 +2452,7 @@ void FoFiType1C::getIndexVal(Type1CIndex *idx, int i,
                                   idx->offSize, ok);
   pos1 = idx->startPos + getUVarBE(idx->pos + 3 + (i + 1) * idx->offSize,
                                   idx->offSize, ok);
-  if (pos0 < idx->startPos || pos0 >= idx->endPos ||
+  if (pos0 < idx->startPos || pos0 > idx->endPos ||
       pos1 <= idx->startPos || pos1 > idx->endPos ||
       pos1 < pos0) {
     *ok = gFalse;
@@ -2374,7 +2470,7 @@ char *FoFiType1C::getString(int sid, char *buf, GBool *ok) {
   } else {
     sid -= 391;
     getIndexVal(&stringIdx, sid, &val, ok);
-    if (ok) {
+    if (*ok) {
       if ((n = val.len) > 255) {
        n = 255;
       }