Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(448)

Side by Side Diff: src/pdf/SkPDFMakeToUnicodeCmap.cpp

Issue 2292303004: SkPDF: Fix Type3 ToUnicode table. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkPDFMakeToUnicodeCmap.h" 8 #include "SkPDFMakeToUnicodeCmap.h"
9 #include "SkPDFUtils.h" 9 #include "SkPDFUtils.h"
10 #include "SkUtils.h" 10 #include "SkUtils.h"
11 11
12 static void append_tounicode_header(SkDynamicMemoryWStream* cmap, 12 static void append_tounicode_header(SkDynamicMemoryWStream* cmap,
13 SkGlyphID firstGlyphID, 13 bool multibyte) {
14 SkGlyphID lastGlyphID) {
15 // 12 dict begin: 12 is an Adobe-suggested value. Shall not change. 14 // 12 dict begin: 12 is an Adobe-suggested value. Shall not change.
16 // It's there to prevent old version Adobe Readers from malfunctioning. 15 // It's there to prevent old version Adobe Readers from malfunctioning.
17 const char* kHeader = 16 const char* kHeader =
18 "/CIDInit /ProcSet findresource begin\n" 17 "/CIDInit /ProcSet findresource begin\n"
19 "12 dict begin\n" 18 "12 dict begin\n"
20 "begincmap\n"; 19 "begincmap\n";
21 cmap->writeText(kHeader); 20 cmap->writeText(kHeader);
22 21
23 // The /CIDSystemInfo must be consistent to the one in 22 // The /CIDSystemInfo must be consistent to the one in
24 // SkPDFFont::populateCIDFont(). 23 // SkPDFFont::populateCIDFont().
25 // We can not pass over the system info object here because the format is 24 // We can not pass over the system info object here because the format is
26 // different. This is not a reference object. 25 // different. This is not a reference object.
27 const char* kSysInfo = 26 const char* kSysInfo =
28 "/CIDSystemInfo\n" 27 "/CIDSystemInfo\n"
29 "<< /Registry (Adobe)\n" 28 "<< /Registry (Skia)\n"
30 "/Ordering (UCS)\n" 29 "/Ordering (SkiaOrdering)\n"
Rik 2016/09/01 17:41:21 Please leave this as-is
31 "/Supplement 0\n" 30 "/Supplement 0\n"
32 ">> def\n"; 31 ">> def\n";
33 cmap->writeText(kSysInfo); 32 cmap->writeText(kSysInfo);
34 33
35 // The CMapName must be consistent to /CIDSystemInfo above. 34 // The CMapName must be consistent to /CIDSystemInfo above.
36 // /CMapType 2 means ToUnicode. 35 // /CMapType 2 means ToUnicode.
37 // Codespace range just tells the PDF processor the valid range. 36 // Codespace range just tells the PDF processor the valid range.
38 const char* kTypeInfoHeader = 37 const char* kTypeInfoHeader =
39 "/CMapName /Adobe-Identity-UCS def\n" 38 "/CMapName /Skia-Identity-SkiaOrdering def\n"
40 "/CMapType 2 def\n" 39 "/CMapType 2 def\n"
41 "1 begincodespacerange\n"; 40 "1 begincodespacerange\n";
42 cmap->writeText(kTypeInfoHeader); 41 cmap->writeText(kTypeInfoHeader);
43 42 if (multibyte) {
44 // e.g. "<0000> <FFFF>\n" 43 cmap->writeText("<0000> <FFFF>\n");
45 SkString range; 44 } else {
46 range.appendf("<%04X> <%04X>\n", firstGlyphID, lastGlyphID); 45 cmap->writeText("<00> <FF>\n");
47 cmap->writeText(range.c_str()); 46 }
48 47 cmap->writeText("endcodespacerange\n");
49 const char* kTypeInfoFooter = "endcodespacerange\n";
50 cmap->writeText(kTypeInfoFooter);
51 } 48 }
52 49
53 static void append_cmap_footer(SkDynamicMemoryWStream* cmap) { 50 static void append_cmap_footer(SkDynamicMemoryWStream* cmap) {
54 const char kFooter[] = 51 const char kFooter[] =
55 "endcmap\n" 52 "endcmap\n"
56 "CMapName currentdict /CMap defineresource pop\n" 53 "CMapName currentdict /CMap defineresource pop\n"
57 "end\n" 54 "end\n"
58 "end"; 55 "end";
59 cmap->writeText(kFooter); 56 cmap->writeText(kFooter);
60 } 57 }
(...skipping 14 matching lines...) Expand all
75 static void write_utf16be(SkDynamicMemoryWStream* wStream, SkUnichar utf32) { 72 static void write_utf16be(SkDynamicMemoryWStream* wStream, SkUnichar utf32) {
76 SkGlyphID utf16[2] = {0, 0}; 73 SkGlyphID utf16[2] = {0, 0};
77 size_t len = SkUTF16_FromUnichar(utf32, utf16); 74 size_t len = SkUTF16_FromUnichar(utf32, utf16);
78 SkASSERT(len == 1 || len == 2); 75 SkASSERT(len == 1 || len == 2);
79 SkPDFUtils::WriteUInt16BE(wStream, utf16[0]); 76 SkPDFUtils::WriteUInt16BE(wStream, utf16[0]);
80 if (len == 2) { 77 if (len == 2) {
81 SkPDFUtils::WriteUInt16BE(wStream, utf16[1]); 78 SkPDFUtils::WriteUInt16BE(wStream, utf16[1]);
82 } 79 }
83 } 80 }
84 81
82 static void write_glyph(SkDynamicMemoryWStream* cmap,
83 bool multiByte,
84 SkGlyphID gid) {
85 if (multiByte) {
86 SkPDFUtils::WriteUInt16BE(cmap, gid);
87 } else {
88 SkPDFUtils::WriteUInt8(cmap, SkToU8(gid));
89 }
90 }
91
85 static void append_bfchar_section(const SkTDArray<BFChar>& bfchar, 92 static void append_bfchar_section(const SkTDArray<BFChar>& bfchar,
93 bool multiByte,
86 SkDynamicMemoryWStream* cmap) { 94 SkDynamicMemoryWStream* cmap) {
87 // PDF spec defines that every bf* list can have at most 100 entries. 95 // PDF spec defines that every bf* list can have at most 100 entries.
88 for (int i = 0; i < bfchar.count(); i += 100) { 96 for (int i = 0; i < bfchar.count(); i += 100) {
89 int count = bfchar.count() - i; 97 int count = bfchar.count() - i;
90 count = SkMin32(count, 100); 98 count = SkMin32(count, 100);
91 cmap->writeDecAsText(count); 99 cmap->writeDecAsText(count);
92 cmap->writeText(" beginbfchar\n"); 100 cmap->writeText(" beginbfchar\n");
93 for (int j = 0; j < count; ++j) { 101 for (int j = 0; j < count; ++j) {
94 cmap->writeText("<"); 102 cmap->writeText("<");
95 SkPDFUtils::WriteUInt16BE(cmap, bfchar[i + j].fGlyphId); 103 write_glyph(cmap, multiByte, bfchar[i + j].fGlyphId);
96 cmap->writeText("> <"); 104 cmap->writeText("> <");
97 write_utf16be(cmap, bfchar[i + j].fUnicode); 105 write_utf16be(cmap, bfchar[i + j].fUnicode);
98 cmap->writeText(">\n"); 106 cmap->writeText(">\n");
99 } 107 }
100 cmap->writeText("endbfchar\n"); 108 cmap->writeText("endbfchar\n");
101 } 109 }
102 } 110 }
103 111
104 static void append_bfrange_section(const SkTDArray<BFRange>& bfrange, 112 static void append_bfrange_section(const SkTDArray<BFRange>& bfrange,
113 bool multiByte,
105 SkDynamicMemoryWStream* cmap) { 114 SkDynamicMemoryWStream* cmap) {
106 // PDF spec defines that every bf* list can have at most 100 entries. 115 // PDF spec defines that every bf* list can have at most 100 entries.
107 for (int i = 0; i < bfrange.count(); i += 100) { 116 for (int i = 0; i < bfrange.count(); i += 100) {
108 int count = bfrange.count() - i; 117 int count = bfrange.count() - i;
109 count = SkMin32(count, 100); 118 count = SkMin32(count, 100);
110 cmap->writeDecAsText(count); 119 cmap->writeDecAsText(count);
111 cmap->writeText(" beginbfrange\n"); 120 cmap->writeText(" beginbfrange\n");
112 for (int j = 0; j < count; ++j) { 121 for (int j = 0; j < count; ++j) {
113 cmap->writeText("<"); 122 cmap->writeText("<");
114 SkPDFUtils::WriteUInt16BE(cmap, bfrange[i + j].fStart); 123 write_glyph(cmap, multiByte, bfrange[i + j].fStart);
115 cmap->writeText("> <"); 124 cmap->writeText("> <");
116 SkPDFUtils::WriteUInt16BE(cmap, bfrange[i + j].fEnd); 125 write_glyph(cmap, multiByte, bfrange[i + j].fEnd);
117 cmap->writeText("> <"); 126 cmap->writeText("> <");
118 write_utf16be(cmap, bfrange[i + j].fUnicode); 127 write_utf16be(cmap, bfrange[i + j].fUnicode);
119 cmap->writeText(">\n"); 128 cmap->writeText(">\n");
120 } 129 }
121 cmap->writeText("endbfrange\n"); 130 cmap->writeText("endbfrange\n");
122 } 131 }
123 } 132 }
124 133
125 // Generate <bfchar> and <bfrange> table according to PDF spec 1.4 and Adobe 134 // Generate <bfchar> and <bfrange> table according to PDF spec 1.4 and Adobe
126 // Technote 5014. 135 // Technote 5014.
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 if (rangeEmpty) { 208 if (rangeEmpty) {
200 currentRangeEntry.fStart = i; 209 currentRangeEntry.fStart = i;
201 currentRangeEntry.fUnicode = glyphToUnicode[i + glyphOffset]; 210 currentRangeEntry.fUnicode = glyphToUnicode[i + glyphOffset];
202 rangeEmpty = false; 211 rangeEmpty = false;
203 } 212 }
204 } 213 }
205 } 214 }
206 215
207 // The spec requires all bfchar entries for a font must come before bfrange 216 // The spec requires all bfchar entries for a font must come before bfrange
208 // entries. 217 // entries.
209 append_bfchar_section(bfcharEntries, cmap); 218 append_bfchar_section(bfcharEntries, multiByteGlyphs, cmap);
210 append_bfrange_section(bfrangeEntries, cmap); 219 append_bfrange_section(bfrangeEntries, multiByteGlyphs, cmap);
211 } 220 }
212 221
213 sk_sp<SkPDFStream> SkPDFMakeToUnicodeCmap( 222 sk_sp<SkPDFStream> SkPDFMakeToUnicodeCmap(
214 const SkTDArray<SkUnichar>& glyphToUnicode, 223 const SkTDArray<SkUnichar>& glyphToUnicode,
215 const SkBitSet* subset, 224 const SkBitSet* subset,
216 bool multiByteGlyphs, 225 bool multiByteGlyphs,
217 SkGlyphID firstGlyphID, 226 SkGlyphID firstGlyphID,
218 SkGlyphID lastGlyphID) { 227 SkGlyphID lastGlyphID) {
219 SkDynamicMemoryWStream cmap; 228 SkDynamicMemoryWStream cmap;
220 if (multiByteGlyphs) { 229 append_tounicode_header(&cmap, multiByteGlyphs);
221 append_tounicode_header(&cmap, firstGlyphID, lastGlyphID);
222 } else {
223 append_tounicode_header(&cmap, 1, lastGlyphID - firstGlyphID + 1);
224 }
225 SkPDFAppendCmapSections(glyphToUnicode, subset, &cmap, multiByteGlyphs, 230 SkPDFAppendCmapSections(glyphToUnicode, subset, &cmap, multiByteGlyphs,
226 firstGlyphID, lastGlyphID); 231 firstGlyphID, lastGlyphID);
227 append_cmap_footer(&cmap); 232 append_cmap_footer(&cmap);
228 return sk_make_sp<SkPDFStream>( 233 return sk_make_sp<SkPDFStream>(
229 std::unique_ptr<SkStreamAsset>(cmap.detachAsStream())); 234 std::unique_ptr<SkStreamAsset>(cmap.detachAsStream()));
230 } 235 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698