blob: eb0e20429c8ecfd558352b27933beb21b25c1c17 [file] [log] [blame]
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +00001/*
vandebo@chromium.org2a22e102011-01-25 21:01:34 +00002 * Copyright (C) 2011 Google Inc.
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +00003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "SkPDFCatalog.h"
18#include "SkPDFTypes.h"
19#include "SkStream.h"
20
vandebo@chromium.org094316b2011-03-04 03:15:13 +000021#ifdef SK_BUILD_FOR_WIN
22 #define SNPRINTF _snprintf
23#else
24 #define SNPRINTF snprintf
25#endif
26
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +000027SkPDFObject::SkPDFObject() {}
28SkPDFObject::~SkPDFObject() {}
29
vandebo@chromium.org2ef12d42011-07-06 23:31:24 +000030void SkPDFObject::emit(SkWStream* stream, SkPDFCatalog* catalog,
31 bool indirect) {
32 SkPDFObject* realObject = catalog->getSubstituteObject(this);
33 return realObject->emitObject(stream, catalog, indirect);
34}
35
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000036size_t SkPDFObject::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
37 SkDynamicMemoryWStream buffer;
vandebo@chromium.org2ef12d42011-07-06 23:31:24 +000038 emit(&buffer, catalog, indirect);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000039 return buffer.getOffset();
40}
41
vandebo@chromium.orga5180862010-10-26 19:48:49 +000042void SkPDFObject::getResources(SkTDArray<SkPDFObject*>* resourceList) {}
43
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000044void SkPDFObject::emitIndirectObject(SkWStream* stream, SkPDFCatalog* catalog) {
45 catalog->emitObjectNumber(stream, this);
46 stream->writeText(" obj\n");
vandebo@chromium.org2ef12d42011-07-06 23:31:24 +000047 emit(stream, catalog, false);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000048 stream->writeText("\nendobj\n");
49}
50
51size_t SkPDFObject::getIndirectOutputSize(SkPDFCatalog* catalog) {
52 return catalog->getObjectNumberSize(this) + strlen(" obj\n") +
53 this->getOutputSize(catalog, false) + strlen("\nendobj\n");
54}
55
vandebo@chromium.org421d6442011-07-20 17:39:01 +000056void SkPDFObject::AddResourceHelper(SkPDFObject* resource,
57 SkTDArray<SkPDFObject*>* list) {
58 list->push(resource);
59 resource->ref();
60}
61
62void SkPDFObject::GetResourcesHelper(SkTDArray<SkPDFObject*>* resources,
63 SkTDArray<SkPDFObject*>* result) {
64 if (resources->count()) {
65 result->setReserve(result->count() + resources->count());
66 for (int i = 0; i < resources->count(); i++) {
67 result->push((*resources)[i]);
68 (*resources)[i]->ref();
69 (*resources)[i]->getResources(result);
70 }
71 }
72}
73
74SkPDFObjRef::SkPDFObjRef(SkPDFObject* obj) : fObj(obj) {}
75SkPDFObjRef::~SkPDFObjRef() {}
76
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000077void SkPDFObjRef::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
78 bool indirect) {
79 SkASSERT(!indirect);
80 catalog->emitObjectNumber(stream, fObj.get());
81 stream->writeText(" R");
82}
83
84size_t SkPDFObjRef::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
85 SkASSERT(!indirect);
86 return catalog->getObjectNumberSize(fObj.get()) + strlen(" R");
87}
88
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +000089SkPDFInt::SkPDFInt(int32_t value) : fValue(value) {}
90SkPDFInt::~SkPDFInt() {}
91
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000092void SkPDFInt::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
93 bool indirect) {
94 if (indirect)
95 return emitIndirectObject(stream, catalog);
96 stream->writeDecAsText(fValue);
97}
98
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000099SkPDFBool::SkPDFBool(bool value) : fValue(value) {}
100SkPDFBool::~SkPDFBool() {}
101
102void SkPDFBool::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
103 bool indirect) {
104 SkASSERT(!indirect);
105 if (fValue) {
106 stream->writeText("true");
107 } else {
108 stream->writeText("false");
109 }
110}
111
112size_t SkPDFBool::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
113 SkASSERT(!indirect);
114 if (fValue)
115 return strlen("true");
116 return strlen("false");
117}
118
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000119SkPDFScalar::SkPDFScalar(SkScalar value) : fValue(value) {}
120SkPDFScalar::~SkPDFScalar() {}
121
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000122void SkPDFScalar::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
123 bool indirect) {
124 if (indirect)
125 return emitIndirectObject(stream, catalog);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000126
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000127 Append(fValue, stream);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000128}
129
130// static
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000131void SkPDFScalar::Append(SkScalar value, SkWStream* stream) {
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000132 // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and
133 // +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31).
134 // When using floats that are outside the whole value range, we can use
135 // integers instead.
136
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000137
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000138#if defined(SK_SCALAR_IS_FIXED)
epoger@google.com2047f002011-05-17 17:36:59 +0000139 stream->writeScalarAsText(value);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000140 return;
141#endif // SK_SCALAR_IS_FIXED
142
143#if !defined(SK_ALLOW_LARGE_PDF_SCALARS)
144 if (value > 32767 || value < -32767) {
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000145 stream->writeDecAsText(SkScalarRound(value));
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000146 return;
147 }
148
149 char buffer[SkStrAppendScalar_MaxSize];
150 char* end = SkStrAppendFixed(buffer, SkScalarToFixed(value));
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000151 stream->write(buffer, end - buffer);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000152 return;
153#endif // !SK_ALLOW_LARGE_PDF_SCALARS
154
155#if defined(SK_SCALAR_IS_FLOAT) && defined(SK_ALLOW_LARGE_PDF_SCALARS)
156 // Floats have 24bits of significance, so anything outside that range is
157 // no more precise than an int. (Plus PDF doesn't support scientific
158 // notation, so this clamps to SK_Max/MinS32).
159 if (value > (1 << 24) || value < -(1 << 24)) {
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000160 stream->writeDecAsText(value);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000161 return;
162 }
163 // Continue to enforce the PDF limits for small floats.
164 if (value < 1.0f/65536 && value > -1.0f/65536) {
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000165 stream->writeDecAsText(0);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000166 return;
167 }
168 // SkStrAppendFloat might still use scientific notation, so use snprintf
169 // directly..
170 static const int kFloat_MaxSize = 19;
171 char buffer[kFloat_MaxSize];
172 int len = SNPRINTF(buffer, kFloat_MaxSize, "%#.8f", value);
173 // %f always prints trailing 0s, so strip them.
174 for (; buffer[len - 1] == '0' && len > 0; len--) {
175 buffer[len - 1] = '\0';
176 }
177 if (buffer[len - 1] == '.') {
178 buffer[len - 1] = '\0';
179 }
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000180 stream->writeText(buffer);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000181 return;
182#endif // SK_SCALAR_IS_FLOAT && SK_ALLOW_LARGE_PDF_SCALARS
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000183}
184
185SkPDFString::SkPDFString(const char value[])
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000186 : fValue(FormatString(value, strlen(value))) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000187}
188
189SkPDFString::SkPDFString(const SkString& value)
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000190 : fValue(FormatString(value.c_str(), value.size())) {
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000191}
192
193SkPDFString::SkPDFString(const uint16_t* value, size_t len, bool wideChars)
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000194 : fValue(FormatString(value, len, wideChars)) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000195}
196
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000197SkPDFString::~SkPDFString() {}
198
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000199void SkPDFString::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
200 bool indirect) {
201 if (indirect)
202 return emitIndirectObject(stream, catalog);
203 stream->write(fValue.c_str(), fValue.size());
204}
205
206size_t SkPDFString::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
207 if (indirect)
208 return getIndirectOutputSize(catalog);
209 return fValue.size();
210}
211
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000212// static
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000213SkString SkPDFString::FormatString(const char* input, size_t len) {
214 return DoFormatString(input, len, false, false);
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000215}
216
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000217SkString SkPDFString::FormatString(const uint16_t* input, size_t len,
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000218 bool wideChars) {
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000219 return DoFormatString(input, len, true, wideChars);
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000220}
221
222// static
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000223SkString SkPDFString::DoFormatString(const void* input, size_t len,
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000224 bool wideInput, bool wideOutput) {
225 SkASSERT(len <= kMaxLen);
226 const uint16_t* win = (const uint16_t*) input;
227 const char* cin = (const char*) input;
228
229 if (wideOutput) {
230 SkASSERT(wideInput);
231 SkString result;
232 result.append("<");
233 for (size_t i = 0; i < len; i++)
234 result.appendHex(win[i], 4);
235 result.append(">");
236 return result;
237 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000238
239 // 7-bit clean is a heuristic to decide what string format to use;
240 // a 7-bit clean string should require little escaping.
241 bool sevenBitClean = true;
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000242 for (size_t i = 0; i < len; i++) {
243 SkASSERT(!wideInput || !(win[i] & ~0xFF));
244 char val = wideInput ? win[i] : cin[i];
vandebo@chromium.org2a22e102011-01-25 21:01:34 +0000245 if (val > '~' || val < ' ') {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000246 sevenBitClean = false;
247 break;
248 }
249 }
250
251 SkString result;
252 if (sevenBitClean) {
253 result.append("(");
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000254 for (size_t i = 0; i < len; i++) {
255 SkASSERT(!wideInput || !(win[i] & ~0xFF));
256 char val = wideInput ? win[i] : cin[i];
257 if (val == '\\' || val == '(' || val == ')')
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000258 result.append("\\");
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000259 result.append(&val, 1);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000260 }
261 result.append(")");
262 } else {
263 result.append("<");
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000264 for (size_t i = 0; i < len; i++) {
265 SkASSERT(!wideInput || !(win[i] & ~0xFF));
vandebo@chromium.org2a22e102011-01-25 21:01:34 +0000266 unsigned char val = wideInput ? win[i] : cin[i];
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000267 result.appendHex(val, 2);
268 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000269 result.append(">");
270 }
271
272 return result;
273}
274
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000275SkPDFName::SkPDFName(const char name[]) : fValue(FormatName(SkString(name))) {}
276SkPDFName::SkPDFName(const SkString& name) : fValue(FormatName(name)) {}
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000277SkPDFName::~SkPDFName() {}
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000278
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000279bool SkPDFName::operator==(const SkPDFName& b) const {
280 return fValue == b.fValue;
281}
282
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000283void SkPDFName::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
284 bool indirect) {
285 SkASSERT(!indirect);
286 stream->write(fValue.c_str(), fValue.size());
287}
288
289size_t SkPDFName::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
290 SkASSERT(!indirect);
291 return fValue.size();
292}
293
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000294// static
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000295SkString SkPDFName::FormatName(const SkString& input) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000296 SkASSERT(input.size() <= kMaxLen);
297
298 SkString result("/");
299 for (size_t i = 0; i < input.size(); i++) {
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000300 if (input[i] & 0x80 || input[i] < '!' || input[i] == '#') {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000301 result.append("#");
302 result.appendHex(input[i], 2);
303 } else {
304 result.append(input.c_str() + i, 1);
305 }
306 }
307
308 return result;
309}
310
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000311SkPDFArray::SkPDFArray() {}
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000312SkPDFArray::~SkPDFArray() {
reed@google.com2812b802011-07-19 15:46:40 +0000313 fValue.unrefAll();
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000314}
315
316void SkPDFArray::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
317 bool indirect) {
318 if (indirect)
319 return emitIndirectObject(stream, catalog);
320
321 stream->writeText("[");
322 for (int i = 0; i < fValue.count(); i++) {
vandebo@chromium.org2ef12d42011-07-06 23:31:24 +0000323 fValue[i]->emit(stream, catalog, false);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000324 if (i + 1 < fValue.count())
325 stream->writeText(" ");
326 }
327 stream->writeText("]");
328}
329
330size_t SkPDFArray::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
331 if (indirect)
332 return getIndirectOutputSize(catalog);
333
334 size_t result = strlen("[]");
335 if (fValue.count())
336 result += fValue.count() - 1;
337 for (int i = 0; i < fValue.count(); i++)
338 result += fValue[i]->getOutputSize(catalog, false);
339 return result;
340}
341
342void SkPDFArray::reserve(int length) {
343 SkASSERT(length <= kMaxLen);
344 fValue.setReserve(length);
345}
346
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000347SkPDFObject* SkPDFArray::setAt(int offset, SkPDFObject* value) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000348 SkASSERT(offset < fValue.count());
reed@google.com2812b802011-07-19 15:46:40 +0000349 value->ref();
350 fValue[offset]->unref();
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000351 fValue[offset] = value;
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000352 return value;
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000353}
354
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000355SkPDFObject* SkPDFArray::append(SkPDFObject* value) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000356 SkASSERT(fValue.count() < kMaxLen);
reed@google.com2812b802011-07-19 15:46:40 +0000357 value->ref();
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000358 fValue.push(value);
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000359 return value;
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000360}
361
reed@google.comc789cf12011-07-20 12:14:33 +0000362void SkPDFArray::appendInt(int32_t value) {
363 SkASSERT(fValue.count() < kMaxLen);
364 fValue.push(new SkPDFInt(value));
365}
366
367void SkPDFArray::appendScalar(SkScalar value) {
368 SkASSERT(fValue.count() < kMaxLen);
369 fValue.push(new SkPDFScalar(value));
370}
371
372void SkPDFArray::appendName(const char name[]) {
373 SkASSERT(fValue.count() < kMaxLen);
374 fValue.push(new SkPDFName(name));
375}
376
377///////////////////////////////////////////////////////////////////////////////
378
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000379SkPDFDict::SkPDFDict() {}
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000380
381SkPDFDict::SkPDFDict(const char type[]) {
vandebo@chromium.org06f7f402011-07-20 18:39:20 +0000382 insertName("Type", type);
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000383}
384
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000385SkPDFDict::~SkPDFDict() {
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000386 clear();
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000387}
388
389void SkPDFDict::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
390 bool indirect) {
391 if (indirect)
392 return emitIndirectObject(stream, catalog);
393
394 stream->writeText("<<");
395 for (int i = 0; i < fValue.count(); i++) {
396 fValue[i].key->emitObject(stream, catalog, false);
397 stream->writeText(" ");
vandebo@chromium.org2ef12d42011-07-06 23:31:24 +0000398 fValue[i].value->emit(stream, catalog, false);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000399 stream->writeText("\n");
400 }
401 stream->writeText(">>");
402}
403
404size_t SkPDFDict::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
405 if (indirect)
406 return getIndirectOutputSize(catalog);
407
408 size_t result = strlen("<<>>") + (fValue.count() * 2);
409 for (int i = 0; i < fValue.count(); i++) {
410 result += fValue[i].key->getOutputSize(catalog, false);
411 result += fValue[i].value->getOutputSize(catalog, false);
412 }
413 return result;
414}
415
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000416SkPDFObject* SkPDFDict::insert(SkPDFName* key, SkPDFObject* value) {
reed@google.com2812b802011-07-19 15:46:40 +0000417 key->ref();
418 value->ref();
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000419 struct Rec* newEntry = fValue.append();
420 newEntry->key = key;
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000421 newEntry->value = value;
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000422 return value;
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000423}
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000424
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000425SkPDFObject* SkPDFDict::insert(const char key[], SkPDFObject* value) {
reed@google.com2812b802011-07-19 15:46:40 +0000426 value->ref();
427 struct Rec* newEntry = fValue.append();
428 newEntry->key = new SkPDFName(key);
429 newEntry->value = value;
430 return value;
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000431}
432
reed@google.comc789cf12011-07-20 12:14:33 +0000433void SkPDFDict::insertInt(const char key[], int32_t value) {
434 struct Rec* newEntry = fValue.append();
435 newEntry->key = new SkPDFName(key);
436 newEntry->value = new SkPDFInt(value);
437}
438
439void SkPDFDict::insertScalar(const char key[], SkScalar value) {
440 struct Rec* newEntry = fValue.append();
441 newEntry->key = new SkPDFName(key);
442 newEntry->value = new SkPDFScalar(value);
443}
444
445void SkPDFDict::insertName(const char key[], const char name[]) {
446 struct Rec* newEntry = fValue.append();
447 newEntry->key = new SkPDFName(key);
448 newEntry->value = new SkPDFName(name);
449}
450
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000451void SkPDFDict::clear() {
452 for (int i = 0; i < fValue.count(); i++) {
reed@google.com2812b802011-07-19 15:46:40 +0000453 fValue[i].key->unref();
454 fValue[i].value->unref();
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000455 }
456 fValue.reset();
457}
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000458
459SkPDFDict::Iter::Iter(const SkPDFDict& dict)
460 : fIter(dict.fValue.begin()),
461 fStop(dict.fValue.end()) {
462}
463
464SkPDFName* SkPDFDict::Iter::next(SkPDFObject** value) {
465 if (fIter != fStop) {
466 Rec* cur = fIter;
467 fIter++;
468 *value = cur->value;
469 return cur->key;
470 }
471 *value = NULL;
472 return NULL;
473}