| 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 SkPDFDocument_DEFINED | 
|---|
| 4 | #define SkPDFDocument_DEFINED | 
|---|
| 5 |  | 
|---|
| 6 | #include "include/core/SkDocument.h" | 
|---|
| 7 |  | 
|---|
| 8 | #include <vector> | 
|---|
| 9 |  | 
|---|
| 10 | #include "include/core/SkColor.h" | 
|---|
| 11 | #include "include/core/SkMilestone.h" | 
|---|
| 12 | #include "include/core/SkScalar.h" | 
|---|
| 13 | #include "include/core/SkString.h" | 
|---|
| 14 | #include "include/core/SkTime.h" | 
|---|
| 15 | #include "include/private/SkNoncopyable.h" | 
|---|
| 16 |  | 
|---|
| 17 | #define SKPDF_STRING(X) SKPDF_STRING_IMPL(X) | 
|---|
| 18 | #define SKPDF_STRING_IMPL(X) #X | 
|---|
| 19 |  | 
|---|
| 20 | class SkExecutor; | 
|---|
| 21 | class SkPDFArray; | 
|---|
| 22 | class SkPDFTagTree; | 
|---|
| 23 |  | 
|---|
| 24 | namespace SkPDF { | 
|---|
| 25 |  | 
|---|
| 26 | /** Table 333 in PDF 32000-1:2008 ยง14.8.4.2 | 
|---|
| 27 | */ | 
|---|
| 28 | enum class DocumentStructureType { | 
|---|
| 29 | kDocument,    //!< Document | 
|---|
| 30 | kPart,        //!< Part | 
|---|
| 31 | kArt,         //!< Article | 
|---|
| 32 | kSect,        //!< Section | 
|---|
| 33 | kDiv,         //!< Division | 
|---|
| 34 | kBlockQuote,  //!< Block quotation | 
|---|
| 35 | kCaption,     //!< Caption | 
|---|
| 36 | kTOC,         //!< Table of Contents | 
|---|
| 37 | kTOCI,        //!< Table of Contents Item | 
|---|
| 38 | kIndex,       //!< Index | 
|---|
| 39 | kNonStruct,   //!< Nonstructural element | 
|---|
| 40 | kPrivate,     //!< Private element | 
|---|
| 41 | kH,           //!< Heading | 
|---|
| 42 | kH1,          //!< Heading level 1 | 
|---|
| 43 | kH2,          //!< Heading level 2 | 
|---|
| 44 | kH3,          //!< Heading level 3 | 
|---|
| 45 | kH4,          //!< Heading level 4 | 
|---|
| 46 | kH5,          //!< Heading level 5 | 
|---|
| 47 | kH6,          //!< Heading level 6 | 
|---|
| 48 | kP,           //!< Paragraph | 
|---|
| 49 | kL,           //!< List | 
|---|
| 50 | kLI,          //!< List item | 
|---|
| 51 | kLbl,         //!< List item label | 
|---|
| 52 | kLBody,       //!< List item body | 
|---|
| 53 | kTable,       //!< Table | 
|---|
| 54 | kTR,          //!< Table row | 
|---|
| 55 | kTH,          //!< Table header cell | 
|---|
| 56 | kTD,          //!< Table data cell | 
|---|
| 57 | kTHead,       //!< Table header row group | 
|---|
| 58 | kTBody,       //!< Table body row group | 
|---|
| 59 | ,       //!< table footer row group | 
|---|
| 60 | kSpan,        //!< Span | 
|---|
| 61 | kQuote,       //!< Quotation | 
|---|
| 62 | kNote,        //!< Note | 
|---|
| 63 | kReference,   //!< Reference | 
|---|
| 64 | kBibEntry,    //!< Bibliography entry | 
|---|
| 65 | kCode,        //!< Code | 
|---|
| 66 | kLink,        //!< Link | 
|---|
| 67 | kAnnot,       //!< Annotation | 
|---|
| 68 | kRuby,        //!< Ruby annotation | 
|---|
| 69 | kRB,          //!< Ruby base text | 
|---|
| 70 | kRT,          //!< Ruby annotation text | 
|---|
| 71 | kRP,          //!< Ruby punctuation | 
|---|
| 72 | kWarichu,     //!< Warichu annotation | 
|---|
| 73 | kWT,          //!< Warichu text | 
|---|
| 74 | kWP,          //!< Warichu punctuation | 
|---|
| 75 | kFigure,      //!< Figure | 
|---|
| 76 | kFormula,     //!< Formula | 
|---|
| 77 | kForm,        //!< Form control (not like an HTML FORM element) | 
|---|
| 78 | }; | 
|---|
| 79 |  | 
|---|
| 80 | /** Attributes for nodes in the PDF tree. */ | 
|---|
| 81 | class SK_API AttributeList : SkNoncopyable { | 
|---|
| 82 | public: | 
|---|
| 83 | AttributeList(); | 
|---|
| 84 | ~AttributeList(); | 
|---|
| 85 |  | 
|---|
| 86 | // Each attribute must have an owner (e.g. "Layout", "List", "Table", etc) | 
|---|
| 87 | // and an attribute name (e.g. "BBox", "RowSpan", etc.) from PDF32000_2008 14.8.5, | 
|---|
| 88 | // and then a value of the proper type according to the spec. | 
|---|
| 89 | void appendInt(const char* owner, const char* name, int value); | 
|---|
| 90 | void appendFloat(const char* owner, const char* name, float value); | 
|---|
| 91 | void appendString(const char* owner, const char* name, const char* value); | 
|---|
| 92 | void appendFloatArray(const char* owner, | 
|---|
| 93 | const char* name, | 
|---|
| 94 | const std::vector<float>& value); | 
|---|
| 95 | void appendStringArray(const char* owner, | 
|---|
| 96 | const char* name, | 
|---|
| 97 | const std::vector<SkString>& value); | 
|---|
| 98 |  | 
|---|
| 99 | private: | 
|---|
| 100 | friend class ::SkPDFTagTree; | 
|---|
| 101 |  | 
|---|
| 102 | std::unique_ptr<SkPDFArray> fAttrs; | 
|---|
| 103 | }; | 
|---|
| 104 |  | 
|---|
| 105 | /** A node in a PDF structure tree, giving a semantic representation | 
|---|
| 106 | of the content.  Each node ID is associated with content | 
|---|
| 107 | by passing the SkCanvas and node ID to SkPDF::SetNodeId() when drawing. | 
|---|
| 108 | NodeIDs should be unique within each tree. | 
|---|
| 109 | */ | 
|---|
| 110 | struct StructureElementNode { | 
|---|
| 111 | SkString fTypeString; | 
|---|
| 112 | std::vector<std::unique_ptr<StructureElementNode>> fChildVector; | 
|---|
| 113 | int fNodeId = 0; | 
|---|
| 114 | std::vector<int> fAdditionalNodeIds; | 
|---|
| 115 | AttributeList fAttributes; | 
|---|
| 116 | SkString fAlt; | 
|---|
| 117 | SkString fLang; | 
|---|
| 118 |  | 
|---|
| 119 | // Deprecated. Use fChildVector instead. | 
|---|
| 120 | StructureElementNode* fChildren = nullptr; | 
|---|
| 121 | size_t fChildCount = 0; | 
|---|
| 122 |  | 
|---|
| 123 | // Deprecated. Use fTypeString instead. | 
|---|
| 124 | DocumentStructureType fType = DocumentStructureType::kNonStruct; | 
|---|
| 125 | }; | 
|---|
| 126 |  | 
|---|
| 127 | /** Optional metadata to be passed into the PDF factory function. | 
|---|
| 128 | */ | 
|---|
| 129 | struct Metadata { | 
|---|
| 130 | /** The document's title. | 
|---|
| 131 | */ | 
|---|
| 132 | SkString fTitle; | 
|---|
| 133 |  | 
|---|
| 134 | /** The name of the person who created the document. | 
|---|
| 135 | */ | 
|---|
| 136 | SkString fAuthor; | 
|---|
| 137 |  | 
|---|
| 138 | /** The subject of the document. | 
|---|
| 139 | */ | 
|---|
| 140 | SkString fSubject; | 
|---|
| 141 |  | 
|---|
| 142 | /** Keywords associated with the document.  Commas may be used to delineate | 
|---|
| 143 | keywords within the string. | 
|---|
| 144 | */ | 
|---|
| 145 | SkString fKeywords; | 
|---|
| 146 |  | 
|---|
| 147 | /** If the document was converted to PDF from another format, | 
|---|
| 148 | the name of the conforming product that created the | 
|---|
| 149 | original document from which it was converted. | 
|---|
| 150 | */ | 
|---|
| 151 | SkString fCreator; | 
|---|
| 152 |  | 
|---|
| 153 | /** The product that is converting this document to PDF. | 
|---|
| 154 | */ | 
|---|
| 155 | SkString fProducer = SkString( "Skia/PDF m"SKPDF_STRING(SK_MILESTONE)); | 
|---|
| 156 |  | 
|---|
| 157 | /** The date and time the document was created. | 
|---|
| 158 | The zero default value represents an unknown/unset time. | 
|---|
| 159 | */ | 
|---|
| 160 | SkTime::DateTime fCreation = {0, 0, 0, 0, 0, 0, 0, 0}; | 
|---|
| 161 |  | 
|---|
| 162 | /** The date and time the document was most recently modified. | 
|---|
| 163 | The zero default value represents an unknown/unset time. | 
|---|
| 164 | */ | 
|---|
| 165 | SkTime::DateTime fModified = {0, 0, 0, 0, 0, 0, 0, 0}; | 
|---|
| 166 |  | 
|---|
| 167 | /** The DPI (pixels-per-inch) at which features without native PDF support | 
|---|
| 168 | will be rasterized (e.g. draw image with perspective, draw text with | 
|---|
| 169 | perspective, ...)  A larger DPI would create a PDF that reflects the | 
|---|
| 170 | original intent with better fidelity, but it can make for larger PDF | 
|---|
| 171 | files too, which would use more memory while rendering, and it would be | 
|---|
| 172 | slower to be processed or sent online or to printer. | 
|---|
| 173 | */ | 
|---|
| 174 | SkScalar fRasterDPI = SK_ScalarDefaultRasterDPI; | 
|---|
| 175 |  | 
|---|
| 176 | /** If true, include XMP metadata, a document UUID, and sRGB output intent | 
|---|
| 177 | information.  This adds length to the document and makes it | 
|---|
| 178 | non-reproducable, but are necessary features for PDF/A-2b conformance | 
|---|
| 179 | */ | 
|---|
| 180 | bool fPDFA = false; | 
|---|
| 181 |  | 
|---|
| 182 | /** Encoding quality controls the trade-off between size and quality. By | 
|---|
| 183 | default this is set to 101 percent, which corresponds to lossless | 
|---|
| 184 | encoding. If this value is set to a value <= 100, and the image is | 
|---|
| 185 | opaque, it will be encoded (using JPEG) with that quality setting. | 
|---|
| 186 | */ | 
|---|
| 187 | int fEncodingQuality = 101; | 
|---|
| 188 |  | 
|---|
| 189 | /** An optional tree of structured document tags that provide | 
|---|
| 190 | a semantic representation of the content. The caller | 
|---|
| 191 | should retain ownership. | 
|---|
| 192 | */ | 
|---|
| 193 | StructureElementNode* fStructureElementTreeRoot = nullptr; | 
|---|
| 194 |  | 
|---|
| 195 | /** Executor to handle threaded work within PDF Backend. If this is nullptr, | 
|---|
| 196 | then all work will be done serially on the main thread. To have worker | 
|---|
| 197 | threads assist with various tasks, set this to a valid SkExecutor | 
|---|
| 198 | instance. Currently used for executing Deflate algorithm in parallel. | 
|---|
| 199 |  | 
|---|
| 200 | If set, the PDF output will be non-reproducible in the order and | 
|---|
| 201 | internal numbering of objects, but should render the same. | 
|---|
| 202 |  | 
|---|
| 203 | Experimental. | 
|---|
| 204 | */ | 
|---|
| 205 | SkExecutor* fExecutor = nullptr; | 
|---|
| 206 |  | 
|---|
| 207 | /** Preferred Subsetter. Only respected if both are compiled in. | 
|---|
| 208 |  | 
|---|
| 209 | The Sfntly subsetter is deprecated. | 
|---|
| 210 |  | 
|---|
| 211 | Experimental. | 
|---|
| 212 | */ | 
|---|
| 213 | enum Subsetter { | 
|---|
| 214 | kHarfbuzz_Subsetter, | 
|---|
| 215 | kSfntly_Subsetter, | 
|---|
| 216 | } fSubsetter = kHarfbuzz_Subsetter; | 
|---|
| 217 | }; | 
|---|
| 218 |  | 
|---|
| 219 | /** Associate a node ID with subsequent drawing commands in an | 
|---|
| 220 | SkCanvas.  The same node ID can appear in a StructureElementNode | 
|---|
| 221 | in order to associate a document's structure element tree with | 
|---|
| 222 | its content. | 
|---|
| 223 |  | 
|---|
| 224 | A node ID of zero indicates no node ID. | 
|---|
| 225 |  | 
|---|
| 226 | @param canvas  The canvas used to draw to the PDF. | 
|---|
| 227 | @param nodeId  The node ID for subsequent drawing commands. | 
|---|
| 228 | */ | 
|---|
| 229 | SK_API void SetNodeId(SkCanvas* dst, int nodeID); | 
|---|
| 230 |  | 
|---|
| 231 | /** Create a PDF-backed document, writing the results into a SkWStream. | 
|---|
| 232 |  | 
|---|
| 233 | PDF pages are sized in point units. 1 pt == 1/72 inch == 127/360 mm. | 
|---|
| 234 |  | 
|---|
| 235 | @param stream A PDF document will be written to this stream.  The document may write | 
|---|
| 236 | to the stream at anytime during its lifetime, until either close() is | 
|---|
| 237 | called or the document is deleted. | 
|---|
| 238 | @param metadata a PDFmetadata object.  Any fields may be left empty. | 
|---|
| 239 |  | 
|---|
| 240 | @returns NULL if there is an error, otherwise a newly created PDF-backed SkDocument. | 
|---|
| 241 | */ | 
|---|
| 242 | SK_API sk_sp<SkDocument> MakeDocument(SkWStream* stream, const Metadata& metadata); | 
|---|
| 243 |  | 
|---|
| 244 | static inline sk_sp<SkDocument> MakeDocument(SkWStream* stream) { | 
|---|
| 245 | return MakeDocument(stream, Metadata()); | 
|---|
| 246 | } | 
|---|
| 247 |  | 
|---|
| 248 | }  // namespace SkPDF | 
|---|
| 249 |  | 
|---|
| 250 | #undef SKPDF_STRING | 
|---|
| 251 | #undef SKPDF_STRING_IMPL | 
|---|
| 252 | #endif  // SkPDFDocument_DEFINED | 
|---|
| 253 |  | 
|---|