Adds SkPDFResourceDict class to manage resource dicts. Refactors existing code to use this class.
BUG= R=vandebo@chromium.org, edisonn@google.com Author: richardlin@chromium.org Review URL: https://chromiumcodereview.appspot.com/18977002 git-svn-id: http://skia.googlecode.com/svn/trunk@10202 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
6645cde43d
commit
c84fb471d1
@ -38,6 +38,8 @@
|
|||||||
'../src/pdf/SkPDFImageStream.h',
|
'../src/pdf/SkPDFImageStream.h',
|
||||||
'../src/pdf/SkPDFPage.cpp',
|
'../src/pdf/SkPDFPage.cpp',
|
||||||
'../src/pdf/SkPDFPage.h',
|
'../src/pdf/SkPDFPage.h',
|
||||||
|
'../src/pdf/SkPDFResourceDict.cpp',
|
||||||
|
'../src/pdf/SkPDFResourceDict.h',
|
||||||
'../src/pdf/SkPDFShader.cpp',
|
'../src/pdf/SkPDFShader.cpp',
|
||||||
'../src/pdf/SkPDFShader.h',
|
'../src/pdf/SkPDFShader.h',
|
||||||
'../src/pdf/SkPDFStream.cpp',
|
'../src/pdf/SkPDFStream.cpp',
|
||||||
|
@ -28,6 +28,7 @@ class SkPDFFormXObject;
|
|||||||
class SkPDFGlyphSetMap;
|
class SkPDFGlyphSetMap;
|
||||||
class SkPDFGraphicState;
|
class SkPDFGraphicState;
|
||||||
class SkPDFObject;
|
class SkPDFObject;
|
||||||
|
class SkPDFResourceDict;
|
||||||
class SkPDFShader;
|
class SkPDFShader;
|
||||||
class SkPDFStream;
|
class SkPDFStream;
|
||||||
template <typename T> class SkTSet;
|
template <typename T> class SkTSet;
|
||||||
@ -147,23 +148,7 @@ public:
|
|||||||
|
|
||||||
/** Returns the resource dictionary for this device.
|
/** Returns the resource dictionary for this device.
|
||||||
*/
|
*/
|
||||||
SK_API SkPDFDict* getResourceDict();
|
SK_API SkPDFResourceDict* getResourceDict();
|
||||||
|
|
||||||
/** Get the list of resources (PDF objects) used on this page.
|
|
||||||
* This method will add to newResourceObjects any objects that this method
|
|
||||||
* 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
|
|
||||||
* device's resources recursively. (Useful for adding
|
|
||||||
* objects to the catalog.)
|
|
||||||
*/
|
|
||||||
SK_API void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
|
|
||||||
SkTSet<SkPDFObject*>* newResourceObjects,
|
|
||||||
bool recursive) const;
|
|
||||||
|
|
||||||
/** Get the fonts used on this device.
|
/** Get the fonts used on this device.
|
||||||
*/
|
*/
|
||||||
@ -223,7 +208,7 @@ private:
|
|||||||
SkClipStack fExistingClipStack;
|
SkClipStack fExistingClipStack;
|
||||||
SkRegion fExistingClipRegion;
|
SkRegion fExistingClipRegion;
|
||||||
SkPDFArray* fAnnotations;
|
SkPDFArray* fAnnotations;
|
||||||
SkPDFDict* fResourceDict;
|
SkPDFResourceDict* fResourceDict;
|
||||||
SkTDArray<NamedDestination*> fNamedDestinations;
|
SkTDArray<NamedDestination*> fNamedDestinations;
|
||||||
|
|
||||||
SkTDArray<SkPDFGraphicState*> fGraphicStateResources;
|
SkTDArray<SkPDFGraphicState*> fGraphicStateResources;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "SkPDFFormXObject.h"
|
#include "SkPDFFormXObject.h"
|
||||||
#include "SkPDFGraphicState.h"
|
#include "SkPDFGraphicState.h"
|
||||||
#include "SkPDFImage.h"
|
#include "SkPDFImage.h"
|
||||||
|
#include "SkPDFResourceDict.h"
|
||||||
#include "SkPDFShader.h"
|
#include "SkPDFShader.h"
|
||||||
#include "SkPDFStream.h"
|
#include "SkPDFStream.h"
|
||||||
#include "SkPDFTypes.h"
|
#include "SkPDFTypes.h"
|
||||||
@ -424,10 +425,13 @@ void GraphicStackState::updateDrawingState(const GraphicStateEntry& state) {
|
|||||||
// PDF treats a shader as a color, so we only set one or the other.
|
// PDF treats a shader as a color, so we only set one or the other.
|
||||||
if (state.fShaderIndex >= 0) {
|
if (state.fShaderIndex >= 0) {
|
||||||
if (state.fShaderIndex != currentEntry()->fShaderIndex) {
|
if (state.fShaderIndex != currentEntry()->fShaderIndex) {
|
||||||
fContentStream->writeText("/Pattern CS /Pattern cs /P");
|
SkString resourceName = SkPDFResourceDict::getResourceName(
|
||||||
fContentStream->writeDecAsText(state.fShaderIndex);
|
SkPDFResourceDict::kPattern_ResourceType,
|
||||||
fContentStream->writeText(" SCN /P");
|
state.fShaderIndex);
|
||||||
fContentStream->writeDecAsText(state.fShaderIndex);
|
fContentStream->writeText("/Pattern CS /Pattern cs /");
|
||||||
|
fContentStream->writeText(resourceName.c_str());
|
||||||
|
fContentStream->writeText(" SCN /");
|
||||||
|
fContentStream->writeText(resourceName.c_str());
|
||||||
fContentStream->writeText(" scn\n");
|
fContentStream->writeText(" scn\n");
|
||||||
currentEntry()->fShaderIndex = state.fShaderIndex;
|
currentEntry()->fShaderIndex = state.fShaderIndex;
|
||||||
}
|
}
|
||||||
@ -1123,123 +1127,46 @@ void SkPDFDevice::setDrawingArea(DrawingArea drawingArea) {
|
|||||||
fDrawingArea = drawingArea;
|
fDrawingArea = drawingArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkPDFDict* SkPDFDevice::getResourceDict() {
|
SkPDFResourceDict* SkPDFDevice::getResourceDict() {
|
||||||
if (NULL == fResourceDict) {
|
if (NULL == fResourceDict) {
|
||||||
fResourceDict = SkNEW(SkPDFDict);
|
fResourceDict = SkNEW(SkPDFResourceDict);
|
||||||
|
|
||||||
if (fGraphicStateResources.count()) {
|
if (fGraphicStateResources.count()) {
|
||||||
SkAutoTUnref<SkPDFDict> extGState(new SkPDFDict());
|
|
||||||
for (int i = 0; i < fGraphicStateResources.count(); i++) {
|
for (int i = 0; i < fGraphicStateResources.count(); i++) {
|
||||||
SkString nameString("G");
|
fResourceDict->insertResourceAsRef(
|
||||||
nameString.appendS32(i);
|
SkPDFResourceDict::kExtGState_ResourceType,
|
||||||
extGState->insert(
|
i, fGraphicStateResources[i]);
|
||||||
nameString.c_str(),
|
|
||||||
new SkPDFObjRef(fGraphicStateResources[i]))->unref();
|
|
||||||
}
|
}
|
||||||
fResourceDict->insert("ExtGState", extGState.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fXObjectResources.count()) {
|
if (fXObjectResources.count()) {
|
||||||
SkAutoTUnref<SkPDFDict> xObjects(new SkPDFDict());
|
|
||||||
for (int i = 0; i < fXObjectResources.count(); i++) {
|
for (int i = 0; i < fXObjectResources.count(); i++) {
|
||||||
SkString nameString("X");
|
fResourceDict->insertResourceAsRef(
|
||||||
nameString.appendS32(i);
|
SkPDFResourceDict::kXObject_ResourceType,
|
||||||
xObjects->insert(
|
i, fXObjectResources[i]);
|
||||||
nameString.c_str(),
|
|
||||||
new SkPDFObjRef(fXObjectResources[i]))->unref();
|
|
||||||
}
|
}
|
||||||
fResourceDict->insert("XObject", xObjects.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fFontResources.count()) {
|
if (fFontResources.count()) {
|
||||||
SkAutoTUnref<SkPDFDict> fonts(new SkPDFDict());
|
|
||||||
for (int i = 0; i < fFontResources.count(); i++) {
|
for (int i = 0; i < fFontResources.count(); i++) {
|
||||||
SkString nameString("F");
|
fResourceDict->insertResourceAsRef(
|
||||||
nameString.appendS32(i);
|
SkPDFResourceDict::kFont_ResourceType,
|
||||||
fonts->insert(nameString.c_str(),
|
i, fFontResources[i]);
|
||||||
new SkPDFObjRef(fFontResources[i]))->unref();
|
|
||||||
}
|
}
|
||||||
fResourceDict->insert("Font", fonts.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fShaderResources.count()) {
|
if (fShaderResources.count()) {
|
||||||
SkAutoTUnref<SkPDFDict> patterns(new SkPDFDict());
|
SkAutoTUnref<SkPDFDict> patterns(new SkPDFDict());
|
||||||
for (int i = 0; i < fShaderResources.count(); i++) {
|
for (int i = 0; i < fShaderResources.count(); i++) {
|
||||||
SkString nameString("P");
|
fResourceDict->insertResourceAsRef(
|
||||||
nameString.appendS32(i);
|
SkPDFResourceDict::kPattern_ResourceType,
|
||||||
patterns->insert(nameString.c_str(),
|
i, fShaderResources[i]);
|
||||||
new SkPDFObjRef(fShaderResources[i]))->unref();
|
|
||||||
}
|
}
|
||||||
fResourceDict->insert("Pattern", patterns.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For compatibility, add all proc sets (only used for output to PS
|
|
||||||
// devices).
|
|
||||||
const char procs[][7] = {"PDF", "Text", "ImageB", "ImageC", "ImageI"};
|
|
||||||
SkAutoTUnref<SkPDFArray> procSets(new SkPDFArray());
|
|
||||||
procSets->reserve(SK_ARRAY_COUNT(procs));
|
|
||||||
for (size_t i = 0; i < SK_ARRAY_COUNT(procs); i++)
|
|
||||||
procSets->appendName(procs[i]);
|
|
||||||
fResourceDict->insert("ProcSet", procSets.get());
|
|
||||||
}
|
}
|
||||||
return fResourceDict;
|
return fResourceDict;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkPDFDevice::getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
|
|
||||||
SkTSet<SkPDFObject*>* newResourceObjects,
|
|
||||||
bool recursive) const {
|
|
||||||
// TODO: reserve not correct if we need to recursively explore.
|
|
||||||
newResourceObjects->setReserve(newResourceObjects->count() +
|
|
||||||
fGraphicStateResources.count() +
|
|
||||||
fXObjectResources.count() +
|
|
||||||
fFontResources.count() +
|
|
||||||
fShaderResources.count());
|
|
||||||
for (int i = 0; i < fGraphicStateResources.count(); i++) {
|
|
||||||
if (!knownResourceObjects.contains(fGraphicStateResources[i]) &&
|
|
||||||
!newResourceObjects->contains(fGraphicStateResources[i])) {
|
|
||||||
newResourceObjects->add(fGraphicStateResources[i]);
|
|
||||||
fGraphicStateResources[i]->ref();
|
|
||||||
if (recursive) {
|
|
||||||
fGraphicStateResources[i]->getResources(knownResourceObjects,
|
|
||||||
newResourceObjects);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < fXObjectResources.count(); i++) {
|
|
||||||
if (!knownResourceObjects.contains(fXObjectResources[i]) &&
|
|
||||||
!newResourceObjects->contains(fXObjectResources[i])) {
|
|
||||||
newResourceObjects->add(fXObjectResources[i]);
|
|
||||||
fXObjectResources[i]->ref();
|
|
||||||
if (recursive) {
|
|
||||||
fXObjectResources[i]->getResources(knownResourceObjects,
|
|
||||||
newResourceObjects);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < fFontResources.count(); i++) {
|
|
||||||
if (!knownResourceObjects.contains(fFontResources[i]) &&
|
|
||||||
!newResourceObjects->contains(fFontResources[i])) {
|
|
||||||
newResourceObjects->add(fFontResources[i]);
|
|
||||||
fFontResources[i]->ref();
|
|
||||||
if (recursive) {
|
|
||||||
fFontResources[i]->getResources(knownResourceObjects,
|
|
||||||
newResourceObjects);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < fShaderResources.count(); i++) {
|
|
||||||
if (!knownResourceObjects.contains(fShaderResources[i]) &&
|
|
||||||
!newResourceObjects->contains(fShaderResources[i])) {
|
|
||||||
newResourceObjects->add(fShaderResources[i]);
|
|
||||||
fShaderResources[i]->ref();
|
|
||||||
if (recursive) {
|
|
||||||
fShaderResources[i]->getResources(knownResourceObjects,
|
|
||||||
newResourceObjects);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const SkTDArray<SkPDFFont*>& SkPDFDevice::getFontResources() const {
|
const SkTDArray<SkPDFFont*>& SkPDFDevice::getFontResources() const {
|
||||||
return fFontResources;
|
return fFontResources;
|
||||||
}
|
}
|
||||||
@ -1771,8 +1698,10 @@ void SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID,
|
|||||||
contentEntry->fState.fTextSize != paint.getTextSize() ||
|
contentEntry->fState.fTextSize != paint.getTextSize() ||
|
||||||
!contentEntry->fState.fFont->hasGlyph(glyphID)) {
|
!contentEntry->fState.fFont->hasGlyph(glyphID)) {
|
||||||
int fontIndex = getFontResourceIndex(typeface, glyphID);
|
int fontIndex = getFontResourceIndex(typeface, glyphID);
|
||||||
contentEntry->fContent.writeText("/F");
|
contentEntry->fContent.writeText("/");
|
||||||
contentEntry->fContent.writeDecAsText(fontIndex);
|
contentEntry->fContent.writeText(SkPDFResourceDict::getResourceName(
|
||||||
|
SkPDFResourceDict::kFont_ResourceType,
|
||||||
|
fontIndex).c_str());
|
||||||
contentEntry->fContent.writeText(" ");
|
contentEntry->fContent.writeText(" ");
|
||||||
SkPDFScalar::Append(paint.getTextSize(), &contentEntry->fContent);
|
SkPDFScalar::Append(paint.getTextSize(), &contentEntry->fContent);
|
||||||
contentEntry->fContent.writeText(" Tf\n");
|
contentEntry->fContent.writeText(" Tf\n");
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "SkMatrix.h"
|
#include "SkMatrix.h"
|
||||||
#include "SkPDFCatalog.h"
|
#include "SkPDFCatalog.h"
|
||||||
#include "SkPDFDevice.h"
|
#include "SkPDFDevice.h"
|
||||||
|
#include "SkPDFResourceDict.h"
|
||||||
#include "SkPDFUtils.h"
|
#include "SkPDFUtils.h"
|
||||||
#include "SkStream.h"
|
#include "SkStream.h"
|
||||||
#include "SkTypes.h"
|
#include "SkTypes.h"
|
||||||
@ -21,7 +22,8 @@ SkPDFFormXObject::SkPDFFormXObject(SkPDFDevice* device) {
|
|||||||
// 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;
|
SkTSet<SkPDFObject*> emptySet;
|
||||||
device->getResources(emptySet, &fResources, false);
|
SkPDFResourceDict* resourceDict = device->getResourceDict();
|
||||||
|
resourceDict->getResources(emptySet, &fResources, false);
|
||||||
|
|
||||||
SkAutoTUnref<SkStream> content(device->content());
|
SkAutoTUnref<SkStream> content(device->content());
|
||||||
setData(content.get());
|
setData(content.get());
|
||||||
@ -29,7 +31,7 @@ SkPDFFormXObject::SkPDFFormXObject(SkPDFDevice* device) {
|
|||||||
insertName("Type", "XObject");
|
insertName("Type", "XObject");
|
||||||
insertName("Subtype", "Form");
|
insertName("Subtype", "Form");
|
||||||
SkSafeUnref(this->insert("BBox", device->copyMediaBox()));
|
SkSafeUnref(this->insert("BBox", device->copyMediaBox()));
|
||||||
insert("Resources", device->getResourceDict());
|
insert("Resources", resourceDict);
|
||||||
|
|
||||||
// We invert the initial transform and apply that to the xobject so that
|
// We invert the initial transform and apply that to the xobject so that
|
||||||
// it doesn't get applied twice. We can't just undo it because it's
|
// it doesn't get applied twice. We can't just undo it because it's
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "SkPDFCatalog.h"
|
#include "SkPDFCatalog.h"
|
||||||
#include "SkPDFDevice.h"
|
#include "SkPDFDevice.h"
|
||||||
#include "SkPDFPage.h"
|
#include "SkPDFPage.h"
|
||||||
|
#include "SkPDFResourceDict.h"
|
||||||
#include "SkStream.h"
|
#include "SkStream.h"
|
||||||
|
|
||||||
SkPDFPage::SkPDFPage(SkPDFDevice* content)
|
SkPDFPage::SkPDFPage(SkPDFDevice* content)
|
||||||
@ -23,8 +24,9 @@ SkPDFPage::~SkPDFPage() {}
|
|||||||
void SkPDFPage::finalizePage(SkPDFCatalog* catalog, bool firstPage,
|
void SkPDFPage::finalizePage(SkPDFCatalog* catalog, bool firstPage,
|
||||||
const SkTSet<SkPDFObject*>& knownResourceObjects,
|
const SkTSet<SkPDFObject*>& knownResourceObjects,
|
||||||
SkTSet<SkPDFObject*>* newResourceObjects) {
|
SkTSet<SkPDFObject*>* newResourceObjects) {
|
||||||
|
SkPDFResourceDict* resourceDict = fDevice->getResourceDict();
|
||||||
if (fContentStream.get() == NULL) {
|
if (fContentStream.get() == NULL) {
|
||||||
insert("Resources", fDevice->getResourceDict());
|
insert("Resources", resourceDict);
|
||||||
SkSafeUnref(this->insert("MediaBox", fDevice->copyMediaBox()));
|
SkSafeUnref(this->insert("MediaBox", fDevice->copyMediaBox()));
|
||||||
if (!SkToBool(catalog->getDocumentFlags() &
|
if (!SkToBool(catalog->getDocumentFlags() &
|
||||||
SkPDFDocument::kNoLinks_Flags)) {
|
SkPDFDocument::kNoLinks_Flags)) {
|
||||||
@ -39,7 +41,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);
|
resourceDict->getResources(knownResourceObjects, newResourceObjects, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t SkPDFPage::getPageSize(SkPDFCatalog* catalog, off_t fileOffset) {
|
off_t SkPDFPage::getPageSize(SkPDFCatalog* catalog, off_t fileOffset) {
|
||||||
|
125
src/pdf/SkPDFResourceDict.cpp
Normal file
125
src/pdf/SkPDFResourceDict.cpp
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 Google Inc.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SkPDFResourceDict.h"
|
||||||
|
#include "SkPostConfig.h"
|
||||||
|
|
||||||
|
SK_DEFINE_INST_COUNT(SkPDFResourceDict)
|
||||||
|
|
||||||
|
// Sanity check that the values of enum SkPDFResourceType correspond to the
|
||||||
|
// expected values as defined in the arrays below.
|
||||||
|
// If these are failing, you may need to update the resource_type_prefixes
|
||||||
|
// and resource_type_names arrays below.
|
||||||
|
SK_COMPILE_ASSERT(SkPDFResourceDict::kExtGState_ResourceType == 0,
|
||||||
|
resource_type_mismatch);
|
||||||
|
SK_COMPILE_ASSERT(SkPDFResourceDict::kPattern_ResourceType == 1,
|
||||||
|
resource_type_mismatch);
|
||||||
|
SK_COMPILE_ASSERT(SkPDFResourceDict::kXObject_ResourceType == 2,
|
||||||
|
resource_type_mismatch);
|
||||||
|
SK_COMPILE_ASSERT(SkPDFResourceDict::kFont_ResourceType == 3,
|
||||||
|
resource_type_mismatch);
|
||||||
|
|
||||||
|
static const char resource_type_prefixes[] = {
|
||||||
|
'G',
|
||||||
|
'P',
|
||||||
|
'X',
|
||||||
|
'F'
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* resource_type_names[] = {
|
||||||
|
"ExtGState",
|
||||||
|
"Pattern",
|
||||||
|
"XObject",
|
||||||
|
"Font"
|
||||||
|
};
|
||||||
|
|
||||||
|
static char get_resource_type_prefix(
|
||||||
|
SkPDFResourceDict::SkPDFResourceType type) {
|
||||||
|
SkASSERT(type >= 0);
|
||||||
|
SkASSERT(type < SkPDFResourceDict::kResourceTypeCount);
|
||||||
|
|
||||||
|
return resource_type_prefixes[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* get_resource_type_name(
|
||||||
|
SkPDFResourceDict::SkPDFResourceType type) {
|
||||||
|
SkASSERT(type >= 0);
|
||||||
|
SkASSERT(type < SkPDFResourceDict::kResourceTypeCount);
|
||||||
|
|
||||||
|
return resource_type_names[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
SkPDFResourceDict::SkPDFResourceDict() : SkPDFDict() {
|
||||||
|
const char procs[][7] = {"PDF", "Text", "ImageB", "ImageC", "ImageI"};
|
||||||
|
SkPDFArray* procSets = SkNEW(SkPDFArray());
|
||||||
|
|
||||||
|
procSets->reserve(SK_ARRAY_COUNT(procs));
|
||||||
|
for (size_t i = 0; i < SK_ARRAY_COUNT(procs); i++) {
|
||||||
|
procSets->appendName(procs[i]);
|
||||||
|
}
|
||||||
|
insert("ProcSets", procSets)->unref();
|
||||||
|
|
||||||
|
// Actual sub-dicts will be lazily added later
|
||||||
|
fTypes.setCount(kResourceTypeCount);
|
||||||
|
for (size_t i=0; i < kResourceTypeCount; i++) {
|
||||||
|
fTypes[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SkPDFObject* SkPDFResourceDict::insertResourceAsRef(
|
||||||
|
SkPDFResourceType type, int key, SkPDFObject* value) {
|
||||||
|
SkAutoTUnref<SkPDFObjRef> ref(SkNEW_ARGS(SkPDFObjRef, (value)));
|
||||||
|
insertResource(type, key, ref);
|
||||||
|
fResources.add(value);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkPDFResourceDict::getResources(
|
||||||
|
const SkTSet<SkPDFObject*>& knownResourceObjects,
|
||||||
|
SkTSet<SkPDFObject*>* newResourceObjects,
|
||||||
|
bool recursive) const {
|
||||||
|
// TODO: reserve not correct if we need to recursively explore.
|
||||||
|
newResourceObjects->setReserve(newResourceObjects->count() +
|
||||||
|
fResources.count());
|
||||||
|
|
||||||
|
for (int i = 0; i < fResources.count(); i++) {
|
||||||
|
if (!knownResourceObjects.contains(fResources[i]) &&
|
||||||
|
!newResourceObjects->contains(fResources[i])) {
|
||||||
|
newResourceObjects->add(fResources[i]);
|
||||||
|
fResources[i]->ref();
|
||||||
|
if (recursive) {
|
||||||
|
fResources[i]->getResources(knownResourceObjects,
|
||||||
|
newResourceObjects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SkString SkPDFResourceDict::getResourceName(
|
||||||
|
SkPDFResourceType type, int key) {
|
||||||
|
SkString keyString;
|
||||||
|
keyString.printf("%c%d", get_resource_type_prefix(type), key);
|
||||||
|
return keyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkPDFObject* SkPDFResourceDict::insertResource(
|
||||||
|
SkPDFResourceType type, int key, SkPDFObject* value) {
|
||||||
|
SkPDFDict* typeDict = fTypes[type];
|
||||||
|
if (NULL == typeDict) {
|
||||||
|
SkAutoTUnref<SkPDFDict> newDict(SkNEW(SkPDFDict()));
|
||||||
|
SkPDFName* typeName = SkNEW_ARGS(
|
||||||
|
SkPDFName, (get_resource_type_name(type)));
|
||||||
|
insert(typeName, newDict); // ref counting handled here
|
||||||
|
fTypes[type] = newDict;
|
||||||
|
typeDict = newDict.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
SkPDFName* keyName = SkNEW_ARGS(SkPDFName, (getResourceName(type, key)));
|
||||||
|
typeDict->insert(keyName, value);
|
||||||
|
return value;
|
||||||
|
}
|
100
src/pdf/SkPDFResourceDict.h
Normal file
100
src/pdf/SkPDFResourceDict.h
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 Google Inc.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SkPDFResourceDict_DEFINED
|
||||||
|
#define SkPDFResourceDict_DEFINED
|
||||||
|
|
||||||
|
#include "SkPDFTypes.h"
|
||||||
|
#include "SkTDArray.h"
|
||||||
|
#include "SkTSet.h"
|
||||||
|
#include "SkTypes.h"
|
||||||
|
|
||||||
|
/** \class SkPDFResourceDict
|
||||||
|
|
||||||
|
A resource dictionary, which maintains the relevant sub-dicts and
|
||||||
|
allows generation of a list of referenced SkPDFObjects inserted with
|
||||||
|
insertResourceAsRef.
|
||||||
|
*/
|
||||||
|
class SkPDFResourceDict : public SkPDFDict {
|
||||||
|
public:
|
||||||
|
SK_DECLARE_INST_COUNT(SkPDFResourceDict)
|
||||||
|
|
||||||
|
enum SkPDFResourceType{
|
||||||
|
kExtGState_ResourceType,
|
||||||
|
kPattern_ResourceType,
|
||||||
|
kXObject_ResourceType,
|
||||||
|
kFont_ResourceType,
|
||||||
|
// These additional types are defined by the spec, but not
|
||||||
|
// currently used by Skia: ColorSpace, Shading, Properties
|
||||||
|
kResourceTypeCount
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Create a PDF resource dictionary.
|
||||||
|
* The full set of ProcSet entries is automatically created for backwards
|
||||||
|
* compatibility, as recommended by the PDF spec.
|
||||||
|
*/
|
||||||
|
SkPDFResourceDict();
|
||||||
|
|
||||||
|
/** Add the value SkPDFObject as a reference to the resource dictionary
|
||||||
|
* with the give type and key.
|
||||||
|
* The relevant sub-dicts will be automatically generated, and the
|
||||||
|
* resource will be named by concatenating a type-specific prefix and
|
||||||
|
* the input key.
|
||||||
|
* This object will be part of the resource list when requested later.
|
||||||
|
* @param type The type of resource being entered, like
|
||||||
|
* kPattern_ResourceType or kExtGState_ResourceType.
|
||||||
|
* @param key The resource key, should be unique within its type.
|
||||||
|
* @param value The resource itself.
|
||||||
|
* @return The value argument is returned.
|
||||||
|
*/
|
||||||
|
SkPDFObject* insertResourceAsRef(SkPDFResourceType type, int key,
|
||||||
|
SkPDFObject* value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets resources inserted into this dictionary.
|
||||||
|
*
|
||||||
|
* @param knownResourceObjects Set containing currently known resources.
|
||||||
|
* Resources in the dict and this set will not be added to the output.
|
||||||
|
* @param newResourceObjects Output set to which non-preexisting resources
|
||||||
|
* will be added.
|
||||||
|
* @param recursive Whether or not to add resources of resources.
|
||||||
|
*/
|
||||||
|
void getResources(
|
||||||
|
const SkTSet<SkPDFObject*>& knownResourceObjects,
|
||||||
|
SkTSet<SkPDFObject*>* newResourceObjects,
|
||||||
|
bool recursive) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name for the resource that will be generated by the resource
|
||||||
|
* dict.
|
||||||
|
*
|
||||||
|
* @param type The type of resource being entered, like
|
||||||
|
* kPattern_ResourceType or kExtGState_ResourceType.
|
||||||
|
* @param key The resource key, should be unique within its type.
|
||||||
|
*/
|
||||||
|
static SkString getResourceName(SkPDFResourceType type, int key);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** Add the value to the dictionary with the given key. Refs value.
|
||||||
|
* The relevant sub-dicts will be automatically generated, and the
|
||||||
|
* resource will be named by concatenating a type-specific prefix and
|
||||||
|
* the input key.
|
||||||
|
* The object will NOT be part of the resource list when requested later.
|
||||||
|
* @param type The type of resource being entered.
|
||||||
|
* @param key The resource key, should be unique within its type.
|
||||||
|
* @param value The resource itself.
|
||||||
|
* @return The value argument is returned.
|
||||||
|
*/
|
||||||
|
SkPDFObject* insertResource(SkPDFResourceType type, int key,
|
||||||
|
SkPDFObject* value);
|
||||||
|
|
||||||
|
SkTSet<SkPDFObject*> fResources;
|
||||||
|
|
||||||
|
SkTDArray<SkPDFDict*> fTypes;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -14,6 +14,7 @@
|
|||||||
#include "SkPDFCatalog.h"
|
#include "SkPDFCatalog.h"
|
||||||
#include "SkPDFDevice.h"
|
#include "SkPDFDevice.h"
|
||||||
#include "SkPDFTypes.h"
|
#include "SkPDFTypes.h"
|
||||||
|
#include "SkPDFResourceDict.h"
|
||||||
#include "SkPDFUtils.h"
|
#include "SkPDFUtils.h"
|
||||||
#include "SkScalar.h"
|
#include "SkScalar.h"
|
||||||
#include "SkStream.h"
|
#include "SkStream.h"
|
||||||
@ -838,7 +839,8 @@ 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);
|
SkPDFResourceDict* resourceDict = pattern.getResourceDict();
|
||||||
|
resourceDict->getResources(fResources, &fResources, false);
|
||||||
|
|
||||||
insertName("Type", "Pattern");
|
insertName("Type", "Pattern");
|
||||||
insertInt("PatternType", 1);
|
insertInt("PatternType", 1);
|
||||||
@ -847,7 +849,7 @@ SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) {
|
|||||||
insert("BBox", patternBBoxArray.get());
|
insert("BBox", patternBBoxArray.get());
|
||||||
insertScalar("XStep", patternBBox.width());
|
insertScalar("XStep", patternBBox.width());
|
||||||
insertScalar("YStep", patternBBox.height());
|
insertScalar("YStep", patternBBox.height());
|
||||||
insert("Resources", pattern.getResourceDict());
|
insert("Resources", resourceDict);
|
||||||
insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref();
|
insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref();
|
||||||
|
|
||||||
fState.get()->fImage.unlockPixels();
|
fState.get()->fImage.unlockPixels();
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "SkGeometry.h"
|
#include "SkGeometry.h"
|
||||||
#include "SkPaint.h"
|
#include "SkPaint.h"
|
||||||
#include "SkPath.h"
|
#include "SkPath.h"
|
||||||
|
#include "SkPDFResourceDict.h"
|
||||||
#include "SkPDFUtils.h"
|
#include "SkPDFUtils.h"
|
||||||
#include "SkStream.h"
|
#include "SkStream.h"
|
||||||
#include "SkString.h"
|
#include "SkString.h"
|
||||||
@ -206,14 +207,18 @@ void SkPDFUtils::StrokePath(SkWStream* content) {
|
|||||||
|
|
||||||
// static
|
// static
|
||||||
void SkPDFUtils::DrawFormXObject(int objectIndex, SkWStream* content) {
|
void SkPDFUtils::DrawFormXObject(int objectIndex, SkWStream* content) {
|
||||||
content->writeText("/X");
|
content->writeText("/");
|
||||||
content->writeDecAsText(objectIndex);
|
content->writeText(SkPDFResourceDict::getResourceName(
|
||||||
|
SkPDFResourceDict::kXObject_ResourceType,
|
||||||
|
objectIndex).c_str());
|
||||||
content->writeText(" Do\n");
|
content->writeText(" Do\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void SkPDFUtils::ApplyGraphicState(int objectIndex, SkWStream* content) {
|
void SkPDFUtils::ApplyGraphicState(int objectIndex, SkWStream* content) {
|
||||||
content->writeText("/G");
|
content->writeText("/");
|
||||||
content->writeDecAsText(objectIndex);
|
content->writeText(SkPDFResourceDict::getResourceName(
|
||||||
|
SkPDFResourceDict::kExtGState_ResourceType,
|
||||||
|
objectIndex).c_str());
|
||||||
content->writeText(" gs\n");
|
content->writeText(" gs\n");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user