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