/* * Copyright 2010 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkPDFTypes_DEFINED #define SkPDFTypes_DEFINED #include "include/core/SkScalar.h" #include "include/core/SkSpan.h" #include "include/core/SkTypes.h" #include "src/pdf/SkPDFUnion.h" #include #include #include #include #include class SkPDFDocument; class SkStreamAsset; class SkString; class SkWStream; #ifndef SK_PDF_MASK_QUALITY // If MASK_QUALITY is in [0,100], will be used for JpegEncoder. // Otherwise, just encode masks losslessly. #define SK_PDF_MASK_QUALITY 50 // Since these masks are used for blurry shadows, we shouldn't need // high quality. Raise this value if your shadows have visible JPEG // artifacts. // If SkJpegEncoder::Encode fails, we will fall back to the lossless // encoding. #endif struct SkPDFIndirectReference { int fValue = -1; explicit operator bool() const { return fValue != -1; } bool operator==(SkPDFIndirectReference v) const { return fValue == v.fValue; } bool operator!=(SkPDFIndirectReference v) const { return fValue != v.fValue; } }; /** \class SkPDFObject A PDF Object is the base class for primitive elements in a PDF file. A common subtype is used to ease the use of indirect object references, which are common in the PDF format. */ class SkPDFObject { public: SkPDFObject() = default; /** Subclasses must implement this method to print the object to the * PDF file. * @param catalog The object catalog to use. * @param stream The writable output stream to send the output to. */ virtual void emitObject(SkWStream* stream) const = 0; virtual ~SkPDFObject() = default; private: SkPDFObject(SkPDFObject&&) = delete; SkPDFObject(const SkPDFObject&) = delete; SkPDFObject& operator=(SkPDFObject&&) = delete; SkPDFObject& operator=(const SkPDFObject&) = delete; }; //////////////////////////////////////////////////////////////////////////////// /** \class SkPDFArray An array object in a PDF. */ class SkPDFArray : public SkPDFObject { public: /** Create a PDF array. Maximum length is 8191. */ SkPDFArray(); ~SkPDFArray() override; // The SkPDFObject interface. void emitObject(SkWStream* stream) const override; /** The size of the array. */ size_t size() const; /** Preallocate space for the given number of entries. * @param length The number of array slots to preallocate. */ void reserve(int length); /** Appends a value to the end of the array. * @param value The value to add to the array. */ void appendInt(int32_t); void appendColorComponent(uint8_t); void appendBool(bool); void appendScalar(SkScalar); void appendName(const char[]); void appendName(SkString); void appendByteString(const char[]); void appendTextString(const char[]); void appendByteString(SkString); void appendTextString(SkString); void appendObject(std::unique_ptr&&); void appendRef(SkPDFIndirectReference); protected: SkSpan values() const { return SkSpan(fValues); } private: std::vector fValues; void append(SkPDFUnion&& value); }; static inline void SkPDFArray_Append(SkPDFArray* a, int v) { a->appendInt(v); } static inline void SkPDFArray_Append(SkPDFArray* a, SkScalar v) { a->appendScalar(v); } template static inline void SkPDFArray_Append(SkPDFArray* a, T v, Args... args) { SkPDFArray_Append(a, v); SkPDFArray_Append(a, args...); } static inline void SkPDFArray_Append(SkPDFArray* a) {} template static inline std::unique_ptr SkPDFMakeArray(Args... args) { std::unique_ptr ret(new SkPDFArray()); ret->reserve(sizeof...(Args)); SkPDFArray_Append(ret.get(), args...); return ret; } /** \class SkPDFOptionalArray * * An SkPDFArray which may be emitted as a non-array if it contains a single entry. * Search the specification for "or an array" for where this can be used. */ class SkPDFOptionalArray final : public SkPDFArray { void emitObject(SkWStream* stream) const override; }; /** \class SkPDFDict A dictionary object in a PDF. */ class SkPDFDict final : public SkPDFObject { public: /** Create a PDF dictionary. * @param type The value of the Type entry, nullptr for no type. */ explicit SkPDFDict(const char type[] = nullptr); ~SkPDFDict() override; // The SkPDFObject interface. void emitObject(SkWStream* stream) const override; /** The size of the dictionary. */ size_t size() const; /** Preallocate space for n key-value pairs */ void reserve(int n); /** Add the value to the dictionary with the given key. * @param key The text of the key for this dictionary entry. * @param value The value for this dictionary entry. */ void insertObject(const char key[], std::unique_ptr&&); void insertObject(SkString, std::unique_ptr&&); void insertRef(const char key[], SkPDFIndirectReference); void insertRef(SkString, SkPDFIndirectReference); /** Add the value to the dictionary with the given key. * @param key The text of the key for this dictionary entry. * @param value The value for this dictionary entry. */ void insertBool(const char key[], bool value); void insertInt(const char key[], int32_t value); void insertInt(const char key[], size_t value); void insertScalar(const char key[], SkScalar value); void insertColorComponentF(const char key[], SkScalar value); void insertName(const char key[], const char nameValue[]); void insertName(const char key[], SkString nameValue); void insertByteString(const char key[], const char value[]); void insertTextString(const char key[], const char value[]); void insertByteString(const char key[], SkString value); void insertTextString(const char key[], SkString value); void insertUnion(const char key[], SkPDFUnion&&); private: std::vector> fRecords; }; static inline std::unique_ptr SkPDFMakeDict(const char* type = nullptr) { return std::make_unique(type); } enum class SkPDFSteamCompressionEnabled : bool { No = false, Yes = true, }; // Exposed for unit testing. void SkPDFWriteTextString(SkWStream* wStream, const char* cin, size_t len); void SkPDFWriteByteString(SkWStream* wStream, const char* cin, size_t len); SkPDFIndirectReference SkPDFStreamOut( std::unique_ptr dict, std::unique_ptr stream, SkPDFDocument* doc, SkPDFSteamCompressionEnabled compress = SkPDFSteamCompressionEnabled::Yes); #endif