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