1// Copyright 2018 Google LLC.
2// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
3#ifndef SkPDFUnion_DEFINED
4#define SkPDFUnion_DEFINED
5
6#include "src/pdf/SkPDFTypes.h"
7
8// Exposed for unit testing.
9void SkPDFWriteString(SkWStream* wStream, const char* cin, size_t len);
10
11////////////////////////////////////////////////////////////////////////////////
12
13/**
14 A SkPDFUnion is a non-virtualized implementation of the
15 non-compound, non-specialized PDF Object types: Name, String,
16 Number, Boolean.
17 */
18class SkPDFUnion {
19public:
20 // Move constructor and assignment operator destroy the argument
21 // and steal their references (if needed).
22 SkPDFUnion(SkPDFUnion&&);
23 SkPDFUnion& operator=(SkPDFUnion&&);
24
25 ~SkPDFUnion();
26
27 /** The following nine functions are the standard way of creating
28 SkPDFUnion objects. */
29
30 static SkPDFUnion Int(int32_t);
31
32 static SkPDFUnion Int(size_t v) { return SkPDFUnion::Int(SkToS32(v)); }
33
34 static SkPDFUnion Bool(bool);
35
36 static SkPDFUnion Scalar(SkScalar);
37
38 static SkPDFUnion ColorComponent(uint8_t);
39
40 static SkPDFUnion ColorComponentF(float);
41
42 /** These two functions do NOT take ownership of char*, and do NOT
43 copy the string. Suitable for passing in static const
44 strings. For example:
45 SkPDFUnion n = SkPDFUnion::Name("Length");
46 SkPDFUnion u = SkPDFUnion::String("Identity"); */
47
48 /** SkPDFUnion::Name(const char*) assumes that the passed string
49 is already a valid name (that is: it has no control or
50 whitespace characters). This will not copy the name. */
51 static SkPDFUnion Name(const char*);
52
53 /** SkPDFUnion::String will encode the passed string. This will
54 not copy the name. */
55 static SkPDFUnion String(const char*);
56
57 /** SkPDFUnion::Name(SkString) does not assume that the
58 passed string is already a valid name and it will escape the
59 string. */
60 static SkPDFUnion Name(SkString);
61
62 /** SkPDFUnion::String will encode the passed string. */
63 static SkPDFUnion String(SkString);
64
65 static SkPDFUnion Object(std::unique_ptr<SkPDFObject>);
66
67 static SkPDFUnion Ref(SkPDFIndirectReference);
68
69 /** These two non-virtual methods mirror SkPDFObject's
70 corresponding virtuals. */
71 void emitObject(SkWStream*) const;
72
73 bool isName() const;
74
75private:
76 using PDFObject = std::unique_ptr<SkPDFObject>;
77 union {
78 int32_t fIntValue;
79 bool fBoolValue;
80 SkScalar fScalarValue;
81 const char* fStaticString;
82 SkString fSkString;
83 PDFObject fObject;
84 };
85 enum class Type : char {
86 /** It is an error to call emitObject() or addResources() on an kDestroyed object. */
87 kDestroyed = 0,
88 kInt,
89 kColorComponent,
90 kColorComponentF,
91 kBool,
92 kScalar,
93 kName,
94 kString,
95 kNameSkS,
96 kStringSkS,
97 kObject,
98 kRef,
99 };
100 Type fType;
101
102 SkPDFUnion(Type, int32_t);
103 SkPDFUnion(Type, bool);
104 SkPDFUnion(Type, SkScalar);
105 SkPDFUnion(Type, const char*);
106 SkPDFUnion(Type, SkString);
107 SkPDFUnion(Type, PDFObject);
108
109 SkPDFUnion& operator=(const SkPDFUnion&) = delete;
110 SkPDFUnion(const SkPDFUnion&) = delete;
111};
112static_assert(sizeof(SkString) == sizeof(void*), "SkString_size");
113
114#endif // SkPDFUnion_DEFINED
115