SkPDF: Factor SkPDFCatalog into SkPDFObjNumMap and SkPDFSubstituteMap
Motivation: Keep separate features separate. Also, future
linearization work will need to have several objNumMap
objects share a substituteMap. Also "catalog" has a
specific meaning in PDF. This catalog did not map to that
catalog.
- Modify SkPDFObject::emitObject and SkPDFObject::addResources
interface to requiore SkPDFObjNumMap and SkPDFSubstituteMap.
- SkPDFObjNumMap const in SkPDFObject::emitObject.
- Remove SkPDFCatalog.cpp/.h
- Modify SkDocument_PDF.cpp to use new functions
- Fold in SkPDFStream::populate
- Fold in SkPDFBitmap::emitDict
- Move SkPDFObjNumMap and SkPDFSubstituteMap to SkPDFTypes.h
- Note (via assert) that SkPDFArray & SkPDFDict don't need to
check substitutes.
- Remove extra space from SkPDFDict serialization.
- SkPDFBitmap SkPDFType0Font SkPDFGraphicState SkPDFStream
updated to new interface.
- PDFPrimitivesTest updated for new interface.
BUG=skia:3585
Review URL: https://codereview.chromium.org/1049753002
diff --git a/src/pdf/SkPDFTypes.cpp b/src/pdf/SkPDFTypes.cpp
index 02c5573..e80d118 100644
--- a/src/pdf/SkPDFTypes.cpp
+++ b/src/pdf/SkPDFTypes.cpp
@@ -7,7 +7,6 @@
*/
-#include "SkPDFCatalog.h"
#include "SkPDFTypes.h"
#include "SkStream.h"
@@ -25,17 +24,20 @@
SkPDFObjRef::~SkPDFObjRef() {}
-void SkPDFObjRef::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
- SkPDFObject* obj = catalog->getSubstituteObject(fObj);
- stream->writeDecAsText(catalog->getObjectNumber(obj));
+void SkPDFObjRef::emitObject(SkWStream* stream,
+ const SkPDFObjNumMap& objNumMap,
+ const SkPDFSubstituteMap& substitutes) {
+ SkPDFObject* obj = substitutes.getSubstitute(fObj);
+ stream->writeDecAsText(objNumMap.getObjectNumber(obj));
stream->writeText(" 0 R"); // Generation number is always 0.
}
-void SkPDFObjRef::addResources(SkPDFCatalog* catalog) const {
- SkPDFObject* obj = catalog->getSubstituteObject(fObj);
+void SkPDFObjRef::addResources(SkPDFObjNumMap* catalog,
+ const SkPDFSubstituteMap& substitutes) const {
+ SkPDFObject* obj = substitutes.getSubstitute(fObj);
SkASSERT(obj);
if (catalog->addObject(obj)) {
- obj->addResources(catalog);
+ obj->addResources(catalog, substitutes);
}
}
@@ -44,7 +46,9 @@
SkPDFInt::SkPDFInt(int32_t value) : fValue(value) {}
SkPDFInt::~SkPDFInt() {}
-void SkPDFInt::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
+void SkPDFInt::emitObject(SkWStream* stream,
+ const SkPDFObjNumMap&,
+ const SkPDFSubstituteMap&) {
stream->writeDecAsText(fValue);
}
@@ -53,12 +57,10 @@
SkPDFBool::SkPDFBool(bool value) : fValue(value) {}
SkPDFBool::~SkPDFBool() {}
-void SkPDFBool::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
- if (fValue) {
- stream->writeText("true");
- } else {
- stream->writeText("false");
- }
+void SkPDFBool::emitObject(SkWStream* stream,
+ const SkPDFObjNumMap&,
+ const SkPDFSubstituteMap&) {
+ stream->writeText(fValue ? "true" : "false");
}
////////////////////////////////////////////////////////////////////////////////
@@ -66,8 +68,10 @@
SkPDFScalar::SkPDFScalar(SkScalar value) : fValue(value) {}
SkPDFScalar::~SkPDFScalar() {}
-void SkPDFScalar::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
- Append(fValue, stream);
+void SkPDFScalar::emitObject(SkWStream* stream,
+ const SkPDFObjNumMap&,
+ const SkPDFSubstituteMap&) {
+ SkPDFScalar::Append(fValue, stream);
}
// static
@@ -135,7 +139,9 @@
SkPDFString::~SkPDFString() {}
-void SkPDFString::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
+void SkPDFString::emitObject(SkWStream* stream,
+ const SkPDFObjNumMap&,
+ const SkPDFSubstituteMap&) {
stream->write(fValue.c_str(), fValue.size());
}
@@ -214,7 +220,9 @@
return fValue == b.fValue;
}
-void SkPDFName::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
+void SkPDFName::emitObject(SkWStream* stream,
+ const SkPDFObjNumMap&,
+ const SkPDFSubstituteMap&) {
stream->write(fValue.c_str(), fValue.size());
}
@@ -245,10 +253,13 @@
fValue.unrefAll();
}
-void SkPDFArray::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
+void SkPDFArray::emitObject(SkWStream* stream,
+ const SkPDFObjNumMap& objNumMap,
+ const SkPDFSubstituteMap& substitutes) {
stream->writeText("[");
for (int i = 0; i < fValue.count(); i++) {
- catalog->getSubstituteObject(fValue[i])->emitObject(stream, catalog);
+ SkASSERT(substitutes.getSubstitute(fValue[i]) == fValue[i]);
+ fValue[i]->emitObject(stream, objNumMap, substitutes);
if (i + 1 < fValue.count()) {
stream->writeText(" ");
}
@@ -256,9 +267,11 @@
stream->writeText("]");
}
-void SkPDFArray::addResources(SkPDFCatalog* catalog) const {
+void SkPDFArray::addResources(SkPDFObjNumMap* catalog,
+ const SkPDFSubstituteMap& substitutes) const {
for (int i = 0; i < fValue.count(); i++) {
- catalog->getSubstituteObject(fValue[i])->addResources(catalog);
+ SkASSERT(substitutes.getSubstitute(fValue[i]) == fValue[i]);
+ fValue[i]->addResources(catalog, substitutes);
}
}
@@ -313,26 +326,33 @@
return fValue.count();
}
-void SkPDFDict::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
+void SkPDFDict::emitObject(SkWStream* stream,
+ const SkPDFObjNumMap& objNumMap,
+ const SkPDFSubstituteMap& substitutes) {
stream->writeText("<<");
for (int i = 0; i < fValue.count(); i++) {
SkASSERT(fValue[i].key);
SkASSERT(fValue[i].value);
- fValue[i].key->emitObject(stream, catalog);
+ SkASSERT(substitutes.getSubstitute(fValue[i].key) == fValue[i].key);
+ SkASSERT(substitutes.getSubstitute(fValue[i].value) == fValue[i].value);
+ fValue[i].key->emitObject(stream, objNumMap, substitutes);
stream->writeText(" ");
- catalog->getSubstituteObject(fValue[i].value)
- ->emitObject(stream, catalog);
- stream->writeText("\n");
+ fValue[i].value->emitObject(stream, objNumMap, substitutes);
+ if (i + 1 < fValue.count()) {
+ stream->writeText("\n");
+ }
}
stream->writeText(">>");
}
-void SkPDFDict::addResources(SkPDFCatalog* catalog) const {
+void SkPDFDict::addResources(SkPDFObjNumMap* catalog,
+ const SkPDFSubstituteMap& substitutes) const {
for (int i = 0; i < fValue.count(); i++) {
SkASSERT(fValue[i].key);
SkASSERT(fValue[i].value);
- fValue[i].key->addResources(catalog);
- catalog->getSubstituteObject(fValue[i].value)->addResources(catalog);
+ fValue[i].key->addResources(catalog, substitutes);
+ SkASSERT(substitutes.getSubstitute(fValue[i].value) == fValue[i].value);
+ fValue[i].value->addResources(catalog, substitutes);
}
}
@@ -394,3 +414,40 @@
Rec(SkRef(other.fValue[i].key), SkRef(other.fValue[i].value));
}
}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SkPDFSubstituteMap::~SkPDFSubstituteMap() {
+ fSubstituteMap.foreach(
+ [](SkPDFObject*, SkPDFObject** v) { (*v)->unref(); });
+}
+
+void SkPDFSubstituteMap::setSubstitute(SkPDFObject* original,
+ SkPDFObject* substitute) {
+ SkASSERT(original != substitute);
+ SkASSERT(!fSubstituteMap.find(original));
+ fSubstituteMap.set(original, SkRef(substitute));
+}
+
+SkPDFObject* SkPDFSubstituteMap::getSubstitute(SkPDFObject* object) const {
+ SkPDFObject** found = fSubstituteMap.find(object);
+ return found ? *found : object;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool SkPDFObjNumMap::addObject(SkPDFObject* obj) {
+ if (fObjectNumbers.find(obj)) {
+ return false;
+ }
+ fObjectNumbers.set(obj, fObjectNumbers.count() + 1);
+ fObjects.push(obj);
+ return true;
+}
+
+int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const {
+ int32_t* objectNumberFound = fObjectNumbers.find(obj);
+ SkASSERT(objectNumberFound);
+ return *objectNumberFound;
+}
+