[PDF] Fix bug in ToUnicode table generation for Type 3 fonts.

True glyphIDs where being using in the Type3 ToUnicode table instead of IDs of 1-255.  This causes poppler to complain about each entry.

BUG:skia:1565

R=bungeman@google.com

Author: vandebo@chromium.org

Review URL: https://codereview.chromium.org/112053005

git-svn-id: http://skia.googlecode.com/svn/trunk@12625 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp
index 1641a89..ef9c3bb 100644
--- a/src/pdf/SkPDFFont.cpp
+++ b/src/pdf/SkPDFFont.cpp
@@ -460,7 +460,7 @@
 // endbfchar              endbfrange
 //
 // Adobe Technote 5014 said: "Code mappings (unlike codespace ranges) may
-// overlap, but succeeding maps superceded preceding maps."
+// overlap, but succeeding maps supersede preceding maps."
 //
 // In case of searching text in PDF, bfrange will have higher precedence so
 // typing char id 0x0014 in search box will get glyph id 0x0004 first.  However,
@@ -475,28 +475,35 @@
 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode,
                           const SkPDFGlyphSet* subset,
                           SkDynamicMemoryWStream* cmap,
+                          bool multiByteGlyphs,
                           uint16_t firstGlyphID,
                           uint16_t lastGlyphID);
 
 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode,
                           const SkPDFGlyphSet* subset,
                           SkDynamicMemoryWStream* cmap,
