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