blob: 11f4310944f4df3b1400d5e528522546612298f1 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2011 Google Inc.
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +00004 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +00007 */
8
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +00009#include "SkPDFTypes.h"
10#include "SkStream.h"
11
vandebo@chromium.org094316b2011-03-04 03:15:13 +000012#ifdef SK_BUILD_FOR_WIN
13 #define SNPRINTF _snprintf
14#else
15 #define SNPRINTF snprintf
16#endif
17
halcanary6a144342015-01-23 11:45:10 -080018////////////////////////////////////////////////////////////////////////////////
19
halcanary130444f2015-04-25 06:45:07 -070020SkString* pun(char* x) { return reinterpret_cast<SkString*>(x); }
21const SkString* pun(const char* x) {
22 return reinterpret_cast<const SkString*>(x);
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +000023}
24
halcanary130444f2015-04-25 06:45:07 -070025SkPDFUnion::SkPDFUnion(Type t) : fType(t) {}
vandebo@chromium.org421d6442011-07-20 17:39:01 +000026
halcanary130444f2015-04-25 06:45:07 -070027SkPDFUnion::~SkPDFUnion() {
28 switch (fType) {
29 case Type::kNameSkS:
30 case Type::kStringSkS:
31 pun(fSkString)->~SkString();
32 return;
33 case Type::kObjRef:
34 case Type::kObject:
35 SkSafeUnref(fObject);
36 return;
37 default:
38 return;
halcanarybf799cd2015-02-10 13:32:09 -080039 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000040}
41
halcanary130444f2015-04-25 06:45:07 -070042SkPDFUnion& SkPDFUnion::operator=(SkPDFUnion&& other) {
43 if (this != &other) {
44 this->~SkPDFUnion();
45 SkNEW_PLACEMENT_ARGS(this, SkPDFUnion, (other.move()));
46 }
47 return *this;
48}
halcanary6a144342015-01-23 11:45:10 -080049
halcanary130444f2015-04-25 06:45:07 -070050SkPDFUnion::SkPDFUnion(SkPDFUnion&& other) {
51 SkASSERT(this != &other);
52 memcpy(this, &other, sizeof(*this));
53 other.fType = Type::kDestroyed;
54}
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +000055
halcanary130444f2015-04-25 06:45:07 -070056#if 0
57SkPDFUnion SkPDFUnion::copy() const {
58 SkPDFUnion u(fType);
59 memcpy(&u, this, sizeof(u));
60 switch (fType) {
61 case Type::kNameSkS:
62 case Type::kStringSkS:
63 SkNEW_PLACEMENT_ARGS(pun(u.fSkString), SkString,
64 (*pun(fSkString)));
65 return u.move();
66 case Type::kObjRef:
67 case Type::kObject:
68 SkRef(u.fObject);
69 return u.move();
70 default:
71 return u.move();
72 }
73}
74SkPDFUnion& SkPDFUnion::operator=(const SkPDFUnion& other) {
75 return *this = other.copy();
76}
77SkPDFUnion::SkPDFUnion(const SkPDFUnion& other) {
78 *this = other.copy();
79}
80#endif
81
82bool SkPDFUnion::isName() const {
83 return Type::kName == fType || Type::kNameSkS == fType;
84}
85
86#ifdef SK_DEBUG
87// Most names need no escaping. Such names are handled as static
88// const strings.
89bool is_valid_name(const char* n) {
90 static const char kControlChars[] = "/%()<>[]{}";
91 while (*n) {
92 if (*n < '!' || *n > '~' || strchr(kControlChars, *n)) {
93 return false;
94 }
95 ++n;
96 }
97 return true;
98}
99#endif // SK_DEBUG
100
101// Given an arbitrary string, convert it to a valid name.
102static SkString escape_name(const char* name, size_t len) {
103 static const char kToEscape[] = "#/%()<>[]{}";
104 int count = 0;
105 const char* const end = &name[len];
106 for (const char* n = name; n != end; ++n) {
107 if (*n < '!' || *n > '~' || strchr(kToEscape, *n)) {
108 count += 2;
109 }
110 ++count;
111 }
112 SkString result(count);
113 char* s = result.writable_str();
114 static const char kHex[] = "0123456789ABCDEF";
115 for (const char* n = name; n != end; ++n) {
116 if (*n < '!' || *n > '~' || strchr(kToEscape, *n)) {
117 *s++ = '#';
118 *s++ = kHex[(*n >> 4) & 0xF];
119 *s++ = kHex[*n & 0xF];
120 } else {
121 *s++ = *n;
122 }
123 }
124 SkASSERT(&result.writable_str()[count] == s); // don't over-write
125 return result; // allocated space
126}
127
128static SkString escape_name(const SkString& name) {
129 return escape_name(name.c_str(), name.size());
130}
131
132static void write_string(SkWStream* o, const SkString& s) {
133 o->write(s.c_str(), s.size());
134}
135
136static SkString format_string(const SkString& s) {
137 return SkPDFString::FormatString(s.c_str(), s.size());
138}
139
140static SkString format_string(const char* s) {
141 return SkPDFString::FormatString(s, strlen(s));
142}
143
144void SkPDFUnion::emitObject(SkWStream* stream,
145 const SkPDFObjNumMap& objNumMap,
146 const SkPDFSubstituteMap& substitutes) const {
147 switch (fType) {
148 case Type::kInt:
149 stream->writeDecAsText(fIntValue);
150 return;
151 case Type::kBool:
152 stream->writeText(fBoolValue ? "true" : "false");
153 return;
154 case Type::kScalar:
155 SkPDFScalar::Append(fScalarValue, stream);
156 return;
157 case Type::kName:
158 stream->writeText("/");
159 SkASSERT(is_valid_name(fStaticString));
160 stream->writeText(fStaticString);
161 return;
162 case Type::kString:
163 SkASSERT(fStaticString);
164 write_string(stream, format_string(fStaticString));
165 return;
166 case Type::kNameSkS:
167 stream->writeText("/");
168 write_string(stream, escape_name(*pun(fSkString)));
169 return;
170 case Type::kStringSkS:
171 write_string(stream, format_string(*pun(fSkString)));
172 return;
173 case Type::kObjRef:
174 stream->writeDecAsText(objNumMap.getObjectNumber(
175 substitutes.getSubstitute(fObject)));
176 stream->writeText(" 0 R"); // Generation number is always 0.
177 return;
178 case Type::kObject:
179 fObject->emitObject(stream, objNumMap, substitutes);
180 return;
181 default:
182 SkDEBUGFAIL("SkPDFUnion::emitObject with bad type");
183 }
184}
185
186void SkPDFUnion::addResources(SkPDFObjNumMap* objNumMap,
187 const SkPDFSubstituteMap& substituteMap) const {
188 switch (fType) {
189 case Type::kInt:
190 case Type::kBool:
191 case Type::kScalar:
192 case Type::kName:
193 case Type::kString:
194 case Type::kNameSkS:
195 case Type::kStringSkS:
196 return; // These have no resources.
197 case Type::kObjRef: {
198 SkPDFObject* obj = substituteMap.getSubstitute(fObject);
199 if (objNumMap->addObject(obj)) {
200 obj->addResources(objNumMap, substituteMap);
201 }
202 return;
203 }
204 case Type::kObject:
205 fObject->addResources(objNumMap, substituteMap);
206 return;
207 default:
208 SkDEBUGFAIL("SkPDFUnion::addResources with bad type");
209 }
210}
211
212SkPDFUnion SkPDFUnion::Int(int32_t value) {
213 SkPDFUnion u(Type::kInt);
214 u.fIntValue = value;
215 return u.move();
216}
217
218SkPDFUnion SkPDFUnion::Bool(bool value) {
219 SkPDFUnion u(Type::kBool);
220 u.fBoolValue = value;
221 return u.move();
222}
223
224SkPDFUnion SkPDFUnion::Scalar(SkScalar value) {
225 SkPDFUnion u(Type::kScalar);
226 u.fScalarValue = value;
227 return u.move();
228}
229
230SkPDFUnion SkPDFUnion::Name(const char* value) {
231 SkPDFUnion u(Type::kName);
232 SkASSERT(value);
233 SkASSERT(is_valid_name(value));
234 u.fStaticString = value;
235 return u.move();
236}
237
238SkPDFUnion SkPDFUnion::String(const char* value) {
239 SkPDFUnion u(Type::kString);
240 SkASSERT(value);
241 u.fStaticString = value;
242 return u.move();
243}
244
245SkPDFUnion SkPDFUnion::Name(const SkString& s) {
246 SkPDFUnion u(Type::kNameSkS);
247 SkNEW_PLACEMENT_ARGS(pun(u.fSkString), SkString, (s));
248 return u.move();
249}
250
251SkPDFUnion SkPDFUnion::String(const SkString& s) {
252 SkPDFUnion u(Type::kStringSkS);
253 SkNEW_PLACEMENT_ARGS(pun(u.fSkString), SkString, (s));
254 return u.move();
255}
256
257SkPDFUnion SkPDFUnion::ObjRef(SkPDFObject* ptr) {
258 SkPDFUnion u(Type::kObjRef);
259 SkASSERT(ptr);
260 u.fObject = ptr;
261 return u.move();
262}
263
264SkPDFUnion SkPDFUnion::Object(SkPDFObject* ptr) {
265 SkPDFUnion u(Type::kObject);
266 SkASSERT(ptr);
267 u.fObject = ptr;
268 return u.move();
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000269}
270
halcanary6a144342015-01-23 11:45:10 -0800271////////////////////////////////////////////////////////////////////////////////
272
halcanary130444f2015-04-25 06:45:07 -0700273void SkPDFAtom::emitObject(SkWStream* stream,
274 const SkPDFObjNumMap& objNumMap,
275 const SkPDFSubstituteMap& substitutes) {
276 fValue.emitObject(stream, objNumMap, substitutes);
277}
278void SkPDFAtom::addResources(SkPDFObjNumMap* map,
279 const SkPDFSubstituteMap& substitutes) const {
280 fValue.addResources(map, substitutes);
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000281}
282
halcanary6a144342015-01-23 11:45:10 -0800283////////////////////////////////////////////////////////////////////////////////
284
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000285// static
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000286void SkPDFScalar::Append(SkScalar value, SkWStream* stream) {
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000287 // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and
288 // +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31).
289 // When using floats that are outside the whole value range, we can use
290 // integers instead.
291
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000292#if !defined(SK_ALLOW_LARGE_PDF_SCALARS)
293 if (value > 32767 || value < -32767) {
reed@google.come1ca7052013-12-17 19:22:07 +0000294 stream->writeDecAsText(SkScalarRoundToInt(value));
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000295 return;
296 }
297
298 char buffer[SkStrAppendScalar_MaxSize];
299 char* end = SkStrAppendFixed(buffer, SkScalarToFixed(value));
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000300 stream->write(buffer, end - buffer);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000301 return;
302#endif // !SK_ALLOW_LARGE_PDF_SCALARS
303
reed@google.com8f4d2302013-12-17 16:44:46 +0000304#if defined(SK_ALLOW_LARGE_PDF_SCALARS)
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000305 // Floats have 24bits of significance, so anything outside that range is
306 // no more precise than an int. (Plus PDF doesn't support scientific
307 // notation, so this clamps to SK_Max/MinS32).
308 if (value > (1 << 24) || value < -(1 << 24)) {
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000309 stream->writeDecAsText(value);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000310 return;
311 }
312 // Continue to enforce the PDF limits for small floats.
313 if (value < 1.0f/65536 && value > -1.0f/65536) {
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000314 stream->writeDecAsText(0);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000315 return;
316 }
317 // SkStrAppendFloat might still use scientific notation, so use snprintf
318 // directly..
319 static const int kFloat_MaxSize = 19;
320 char buffer[kFloat_MaxSize];
321 int len = SNPRINTF(buffer, kFloat_MaxSize, "%#.8f", value);
322 // %f always prints trailing 0s, so strip them.
323 for (; buffer[len - 1] == '0' && len > 0; len--) {
324 buffer[len - 1] = '\0';
325 }
326 if (buffer[len - 1] == '.') {
327 buffer[len - 1] = '\0';
328 }
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000329 stream->writeText(buffer);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000330 return;
reed@google.com8f4d2302013-12-17 16:44:46 +0000331#endif // SK_ALLOW_LARGE_PDF_SCALARS
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000332}
333
halcanary6a144342015-01-23 11:45:10 -0800334////////////////////////////////////////////////////////////////////////////////
335
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000336// static
halcanary130444f2015-04-25 06:45:07 -0700337
halcanarybb264b72015-04-07 10:40:03 -0700338SkString SkPDFString::FormatString(const char* cin, size_t len) {
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000339 SkASSERT(len <= kMaxLen);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000340
341 // 7-bit clean is a heuristic to decide what string format to use;
342 // a 7-bit clean string should require little escaping.
343 bool sevenBitClean = true;
halcanarybb264b72015-04-07 10:40:03 -0700344 size_t characterCount = 2 + len;
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000345 for (size_t i = 0; i < len; i++) {
halcanarybb264b72015-04-07 10:40:03 -0700346 if (cin[i] > '~' || cin[i] < ' ') {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000347 sevenBitClean = false;
348 break;
349 }
halcanarybb264b72015-04-07 10:40:03 -0700350 if (cin[i] == '\\' || cin[i] == '(' || cin[i] == ')') {
351 ++characterCount;
352 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000353 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000354 SkString result;
355 if (sevenBitClean) {
halcanarybb264b72015-04-07 10:40:03 -0700356 result.resize(characterCount);
357 char* str = result.writable_str();
358 *str++ = '(';
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000359 for (size_t i = 0; i < len; i++) {
halcanarybb264b72015-04-07 10:40:03 -0700360 if (cin[i] == '\\' || cin[i] == '(' || cin[i] == ')') {
361 *str++ = '\\';
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000362 }
halcanarybb264b72015-04-07 10:40:03 -0700363 *str++ = cin[i];
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000364 }
halcanarybb264b72015-04-07 10:40:03 -0700365 *str++ = ')';
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000366 } else {
halcanarybb264b72015-04-07 10:40:03 -0700367 result.resize(2 * len + 2);
368 char* str = result.writable_str();
369 *str++ = '<';
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000370 for (size_t i = 0; i < len; i++) {
halcanarybb264b72015-04-07 10:40:03 -0700371 uint8_t c = static_cast<uint8_t>(cin[i]);
372 static const char gHex[] = "0123456789ABCDEF";
373 *str++ = gHex[(c >> 4) & 0xF];
374 *str++ = gHex[(c ) & 0xF];
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000375 }
halcanarybb264b72015-04-07 10:40:03 -0700376 *str++ = '>';
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000377 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000378 return result;
379}
380
halcanary6a144342015-01-23 11:45:10 -0800381////////////////////////////////////////////////////////////////////////////////
382
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000383SkPDFArray::SkPDFArray() {}
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000384SkPDFArray::~SkPDFArray() {
halcanary130444f2015-04-25 06:45:07 -0700385 for (SkPDFUnion& value : fValues) {
386 value.~SkPDFUnion();
387 }
388 fValues.reset();
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000389}
390
halcanary130444f2015-04-25 06:45:07 -0700391int SkPDFArray::size() const { return fValues.count(); }
392
393void SkPDFArray::reserve(int length) { fValues.setReserve(length); }
394
halcanary37c46ca2015-03-31 12:30:20 -0700395void SkPDFArray::emitObject(SkWStream* stream,
396 const SkPDFObjNumMap& objNumMap,
397 const SkPDFSubstituteMap& substitutes) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000398 stream->writeText("[");
halcanary130444f2015-04-25 06:45:07 -0700399 for (int i = 0; i < fValues.count(); i++) {
400 fValues[i].emitObject(stream, objNumMap, substitutes);
401 if (i + 1 < fValues.count()) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000402 stream->writeText(" ");
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000403 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000404 }
405 stream->writeText("]");
406}
407
halcanary37c46ca2015-03-31 12:30:20 -0700408void SkPDFArray::addResources(SkPDFObjNumMap* catalog,
409 const SkPDFSubstituteMap& substitutes) const {
halcanary130444f2015-04-25 06:45:07 -0700410 for (const SkPDFUnion& value : fValues) {
411 value.addResources(catalog, substitutes);
halcanarybf799cd2015-02-10 13:32:09 -0800412 }
413}
414
halcanary130444f2015-04-25 06:45:07 -0700415void SkPDFArray::append(SkPDFUnion&& value) {
416 SkNEW_PLACEMENT_ARGS(fValues.append(), SkPDFUnion, (value.move()));
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000417}
418
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000419SkPDFObject* SkPDFArray::append(SkPDFObject* value) {
halcanary130444f2015-04-25 06:45:07 -0700420 // DEPRECATED
421 this->append(SkPDFUnion::Object(SkRef(value)));
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000422 return value;
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000423}
424
reed@google.comc789cf12011-07-20 12:14:33 +0000425void SkPDFArray::appendInt(int32_t value) {
halcanary130444f2015-04-25 06:45:07 -0700426 this->append(SkPDFUnion::Int(value));
427}
428
429void SkPDFArray::appendBool(bool value) {
430 this->append(SkPDFUnion::Bool(value));
reed@google.comc789cf12011-07-20 12:14:33 +0000431}
432
433void SkPDFArray::appendScalar(SkScalar value) {
halcanary130444f2015-04-25 06:45:07 -0700434 this->append(SkPDFUnion::Scalar(value));
reed@google.comc789cf12011-07-20 12:14:33 +0000435}
436
437void SkPDFArray::appendName(const char name[]) {
halcanary130444f2015-04-25 06:45:07 -0700438 this->append(SkPDFUnion::Name(SkString(name)));
439}
440
441void SkPDFArray::appendName(const SkString& name) {
442 this->append(SkPDFUnion::Name(name));
443}
444
445void SkPDFArray::appendString(const SkString& value) {
446 this->append(SkPDFUnion::String(value));
447}
448
449void SkPDFArray::appendString(const char value[]) {
450 this->append(SkPDFUnion::String(value));
451}
452
453void SkPDFArray::appendObject(SkPDFObject* value) {
454 this->append(SkPDFUnion::Object(value));
455}
456
457void SkPDFArray::appendObjRef(SkPDFObject* value) {
458 this->append(SkPDFUnion::ObjRef(value));
reed@google.comc789cf12011-07-20 12:14:33 +0000459}
460
461///////////////////////////////////////////////////////////////////////////////
462
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000463SkPDFDict::SkPDFDict() {}
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000464
halcanary130444f2015-04-25 06:45:07 -0700465SkPDFDict::~SkPDFDict() { this->clear(); }
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000466
halcanary130444f2015-04-25 06:45:07 -0700467SkPDFDict::SkPDFDict(const char type[]) { this->insertName("Type", type); }
halcanary1f8ed022014-06-27 10:37:27 -0700468
halcanary37c46ca2015-03-31 12:30:20 -0700469void SkPDFDict::emitObject(SkWStream* stream,
470 const SkPDFObjNumMap& objNumMap,
471 const SkPDFSubstituteMap& substitutes) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000472 stream->writeText("<<");
halcanary130444f2015-04-25 06:45:07 -0700473 for (int i = 0; i < fRecords.count(); i++) {
474 fRecords[i].fKey.emitObject(stream, objNumMap, substitutes);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000475 stream->writeText(" ");
halcanary130444f2015-04-25 06:45:07 -0700476 fRecords[i].fValue.emitObject(stream, objNumMap, substitutes);
477 if (i + 1 < fRecords.count()) {
halcanary37c46ca2015-03-31 12:30:20 -0700478 stream->writeText("\n");
479 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000480 }
481 stream->writeText(">>");
482}
483
halcanary37c46ca2015-03-31 12:30:20 -0700484void SkPDFDict::addResources(SkPDFObjNumMap* catalog,
485 const SkPDFSubstituteMap& substitutes) const {
halcanary130444f2015-04-25 06:45:07 -0700486 for (int i = 0; i < fRecords.count(); i++) {
487 fRecords[i].fKey.addResources(catalog, substitutes);
488 fRecords[i].fValue.addResources(catalog, substitutes);
halcanarybf799cd2015-02-10 13:32:09 -0800489 }
490}
491
halcanary130444f2015-04-25 06:45:07 -0700492void SkPDFDict::set(SkPDFUnion&& name, SkPDFUnion&& value) {
493 Record* rec = fRecords.append();
494 SkASSERT(name.isName());
495 SkNEW_PLACEMENT_ARGS(&rec->fKey, SkPDFUnion, (name.move()));
496 SkNEW_PLACEMENT_ARGS(&rec->fValue, SkPDFUnion, (value.move()));
497}
498
499int SkPDFDict::size() const { return fRecords.count(); }
500
501void SkPDFDict::insertObjRef(const char key[], SkPDFObject* value) {
502 this->set(SkPDFUnion::Name(key), SkPDFUnion::ObjRef(value));
503}
504void SkPDFDict::insertObjRef(const SkString& key, SkPDFObject* value) {
505 this->set(SkPDFUnion::Name(key), SkPDFUnion::ObjRef(value));
506}
507
508void SkPDFDict::insertObject(const char key[], SkPDFObject* value) {
509 this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(value));
510}
511void SkPDFDict::insertObject(const SkString& key, SkPDFObject* value) {
512 this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(value));
513}
514
515// DEPRECATED
516SkPDFObject* SkPDFDict::insert(const char key[], SkPDFObject* value) {
517 this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(SkRef(value)));
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000518 return value;
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000519}
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000520
halcanarya25b3372015-04-27 14:00:09 -0700521void SkPDFDict::insertBool(const char key[], bool value) {
522 this->set(SkPDFUnion::Name(key), SkPDFUnion::Bool(value));
523}
524
reed@google.comc789cf12011-07-20 12:14:33 +0000525void SkPDFDict::insertInt(const char key[], int32_t value) {
halcanary130444f2015-04-25 06:45:07 -0700526 this->set(SkPDFUnion::Name(key), SkPDFUnion::Int(value));
527}
528
529void SkPDFDict::insertInt(const char key[], size_t value) {
530 this->insertInt(key, SkToS32(value));
reed@google.comc789cf12011-07-20 12:14:33 +0000531}
532
533void SkPDFDict::insertScalar(const char key[], SkScalar value) {
halcanary130444f2015-04-25 06:45:07 -0700534 this->set(SkPDFUnion::Name(key), SkPDFUnion::Scalar(value));
reed@google.comc789cf12011-07-20 12:14:33 +0000535}
536
537void SkPDFDict::insertName(const char key[], const char name[]) {
halcanary130444f2015-04-25 06:45:07 -0700538 this->set(SkPDFUnion::Name(key), SkPDFUnion::Name(name));
539}
540
541void SkPDFDict::insertName(const char key[], const SkString& name) {
542 this->set(SkPDFUnion::Name(key), SkPDFUnion::Name(name));
543}
544
545void SkPDFDict::insertString(const char key[], const char value[]) {
546 this->set(SkPDFUnion::Name(key), SkPDFUnion::String(value));
547}
548
549void SkPDFDict::insertString(const char key[], const SkString& value) {
550 this->set(SkPDFUnion::Name(key), SkPDFUnion::String(value));
reed@google.comc789cf12011-07-20 12:14:33 +0000551}
552
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000553void SkPDFDict::clear() {
halcanary130444f2015-04-25 06:45:07 -0700554 for (Record& rec : fRecords) {
555 rec.fKey.~SkPDFUnion();
556 rec.fValue.~SkPDFUnion();
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000557 }
halcanary130444f2015-04-25 06:45:07 -0700558 fRecords.reset();
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000559}
halcanary37c46ca2015-03-31 12:30:20 -0700560
561////////////////////////////////////////////////////////////////////////////////
562
563SkPDFSubstituteMap::~SkPDFSubstituteMap() {
564 fSubstituteMap.foreach(
565 [](SkPDFObject*, SkPDFObject** v) { (*v)->unref(); });
566}
567
568void SkPDFSubstituteMap::setSubstitute(SkPDFObject* original,
569 SkPDFObject* substitute) {
570 SkASSERT(original != substitute);
571 SkASSERT(!fSubstituteMap.find(original));
572 fSubstituteMap.set(original, SkRef(substitute));
573}
574
575SkPDFObject* SkPDFSubstituteMap::getSubstitute(SkPDFObject* object) const {
576 SkPDFObject** found = fSubstituteMap.find(object);
577 return found ? *found : object;
578}
579
580////////////////////////////////////////////////////////////////////////////////
581
582bool SkPDFObjNumMap::addObject(SkPDFObject* obj) {
583 if (fObjectNumbers.find(obj)) {
584 return false;
585 }
586 fObjectNumbers.set(obj, fObjectNumbers.count() + 1);
587 fObjects.push(obj);
588 return true;
589}
590
591int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const {
592 int32_t* objectNumberFound = fObjectNumbers.find(obj);
593 SkASSERT(objectNumberFound);
594 return *objectNumberFound;
595}
596