1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2011 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SkPDFUtils_DEFINED
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define SkPDFUtils_DEFINED
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkFloatToDecimal.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPDFTypes.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPaint.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPath.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkShader.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkStream.h"
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkUtils.h"
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkMatrix;
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkPDFArray;
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct SkRect;
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T>
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkPackedArrayEqual(T* u, T* v, size_t n) {
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(u);
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(v);
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return 0 == memcmp(u, v, n * sizeof(T));
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define PRINT_NOT_IMPL(str) fprintf(stderr, str)
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#else
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define PRINT_NOT_IMPL(str)
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define NOT_IMPLEMENTED(condition, assert)                         \
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {                                                           \
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if ((bool)(condition)) {                                   \
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            PRINT_NOT_IMPL("NOT_IMPLEMENTED: " #condition "\n");   \
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDEBUGCODE(SkASSERT(!assert);)                        \
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }                                                          \
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (0)
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotnamespace SkPDFUtils {
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconstexpr float kDpiForRasterScaleOne = 72.0f;
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkPDFArray> RectToArray(const SkRect& rect);
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkPDFArray> MatrixToArray(const SkMatrix& matrix);
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid AppendTransform(const SkMatrix& matrix, SkWStream* content);
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid MoveTo(SkScalar x, SkScalar y, SkWStream* content);
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid AppendLine(SkScalar x, SkScalar y, SkWStream* content);
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid AppendCubic(SkScalar ctl1X, SkScalar ctl1Y,
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                 SkScalar ctl2X, SkScalar ctl2Y,
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                 SkScalar dstX, SkScalar dstY, SkWStream* content);
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid AppendRectangle(const SkRect& rect, SkWStream* content);
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid EmitPath(const SkPath& path, SkPaint::Style paintStyle,
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot              bool doConsumeDegerates, SkWStream* content, SkScalar tolerance = 0.25f);
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotinline void EmitPath(const SkPath& path, SkPaint::Style paintStyle,
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                     SkWStream* content, SkScalar tolerance = 0.25f) {
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPDFUtils::EmitPath(path, paintStyle, true, content, tolerance);
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid ClosePath(SkWStream* content);
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid PaintPath(SkPaint::Style style, SkPath::FillType fill,
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                      SkWStream* content);
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid StrokePath(SkWStream* content);
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid DrawFormXObject(int objectIndex, SkWStream* content);
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid ApplyGraphicState(int objectIndex, SkWStream* content);
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid ApplyPattern(int objectIndex, SkWStream* content);
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Converts (value / 255.0) with three significant digits of accuracy.
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Writes value as string into result.  Returns strlen() of result.
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsize_t ColorToDecimal(uint8_t value, char result[5]);
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotinline void AppendColorComponent(uint8_t value, SkWStream* wStream) {
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char buffer[5];
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t len = SkPDFUtils::ColorToDecimal(value, buffer);
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    wStream->write(buffer, len);
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotinline void AppendScalar(SkScalar value, SkWStream* stream) {
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char result[kMaximumSkFloatToDecimalLength];
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t len = SkFloatToDecimal(SkScalarToFloat(value), result);
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(len < kMaximumSkFloatToDecimalLength);
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    stream->write(result, len);
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid WriteString(SkWStream* wStream, const char* input, size_t len);
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotinline void WriteUInt16BE(SkDynamicMemoryWStream* wStream, uint16_t value) {
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char result[4];
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    result[0] = SkHexadecimalDigits::gUpper[       value >> 12 ];
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    result[1] = SkHexadecimalDigits::gUpper[0xF & (value >> 8 )];
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    result[2] = SkHexadecimalDigits::gUpper[0xF & (value >> 4 )];
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    result[3] = SkHexadecimalDigits::gUpper[0xF & (value      )];
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    wStream->write(result, 4);
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotinline void WriteUInt8(SkDynamicMemoryWStream* wStream, uint8_t value) {
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char result[2] = { SkHexadecimalDigits::gUpper[value >> 4],
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                       SkHexadecimalDigits::gUpper[value & 0xF] };
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    wStream->write(result, 2);
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotinline void WriteUTF16beHex(SkDynamicMemoryWStream* wStream, SkUnichar utf32) {
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint16_t utf16[2] = {0, 0};
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t len = SkUTF16_FromUnichar(utf32, utf16);
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(len == 1 || len == 2);
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPDFUtils::WriteUInt16BE(wStream, utf16[0]);
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (len == 2) {
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPDFUtils::WriteUInt16BE(wStream, utf16[1]);
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotinline SkMatrix GetShaderLocalMatrix(const SkShader* shader) {
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkMatrix localMatrix;
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (sk_sp<SkShader> s = shader->makeAsALocalMatrixShader(&localMatrix)) {
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkMatrix::Concat(s->getLocalMatrix(), localMatrix);
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return shader->getLocalMatrix();
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool InverseTransformBBox(const SkMatrix& matrix, SkRect* bbox);
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid PopulateTilingPatternDict(SkPDFDict* pattern,
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               SkRect& bbox,
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               sk_sp<SkPDFDict> resources,
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               const SkMatrix& matrix);
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool ToBitmap(const SkImage* img, SkBitmap* dst);
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}  // namespace SkPDFUtils
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
131