Flutter Engine
The Flutter Engine
SkPDFTypes.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
16#include "src/base/SkUTF.h"
17#include "src/base/SkUtils.h"
19#include "src/pdf/SkDeflate.h"
21#include "src/pdf/SkPDFUnion.h"
22#include "src/pdf/SkPDFUtils.h"
23
24#include <cstring>
25#include <functional>
26#include <new>
27
28////////////////////////////////////////////////////////////////////////////////
29
30SkPDFUnion::SkPDFUnion(Type t, int32_t v) : fIntValue (v) , fType(t) {}
31SkPDFUnion::SkPDFUnion(Type t, bool v) : fBoolValue (v) , fType(t) {}
32SkPDFUnion::SkPDFUnion(Type t, SkScalar v) : fScalarValue (v) , fType(t) {}
33SkPDFUnion::SkPDFUnion(Type t, const char* v) : fStaticString (v) , fType(t) {}
34SkPDFUnion::SkPDFUnion(Type t, SkString v) : fSkString(std::move(v)), fType(t) {}
35SkPDFUnion::SkPDFUnion(Type t, PDFObject v) : fObject (std::move(v)), fType(t) {}
36
38 switch (fType) {
39 case Type::kNameSkS:
40 case Type::kByteStringSkS:
41 case Type::kTextStringSkS:
43 return;
44 case Type::kObject:
45 fObject.~PDFObject();
46 return;
47 default:
48 return;
49 }
50}
51
52SkPDFUnion::SkPDFUnion(SkPDFUnion&& that) : fType(that.fType) {
53 SkASSERT(this != &that);
54
55 switch (fType) {
56 case Type::kDestroyed:
57 break;
58 case Type::kInt:
59 case Type::kColorComponent:
60 case Type::kRef:
61 fIntValue = that.fIntValue;
62 break;
63 case Type::kBool:
64 fBoolValue = that.fBoolValue;
65 break;
66 case Type::kColorComponentF:
67 case Type::kScalar:
68 fScalarValue = that.fScalarValue;
69 break;
70 case Type::kName:
71 case Type::kByteString:
72 case Type::kTextString:
73 fStaticString = that.fStaticString;
74 break;
75 case Type::kNameSkS:
76 case Type::kByteStringSkS:
77 case Type::kTextStringSkS:
78 new (&fSkString) SkString(std::move(that.fSkString));
79 break;
80 case Type::kObject:
81 new (&fObject) PDFObject(std::move(that.fObject));
82 break;
83 default:
84 SkDEBUGFAIL("SkPDFUnion::SkPDFUnion with bad type");
85 }
86 that.fType = Type::kDestroyed;
87}
88
90 if (this != &that) {
91 this->~SkPDFUnion();
92 new (this) SkPDFUnion(std::move(that));
93 }
94 return *this;
95}
96
97bool SkPDFUnion::isName() const {
98 return Type::kName == fType || Type::kNameSkS == fType;
99}
100
101#ifdef SK_DEBUG
102// Most names need no escaping. Such names are handled as static const strings.
103bool is_valid_name(const char* n) {
104 static const char kControlChars[] = "/%()<>[]{}";
105 while (*n) {
106 if (*n < '!' || *n > '~' || strchr(kControlChars, *n)) {
107 return false;
108 }
109 ++n;
110 }
111 return true;
112}
113#endif // SK_DEBUG
114
115// Given an arbitrary string, write it as a valid name (not including leading slash).
116static void write_name_escaped(SkWStream* o, const char* name) {
117 static const char kToEscape[] = "#/%()<>[]{}";
118 for (const uint8_t* n = reinterpret_cast<const uint8_t*>(name); *n; ++n) {
119 uint8_t v = *n;
120 if (v < '!' || v > '~' || strchr(kToEscape, v)) {
121 char buffer[3] = {'#',
124 o->write(buffer, sizeof(buffer));
125 } else {
126 o->write(n, 1);
127 }
128 }
129}
130
131static void write_literal_byte_string(SkWStream* wStream, const char* cin, size_t len) {
132 wStream->writeText("(");
133 for (size_t i = 0; i < len; i++) {
134 uint8_t c = static_cast<uint8_t>(cin[i]);
135 if (c < ' ' || '~' < c) {
136 uint8_t octal[4] = { '\\',
137 (uint8_t)('0' | ( c >> 6 )),
138 (uint8_t)('0' | ((c >> 3) & 0x07)),
139 (uint8_t)('0' | ( c & 0x07)) };
140 wStream->write(octal, 4);
141 } else {
142 if (c == '\\' || c == '(' || c == ')') {
143 wStream->writeText("\\");
144 }
145 wStream->write(&c, 1);
146 }
147 }
148 wStream->writeText(")");
149}
150
151static void write_hex_byte_string(SkWStream* wStream, const char* cin, size_t len) {
152 SkDEBUGCODE(static const size_t kMaxLen = 65535;)
153 SkASSERT(len <= kMaxLen);
154
155 wStream->writeText("<");
156 for (size_t i = 0; i < len; i++) {
157 uint8_t c = static_cast<uint8_t>(cin[i]);
158 char hexValue[2] = { SkHexadecimalDigits::gUpper[c >> 4],
160 wStream->write(hexValue, 2);
161 }
162 wStream->writeText(">");
163}
164
165static void write_optimized_byte_string(SkWStream* wStream, const char* cin, size_t len,
166 size_t literalExtras) {
167 const size_t hexLength = 2 + 2*len;
168 const size_t literalLength = 2 + len + literalExtras;
169 if (literalLength <= hexLength) {
170 write_literal_byte_string(wStream, cin, len);
171 } else {
172 write_hex_byte_string(wStream, cin, len);
173 }
174}
175
176static void write_byte_string(SkWStream* wStream, const char* cin, size_t len) {
177 SkDEBUGCODE(static const size_t kMaxLen = 65535;)
178 SkASSERT(len <= kMaxLen);
179
180 size_t literalExtras = 0;
181 {
182 for (size_t i = 0; i < len; i++) {
183 uint8_t c = static_cast<uint8_t>(cin[i]);
184 if (c < ' ' || '~' < c) {
185 literalExtras += 3;
186 } else if (c == '\\' || c == '(' || c == ')') {
187 ++literalExtras;
188 }
189 }
190 }
191 write_optimized_byte_string(wStream, cin, len, literalExtras);
192}
193
194static void write_text_string(SkWStream* wStream, const char* cin, size_t len) {
195 SkDEBUGCODE(static const size_t kMaxLen = 65535;)
196 SkASSERT(len <= kMaxLen);
197
198 bool inputIsValidUTF8 = true;
199 bool inputIsPDFDocEncoding = true;
200 size_t literalExtras = 0;
201 {
202 const char* textPtr = cin;
203 const char* textEnd = cin + len;
204 while (textPtr < textEnd) {
205 SkUnichar unichar = SkUTF::NextUTF8(&textPtr, textEnd);
206 if (unichar < 0) {
207 inputIsValidUTF8 = false;
208 break;
209 }
210 // See Table D.2 (PDFDocEncoding Character Set) in the PDF3200_2008 spec.
211 // Could convert from UTF-8 to PDFDocEncoding and, if successful, use that.
212 if ((0x15 < unichar && unichar < 0x20) || 0x7E < unichar) {
213 inputIsPDFDocEncoding = false;
214 break;
215 }
216 if (unichar < ' ' || '~' < unichar) {
217 literalExtras += 3;
218 } else if (unichar == '\\' || unichar == '(' || unichar == ')') {
219 ++literalExtras;
220 }
221 }
222 }
223
224 if (!inputIsValidUTF8) {
225 SkDebugf("Invalid UTF8: %.*s\n", (int)len, cin);
226 wStream->writeText("<>");
227 return;
228 }
229
230 if (inputIsPDFDocEncoding) {
231 write_optimized_byte_string(wStream, cin, len, literalExtras);
232 return;
233 }
234
235 wStream->writeText("<FEFF");
236 const char* textPtr = cin;
237 const char* textEnd = cin + len;
238 while (textPtr < textEnd) {
239 SkUnichar unichar = SkUTF::NextUTF8(&textPtr, textEnd);
240 SkPDFUtils::WriteUTF16beHex(wStream, unichar);
241 }
242 wStream->writeText(">");
243}
244
245void SkPDFWriteTextString(SkWStream* wStream, const char* cin, size_t len) {
246 write_text_string(wStream, cin, len);
247}
248void SkPDFWriteByteString(SkWStream* wStream, const char* cin, size_t len) {
249 write_byte_string(wStream, cin, len);
250}
251
253 switch (fType) {
254 case Type::kInt:
255 stream->writeDecAsText(fIntValue);
256 return;
257 case Type::kColorComponent:
259 return;
260 case Type::kColorComponentF:
262 return;
263 case Type::kBool:
264 stream->writeText(fBoolValue ? "true" : "false");
265 return;
266 case Type::kScalar:
268 return;
269 case Type::kName:
270 stream->writeText("/");
272 stream->writeText(fStaticString);
273 return;
274 case Type::kByteString:
277 return;
278 case Type::kTextString:
281 return;
282 case Type::kNameSkS:
283 stream->writeText("/");
285 return;
286 case Type::kByteStringSkS:
288 return;
289 case Type::kTextStringSkS:
291 return;
292 case Type::kObject:
293 fObject->emitObject(stream);
294 return;
295 case Type::kRef:
296 SkASSERT(fIntValue >= 0);
297 stream->writeDecAsText(fIntValue);
298 stream->writeText(" 0 R"); // Generation number is always 0.
299 return;
300 default:
301 SkDEBUGFAIL("SkPDFUnion::emitObject with bad type");
302 }
303}
304
306 return SkPDFUnion(Type::kInt, value);
307}
308
310 return SkPDFUnion(Type::kColorComponent, SkTo<int32_t>(value));
311}
312
314 return SkPDFUnion(Type::kColorComponentF, value);
315}
316
318 return SkPDFUnion(Type::kBool, value);
319}
320
322 return SkPDFUnion(Type::kScalar, value);
323}
324
328 return SkPDFUnion(Type::kName, value);
329}
330
333 return SkPDFUnion(Type::kByteString, value);
334}
335
338 return SkPDFUnion(Type::kTextString, value);
339}
340
342 return SkPDFUnion(Type::kNameSkS, std::move(s));
343}
344
346 return SkPDFUnion(Type::kByteStringSkS, std::move(s));
347}
348
350 return SkPDFUnion(Type::kTextStringSkS, std::move(s));
351}
352
353SkPDFUnion SkPDFUnion::Object(std::unique_ptr<SkPDFObject> objSp) {
354 SkASSERT(objSp.get());
355 return SkPDFUnion(Type::kObject, std::move(objSp));
356}
357
359 SkASSERT(ref.fValue > 0);
360 return SkPDFUnion(Type::kRef, SkTo<int32_t>(ref.fValue));
361}
362
363////////////////////////////////////////////////////////////////////////////////
364
365#if 0 // Enable if needed.
366void SkPDFAtom::emitObject(SkWStream* stream) const {
367 fValue.emitObject(stream);
368}
369#endif // 0
370
371////////////////////////////////////////////////////////////////////////////////
372
374
376
377size_t SkPDFArray::size() const { return fValues.size(); }
378
380 fValues.reserve(length);
381}
382
384 stream->writeText("[");
385 for (size_t i = 0; i < fValues.size(); i++) {
386 fValues[i].emitObject(stream);
387 if (i + 1 < fValues.size()) {
388 stream->writeText(" ");
389 }
390 }
391 stream->writeText("]");
392}
393
394void SkPDFArray::append(SkPDFUnion&& value) {
395 fValues.emplace_back(std::move(value));
396}
397
399 this->append(SkPDFUnion::Int(value));
400}
401
403 this->append(SkPDFUnion::ColorComponent(value));
404}
405
407 this->append(SkPDFUnion::Bool(value));
408}
409
411 this->append(SkPDFUnion::Scalar(value));
412}
413
414void SkPDFArray::appendName(const char name[]) {
415 this->append(SkPDFUnion::Name(SkString(name)));
416}
417
419 this->append(SkPDFUnion::Name(std::move(name)));
420}
421
423 this->append(SkPDFUnion::ByteString(std::move(value)));
424}
425
427 this->append(SkPDFUnion::TextString(std::move(value)));
428}
429
431 this->append(SkPDFUnion::ByteString(value));
432}
433
435 this->append(SkPDFUnion::TextString(value));
436}
437
438void SkPDFArray::appendObject(std::unique_ptr<SkPDFObject>&& objSp) {
439 this->append(SkPDFUnion::Object(std::move(objSp)));
440}
441
443 this->append(SkPDFUnion::Ref(ref));
444}
445
446///////////////////////////////////////////////////////////////////////////////
447
449
451 if (type) {
452 this->insertName("Type", type);
453 }
454}
455
457 stream->writeText("<<");
458 for (size_t i = 0; i < fRecords.size(); ++i) {
459 const std::pair<SkPDFUnion, SkPDFUnion>& record = fRecords[i];
460 record.first.emitObject(stream);
461 stream->writeText(" ");
462 record.second.emitObject(stream);
463 if (i + 1 < fRecords.size()) {
464 stream->writeText("\n");
465 }
466 }
467 stream->writeText(">>");
468}
469
470size_t SkPDFDict::size() const { return fRecords.size(); }
471
473 fRecords.reserve(n);
474}
475
477 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Ref(ref));
478}
479
481 fRecords.emplace_back(SkPDFUnion::Name(std::move(key)), SkPDFUnion::Ref(ref));
482}
483
484void SkPDFDict::insertObject(const char key[], std::unique_ptr<SkPDFObject>&& objSp) {
485 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Object(std::move(objSp)));
486}
487void SkPDFDict::insertObject(SkString key, std::unique_ptr<SkPDFObject>&& objSp) {
488 fRecords.emplace_back(SkPDFUnion::Name(std::move(key)),
489 SkPDFUnion::Object(std::move(objSp)));
490}
491
492void SkPDFDict::insertBool(const char key[], bool value) {
493 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Bool(value));
494}
495
496void SkPDFDict::insertInt(const char key[], int32_t value) {
497 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Int(value));
498}
499
500void SkPDFDict::insertInt(const char key[], size_t value) {
501 this->insertInt(key, SkToS32(value));
502}
503
505 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::ColorComponentF(value));
506}
507
509 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Scalar(value));
510}
511
512void SkPDFDict::insertName(const char key[], const char name[]) {
513 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Name(name));
514}
515
517 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Name(std::move(name)));
518}
519
520void SkPDFDict::insertByteString(const char key[], const char value[]) {
521 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::ByteString(value));
522}
523
524void SkPDFDict::insertTextString(const char key[], const char value[]) {
525 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::TextString(value));
526}
527
529 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::ByteString(std::move(value)));
530}
531
533 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::TextString(std::move(value)));
534}
535
537 fRecords.emplace_back(SkPDFUnion::Name(key), std::move(value));
538}
539
540////////////////////////////////////////////////////////////////////////////////
541
542
543
544static void serialize_stream(SkPDFDict* origDict,
547 SkPDFDocument* doc,
549 // Code assumes that the stream starts at the beginning.
550 SkASSERT(stream && stream->hasLength());
551
552 std::unique_ptr<SkStreamAsset> tmp;
553 SkPDFDict tmpDict;
554 SkPDFDict& dict = origDict ? *origDict : tmpDict;
555 static const size_t kMinimumSavings = strlen("/Filter_/FlateDecode_");
558 stream->getLength() > kMinimumSavings)
559 {
560 SkDynamicMemoryWStream compressedData;
561 SkDeflateWStream deflateWStream(&compressedData,SkToInt(doc->metadata().fCompressionLevel));
562 SkStreamCopy(&deflateWStream, stream);
563 deflateWStream.finalize();
564 #ifdef SK_PDF_BASE85_BINARY
565 {
566 SkPDFUtils::Base85Encode(compressedData.detachAsStream(), &compressedData);
567 tmp = compressedData.detachAsStream();
568 stream = tmp.get();
569 auto filters = SkPDFMakeArray();
570 filters->appendName("ASCII85Decode");
571 filters->appendName("FlateDecode");
572 dict.insertObject("Filter", std::move(filters));
573 }
574 #else
575 if (stream->getLength() > compressedData.bytesWritten() + kMinimumSavings) {
576 tmp = compressedData.detachAsStream();
577 stream = tmp.get();
578 dict.insertName("Filter", "FlateDecode");
579 } else {
580 SkAssertResult(stream->rewind());
581 }
582 #endif
583
584 }
585 dict.insertInt("Length", stream->getLength());
586 doc->emitStream(dict,
587 [stream](SkWStream* dst) { dst->writeStream(stream, stream->getLength()); },
588 ref);
589}
590
591SkPDFIndirectReference SkPDFStreamOut(std::unique_ptr<SkPDFDict> dict,
592 std::unique_ptr<SkStreamAsset> content,
593 SkPDFDocument* doc,
596 if (SkExecutor* executor = doc->executor()) {
597 SkPDFDict* dictPtr = dict.release();
598 SkStreamAsset* contentPtr = content.release();
599 // Pass ownership of both pointers into a std::function, which should
600 // only be executed once.
601 doc->incrementJobCount();
602 executor->add([dictPtr, contentPtr, compress, doc, ref]() {
603 serialize_stream(dictPtr, contentPtr, compress, doc, ref);
604 delete dictPtr;
605 delete contentPtr;
606 doc->signalJobComplete();
607 });
608 return ref;
609 }
610 serialize_stream(dict.get(), content.get(), compress, doc, ref);
611 return ref;
612}
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
static bool is_valid_name(const SkString &name)
#define SkDEBUGFAIL(message)
Definition: SkAssert.h:118
#define SkASSERT(cond)
Definition: SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static void write_byte_string(SkWStream *wStream, const char *cin, size_t len)
Definition: SkPDFTypes.cpp:176
static void write_optimized_byte_string(SkWStream *wStream, const char *cin, size_t len, size_t literalExtras)
Definition: SkPDFTypes.cpp:165
static void write_name_escaped(SkWStream *o, const char *name)
Definition: SkPDFTypes.cpp:116
void SkPDFWriteByteString(SkWStream *wStream, const char *cin, size_t len)
Definition: SkPDFTypes.cpp:248
static void write_hex_byte_string(SkWStream *wStream, const char *cin, size_t len)
Definition: SkPDFTypes.cpp:151
static void write_literal_byte_string(SkWStream *wStream, const char *cin, size_t len)
Definition: SkPDFTypes.cpp:131
static void write_text_string(SkWStream *wStream, const char *cin, size_t len)
Definition: SkPDFTypes.cpp:194
void SkPDFWriteTextString(SkWStream *wStream, const char *cin, size_t len)
Definition: SkPDFTypes.cpp:245
static void serialize_stream(SkPDFDict *origDict, SkStreamAsset *stream, SkPDFSteamCompressionEnabled compress, SkPDFDocument *doc, SkPDFIndirectReference ref)
Definition: SkPDFTypes.cpp:544
SkPDFIndirectReference SkPDFStreamOut(std::unique_ptr< SkPDFDict > dict, std::unique_ptr< SkStreamAsset > content, SkPDFDocument *doc, SkPDFSteamCompressionEnabled compress)
Definition: SkPDFTypes.cpp:591
static std::unique_ptr< SkPDFArray > SkPDFMakeArray(Args... args)
Definition: SkPDFTypes.h:125
SkPDFSteamCompressionEnabled
Definition: SkPDFTypes.h:189
bool SkStreamCopy(SkWStream *out, SkStream *input)
Definition: SkStream.cpp:954
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
constexpr int32_t SkToS32(S x)
Definition: SkTo.h:25
constexpr int SkToInt(S x)
Definition: SkTo.h:29
constexpr uint8_t SkToU8(S x)
Definition: SkTo.h:22
int32_t SkUnichar
Definition: SkTypes.h:175
GLenum type
size_t bytesWritten() const override
Definition: SkStream.cpp:526
std::unique_ptr< SkStreamAsset > detachAsStream()
Definition: SkStream.cpp:876
size_t size() const
Definition: SkPDFTypes.cpp:377
void appendRef(SkPDFIndirectReference)
Definition: SkPDFTypes.cpp:442
void reserve(int length)
Definition: SkPDFTypes.cpp:379
void appendTextString(const char[])
Definition: SkPDFTypes.cpp:434
~SkPDFArray() override
Definition: SkPDFTypes.cpp:375
void appendInt(int32_t)
Definition: SkPDFTypes.cpp:398
void appendByteString(const char[])
Definition: SkPDFTypes.cpp:430
void appendObject(std::unique_ptr< SkPDFObject > &&)
Definition: SkPDFTypes.cpp:438
void appendBool(bool)
Definition: SkPDFTypes.cpp:406
void appendColorComponent(uint8_t)
Definition: SkPDFTypes.cpp:402
void appendName(const char[])
Definition: SkPDFTypes.cpp:414
void appendScalar(SkScalar)
Definition: SkPDFTypes.cpp:410
void emitObject(SkWStream *stream) const override
Definition: SkPDFTypes.cpp:383
void reserve(int n)
Definition: SkPDFTypes.cpp:472
void insertName(const char key[], const char nameValue[])
Definition: SkPDFTypes.cpp:512
void insertObject(const char key[], std::unique_ptr< SkPDFObject > &&)
Definition: SkPDFTypes.cpp:484
~SkPDFDict() override
Definition: SkPDFTypes.cpp:448
void insertColorComponentF(const char key[], SkScalar value)
Definition: SkPDFTypes.cpp:504
void insertUnion(const char key[], SkPDFUnion &&)
Definition: SkPDFTypes.cpp:536
void insertInt(const char key[], int32_t value)
Definition: SkPDFTypes.cpp:496
void insertTextString(const char key[], const char value[])
Definition: SkPDFTypes.cpp:524
void insertRef(const char key[], SkPDFIndirectReference)
Definition: SkPDFTypes.cpp:476
void insertScalar(const char key[], SkScalar value)
Definition: SkPDFTypes.cpp:508
void insertByteString(const char key[], const char value[])
Definition: SkPDFTypes.cpp:520
size_t size() const
Definition: SkPDFTypes.cpp:470
void emitObject(SkWStream *stream) const override
Definition: SkPDFTypes.cpp:456
void insertBool(const char key[], bool value)
Definition: SkPDFTypes.cpp:492
SkPDFDict(const char type[]=nullptr)
Definition: SkPDFTypes.cpp:450
SkExecutor * executor() const
void signalJobComplete()
const SkPDF::Metadata & metadata() const
void incrementJobCount()
void emitStream(const SkPDFDict &dict, T writeStream, SkPDFIndirectReference ref)
SkPDFIndirectReference reserveRef()
int32_t fIntValue
Definition: SkPDFUnion.h:84
static SkPDFUnion Ref(SkPDFIndirectReference)
Definition: SkPDFTypes.cpp:358
static SkPDFUnion ColorComponentF(float)
Definition: SkPDFTypes.cpp:313
SkPDFUnion(SkPDFUnion &&)
Definition: SkPDFTypes.cpp:52
SkScalar fScalarValue
Definition: SkPDFUnion.h:86
static SkPDFUnion Bool(bool)
Definition: SkPDFTypes.cpp:317
static SkPDFUnion Int(int32_t)
Definition: SkPDFTypes.cpp:305
static SkPDFUnion TextString(const char *)
Definition: SkPDFTypes.cpp:336
PDFObject fObject
Definition: SkPDFUnion.h:89
void emitObject(SkWStream *) const
Definition: SkPDFTypes.cpp:252
static SkPDFUnion ByteString(const char *)
Definition: SkPDFTypes.cpp:331
static SkPDFUnion Object(std::unique_ptr< SkPDFObject >)
Definition: SkPDFTypes.cpp:353
SkPDFUnion & operator=(SkPDFUnion &&)
Definition: SkPDFTypes.cpp:89
static SkPDFUnion Name(const char *)
Definition: SkPDFTypes.cpp:325
const char * fStaticString
Definition: SkPDFUnion.h:87
SkString fSkString
Definition: SkPDFUnion.h:88
bool fBoolValue
Definition: SkPDFUnion.h:85
bool isName() const
Definition: SkPDFTypes.cpp:97
static SkPDFUnion Scalar(SkScalar)
Definition: SkPDFTypes.cpp:321
static SkPDFUnion ColorComponent(uint8_t)
Definition: SkPDFTypes.cpp:309
size_t size() const
Definition: SkString.h:131
const char * c_str() const
Definition: SkString.h:133
virtual bool write(const void *buffer, size_t size)=0
bool writeText(const char text[])
Definition: SkStream.h:247
float SkScalar
Definition: extension.cpp:12
struct MyStruct s
uint8_t value
size_t length
union flutter::testing::@2836::KeyboardChange::@76 content
const char gUpper[16]
Definition: SkUtils.cpp:10
void AppendColorComponent(uint8_t value, SkWStream *wStream)
Definition: SkPDFUtils.h:87
void AppendScalar(SkScalar value, SkWStream *stream)
Definition: SkPDFUtils.h:98
void AppendColorComponentF(float value, SkWStream *wStream)
Definition: SkPDFUtils.h:92
void WriteUTF16beHex(SkWStream *wStream, SkUnichar utf32)
Definition: SkPDFUtils.h:119
SK_SPI SkUnichar NextUTF8(const char **ptr, const char *end)
Definition: SkUTF.cpp:118
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
dst
Definition: cp.py:12
Definition: ref_ptr.h:256
enum SkPDF::Metadata::CompressionLevel fCompressionLevel