Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: src/pdf/SkPDFTypes.cpp

Issue 1069103003: SkPDF: Refactor SkPDFObject heiararchy. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2015-04-23 (Thursday) 17:02:33 EDT Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2011 Google Inc. 3 * Copyright 2011 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9
10 #include "SkPDFTypes.h" 9 #include "SkPDFTypes.h"
11 #include "SkStream.h" 10 #include "SkStream.h"
12 11
13 #ifdef SK_BUILD_FOR_WIN 12 #ifdef SK_BUILD_FOR_WIN
14 #define SNPRINTF _snprintf 13 #define SNPRINTF _snprintf
15 #else 14 #else
16 #define SNPRINTF snprintf 15 #define SNPRINTF snprintf
17 #endif 16 #endif
18 17
19 //////////////////////////////////////////////////////////////////////////////// 18 ////////////////////////////////////////////////////////////////////////////////
20 19
21 SkPDFObjRef::SkPDFObjRef(SkPDFObject* obj) : fObj(obj) { 20 SkString* pun(char* x) { return reinterpret_cast<SkString*>(x); }
22 SkSafeRef(obj); 21 const SkString* pun(const char* x) {
23 } 22 return reinterpret_cast<const SkString*>(x);
24 23 }
25 SkPDFObjRef::~SkPDFObjRef() {} 24
26 25 SkPDFUnion::SkPDFUnion(Type t) : fType(t) {}
27 void SkPDFObjRef::emitObject(SkWStream* stream, 26
28 const SkPDFObjNumMap& objNumMap, 27 SkPDFUnion::~SkPDFUnion() {
29 const SkPDFSubstituteMap& substitutes) { 28 switch (fType) {
30 SkPDFObject* obj = substitutes.getSubstitute(fObj); 29 case Type::kNameSkS:
31 stream->writeDecAsText(objNumMap.getObjectNumber(obj)); 30 case Type::kStringSkS:
32 stream->writeText(" 0 R"); // Generation number is always 0. 31 pun(fSkString)->~SkString();
33 } 32 return;
34 33 case Type::kObjRef:
35 void SkPDFObjRef::addResources(SkPDFObjNumMap* catalog, 34 case Type::kObject:
36 const SkPDFSubstituteMap& substitutes) const { 35 SkSafeUnref(fObject);
37 SkPDFObject* obj = substitutes.getSubstitute(fObj); 36 return;
38 SkASSERT(obj); 37 default:
39 if (catalog->addObject(obj)) { 38 return;
40 obj->addResources(catalog, substitutes); 39 }
41 } 40 }
41
42 SkPDFUnion& SkPDFUnion::operator=(SkPDFUnion&& other) {
43 if (this != &other) {
tomhudson 2015/04/24 21:32:29 Never worked with && before, so I'm assuming you'v
hal.canary 2015/04/24 21:51:46 It is not isomorphic to **. This is C++11 notatio
44 this->~SkPDFUnion();
45 SkNEW_PLACEMENT_ARGS(this, SkPDFUnion, (other.move()));
46 }
47 return *this;
48 }
49
50 SkPDFUnion::SkPDFUnion(SkPDFUnion&& other) {
51 SkASSERT(this != &other);
52 memcpy(this, &other, sizeof(*this));
53 other.fType = Type::kDestroyed;
54 }
55
56 #if 0
57 SkPDFUnion 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 }
74 SkPDFUnion& SkPDFUnion::operator=(const SkPDFUnion& other) {
75 return *this = other.copy();
76 }
77 SkPDFUnion::SkPDFUnion(const SkPDFUnion& other) {
78 *this = other.copy();
79 }
80 #endif
81
82 bool SkPDFUnion::isName() const {
83 return Type::kName == fType || Type::kNameSkS == fType;
84 }
85
86 bool SkPDFUnion::IsValidName(const char* n) {
87 static const char kControlChars[] = "/%()<>[]{}";
88 while (*n) {
89 if (*n < '!' || *n > '~' || strchr(kControlChars, *n)) {
90 return false;
91 }
92 ++n;
93 }
94 return true;
95 }
96
97 SkString SkPDFUnion::EscapeName(const char* name, size_t len) {
98 static const char kToEscape[] = "#/%()<>[]{}";
99 int count = 0;
100 const char* const end = &name[len];
101 for (const char* n = name; n != end; ++n) {
102 if (*n < '!' || *n > '~' || strchr(kToEscape, *n)) {
103 count += 2;
104 }
105 ++count;
106 }
107 SkString result(count);
108 char* s = result.writable_str();
109 static const char kHex[] = "0123456789ABCDEF";
110 for (const char* n = name; n != end; ++n) {
111 if (*n < '!' || *n > '~' || strchr(kToEscape, *n)) {
112 *s++ = '#';
113 *s++ = kHex[(*n >> 4) & 0xF];
114 *s++ = kHex[*n & 0xF];
115 } else {
116 *s++ = *n;
117 }
118 }
119 SkASSERT(&result.writable_str()[count] == s); // don't over-write
120 return result; // allocated space
121 }
122
123 static void write_string(SkWStream* o, const SkString& s) {
124 o->write(s.c_str(), s.size());
125 }
126
127 static SkString format_string(const SkString& s) {
128 return SkPDFString::FormatString(s.c_str(), s.size());
129 }
130
131 static SkString format_string(const char* s) {
132 return SkPDFString::FormatString(s, strlen(s));
133 }
134
135 SkString escape_name(const SkString& name) {
136 return SkPDFUnion::EscapeName(name.c_str(), name.size());
137 }
138
139 void SkPDFUnion::emitObject(SkWStream* stream,
140 const SkPDFObjNumMap& objNumMap,
141 const SkPDFSubstituteMap& substitutes) const {
142 switch (fType) {
143 case Type::kInt:
144 stream->writeDecAsText(fIntValue);
145 return;
146 case Type::kBool:
147 stream->writeText(fBoolValue ? "true" : "false");
148 return;
149 case Type::kScalar:
150 SkPDFScalar::Append(fScalarValue, stream);
151 return;
152 case Type::kName:
153 stream->writeText("/");
154 SkASSERT(SkPDFUnion::IsValidName(fStaticString));
155 stream->writeText(fStaticString);
156 return;
157 case Type::kString:
158 SkASSERT(fStaticString);
159 write_string(stream, format_string(fStaticString));
160 return;
161 case Type::kNameSkS:
162 stream->writeText("/");
163 write_string(stream, escape_name(*pun(fSkString)));
164 return;
165 case Type::kStringSkS:
166 write_string(stream, format_string(*pun(fSkString)));
167 return;
168 case Type::kObjRef:
169 stream->writeDecAsText(objNumMap.getObjectNumber(
170 substitutes.getSubstitute(fObject)));
171 stream->writeText(" 0 R"); // Generation number is always 0.
172 return;
173 case Type::kObject:
174 fObject->emitObject(stream, objNumMap, substitutes);
175 return;
176 default:
177 SkDEBUGFAIL("SkPDFUnion::emitObject with bad type");
178 }
179 }
180
181 void SkPDFUnion::addResources(SkPDFObjNumMap* objNumMap,
182 const SkPDFSubstituteMap& substituteMap) const {
183 switch (fType) {
184 case Type::kInt:
185 case Type::kBool:
186 case Type::kScalar:
187 case Type::kName:
188 case Type::kString:
189 case Type::kNameSkS:
190 case Type::kStringSkS:
191 return; // These have no resources.
192 case Type::kObjRef: {
193 SkPDFObject* obj = substituteMap.getSubstitute(fObject);
194 if (objNumMap->addObject(obj)) {
195 obj->addResources(objNumMap, substituteMap);
196 }
197 return;
198 }
199 case Type::kObject:
200 fObject->addResources(objNumMap, substituteMap);
201 return;
202 default:
203 SkDEBUGFAIL("SkPDFUnion::addResources with bad type");
204 }
205 }
206
207 SkPDFUnion SkPDFUnion::Int(int32_t value) {
208 SkPDFUnion u(Type::kInt);
209 u.fIntValue = value;
210 return u.move();
211 }
212
213 SkPDFUnion SkPDFUnion::Bool(bool value) {
214 SkPDFUnion u(Type::kBool);
215 u.fBoolValue = value;
216 return u.move();
217 }
218
219 SkPDFUnion SkPDFUnion::Scalar(SkScalar value) {
220 SkPDFUnion u(Type::kScalar);
221 u.fScalarValue = value;
222 return u.move();
223 }
224
225 SkPDFUnion SkPDFUnion::Name(const char* value) {
226 SkPDFUnion u(Type::kName);
227 SkASSERT(value);
228 SkASSERT(SkPDFUnion::IsValidName(value));
229 u.fStaticString = value;
230 return u.move();
231 }
232
233 SkPDFUnion SkPDFUnion::String(const char* value) {
234 SkPDFUnion u(Type::kString);
235 SkASSERT(value);
236 u.fStaticString = value;
237 return u.move();
238 }
239
240 SkPDFUnion SkPDFUnion::Name(const SkString& s) {
241 SkPDFUnion u(Type::kNameSkS);
242 SkNEW_PLACEMENT_ARGS(pun(u.fSkString), SkString, (s));
243 return u.move();
244 }
245
246 SkPDFUnion SkPDFUnion::String(const SkString& s) {
247 SkPDFUnion u(Type::kStringSkS);
248 SkNEW_PLACEMENT_ARGS(pun(u.fSkString), SkString, (s));
249 return u.move();
250 }
251
252 SkPDFUnion SkPDFUnion::ObjRef(SkPDFObject* ptr) {
253 SkPDFUnion u(Type::kObjRef);
254 SkASSERT(ptr);
255 u.fObject = ptr;
256 return u.move();
257 }
258
259 SkPDFUnion SkPDFUnion::Object(SkPDFObject* ptr) {
260 SkPDFUnion u(Type::kObject);
261 SkASSERT(ptr);
262 u.fObject = ptr;
263 return u.move();
42 } 264 }
43 265
44 //////////////////////////////////////////////////////////////////////////////// 266 ////////////////////////////////////////////////////////////////////////////////
45 267
46 SkPDFInt::SkPDFInt(int32_t value) : fValue(value) {} 268 void SkPDFAtom::emitObject(SkWStream* stream,
47 SkPDFInt::~SkPDFInt() {} 269 const SkPDFObjNumMap& objNumMap,
48 270 const SkPDFSubstituteMap& substitutes) {
49 void SkPDFInt::emitObject(SkWStream* stream, 271 fValue.emitObject(stream, objNumMap, substitutes);
50 const SkPDFObjNumMap&, 272 }
51 const SkPDFSubstituteMap&) { 273 void SkPDFAtom::addResources(SkPDFObjNumMap* map,
52 stream->writeDecAsText(fValue); 274 const SkPDFSubstituteMap& substitutes) const {
275 fValue.addResources(map, substitutes);
53 } 276 }
54 277
55 //////////////////////////////////////////////////////////////////////////////// 278 ////////////////////////////////////////////////////////////////////////////////
56 279
57 SkPDFBool::SkPDFBool(bool value) : fValue(value) {}
58 SkPDFBool::~SkPDFBool() {}
59
60 void SkPDFBool::emitObject(SkWStream* stream,
61 const SkPDFObjNumMap&,
62 const SkPDFSubstituteMap&) {
63 stream->writeText(fValue ? "true" : "false");
64 }
65
66 ////////////////////////////////////////////////////////////////////////////////
67
68 SkPDFScalar::SkPDFScalar(SkScalar value) : fValue(value) {}
69 SkPDFScalar::~SkPDFScalar() {}
70
71 void SkPDFScalar::emitObject(SkWStream* stream,
72 const SkPDFObjNumMap&,
73 const SkPDFSubstituteMap&) {
74 SkPDFScalar::Append(fValue, stream);
75 }
76
77 // static 280 // static
78 void SkPDFScalar::Append(SkScalar value, SkWStream* stream) { 281 void SkPDFScalar::Append(SkScalar value, SkWStream* stream) {
79 // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and 282 // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and
80 // +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31). 283 // +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31).
81 // When using floats that are outside the whole value range, we can use 284 // When using floats that are outside the whole value range, we can use
82 // integers instead. 285 // integers instead.
83 286
84 #if !defined(SK_ALLOW_LARGE_PDF_SCALARS) 287 #if !defined(SK_ALLOW_LARGE_PDF_SCALARS)
85 if (value > 32767 || value < -32767) { 288 if (value > 32767 || value < -32767) {
86 stream->writeDecAsText(SkScalarRoundToInt(value)); 289 stream->writeDecAsText(SkScalarRoundToInt(value));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 if (buffer[len - 1] == '.') { 321 if (buffer[len - 1] == '.') {
119 buffer[len - 1] = '\0'; 322 buffer[len - 1] = '\0';
120 } 323 }
121 stream->writeText(buffer); 324 stream->writeText(buffer);
122 return; 325 return;
123 #endif // SK_ALLOW_LARGE_PDF_SCALARS 326 #endif // SK_ALLOW_LARGE_PDF_SCALARS
124 } 327 }
125 328
126 //////////////////////////////////////////////////////////////////////////////// 329 ////////////////////////////////////////////////////////////////////////////////
127 330
128 SkPDFString::SkPDFString(const char value[]) 331 // static
129 : fValue(FormatString(value, strlen(value))) {
130 }
131 332
132 SkPDFString::SkPDFString(const SkString& value)
133 : fValue(FormatString(value.c_str(), value.size())) {
134 }
135
136 SkPDFString::~SkPDFString() {}
137
138 void SkPDFString::emitObject(SkWStream* stream,
139 const SkPDFObjNumMap&,
140 const SkPDFSubstituteMap&) {
141 stream->write(fValue.c_str(), fValue.size());
142 }
143
144 // static
145 SkString SkPDFString::FormatString(const char* cin, size_t len) { 333 SkString SkPDFString::FormatString(const char* cin, size_t len) {
146 SkASSERT(len <= kMaxLen); 334 SkASSERT(len <= kMaxLen);
147 335
148 // 7-bit clean is a heuristic to decide what string format to use; 336 // 7-bit clean is a heuristic to decide what string format to use;
149 // a 7-bit clean string should require little escaping. 337 // a 7-bit clean string should require little escaping.
150 bool sevenBitClean = true; 338 bool sevenBitClean = true;
151 size_t characterCount = 2 + len; 339 size_t characterCount = 2 + len;
152 for (size_t i = 0; i < len; i++) { 340 for (size_t i = 0; i < len; i++) {
153 if (cin[i] > '~' || cin[i] < ' ') { 341 if (cin[i] > '~' || cin[i] < ' ') {
154 sevenBitClean = false; 342 sevenBitClean = false;
(...skipping 25 matching lines...) Expand all
180 *str++ = gHex[(c >> 4) & 0xF]; 368 *str++ = gHex[(c >> 4) & 0xF];
181 *str++ = gHex[(c ) & 0xF]; 369 *str++ = gHex[(c ) & 0xF];
182 } 370 }
183 *str++ = '>'; 371 *str++ = '>';
184 } 372 }
185 return result; 373 return result;
186 } 374 }
187 375
188 //////////////////////////////////////////////////////////////////////////////// 376 ////////////////////////////////////////////////////////////////////////////////
189 377
190 SkPDFName::SkPDFName(const char name[]) : fValue(FormatName(SkString(name))) {}
191 SkPDFName::SkPDFName(const SkString& name) : fValue(FormatName(name)) {}
192 SkPDFName::~SkPDFName() {}
193
194 bool SkPDFName::operator==(const SkPDFName& b) const {
195 return fValue == b.fValue;
196 }
197
198 void SkPDFName::emitObject(SkWStream* stream,
199 const SkPDFObjNumMap&,
200 const SkPDFSubstituteMap&) {
201 stream->write(fValue.c_str(), fValue.size());
202 }
203
204 // static
205 SkString SkPDFName::FormatName(const SkString& input) {
206 SkASSERT(input.size() <= kMaxLen);
207 // TODO(vandebo) If more escaping is needed, improve the linear scan.
208 static const char escaped[] = "#/%()<>[]{}";
209
210 SkString result("/");
211 for (size_t i = 0; i < input.size(); i++) {
212 if (input[i] & 0x80 || input[i] < '!' || strchr(escaped, input[i])) {
213 result.append("#");
214 // Mask with 0xFF to avoid sign extension. i.e. #FFFFFF81
215 result.appendHex(input[i] & 0xFF, 2);
216 } else {
217 result.append(input.c_str() + i, 1);
218 }
219 }
220
221 return result;
222 }
223
224 ////////////////////////////////////////////////////////////////////////////////
225
226 SkPDFArray::SkPDFArray() {} 378 SkPDFArray::SkPDFArray() {}
227 SkPDFArray::~SkPDFArray() { 379 SkPDFArray::~SkPDFArray() {
228 fValue.unrefAll(); 380 for (SkPDFUnion& value : fValues) {
381 value.~SkPDFUnion();
382 }
383 fValues.reset();
229 } 384 }
230 385
386 int SkPDFArray::size() const { return fValues.count(); }
387
388 void SkPDFArray::reserve(int length) { fValues.setReserve(length); }
389
231 void SkPDFArray::emitObject(SkWStream* stream, 390 void SkPDFArray::emitObject(SkWStream* stream,
232 const SkPDFObjNumMap& objNumMap, 391 const SkPDFObjNumMap& objNumMap,
233 const SkPDFSubstituteMap& substitutes) { 392 const SkPDFSubstituteMap& substitutes) {
234 stream->writeText("["); 393 stream->writeText("[");
235 for (int i = 0; i < fValue.count(); i++) { 394 for (int i = 0; i < fValues.count(); i++) {
236 SkASSERT(substitutes.getSubstitute(fValue[i]) == fValue[i]); 395 fValues[i].emitObject(stream, objNumMap, substitutes);
tomhudson 2015/04/24 21:32:29 Not worth maintaining this invariant?
hal.canary 2015/04/25 13:41:02 Only top level objects (referred to via ObjRefs) s
237 fValue[i]->emitObject(stream, objNumMap, substitutes); 396 if (i + 1 < fValues.count()) {
238 if (i + 1 < fValue.count()) {
239 stream->writeText(" "); 397 stream->writeText(" ");
240 } 398 }
241 } 399 }
242 stream->writeText("]"); 400 stream->writeText("]");
243 } 401 }
244 402
245 void SkPDFArray::addResources(SkPDFObjNumMap* catalog, 403 void SkPDFArray::addResources(SkPDFObjNumMap* catalog,
246 const SkPDFSubstituteMap& substitutes) const { 404 const SkPDFSubstituteMap& substitutes) const {
247 for (int i = 0; i < fValue.count(); i++) { 405 for (const SkPDFUnion& value : fValues) {
248 SkASSERT(substitutes.getSubstitute(fValue[i]) == fValue[i]); 406 value.addResources(catalog, substitutes);
249 fValue[i]->addResources(catalog, substitutes);
250 } 407 }
251 } 408 }
252 409
253 void SkPDFArray::reserve(int length) { 410 // void SkPDFArray::append(const SkPDFUnion& value) {
254 SkASSERT(length <= kMaxLen); 411 // SkNEW_PLACEMENT_ARGS(fValues.append(), SkPDFUnion, (value));
255 fValue.setReserve(length); 412 // }
tomhudson 2015/04/24 21:32:29 Commented out code - delete?
hal.canary 2015/04/25 13:41:02 Done.
413
414 void SkPDFArray::append(SkPDFUnion&& value) {
415 SkNEW_PLACEMENT_ARGS(fValues.append(), SkPDFUnion, (value.move()));
256 } 416 }
257 417
258 SkPDFObject* SkPDFArray::append(SkPDFObject* value) { 418 SkPDFObject* SkPDFArray::append(SkPDFObject* value) {
259 SkASSERT(fValue.count() < kMaxLen); 419 // DEPRECATED
260 value->ref(); 420 this->append(SkPDFUnion::Object(SkRef(value)));
261 fValue.push(value);
262 return value; 421 return value;
263 } 422 }
264 423
265 void SkPDFArray::appendInt(int32_t value) { 424 void SkPDFArray::appendInt(int32_t value) {
266 SkASSERT(fValue.count() < kMaxLen); 425 this->append(SkPDFUnion::Int(value));
267 fValue.push(new SkPDFInt(value)); 426 }
427
428 void SkPDFArray::appendBool(bool value) {
429 this->append(SkPDFUnion::Bool(value));
268 } 430 }
269 431
270 void SkPDFArray::appendScalar(SkScalar value) { 432 void SkPDFArray::appendScalar(SkScalar value) {
271 SkASSERT(fValue.count() < kMaxLen); 433 this->append(SkPDFUnion::Scalar(value));
272 fValue.push(new SkPDFScalar(value));
273 } 434 }
274 435
275 void SkPDFArray::appendName(const char name[]) { 436 void SkPDFArray::appendName(const char name[]) {
276 SkASSERT(fValue.count() < kMaxLen); 437 this->append(SkPDFUnion::Name(SkString(name)));
277 fValue.push(new SkPDFName(name)); 438 }
439
440 void SkPDFArray::appendName(const SkString& name) {
441 this->append(SkPDFUnion::Name(name));
442 }
443
444 void SkPDFArray::appendString(const SkString& value) {
445 this->append(SkPDFUnion::String(value));
446 }
447
448 void SkPDFArray::appendString(const char value[]) {
449 this->append(SkPDFUnion::String(value));
450 }
451
452 void SkPDFArray::appendObject(SkPDFObject* value) {
453 this->append(SkPDFUnion::Object(value));
454 }
455
456 void SkPDFArray::appendObjRef(SkPDFObject* value) {
457 this->append(SkPDFUnion::ObjRef(value));
278 } 458 }
279 459
280 /////////////////////////////////////////////////////////////////////////////// 460 ///////////////////////////////////////////////////////////////////////////////
281 461
282 SkPDFDict::SkPDFDict() {} 462 SkPDFDict::SkPDFDict() {}
283 463
284 SkPDFDict::SkPDFDict(const char type[]) { 464 SkPDFDict::~SkPDFDict() { this->clear(); }
285 insertName("Type", type);
286 }
287 465
288 SkPDFDict::~SkPDFDict() { 466 SkPDFDict::SkPDFDict(const char type[]) { this->insertName("Type", type); }
289 clear();
290 }
291
292 int SkPDFDict::size() const {
293 return fValue.count();
294 }
295 467
296 void SkPDFDict::emitObject(SkWStream* stream, 468 void SkPDFDict::emitObject(SkWStream* stream,
297 const SkPDFObjNumMap& objNumMap, 469 const SkPDFObjNumMap& objNumMap,
298 const SkPDFSubstituteMap& substitutes) { 470 const SkPDFSubstituteMap& substitutes) {
299 stream->writeText("<<"); 471 stream->writeText("<<");
300 for (int i = 0; i < fValue.count(); i++) { 472 for (int i = 0; i < fRecords.count(); i++) {
301 SkASSERT(fValue[i].key); 473 fRecords[i].fKey.emitObject(stream, objNumMap, substitutes);
302 SkASSERT(fValue[i].value);
303 SkASSERT(substitutes.getSubstitute(fValue[i].key) == fValue[i].key);
304 SkASSERT(substitutes.getSubstitute(fValue[i].value) == fValue[i].value);
305 fValue[i].key->emitObject(stream, objNumMap, substitutes);
306 stream->writeText(" "); 474 stream->writeText(" ");
307 fValue[i].value->emitObject(stream, objNumMap, substitutes); 475 fRecords[i].fValue.emitObject(stream, objNumMap, substitutes);
308 if (i + 1 < fValue.count()) { 476 if (i + 1 < fRecords.count()) {
309 stream->writeText("\n"); 477 stream->writeText("\n");
310 } 478 }
311 } 479 }
312 stream->writeText(">>"); 480 stream->writeText(">>");
313 } 481 }
314 482
315 void SkPDFDict::addResources(SkPDFObjNumMap* catalog, 483 void SkPDFDict::addResources(SkPDFObjNumMap* catalog,
316 const SkPDFSubstituteMap& substitutes) const { 484 const SkPDFSubstituteMap& substitutes) const {
317 for (int i = 0; i < fValue.count(); i++) { 485 for (int i = 0; i < fRecords.count(); i++) {
318 SkASSERT(fValue[i].key); 486 fRecords[i].fKey.addResources(catalog, substitutes);
319 SkASSERT(fValue[i].value); 487 fRecords[i].fValue.addResources(catalog, substitutes);
320 fValue[i].key->addResources(catalog, substitutes);
321 SkASSERT(substitutes.getSubstitute(fValue[i].value) == fValue[i].value);
322 fValue[i].value->addResources(catalog, substitutes);
323 } 488 }
324 } 489 }
325 490
326 SkPDFObject* SkPDFDict::append(SkPDFName* key, SkPDFObject* value) { 491 void SkPDFDict::set(SkPDFUnion&& name, SkPDFUnion&& value) {
327 SkASSERT(key); 492 Record* rec = fRecords.append();
328 SkASSERT(value); 493 SkASSERT(name.isName());
329 *(fValue.append()) = Rec(key, value); 494 SkNEW_PLACEMENT_ARGS(&rec->fKey, SkPDFUnion, (name.move()));
495 SkNEW_PLACEMENT_ARGS(&rec->fValue, SkPDFUnion, (value.move()));
496 }
497
498 int SkPDFDict::size() const { return fRecords.count(); }
499
500 void SkPDFDict::insertObjRef(const char key[], SkPDFObject* value) {
501 this->set(SkPDFUnion::Name(key), SkPDFUnion::ObjRef(value));
502 }
503 void SkPDFDict::insertObjRef(const SkString& key, SkPDFObject* value) {
504 this->set(SkPDFUnion::Name(key), SkPDFUnion::ObjRef(value));
505 }
506
507 void SkPDFDict::insertObject(const char key[], SkPDFObject* value) {
508 this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(value));
509 }
510 void SkPDFDict::insertObject(const SkString& key, SkPDFObject* value) {
511 this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(value));
512 }
513
514 // DEPRECATED
515 SkPDFObject* SkPDFDict::insert(const char key[], SkPDFObject* value) {
516 this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(SkRef(value)));
330 return value; 517 return value;
331 } 518 }
332 519
333 SkPDFObject* SkPDFDict::insert(SkPDFName* key, SkPDFObject* value) { 520 void SkPDFDict::insertInt(const char key[], int32_t value) {
334 return this->append(SkRef(key), SkRef(value)); 521 this->set(SkPDFUnion::Name(key), SkPDFUnion::Int(value));
335 } 522 }
336 523
337 SkPDFObject* SkPDFDict::insert(const char key[], SkPDFObject* value) { 524 void SkPDFDict::insertInt(const char key[], size_t value) {
338 return this->append(new SkPDFName(key), SkRef(value)); 525 this->insertInt(key, SkToS32(value));
339 }
340
341 void SkPDFDict::insertInt(const char key[], int32_t value) {
342 (void)this->append(new SkPDFName(key), new SkPDFInt(value));
343 } 526 }
344 527
345 void SkPDFDict::insertScalar(const char key[], SkScalar value) { 528 void SkPDFDict::insertScalar(const char key[], SkScalar value) {
346 (void)this->append(new SkPDFName(key), new SkPDFScalar(value)); 529 this->set(SkPDFUnion::Name(key), SkPDFUnion::Scalar(value));
347 } 530 }
348 531
349 void SkPDFDict::insertName(const char key[], const char name[]) { 532 void SkPDFDict::insertName(const char key[], const char name[]) {
350 (void)this->append(new SkPDFName(key), new SkPDFName(name)); 533 this->set(SkPDFUnion::Name(key), SkPDFUnion::Name(name));
534 }
535
536 void SkPDFDict::insertName(const char key[], const SkString& name) {
537 this->set(SkPDFUnion::Name(key), SkPDFUnion::Name(name));
538 }
539
540 void SkPDFDict::insertString(const char key[], const char value[]) {
541 this->set(SkPDFUnion::Name(key), SkPDFUnion::String(value));
542 }
543
544 void SkPDFDict::insertString(const char key[], const SkString& value) {
545 this->set(SkPDFUnion::Name(key), SkPDFUnion::String(value));
351 } 546 }
352 547
353 void SkPDFDict::clear() { 548 void SkPDFDict::clear() {
354 for (int i = 0; i < fValue.count(); i++) { 549 for (Record& rec : fRecords) {
355 SkASSERT(fValue[i].key); 550 rec.fKey.~SkPDFUnion();
356 SkASSERT(fValue[i].value); 551 rec.fValue.~SkPDFUnion();
357 fValue[i].key->unref();
358 fValue[i].value->unref();
359 } 552 }
360 fValue.reset(); 553 fRecords.reset();
361 }
362
363 void SkPDFDict::remove(const char key[]) {
364 SkASSERT(key);
365 SkPDFName name(key);
366 for (int i = 0; i < fValue.count(); i++) {
367 SkASSERT(fValue[i].key);
368 if (*(fValue[i].key) == name) {
369 fValue[i].key->unref();
370 SkASSERT(fValue[i].value);
371 fValue[i].value->unref();
372 fValue.removeShuffle(i);
373 return;
374 }
375 }
376 }
377
378 void SkPDFDict::mergeFrom(const SkPDFDict& other) {
379 for (int i = 0; i < other.fValue.count(); i++) {
380 *(fValue.append()) =
381 Rec(SkRef(other.fValue[i].key), SkRef(other.fValue[i].value));
382 }
383 } 554 }
384 555
385 //////////////////////////////////////////////////////////////////////////////// 556 ////////////////////////////////////////////////////////////////////////////////
386 557
387 SkPDFSubstituteMap::~SkPDFSubstituteMap() { 558 SkPDFSubstituteMap::~SkPDFSubstituteMap() {
388 fSubstituteMap.foreach( 559 fSubstituteMap.foreach(
389 [](SkPDFObject*, SkPDFObject** v) { (*v)->unref(); }); 560 [](SkPDFObject*, SkPDFObject** v) { (*v)->unref(); });
390 } 561 }
391 562
392 void SkPDFSubstituteMap::setSubstitute(SkPDFObject* original, 563 void SkPDFSubstituteMap::setSubstitute(SkPDFObject* original,
(...skipping 18 matching lines...) Expand all
411 fObjects.push(obj); 582 fObjects.push(obj);
412 return true; 583 return true;
413 } 584 }
414 585
415 int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const { 586 int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const {
416 int32_t* objectNumberFound = fObjectNumbers.find(obj); 587 int32_t* objectNumberFound = fObjectNumbers.find(obj);
417 SkASSERT(objectNumberFound); 588 SkASSERT(objectNumberFound);
418 return *objectNumberFound; 589 return *objectNumberFound;
419 } 590 }
420 591
OLDNEW
« src/pdf/SkPDFTypes.h ('K') | « src/pdf/SkPDFTypes.h ('k') | tests/PDFPrimitivesTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698