blob: 7902e599cee875b80d19d533fdc7a39cce837f4b [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
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000010#include "SkPDFCatalog.h"
11#include "SkPDFTypes.h"
12#include "SkStream.h"
13
vandebo@chromium.org094316b2011-03-04 03:15:13 +000014#ifdef SK_BUILD_FOR_WIN
15 #define SNPRINTF _snprintf
16#else
17 #define SNPRINTF snprintf
18#endif
19
halcanary6a144342015-01-23 11:45:10 -080020////////////////////////////////////////////////////////////////////////////////
21
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +000022SkPDFObjRef::SkPDFObjRef(SkPDFObject* obj) : fObj(obj) {
23 SkSafeRef(obj);
24}
25
vandebo@chromium.org421d6442011-07-20 17:39:01 +000026SkPDFObjRef::~SkPDFObjRef() {}
27
halcanary4fc48af2015-01-12 10:07:50 -080028void SkPDFObjRef::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
halcanarybf799cd2015-02-10 13:32:09 -080029 stream->writeDecAsText(catalog->getObjectNumber(fObj.get()));
30 stream->writeText(" 0 R"); // Generation number is always 0.
31}
32
33void SkPDFObjRef::addResources(SkTSet<SkPDFObject*>* resourceSet,
34 SkPDFCatalog* catalog) const {
35 SkPDFObject* obj = catalog->getSubstituteObject(fObj);
36 SkASSERT(obj);
37 if (resourceSet->add(obj)) {
38 obj->addResources(resourceSet, catalog);
39 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000040}
41
halcanary6a144342015-01-23 11:45:10 -080042////////////////////////////////////////////////////////////////////////////////
43
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +000044SkPDFInt::SkPDFInt(int32_t value) : fValue(value) {}
45SkPDFInt::~SkPDFInt() {}
46
halcanary4fc48af2015-01-12 10:07:50 -080047void SkPDFInt::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000048 stream->writeDecAsText(fValue);
49}
50
halcanary6a144342015-01-23 11:45:10 -080051////////////////////////////////////////////////////////////////////////////////
52
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000053SkPDFBool::SkPDFBool(bool value) : fValue(value) {}
54SkPDFBool::~SkPDFBool() {}
55
halcanary4fc48af2015-01-12 10:07:50 -080056void SkPDFBool::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000057 if (fValue) {
58 stream->writeText("true");
59 } else {
60 stream->writeText("false");
61 }
62}
63
halcanary6a144342015-01-23 11:45:10 -080064////////////////////////////////////////////////////////////////////////////////
65
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +000066SkPDFScalar::SkPDFScalar(SkScalar value) : fValue(value) {}
67SkPDFScalar::~SkPDFScalar() {}
68
halcanary4fc48af2015-01-12 10:07:50 -080069void SkPDFScalar::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000070 Append(fValue, stream);
vandebo@chromium.org094316b2011-03-04 03:15:13 +000071}
72
73// static
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000074void SkPDFScalar::Append(SkScalar value, SkWStream* stream) {
vandebo@chromium.org094316b2011-03-04 03:15:13 +000075 // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and
76 // +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31).
77 // When using floats that are outside the whole value range, we can use
78 // integers instead.
79
vandebo@chromium.org094316b2011-03-04 03:15:13 +000080#if !defined(SK_ALLOW_LARGE_PDF_SCALARS)
81 if (value > 32767 || value < -32767) {
reed@google.come1ca7052013-12-17 19:22:07 +000082 stream->writeDecAsText(SkScalarRoundToInt(value));
vandebo@chromium.org094316b2011-03-04 03:15:13 +000083 return;
84 }
85
86 char buffer[SkStrAppendScalar_MaxSize];
87 char* end = SkStrAppendFixed(buffer, SkScalarToFixed(value));
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000088 stream->write(buffer, end - buffer);
vandebo@chromium.org094316b2011-03-04 03:15:13 +000089 return;
90#endif // !SK_ALLOW_LARGE_PDF_SCALARS
91
reed@google.com8f4d2302013-12-17 16:44:46 +000092#if defined(SK_ALLOW_LARGE_PDF_SCALARS)
vandebo@chromium.org094316b2011-03-04 03:15:13 +000093 // Floats have 24bits of significance, so anything outside that range is
94 // no more precise than an int. (Plus PDF doesn't support scientific
95 // notation, so this clamps to SK_Max/MinS32).
96 if (value > (1 << 24) || value < -(1 << 24)) {
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +000097 stream->writeDecAsText(value);
vandebo@chromium.org094316b2011-03-04 03:15:13 +000098 return;
99 }
100 // Continue to enforce the PDF limits for small floats.
101 if (value < 1.0f/65536 && value > -1.0f/65536) {
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000102 stream->writeDecAsText(0);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000103 return;
104 }
105 // SkStrAppendFloat might still use scientific notation, so use snprintf
106 // directly..
107 static const int kFloat_MaxSize = 19;
108 char buffer[kFloat_MaxSize];
109 int len = SNPRINTF(buffer, kFloat_MaxSize, "%#.8f", value);
110 // %f always prints trailing 0s, so strip them.
111 for (; buffer[len - 1] == '0' && len > 0; len--) {
112 buffer[len - 1] = '\0';
113 }
114 if (buffer[len - 1] == '.') {
115 buffer[len - 1] = '\0';
116 }
vandebo@chromium.orgcae5fba2011-03-28 19:03:50 +0000117 stream->writeText(buffer);
vandebo@chromium.org094316b2011-03-04 03:15:13 +0000118 return;
reed@google.com8f4d2302013-12-17 16:44:46 +0000119#endif // SK_ALLOW_LARGE_PDF_SCALARS
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000120}
121
halcanary6a144342015-01-23 11:45:10 -0800122////////////////////////////////////////////////////////////////////////////////
123
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000124SkPDFString::SkPDFString(const char value[])
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000125 : fValue(FormatString(value, strlen(value))) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000126}
127
128SkPDFString::SkPDFString(const SkString& value)
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000129 : fValue(FormatString(value.c_str(), value.size())) {
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000130}
131
132SkPDFString::SkPDFString(const uint16_t* value, size_t len, bool wideChars)
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000133 : fValue(FormatString(value, len, wideChars)) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000134}
135
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000136SkPDFString::~SkPDFString() {}
137
halcanary4fc48af2015-01-12 10:07:50 -0800138void SkPDFString::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000139 stream->write(fValue.c_str(), fValue.size());
140}
141
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000142// static
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000143SkString SkPDFString::FormatString(const char* input, size_t len) {
144 return DoFormatString(input, len, false, false);
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000145}
146
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000147SkString SkPDFString::FormatString(const uint16_t* input, size_t len,
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000148 bool wideChars) {
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000149 return DoFormatString(input, len, true, wideChars);
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000150}
151
152// static
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000153SkString SkPDFString::DoFormatString(const void* input, size_t len,
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000154 bool wideInput, bool wideOutput) {
155 SkASSERT(len <= kMaxLen);
156 const uint16_t* win = (const uint16_t*) input;
157 const char* cin = (const char*) input;
158
159 if (wideOutput) {
160 SkASSERT(wideInput);
161 SkString result;
162 result.append("<");
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000163 for (size_t i = 0; i < len; i++) {
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000164 result.appendHex(win[i], 4);
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000165 }
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000166 result.append(">");
167 return result;
168 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000169
170 // 7-bit clean is a heuristic to decide what string format to use;
171 // a 7-bit clean string should require little escaping.
172 bool sevenBitClean = true;
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000173 for (size_t i = 0; i < len; i++) {
174 SkASSERT(!wideInput || !(win[i] & ~0xFF));
175 char val = wideInput ? win[i] : cin[i];
vandebo@chromium.org2a22e102011-01-25 21:01:34 +0000176 if (val > '~' || val < ' ') {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000177 sevenBitClean = false;
178 break;
179 }
180 }
181
182 SkString result;
183 if (sevenBitClean) {
184 result.append("(");
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000185 for (size_t i = 0; i < len; i++) {
186 SkASSERT(!wideInput || !(win[i] & ~0xFF));
187 char val = wideInput ? win[i] : cin[i];
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000188 if (val == '\\' || val == '(' || val == ')') {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000189 result.append("\\");
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000190 }
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000191 result.append(&val, 1);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000192 }
193 result.append(")");
194 } else {
195 result.append("<");
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000196 for (size_t i = 0; i < len; i++) {
197 SkASSERT(!wideInput || !(win[i] & ~0xFF));
vandebo@chromium.org2a22e102011-01-25 21:01:34 +0000198 unsigned char val = wideInput ? win[i] : cin[i];
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000199 result.appendHex(val, 2);
200 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000201 result.append(">");
202 }
203
204 return result;
205}
206
halcanary6a144342015-01-23 11:45:10 -0800207////////////////////////////////////////////////////////////////////////////////
208
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000209SkPDFName::SkPDFName(const char name[]) : fValue(FormatName(SkString(name))) {}
210SkPDFName::SkPDFName(const SkString& name) : fValue(FormatName(name)) {}
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000211SkPDFName::~SkPDFName() {}
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000212
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000213bool SkPDFName::operator==(const SkPDFName& b) const {
214 return fValue == b.fValue;
215}
216
halcanary4fc48af2015-01-12 10:07:50 -0800217void SkPDFName::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000218 stream->write(fValue.c_str(), fValue.size());
219}
220
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000221// static
reed@google.comf6c3ebd2011-07-20 17:20:28 +0000222SkString SkPDFName::FormatName(const SkString& input) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000223 SkASSERT(input.size() <= kMaxLen);
vandebo@chromium.org251a7662012-09-21 17:50:50 +0000224 // TODO(vandebo) If more escaping is needed, improve the linear scan.
225 static const char escaped[] = "#/%()<>[]{}";
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000226
227 SkString result("/");
228 for (size_t i = 0; i < input.size(); i++) {
vandebo@chromium.org251a7662012-09-21 17:50:50 +0000229 if (input[i] & 0x80 || input[i] < '!' || strchr(escaped, input[i])) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000230 result.append("#");
vandebo@chromium.orgc0376fe2012-03-05 18:44:33 +0000231 // Mask with 0xFF to avoid sign extension. i.e. #FFFFFF81
232 result.appendHex(input[i] & 0xFF, 2);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000233 } else {
234 result.append(input.c_str() + i, 1);
235 }
236 }
237
238 return result;
239}
240
halcanary6a144342015-01-23 11:45:10 -0800241////////////////////////////////////////////////////////////////////////////////
242
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000243SkPDFArray::SkPDFArray() {}
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000244SkPDFArray::~SkPDFArray() {
reed@google.com2812b802011-07-19 15:46:40 +0000245 fValue.unrefAll();
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000246}
247
halcanary4fc48af2015-01-12 10:07:50 -0800248void SkPDFArray::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000249 stream->writeText("[");
250 for (int i = 0; i < fValue.count(); i++) {
halcanary6a144342015-01-23 11:45:10 -0800251 catalog->getSubstituteObject(fValue[i])->emitObject(stream, catalog);
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000252 if (i + 1 < fValue.count()) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000253 stream->writeText(" ");
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000254 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000255 }
256 stream->writeText("]");
257}
258
halcanarybf799cd2015-02-10 13:32:09 -0800259void SkPDFArray::addResources(SkTSet<SkPDFObject*>* resourceSet,
260 SkPDFCatalog* catalog) const {
261 for (int i = 0; i < fValue.count(); i++) {
262 catalog->getSubstituteObject(fValue[i])
263 ->addResources(resourceSet, catalog);
264 }
265}
266
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000267void SkPDFArray::reserve(int length) {
268 SkASSERT(length <= kMaxLen);
269 fValue.setReserve(length);
270}
271
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000272SkPDFObject* SkPDFArray::setAt(int offset, SkPDFObject* value) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000273 SkASSERT(offset < fValue.count());
reed@google.com2812b802011-07-19 15:46:40 +0000274 value->ref();
275 fValue[offset]->unref();
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000276 fValue[offset] = value;
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000277 return value;
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000278}
279
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000280SkPDFObject* SkPDFArray::append(SkPDFObject* value) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000281 SkASSERT(fValue.count() < kMaxLen);
reed@google.com2812b802011-07-19 15:46:40 +0000282 value->ref();
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000283 fValue.push(value);
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000284 return value;
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000285}
286
reed@google.comc789cf12011-07-20 12:14:33 +0000287void SkPDFArray::appendInt(int32_t value) {
288 SkASSERT(fValue.count() < kMaxLen);
289 fValue.push(new SkPDFInt(value));
290}
291
292void SkPDFArray::appendScalar(SkScalar value) {
293 SkASSERT(fValue.count() < kMaxLen);
294 fValue.push(new SkPDFScalar(value));
295}
296
297void SkPDFArray::appendName(const char name[]) {
298 SkASSERT(fValue.count() < kMaxLen);
299 fValue.push(new SkPDFName(name));
300}
301
302///////////////////////////////////////////////////////////////////////////////
303
vandebo@chromium.orgf66025d2010-10-01 23:26:55 +0000304SkPDFDict::SkPDFDict() {}
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000305
306SkPDFDict::SkPDFDict(const char type[]) {
vandebo@chromium.org06f7f402011-07-20 18:39:20 +0000307 insertName("Type", type);
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000308}
309
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000310SkPDFDict::~SkPDFDict() {
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000311 clear();
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000312}
313
halcanary1f8ed022014-06-27 10:37:27 -0700314int SkPDFDict::size() const {
315 SkAutoMutexAcquire lock(fMutex);
316 return fValue.count();
317}
318
halcanary4fc48af2015-01-12 10:07:50 -0800319void SkPDFDict::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
halcanary1f8ed022014-06-27 10:37:27 -0700320 SkAutoMutexAcquire lock(fMutex); // If another thread triggers a
321 // resize while this thread is in
322 // the for-loop, we can be left
323 // with a bad fValue[i] reference.
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000324 stream->writeText("<<");
325 for (int i = 0; i < fValue.count(); i++) {
halcanary1f8ed022014-06-27 10:37:27 -0700326 SkASSERT(fValue[i].key);
327 SkASSERT(fValue[i].value);
halcanary4fc48af2015-01-12 10:07:50 -0800328 fValue[i].key->emitObject(stream, catalog);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000329 stream->writeText(" ");
halcanary6a144342015-01-23 11:45:10 -0800330 catalog->getSubstituteObject(fValue[i].value)
331 ->emitObject(stream, catalog);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000332 stream->writeText("\n");
333 }
334 stream->writeText(">>");
335}
336
halcanarybf799cd2015-02-10 13:32:09 -0800337void SkPDFDict::addResources(SkTSet<SkPDFObject*>* resourceSet,
338 SkPDFCatalog* catalog) const {
339 for (int i = 0; i < fValue.count(); i++) {
340 SkASSERT(fValue[i].key);
341 SkASSERT(fValue[i].value);
342 fValue[i].key->addResources(resourceSet, catalog);
343 catalog->getSubstituteObject(fValue[i].value)
344 ->addResources(resourceSet, catalog);
345 }
346}
347
halcanary1f8ed022014-06-27 10:37:27 -0700348SkPDFObject* SkPDFDict::append(SkPDFName* key, SkPDFObject* value) {
349 SkASSERT(key);
350 SkASSERT(value);
351 SkAutoMutexAcquire lock(fMutex); // If the SkTDArray resizes while
352 // two threads access array, one
353 // is left with a bad pointer.
354 *(fValue.append()) = Rec(key, value);
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000355 return value;
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000356}
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000357
halcanary1f8ed022014-06-27 10:37:27 -0700358SkPDFObject* SkPDFDict::insert(SkPDFName* key, SkPDFObject* value) {
359 return this->append(SkRef(key), SkRef(value));
360}
361
vandebo@chromium.orgf7c15762011-02-01 22:19:44 +0000362SkPDFObject* SkPDFDict::insert(const char key[], SkPDFObject* value) {
halcanary1f8ed022014-06-27 10:37:27 -0700363 return this->append(new SkPDFName(key), SkRef(value));
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000364}
365
reed@google.comc789cf12011-07-20 12:14:33 +0000366void SkPDFDict::insertInt(const char key[], int32_t value) {
halcanary1f8ed022014-06-27 10:37:27 -0700367 (void)this->append(new SkPDFName(key), new SkPDFInt(value));
reed@google.comc789cf12011-07-20 12:14:33 +0000368}
369
370void SkPDFDict::insertScalar(const char key[], SkScalar value) {
halcanary1f8ed022014-06-27 10:37:27 -0700371 (void)this->append(new SkPDFName(key), new SkPDFScalar(value));
reed@google.comc789cf12011-07-20 12:14:33 +0000372}
373
374void SkPDFDict::insertName(const char key[], const char name[]) {
halcanary1f8ed022014-06-27 10:37:27 -0700375 (void)this->append(new SkPDFName(key), new SkPDFName(name));
reed@google.comc789cf12011-07-20 12:14:33 +0000376}
377
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000378void SkPDFDict::clear() {
halcanary1f8ed022014-06-27 10:37:27 -0700379 SkAutoMutexAcquire lock(fMutex);
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000380 for (int i = 0; i < fValue.count(); i++) {
halcanary1f8ed022014-06-27 10:37:27 -0700381 SkASSERT(fValue[i].key);
382 SkASSERT(fValue[i].value);
reed@google.com2812b802011-07-19 15:46:40 +0000383 fValue[i].key->unref();
384 fValue[i].value->unref();
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000385 }
386 fValue.reset();
387}
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000388
halcanary1f8ed022014-06-27 10:37:27 -0700389void SkPDFDict::remove(const char key[]) {
390 SkASSERT(key);
391 SkPDFName name(key);
392 SkAutoMutexAcquire lock(fMutex);
393 for (int i = 0; i < fValue.count(); i++) {
394 SkASSERT(fValue[i].key);
395 if (*(fValue[i].key) == name) {
396 fValue[i].key->unref();
397 SkASSERT(fValue[i].value);
398 fValue[i].value->unref();
399 fValue.removeShuffle(i);
400 return;
401 }
402 }
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000403}
404
halcanary1f8ed022014-06-27 10:37:27 -0700405void SkPDFDict::mergeFrom(const SkPDFDict& other) {
406 SkAutoMutexAcquire lockOther(other.fMutex);
407 SkTDArray<Rec> copy(other.fValue);
408 lockOther.release(); // Do not hold both mutexes at once.
409
410 SkAutoMutexAcquire lock(fMutex);
411 for (int i = 0; i < copy.count(); i++) {
412 *(fValue.append()) = Rec(SkRef(copy[i].key), SkRef(copy[i].value));
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000413 }
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000414}