+                          bool multiByteGlyphs,
                           uint16_t firstGlyphID,
                           uint16_t lastGlyphID) {
     if (glyphToUnicode.isEmpty()) {
         return;
     }
+    int glyphOffset = 0;
+    if (!multiByteGlyphs) {
+        glyphOffset = firstGlyphID - 1;
+    }
 
     SkTDArray<BFChar> bfcharEntries;
     SkTDArray<BFRange> bfrangeEntries;
 
     BFRange currentRangeEntry = {0, 0, 0};
     bool rangeEmpty = true;
-    const int limit = SkMin32(lastGlyphID + 1, glyphToUnicode.count());
+    const int limit =
+            SkMin32(lastGlyphID + 1, glyphToUnicode.count()) - glyphOffset;
 
-    for (int i = firstGlyphID; i < limit + 1; ++i) {
+    for (int i = firstGlyphID - glyphOffset; i < limit + 1; ++i) {
         bool inSubset = i < limit &&
-                        (subset == NULL || subset->has(i));
+                        (subset == NULL || subset->has(i + glyphOffset));
         if (!rangeEmpty) {
             // PDF spec requires bfrange not changing the higher byte,
             // e.g. <1035> <10FF> <2222> is ok, but
@@ -505,8 +512,8 @@
                 i == currentRangeEntry.fEnd + 1 &&
                 i >> 8 == currentRangeEntry.fStart >> 8 &&
                 i < limit &&
-                glyphToUnicode[i] == currentRangeEntry.fUnicode + i -
-                                         currentRangeEntry.fStart;
+                glyphToUnicode[i + glyphOffset] ==
+                    currentRangeEntry.fUnicode + i - currentRangeEntry.fStart;
             if (!inSubset || !inRange) {
                 if (currentRangeEntry.fEnd > currentRangeEntry.fStart) {
                     bfrangeEntries.push(currentRangeEntry);
@@ -522,7 +529,7 @@
             currentRangeEntry.fEnd = i;
             if (rangeEmpty) {
               currentRangeEntry.fStart = i;
-              currentRangeEntry.fUnicode = glyphToUnicode[i];
+              currentRangeEntry.fUnicode = glyphToUnicode[i + glyphOffset];
               rangeEmpty = false;
             }
         }
@@ -537,11 +544,16 @@
 static SkPDFStream* generate_tounicode_cmap(
         const SkTDArray<SkUnichar>& glyphToUnicode,
         const SkPDFGlyphSet* subset,
+        bool multiByteGlyphs,
         uint16_t firstGlyphID,
         uint16_t lastGlyphID) {
     SkDynamicMemoryWStream cmap;
-    append_tounicode_header(&cmap, firstGlyphID, lastGlyphID);
-    append_cmap_sections(glyphToUnicode, subset, &cmap,
+    if (multiByteGlyphs) {
+        append_tounicode_header(&cmap, firstGlyphID, lastGlyphID);
+    } else {
+        append_tounicode_header(&cmap, 1, lastGlyphID - firstGlyphID + 1);
+    }
+    append_cmap_sections(glyphToUnicode, subset, &cmap, multiByteGlyphs,
                          firstGlyphID, lastGlyphID);
     append_cmap_footer(&cmap);
     SkAutoTUnref<SkMemoryStream> cmapStream(new SkMemoryStream());
@@ -1027,7 +1039,8 @@
     }
     SkAutoTUnref<SkPDFStream> pdfCmap(
         generate_tounicode_cmap(fFontInfo->fGlyphToUnicode, subset,
-                                firstGlyphID(), lastGlyphID()));
+                                multiByteGlyphs(), firstGlyphID(),
+                                lastGlyphID()));
     addResource(pdfCmap.get());
     insert("ToUnicode", new SkPDFObjRef(pdfCmap.get()))->unref();
 }
@@ -1420,8 +1433,8 @@
     }
 
     insert("FontBBox", makeFontBBox(bbox, 1000))->unref();
-    insertInt("FirstChar", firstGlyphID());
-    insertInt("LastChar", lastGlyphID());
+    insertInt("FirstChar", 1);
+    insertInt("LastChar", lastGlyphID() - firstGlyphID() + 1);
     insert("Widths", widthArray.get());
     insertName("CIDToGIDMap", "Identity");
 
diff --git a/tests/ToUnicode.cpp b/tests/ToUnicode.cpp
index 69ec614..d518432 100644
--- a/tests/ToUnicode.cpp
+++ b/tests/ToUnicode.cpp
@@ -28,6 +28,7 @@
 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode,
                           const SkPDFGlyphSet* subset,
                           SkDynamicMemoryWStream* cmap,
+                          bool multiByteGlyphs,
                           uint16_t firstGlypthID,
                           uint16_t lastGlypthID);
 
@@ -74,7 +75,7 @@
 
     SkDynamicMemoryWStream buffer;
     subset.set(glyphsInSubset.begin(), glyphsInSubset.count());
-    append_cmap_sections(glyphToUnicode, &subset, &buffer, 0, 0xFFFF);
+    append_cmap_sections(glyphToUnicode, &subset, &buffer, true, 0, 0xFFFF);
 
     char expectedResult[] =
 "4 beginbfchar\n\
@@ -96,7 +97,7 @@
     // Remove characters and ranges.
     buffer.reset();
 
-    append_cmap_sections(glyphToUnicode, &subset, &buffer, 8, 0x00FF);
+    append_cmap_sections(glyphToUnicode, &subset, &buffer, true, 8, 0x00FF);
 
     char expectedResultChop1[] =
 "2 beginbfchar\n\
@@ -114,7 +115,7 @@
     // Remove characters from range to downdrade it to one char.
     buffer.reset();
 
-    append_cmap_sections(glyphToUnicode, &subset, &buffer, 0x00D, 0x00FE);
+    append_cmap_sections(glyphToUnicode, &subset, &buffer, true, 0x00D, 0x00FE);
 
     char expectedResultChop2[] =
 "2 beginbfchar\n\
@@ -125,6 +126,23 @@
     REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedResultChop2,
                                             buffer.getOffset()));
 
+    buffer.reset();
+
+    append_cmap_sections(glyphToUnicode, NULL, &buffer, false, 0xFC, 0x110);
+
+    char expectedResultSingleBytes[] =
+"2 beginbfchar\n\
+<0001> <0000>\n\
+<0002> <0000>\n\
+endbfchar\n\
+1 beginbfrange\n\
+<0003> <0006> <1010>\n\
+endbfrange\n";
+
+    REPORTER_ASSERT(reporter, stream_equals(buffer, 0,
+                                            expectedResultSingleBytes,
+                                            buffer.getOffset()));
+
     glyphToUnicode.reset();
     glyphsInSubset.reset();
     SkPDFGlyphSet subset2;
@@ -146,7 +164,7 @@
 
     SkDynamicMemoryWStream buffer2;
     subset2.set(glyphsInSubset.begin(), glyphsInSubset.count());
-    append_cmap_sections(glyphToUnicode, &subset2, &buffer2, 0, 0xffff);
+    append_cmap_sections(glyphToUnicode, &subset2, &buffer2, true, 0, 0xffff);
 
     char expectedResult2[] =
 "4 beginbfchar\n\