resubmit after fixing assert issue: https://codereview.appspot.com/6744050
git-svn-id: http://skia.googlecode.com/svn/trunk@7892 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/pdf/SkPDFDocument.cpp b/src/pdf/SkPDFDocument.cpp
index c7266d8..fc09286 100644
--- a/src/pdf/SkPDFDocument.cpp
+++ b/src/pdf/SkPDFDocument.cpp
@@ -14,21 +14,13 @@
#include "SkPDFPage.h"
#include "SkPDFTypes.h"
#include "SkStream.h"
+#include "SkTSet.h"
-// Add the resources, starting at firstIndex to the catalog, removing any dupes.
-// A hash table would be really nice here.
-static void addResourcesToCatalog(int firstIndex, bool firstPage,
- SkTDArray<SkPDFObject*>* resourceList,
- SkPDFCatalog* catalog) {
- for (int i = firstIndex; i < resourceList->count(); i++) {
- int index = resourceList->find((*resourceList)[i]);
- if (index != i) {
- (*resourceList)[i]->unref();
- resourceList->removeShuffle(i);
- i--;
- } else {
- catalog->addObject((*resourceList)[i], firstPage);
- }
+static void addResourcesToCatalog(bool firstPage,
+ SkTSet<SkPDFObject*>* resourceSet,
+ SkPDFCatalog* catalog) {
+ for (int i = 0; i < resourceSet->count(); i++) {
+ catalog->addObject((*resourceSet)[i], firstPage);
}
}
@@ -57,11 +49,12 @@
SkPDFDocument::SkPDFDocument(Flags flags)
: fXRefFileOffset(0),
- fSecondPageFirstResourceIndex(0),
fTrailerDict(NULL) {
fCatalog.reset(new SkPDFCatalog(flags));
fDocCatalog = SkNEW_ARGS(SkPDFDict, ("Catalog"));
fCatalog->addObject(fDocCatalog, true);
+ fFirstPageResources = NULL;
+ fOtherPageResources = NULL;
}
SkPDFDocument::~SkPDFDocument() {
@@ -73,11 +66,14 @@
fPageTree[i]->clear();
}
fPageTree.safeUnrefAll();
- fPageResources.safeUnrefAll();
+ fFirstPageResources->safeUnrefAll();
+ fOtherPageResources->safeUnrefAll();
fSubstitutes.safeUnrefAll();
fDocCatalog->unref();
SkSafeUnref(fTrailerDict);
+ SkDELETE(fFirstPageResources);
+ SkDELETE(fOtherPageResources);
}
bool SkPDFDocument::emitPDF(SkWStream* stream) {
@@ -90,6 +86,9 @@
}
}
+ fFirstPageResources = SkNEW(SkTSet<SkPDFObject*>);
+ fOtherPageResources = SkNEW(SkTSet<SkPDFObject*>);
+
// We haven't emitted the document before if fPageTree is empty.
if (fPageTree.isEmpty()) {
SkPDFDict* pageTreeRoot;
@@ -108,15 +107,35 @@
*/
bool firstPage = true;
+ /* The references returned in newResources are transfered to
+ * fFirstPageResources or fOtherPageResources depending on firstPage and
+ * knownResources doesn't have a reference but just relies on the other
+ * two sets to maintain a reference.
+ */
+ SkTSet<SkPDFObject*> knownResources;
+
+ // mergeInto returns the number of duplicates.
+ // If there are duplicates, there is a bug and we mess ref counting.
+ int duplicates = 0;
+ knownResources.mergeInto(*fFirstPageResources);
for (int i = 0; i < fPages.count(); i++) {
- int resourceCount = fPageResources.count();
- fPages[i]->finalizePage(fCatalog.get(), firstPage, &fPageResources);
- addResourcesToCatalog(resourceCount, firstPage, &fPageResources,
- fCatalog.get());
- if (i == 0) {
+ if (i == 1) {
firstPage = false;
- fSecondPageFirstResourceIndex = fPageResources.count();
+ duplicates = knownResources.mergeInto(*fOtherPageResources);
}
+ SkTSet<SkPDFObject*> newResources;
+ fPages[i]->finalizePage(
+ fCatalog.get(), firstPage, knownResources, &newResources);
+ addResourcesToCatalog(firstPage, &newResources, fCatalog.get());
+ if (firstPage) {
+ duplicates = fFirstPageResources->mergeInto(newResources);
+ } else {
+ duplicates = fOtherPageResources->mergeInto(newResources);
+ }
+ SkASSERT(duplicates == 0);
+
+ duplicates = knownResources.mergeInto(newResources);
+ SkASSERT(duplicates == 0);
}
// Build font subsetting info before proceeding.
@@ -128,8 +147,8 @@
fileOffset += fCatalog->setFileOffset(fPages[0], fileOffset);
fileOffset += fPages[0]->getPageSize(fCatalog.get(),
(size_t) fileOffset);
- for (int i = 0; i < fSecondPageFirstResourceIndex; i++) {
- fileOffset += fCatalog->setFileOffset(fPageResources[i],
+ for (int i = 0; i < fFirstPageResources->count(); i++) {
+ fileOffset += fCatalog->setFileOffset((*fFirstPageResources)[i],
fileOffset);
}
// Add the size of resources of substitute objects used on page 1.
@@ -147,11 +166,9 @@
fileOffset += fPages[i]->getPageSize(fCatalog.get(), fileOffset);
}
- for (int i = fSecondPageFirstResourceIndex;
- i < fPageResources.count();
- i++) {
- fileOffset += fCatalog->setFileOffset(fPageResources[i],
- fileOffset);
+ for (int i = 0; i < fOtherPageResources->count(); i++) {
+ fileOffset += fCatalog->setFileOffset(
+ (*fOtherPageResources)[i], fileOffset);
}
fileOffset += fCatalog->setSubstituteResourcesOffsets(fileOffset,
@@ -163,8 +180,8 @@
fDocCatalog->emitObject(stream, fCatalog.get(), true);
fPages[0]->emitObject(stream, fCatalog.get(), true);
fPages[0]->emitPage(stream, fCatalog.get());
- for (int i = 0; i < fSecondPageFirstResourceIndex; i++) {
- fPageResources[i]->emit(stream, fCatalog.get(), true);
+ for (int i = 0; i < fFirstPageResources->count(); i++) {
+ (*fFirstPageResources)[i]->emit(stream, fCatalog.get(), true);
}
fCatalog->emitSubstituteResources(stream, true);
// TODO(vandebo): Support linearized format
@@ -181,10 +198,8 @@
fPages[i]->emitPage(stream, fCatalog.get());
}
- for (int i = fSecondPageFirstResourceIndex;
- i < fPageResources.count();
- i++) {
- fPageResources[i]->emit(stream, fCatalog.get(), true);
+ for (int i = 0; i < fOtherPageResources->count(); i++) {
+ (*fOtherPageResources)[i]->emit(stream, fCatalog.get(), true);
}
fCatalog->emitSubstituteResources(stream, false);