blob: ba5d6e29e7c22a32b8629e0cb3e3936168a37cc6 [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
halcanary002653e2015-05-05 11:28:55 -0700273#if 0 // Enable if needed.
halcanary130444f2015-04-25 06:45:07 -0700274void SkPDFAtom::emitObject(SkWStream* stream,
275 const SkPDFObjNumMap& objNumMap,
276 const SkPDFSubstituteMap& substitutes) {
277 fValue.emitObject(stream, objNumMap, substitutes);
278}
279void SkPDFAtom::addResources(SkPDFObjNumMap* map,
280 const SkPDFSubstituteMap& substitutes) const {
281 fValue.addResources(map, substitutes);
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000282}
halcanary002653e2015-05-05 11:28:55 -0700283#endif // 0
halcanary6a144342015-01-23 11:45:10 -0800284////////////////////////////////////////////////////////////////////////////////
285
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000286// static
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000287void SkPDFScalar::Append(SkScalar value, SkWStream* stream) {
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000288 // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and
289 // +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31).
290 // When using floats that are outside the whole value range, we can use
291 // integers instead.
292
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000293#if !defined(SK_ALLOW_LARGE_PDF_SCALARS)
294 if (value > 32767 || value < -32767) {
reed@google.come1ca7052013-12-17 19:22:07 +0000295 stream->writeDecAsText(SkScalarRoundToInt(value));
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000296 return;
297 }
298
299 char buffer[SkStrAppendScalar_MaxSize];
300 char* end = SkStrAppendFixed(buffer, SkScalarToFixed(value));
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000301 stream->write(buffer, end - buffer);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000302 return;
303#endif // !SK_ALLOW_LARGE_PDF_SCALARS
304
reed@google.com8f4d2302013-12-17 16:44:46 +0000305#if defined(SK_ALLOW_LARGE_PDF_SCALARS)
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000306 // Floats have 24bits of significance, so anything outside that range is
307 // no more precise than an int. (Plus PDF doesn't support scientific
308 // notation, so this clamps to SK_Max/MinS32).
309 if (value > (1 << 24) || value < -(1 << 24)) {
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000310 stream->writeDecAsText(value);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000311 return;
312 }
313 // Continue to enforce the PDF limits for small floats.
314 if (value < 1.0f/65536 && value > -1.0f/65536) {
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000315 stream->writeDecAsText(0);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000316 return;
317 }
318 // SkStrAppendFloat might still use scientific notation, so use snprintf
319 // directly..
320 static const int kFloat_MaxSize = 19;
321 char buffer[kFloat_MaxSize];
322 int len = SNPRINTF(buffer, kFloat_MaxSize, "%#.8f", value);
323 // %f always prints trailing 0s, so strip them.
324 for (; buffer[len - 1] == '0' && len > 0; len--) {
325 buffer[len - 1] = '\0';
326 }
327 if (buffer[len - 1] == '.') {
328 buffer[len - 1] = '\0';
329 }
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000330 stream->writeText(buffer);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000331 return;
reed@google.com8f4d2302013-12-17 16:44:46 +0000332#endif // SK_ALLOW_LARGE_PDF_SCALARS
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000333}
334
halcanary6a144342015-01-23 11:45:10 -0800335////////////////////////////////////////////////////////////////////////////////
336
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000337// static
halcanary130444f2015-04-25 06:45:07 -0700338
halcanarybb264b72015-04-07 10:40:03 -0700339SkString SkPDFString::FormatString(const char* cin, size_t len) {
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000340 SkASSERT(len <= kMaxLen);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000341
342 // 7-bit clean is a heuristic to decide what string format to use;
343 // a 7-bit clean string should require little escaping.
344 bool sevenBitClean = true;
halcanarybb264b72015-04-07 10:40:03 -0700345 size_t characterCount = 2 + len;
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000346 for (size_t i = 0; i < len; i++) {
halcanarybb264b72015-04-07 10:40:03 -0700347 if (cin[i] > '~' || cin[i] < ' ') {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000348 sevenBitClean = false;
349 break;
350 }
halcanarybb264b72015-04-07 10:40:03 -0700351 if (cin[i] == '\\' || cin[i] == '(' || cin[i] == ')') {
352 ++characterCount;
353 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000354 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000355 SkString result;
356 if (sevenBitClean) {
halcanarybb264b72015-04-07 10:40:03 -0700357 result.resize(characterCount);
358 char* str = result.writable_str();
359 *str++ = '(';
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000360 for (size_t i = 0; i < len; i++) {
halcanarybb264b72015-04-07 10:40:03 -0700361 if (cin[i] == '\\' || cin[i] == '(' || cin[i] == ')') {
362 *str++ = '\\';
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000363 }
halcanarybb264b72015-04-07 10:40:03 -0700364 *str++ = cin[i];
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000365 }
halcanarybb264b72015-04-07 10:40:03 -0700366 *str++ = ')';
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000367 } else {
halcanarybb264b72015-04-07 10:40:03 -0700368 result.resize(2 * len + 2);
369 char* str = result.writable_str();
370 *str++ = '<';
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000371 for (size_t i = 0; i < len; i++) {
halcanarybb264b72015-04-07 10:40:03 -0700372 uint8_t c = static_cast<uint8_t>(cin[i]);
373 static const char gHex[] = "0123456789ABCDEF";
374 *str++ = gHex[(c >> 4) & 0xF];
375 *str++ = gHex[(c ) & 0xF];
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000376 }
halcanarybb264b72015-04-07 10:40:03 -0700377 *str++ = '>';
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000378 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000379 return result;
380}
381
halcanary6a144342015-01-23 11:45:10 -0800382////////////////////////////////////////////////////////////////////////////////
383
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000384SkPDFArray::SkPDFArray() {}
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000385SkPDFArray::~SkPDFArray() {
halcanary130444f2015-04-25 06:45:07 -0700386 for (SkPDFUnion& value : fValues) {
387 value.~SkPDFUnion();
388 }
389 fValues.reset();
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000390}
391
halcanary130444f2015-04-25 06:45:07 -0700392int SkPDFArray::size() const { return fValues.count(); }
393
394void SkPDFArray::reserve(int length) { fValues.setReserve(length); }
395
halcanary37c46ca2015-03-31 12:30:20 -0700396void SkPDFArray::emitObject(SkWStream* stream,
397 const SkPDFObjNumMap& objNumMap,
398 const SkPDFSubstituteMap& substitutes) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000399 stream->writeText("[");
halcanary130444f2015-04-25 06:45:07 -0700400 for (int i = 0; i < fValues.count(); i++) {
401 fValues[i].emitObject(stream, objNumMap, substitutes);
402 if (i + 1 < fValues.count()) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000403 stream->writeText(" ");
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000404 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000405 }
406 stream->writeText("]");
407}
408
halcanary37c46ca2015-03-31 12:30:20 -0700409void SkPDFArray::addResources(SkPDFObjNumMap* catalog,
410 const SkPDFSubstituteMap& substitutes) const {
halcanary130444f2015-04-25 06:45:07 -0700411 for (const SkPDFUnion& value : fValues) {
412 value.addResources(catalog, substitutes);
halcanarybf799cd2015-02-10 13:32:09 -0800413 }
414}
415
halcanary130444f2015-04-25 06:45:07 -0700416void SkPDFArray::append(SkPDFUnion&& value) {
417 SkNEW_PLACEMENT_ARGS(fValues.append(), SkPDFUnion, (value.move()));
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000418}
419
reed@google.comc789cf12011-07-20 12:14:33 +0000420void SkPDFArray::appendInt(int32_t value) {
halcanary130444f2015-04-25 06:45:07 -0700421 this->append(SkPDFUnion::Int(value));
422}
423
424void SkPDFArray::appendBool(bool value) {
425 this->append(SkPDFUnion::Bool(value));
reed@google.comc789cf12011-07-20 12:14:33 +0000426}
427
428void SkPDFArray::appendScalar(SkScalar value) {
halcanary130444f2015-04-25 06:45:07 -0700429 this->append(SkPDFUnion::Scalar(value));
reed@google.comc789cf12011-07-20 12:14:33 +0000430}
431
432void SkPDFArray::appendName(const char name[]) {
halcanary130444f2015-04-25 06:45:07 -0700433 this->append(SkPDFUnion::Name(SkString(name)));
434}
435
436void SkPDFArray::appendName(const SkString& name) {
437 this->append(SkPDFUnion::Name(name));
438}
439
440void SkPDFArray::appendString(const SkString& value) {
441 this->append(SkPDFUnion::String(value));
442}
443
444void SkPDFArray::appendString(const char value[]) {
445 this->append(SkPDFUnion::String(value));
446}
447
448void SkPDFArray::appendObject(SkPDFObject* value) {
449 this->append(SkPDFUnion::Object(value));
450}
451
452void SkPDFArray::appendObjRef(SkPDFObject* value) {
453 this->append(SkPDFUnion::ObjRef(value));
reed@google.comc789cf12011-07-20 12:14:33 +0000454}
455
456///////////////////////////////////////////////////////////////////////////////
457
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000458SkPDFDict::SkPDFDict() {}
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000459
halcanary130444f2015-04-25 06:45:07 -0700460SkPDFDict::~SkPDFDict() { this->clear(); }
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000461
halcanary130444f2015-04-25 06:45:07 -0700462SkPDFDict::SkPDFDict(const char type[]) { this->insertName("Type", type); }
halcanary1f8ed022014-06-27 10:37:27 -0700463
halcanary37c46ca2015-03-31 12:30:20 -0700464void SkPDFDict::emitObject(SkWStream* stream,
465 const SkPDFObjNumMap& objNumMap,
466 const SkPDFSubstituteMap& substitutes) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000467 stream->writeText("<<");
halcanary130444f2015-04-25 06:45:07 -0700468 for (int i = 0; i < fRecords.count(); i++) {
469 fRecords[i].fKey.emitObject(stream, objNumMap, substitutes);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000470 stream->writeText(" ");
halcanary130444f2015-04-25 06:45:07 -0700471 fRecords[i].fValue.emitObject(stream, objNumMap, substitutes);
472 if (i + 1 < fRecords.count()) {
halcanary37c46ca2015-03-31 12:30:20 -0700473 stream->writeText("\n");
474 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000475 }
476 stream->writeText(">>");
477}
478
halcanary37c46ca2015-03-31 12:30:20 -0700479void SkPDFDict::addResources(SkPDFObjNumMap* catalog,
480 const SkPDFSubstituteMap& substitutes) const {
halcanary130444f2015-04-25 06:45:07 -0700481 for (int i = 0; i < fRecords.count(); i++) {
482 fRecords[i].fKey.addResources(catalog, substitutes);
483 fRecords[i].fValue.addResources(catalog, substitutes);
halcanarybf799cd2015-02-10 13:32:09 -0800484 }
485}
486
halcanary130444f2015-04-25 06:45:07 -0700487void SkPDFDict::set(SkPDFUnion&& name, SkPDFUnion&& value) {
488 Record* rec = fRecords.append();
489 SkASSERT(name.isName());
490 SkNEW_PLACEMENT_ARGS(&rec->fKey, SkPDFUnion, (name.move()));
491 SkNEW_PLACEMENT_ARGS(&rec->fValue, SkPDFUnion, (value.move()));
492}
493
494int SkPDFDict::size() const { return fRecords.count(); }
495
496void SkPDFDict::insertObjRef(const char key[], SkPDFObject* value) {
497 this->set(SkPDFUnion::Name(key), SkPDFUnion::ObjRef(value));
498}
499void SkPDFDict::insertObjRef(const SkString& key, SkPDFObject* value) {
500 this->set(SkPDFUnion::Name(key), SkPDFUnion::ObjRef(value));
501}
502
503void SkPDFDict::insertObject(const char key[], SkPDFObject* value) {
504 this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(value));
505}
506void SkPDFDict::insertObject(const SkString& key, SkPDFObject* value) {
507 this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(value));
508}
509
halcanarya25b3372015-04-27 14:00:09 -0700510void SkPDFDict::insertBool(const char key[], bool value) {
511 this->set(SkPDFUnion::Name(key), SkPDFUnion::Bool(value));
512}
513
reed@google.comc789cf12011-07-20 12:14:33 +0000514void SkPDFDict::insertInt(const char key[], int32_t value) {
halcanary130444f2015-04-25 06:45:07 -0700515 this->set(SkPDFUnion::Name(key), SkPDFUnion::Int(value));
516}
517
518void SkPDFDict::insertInt(const char key[], size_t value) {
519 this->insertInt(key, SkToS32(value));
reed@google.comc789cf12011-07-20 12:14:33 +0000520}
521
522void SkPDFDict::insertScalar(const char key[], SkScalar value) {
halcanary130444f2015-04-25 06:45:07 -0700523 this->set(SkPDFUnion::Name(key), SkPDFUnion::Scalar(value));
reed@google.comc789cf12011-07-20 12:14:33 +0000524}
525
526void SkPDFDict::insertName(const char key[], const char name[]) {
halcanary130444f2015-04-25 06:45:07 -0700527 this->set(SkPDFUnion::Name(key), SkPDFUnion::Name(name));
528}
529
530void SkPDFDict::insertName(const char key[], const SkString& name) {
531 this->set(SkPDFUnion::Name(key), SkPDFUnion::Name(name));
532}
533
534void SkPDFDict::insertString(const char key[], const char value[]) {
535 this->set(SkPDFUnion::Name(key), SkPDFUnion::String(value));
536}
537
538void SkPDFDict::insertString(const char key[], const SkString& value) {
539 this->set(SkPDFUnion::Name(key), SkPDFUnion::String(value));
reed@google.comc789cf12011-07-20 12:14:33 +0000540}
541
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000542void SkPDFDict::clear() {
halcanary130444f2015-04-25 06:45:07 -0700543 for (Record& rec : fRecords) {
544 rec.fKey.~SkPDFUnion();
545 rec.fValue.~SkPDFUnion();
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000546 }
halcanary130444f2015-04-25 06:45:07 -0700547 fRecords.reset();
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000548}
halcanary37c46ca2015-03-31 12:30:20 -0700549
550////////////////////////////////////////////////////////////////////////////////
551
552SkPDFSubstituteMap::~SkPDFSubstituteMap() {
553 fSubstituteMap.foreach(
554 [](SkPDFObject*, SkPDFObject** v) { (*v)->unref(); });
555}
556
557void SkPDFSubstituteMap::setSubstitute(SkPDFObject* original,
558 SkPDFObject* substitute) {
559 SkASSERT(original != substitute);
560 SkASSERT(!fSubstituteMap.find(original));
561 fSubstituteMap.set(original, SkRef(substitute));
562}
563
564SkPDFObject* SkPDFSubstituteMap::getSubstitute(SkPDFObject* object) const {
565 SkPDFObject** found = fSubstituteMap.find(object);
566 return found ? *found : object;
567}
568
569////////////////////////////////////////////////////////////////////////////////
570
571bool SkPDFObjNumMap::addObject(SkPDFObject* obj) {
572 if (fObjectNumbers.find(obj)) {
573 return false;
574 }
575 fObjectNumbers.set(obj, fObjectNumbers.count() + 1);
576 fObjects.push(obj);
577 return true;
578}
579
580int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const {
581 int32_t* objectNumberFound = fObjectNumbers.find(obj);
582 SkASSERT(objectNumberFound);
583 return *objectNumberFound;
584}
585