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
This commit is contained in:
parent
e3289d39f8
commit
26d2e046cd
@ -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();
|
||||
}
|
||||
|
@ -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\
|
||||
|
Loading…
Reference in New Issue
Block a user