git-svn-id: http://skia.googlecode.com/svn/trunk@7884 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
edisonn@google.com 2013-02-27 17:46:09 +00:00
Родитель 676aef05ab
Коммит d1c53aae59
21 изменённых файлов: 127 добавлений и 207 удалений

Просмотреть файл

@ -12,7 +12,6 @@
'include_dirs': [ 'include_dirs': [
'../include/config', '../include/config',
'../include/core', '../include/core',
'../include/images',
'../include/pdf', '../include/pdf',
'../src/core', # needed to get SkGlyphCache.h and SkTextFormatParams.h '../src/core', # needed to get SkGlyphCache.h and SkTextFormatParams.h
'../src/utils', # needed to get SkBitSet.h '../src/utils', # needed to get SkBitSet.h
@ -44,7 +43,6 @@
'../src/pdf/SkPDFTypes.h', '../src/pdf/SkPDFTypes.h',
'../src/pdf/SkPDFUtils.cpp', '../src/pdf/SkPDFUtils.cpp',
'../src/pdf/SkPDFUtils.h', '../src/pdf/SkPDFUtils.h',
'../src/pdf/SkTSet.h',
], ],
# This section makes all targets that depend on this target # This section makes all targets that depend on this target
# #define SK_SUPPORT_PDF and have access to the pdf header files. # #define SK_SUPPORT_PDF and have access to the pdf header files.

Просмотреть файл

