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

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

Powered by Google App Engine
This is Rietveld 408576698