// 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
|