@ -29,7 +29,6 @@ class SkPDFGraphicState;
class SkPDFObject; class SkPDFObject;
class SkPDFShader; class SkPDFShader;
class SkPDFStream; class SkPDFStream;
template <typename T> class SK_API SkTSet;
// Private classes. // Private classes.
struct ContentEntry; struct ContentEntry;
@ -131,19 +130,12 @@ public:
SK_API SkPDFDict* getResourceDict(); SK_API SkPDFDict* getResourceDict();
/** Get the list of resources (PDF objects) used on this page. /** Get the list of resources (PDF objects) used on this page.
* This method will add to newResourceObjects any objects that this method * @param resourceList A list to append the resources to.
* depends on, but not already in knownResourceObjects. This might operate
* recursively so if this object depends on another object and that object
* depends on two more, all three objects will be added.
*
* @param knownResourceObjects The set of resources to be ignored.
* @param newResourceObjects The set to append dependant resources to.
* @param recursive If recursive is true, get the resources of the * @param recursive If recursive is true, get the resources of the
* device's resources recursively. (Useful for adding * device's resources recursively. (Useful for adding
* objects to the catalog.) * objects to the catalog.)
*/ */
SK_API void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, SK_API void getResources(SkTDArray<SkPDFObject*>* resourceList,
SkTSet<SkPDFObject*>* newResourceObjects,
bool recursive) const; bool recursive) const;
/** Get the fonts used on this device. /** Get the fonts used on this device.

Просмотреть файл

@ -21,7 +21,6 @@ class SkPDFDict;
class SkPDFPage; class SkPDFPage;
class SkPDFObject; class SkPDFObject;
class SkWStream; class SkWStream;
template <typename T> class SK_API SkTSet;
/** \class SkPDFDocument /** \class SkPDFDocument
@ -77,8 +76,7 @@ private:
SkTDArray<SkPDFPage*> fPages; SkTDArray<SkPDFPage*> fPages;
SkTDArray<SkPDFDict*> fPageTree; SkTDArray<SkPDFDict*> fPageTree;
SkPDFDict* fDocCatalog; SkPDFDict* fDocCatalog;
SkTSet<SkPDFObject*>* fFirstPageResources; SkTDArray<SkPDFObject*> fPageResources;
SkTSet<SkPDFObject*>* fOtherPageResources;
SkTDArray<SkPDFObject*> fSubstitutes; SkTDArray<SkPDFObject*> fSubstitutes;
int fSecondPageFirstResourceIndex; int fSecondPageFirstResourceIndex;

Просмотреть файл

@ -168,15 +168,12 @@ void SkPDFCatalog::setSubstitute(SkPDFObject* original,
fSubstituteMap.append(1, &newMapping); fSubstituteMap.append(1, &newMapping);
// Add resource objects of substitute object to catalog. // Add resource objects of substitute object to catalog.
SkTSet<SkPDFObject*>* targetSet = getSubstituteList(onFirstPage); SkTDArray<SkPDFObject*>* targetList = getSubstituteList(onFirstPage);
SkTSet<SkPDFObject*> newResourceObjects; int existingSize = targetList->count();
newMapping.fSubstitute->getResources(*targetSet, &newResourceObjects); newMapping.fSubstitute->getResources(targetList);
for (int i = 0; i < newResourceObjects.count(); ++i) { for (int i = existingSize; i < targetList->count(); ++i) {
addObject(newResourceObjects[i], onFirstPage); addObject((*targetList)[i], onFirstPage);
} }
// mergeInto returns the numbr of duplicates.
// If there are duplicates, there is a bug and we mess ref counting.
SkASSERT(targetSet->mergeInto(newResourceObjects) == 0);
} }
SkPDFObject* SkPDFCatalog::getSubstituteObject(SkPDFObject* object) { SkPDFObject* SkPDFCatalog::getSubstituteObject(SkPDFObject* object) {
@ -190,22 +187,22 @@ SkPDFObject* SkPDFCatalog::getSubstituteObject(SkPDFObject* object) {
off_t SkPDFCatalog::setSubstituteResourcesOffsets(off_t fileOffset, off_t SkPDFCatalog::setSubstituteResourcesOffsets(off_t fileOffset,
bool firstPage) { bool firstPage) {
SkTSet<SkPDFObject*>* targetSet = getSubstituteList(firstPage); SkTDArray<SkPDFObject*>* targetList = getSubstituteList(firstPage);
off_t offsetSum = fileOffset; off_t offsetSum = fileOffset;
for (int i = 0; i < targetSet->count(); ++i) { for (int i = 0; i < targetList->count(); ++i) {
offsetSum += setFileOffset((*targetSet)[i], offsetSum); offsetSum += setFileOffset((*targetList)[i], offsetSum);
} }
return offsetSum - fileOffset; return offsetSum - fileOffset;
} }
void SkPDFCatalog::emitSubstituteResources(SkWStream *stream, bool firstPage) { void SkPDFCatalog::emitSubstituteResources(SkWStream *stream, bool firstPage) {
SkTSet<SkPDFObject*>* targetSet = getSubstituteList(firstPage); SkTDArray<SkPDFObject*>* targetList = getSubstituteList(firstPage);
for (int i = 0; i < targetSet->count(); ++i) { for (int i = 0; i < targetList->count(); ++i) {
(*targetSet)[i]->emit(stream, this, true); (*targetList)[i]->emit(stream, this, true);
} }
} }
SkTSet<SkPDFObject*>* SkPDFCatalog::getSubstituteList(bool firstPage) { SkTDArray<SkPDFObject*>* SkPDFCatalog::getSubstituteList(bool firstPage) {
return firstPage ? &fSubstituteResourcesFirstPage : return firstPage ? &fSubstituteResourcesFirstPage :
&fSubstituteResourcesRemaining; &fSubstituteResourcesRemaining;
} }

Просмотреть файл

@ -115,8 +115,8 @@ private:
// TODO(arthurhsu): Make this a hash if it's a performance problem. // TODO(arthurhsu): Make this a hash if it's a performance problem.
SkTDArray<SubstituteMapping> fSubstituteMap; SkTDArray<SubstituteMapping> fSubstituteMap;
SkTSet<SkPDFObject*> fSubstituteResourcesFirstPage; SkTDArray<SkPDFObject*> fSubstituteResourcesFirstPage;
SkTSet<SkPDFObject*> fSubstituteResourcesRemaining; SkTDArray<SkPDFObject*> fSubstituteResourcesRemaining;
// Number of objects on the first page. // Number of objects on the first page.
uint32_t fFirstPageCount; uint32_t fFirstPageCount;
@ -131,7 +131,7 @@ private:
int assignObjNum(SkPDFObject* obj); int assignObjNum(SkPDFObject* obj);
SkTSet<SkPDFObject*>* getSubstituteList(bool firstPage); SkTDArray<SkPDFObject*>* getSubstituteList(bool firstPage);
}; };
#endif #endif

Просмотреть файл

@ -32,7 +32,6 @@
#include "SkTemplates.h" #include "SkTemplates.h"
#include "SkTypeface.h" #include "SkTypeface.h"
#include "SkTypes.h" #include "SkTypes.h"
#include "SkTSet.h"
// Utility functions // Utility functions
@ -1176,57 +1175,39 @@ SkPDFDict* SkPDFDevice::getResourceDict() {
return fResourceDict; return fResourceDict;
} }
void SkPDFDevice::getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, void SkPDFDevice::getResources(SkTDArray<SkPDFObject*>* resourceList,
SkTSet<SkPDFObject*>* newResourceObjects,
bool recursive) const { bool recursive) const {
// TODO: reserve not correct if we need to recursively explore. resourceList->setReserve(resourceList->count() +
newResourceObjects->setReserve(newResourceObjects->count() +
fGraphicStateResources.count() + fGraphicStateResources.count() +
fXObjectResources.count() + fXObjectResources.count() +
fFontResources.count() + fFontResources.count() +
fShaderResources.count()); fShaderResources.count());
for (int i = 0; i < fGraphicStateResources.count(); i++) { for (int i = 0; i < fGraphicStateResources.count(); i++) {
if (!knownResourceObjects.contains(fGraphicStateResources[i]) && resourceList->push(fGraphicStateResources[i]);
!newResourceObjects->contains(fGraphicStateResources[i])) {
newResourceObjects->add(fGraphicStateResources[i]);
fGraphicStateResources[i]->ref(); fGraphicStateResources[i]->ref();
if (recursive) { if (recursive) {
fGraphicStateResources[i]->getResources(knownResourceObjects, fGraphicStateResources[i]->getResources(resourceList);
newResourceObjects);
}
} }
} }
for (int i = 0; i < fXObjectResources.count(); i++) { for (int i = 0; i < fXObjectResources.count(); i++) {
if (!knownResourceObjects.contains(fXObjectResources[i]) && resourceList->push(fXObjectResources[i]);
!newResourceObjects->contains(fXObjectResources[i])) {
newResourceObjects->add(fXObjectResources[i]);
fXObjectResources[i]->ref(); fXObjectResources[i]->ref();
if (recursive) { if (recursive) {
fXObjectResources[i]->getResources(knownResourceObjects, fXObjectResources[i]->getResources(resourceList);
newResourceObjects);
}
} }
} }
for (int i = 0; i < fFontResources.count(); i++) { for (int i = 0; i < fFontResources.count(); i++) {
if (!knownResourceObjects.contains(fFontResources[i]) && resourceList->push(fFontResources[i]);
!newResourceObjects->contains(fFontResources[i])) {
newResourceObjects->add(fFontResources[i]);
fFontResources[i]->ref(); fFontResources[i]->ref();
if (recursive) { if (recursive) {
fFontResources[i]->getResources(knownResourceObjects, fFontResources[i]->getResources(resourceList);
newResourceObjects);
}
} }
} }
for (int i = 0; i < fShaderResources.count(); i++) { for (int i = 0; i < fShaderResources.count(); i++) {
if (!knownResourceObjects.contains(fShaderResources[i]) && resourceList->push(fShaderResources[i]);
!newResourceObjects->contains(fShaderResources[i])) {
newResourceObjects->add(fShaderResources[i]);
fShaderResources[i]->ref(); fShaderResources[i]->ref();
if (recursive) { if (recursive) {
fShaderResources[i]->getResources(knownResourceObjects, fShaderResources[i]->getResources(resourceList);
newResourceObjects);
}
} }
} }
} }

Просмотреть файл

@ -14,13 +14,21 @@
#include "SkPDFPage.h" #include "SkPDFPage.h"
#include "SkPDFTypes.h" #include "SkPDFTypes.h"
#include "SkStream.h" #include "SkStream.h"
#include "SkTSet.h"
static void addResourcesToCatalog(bool firstPage, // Add the resources, starting at firstIndex to the catalog, removing any dupes.
SkTSet<SkPDFObject*>* resourceSet, // A hash table would be really nice here.
static void addResourcesToCatalog(int firstIndex, bool firstPage,
SkTDArray<SkPDFObject*>* resourceList,
SkPDFCatalog* catalog) { SkPDFCatalog* catalog) {
for (int i = 0; i < resourceSet->count(); i++) { for (int i = firstIndex; i < resourceList->count(); i++) {
catalog->addObject((*resourceSet)[i], firstPage); int index = resourceList->find((*resourceList)[i]);
if (index != i) {
(*resourceList)[i]->unref();
resourceList->removeShuffle(i);
i--;
} else {
catalog->addObject((*resourceList)[i], firstPage);
}
} }
} }
@ -49,12 +57,11 @@ static void perform_font_subsetting(SkPDFCatalog* catalog,
SkPDFDocument::SkPDFDocument(Flags flags) SkPDFDocument::SkPDFDocument(Flags flags)
: fXRefFileOffset(0), : fXRefFileOffset(0),
fSecondPageFirstResourceIndex(0),
fTrailerDict(NULL) { fTrailerDict(NULL) {
fCatalog.reset(new SkPDFCatalog(flags)); fCatalog.reset(new SkPDFCatalog(flags));
fDocCatalog = SkNEW_ARGS(SkPDFDict, ("Catalog")); fDocCatalog = SkNEW_ARGS(SkPDFDict, ("Catalog"));
fCatalog->addObject(fDocCatalog, true); fCatalog->addObject(fDocCatalog, true);
fFirstPageResources = NULL;
fOtherPageResources = NULL;
} }
SkPDFDocument::~SkPDFDocument() { SkPDFDocument::~SkPDFDocument() {
@ -66,14 +73,11 @@ SkPDFDocument::~SkPDFDocument() {
fPageTree[i]->clear(); fPageTree[i]->clear();
} }
fPageTree.safeUnrefAll(); fPageTree.safeUnrefAll();
fFirstPageResources->safeUnrefAll(); fPageResources.safeUnrefAll();
fOtherPageResources->safeUnrefAll();
fSubstitutes.safeUnrefAll(); fSubstitutes.safeUnrefAll();
fDocCatalog->unref(); fDocCatalog->unref();
SkSafeUnref(fTrailerDict); SkSafeUnref(fTrailerDict);
SkDELETE(fFirstPageResources);
SkDELETE(fOtherPageResources);
} }
bool SkPDFDocument::emitPDF(SkWStream* stream) { bool SkPDFDocument::emitPDF(SkWStream* stream) {
@ -86,9 +90,6 @@ bool SkPDFDocument::emitPDF(SkWStream* stream) {
} }
} }
fFirstPageResources = SkNEW(SkTSet<SkPDFObject*>);
fOtherPageResources = SkNEW(SkTSet<SkPDFObject*>);
// We haven't emitted the document before if fPageTree is empty. // We haven't emitted the document before if fPageTree is empty.
if (fPageTree.isEmpty()) { if (fPageTree.isEmpty()) {
SkPDFDict* pageTreeRoot; SkPDFDict* pageTreeRoot;
@ -107,35 +108,15 @@ bool SkPDFDocument::emitPDF(SkWStream* stream) {
*/ */
bool firstPage = true; 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++) { for (int i = 0; i < fPages.count(); i++) {
if (i == 1) { int resourceCount = fPageResources.count();
fPages[i]->finalizePage(fCatalog.get(), firstPage, &fPageResources);
addResourcesToCatalog(resourceCount, firstPage, &fPageResources,
fCatalog.get());
if (i == 0) {
firstPage = false; firstPage = false;
duplicates = knownResources.mergeInto(*fOtherPageResources); fSecondPageFirstResourceIndex = fPageResources.count();
} }
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. // Build font subsetting info before proceeding.
@ -147,8 +128,8 @@ bool SkPDFDocument::emitPDF(SkWStream* stream) {
fileOffset += fCatalog->setFileOffset(fPages[0], fileOffset); fileOffset += fCatalog->setFileOffset(fPages[0], fileOffset);
fileOffset += fPages[0]->getPageSize(fCatalog.get(), fileOffset += fPages[0]->getPageSize(fCatalog.get(),
(size_t) fileOffset); (size_t) fileOffset);
for (int i = 0; i < fFirstPageResources->count(); i++) { for (int i = 0; i < fSecondPageFirstResourceIndex; i++) {
fileOffset += fCatalog->setFileOffset((*fFirstPageResources)[i], fileOffset += fCatalog->setFileOffset(fPageResources[i],
fileOffset); fileOffset);
} }
// Add the size of resources of substitute objects used on page 1. // Add the size of resources of substitute objects used on page 1.
@ -166,9 +147,11 @@ bool SkPDFDocument::emitPDF(SkWStream* stream) {
fileOffset += fPages[i]->getPageSize(fCatalog.get(), fileOffset); fileOffset += fPages[i]->getPageSize(fCatalog.get(), fileOffset);
} }
for (int i = 0; i < fOtherPageResources->count(); i++) { for (int i = fSecondPageFirstResourceIndex;
fileOffset += fCatalog->setFileOffset( i < fPageResources.count();
(*fOtherPageResources)[i], fileOffset); i++) {
fileOffset += fCatalog->setFileOffset(fPageResources[i],
fileOffset);
} }
fileOffset += fCatalog->setSubstituteResourcesOffsets(fileOffset, fileOffset += fCatalog->setSubstituteResourcesOffsets(fileOffset,
@ -180,8 +163,8 @@ bool SkPDFDocument::emitPDF(SkWStream* stream) {
fDocCatalog->emitObject(stream, fCatalog.get(), true); fDocCatalog->emitObject(stream, fCatalog.get(), true);
fPages[0]->emitObject(stream, fCatalog.get(), true); fPages[0]->emitObject(stream, fCatalog.get(), true);
fPages[0]->emitPage(stream, fCatalog.get()); fPages[0]->emitPage(stream, fCatalog.get());
for (int i = 0; i < fFirstPageResources->count(); i++) { for (int i = 0; i < fSecondPageFirstResourceIndex; i++) {
(*fFirstPageResources)[i]->emit(stream, fCatalog.get(), true); fPageResources[i]->emit(stream, fCatalog.get(), true);
} }
fCatalog->emitSubstituteResources(stream, true); fCatalog->emitSubstituteResources(stream, true);
// TODO(vandebo): Support linearized format // TODO(vandebo): Support linearized format
@ -198,8 +181,10 @@ bool SkPDFDocument::emitPDF(SkWStream* stream) {
fPages[i]->emitPage(stream, fCatalog.get()); fPages[i]->emitPage(stream, fCatalog.get());
} }
for (int i = 0; i < fOtherPageResources->count(); i++) { for (int i = fSecondPageFirstResourceIndex;
(*fOtherPageResources)[i]->emit(stream, fCatalog.get(), true); i < fPageResources.count();
i++) {
fPageResources[i]->emit(stream, fCatalog.get(), true);
} }
fCatalog->emitSubstituteResources(stream, false); fCatalog->emitSubstituteResources(stream, false);

Просмотреть файл

@ -716,9 +716,8 @@ SkPDFFont::~SkPDFFont() {
fResources.unrefAll(); fResources.unrefAll();
} }
void SkPDFFont::getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, void SkPDFFont::getResources(SkTDArray<SkPDFObject*>* resourceList) {
SkTSet<SkPDFObject*>* newResourceObjects) { GetResourcesHelper(&fResources, resourceList);
GetResourcesHelper(&fResources, knownResourceObjects, newResourceObjects);
} }
SkTypeface* SkPDFFont::typeface() { SkTypeface* SkPDFFont::typeface() {

Просмотреть файл

@ -81,8 +81,7 @@ class SkPDFFont : public SkPDFDict {
public: public:
virtual ~SkPDFFont(); virtual ~SkPDFFont();
virtual void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, virtual void getResources(SkTDArray<SkPDFObject*>* resourceList);
SkTSet<SkPDFObject*>* newResourceObjects);
/** Returns the typeface represented by this class. Returns NULL for the /** Returns the typeface represented by this class. Returns NULL for the
* default typeface. * default typeface.

Просмотреть файл

@ -20,8 +20,16 @@ SkPDFFormXObject::SkPDFFormXObject(SkPDFDevice* device) {
// We don't want to keep around device because we'd have two copies // We don't want to keep around device because we'd have two copies
// of content, so reference or copy everything we need (content and // of content, so reference or copy everything we need (content and
// resources). // resources).
SkTSet<SkPDFObject*> emptySet; device->getResources(&fResources, false);
device->getResources(emptySet, &fResources, false);
// Fail fast if in the tree of resources a child references a parent.
// If there is an issue, getResources will end up consuming all memory.
// TODO: A better approach might be for all SkPDFObject to keep track
// of possible cycles.
#ifdef SK_DEBUG
SkTDArray<SkPDFObject*> dummy_resourceList;
getResources(&dummy_resourceList);
#endif
SkAutoTUnref<SkStream> content(device->content()); SkAutoTUnref<SkStream> content(device->content());
setData(content.get()); setData(content.get());
@ -56,10 +64,6 @@ SkPDFFormXObject::~SkPDFFormXObject() {
fResources.unrefAll(); fResources.unrefAll();
} }
void SkPDFFormXObject::getResources( void SkPDFFormXObject::getResources(SkTDArray<SkPDFObject*>* resourceList) {
const SkTSet<SkPDFObject*>& knownResourceObjects, GetResourcesHelper(&fResources, resourceList);
SkTSet<SkPDFObject*>* newResourceObjects) {
GetResourcesHelper(&fResources.toArray(),
knownResourceObjects,
newResourceObjects);
} }

Просмотреть файл

@ -39,11 +39,10 @@ public:
virtual ~SkPDFFormXObject(); virtual ~SkPDFFormXObject();
// The SkPDFObject interface. // The SkPDFObject interface.
virtual void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, virtual void getResources(SkTDArray<SkPDFObject*>* resourceList);
SkTSet<SkPDFObject*>* newResourceObjects);
private: private:
SkTSet<SkPDFObject*> fResources; SkTDArray<SkPDFObject*> fResources;
}; };
#endif #endif

Просмотреть файл

@ -59,10 +59,8 @@ SkPDFGraphicState::~SkPDFGraphicState() {
fResources.unrefAll(); fResources.unrefAll();
} }
void SkPDFGraphicState::getResources( void SkPDFGraphicState::getResources(SkTDArray<SkPDFObject*>* resourceList) {
const SkTSet<SkPDFObject*>& knownResourceObjects, GetResourcesHelper(&fResources, resourceList);
SkTSet<SkPDFObject*>* newResourceObjects) {
GetResourcesHelper(&fResources, knownResourceObjects, newResourceObjects);
} }
void SkPDFGraphicState::emitObject(SkWStream* stream, SkPDFCatalog* catalog, void SkPDFGraphicState::emitObject(SkWStream* stream, SkPDFCatalog* catalog,

Просмотреть файл

@ -30,8 +30,7 @@ class SkPDFGraphicState : public SkPDFDict {
public: public:
virtual ~SkPDFGraphicState(); virtual ~SkPDFGraphicState();
virtual void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, virtual void getResources(SkTDArray<SkPDFObject*>* resourceList);
SkTSet<SkPDFObject*>* newResourceObjects);
// Override emitObject and getOutputSize so that we can populate // Override emitObject and getOutputSize so that we can populate
// the dictionary on demand. // the dictionary on demand.

Просмотреть файл

@ -287,9 +287,8 @@ SkPDFImage* SkPDFImage::addSMask(SkPDFImage* mask) {
return mask; return mask;
} }
void SkPDFImage::getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, void SkPDFImage::getResources(SkTDArray<SkPDFObject*>* resourceList) {
SkTSet<SkPDFObject*>* newResourceObjects) { GetResourcesHelper(&fResources, resourceList);
GetResourcesHelper(&fResources, knownResourceObjects, newResourceObjects);
} }
SkPDFImage::SkPDFImage(SkStream* imageData, const SkBitmap& bitmap, SkPDFImage::SkPDFImage(SkStream* imageData, const SkBitmap& bitmap,

Просмотреть файл

@ -49,8 +49,7 @@ public:
SkPDFImage* addSMask(SkPDFImage* mask); SkPDFImage* addSMask(SkPDFImage* mask);
// The SkPDFObject interface. // The SkPDFObject interface.
virtual void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, virtual void getResources(SkTDArray<SkPDFObject*>* resourceList);
SkTSet<SkPDFObject*>* newResourceObjects);
private: private:
SkTDArray<SkPDFObject*> fResources; SkTDArray<SkPDFObject*> fResources;

Просмотреть файл

@ -21,8 +21,7 @@ SkPDFPage::SkPDFPage(SkPDFDevice* content)
SkPDFPage::~SkPDFPage() {} SkPDFPage::~SkPDFPage() {}
void SkPDFPage::finalizePage(SkPDFCatalog* catalog, bool firstPage, void SkPDFPage::finalizePage(SkPDFCatalog* catalog, bool firstPage,
const SkTSet<SkPDFObject*>& knownResourceObjects, SkTDArray<SkPDFObject*>* resourceObjects) {
SkTSet<SkPDFObject*>* newResourceObjects) {
if (fContentStream.get() == NULL) { if (fContentStream.get() == NULL) {
insert("Resources", fDevice->getResourceDict()); insert("Resources", fDevice->getResourceDict());
SkSafeUnref(this->insert("MediaBox", fDevice->copyMediaBox())); SkSafeUnref(this->insert("MediaBox", fDevice->copyMediaBox()));
@ -39,7 +38,7 @@ void SkPDFPage::finalizePage(SkPDFCatalog* catalog, bool firstPage,
insert("Contents", new SkPDFObjRef(fContentStream.get()))->unref(); insert("Contents", new SkPDFObjRef(fContentStream.get()))->unref();
} }
catalog->addObject(fContentStream.get(), firstPage); catalog->addObject(fContentStream.get(), firstPage);
fDevice->getResources(knownResourceObjects, newResourceObjects, true); fDevice->getResources(resourceObjects, true);
} }
off_t SkPDFPage::getPageSize(SkPDFCatalog* catalog, off_t fileOffset) { off_t SkPDFPage::getPageSize(SkPDFCatalog* catalog, off_t fileOffset) {

Просмотреть файл

@ -40,15 +40,13 @@ public:
* that the page is part of. * that the page is part of.
* @param catalog The catalog to add page content objects to. * @param catalog The catalog to add page content objects to.
* @param firstPage Indicate if this is the first page of a document. * @param firstPage Indicate if this is the first page of a document.
* @param newResourceObjects All the resource objects (recursively) used on * @param resourceObjects All the resource objects (recursively) used on
* the page are added to this array. This gives * the page are added to this array. This gives
* the caller a chance to deduplicate resources * the caller a chance to deduplicate resources
* across pages. * across pages.
* @param knownResourceObjects The set of resources to be ignored.
*/ */
void finalizePage(SkPDFCatalog* catalog, bool firstPage, void finalizePage(SkPDFCatalog* catalog, bool firstPage,
const SkTSet<SkPDFObject*>& knownResourceObjects, SkTDArray<SkPDFObject*>* resourceObjects);
SkTSet<SkPDFObject*>* newResourceObjects);
/** Determine the size of the page content and store to the catalog /** Determine the size of the page content and store to the catalog
* the offsets of all nonresource-indirect objects that make up the page * the offsets of all nonresource-indirect objects that make up the page

Просмотреть файл

@ -425,11 +425,8 @@ public:
virtual bool isValid() { return fResources.count() > 0; } virtual bool isValid() { return fResources.count() > 0; }
void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, void getResources(SkTDArray<SkPDFObject*>* resourceList) {
SkTSet<SkPDFObject*>* newResourceObjects) { GetResourcesHelper(&fResources, resourceList);
GetResourcesHelper(&fResources,
knownResourceObjects,
newResourceObjects);
} }
private: private:
@ -451,15 +448,12 @@ public:
virtual bool isValid() { return size() > 0; } virtual bool isValid() { return size() > 0; }
void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, void getResources(SkTDArray<SkPDFObject*>* resourceList) {
SkTSet<SkPDFObject*>* newResourceObjects) { GetResourcesHelper(&fResources, resourceList);
GetResourcesHelper(&fResources.toArray(),
knownResourceObjects,
newResourceObjects);
} }
private: private:
SkTSet<SkPDFObject*> fResources; SkTDArray<SkPDFObject*> fResources;
SkAutoTDelete<const SkPDFShader::State> fState; SkAutoTDelete<const SkPDFShader::State> fState;
}; };
@ -838,7 +832,7 @@ SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) {
// Put the canvas into the pattern stream (fContent). // Put the canvas into the pattern stream (fContent).
SkAutoTUnref<SkStream> content(pattern.content()); SkAutoTUnref<SkStream> content(pattern.content());
setData(content.get()); setData(content.get());
pattern.getResources(fResources, &fResources, false); pattern.getResources(&fResources, false);
insertName("Type", "Pattern"); insertName("Type", "Pattern");
insertInt("PatternType", 1); insertInt("PatternType", 1);

Просмотреть файл

@ -41,8 +41,7 @@ size_t SkPDFObject::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
return buffer.getOffset(); return buffer.getOffset();
} }
void SkPDFObject::getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, void SkPDFObject::getResources(SkTDArray<SkPDFObject*>* resourceList) {}
SkTSet<SkPDFObject*>* newResourceObjects) {}
void SkPDFObject::emitIndirectObject(SkWStream* stream, SkPDFCatalog* catalog) { void SkPDFObject::emitIndirectObject(SkWStream* stream, SkPDFCatalog* catalog) {
catalog->emitObjectNumber(stream, this); catalog->emitObjectNumber(stream, this);
@ -62,21 +61,14 @@ void SkPDFObject::AddResourceHelper(SkPDFObject* resource,
resource->ref(); resource->ref();
} }
void SkPDFObject::GetResourcesHelper( void SkPDFObject::GetResourcesHelper(SkTDArray<SkPDFObject*>* resources,
const SkTDArray<SkPDFObject*>* resources, SkTDArray<SkPDFObject*>* result) {
const SkTSet<SkPDFObject*>& knownResourceObjects,
SkTSet<SkPDFObject*>* newResourceObjects) {
if (resources->count()) { if (resources->count()) {
newResourceObjects->setReserve( result->setReserve(result->count() + resources->count());
newResourceObjects->count() + resources->count());
for (int i = 0; i < resources->count(); i++) { for (int i = 0; i < resources->count(); i++) {
if (!knownResourceObjects.contains((*resources)[i]) && result->push((*resources)[i]);
!newResourceObjects->contains((*resources)[i])) {
newResourceObjects->add((*resources)[i]);
(*resources)[i]->ref(); (*resources)[i]->ref();
(*resources)[i]->getResources(knownResourceObjects, (*resources)[i]->getResources(result);
newResourceObjects);
}
} }
} }
} }

Просмотреть файл

@ -14,7 +14,6 @@
#include "SkScalar.h" #include "SkScalar.h"
#include "SkString.h" #include "SkString.h"
#include "SkTDArray.h" #include "SkTDArray.h"
#include "SkTSet.h"
#include "SkTypes.h" #include "SkTypes.h"
class SkPDFCatalog; class SkPDFCatalog;
@ -39,16 +38,13 @@ public:
virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect);
/** For non-primitive objects (i.e. objects defined outside this file), /** For non-primitive objects (i.e. objects defined outside this file),
* this method will add to newResourceObjects any objects that this method * this method will add to resourceList any objects that this method
* depends on, but not already in knownResourceObjects. This operates * depends on. This operates recursively so if this object depends on
* recursively so if this object depends on another object and that object * another object and that object depends on two more, all three objects
* depends on two more, all three objects will be added. * will be added.
* * @param resourceList The list to append dependant resources to.
* @param knownResourceObjects The set of resources to be ignored.
* @param newResourceObjects The set to append dependant resources to.
*/ */
virtual void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, virtual void getResources(SkTDArray<SkPDFObject*>* resourceList);
SkTSet<SkPDFObject*>* newResourceObjects);
/** Emit this object unless the catalog has a substitute object, in which /** Emit this object unless the catalog has a substitute object, in which
* case emit that. * case emit that.
@ -78,16 +74,10 @@ public:
/** Static helper function to copy and reference the resources (and all /** Static helper function to copy and reference the resources (and all
* their subresources) into a new list. * their subresources) into a new list.
* @param resources The resource list. * @param resources The resource list.
* @param newResourceObjects All the resource objects (recursively) used on * @param result The list to add to.
* the page are added to this array. This gives
* the caller a chance to deduplicate resources
* across pages.
* @param knownResourceObjects The set of resources to be ignored.
*/ */
static void GetResourcesHelper( static void GetResourcesHelper(SkTDArray<SkPDFObject*>* resources,
const SkTDArray<SkPDFObject*>* resources, SkTDArray<SkPDFObject*>* result);
const SkTSet<SkPDFObject*>& knownResourceObjects,
SkTSet<SkPDFObject*>* newResourceObjects);
protected: protected:
/** Subclasses must implement this method to print the object to the /** Subclasses must implement this method to print the object to the

Просмотреть файл

@ -21,10 +21,10 @@
class SkPDFTestDict : public SkPDFDict { class SkPDFTestDict : public SkPDFDict {
public: public:
virtual void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, void getResources(SkTDArray<SkPDFObject*>* resourceList) {
SkTSet<SkPDFObject*>* newResourceObjects) { resourceList->setReserve(resourceList->count() + fResources.count());
for (int i = 0; i < fResources.count(); i++) { for (int i = 0; i < fResources.count(); i++) {
newResourceObjects->add(fResources[i]); resourceList->push(fResources[i]);
fResources[i]->ref(); fResources[i]->ref();
} }
} }