pdf: write only ToUnicode mappings needed by the font, trimming anything out of [firstChar, lastChar] interval.

R=vandebo@chromium.org

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

git-svn-id: http://skia.googlecode.com/svn/trunk@11360 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp
index 7d8c286..4184e87 100644
--- a/src/pdf/SkPDFFont.cpp
+++ b/src/pdf/SkPDFFont.cpp
@@ -342,7 +342,9 @@
 
 }  // namespace
 
-static void append_tounicode_header(SkDynamicMemoryWStream* cmap) {
+static void append_tounicode_header(SkDynamicMemoryWStream* cmap,
+                                    uint16_t firstGlyphID,
+                                    uint16_t lastGlyphID) {
     // 12 dict begin: 12 is an Adobe-suggested value. Shall not change.
     // It's there to prevent old version Adobe Readers from malfunctioning.
     const char* kHeader =
@@ -365,17 +367,20 @@
 
     // The CMapName must be consistent to /CIDSystemInfo above.
     // /CMapType 2 means ToUnicode.
-    // We specify codespacerange from 0x0000 to 0xFFFF because we convert our
-    // code table from unsigned short (16-bits). Codespace range just tells the
-    // PDF processor the valid range. It does not matter whether a complete
-    // mapping is provided or not.
-    const char* kTypeInfo =
+    // Codespace range just tells the PDF processor the valid range.
+    const char* kTypeInfoHeader =
         "/CMapName /Adobe-Identity-UCS def\n"
         "/CMapType 2 def\n"
-        "1 begincodespacerange\n"
-        "<0000> <FFFF>\n"
-        "endcodespacerange\n";
-    cmap->writeText(kTypeInfo);
+        "1 begincodespacerange\n";
+    cmap->writeText(kTypeInfoHeader);
+    
+    // e.g.     "<0000> <FFFF>\n"
+    SkString range;
+    range.appendf("<%04X> <%04X>\n", firstGlyphID, lastGlyphID);
+    cmap->writeText(range.c_str());
+    
+    const char* kTypeInfoFooter = "endcodespacerange\n";
+    cmap->writeText(kTypeInfoFooter);
 }
 
 static void append_cmap_footer(SkDynamicMemoryWStream* cmap) {
@@ -469,11 +474,15 @@
 // ( see caller in tests/ToUnicode.cpp )
 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode,
                           const SkPDFGlyphSet* subset,
-                          SkDynamicMemoryWStream* cmap);
+                          SkDynamicMemoryWStream* cmap,
+                          uint16_t firstGlyphID,
+                          uint16_t lastGlyphID);
 
 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode,
                           const SkPDFGlyphSet* subset,
-                          SkDynamicMemoryWStream* cmap) {
+                          SkDynamicMemoryWStream* cmap,
+                          uint16_t firstGlyphID,
+                          uint16_t lastGlyphID) {
     if (glyphToUnicode.isEmpty()) {
         return;
     }
@@ -483,10 +492,11 @@
 
     BFRange currentRangeEntry = {0, 0, 0};
     bool rangeEmpty = true;
-    const int count = glyphToUnicode.count();
+    const int limit = SkMin32(lastGlyphID + 1, glyphToUnicode.count());
 
-    for (int i = 0; i < count + 1; ++i) {
-        bool inSubset = i < count && (subset == NULL || subset->has(i));
+    for (int i = firstGlyphID; i < limit + 1; ++i) {
+        bool inSubset = i < limit &&
+                        (subset == NULL || subset->has(i));
         if (!rangeEmpty) {
             // PDF spec requires bfrange not changing the higher byte,
             // e.g. <1035> <10FF> <2222> is ok, but
@@ -494,7 +504,7 @@
             bool inRange =
                 i == currentRangeEntry.fEnd + 1 &&
                 i >> 8 == currentRangeEntry.fStart >> 8 &&
-                i < count &&
+                i < limit &&
                 glyphToUnicode[i] == currentRangeEntry.fUnicode + i -
                                          currentRangeEntry.fStart;
             if (!inSubset || !inRange) {
@@ -526,10 +536,13 @@
 
 static SkPDFStream* generate_tounicode_cmap(
         const SkTDArray<SkUnichar>& glyphToUnicode,
-        const SkPDFGlyphSet* subset) {
+        const SkPDFGlyphSet* subset,
+        uint16_t firstGlyphID,
+        uint16_t lastGlyphID) {
     SkDynamicMemoryWStream cmap;
-    append_tounicode_header(&cmap);
-    append_cmap_sections(glyphToUnicode, subset, &cmap);
+    append_tounicode_header(&cmap, firstGlyphID, lastGlyphID);
+    append_cmap_sections(glyphToUnicode, subset, &cmap,
+                         firstGlyphID, lastGlyphID);
     append_cmap_footer(&cmap);
     SkAutoTUnref<SkMemoryStream> cmapStream(new SkMemoryStream());
     cmapStream->setData(cmap.copyToData())->unref();
@@ -1015,7 +1028,8 @@
         return;
     }
     SkAutoTUnref<SkPDFStream> pdfCmap(
-        generate_tounicode_cmap(fFontInfo->fGlyphToUnicode, subset));
+        generate_tounicode_cmap(fFontInfo->fGlyphToUnicode, subset,
+                                firstGlyphID(), lastGlyphID()));
     addResource(pdfCmap.get());
     insert("ToUnicode", new SkPDFObjRef(pdfCmap.get()))->unref();
 }