OLD | NEW |
---|---|
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 | 9 |
10 #include "SkPDFCatalog.h" | 10 #include "SkPDFCatalog.h" |
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
395 SkPDFDict::~SkPDFDict() { | 395 SkPDFDict::~SkPDFDict() { |
396 clear(); | 396 clear(); |
397 } | 397 } |
398 | 398 |
399 void SkPDFDict::emitObject(SkWStream* stream, SkPDFCatalog* catalog, | 399 void SkPDFDict::emitObject(SkWStream* stream, SkPDFCatalog* catalog, |
400 bool indirect) { | 400 bool indirect) { |
401 if (indirect) { | 401 if (indirect) { |
402 return emitIndirectObject(stream, catalog); | 402 return emitIndirectObject(stream, catalog); |
403 } | 403 } |
404 | 404 |
405 SkAutoMutexAcquire lock(fMutex); // If another thread triggers a | |
406 // resize while this thread is in | |
407 // the for-loop, we can be left | |
408 // with a bad fValue[i] reference. | |
405 stream->writeText("<<"); | 409 stream->writeText("<<"); |
406 for (int i = 0; i < fValue.count(); i++) { | 410 for (int i = 0; i < fValue.count(); i++) { |
411 SkASSERT(fValue[i].key); | |
412 SkASSERT(fValue[i].value); | |
407 fValue[i].key->emitObject(stream, catalog, false); | 413 fValue[i].key->emitObject(stream, catalog, false); |
408 stream->writeText(" "); | 414 stream->writeText(" "); |
409 fValue[i].value->emit(stream, catalog, false); | 415 fValue[i].value->emit(stream, catalog, false); |
410 stream->writeText("\n"); | 416 stream->writeText("\n"); |
411 } | 417 } |
412 stream->writeText(">>"); | 418 stream->writeText(">>"); |
413 } | 419 } |
414 | 420 |
415 size_t SkPDFDict::getOutputSize(SkPDFCatalog* catalog, bool indirect) { | 421 size_t SkPDFDict::getOutputSize(SkPDFCatalog* catalog, bool indirect) { |
416 if (indirect) { | 422 if (indirect) { |
417 return getIndirectOutputSize(catalog); | 423 return getIndirectOutputSize(catalog); |
418 } | 424 } |
419 | 425 |
426 SkAutoMutexAcquire lock(fMutex); // If another thread triggers a | |
427 // resize while this thread is in | |
428 // the for-loop, we can be left | |
429 // with a bad fValue[i] reference. | |
420 size_t result = strlen("<<>>") + (fValue.count() * 2); | 430 size_t result = strlen("<<>>") + (fValue.count() * 2); |
421 for (int i = 0; i < fValue.count(); i++) { | 431 for (int i = 0; i < fValue.count(); i++) { |
432 SkASSERT(fValue[i].key); | |
433 SkASSERT(fValue[i].value); | |
422 result += fValue[i].key->getOutputSize(catalog, false); | 434 result += fValue[i].key->getOutputSize(catalog, false); |
423 result += fValue[i].value->getOutputSize(catalog, false); | 435 result += fValue[i].value->getOutputSize(catalog, false); |
424 } | 436 } |
425 return result; | 437 return result; |
426 } | 438 } |
427 | 439 |
428 SkPDFObject* SkPDFDict::insert(SkPDFName* key, SkPDFObject* value) { | 440 SkPDFObject* SkPDFDict::appendRec(SkPDFName* key, SkPDFObject* value) { |
429 key->ref(); | 441 SkASSERT(key); |
430 value->ref(); | 442 SkASSERT(value); |
431 struct Rec* newEntry = fValue.append(); | 443 SkAutoMutexAcquire lock(fMutex); // If the SkTDArray resizes while |
432 newEntry->key = key; | 444 // two threads access array, one |
433 newEntry->value = value; | 445 // is left with a bad pointer. |
446 *(fValue.append()) = Rec(key, value); | |
434 return value; | 447 return value; |
435 } | 448 } |
436 | 449 |
450 SkPDFObject* SkPDFDict::insert(SkPDFName* key, SkPDFObject* value) { | |
451 return this->appendRec(SkRef(key), SkRef(value)); | |
452 } | |
453 | |
437 SkPDFObject* SkPDFDict::insert(const char key[], SkPDFObject* value) { | 454 SkPDFObject* SkPDFDict::insert(const char key[], SkPDFObject* value) { |
438 value->ref(); | 455 return this->appendRec(new SkPDFName(key), SkRef(value)); |
439 struct Rec* newEntry = fValue.append(); | |
440 newEntry->key = new SkPDFName(key); | |
441 newEntry->value = value; | |
442 return value; | |
443 } | 456 } |
444 | 457 |
445 void SkPDFDict::insertInt(const char key[], int32_t value) { | 458 void SkPDFDict::insertInt(const char key[], int32_t value) { |
446 struct Rec* newEntry = fValue.append(); | 459 (void)this->appendRec(new SkPDFName(key), new SkPDFInt(value)); |
447 newEntry->key = new SkPDFName(key); | |
448 newEntry->value = new SkPDFInt(value); | |
449 } | 460 } |
450 | 461 |
451 void SkPDFDict::insertScalar(const char key[], SkScalar value) { | 462 void SkPDFDict::insertScalar(const char key[], SkScalar value) { |
452 struct Rec* newEntry = fValue.append(); | 463 (void)this->appendRec(new SkPDFName(key), new SkPDFScalar(value)); |
453 newEntry->key = new SkPDFName(key); | |
454 newEntry->value = new SkPDFScalar(value); | |
455 } | 464 } |
456 | 465 |
457 void SkPDFDict::insertName(const char key[], const char name[]) { | 466 void SkPDFDict::insertName(const char key[], const char name[]) { |
458 struct Rec* newEntry = fValue.append(); | 467 (void)this->appendRec(new SkPDFName(key), new SkPDFName(name)); |
459 newEntry->key = new SkPDFName(key); | |
460 newEntry->value = new SkPDFName(name); | |
461 } | 468 } |
462 | 469 |
463 void SkPDFDict::clear() { | 470 void SkPDFDict::clear() { |
471 SkAutoMutexAcquire lock(fMutex); | |
464 for (int i = 0; i < fValue.count(); i++) { | 472 for (int i = 0; i < fValue.count(); i++) { |
473 SkASSERT(fValue[i].key); | |
474 SkASSERT(fValue[i].value); | |
465 fValue[i].key->unref(); | 475 fValue[i].key->unref(); |
466 fValue[i].value->unref(); | 476 fValue[i].value->unref(); |
467 } | 477 } |
468 fValue.reset(); | 478 fValue.reset(); |
469 } | 479 } |
470 | 480 |
471 SkPDFDict::Iter::Iter(const SkPDFDict& dict) | 481 void SkPDFDict::remove(const char key[]) { |
472 : fIter(dict.fValue.begin()), | 482 SkASSERT(key); |
473 fStop(dict.fValue.end()) { | 483 SkPDFName name(key); |
484 SkAutoMutexAcquire lock(fMutex); | |
485 for (int i = 0; i < fValue.count(); i++) { | |
486 SkASSERT(fValue[i].key); | |
487 if (*(fValue[i].key) == name) { | |
488 fValue[i].key->unref(); | |
489 SkASSERT(fValue[i].value); | |
490 fValue[i].value->unref(); | |
491 fValue.removeShuffle(i); | |
492 return; | |
493 } | |
494 } | |
474 } | 495 } |
475 | 496 |
476 SkPDFName* SkPDFDict::Iter::next(SkPDFObject** value) { | 497 void SkPDFDict::insertDict(const SkPDFDict& other) { |
477 if (fIter != fStop) { | 498 SkAutoMutexAcquire lockOther(const_cast<SkMutex&>(other.fMutex)); |
mtklein
2014/06/27 15:26:51
fMutex should probably be mutable
hal.canary
2014/06/27 16:03:27
Done.
| |
478 const Rec* cur = fIter; | 499 SkAutoMutexAcquire lock(fMutex); |
mtklein
2014/06/27 15:26:51
Locking more than one lock should terrify you. We
hal.canary
2014/06/27 16:03:27
Done.
| |
479 fIter++; | 500 for (int i = 0; i < other.fValue.count(); i++) { |
480 *value = cur->value; | 501 *(fValue.append()) |
481 return cur->key; | 502 = Rec(SkRef(other.fValue[i].key), SkRef(other.fValue[i].value)); |
482 } | 503 } |
483 *value = NULL; | |
484 return NULL; | |
485 } | 504 } |
OLD | NEW |