OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "SkPDFTypes.h" | 9 #include "SkPDFTypes.h" |
| 10 #include "SkPDFUtils.h" |
10 #include "SkStream.h" | 11 #include "SkStream.h" |
11 | 12 |
12 #ifdef SK_BUILD_FOR_WIN | 13 #ifdef SK_BUILD_FOR_WIN |
13 #define SNPRINTF _snprintf | 14 #define SNPRINTF _snprintf |
14 #else | 15 #else |
15 #define SNPRINTF snprintf | 16 #define SNPRINTF snprintf |
16 #endif | 17 #endif |
17 | 18 |
18 //////////////////////////////////////////////////////////////////////////////// | 19 //////////////////////////////////////////////////////////////////////////////// |
19 | 20 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 | 128 |
128 static SkString escape_name(const SkString& name) { | 129 static SkString escape_name(const SkString& name) { |
129 return escape_name(name.c_str(), name.size()); | 130 return escape_name(name.c_str(), name.size()); |
130 } | 131 } |
131 | 132 |
132 static void write_string(SkWStream* o, const SkString& s) { | 133 static void write_string(SkWStream* o, const SkString& s) { |
133 o->write(s.c_str(), s.size()); | 134 o->write(s.c_str(), s.size()); |
134 } | 135 } |
135 | 136 |
136 static SkString format_string(const SkString& s) { | 137 static SkString format_string(const SkString& s) { |
137 return SkPDFString::FormatString(s.c_str(), s.size()); | 138 return SkPDFUtils::FormatString(s.c_str(), s.size()); |
138 } | 139 } |
139 | 140 |
140 static SkString format_string(const char* s) { | 141 static SkString format_string(const char* s) { |
141 return SkPDFString::FormatString(s, strlen(s)); | 142 return SkPDFUtils::FormatString(s, strlen(s)); |
142 } | 143 } |
143 | 144 |
144 void SkPDFUnion::emitObject(SkWStream* stream, | 145 void SkPDFUnion::emitObject(SkWStream* stream, |
145 const SkPDFObjNumMap& objNumMap, | 146 const SkPDFObjNumMap& objNumMap, |
146 const SkPDFSubstituteMap& substitutes) const { | 147 const SkPDFSubstituteMap& substitutes) const { |
147 switch (fType) { | 148 switch (fType) { |
148 case Type::kInt: | 149 case Type::kInt: |
149 stream->writeDecAsText(fIntValue); | 150 stream->writeDecAsText(fIntValue); |
150 return; | 151 return; |
151 case Type::kBool: | 152 case Type::kBool: |
152 stream->writeText(fBoolValue ? "true" : "false"); | 153 stream->writeText(fBoolValue ? "true" : "false"); |
153 return; | 154 return; |
154 case Type::kScalar: | 155 case Type::kScalar: |
155 SkPDFScalar::Append(fScalarValue, stream); | 156 SkPDFUtils::AppendScalar(fScalarValue, stream); |
156 return; | 157 return; |
157 case Type::kName: | 158 case Type::kName: |
158 stream->writeText("/"); | 159 stream->writeText("/"); |
159 SkASSERT(is_valid_name(fStaticString)); | 160 SkASSERT(is_valid_name(fStaticString)); |
160 stream->writeText(fStaticString); | 161 stream->writeText(fStaticString); |
161 return; | 162 return; |
162 case Type::kString: | 163 case Type::kString: |
163 SkASSERT(fStaticString); | 164 SkASSERT(fStaticString); |
164 write_string(stream, format_string(fStaticString)); | 165 write_string(stream, format_string(fStaticString)); |
165 return; | 166 return; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 void SkPDFAtom::emitObject(SkWStream* stream, | 275 void SkPDFAtom::emitObject(SkWStream* stream, |
275 const SkPDFObjNumMap& objNumMap, | 276 const SkPDFObjNumMap& objNumMap, |
276 const SkPDFSubstituteMap& substitutes) { | 277 const SkPDFSubstituteMap& substitutes) { |
277 fValue.emitObject(stream, objNumMap, substitutes); | 278 fValue.emitObject(stream, objNumMap, substitutes); |
278 } | 279 } |
279 void SkPDFAtom::addResources(SkPDFObjNumMap* map, | 280 void SkPDFAtom::addResources(SkPDFObjNumMap* map, |
280 const SkPDFSubstituteMap& substitutes) const { | 281 const SkPDFSubstituteMap& substitutes) const { |
281 fValue.addResources(map, substitutes); | 282 fValue.addResources(map, substitutes); |
282 } | 283 } |
283 #endif // 0 | 284 #endif // 0 |
284 //////////////////////////////////////////////////////////////////////////////// | |
285 | |
286 // static | |
287 void SkPDFScalar::Append(SkScalar value, SkWStream* stream) { | |
288 // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and | |
289 // +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31). | |
290 // When using floats that are outside the whole value range, we can use | |
291 // integers instead. | |
292 | |
293 #if !defined(SK_ALLOW_LARGE_PDF_SCALARS) | |
294 if (value > 32767 || value < -32767) { | |
295 stream->writeDecAsText(SkScalarRoundToInt(value)); | |
296 return; | |
297 } | |
298 | |
299 char buffer[SkStrAppendScalar_MaxSize]; | |
300 char* end = SkStrAppendFixed(buffer, SkScalarToFixed(value)); | |
301 stream->write(buffer, end - buffer); | |
302 return; | |
303 #endif // !SK_ALLOW_LARGE_PDF_SCALARS | |
304 | |
305 #if defined(SK_ALLOW_LARGE_PDF_SCALARS) | |
306 // Floats have 24bits of significance, so anything outside that range is | |
307 // no more precise than an int. (Plus PDF doesn't support scientific | |
308 // notation, so this clamps to SK_Max/MinS32). | |
309 if (value > (1 << 24) || value < -(1 << 24)) { | |
310 stream->writeDecAsText(value); | |
311 return; | |
312 } | |
313 // Continue to enforce the PDF limits for small floats. | |
314 if (value < 1.0f/65536 && value > -1.0f/65536) { | |
315 stream->writeDecAsText(0); | |
316 return; | |
317 } | |
318 // SkStrAppendFloat might still use scientific notation, so use snprintf | |
319 // directly.. | |
320 static const int kFloat_MaxSize = 19; | |
321 char buffer[kFloat_MaxSize]; | |
322 int len = SNPRINTF(buffer, kFloat_MaxSize, "%#.8f", value); | |
323 // %f always prints trailing 0s, so strip them. | |
324 for (; buffer[len - 1] == '0' && len > 0; len--) { | |
325 buffer[len - 1] = '\0'; | |
326 } | |
327 if (buffer[len - 1] == '.') { | |
328 buffer[len - 1] = '\0'; | |
329 } | |
330 stream->writeText(buffer); | |
331 return; | |
332 #endif // SK_ALLOW_LARGE_PDF_SCALARS | |
333 } | |
334 | 285 |
335 //////////////////////////////////////////////////////////////////////////////// | 286 //////////////////////////////////////////////////////////////////////////////// |
336 | 287 |
337 // static | |
338 | |
339 SkString SkPDFString::FormatString(const char* cin, size_t len) { | |
340 SkASSERT(len <= kMaxLen); | |
341 | |
342 // 7-bit clean is a heuristic to decide what string format to use; | |
343 // a 7-bit clean string should require little escaping. | |
344 bool sevenBitClean = true; | |
345 size_t characterCount = 2 + len; | |
346 for (size_t i = 0; i < len; i++) { | |
347 if (cin[i] > '~' || cin[i] < ' ') { | |
348 sevenBitClean = false; | |
349 break; | |
350 } | |
351 if (cin[i] == '\\' || cin[i] == '(' || cin[i] == ')') { | |
352 ++characterCount; | |
353 } | |
354 } | |
355 SkString result; | |
356 if (sevenBitClean) { | |
357 result.resize(characterCount); | |
358 char* str = result.writable_str(); | |
359 *str++ = '('; | |
360 for (size_t i = 0; i < len; i++) { | |
361 if (cin[i] == '\\' || cin[i] == '(' || cin[i] == ')') { | |
362 *str++ = '\\'; | |
363 } | |
364 *str++ = cin[i]; | |
365 } | |
366 *str++ = ')'; | |
367 } else { | |
368 result.resize(2 * len + 2); | |
369 char* str = result.writable_str(); | |
370 *str++ = '<'; | |
371 for (size_t i = 0; i < len; i++) { | |
372 uint8_t c = static_cast<uint8_t>(cin[i]); | |
373 static const char gHex[] = "0123456789ABCDEF"; | |
374 *str++ = gHex[(c >> 4) & 0xF]; | |
375 *str++ = gHex[(c ) & 0xF]; | |
376 } | |
377 *str++ = '>'; | |
378 } | |
379 return result; | |
380 } | |
381 | |
382 //////////////////////////////////////////////////////////////////////////////// | |
383 | |
384 SkPDFArray::SkPDFArray() {} | 288 SkPDFArray::SkPDFArray() {} |
385 SkPDFArray::~SkPDFArray() { | 289 SkPDFArray::~SkPDFArray() { |
386 for (SkPDFUnion& value : fValues) { | 290 for (SkPDFUnion& value : fValues) { |
387 value.~SkPDFUnion(); | 291 value.~SkPDFUnion(); |
388 } | 292 } |
389 fValues.reset(); | 293 fValues.reset(); |
390 } | 294 } |
391 | 295 |
392 int SkPDFArray::size() const { return fValues.count(); } | 296 int SkPDFArray::size() const { return fValues.count(); } |
393 | 297 |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 fObjects.push(obj); | 480 fObjects.push(obj); |
577 return true; | 481 return true; |
578 } | 482 } |
579 | 483 |
580 int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const { | 484 int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const { |
581 int32_t* objectNumberFound = fObjectNumbers.find(obj); | 485 int32_t* objectNumberFound = fObjectNumbers.find(obj); |
582 SkASSERT(objectNumberFound); | 486 SkASSERT(objectNumberFound); |
583 return *objectNumberFound; | 487 return *objectNumberFound; |
584 } | 488 } |
585 | 489 |
OLD | NEW |