diff options
-rw-r--r-- | src/pdf/SkPDFFont.cpp | 54 | ||||
-rw-r--r-- | tests/ToUnicode.cpp | 46 |
2 files changed, 75 insertions, 25 deletions
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp index 7d8c286e2e..4184e87f05 100644 --- a/src/pdf/SkPDFFont.cpp +++ b/src/pdf/SkPDFFont.cpp @@ -342,7 +342,9 @@ SkPDFArray* composeAdvanceData( } // 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 @@ static void append_tounicode_header(SkDynamicMemoryWStream* cmap) { // 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 @@ static void append_bfrange_section(const SkTDArray<BFRange>& bfrange, // ( 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 @@ void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode, 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 @@ void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode, 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 @@ void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode, 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 @@ void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) { 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(); } diff --git a/tests/ToUnicode.cpp b/tests/ToUnicode.cpp index ea9e258ac3..69ec614bcf 100644 --- a/tests/ToUnicode.cpp +++ b/tests/ToUnicode.cpp @@ -27,7 +27,9 @@ static bool stream_equals(const SkDynamicMemoryWStream& stream, size_t offset, void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode, const SkPDFGlyphSet* subset, - SkDynamicMemoryWStream* cmap); + SkDynamicMemoryWStream* cmap, + uint16_t firstGlypthID, + uint16_t lastGlypthID); static void TestToUnicode(skiatest::Reporter* reporter) { SkTDArray<SkUnichar> glyphToUnicode; @@ -56,7 +58,9 @@ static void TestToUnicode(skiatest::Reporter* reporter) { glyphToUnicode.push(0x35); // 11 glyphsInSubset.push(12); glyphToUnicode.push(0x36); // 12 - for (uint16_t i = 13; i < 0xFE; ++i) { + glyphsInSubset.push(13); + glyphToUnicode.push(0x37); // 13 + for (uint16_t i = 14; i < 0xFE; ++i) { glyphToUnicode.push(0); // Zero from index 0x9 to 0xFD } glyphsInSubset.push(0xFE); @@ -70,7 +74,7 @@ static void TestToUnicode(skiatest::Reporter* reporter) { SkDynamicMemoryWStream buffer; subset.set(glyphsInSubset.begin(), glyphsInSubset.count()); - append_cmap_sections(glyphToUnicode, &subset, &buffer); + append_cmap_sections(glyphToUnicode, &subset, &buffer, 0, 0xFFFF); char expectedResult[] = "4 beginbfchar\n\ @@ -81,7 +85,7 @@ static void TestToUnicode(skiatest::Reporter* reporter) { endbfchar\n\ 4 beginbfrange\n\ <0005> <0007> <0027>\n\ -<000B> <000C> <0035>\n\ +<000B> <000D> <0035>\n\ <00FE> <00FF> <1010>\n\ <0100> <0101> <1012>\n\ endbfrange\n"; @@ -89,6 +93,38 @@ endbfrange\n"; REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedResult, buffer.getOffset())); + // Remove characters and ranges. + buffer.reset(); + + append_cmap_sections(glyphToUnicode, &subset, &buffer, 8, 0x00FF); + + char expectedResultChop1[] = +"2 beginbfchar\n\ +<0008> <002F>\n\ +<0009> <0033>\n\ +endbfchar\n\ +2 beginbfrange\n\ +<000B> <000D> <0035>\n\ +<00FE> <00FF> <1010>\n\ +endbfrange\n"; + + REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedResultChop1, + buffer.getOffset())); + + // Remove characters from range to downdrade it to one char. + buffer.reset(); + + append_cmap_sections(glyphToUnicode, &subset, &buffer, 0x00D, 0x00FE); + + char expectedResultChop2[] = +"2 beginbfchar\n\ +<000D> <0037>\n\ +<00FE> <1010>\n\ +endbfchar\n"; + + REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedResultChop2, + buffer.getOffset())); + glyphToUnicode.reset(); glyphsInSubset.reset(); SkPDFGlyphSet subset2; @@ -110,7 +146,7 @@ endbfrange\n"; SkDynamicMemoryWStream buffer2; subset2.set(glyphsInSubset.begin(), glyphsInSubset.count()); - append_cmap_sections(glyphToUnicode, &subset2, &buffer2); + append_cmap_sections(glyphToUnicode, &subset2, &buffer2, 0, 0xffff); char expectedResult2[] = "4 beginbfchar\n\ |