1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2010 The Android Open Source Project
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 "include/core/SkTypes.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_SUPPORT_PDF
11*c8dee2aaSAndroid Build Coastguard Worker
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTDArray.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFGlyphUse.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFMakeToUnicodeCmap.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
19*c8dee2aaSAndroid Build Coastguard Worker
20*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
21*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
22*c8dee2aaSAndroid Build Coastguard Worker #include <cstring>
23*c8dee2aaSAndroid Build Coastguard Worker
24*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
25*c8dee2aaSAndroid Build Coastguard Worker
26*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkGlyphID kMaximumGlyphIndex = UINT16_MAX;
27*c8dee2aaSAndroid Build Coastguard Worker
stream_equals(const SkDynamicMemoryWStream & stream,const char * buffer)28*c8dee2aaSAndroid Build Coastguard Worker static bool stream_equals(const SkDynamicMemoryWStream& stream, const char* buffer) {
29*c8dee2aaSAndroid Build Coastguard Worker const size_t streamSize = stream.bytesWritten();
30*c8dee2aaSAndroid Build Coastguard Worker AutoTMalloc<char> data(streamSize);
31*c8dee2aaSAndroid Build Coastguard Worker stream.copyTo(data.get());
32*c8dee2aaSAndroid Build Coastguard Worker
33*c8dee2aaSAndroid Build Coastguard Worker if ((false)) {
34*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Output\n%.*s\n", SkToInt(streamSize), data.data());
35*c8dee2aaSAndroid Build Coastguard Worker }
36*c8dee2aaSAndroid Build Coastguard Worker
37*c8dee2aaSAndroid Build Coastguard Worker if (streamSize != strlen(buffer)) {
38*c8dee2aaSAndroid Build Coastguard Worker return false;
39*c8dee2aaSAndroid Build Coastguard Worker }
40*c8dee2aaSAndroid Build Coastguard Worker return memcmp(data.get(), buffer, streamSize) == 0;
41*c8dee2aaSAndroid Build Coastguard Worker }
42*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(SkPDF_ToUnicode,reporter)43*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(SkPDF_ToUnicode, reporter) {
44*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<SkUnichar> glyphToUnicode;
45*c8dee2aaSAndroid Build Coastguard Worker THashMap<SkGlyphID, SkString> glyphToUnicodeEx;
46*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<uint16_t> glyphsInSubset;
47*c8dee2aaSAndroid Build Coastguard Worker SkPDFGlyphUse subset(1, kMaximumGlyphIndex);
48*c8dee2aaSAndroid Build Coastguard Worker
49*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0); // 0
50*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0); // 1
51*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0); // 2
52*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(3);
53*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0x20); // 3
54*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(4);
55*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0x25); // 4
56*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(5);
57*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0x27); // 5
58*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(6);
59*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0x28); // 6
60*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(7);
61*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0x29); // 7
62*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(8);
63*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0x2F); // 8
64*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(9);
65*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0x33); // 9
66*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0); // 10
67*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(11);
68*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0x35); // 11
69*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(12);
70*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0x36); // 12
71*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(13);
72*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0x37); // 13
73*c8dee2aaSAndroid Build Coastguard Worker for (uint16_t i = 14; i < 0xFE; ++i) {
74*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0); // Zero from index 0x9 to 0xFD
75*c8dee2aaSAndroid Build Coastguard Worker }
76*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(0xFE);
77*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0x1010);
78*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(0xFF);
79*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0x1011);
80*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(0x100);
81*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0x1012);
82*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(0x101);
83*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(0x1013);
84*c8dee2aaSAndroid Build Coastguard Worker
85*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicodeEx.set(0x9, SkString("ffi"));
86*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicodeEx.set(0xFC, SkString("st"));
87*c8dee2aaSAndroid Build Coastguard Worker
88*c8dee2aaSAndroid Build Coastguard Worker SkGlyphID lastGlyphID = SkToU16(glyphToUnicode.size() - 1);
89*c8dee2aaSAndroid Build Coastguard Worker
90*c8dee2aaSAndroid Build Coastguard Worker SkDynamicMemoryWStream buffer;
91*c8dee2aaSAndroid Build Coastguard Worker for (uint16_t v : glyphsInSubset) {
92*c8dee2aaSAndroid Build Coastguard Worker subset.set(v);
93*c8dee2aaSAndroid Build Coastguard Worker }
94*c8dee2aaSAndroid Build Coastguard Worker SkPDFAppendCmapSections(glyphToUnicode.data(), glyphToUnicodeEx, &subset, &buffer, true, 0,
95*c8dee2aaSAndroid Build Coastguard Worker std::min<SkGlyphID>(0xFFFF, lastGlyphID));
96*c8dee2aaSAndroid Build Coastguard Worker
97*c8dee2aaSAndroid Build Coastguard Worker char expectedResult[] =
98*c8dee2aaSAndroid Build Coastguard Worker "4 beginbfchar\n\
99*c8dee2aaSAndroid Build Coastguard Worker <0003> <0020>\n\
100*c8dee2aaSAndroid Build Coastguard Worker <0004> <0025>\n\
101*c8dee2aaSAndroid Build Coastguard Worker <0008> <002F>\n\
102*c8dee2aaSAndroid Build Coastguard Worker <0009> <0033>\n\
103*c8dee2aaSAndroid Build Coastguard Worker endbfchar\n\
104*c8dee2aaSAndroid Build Coastguard Worker 2 beginbfchar\n\
105*c8dee2aaSAndroid Build Coastguard Worker <0009> <006600660069>\n\
106*c8dee2aaSAndroid Build Coastguard Worker <00FC> <00730074>\n\
107*c8dee2aaSAndroid Build Coastguard Worker endbfchar\n\
108*c8dee2aaSAndroid Build Coastguard Worker 4 beginbfrange\n\
109*c8dee2aaSAndroid Build Coastguard Worker <0005> <0007> <0027>\n\
110*c8dee2aaSAndroid Build Coastguard Worker <000B> <000D> <0035>\n\
111*c8dee2aaSAndroid Build Coastguard Worker <00FE> <00FF> <1010>\n\
112*c8dee2aaSAndroid Build Coastguard Worker <0100> <0101> <1012>\n\
113*c8dee2aaSAndroid Build Coastguard Worker endbfrange\n";
114*c8dee2aaSAndroid Build Coastguard Worker
115*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, stream_equals(buffer, expectedResult));
116*c8dee2aaSAndroid Build Coastguard Worker
117*c8dee2aaSAndroid Build Coastguard Worker // Remove characters and ranges.
118*c8dee2aaSAndroid Build Coastguard Worker buffer.reset();
119*c8dee2aaSAndroid Build Coastguard Worker
120*c8dee2aaSAndroid Build Coastguard Worker SkPDFAppendCmapSections(glyphToUnicode.data(), glyphToUnicodeEx, &subset, &buffer, true, 8,
121*c8dee2aaSAndroid Build Coastguard Worker std::min<SkGlyphID>(0x00FF, lastGlyphID));
122*c8dee2aaSAndroid Build Coastguard Worker
123*c8dee2aaSAndroid Build Coastguard Worker char expectedResultChop1[] =
124*c8dee2aaSAndroid Build Coastguard Worker "2 beginbfchar\n\
125*c8dee2aaSAndroid Build Coastguard Worker <0008> <002F>\n\
126*c8dee2aaSAndroid Build Coastguard Worker <0009> <0033>\n\
127*c8dee2aaSAndroid Build Coastguard Worker endbfchar\n\
128*c8dee2aaSAndroid Build Coastguard Worker 2 beginbfchar\n\
129*c8dee2aaSAndroid Build Coastguard Worker <0009> <006600660069>\n\
130*c8dee2aaSAndroid Build Coastguard Worker <00FC> <00730074>\n\
131*c8dee2aaSAndroid Build Coastguard Worker endbfchar\n\
132*c8dee2aaSAndroid Build Coastguard Worker 2 beginbfrange\n\
133*c8dee2aaSAndroid Build Coastguard Worker <000B> <000D> <0035>\n\
134*c8dee2aaSAndroid Build Coastguard Worker <00FE> <00FF> <1010>\n\
135*c8dee2aaSAndroid Build Coastguard Worker endbfrange\n";
136*c8dee2aaSAndroid Build Coastguard Worker
137*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, stream_equals(buffer, expectedResultChop1));
138*c8dee2aaSAndroid Build Coastguard Worker
139*c8dee2aaSAndroid Build Coastguard Worker // Remove characters from range to downdrade it to one char.
140*c8dee2aaSAndroid Build Coastguard Worker buffer.reset();
141*c8dee2aaSAndroid Build Coastguard Worker
142*c8dee2aaSAndroid Build Coastguard Worker SkPDFAppendCmapSections(glyphToUnicode.data(), glyphToUnicodeEx, &subset, &buffer, true, 0x00D,
143*c8dee2aaSAndroid Build Coastguard Worker std::min<SkGlyphID>(0x00FE, lastGlyphID));
144*c8dee2aaSAndroid Build Coastguard Worker
145*c8dee2aaSAndroid Build Coastguard Worker char expectedResultChop2[] =
146*c8dee2aaSAndroid Build Coastguard Worker "2 beginbfchar\n\
147*c8dee2aaSAndroid Build Coastguard Worker <000D> <0037>\n\
148*c8dee2aaSAndroid Build Coastguard Worker <00FE> <1010>\n\
149*c8dee2aaSAndroid Build Coastguard Worker endbfchar\n\
150*c8dee2aaSAndroid Build Coastguard Worker 1 beginbfchar\n\
151*c8dee2aaSAndroid Build Coastguard Worker <00FC> <00730074>\n\
152*c8dee2aaSAndroid Build Coastguard Worker endbfchar\n";
153*c8dee2aaSAndroid Build Coastguard Worker
154*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, stream_equals(buffer, expectedResultChop2));
155*c8dee2aaSAndroid Build Coastguard Worker
156*c8dee2aaSAndroid Build Coastguard Worker buffer.reset();
157*c8dee2aaSAndroid Build Coastguard Worker
158*c8dee2aaSAndroid Build Coastguard Worker SkPDFAppendCmapSections(glyphToUnicode.data(), glyphToUnicodeEx, &subset, &buffer, false, 0xFC,
159*c8dee2aaSAndroid Build Coastguard Worker std::min<SkGlyphID>(0x110, lastGlyphID));
160*c8dee2aaSAndroid Build Coastguard Worker
161*c8dee2aaSAndroid Build Coastguard Worker char expectedResultSingleBytes[] =
162*c8dee2aaSAndroid Build Coastguard Worker "1 beginbfchar\n\
163*c8dee2aaSAndroid Build Coastguard Worker <01> <00730074>\n\
164*c8dee2aaSAndroid Build Coastguard Worker endbfchar\n\
165*c8dee2aaSAndroid Build Coastguard Worker 1 beginbfrange\n\
166*c8dee2aaSAndroid Build Coastguard Worker <03> <06> <1010>\n\
167*c8dee2aaSAndroid Build Coastguard Worker endbfrange\n";
168*c8dee2aaSAndroid Build Coastguard Worker
169*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, stream_equals(buffer, expectedResultSingleBytes));
170*c8dee2aaSAndroid Build Coastguard Worker
171*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.reset();
172*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicodeEx.reset();
173*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.reset();
174*c8dee2aaSAndroid Build Coastguard Worker SkPDFGlyphUse subset2(1, kMaximumGlyphIndex);
175*c8dee2aaSAndroid Build Coastguard Worker
176*c8dee2aaSAndroid Build Coastguard Worker // Test mapping:
177*c8dee2aaSAndroid Build Coastguard Worker // I n s t a l
178*c8dee2aaSAndroid Build Coastguard Worker // Glyph id 2c 51 56 57 44 4f
179*c8dee2aaSAndroid Build Coastguard Worker // Unicode 49 6e 73 74 61 6c
180*c8dee2aaSAndroid Build Coastguard Worker for (SkUnichar i = 0; i < 100; ++i) {
181*c8dee2aaSAndroid Build Coastguard Worker glyphToUnicode.push_back(i + 29);
182*c8dee2aaSAndroid Build Coastguard Worker }
183*c8dee2aaSAndroid Build Coastguard Worker lastGlyphID = SkToU16(glyphToUnicode.size() - 1);
184*c8dee2aaSAndroid Build Coastguard Worker
185*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(0x2C);
186*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(0x44);
187*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(0x4F);
188*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(0x51);
189*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(0x56);
190*c8dee2aaSAndroid Build Coastguard Worker glyphsInSubset.push_back(0x57);
191*c8dee2aaSAndroid Build Coastguard Worker
192*c8dee2aaSAndroid Build Coastguard Worker SkDynamicMemoryWStream buffer2;
193*c8dee2aaSAndroid Build Coastguard Worker for (uint16_t v : glyphsInSubset) {
194*c8dee2aaSAndroid Build Coastguard Worker subset2.set(v);
195*c8dee2aaSAndroid Build Coastguard Worker }
196*c8dee2aaSAndroid Build Coastguard Worker SkPDFAppendCmapSections(glyphToUnicode.data(), glyphToUnicodeEx, &subset2, &buffer2, true, 0,
197*c8dee2aaSAndroid Build Coastguard Worker std::min<SkGlyphID>(0xFFFF, lastGlyphID));
198*c8dee2aaSAndroid Build Coastguard Worker
199*c8dee2aaSAndroid Build Coastguard Worker char expectedResult2[] =
200*c8dee2aaSAndroid Build Coastguard Worker "4 beginbfchar\n\
201*c8dee2aaSAndroid Build Coastguard Worker <002C> <0049>\n\
202*c8dee2aaSAndroid Build Coastguard Worker <0044> <0061>\n\
203*c8dee2aaSAndroid Build Coastguard Worker <004F> <006C>\n\
204*c8dee2aaSAndroid Build Coastguard Worker <0051> <006E>\n\
205*c8dee2aaSAndroid Build Coastguard Worker endbfchar\n\
206*c8dee2aaSAndroid Build Coastguard Worker 1 beginbfrange\n\
207*c8dee2aaSAndroid Build Coastguard Worker <0056> <0057> <0073>\n\
208*c8dee2aaSAndroid Build Coastguard Worker endbfrange\n";
209*c8dee2aaSAndroid Build Coastguard Worker
210*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, stream_equals(buffer2, expectedResult2));
211*c8dee2aaSAndroid Build Coastguard Worker }
212*c8dee2aaSAndroid Build Coastguard Worker
213*c8dee2aaSAndroid Build Coastguard Worker #endif
214