aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-07-19 18:58:34 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-07-19 18:58:34 +0000
commitc84fb471d1428b254c2326d4ce68497c09d2ec45 (patch)
tree1c4c5a4e9128bd1bad60739c59aee2796624abc8 /src
parent6645cde43d7dbf0df76dbda2c089d8f58560e3e2 (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/pdf/SkPDFDevice.cpp123
-rw-r--r--src/pdf/SkPDFFormXObject.cpp6
-rw-r--r--src/pdf/SkPDFPage.cpp6
-rw-r--r--src/pdf/SkPDFResourceDict.cpp125
-rw-r--r--src/pdf/SkPDFResourceDict.h100
-rw-r--r--src/pdf/SkPDFShader.cpp6
-rw-r--r--src/pdf/SkPDFUtils.cpp13
7 files changed, 272 insertions, 107 deletions
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index a8fc3990d8..f925980c94 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -20,6 +20,7 @@
#include "SkPDFFormXObject.h"
#include "SkPDFGraphicState.h"
#include "SkPDFImage.h"
+#include "SkPDFResourceDict.h"
#include "SkPDFShader.h"
#include "SkPDFStream.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.
if (state.fShaderIndex >= 0) {
if (state.fShaderIndex != currentEntry()->fShaderIndex) {
- fContentStream->writeText("/Pattern CS /Pattern cs /P");
- fContentStream->writeDecAsText(state.fShaderIndex);
- fContentStream->writeText(" SCN /P");
- fContentStream->writeDecAsText(state.fShaderIndex);
+ SkString resourceName = SkPDFResourceDict::getResourceName(
+ SkPDFResourceDict::kPattern_ResourceType,
+ 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");
currentEntry()->fShaderIndex = state.fShaderIndex;
}
@@ -1123,123 +1127,46 @@ void SkPDFDevice::setDrawingArea(DrawingArea drawingArea) {
fDrawingArea = drawingArea;
}
-SkPDFDict* SkPDFDevice::getResourceDict() {
+SkPDFResourceDict* SkPDFDevice::getResourceDict() {
if (NULL == fResourceDict) {
- fResourceDict = SkNEW(SkPDFDict);
+ fResourceDict = SkNEW(SkPDFResourceDict);
if (fGraphicStateResources.count()) {
- SkAutoTUnref<SkPDFDict> extGState(new SkPDFDict());
for (int i = 0; i < fGraphicStateResources.count(); i++) {
- SkString nameString("G");
- nameString.appendS32(i);
- extGState->insert(
- nameString.c_str(),
- new SkPDFObjRef(fGraphicStateResources[i]))->unref();
+ fResourceDict->insertResourceAsRef(
+ SkPDFResourceDict::kExtGState_ResourceType,
+ i, fGraphicStateResources[i]);
}
- fResourceDict->insert("ExtGState", extGState.get());
}
if (fXObjectResources.count()) {
- SkAutoTUnref<SkPDFDict> xObjects(new SkPDFDict());
for (int i = 0; i < fXObjectResources.count(); i++) {
- SkString nameString("X");
- nameString.appendS32(i);
- xObjects->insert(
- nameString.c_str(),
- new SkPDFObjRef(fXObjectResources[i]))->unref();
+ fResourceDict->insertResourceAsRef(
+ SkPDFResourceDict::kXObject_ResourceType,
+ i, fXObjectResources[i]);
}
- fResourceDict->insert("XObject", xObjects.get());
}
if (fFontResources.count()) {
- SkAutoTUnref<SkPDFDict> fonts(new SkPDFDict());
for (int i = 0; i < fFontResources.count(); i++) {
- SkString nameString("F");
- nameString.appendS32(i);
- fonts->insert(nameString.c_str(),
- new SkPDFObjRef(fFontResources[i]))->unref();
+ fResourceDict->insertResourceAsRef(
+ SkPDFResourceDict::kFont_ResourceType,
+ i, fFontResources[i]);
}
- fResourceDict->insert("Font", fonts.get());
}
if (fShaderResources.count()) {
SkAutoTUnref<SkPDFDict> patterns(new SkPDFDict());
for (int i = 0; i < fShaderResources.count(); i++) {
- SkString nameString("P");
- nameString.appendS32(i);
- patterns->insert(nameString.c_str(),
- new SkPDFObjRef(fShaderResources[i]))->unref();
+ fResourceDict->insertResourceAsRef(
+ SkPDFResourceDict::kPattern_ResourceType,
+ i, fShaderResources[i]);
}
- 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;
}
-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 {
return fFontResources;
}
@@ -1771,8 +1698,10 @@ void SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID,
contentEntry->fState.fTextSize != paint.getTextSize() ||
!contentEntry->fState.fFont->hasGlyph(glyphID)) {
int fontIndex = getFontResourceIndex(typeface, glyphID);
- contentEntry->fContent.writeText("/F");
- contentEntry->fContent.writeDecAsText(fontIndex);
+ contentEntry->fContent.writeText("/");
+ contentEntry->fContent.writeText(SkPDFResourceDict::getResourceName(
+ SkPDFResourceDict::kFont_ResourceType,
+ fontIndex).c_str());
contentEntry->fContent.writeText(" ");
SkPDFScalar::Append(paint.getTextSize(), &contentEntry->fContent);
contentEntry->fContent.writeText(" Tf\n");
diff --git a/src/pdf/SkPDFFormXObject.cpp b/src/pdf/SkPDFFormXObject.cpp
index 884e6db2e4..e78891a972 100644
--- a/src/pdf/SkPDFFormXObject.cpp
+++ b/src/pdf/SkPDFFormXObject.cpp
@@ -12,6 +12,7 @@
#include "SkMatrix.h"
#include "SkPDFCatalog.h"
#include "SkPDFDevice.h"
+#include "SkPDFResourceDict.h"
#include "SkPDFUtils.h"
#include "SkStream.h"
#include "SkTypes.h"
@@ -21,7 +22,8 @@ SkPDFFormXObject::SkPDFFormXObject(SkPDFDevice* device) {
// of content, so reference or copy everything we need (content and
// resources).
SkTSet<SkPDFObject*> emptySet;
- device->getResources(emptySet, &fResources, false);
+ SkPDFResourceDict* resourceDict = device->getResourceDict();
+ resourceDict->getResources(emptySet, &fResources, false);
SkAutoTUnref<SkStream> content(device->content());
setData(content.get());
@@ -29,7 +31,7 @@ SkPDFFormXObject::SkPDFFormXObject(SkPDFDevice* device) {
insertName("Type", "XObject");
insertName("Subtype", "Form");
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
// it doesn't get applied twice. We can't just undo it because it's
diff --git a/src/pdf/SkPDFPage.cpp b/src/pdf/SkPDFPage.cpp
index d940f41065..f59b5d572c 100644
--- a/src/pdf/SkPDFPage.cpp
+++ b/src/pdf/SkPDFPage.cpp
@@ -10,6 +10,7 @@
#include "SkPDFCatalog.h"
#include "SkPDFDevice.h"
#include "SkPDFPage.h"
+#include "SkPDFResourceDict.h"
#include "SkStream.h"
SkPDFPage::SkPDFPage(SkPDFDevice* content)
@@ -23,8 +24,9 @@ SkPDFPage::~SkPDFPage() {}
void SkPDFPage::finalizePage(SkPDFCatalog* catalog, bool firstPage,
const SkTSet<SkPDFObject*>& knownResourceObjects,
SkTSet<SkPDFObject*>* newResourceObjects) {
+ SkPDFResourceDict* resourceDict = fDevice->getResourceDict();
if (fContentStream.get() == NULL) {
- insert("Resources", fDevice->getResourceDict());
+ insert("Resources", resourceDict);
SkSafeUnref(this->insert("MediaBox", fDevice->copyMediaBox()));
if (!SkToBool(catalog->getDocumentFlags() &
SkPDFDocument::kNoLinks_Flags)) {
@@ -39,7 +41,7 @@ void SkPDFPage::finalizePage(SkPDFCatalog* catalog, bool firstPage,
insert("Contents", new SkPDFObjRef(fContentStream.get()))->unref();
}
catalog->addObject(fContentStream.get(), firstPage);
- fDevice->getResources(knownResourceObjects, newResourceObjects, true);
+ resourceDict->getResources(knownResourceObjects, newResourceObjects, true);
}
off_t SkPDFPage::getPageSize(SkPDFCatalog* catalog, off_t fileOffset) {
diff --git a/src/pdf/SkPDFResourceDict.cpp b/src/pdf/SkPDFResourceDict.cpp
new file mode 100644
index 0000000000..fa72013875
--- /dev/null
+++ b/src/pdf/SkPDFResourceDict.cpp
@@ -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;
+}
diff --git a/src/pdf/SkPDFResourceDict.h b/src/pdf/SkPDFResourceDict.h
new file mode 100644
index 0000000000..004167925e
--- /dev/null
+++ b/src/pdf/SkPDFResourceDict.h
@@ -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
diff --git a/src/pdf/SkPDFShader.cpp b/src/pdf/SkPDFShader.cpp
index a0dffb7791..fec9d05b62 100644
--- a/src/pdf/SkPDFShader.cpp
+++ b/src/pdf/SkPDFShader.cpp
@@ -14,6 +14,7 @@
#include "SkPDFCatalog.h"
#include "SkPDFDevice.h"
#include "SkPDFTypes.h"
+#include "SkPDFResourceDict.h"
#include "SkPDFUtils.h"
#include "SkScalar.h"
#include "SkStream.h"
@@ -838,7 +839,8 @@ SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) {
// Put the canvas into the pattern stream (fContent).
SkAutoTUnref<SkStream> content(pattern.content());
setData(content.get());
- pattern.getResources(fResources, &fResources, false);
+ SkPDFResourceDict* resourceDict = pattern.getResourceDict();
+ resourceDict->getResources(fResources, &fResources, false);
insertName("Type", "Pattern");
insertInt("PatternType", 1);
@@ -847,7 +849,7 @@ SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) {
insert("BBox", patternBBoxArray.get());
insertScalar("XStep", patternBBox.width());
insertScalar("YStep", patternBBox.height());
- insert("Resources", pattern.getResourceDict());
+ insert("Resources", resourceDict);
insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref();
fState.get()->fImage.unlockPixels();
diff --git a/src/pdf/SkPDFUtils.cpp b/src/pdf/SkPDFUtils.cpp
index 90e2058d24..16abc2f9f2 100644
--- a/src/pdf/SkPDFUtils.cpp
+++ b/src/pdf/SkPDFUtils.cpp
@@ -11,6 +11,7 @@
#include "SkGeometry.h"
#include "SkPaint.h"
#include "SkPath.h"
+#include "SkPDFResourceDict.h"
#include "SkPDFUtils.h"
#include "SkStream.h"
#include "SkString.h"
@@ -206,14 +207,18 @@ void SkPDFUtils::StrokePath(SkWStream* content) {
// static
void SkPDFUtils::DrawFormXObject(int objectIndex, SkWStream* content) {
- content->writeText("/X");
- content->writeDecAsText(objectIndex);
+ content->writeText("/");
+ content->writeText(SkPDFResourceDict::getResourceName(
+ SkPDFResourceDict::kXObject_ResourceType,
+ objectIndex).c_str());
content->writeText(" Do\n");
}
// static
void SkPDFUtils::ApplyGraphicState(int objectIndex, SkWStream* content) {
- content->writeText("/G");
- content->writeDecAsText(objectIndex);
+ content->writeText("/");
+ content->writeText(SkPDFResourceDict::getResourceName(
+ SkPDFResourceDict::kExtGState_ResourceType,
+ objectIndex).c_str());
content->writeText(" gs\n");
}