xref: /aosp_15_r20/external/skia/src/pdf/SkPDFMakeToUnicodeCmap.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2011 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFMakeToUnicodeCmap.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkUTF.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFGlyphUse.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFUtils.h"
16*c8dee2aaSAndroid Build Coastguard Worker 
17*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
18*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
19*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
20*c8dee2aaSAndroid Build Coastguard Worker 
21*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
22*c8dee2aaSAndroid Build Coastguard Worker 
append_tounicode_header(SkDynamicMemoryWStream * cmap,bool multibyte)23*c8dee2aaSAndroid Build Coastguard Worker static void append_tounicode_header(SkDynamicMemoryWStream* cmap,
24*c8dee2aaSAndroid Build Coastguard Worker                                     bool multibyte) {
25*c8dee2aaSAndroid Build Coastguard Worker     // 12 dict begin: 12 is an Adobe-suggested value. Shall not change.
26*c8dee2aaSAndroid Build Coastguard Worker     // It's there to prevent old version Adobe Readers from malfunctioning.
27*c8dee2aaSAndroid Build Coastguard Worker     const char* kHeader =
28*c8dee2aaSAndroid Build Coastguard Worker         "/CIDInit /ProcSet findresource begin\n"
29*c8dee2aaSAndroid Build Coastguard Worker         "12 dict begin\n"
30*c8dee2aaSAndroid Build Coastguard Worker         "begincmap\n";
31*c8dee2aaSAndroid Build Coastguard Worker     cmap->writeText(kHeader);
32*c8dee2aaSAndroid Build Coastguard Worker 
33*c8dee2aaSAndroid Build Coastguard Worker     // The /CIDSystemInfo must be consistent to the one in
34*c8dee2aaSAndroid Build Coastguard Worker     // SkPDFFont::populateCIDFont().
35*c8dee2aaSAndroid Build Coastguard Worker     // We can not pass over the system info object here because the format is
36*c8dee2aaSAndroid Build Coastguard Worker     // different. This is not a reference object.
37*c8dee2aaSAndroid Build Coastguard Worker     const char* kSysInfo =
38*c8dee2aaSAndroid Build Coastguard Worker         "/CIDSystemInfo\n"
39*c8dee2aaSAndroid Build Coastguard Worker         "<<  /Registry (Adobe)\n"
40*c8dee2aaSAndroid Build Coastguard Worker         "/Ordering (UCS)\n"
41*c8dee2aaSAndroid Build Coastguard Worker         "/Supplement 0\n"
42*c8dee2aaSAndroid Build Coastguard Worker         ">> def\n";
43*c8dee2aaSAndroid Build Coastguard Worker     cmap->writeText(kSysInfo);
44*c8dee2aaSAndroid Build Coastguard Worker 
45*c8dee2aaSAndroid Build Coastguard Worker     // The CMapName must be consistent to /CIDSystemInfo above.
46*c8dee2aaSAndroid Build Coastguard Worker     // /CMapType 2 means ToUnicode.
47*c8dee2aaSAndroid Build Coastguard Worker     // Codespace range just tells the PDF processor the valid range.
48*c8dee2aaSAndroid Build Coastguard Worker     const char* kTypeInfoHeader =
49*c8dee2aaSAndroid Build Coastguard Worker         "/CMapName /Adobe-Identity-UCS def\n"
50*c8dee2aaSAndroid Build Coastguard Worker         "/CMapType 2 def\n"
51*c8dee2aaSAndroid Build Coastguard Worker         "1 begincodespacerange\n";
52*c8dee2aaSAndroid Build Coastguard Worker     cmap->writeText(kTypeInfoHeader);
53*c8dee2aaSAndroid Build Coastguard Worker     if (multibyte) {
54*c8dee2aaSAndroid Build Coastguard Worker         cmap->writeText("<0000> <FFFF>\n");
55*c8dee2aaSAndroid Build Coastguard Worker     } else {
56*c8dee2aaSAndroid Build Coastguard Worker         cmap->writeText("<00> <FF>\n");
57*c8dee2aaSAndroid Build Coastguard Worker     }
58*c8dee2aaSAndroid Build Coastguard Worker     cmap->writeText("endcodespacerange\n");
59*c8dee2aaSAndroid Build Coastguard Worker }
60*c8dee2aaSAndroid Build Coastguard Worker 
append_cmap_footer(SkDynamicMemoryWStream * cmap)61*c8dee2aaSAndroid Build Coastguard Worker static void append_cmap_footer(SkDynamicMemoryWStream* cmap) {
62*c8dee2aaSAndroid Build Coastguard Worker     const char kFooter[] =
63*c8dee2aaSAndroid Build Coastguard Worker         "endcmap\n"
64*c8dee2aaSAndroid Build Coastguard Worker         "CMapName currentdict /CMap defineresource pop\n"
65*c8dee2aaSAndroid Build Coastguard Worker         "end\n"
66*c8dee2aaSAndroid Build Coastguard Worker         "end";
67*c8dee2aaSAndroid Build Coastguard Worker     cmap->writeText(kFooter);
68*c8dee2aaSAndroid Build Coastguard Worker }
69*c8dee2aaSAndroid Build Coastguard Worker 
70*c8dee2aaSAndroid Build Coastguard Worker namespace {
71*c8dee2aaSAndroid Build Coastguard Worker struct BFChar {
72*c8dee2aaSAndroid Build Coastguard Worker     SkGlyphID fGlyphId;
73*c8dee2aaSAndroid Build Coastguard Worker     SkUnichar fUnicode;
74*c8dee2aaSAndroid Build Coastguard Worker };
75*c8dee2aaSAndroid Build Coastguard Worker 
76*c8dee2aaSAndroid Build Coastguard Worker struct BFRange {
77*c8dee2aaSAndroid Build Coastguard Worker     SkGlyphID fStart;
78*c8dee2aaSAndroid Build Coastguard Worker     SkGlyphID fEnd;
79*c8dee2aaSAndroid Build Coastguard Worker     SkUnichar fUnicode;
80*c8dee2aaSAndroid Build Coastguard Worker };
81*c8dee2aaSAndroid Build Coastguard Worker }  // namespace
82*c8dee2aaSAndroid Build Coastguard Worker 
write_glyph(SkDynamicMemoryWStream * cmap,bool multiByte,SkGlyphID gid)83*c8dee2aaSAndroid Build Coastguard Worker static void write_glyph(SkDynamicMemoryWStream* cmap,
84*c8dee2aaSAndroid Build Coastguard Worker                         bool multiByte,
85*c8dee2aaSAndroid Build Coastguard Worker                         SkGlyphID gid) {
86*c8dee2aaSAndroid Build Coastguard Worker     if (multiByte) {
87*c8dee2aaSAndroid Build Coastguard Worker         SkPDFUtils::WriteUInt16BE(cmap, gid);
88*c8dee2aaSAndroid Build Coastguard Worker     } else {
89*c8dee2aaSAndroid Build Coastguard Worker         SkPDFUtils::WriteUInt8(cmap, SkToU8(gid));
90*c8dee2aaSAndroid Build Coastguard Worker     }
91*c8dee2aaSAndroid Build Coastguard Worker }
92*c8dee2aaSAndroid Build Coastguard Worker 
append_bfchar_section(const std::vector<BFChar> & bfchar,bool multiByte,SkDynamicMemoryWStream * cmap)93*c8dee2aaSAndroid Build Coastguard Worker static void append_bfchar_section(const std::vector<BFChar>& bfchar,
94*c8dee2aaSAndroid Build Coastguard Worker                                   bool multiByte,
95*c8dee2aaSAndroid Build Coastguard Worker                                   SkDynamicMemoryWStream* cmap) {
96*c8dee2aaSAndroid Build Coastguard Worker     // PDF spec defines that every bf* list can have at most 100 entries.
97*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < bfchar.size(); i += 100) {
98*c8dee2aaSAndroid Build Coastguard Worker         int count = SkToInt(bfchar.size() - i);
99*c8dee2aaSAndroid Build Coastguard Worker         count = std::min(count, 100);
100*c8dee2aaSAndroid Build Coastguard Worker         cmap->writeDecAsText(count);
101*c8dee2aaSAndroid Build Coastguard Worker         cmap->writeText(" beginbfchar\n");
102*c8dee2aaSAndroid Build Coastguard Worker         for (int j = 0; j < count; ++j) {
103*c8dee2aaSAndroid Build Coastguard Worker             cmap->writeText("<");
104*c8dee2aaSAndroid Build Coastguard Worker             write_glyph(cmap, multiByte, bfchar[i + j].fGlyphId);
105*c8dee2aaSAndroid Build Coastguard Worker             cmap->writeText("> <");
106*c8dee2aaSAndroid Build Coastguard Worker             SkPDFUtils::WriteUTF16beHex(cmap, bfchar[i + j].fUnicode);
107*c8dee2aaSAndroid Build Coastguard Worker             cmap->writeText(">\n");
108*c8dee2aaSAndroid Build Coastguard Worker         }
109*c8dee2aaSAndroid Build Coastguard Worker         cmap->writeText("endbfchar\n");
110*c8dee2aaSAndroid Build Coastguard Worker     }
111*c8dee2aaSAndroid Build Coastguard Worker }
112*c8dee2aaSAndroid Build Coastguard Worker 
append_bfchar_section_ex(const THashMap<SkGlyphID,SkString> & glyphToUnicodeEx,bool multiByte,SkGlyphID firstGlyphID,SkGlyphID lastGlyphID,SkDynamicMemoryWStream * cmap)113*c8dee2aaSAndroid Build Coastguard Worker static void append_bfchar_section_ex(const THashMap<SkGlyphID, SkString>& glyphToUnicodeEx,
114*c8dee2aaSAndroid Build Coastguard Worker                                      bool multiByte, SkGlyphID firstGlyphID, SkGlyphID lastGlyphID,
115*c8dee2aaSAndroid Build Coastguard Worker                                      SkDynamicMemoryWStream* cmap) {
116*c8dee2aaSAndroid Build Coastguard Worker     size_t glyphCount = 0;
117*c8dee2aaSAndroid Build Coastguard Worker     glyphToUnicodeEx.foreach([&](const SkGlyphID& glyphId, const SkString& a) {
118*c8dee2aaSAndroid Build Coastguard Worker         if (glyphId < firstGlyphID || lastGlyphID < glyphId) {
119*c8dee2aaSAndroid Build Coastguard Worker             return;
120*c8dee2aaSAndroid Build Coastguard Worker         }
121*c8dee2aaSAndroid Build Coastguard Worker         ++glyphCount;
122*c8dee2aaSAndroid Build Coastguard Worker     });
123*c8dee2aaSAndroid Build Coastguard Worker 
124*c8dee2aaSAndroid Build Coastguard Worker     int glyphOffset = 0;
125*c8dee2aaSAndroid Build Coastguard Worker     if (!multiByte) {
126*c8dee2aaSAndroid Build Coastguard Worker         glyphOffset = firstGlyphID - 1;
127*c8dee2aaSAndroid Build Coastguard Worker     }
128*c8dee2aaSAndroid Build Coastguard Worker     // PDF spec defines that every bf* list can have at most 100 entries.
129*c8dee2aaSAndroid Build Coastguard Worker     size_t i = 0;
130*c8dee2aaSAndroid Build Coastguard Worker     glyphToUnicodeEx.foreach([&](const SkGlyphID& glyphId, const SkString& a) {
131*c8dee2aaSAndroid Build Coastguard Worker         if (glyphId < firstGlyphID || lastGlyphID < glyphId) {
132*c8dee2aaSAndroid Build Coastguard Worker             return;
133*c8dee2aaSAndroid Build Coastguard Worker         }
134*c8dee2aaSAndroid Build Coastguard Worker         if (i % 100 == 0) {
135*c8dee2aaSAndroid Build Coastguard Worker             size_t count = glyphCount - i;
136*c8dee2aaSAndroid Build Coastguard Worker             count = std::min(count, SkToSizeT(100));
137*c8dee2aaSAndroid Build Coastguard Worker             cmap->writeDecAsText(count);
138*c8dee2aaSAndroid Build Coastguard Worker             cmap->writeText(" beginbfchar\n");
139*c8dee2aaSAndroid Build Coastguard Worker         }
140*c8dee2aaSAndroid Build Coastguard Worker 
141*c8dee2aaSAndroid Build Coastguard Worker         cmap->writeText("<");
142*c8dee2aaSAndroid Build Coastguard Worker         write_glyph(cmap, multiByte, glyphId - glyphOffset);
143*c8dee2aaSAndroid Build Coastguard Worker         cmap->writeText("> <");
144*c8dee2aaSAndroid Build Coastguard Worker         const char* textPtr = a.begin();
145*c8dee2aaSAndroid Build Coastguard Worker         const char* textEnd = a.end();
146*c8dee2aaSAndroid Build Coastguard Worker         while (textPtr < textEnd) {
147*c8dee2aaSAndroid Build Coastguard Worker             SkUnichar unichar = SkUTF::NextUTF8(&textPtr, textEnd);
148*c8dee2aaSAndroid Build Coastguard Worker             SkPDFUtils::WriteUTF16beHex(cmap, unichar);
149*c8dee2aaSAndroid Build Coastguard Worker         }
150*c8dee2aaSAndroid Build Coastguard Worker         cmap->writeText(">\n");
151*c8dee2aaSAndroid Build Coastguard Worker 
152*c8dee2aaSAndroid Build Coastguard Worker         if (i % 100 == 99 || i == glyphCount - 1) {
153*c8dee2aaSAndroid Build Coastguard Worker             cmap->writeText("endbfchar\n");
154*c8dee2aaSAndroid Build Coastguard Worker         }
155*c8dee2aaSAndroid Build Coastguard Worker         ++i;
156*c8dee2aaSAndroid Build Coastguard Worker     });
157*c8dee2aaSAndroid Build Coastguard Worker }
158*c8dee2aaSAndroid Build Coastguard Worker 
append_bfrange_section(const std::vector<BFRange> & bfrange,bool multiByte,SkDynamicMemoryWStream * cmap)159*c8dee2aaSAndroid Build Coastguard Worker static void append_bfrange_section(const std::vector<BFRange>& bfrange,
160*c8dee2aaSAndroid Build Coastguard Worker                                    bool multiByte,
161*c8dee2aaSAndroid Build Coastguard Worker                                    SkDynamicMemoryWStream* cmap) {
162*c8dee2aaSAndroid Build Coastguard Worker     // PDF spec defines that every bf* list can have at most 100 entries.
163*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < bfrange.size(); i += 100) {
164*c8dee2aaSAndroid Build Coastguard Worker         int count = SkToInt(bfrange.size() - i);
165*c8dee2aaSAndroid Build Coastguard Worker         count = std::min(count, 100);
166*c8dee2aaSAndroid Build Coastguard Worker         cmap->writeDecAsText(count);
167*c8dee2aaSAndroid Build Coastguard Worker         cmap->writeText(" beginbfrange\n");
168*c8dee2aaSAndroid Build Coastguard Worker         for (int j = 0; j < count; ++j) {
169*c8dee2aaSAndroid Build Coastguard Worker             cmap->writeText("<");
170*c8dee2aaSAndroid Build Coastguard Worker             write_glyph(cmap, multiByte, bfrange[i + j].fStart);
171*c8dee2aaSAndroid Build Coastguard Worker             cmap->writeText("> <");
172*c8dee2aaSAndroid Build Coastguard Worker             write_glyph(cmap, multiByte, bfrange[i + j].fEnd);
173*c8dee2aaSAndroid Build Coastguard Worker             cmap->writeText("> <");
174*c8dee2aaSAndroid Build Coastguard Worker             SkPDFUtils::WriteUTF16beHex(cmap, bfrange[i + j].fUnicode);
175*c8dee2aaSAndroid Build Coastguard Worker             cmap->writeText(">\n");
176*c8dee2aaSAndroid Build Coastguard Worker         }
177*c8dee2aaSAndroid Build Coastguard Worker         cmap->writeText("endbfrange\n");
178*c8dee2aaSAndroid Build Coastguard Worker     }
179*c8dee2aaSAndroid Build Coastguard Worker }
180*c8dee2aaSAndroid Build Coastguard Worker 
181*c8dee2aaSAndroid Build Coastguard Worker // Generate <bfchar> and <bfrange> table according to PDF spec 1.4 and Adobe
182*c8dee2aaSAndroid Build Coastguard Worker // Technote 5014.
183*c8dee2aaSAndroid Build Coastguard Worker // The function is not static so we can test it in unit tests.
184*c8dee2aaSAndroid Build Coastguard Worker //
185*c8dee2aaSAndroid Build Coastguard Worker // Current implementation guarantees bfchar and bfrange entries do not overlap.
186*c8dee2aaSAndroid Build Coastguard Worker //
187*c8dee2aaSAndroid Build Coastguard Worker // Current implementation does not attempt aggressive optimizations against
188*c8dee2aaSAndroid Build Coastguard Worker // following case because the specification is not clear.
189*c8dee2aaSAndroid Build Coastguard Worker //
190*c8dee2aaSAndroid Build Coastguard Worker // 4 beginbfchar          1 beginbfchar
191*c8dee2aaSAndroid Build Coastguard Worker // <0003> <0013>          <0020> <0014>
192*c8dee2aaSAndroid Build Coastguard Worker // <0005> <0015>    to    endbfchar
193*c8dee2aaSAndroid Build Coastguard Worker // <0007> <0017>          1 beginbfrange
194*c8dee2aaSAndroid Build Coastguard Worker // <0020> <0014>          <0003> <0007> <0013>
195*c8dee2aaSAndroid Build Coastguard Worker // endbfchar              endbfrange
196*c8dee2aaSAndroid Build Coastguard Worker //
197*c8dee2aaSAndroid Build Coastguard Worker // Adobe Technote 5014 said: "Code mappings (unlike codespace ranges) may
198*c8dee2aaSAndroid Build Coastguard Worker // overlap, but succeeding maps supersede preceding maps."
199*c8dee2aaSAndroid Build Coastguard Worker //
200*c8dee2aaSAndroid Build Coastguard Worker // In case of searching text in PDF, bfrange will have higher precedence so
201*c8dee2aaSAndroid Build Coastguard Worker // typing char id 0x0014 in search box will get glyph id 0x0004 first.  However,
202*c8dee2aaSAndroid Build Coastguard Worker // the spec does not mention how will this kind of conflict being resolved.
203*c8dee2aaSAndroid Build Coastguard Worker //
204*c8dee2aaSAndroid Build Coastguard Worker // For the worst case (having 65536 continuous unicode and we use every other
205*c8dee2aaSAndroid Build Coastguard Worker // one of them), the possible savings by aggressive optimization is 416KB
206*c8dee2aaSAndroid Build Coastguard Worker // pre-compressed and does not provide enough motivation for implementation.
SkPDFAppendCmapSections(const SkUnichar * glyphToUnicode,const THashMap<SkGlyphID,SkString> & glyphToUnicodeEx,const SkPDFGlyphUse * subset,SkDynamicMemoryWStream * cmap,bool multiByteGlyphs,SkGlyphID firstGlyphID,SkGlyphID lastGlyphID)207*c8dee2aaSAndroid Build Coastguard Worker void SkPDFAppendCmapSections(const SkUnichar* glyphToUnicode,
208*c8dee2aaSAndroid Build Coastguard Worker                              const THashMap<SkGlyphID, SkString>& glyphToUnicodeEx,
209*c8dee2aaSAndroid Build Coastguard Worker                              const SkPDFGlyphUse* subset,
210*c8dee2aaSAndroid Build Coastguard Worker                              SkDynamicMemoryWStream* cmap,
211*c8dee2aaSAndroid Build Coastguard Worker                              bool multiByteGlyphs,
212*c8dee2aaSAndroid Build Coastguard Worker                              SkGlyphID firstGlyphID,
213*c8dee2aaSAndroid Build Coastguard Worker                              SkGlyphID lastGlyphID) {
214*c8dee2aaSAndroid Build Coastguard Worker     int glyphOffset = 0;
215*c8dee2aaSAndroid Build Coastguard Worker     if (!multiByteGlyphs) {
216*c8dee2aaSAndroid Build Coastguard Worker         glyphOffset = firstGlyphID - 1;
217*c8dee2aaSAndroid Build Coastguard Worker     }
218*c8dee2aaSAndroid Build Coastguard Worker 
219*c8dee2aaSAndroid Build Coastguard Worker     std::vector<BFChar> bfcharEntries;
220*c8dee2aaSAndroid Build Coastguard Worker     std::vector<BFRange> bfrangeEntries;
221*c8dee2aaSAndroid Build Coastguard Worker 
222*c8dee2aaSAndroid Build Coastguard Worker     BFRange currentRangeEntry = {0, 0, 0};
223*c8dee2aaSAndroid Build Coastguard Worker     bool rangeEmpty = true;
224*c8dee2aaSAndroid Build Coastguard Worker     const int limit = (int)lastGlyphID + 1 - glyphOffset;
225*c8dee2aaSAndroid Build Coastguard Worker 
226*c8dee2aaSAndroid Build Coastguard Worker     for (int i = firstGlyphID - glyphOffset; i < limit + 1; ++i) {
227*c8dee2aaSAndroid Build Coastguard Worker         SkGlyphID gid = i + glyphOffset;
228*c8dee2aaSAndroid Build Coastguard Worker         bool inSubset = i < limit && (subset == nullptr || subset->has(gid));
229*c8dee2aaSAndroid Build Coastguard Worker         if (!rangeEmpty) {
230*c8dee2aaSAndroid Build Coastguard Worker             // PDF spec requires bfrange not changing the higher byte,
231*c8dee2aaSAndroid Build Coastguard Worker             // e.g. <1035> <10FF> <2222> is ok, but
232*c8dee2aaSAndroid Build Coastguard Worker             //      <1035> <1100> <2222> is no good
233*c8dee2aaSAndroid Build Coastguard Worker             bool inRange =
234*c8dee2aaSAndroid Build Coastguard Worker                 i == currentRangeEntry.fEnd + 1 &&
235*c8dee2aaSAndroid Build Coastguard Worker                 i >> 8 == currentRangeEntry.fStart >> 8 &&
236*c8dee2aaSAndroid Build Coastguard Worker                 i < limit &&
237*c8dee2aaSAndroid Build Coastguard Worker                 glyphToUnicode[gid] ==
238*c8dee2aaSAndroid Build Coastguard Worker                     currentRangeEntry.fUnicode + i - currentRangeEntry.fStart;
239*c8dee2aaSAndroid Build Coastguard Worker             if (!inSubset || !inRange) {
240*c8dee2aaSAndroid Build Coastguard Worker                 if (currentRangeEntry.fEnd > currentRangeEntry.fStart) {
241*c8dee2aaSAndroid Build Coastguard Worker                     bfrangeEntries.push_back(currentRangeEntry);
242*c8dee2aaSAndroid Build Coastguard Worker                 } else {
243*c8dee2aaSAndroid Build Coastguard Worker                     bfcharEntries.push_back({currentRangeEntry.fStart, currentRangeEntry.fUnicode});
244*c8dee2aaSAndroid Build Coastguard Worker                 }
245*c8dee2aaSAndroid Build Coastguard Worker                 rangeEmpty = true;
246*c8dee2aaSAndroid Build Coastguard Worker             }
247*c8dee2aaSAndroid Build Coastguard Worker         }
248*c8dee2aaSAndroid Build Coastguard Worker         if (inSubset) {
249*c8dee2aaSAndroid Build Coastguard Worker             currentRangeEntry.fEnd = i;
250*c8dee2aaSAndroid Build Coastguard Worker             if (rangeEmpty) {
251*c8dee2aaSAndroid Build Coastguard Worker               currentRangeEntry.fStart = i;
252*c8dee2aaSAndroid Build Coastguard Worker               currentRangeEntry.fUnicode = glyphToUnicode[gid];
253*c8dee2aaSAndroid Build Coastguard Worker               rangeEmpty = false;
254*c8dee2aaSAndroid Build Coastguard Worker             }
255*c8dee2aaSAndroid Build Coastguard Worker         }
256*c8dee2aaSAndroid Build Coastguard Worker     }
257*c8dee2aaSAndroid Build Coastguard Worker 
258*c8dee2aaSAndroid Build Coastguard Worker     // The spec requires all bfchar entries for a font must come before bfrange
259*c8dee2aaSAndroid Build Coastguard Worker     // entries.
260*c8dee2aaSAndroid Build Coastguard Worker     append_bfchar_section(bfcharEntries, multiByteGlyphs, cmap);
261*c8dee2aaSAndroid Build Coastguard Worker     append_bfchar_section_ex(glyphToUnicodeEx, multiByteGlyphs, firstGlyphID, lastGlyphID, cmap);
262*c8dee2aaSAndroid Build Coastguard Worker     append_bfrange_section(bfrangeEntries, multiByteGlyphs, cmap);
263*c8dee2aaSAndroid Build Coastguard Worker }
264*c8dee2aaSAndroid Build Coastguard Worker 
SkPDFMakeToUnicodeCmap(const SkUnichar * glyphToUnicode,const THashMap<SkGlyphID,SkString> & glyphToUnicodeEx,const SkPDFGlyphUse * subset,bool multiByteGlyphs,SkGlyphID firstGlyphID,SkGlyphID lastGlyphID)265*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkStreamAsset> SkPDFMakeToUnicodeCmap(
266*c8dee2aaSAndroid Build Coastguard Worker         const SkUnichar* glyphToUnicode,
267*c8dee2aaSAndroid Build Coastguard Worker         const THashMap<SkGlyphID, SkString>& glyphToUnicodeEx,
268*c8dee2aaSAndroid Build Coastguard Worker         const SkPDFGlyphUse* subset,
269*c8dee2aaSAndroid Build Coastguard Worker         bool multiByteGlyphs,
270*c8dee2aaSAndroid Build Coastguard Worker         SkGlyphID firstGlyphID,
271*c8dee2aaSAndroid Build Coastguard Worker         SkGlyphID lastGlyphID) {
272*c8dee2aaSAndroid Build Coastguard Worker     SkDynamicMemoryWStream cmap;
273*c8dee2aaSAndroid Build Coastguard Worker     append_tounicode_header(&cmap, multiByteGlyphs);
274*c8dee2aaSAndroid Build Coastguard Worker     SkPDFAppendCmapSections(glyphToUnicode, glyphToUnicodeEx, subset, &cmap, multiByteGlyphs,
275*c8dee2aaSAndroid Build Coastguard Worker                             firstGlyphID, lastGlyphID);
276*c8dee2aaSAndroid Build Coastguard Worker     append_cmap_footer(&cmap);
277*c8dee2aaSAndroid Build Coastguard Worker     return cmap.detachAsStream();
278*c8dee2aaSAndroid Build Coastguard Worker }
279