[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
This commit is contained in:
parent
f3aead2829
commit
1236d8e37c
@ -460,7 +460,7 @@ static void append_bfrange_section(const SkTDArray<BFRange>& bfrange,
|
||||
// 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 @@ static void append_bfrange_section(const SkTDArray<BFRange>& bfrange,
|
||||
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 @@ void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode,
|
||||
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 @@ void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode,
|
||||
currentRangeEntry.fEnd = i;
|
||||
if (rangeEmpty) {
|
||||
currentRangeEntry.fStart = i;
|
||||
currentRangeEntry.fUnicode = glyphToUnicode[i];
|
||||
currentRangeEntry.fUnicode = glyphToUnicode[i + glyphOffset];
|
||||
rangeEmpty = false;
|
||||
}
|
||||
}
|
||||
@ -537,11 +544,16 @@ void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode,
|
||||
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 @@ void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) {
|
||||
}
|
||||
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 @@ bool SkPDFType3Font::populate(int16_t glyphID) {
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
|
@ -28,6 +28,7 @@ static bool stream_equals(const SkDynamicMemoryWStream& stream, size_t offset,
|
||||
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 @@ static void TestToUnicode(skiatest::Reporter* reporter) {
|
||||
|
||||
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 @@ endbfrange\n";
|
||||
// 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 @@ endbfrange\n";
|
||||
// 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 @@ endbfchar\n";
|
||||
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 @@ endbfchar\n";
|
||||
|
||||
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\
|
||||
|
Loading…
Reference in New Issue
Block a user