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 | #ifndef SkPDFUtils_DEFINED |
8 | #define SkPDFUtils_DEFINED |
9 | |
10 | #include "include/core/SkPaint.h" |
11 | #include "include/core/SkPath.h" |
12 | #include "include/core/SkShader.h" |
13 | #include "include/core/SkStream.h" |
14 | #include "src/core/SkUtils.h" |
15 | #include "src/pdf/SkPDFTypes.h" |
16 | #include "src/shaders/SkShaderBase.h" |
17 | #include "src/utils/SkFloatToDecimal.h" |
18 | |
19 | class SkMatrix; |
20 | class SkPDFArray; |
21 | struct SkRect; |
22 | |
23 | template <typename T> |
24 | bool SkPackedArrayEqual(T* u, T* v, size_t n) { |
25 | SkASSERT(u); |
26 | SkASSERT(v); |
27 | return 0 == memcmp(u, v, n * sizeof(T)); |
28 | } |
29 | |
30 | #if 0 |
31 | #define PRINT_NOT_IMPL(str) fprintf(stderr, str) |
32 | #else |
33 | #define PRINT_NOT_IMPL(str) |
34 | #endif |
35 | |
36 | #define NOT_IMPLEMENTED(condition, assert) \ |
37 | do { \ |
38 | if ((bool)(condition)) { \ |
39 | PRINT_NOT_IMPL("NOT_IMPLEMENTED: " #condition "\n"); \ |
40 | SkDEBUGCODE(SkASSERT(!assert);) \ |
41 | } \ |
42 | } while (0) |
43 | |
44 | namespace SkPDFUtils { |
45 | |
46 | const char* BlendModeName(SkBlendMode); |
47 | |
48 | std::unique_ptr<SkPDFArray> RectToArray(const SkRect& rect); |
49 | std::unique_ptr<SkPDFArray> MatrixToArray(const SkMatrix& matrix); |
50 | |
51 | void MoveTo(SkScalar x, SkScalar y, SkWStream* content); |
52 | void AppendLine(SkScalar x, SkScalar y, SkWStream* content); |
53 | void AppendRectangle(const SkRect& rect, SkWStream* content); |
54 | void EmitPath(const SkPath& path, SkPaint::Style paintStyle, |
55 | bool doConsumeDegerates, SkWStream* content, SkScalar tolerance = 0.25f); |
56 | inline void EmitPath(const SkPath& path, SkPaint::Style paintStyle, |
57 | SkWStream* content, SkScalar tolerance = 0.25f) { |
58 | SkPDFUtils::EmitPath(path, paintStyle, true, content, tolerance); |
59 | } |
60 | void ClosePath(SkWStream* content); |
61 | void PaintPath(SkPaint::Style style, SkPathFillType fill, SkWStream* content); |
62 | void StrokePath(SkWStream* content); |
63 | void ApplyGraphicState(int objectIndex, SkWStream* content); |
64 | void ApplyPattern(int objectIndex, SkWStream* content); |
65 | |
66 | // Converts (value / 255.0) with three significant digits of accuracy. |
67 | // Writes value as string into result. Returns strlen() of result. |
68 | size_t ColorToDecimal(uint8_t value, char result[5]); |
69 | |
70 | static constexpr unsigned kFloatColorDecimalCount = 4; |
71 | size_t ColorToDecimalF(float value, char result[kFloatColorDecimalCount + 2]); |
72 | inline void AppendColorComponent(uint8_t value, SkWStream* wStream) { |
73 | char buffer[5]; |
74 | size_t len = SkPDFUtils::ColorToDecimal(value, buffer); |
75 | wStream->write(buffer, len); |
76 | } |
77 | inline void AppendColorComponentF(float value, SkWStream* wStream) { |
78 | char buffer[kFloatColorDecimalCount + 2]; |
79 | size_t len = SkPDFUtils::ColorToDecimalF(value, buffer); |
80 | wStream->write(buffer, len); |
81 | } |
82 | |
83 | inline void AppendScalar(SkScalar value, SkWStream* stream) { |
84 | char result[kMaximumSkFloatToDecimalLength]; |
85 | size_t len = SkFloatToDecimal(SkScalarToFloat(value), result); |
86 | SkASSERT(len < kMaximumSkFloatToDecimalLength); |
87 | stream->write(result, len); |
88 | } |
89 | |
90 | inline void WriteUInt16BE(SkDynamicMemoryWStream* wStream, uint16_t value) { |
91 | char result[4] = { SkHexadecimalDigits::gUpper[ value >> 12 ], |
92 | SkHexadecimalDigits::gUpper[0xF & (value >> 8 )], |
93 | SkHexadecimalDigits::gUpper[0xF & (value >> 4 )], |
94 | SkHexadecimalDigits::gUpper[0xF & (value )] }; |
95 | wStream->write(result, 4); |
96 | } |
97 | |
98 | inline void WriteUInt8(SkDynamicMemoryWStream* wStream, uint8_t value) { |
99 | char result[2] = { SkHexadecimalDigits::gUpper[value >> 4], |
100 | SkHexadecimalDigits::gUpper[value & 0xF] }; |
101 | wStream->write(result, 2); |
102 | } |
103 | |
104 | inline void WriteUTF16beHex(SkDynamicMemoryWStream* wStream, SkUnichar utf32) { |
105 | uint16_t utf16[2] = {0, 0}; |
106 | size_t len = SkUTF::ToUTF16(utf32, utf16); |
107 | SkASSERT(len == 1 || len == 2); |
108 | SkPDFUtils::WriteUInt16BE(wStream, utf16[0]); |
109 | if (len == 2) { |
110 | SkPDFUtils::WriteUInt16BE(wStream, utf16[1]); |
111 | } |
112 | } |
113 | |
114 | inline SkMatrix GetShaderLocalMatrix(const SkShader* shader) { |
115 | SkMatrix localMatrix; |
116 | if (sk_sp<SkShader> s = as_SB(shader)->makeAsALocalMatrixShader(&localMatrix)) { |
117 | return SkMatrix::Concat(as_SB(s)->getLocalMatrix(), localMatrix); |
118 | } |
119 | return as_SB(shader)->getLocalMatrix(); |
120 | } |
121 | bool InverseTransformBBox(const SkMatrix& matrix, SkRect* bbox); |
122 | void PopulateTilingPatternDict(SkPDFDict* pattern, |
123 | SkRect& bbox, |
124 | std::unique_ptr<SkPDFDict> resources, |
125 | const SkMatrix& matrix); |
126 | |
127 | bool ToBitmap(const SkImage* img, SkBitmap* dst); |
128 | |
129 | #ifdef SK_PDF_BASE85_BINARY |
130 | void Base85Encode(std::unique_ptr<SkStreamAsset> src, SkDynamicMemoryWStream* dst); |
131 | #endif // SK_PDF_BASE85_BINARY |
132 | |
133 | void AppendTransform(const SkMatrix&, SkWStream*); |
134 | } // namespace SkPDFUtils |
135 | |
136 | #endif |
137 | |