aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/pdf/SkPDFFont.cpp54
-rw-r--r--tests/ToUnicode.cpp46
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\