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

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-25 (Saturday) 09:40:48 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
« no previous file with comments | « src/pdf/SkPDFTypes.h ('k') | tests/PDFPrimitivesTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) {
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 #ifdef SK_DEBUG
87 // Most names need no escaping. Such names are handled as static
88 // const strings.
89 bool 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.
102 static 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
128 static SkString escape_name(const SkString& name) {
129 return escape_name(name.c_str(), name.size());
130 }
131
132 static void write_string(SkWStream* o, const SkString& s) {
133 o->write(s.c_str(), s.size());
134 }
135
136 static SkString format_string(const SkString& s) {
137 return SkPDFString::FormatString(s.c_str(), s.size());
138 }
139
140 static SkString format_string(const char* s) {
141 return SkPDFString::FormatString(s, strlen(s));
142 }
143
144 void 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
186 void 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
212 SkPDFUnion SkPDFUnion::Int(int32_t value) {
213 SkPDFUnion u(Type::kInt);
214 u.fIntValue = value;
215 return u.move();
216 }
217
218 SkPDFUnion SkPDFUnion::Bool(bool value) {
219 SkPDFUnion u(Type::kBool);
220 u.fBoolValue = value;
221 return u.move();
222 }
223
224 SkPDFUnion SkPDFUnion::Scalar(SkScalar value) {
225 SkPDFUnion u(Type::kScalar);
226 u.fScalarValue = value;
227 return u.move();
228 }
229
230 SkPDFUnion 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
238 SkPDFUnion SkPDFUnion::String(const char* value) {
239 SkPDFUnion u(Type::kString);
240 SkASSERT(value);
241 u.fStaticString = value;
242 return u.move();
243 }
244
245 SkPDFUnion 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
251 SkPDFUnion 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
257 SkPDFUnion SkPDFUnion::ObjRef(SkPDFObject* ptr) {
258 SkPDFUnion u(Type::kObjRef);
259 SkASSERT(ptr);
260 u.fObject = ptr;
261 return u.move();
262 }
263
264 SkPDFUnion SkPDFUnion::Object(SkPDFObject* ptr) {
265 SkPDFUnion u(Type::kObject);
266 SkASSERT(ptr);
267 u.fObject = ptr;
268 return u.move();
42 } 269 }
43 270
44 //////////////////////////////////////////////////////////////////////////////// 271 ////////////////////////////////////////////////////////////////////////////////
45 272
46 SkPDFInt::SkPDFInt(int32_t value) : fValue(value) {} 273 void SkPDFAtom::emitObject(SkWStream* stream,
47 SkPDFInt::~SkPDFInt() {} 274 const SkPDFObjNumMap& objNumMap,
48 275 const SkPDFSubstituteMap& substitutes) {
49 void SkPDFInt::emitObject(SkWStream* stream, 276 fValue.emitObject(stream, objNumMap, substitutes);
50 const SkPDFObjNumMap&, 277 }
51 const SkPDFSubstituteMap&) { 278 void SkPDFAtom::addResources(SkPDFObjNumMap* map,
52 stream->writeDecAsText(fValue); 279 const SkPDFSubstituteMap& substitutes) const {
280 fValue.addResources(map, substitutes);
53 } 281 }
54 282
55 //////////////////////////////////////////////////////////////////////////////// 283 ////////////////////////////////////////////////////////////////////////////////
56 284
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 285 // static
78 void SkPDFScalar::Append(SkScalar value, SkWStream* stream) { 286 void SkPDFScalar::Append(SkScalar value, SkWStream* stream) {
79 // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and 287 // 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). 288 // +/- 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 289 // When using floats that are outside the whole value range, we can use
82 // integers instead. 290 // integers instead.
83 291
84 #if !defined(SK_ALLOW_LARGE_PDF_SCALARS) 292 #if !defined(SK_ALLOW_LARGE_PDF_SCALARS)
85 if (value > 32767 || value < -32767) { 293 if (value > 32767 || value < -32767) {
86 stream->writeDecAsText(SkScalarRoundToInt(value)); 294 stream->writeDecAsText(SkScalarRoundToInt(value));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 if (buffer[len - 1] == '.') { 326 if (buffer[len - 1] == '.') {
119 buffer[len - 1] = '\0'; 327 buffer[len - 1] = '\0';
120 } 328 }
121 stream->writeText(buffer); 329 stream->writeText(buffer);
122 return; 330 return;
123 #endif // SK_ALLOW_LARGE_PDF_SCALARS 331 #endif // SK_ALLOW_LARGE_PDF_SCALARS
124 } 332 }
125 333
126 //////////////////////////////////////////////////////////////////////////////// 334 ////////////////////////////////////////////////////////////////////////////////
127 335
128 SkPDFString::SkPDFString(const char value[]) 336 // static
129 : fValue(FormatString(value, strlen(value))) {
130 }
131 337
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) { 338 SkString SkPDFString::FormatString(const char* cin, size_t len) {
146 SkASSERT(len <= kMaxLen); 339 SkASSERT(len <= kMaxLen);
147 340
148 // 7-bit clean is a heuristic to decide what string format to use; 341 // 7-bit clean is a heuristic to decide what string format to use;
149 // a 7-bit clean string should require little escaping. 342 // a 7-bit clean string should require little escaping.
150 bool sevenBitClean = true; 343 bool sevenBitClean = true;
151 size_t characterCount = 2 + len; 344 size_t characterCount = 2 + len;
152 for (size_t i = 0; i < len; i++) { 345 for (size_t i = 0; i < len; i++) {
153 if (cin[i] > '~' || cin[i] < ' ') { 346 if (cin[i] > '~' || cin[i] < ' ') {
154 sevenBitClean = false; 347 sevenBitClean = false;
(...skipping 25 matching lines...) Expand all
180 *str++ = gHex[(c >> 4) & 0xF]; 373 *str++ = gHex[(c >> 4) & 0xF];
181 *str++ = gHex[(c ) & 0xF]; 374 *str++ = gHex[(c ) & 0xF];
182 } 375 }
183 *str++ = '>'; 376 *str++ = '>';
184 } 377 }
185 return result; 378 return result;
186 } 379 }
187 380
188 //////////////////////////////////////////////////////////////////////////////// 381 ////////////////////////////////////////////////////////////////////////////////
189 382
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() {} 383 SkPDFArray::SkPDFArray() {}
227 SkPDFArray::~SkPDFArray() { 384 SkPDFArray::~SkPDFArray() {
228 fValue.unrefAll(); 385 for (SkPDFUnion& value : fValues) {
386 value.~SkPDFUnion();
387 }
388 fValues.reset();
229 } 389 }
230 390
391 int SkPDFArray::size() const { return fValues.count(); }
392
393 void SkPDFArray::reserve(int length) { fValues.setReserve(length); }
394
231 void SkPDFArray::emitObject(SkWStream* stream, 395 void SkPDFArray::emitObject(SkWStream* stream,
232 const SkPDFObjNumMap& objNumMap, 396 const SkPDFObjNumMap& objNumMap,
233 const SkPDFSubstituteMap& substitutes) { 397 const SkPDFSubstituteMap& substitutes) {
234 stream->writeText("["); 398 stream->writeText("[");
235 for (int i = 0; i < fValue.count(); i++) { 399 for (int i = 0; i < fValues.count(); i++) {
236 SkASSERT(substitutes.getSubstitute(fValue[i]) == fValue[i]); 400 fValues[i].emitObject(stream, objNumMap, substitutes);
237 fValue[i]->emitObject(stream, objNumMap, substitutes); 401 if (i + 1 < fValues.count()) {
238 if (i + 1 < fValue.count()) {
239 stream->writeText(" "); 402 stream->writeText(" ");
240 } 403 }
241 } 404 }
242 stream->writeText("]"); 405 stream->writeText("]");
243 } 406 }
244 407
245 void SkPDFArray::addResources(SkPDFObjNumMap* catalog, 408 void SkPDFArray::addResources(SkPDFObjNumMap* catalog,
246 const SkPDFSubstituteMap& substitutes) const { 409 const SkPDFSubstituteMap& substitutes) const {
247 for (int i = 0; i < fValue.count(); i++) { 410 for (const SkPDFUnion& value : fValues) {
248 SkASSERT(substitutes.getSubstitute(fValue[i]) == fValue[i]); 411 value.addResources(catalog, substitutes);
249 fValue[i]->addResources(catalog, substitutes);
250 } 412 }
251 } 413 }
252 414
253 void SkPDFArray::reserve(int length) { 415 void SkPDFArray::append(SkPDFUnion&& value) {
254 SkASSERT(length <= kMaxLen); 416 SkNEW_PLACEMENT_ARGS(fValues.append(), SkPDFUnion, (value.move()));
255 fValue.setReserve(length);
256 } 417 }
257 418
258 SkPDFObject* SkPDFArray::append(SkPDFObject* value) { 419 SkPDFObject* SkPDFArray::append(SkPDFObject* value) {
259 SkASSERT(fValue.count() < kMaxLen); 420 // DEPRECATED
260 value->ref(); 421 this->append(SkPDFUnion::Object(SkRef(value)));
261 fValue.push(value);
262 return value; 422 return value;
263 } 423 }
264 424
265 void SkPDFArray::appendInt(int32_t value) { 425 void SkPDFArray::appendInt(int32_t value) {
266 SkASSERT(fValue.count() < kMaxLen); 426 this->append(SkPDFUnion::Int(value));
267 fValue.push(new SkPDFInt(value)); 427 }
428
429 void SkPDFArray::appendBool(bool value) {
430 this->append(SkPDFUnion::Bool(value));
268 } 431 }
269 432
270 void SkPDFArray::appendScalar(SkScalar value) { 433 void SkPDFArray::appendScalar(SkScalar value) {
271 SkASSERT(fValue.count() < kMaxLen); 434 this->append(SkPDFUnion::Scalar(value));
272 fValue.push(new SkPDFScalar(value));
273 } 435 }
274 436
275 void SkPDFArray::appendName(const char name[]) { 437 void SkPDFArray::appendName(const char name[]) {
276 SkASSERT(fValue.count() < kMaxLen); 438 this->append(SkPDFUnion::Name(SkString(name)));
277 fValue.push(new SkPDFName(name)); 439 }
440
441 void SkPDFArray::appendName(const SkString& name) {
442 this->append(SkPDFUnion::Name(name));
443 }
444
445 void SkPDFArray::appendString(const SkString& value) {
446 this->append(SkPDFUnion::String(value));
447 }
448
449 void SkPDFArray::appendString(const char value[]) {
450 this->append(SkPDFUnion::String(value));
451 }
452
453 void SkPDFArray::appendObject(SkPDFObject* value) {
454 this->append(SkPDFUnion::Object(value));
455 }
456
457 void SkPDFArray::appendObjRef(SkPDFObject* value) {
458 this->append(SkPDFUnion::ObjRef(value));
278 } 459 }
279 460
280 /////////////////////////////////////////////////////////////////////////////// 461 ///////////////////////////////////////////////////////////////////////////////
281 462
282 SkPDFDict::SkPDFDict() {} 463 SkPDFDict::SkPDFDict() {}
283 464
284 SkPDFDict::SkPDFDict(const char type[]) { 465 SkPDFDict::~SkPDFDict() { this->clear(); }
285 insertName("Type", type);
286 }
287 466
288 SkPDFDict::~SkPDFDict() { 467 SkPDFDict::SkPDFDict(const char type[]) { this->insertName("Type", type); }
289 clear();
290 }
291
292 int SkPDFDict::size() const {
293 return fValue.count();
294 }
295 468
296 void SkPDFDict::emitObject(SkWStream* stream, 469 void SkPDFDict::emitObject(SkWStream* stream,
297 const SkPDFObjNumMap& objNumMap, 470 const SkPDFObjNumMap& objNumMap,
298 const SkPDFSubstituteMap& substitutes) { 471 const SkPDFSubstituteMap& substitutes) {
299 stream->writeText("<<"); 472 stream->writeText("<<");
300 for (int i = 0; i < fValue.count(); i++) { 473 for (int i = 0; i < fRecords.count(); i++) {
301 SkASSERT(fValue[i].key); 474 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(" "); 475 stream->writeText(" ");
307 fValue[i].value->emitObject(stream, objNumMap, substitutes); 476 fRecords[i].fValue.emitObject(stream, objNumMap, substitutes);
308 if (i + 1 < fValue.count()) { 477 if (i + 1 < fRecords.count()) {
309 stream->writeText("\n"); 478 stream->writeText("\n");
310 } 479 }
311 } 480 }
312 stream->writeText(">>"); 481 stream->writeText(">>");
313 } 482 }
314 483
315 void SkPDFDict::addResources(SkPDFObjNumMap* catalog, 484 void SkPDFDict::addResources(SkPDFObjNumMap* catalog,
316 const SkPDFSubstituteMap& substitutes) const { 485 const SkPDFSubstituteMap& substitutes) const {
317 for (int i = 0; i < fValue.count(); i++) { 486 for (int i = 0; i < fRecords.count(); i++) {
318 SkASSERT(fValue[i].key); 487 fRecords[i].fKey.addResources(catalog, substitutes);
319 SkASSERT(fValue[i].value); 488 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 } 489 }
324 } 490 }
325 491
326 SkPDFObject* SkPDFDict::append(SkPDFName* key, SkPDFObject* value) { 492 void SkPDFDict::set(SkPDFUnion&& name, SkPDFUnion&& value) {
327 SkASSERT(key); 493 Record* rec = fRecords.append();
328 SkASSERT(value); 494 SkASSERT(name.isName());
329 *(fValue.append()) = Rec(key, value); 495 SkNEW_PLACEMENT_ARGS(&rec->fKey, SkPDFUnion, (name.move()));
496 SkNEW_PLACEMENT_ARGS(&rec->fValue, SkPDFUnion, (value.move()));
497 }
498
499 int SkPDFDict::size() const { return fRecords.count(); }
500
501 void SkPDFDict::insertObjRef(const char key[], SkPDFObject* value) {
502 this->set(SkPDFUnion::Name(key), SkPDFUnion::ObjRef(value));
503 }
504 void SkPDFDict::insertObjRef(const SkString& key, SkPDFObject* value) {
505 this->set(SkPDFUnion::Name(key), SkPDFUnion::ObjRef(value));
506 }
507
508 void SkPDFDict::insertObject(const char key[], SkPDFObject* value) {
509 this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(value));
510 }
511 void SkPDFDict::insertObject(const SkString& key, SkPDFObject* value) {
512 this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(value));
513 }
514
515 // DEPRECATED
516 SkPDFObject* SkPDFDict::insert(const char key[], SkPDFObject* value) {
517 this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(SkRef(value)));
330 return value; 518 return value;
331 } 519 }
332 520
333 SkPDFObject* SkPDFDict::insert(SkPDFName* key, SkPDFObject* value) { 521 void SkPDFDict::insertInt(const char key[], int32_t value) {
334 return this->append(SkRef(key), SkRef(value)); 522 this->set(SkPDFUnion::Name(key), SkPDFUnion::Int(value));
335 } 523 }
336 524
337 SkPDFObject* SkPDFDict::insert(const char key[], SkPDFObject* value) { 525 void SkPDFDict::insertInt(const char key[], size_t value) {
338 return this->append(new SkPDFName(key), SkRef(value)); 526 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 } 527 }
344 528
345 void SkPDFDict::insertScalar(const char key[], SkScalar value) { 529 void SkPDFDict::insertScalar(const char key[], SkScalar value) {
346 (void)this->append(new SkPDFName(key), new SkPDFScalar(value)); 530 this->set(SkPDFUnion::Name(key), SkPDFUnion::Scalar(value));
347 } 531 }
348 532
349 void SkPDFDict::insertName(const char key[], const char name[]) { 533 void SkPDFDict::insertName(const char key[], const char name[]) {
350 (void)this->append(new SkPDFName(key), new SkPDFName(name)); 534 this->set(SkPDFUnion::Name(key), SkPDFUnion::Name(name));
535 }
536
537 void SkPDFDict::insertName(const char key[], const SkString& name) {
538 this->set(SkPDFUnion::Name(key), SkPDFUnion::Name(name));
539 }
540
541 void SkPDFDict::insertString(const char key[], const char value[]) {
542 this->set(SkPDFUnion::Name(key), SkPDFUnion::String(value));
543 }
544
545 void SkPDFDict::insertString(const char key[], const SkString& value) {
546 this->set(SkPDFUnion::Name(key), SkPDFUnion::String(value));
351 } 547 }
352 548
353 void SkPDFDict::clear() { 549 void SkPDFDict::clear() {
354 for (int i = 0; i < fValue.count(); i++) { 550 for (Record& rec : fRecords) {
355 SkASSERT(fValue[i].key); 551 rec.fKey.~SkPDFUnion();
356 SkASSERT(fValue[i].value); 552 rec.fValue.~SkPDFUnion();
357 fValue[i].key->unref();
358 fValue[i].value->unref();
359 } 553 }
360 fValue.reset(); 554 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 } 555 }
384 556
385 //////////////////////////////////////////////////////////////////////////////// 557 ////////////////////////////////////////////////////////////////////////////////
386 558
387 SkPDFSubstituteMap::~SkPDFSubstituteMap() { 559 SkPDFSubstituteMap::~SkPDFSubstituteMap() {
388 fSubstituteMap.foreach( 560 fSubstituteMap.foreach(
389 [](SkPDFObject*, SkPDFObject** v) { (*v)->unref(); }); 561 [](SkPDFObject*, SkPDFObject** v) { (*v)->unref(); });
390 } 562 }
391 563
392 void SkPDFSubstituteMap::setSubstitute(SkPDFObject* original, 564 void SkPDFSubstituteMap::setSubstitute(SkPDFObject* original,
(...skipping 18 matching lines...) Expand all
411 fObjects.push(obj); 583 fObjects.push(obj);
412 return true; 584 return true;
413 } 585 }
414 586
415 int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const { 587 int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const {
416 int32_t* objectNumberFound = fObjectNumbers.find(obj); 588 int32_t* objectNumberFound = fObjectNumbers.find(obj);
417 SkASSERT(objectNumberFound); 589 SkASSERT(objectNumberFound);
418 return *objectNumberFound; 590 return *objectNumberFound;
419 } 591 }
420 592
OLDNEW
« no previous file with comments | « src/pdf/SkPDFTypes.h ('k') | tests/PDFPrimitivesTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698