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

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

Issue 2221163002: SkPDF: SkPDFFont organization changes. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 4 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
(Empty)
1 /*
2 * Copyright 2011 Google Inc.
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 "SkPDFConvertType1FontStream.h"
9
10 static bool parsePFBSection(const uint8_t** src, size_t* len, int sectionType,
11 size_t* size) {
12 // PFB sections have a two or six bytes header. 0x80 and a one byte
13 // section type followed by a four byte section length. Type one is
14 // an ASCII section (includes a length), type two is a binary section
15 // (includes a length) and type three is an EOF marker with no length.
16 const uint8_t* buf = *src;
17 if (*len < 2 || buf[0] != 0x80 || buf[1] != sectionType) {
18 return false;
19 } else if (buf[1] == 3) {
20 return true;
21 } else if (*len < 6) {
22 return false;
23 }
24
25 *size = (size_t)buf[2] | ((size_t)buf[3] << 8) | ((size_t)buf[4] << 16) |
26 ((size_t)buf[5] << 24);
27 size_t consumed = *size + 6;
28 if (consumed > *len) {
29 return false;
30 }
31 *src = *src + consumed;
32 *len = *len - consumed;
33 return true;
34 }
35
36 static bool parsePFB(const uint8_t* src, size_t size, size_t* headerLen,
37 size_t* dataLen, size_t* trailerLen) {
38 const uint8_t* srcPtr = src;
39 size_t remaining = size;
40
41 return parsePFBSection(&srcPtr, &remaining, 1, headerLen) &&
42 parsePFBSection(&srcPtr, &remaining, 2, dataLen) &&
43 parsePFBSection(&srcPtr, &remaining, 1, trailerLen) &&
44 parsePFBSection(&srcPtr, &remaining, 3, nullptr);
45 }
46
47 /* The sections of a PFA file are implicitly defined. The body starts
48 * after the line containing "eexec," and the trailer starts with 512
49 * literal 0's followed by "cleartomark" (plus arbitrary white space).
50 *
51 * This function assumes that src is NUL terminated, but the NUL
52 * termination is not included in size.
53 *
54 */
55 static bool parsePFA(const char* src, size_t size, size_t* headerLen,
56 size_t* hexDataLen, size_t* dataLen, size_t* trailerLen) {
57 const char* end = src + size;
58
59 const char* dataPos = strstr(src, "eexec");
60 if (!dataPos) {
61 return false;
62 }
63 dataPos += strlen("eexec");
64 while ((*dataPos == '\n' || *dataPos == '\r' || *dataPos == ' ') &&
65 dataPos < end) {
66 dataPos++;
67 }
68 *headerLen = dataPos - src;
69
70 const char* trailerPos = strstr(dataPos, "cleartomark");
71 if (!trailerPos) {
72 return false;
73 }
74 int zeroCount = 0;
75 for (trailerPos--; trailerPos > dataPos && zeroCount < 512; trailerPos--) {
76 if (*trailerPos == '\n' || *trailerPos == '\r' || *trailerPos == ' ') {
77 continue;
78 } else if (*trailerPos == '0') {
79 zeroCount++;
80 } else {
81 return false;
82 }
83 }
84 if (zeroCount != 512) {
85 return false;
86 }
87
88 *hexDataLen = trailerPos - src - *headerLen;
89 *trailerLen = size - *headerLen - *hexDataLen;
90
91 // Verify that the data section is hex encoded and count the bytes.
92 int nibbles = 0;
93 for (; dataPos < trailerPos; dataPos++) {
94 if (isspace(*dataPos)) {
95 continue;
96 }
97 if (!isxdigit(*dataPos)) {
98 return false;
99 }
100 nibbles++;
101 }
102 *dataLen = (nibbles + 1) / 2;
103
104 return true;
105 }
106
107 static int8_t hexToBin(uint8_t c) {
108 if (!isxdigit(c)) {
109 return -1;
110 } else if (c <= '9') {
111 return c - '0';
112 } else if (c <= 'F') {
113 return c - 'A' + 10;
114 } else if (c <= 'f') {
115 return c - 'a' + 10;
116 }
117 return -1;
118 }
119
120 sk_sp<SkData> SkPDFConvertType1FontStream(
121 std::unique_ptr<SkStreamAsset> srcStream, size_t* headerLen,
122 size_t* dataLen, size_t* trailerLen) {
123 // Flatten and Nul-terminate the source stream so that we can use
124 // strstr() to search it.
125 size_t srcLen = srcStream->getLength();
126 SkAutoTMalloc<uint8_t> sourceBuffer(srcLen + 1);
127 (void)srcStream->read(sourceBuffer.get(), srcLen);
128 sourceBuffer[srcLen] = 0;
129 const uint8_t* src = sourceBuffer.get();
130
131 if (parsePFB(src, srcLen, headerLen, dataLen, trailerLen)) {
132 static const int kPFBSectionHeaderLength = 6;
133 const size_t length = *headerLen + *dataLen + *trailerLen;
134 SkASSERT(length > 0);
135 SkASSERT(length + (2 * kPFBSectionHeaderLength) <= srcLen);
136
137 sk_sp<SkData> data(SkData::MakeUninitialized(length));
138
139 const uint8_t* const srcHeader = src + kPFBSectionHeaderLength;
140 // There is a six-byte section header before header and data
141 // (but not trailer) that we're not going to copy.
142 const uint8_t* const srcData = srcHeader + *headerLen + kPFBSectionHeade rLength;
143 const uint8_t* const srcTrailer = srcData + *headerLen;
144
145 uint8_t* const resultHeader = (uint8_t*)data->writable_data();
146 uint8_t* const resultData = resultHeader + *headerLen;
147 uint8_t* const resultTrailer = resultData + *dataLen;
148
149 SkASSERT(resultTrailer + *trailerLen == resultHeader + length);
150
151 memcpy(resultHeader, srcHeader, *headerLen);
152 memcpy(resultData, srcData, *dataLen);
153 memcpy(resultTrailer, srcTrailer, *trailerLen);
154
155 return data;
156 }
157
158 // A PFA has to be converted for PDF.
159 size_t hexDataLen;
160 if (!parsePFA((const char*)src, srcLen, headerLen, &hexDataLen, dataLen,
161 trailerLen)) {
162 return nullptr;
163 }
164 const size_t length = *headerLen + *dataLen + *trailerLen;
165 SkASSERT(length > 0);
166 auto data = SkData::MakeUninitialized(length);
167 uint8_t* buffer = (uint8_t*)data->writable_data();
168
169 memcpy(buffer, src, *headerLen);
170 uint8_t* const resultData = &(buffer[*headerLen]);
171
172 const uint8_t* hexData = src + *headerLen;
173 const uint8_t* trailer = hexData + hexDataLen;
174 size_t outputOffset = 0;
175 uint8_t dataByte = 0; // To hush compiler.
176 bool highNibble = true;
177 for (; hexData < trailer; hexData++) {
178 int8_t curNibble = hexToBin(*hexData);
179 if (curNibble < 0) {
180 continue;
181 }
182 if (highNibble) {
183 dataByte = curNibble << 4;
184 highNibble = false;
185 } else {
186 dataByte |= curNibble;
187 highNibble = true;
188 resultData[outputOffset++] = dataByte;
189 }
190 }
191 if (!highNibble) {
192 resultData[outputOffset++] = dataByte;
193 }
194 SkASSERT(outputOffset == *dataLen);
195
196 uint8_t* const resultTrailer = &(buffer[SkToInt(*headerLen + outputOffset)]) ;
197 memcpy(resultTrailer, src + *headerLen + hexDataLen, *trailerLen);
198 return data;
199 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698