SkPDF: unify Canon and Document
motivation: The Document has become intrusive enough that we almost
always have a pointer to the Document on hand anyways.
Also: update document.
Also: forward declare more things in headers.
Also, don't try to clean up resources when abort() or close() is called.
It is easy enough for the client to delete the Document when done.
Change-Id: I21aeed37f26ba16d68af041d9317adf00e9a61f2
Reviewed-on: https://skia-review.googlesource.com/c/180646
Commit-Queue: Hal Canary <halcanary@google.com>
Reviewed-by: Herb Derby <herb@google.com>
diff --git a/gn/pdf.gni b/gn/pdf.gni
index 8e5c759..a75bd04 100644
--- a/gn/pdf.gni
+++ b/gn/pdf.gni
@@ -20,8 +20,6 @@
"$_src/pdf/SkKeyedImage.h",
"$_src/pdf/SkPDFBitmap.cpp",
"$_src/pdf/SkPDFBitmap.h",
- "$_src/pdf/SkPDFCanon.cpp",
- "$_src/pdf/SkPDFCanon.h",
"$_src/pdf/SkPDFConvertType1FontStream.cpp",
"$_src/pdf/SkPDFConvertType1FontStream.h",
"$_src/pdf/SkPDFDevice.cpp",
diff --git a/site/dev/design/pdftheory.md b/site/dev/design/pdftheory.md
index 776adc1..2927d08 100644
--- a/site/dev/design/pdftheory.md
+++ b/site/dev/design/pdftheory.md
@@ -91,7 +91,7 @@
210399 % Byte offset to the start of the table of contents.
%%EOF
-The class SkPDFObjNumMap and the virtual class SkPDFObject are used to
+The the virtual class SkPDFObject are used to
manage the needs of the file format. Any object that will represent a
PDF object must inherit from SkPDFObject and implement the methods to
generate the binary representation and report any other SkPDFObjects
@@ -100,6 +100,10 @@
(A stream is a dictionary containing at least a Length entry followed
by the data of the stream.)
+Streams are now handled in a slightly different way. The SkPDFStreamOut()
+function compresses and serializes the binary data immediately instead of
+creating a new object.
+
All of these PDF object types except the stream type can be used in
both a direct and an indirect fashion, i.e. an array can have an int
or a dictionary as an inline entry, which does not require an object
@@ -128,23 +132,15 @@
...stream contents can be arbitrary, including binary...
endstream`
-The PDF backend requires all indirect objects used in a PDF to be
-added to the SkPDFObjNumMap of the SkPDFDocument. The catalog is
-responsible for assigning object numbers and generating the table of
-contents required at the end of PDF files. In some sense, generating a
-PDF is a three step process. In the first step all the objects and
-references among them are created (mostly done by SkPDFDevice). In the
-second step, SkPDFObjNumMap assigns and remembers object numbers.
-Finally, in the third
-step, the header is printed, each object is printed, and then the
-table of contents and trailer are printed. SkPDFDocument takes care of
-collecting all the objects from the various SkPDFDevice instances,
-adding them to an SkPDFObjNumMap, iterating through the objects once to
-set their file positions, and iterating again to generate the final
-PDF.
+Indirect objects are either:
-As an optimization, many leaf nodes in the direct graph of indirect
-objects can be assigned object numbers and serialized early.
+ - Serialized as soon as they are needed, and a new SkPDFIndirectReference is
+ returned, or
+
+ - Serialized later, but reserve a document-unique SkPDFIndirectReference to
+ allow other objects to refer to it.
+
+Example document:
%PDF-1.4
2 0 obj <<
@@ -232,17 +228,9 @@
There are a number of high level PDF objects (like fonts, graphic
states, etc) that are likely to be referenced multiple times in a
-single PDF. To ensure that there is only one copy of each object
-instance these objects an implemented with an
-[interning pattern](http://en.wikipedia.org/wiki/String_interning).
-As such, the classes representing these objects (like
-SkPDFGraphicState) have private constructors and static methods to
-retrieve an instance of the class.
-
-The SkPDFCanon object owns the interned objects. For obvious reasons,
-the returned instance should not be modified. A mechanism to ensure
-that interned classes are immutable is needed. See [issue
-2683](https://bug.skia.org/2683).
+single PDF. To ensure that there is only one copy of each object,
+the SkPDFDocument holds on to a mapping from type-specific keys onto the
+SkPDFIndirectReference for these objects.
<span id="Graphic_States">Graphic States</span>
-----------------------------------------------
@@ -508,10 +496,6 @@
<span id="Known_issues">Known issues</span>
-------------------------------------------
-* [issue 237](https://bug.skia.org/237)
- SkMaskFilter is not supported.
-* [issue 238](https://bug.skia.org/238)
- SkColorFilter is not supported.
* [issue 249](https://bug.skia.org/249)
SrcAtop Xor, and Plus xfer modes are not supported.
* [issue 240](https://bug.skia.org/240)
diff --git a/src/pdf/SkPDFCanon.cpp b/src/pdf/SkPDFCanon.cpp
deleted file mode 100644
index ec750da..0000000
--- a/src/pdf/SkPDFCanon.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkImage.h"
-#include "SkPDFBitmap.h"
-#include "SkPDFCanon.h"
-#include "SkPDFFont.h"
-
-SkPDFCanon::~SkPDFCanon() {}
-SkPDFCanon::SkPDFCanon() {}
-SkPDFCanon::SkPDFCanon(SkPDFCanon&&) = default;
-SkPDFCanon& SkPDFCanon::operator=(SkPDFCanon&&) = default;
-
-
diff --git a/src/pdf/SkPDFCanon.h b/src/pdf/SkPDFCanon.h
deleted file mode 100644
index 1d93711..0000000
--- a/src/pdf/SkPDFCanon.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef SkPDFCanon_DEFINED
-#define SkPDFCanon_DEFINED
-
-#include <vector>
-
-#include "SkBitmapKey.h"
-#include "SkMacros.h"
-#include "SkPDFGradientShader.h"
-#include "SkPDFGraphicState.h"
-#include "SkPDFShader.h"
-#include "SkString.h"
-#include "SkTHash.h"
-#include "SkTypeface.h"
-
-class SkPDFFont;
-struct SkAdvancedTypefaceMetrics;
-
-/**
- * The SkPDFCanon canonicalizes objects across PDF pages
- * (SkPDFDevices) and across draw calls.
- */
-class SkPDFCanon {
-public:
- ~SkPDFCanon();
- SkPDFCanon();
- SkPDFCanon(SkPDFCanon&&);
- SkPDFCanon(const SkPDFCanon&) = delete;
- SkPDFCanon& operator=(SkPDFCanon&&);
- SkPDFCanon& operator=(const SkPDFCanon&) = delete;
-
- SkTHashMap<SkPDFImageShaderKey, SkPDFIndirectReference> fImageShaderMap;
-
- SkPDFGradientShader::HashMap fGradientPatternMap;
-
- SkTHashMap<SkBitmapKey, SkPDFIndirectReference> fPDFBitmapMap;
-
- SkTHashMap<uint32_t, std::unique_ptr<SkAdvancedTypefaceMetrics>> fTypefaceMetrics;
- SkTHashMap<uint32_t, std::vector<SkString>> fType1GlyphNames;
- SkTHashMap<uint32_t, std::vector<SkUnichar>> fToUnicodeMap;
- SkTHashMap<uint32_t, SkPDFIndirectReference> fFontDescriptors;
- SkTHashMap<uint32_t, SkPDFIndirectReference> fType3FontDescriptors;
- SkTHashMap<uint64_t, SkPDFFont> fFontMap;
-
- SkTHashMap<SkPDFStrokeGraphicState, SkPDFIndirectReference> fStrokeGSMap;
- SkTHashMap<SkPDFFillGraphicState, SkPDFIndirectReference> fFillGSMap;
-
- SkPDFIndirectReference fInvertFunction;
- SkPDFIndirectReference fNoSmaskGraphicState;
-};
-
-#endif // SkPDFCanon_DEFINED
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 709dc18..93670fe 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -25,7 +25,7 @@
#include "SkMakeUnique.h"
#include "SkMaskFilterBase.h"
#include "SkPDFBitmap.h"
-#include "SkPDFCanon.h"
+#include "SkPDFDocument.h"
#include "SkPDFDocumentPriv.h"
#include "SkPDFFont.h"
#include "SkPDFFormXObject.h"
@@ -390,8 +390,6 @@
return new SkPDFDevice(cinfo.fInfo.dimensions(), fDocument);
}
-SkPDFCanon* SkPDFDevice::getCanon() const { return fDocument->canon(); }
-
// A helper class to automatically finish a ContentEntry at the end of a
// drawing method and maintain the state needed between set up and finish.
class ScopedContentEntry {
@@ -787,7 +785,7 @@
void SkPDFDevice::clearMaskOnGraphicState(SkDynamicMemoryWStream* contentStream) {
// The no-softmask graphic state is used to "turn off" the mask for later draw calls.
- SkPDFIndirectReference& noSMaskGS = this->getCanon()->fNoSmaskGraphicState;
+ SkPDFIndirectReference& noSMaskGS = fDocument->fNoSmaskGraphicState;
if (!noSMaskGS) {
SkPDFDict tmp("ExtGState");
tmp.insertName("SMask", "None");
@@ -1093,14 +1091,13 @@
return;
}
- const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, fDocument->canon());
+ const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, fDocument);
if (!metrics) {
return;
}
SkAdvancedTypefaceMetrics::FontType fontType = SkPDFFont::FontType(*metrics);
- const std::vector<SkUnichar>& glyphToUnicode = SkPDFFont::GetUnicodeMap(
- typeface, fDocument->canon());
+ const std::vector<SkUnichar>& glyphToUnicode = SkPDFFont::GetUnicodeMap(typeface, fDocument);
SkClusterator clusterator(glyphRun);
@@ -2017,14 +2014,14 @@
}
SkBitmapKey key = imageSubset.key();
- SkPDFIndirectReference* pdfimagePtr = fDocument->canon()->fPDFBitmapMap.find(key);
+ SkPDFIndirectReference* pdfimagePtr = fDocument->fPDFBitmapMap.find(key);
SkPDFIndirectReference pdfimage = pdfimagePtr ? *pdfimagePtr : SkPDFIndirectReference();
if (!pdfimagePtr) {
SkASSERT(imageSubset);
pdfimage = SkPDFSerializeImage(imageSubset.image().get(), fDocument,
fDocument->metadata().fEncodingQuality);
SkASSERT((key != SkBitmapKey{{0, 0, 0, 0}, 0}));
- fDocument->canon()->fPDFBitmapMap.set(key, pdfimage);
+ fDocument->fPDFBitmapMap.set(key, pdfimage);
}
SkASSERT(pdfimage != SkPDFIndirectReference());
this->drawFormXObject(pdfimage, content.stream());
diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h
index 4aa30a0..8ba8d18 100644
--- a/src/pdf/SkPDFDevice.h
+++ b/src/pdf/SkPDFDevice.h
@@ -26,14 +26,13 @@
class SkGlyphRunList;
class SkKeyedImage;
-class SkPath;
class SkPDFArray;
-class SkPDFCanon;
class SkPDFDevice;
-class SkPDFDocument;
class SkPDFDict;
+class SkPDFDocument;
class SkPDFFont;
class SkPDFObject;
+class SkPath;
class SkRRect;
struct SkPDFIndirectReference;
@@ -50,7 +49,7 @@
* 1 point == 127/360 mm == 1/72 inch
* @param document A non-null pointer back to the
* PDFDocument object. The document is responsible for
- * de-duplicating across pages (via the SkPDFCanon) and
+ * de-duplicating across pages (via the SkPDFDocument) and
* for early serializing of large immutable objects, such
* as images (via SkPDFDocument::serialize()).
* @param initialTransform Transform to be applied to the entire page.
@@ -115,8 +114,6 @@
*/
std::unique_ptr<SkStreamAsset> content();
- SkPDFCanon* getCanon() const;
-
SkISize size() const { return this->imageInfo().dimensions(); }
SkIRect bounds() const { return this->imageInfo().bounds(); }
diff --git a/src/pdf/SkPDFDocument.cpp b/src/pdf/SkPDFDocument.cpp
index 0f1d53e..ea44de1 100644
--- a/src/pdf/SkPDFDocument.cpp
+++ b/src/pdf/SkPDFDocument.cpp
@@ -9,8 +9,12 @@
#include "SkPDFDocumentPriv.h"
#include "SkMakeUnique.h"
-#include "SkPDFCanon.h"
#include "SkPDFDevice.h"
+#include "SkPDFDocument.h"
+#include "SkPDFFont.h"
+#include "SkPDFGradientShader.h"
+#include "SkPDFGraphicState.h"
+#include "SkPDFShader.h"
#include "SkPDFTag.h"
#include "SkPDFUtils.h"
#include "SkStream.h"
@@ -290,22 +294,6 @@
void SkPDFDocument::onAbort() {
this->waitForJobs();
- this->reset();
-}
-
-void SkPDFDocument::reset() {
- reset_object(&fOffsetMap);
- fCanon = SkPDFCanon();
- reset_object(&fCanvas);
- fPages = std::vector<std::unique_ptr<SkPDFDict>>();
- fPageRefs = std::vector<SkPDFIndirectReference>();
- reset_object(&fDests);
- fPageDevice = nullptr;
- fUUID = SkUUID();
- fXMP = SkPDFIndirectReference();
- fMetadata = SkPDF::Metadata();
- fRasterScale = 1;
- fInverseRasterScale = 1;
}
static sk_sp<SkData> SkSrgbIcm() {
@@ -452,7 +440,7 @@
return fTagTree.getMarkIdForNodeId(nodeId, SkToUInt(this->currentPageIndex()));
}
-static std::vector<const SkPDFFont*> get_fonts(const SkPDFCanon& canon) {
+static std::vector<const SkPDFFont*> get_fonts(const SkPDFDocument& canon) {
std::vector<const SkPDFFont*> fonts;
fonts.reserve(canon.fFontMap.count());
// Sort so the output PDF is reproducible.
@@ -467,7 +455,6 @@
SkASSERT(fCanvas.imageInfo().dimensions().isZero());
if (fPages.empty()) {
this->waitForJobs();
- this->reset();
return;
}
auto docCatalog = SkPDFMakeDict("Catalog");
@@ -497,7 +484,7 @@
auto docCatalogRef = this->emit(*docCatalog);
- for (const SkPDFFont* f : get_fonts(fCanon)) {
+ for (const SkPDFFont* f : get_fonts(*this)) {
f->emitSubset(this);
}
@@ -506,7 +493,6 @@
SkAutoMutexAcquire autoMutexAcquire(fMutex);
serialize_footer(fOffsetMap, this->getStream(), fInfoDict, docCatalogRef, fUUID);
}
- this->reset();
}
void SkPDFDocument::incrementJobCount() { fJobCount++; }
diff --git a/src/pdf/SkPDFDocumentPriv.h b/src/pdf/SkPDFDocumentPriv.h
index 8b58aac..4cc8ead 100644
--- a/src/pdf/SkPDFDocumentPriv.h
+++ b/src/pdf/SkPDFDocumentPriv.h
@@ -8,22 +8,33 @@
#define SkPDFDocumentPriv_DEFINED
#include "SkCanvas.h"
-#include "SkPDFCanon.h"
+#include "SkMutex.h"
#include "SkPDFDocument.h"
-#include "SkPDFFont.h"
#include "SkPDFMetadata.h"
#include "SkPDFTag.h"
-#include "SkUUID.h"
+#include "SkTHash.h"
#include <atomic>
+#include <vector>
+#include <memory>
-class SkPDFDevice;
class SkExecutor;
+class SkPDFDevice;
+class SkPDFFont;
+struct SkAdvancedTypefaceMetrics;
+struct SkBitmapKey;
+struct SkPDFFillGraphicState;
+struct SkPDFImageShaderKey;
+struct SkPDFStrokeGraphicState;
+
+namespace SkPDFGradientShader {
+struct Key;
+struct KeyHash;
+}
const char* SkPDFGetNodeIdKey();
-// Logically part of SkPDFDocument (like SkPDFCanon), but separate to
-// keep similar functionality together.
+// Logically part of SkPDFDocument, but separate to keep similar functionality together.
class SkPDFOffsetMap {
public:
void markStartOfDocument(const SkWStream*);
@@ -58,7 +69,6 @@
*/
SkPDFIndirectReference emit(const SkPDFObject&, SkPDFIndirectReference);
SkPDFIndirectReference emit(const SkPDFObject& o) { return this->emit(o, this->reserveRef()); }
- SkPDFCanon* canon() { return &fCanon; }
const SkPDF::Metadata& metadata() const { return fMetadata; }
SkPDFIndirectReference getPage(size_t pageIndex) const;
@@ -75,9 +85,24 @@
size_t currentPageIndex() { return fPages.size(); }
size_t pageCount() { return fPageRefs.size(); }
+ // Canonicalized objects
+ SkTHashMap<SkPDFImageShaderKey, SkPDFIndirectReference> fImageShaderMap;
+ SkTHashMap<SkPDFGradientShader::Key, SkPDFIndirectReference, SkPDFGradientShader::KeyHash>
+ fGradientPatternMap;
+ SkTHashMap<SkBitmapKey, SkPDFIndirectReference> fPDFBitmapMap;
+ SkTHashMap<uint32_t, std::unique_ptr<SkAdvancedTypefaceMetrics>> fTypefaceMetrics;
+ SkTHashMap<uint32_t, std::vector<SkString>> fType1GlyphNames;
+ SkTHashMap<uint32_t, std::vector<SkUnichar>> fToUnicodeMap;
+ SkTHashMap<uint32_t, SkPDFIndirectReference> fFontDescriptors;
+ SkTHashMap<uint32_t, SkPDFIndirectReference> fType3FontDescriptors;
+ SkTHashMap<uint64_t, SkPDFFont> fFontMap;
+ SkTHashMap<SkPDFStrokeGraphicState, SkPDFIndirectReference> fStrokeGSMap;
+ SkTHashMap<SkPDFFillGraphicState, SkPDFIndirectReference> fFillGSMap;
+ SkPDFIndirectReference fInvertFunction;
+ SkPDFIndirectReference fNoSmaskGraphicState;
+
private:
SkPDFOffsetMap fOffsetMap;
- SkPDFCanon fCanon;
SkCanvas fCanvas;
std::vector<std::unique_ptr<SkPDFDict>> fPages;
std::vector<SkPDFIndirectReference> fPageRefs;
@@ -99,7 +124,6 @@
SkMutex fMutex;
SkSemaphore fSemaphore;
- void reset();
void waitForJobs();
};
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp
index 71696d0..46574f0 100644
--- a/src/pdf/SkPDFFont.cpp
+++ b/src/pdf/SkPDFFont.cpp
@@ -14,7 +14,7 @@
#include "SkMacros.h"
#include "SkMakeUnique.h"
#include "SkPDFBitmap.h"
-#include "SkPDFCanon.h"
+#include "SkPDFDocument.h"
#include "SkPDFConvertType1FontStream.h"
#include "SkPDFDevice.h"
#include "SkPDFDocumentPriv.h"
@@ -105,7 +105,7 @@
}
const SkAdvancedTypefaceMetrics* SkPDFFont::GetMetrics(const SkTypeface* typeface,
- SkPDFCanon* canon) {
+ SkPDFDocument* canon) {
SkASSERT(typeface);
SkFontID id = typeface->uniqueID();
if (std::unique_ptr<SkAdvancedTypefaceMetrics>* ptr = canon->fTypefaceMetrics.find(id)) {
@@ -155,7 +155,7 @@
}
const std::vector<SkUnichar>& SkPDFFont::GetUnicodeMap(const SkTypeface* typeface,
- SkPDFCanon* canon) {
+ SkPDFDocument* canon) {
SkASSERT(typeface);
SkASSERT(canon);
SkFontID id = typeface->uniqueID();
@@ -190,10 +190,8 @@
SkTypeface* face,
SkGlyphID glyphID) {
SkASSERT(doc);
- SkPDFCanon* canon = doc->canon();
- SkASSERT(canon);
SkASSERT(face); // All SkPDFDevice::internalDrawText ensures this.
- const SkAdvancedTypefaceMetrics* fontMetrics = SkPDFFont::GetMetrics(face, canon);
+ const SkAdvancedTypefaceMetrics* fontMetrics = SkPDFFont::GetMetrics(face, doc);
SkASSERT(fontMetrics); // SkPDFDevice::internalDrawText ensures the typeface is good.
// GetMetrics only returns null to signify a bad typeface.
const SkAdvancedTypefaceMetrics& metrics = *fontMetrics;
@@ -205,7 +203,7 @@
SkGlyphID subsetCode = multibyte ? 0 : first_nonzero_glyph_for_single_byte_encoding(glyphID);
uint64_t fontID = (static_cast<uint64_t>(SkTypeface::UniqueID(face)) << 16) | subsetCode;
- if (SkPDFFont* found = canon->fFontMap.find(fontID)) {
+ if (SkPDFFont* found = doc->fFontMap.find(fontID)) {
SkASSERT(multibyte == found->multiByteGlyphs());
return found;
}
@@ -226,7 +224,7 @@
lastGlyph = SkToU16(SkTMin<int>((int)lastGlyph, 254 + (int)subsetCode));
}
auto ref = doc->reserveRef();
- return canon->fFontMap.set(
+ return doc->fFontMap.set(
fontID, SkPDFFont(std::move(typeface), firstNonZeroGlyph, lastGlyph, type, ref));
}
@@ -288,9 +286,8 @@
#endif // SK_PDF_SUBSET_SUPPORTED
static void emit_subset_type0(const SkPDFFont& font, SkPDFDocument* doc) {
- SkPDFCanon* canon = doc->canon();
const SkAdvancedTypefaceMetrics* metricsPtr =
- SkPDFFont::GetMetrics(font.typeface(), canon);
+ SkPDFFont::GetMetrics(font.typeface(), doc);
SkASSERT(metricsPtr);
if (!metricsPtr) { return; }
const SkAdvancedTypefaceMetrics& metrics = *metricsPtr;
@@ -402,7 +399,7 @@
fontDict.insertObject("DescendantFonts", std::move(descendantFonts));
const std::vector<SkUnichar>& glyphToUnicode =
- SkPDFFont::GetUnicodeMap(font.typeface(), canon);
+ SkPDFFont::GetUnicodeMap(font.typeface(), doc);
SkASSERT(SkToSizeT(font.typeface()->countGlyphs()) == glyphToUnicode.size());
std::unique_ptr<SkStreamAsset> toUnicode =
SkPDFMakeToUnicodeCmap(glyphToUnicode.data(),
@@ -449,7 +446,7 @@
}
-static const std::vector<SkString>& type_1_glyphnames(SkPDFCanon* canon,
+static const std::vector<SkString>& type_1_glyphnames(SkPDFDocument* canon,
const SkTypeface* typeface) {
SkFontID fontID = typeface->uniqueID();
const std::vector<SkString>* glyphNames = canon->fType1GlyphNames.find(fontID);
@@ -465,26 +462,25 @@
static SkPDFIndirectReference type1_font_descriptor(SkPDFDocument* doc,
const SkTypeface* typeface) {
SkFontID fontID = typeface->uniqueID();
- SkPDFCanon* canon = doc->canon();
- if (SkPDFIndirectReference* ptr = canon->fFontDescriptors.find(fontID)) {
+ if (SkPDFIndirectReference* ptr = doc->fFontDescriptors.find(fontID)) {
return *ptr;
}
- const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, canon);
+ const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc);
auto fontDescriptor = make_type1_font_descriptor(doc, typeface, info);
- canon->fFontDescriptors.set(fontID, fontDescriptor);
+ doc->fFontDescriptors.set(fontID, fontDescriptor);
return fontDescriptor;
}
static void emit_subset_type1(const SkPDFFont& pdfFont, SkPDFDocument* doc) {
SkTypeface* typeface = pdfFont.typeface();
- const std::vector<SkString> glyphNames = type_1_glyphnames(doc->canon(), typeface);
+ const std::vector<SkString> glyphNames = type_1_glyphnames(doc, typeface);
SkGlyphID firstGlyphID = pdfFont.firstGlyphID();
SkGlyphID lastGlyphID = pdfFont.lastGlyphID();
SkPDFDict font("Font");
font.insertRef("FontDescriptor", type1_font_descriptor(doc, typeface));
font.insertName("Subtype", "Type1");
- if (const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc->canon())) {
+ if (const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc)) {
font.insertName("BaseFont", info->fPostScriptName);
}
@@ -609,14 +605,13 @@
static SkPDFIndirectReference type3_descriptor(SkPDFDocument* doc,
const SkTypeface* typeface,
SkGlyphCache* cache) {
- SkPDFCanon* canon = doc->canon();
- if (SkPDFIndirectReference* ptr = canon->fType3FontDescriptors.find(typeface->uniqueID())) {
+ if (SkPDFIndirectReference* ptr = doc->fType3FontDescriptors.find(typeface->uniqueID())) {
return *ptr;
}
SkPDFDict descriptor("FontDescriptor");
int32_t fontDescriptorFlags = kPdfSymbolic;
- if (const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, canon)) {
+ if (const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, doc)) {
// Type3 FontDescriptor does not require all the same fields.
descriptor.insertName("FontName", metrics->fPostScriptName);
descriptor.insertInt("ItalicAngle", metrics->fItalicAngle);
@@ -632,7 +627,7 @@
}
descriptor.insertInt("Flags", fontDescriptorFlags);
SkPDFIndirectReference ref = doc->emit(descriptor);
- canon->fType3FontDescriptors.set(typeface->uniqueID(), ref);
+ doc->fType3FontDescriptors.set(typeface->uniqueID(), ref);
return ref;
}
@@ -642,7 +637,6 @@
SkGlyphID firstGlyphID = pdfFont.firstGlyphID();
SkGlyphID lastGlyphID = pdfFont.lastGlyphID();
const SkPDFGlyphUse& subset = pdfFont.glyphUsage();
- SkPDFCanon* canon = doc->canon();
SkASSERT(lastGlyphID >= firstGlyphID);
// Remove unused glyphs at the end of the range.
// Keep the lastGlyphID >= firstGlyphID invariant true.
@@ -753,7 +747,7 @@
font.insertName("CIDToGIDMap", "Identity");
- const std::vector<SkUnichar>& glyphToUnicode = SkPDFFont::GetUnicodeMap(typeface, canon);
+ const std::vector<SkUnichar>& glyphToUnicode = SkPDFFont::GetUnicodeMap(typeface, doc);
SkASSERT(glyphToUnicode.size() == SkToSizeT(typeface->countGlyphs()));
auto toUnicodeCmap = SkPDFMakeToUnicodeCmap(glyphToUnicode.data(),
&subset,
@@ -785,8 +779,8 @@
////////////////////////////////////////////////////////////////////////////////
-bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) {
- const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, canon);
+bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFDocument* doc) {
+ const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, doc);
return metrics && can_embed(*metrics);
}
diff --git a/src/pdf/SkPDFFont.h b/src/pdf/SkPDFFont.h
index d970c44..2ba20c0 100644
--- a/src/pdf/SkPDFFont.h
+++ b/src/pdf/SkPDFFont.h
@@ -8,7 +8,7 @@
#define SkPDFFont_DEFINED
#include "SkAdvancedTypefaceMetrics.h"
-#include "SkPDFCanon.h"
+#include "SkPDFDocument.h"
#include "SkPDFGlyphUse.h"
#include "SkPDFTypes.h"
#include "SkStrikeCache.h"
@@ -93,10 +93,10 @@
* @return nullptr only when typeface is bad.
*/
static const SkAdvancedTypefaceMetrics* GetMetrics(const SkTypeface* typeface,
- SkPDFCanon* canon);
+ SkPDFDocument* canon);
static const std::vector<SkUnichar>& GetUnicodeMap(const SkTypeface* typeface,
- SkPDFCanon* canon);
+ SkPDFDocument* canon);
void emitSubset(SkPDFDocument*) const;
@@ -104,7 +104,7 @@
* Return false iff the typeface has its NotEmbeddable flag set.
* typeface is not nullptr
*/
- static bool CanEmbedTypeface(SkTypeface*, SkPDFCanon*);
+ static bool CanEmbedTypeface(SkTypeface*, SkPDFDocument*);
SkGlyphID firstGlyphID() const { return fGlyphUsage.firstNonZero(); }
SkGlyphID lastGlyphID() const { return fGlyphUsage.lastGlyph(); }
diff --git a/src/pdf/SkPDFGradientShader.cpp b/src/pdf/SkPDFGradientShader.cpp
index b601a45..92ff8b3 100644
--- a/src/pdf/SkPDFGradientShader.cpp
+++ b/src/pdf/SkPDFGradientShader.cpp
@@ -8,7 +8,7 @@
#include "SkPDFGradientShader.h"
#include "SkOpts.h"
-#include "SkPDFCanon.h"
+#include "SkPDFDocument.h"
#include "SkPDFDocumentPriv.h"
#include "SkPDFFormXObject.h"
#include "SkPDFGraphicState.h"
@@ -896,7 +896,7 @@
SkPDFGradientShader::Key key,
bool keyHasAlpha) {
SkASSERT(gradient_has_alpha(key) == keyHasAlpha);
- auto& gradientPatternMap = doc->canon()->fGradientPatternMap;
+ auto& gradientPatternMap = doc->fGradientPatternMap;
if (SkPDFIndirectReference* ptr = gradientPatternMap.find(key)) {
return *ptr;
}
diff --git a/src/pdf/SkPDFGradientShader.h b/src/pdf/SkPDFGradientShader.h
index 7050e09..bde7fc4 100644
--- a/src/pdf/SkPDFGradientShader.h
+++ b/src/pdf/SkPDFGradientShader.h
@@ -37,8 +37,6 @@
uint32_t operator()(const Key& k) const { return k.fHash; }
};
-using HashMap = SkTHashMap<Key, SkPDFIndirectReference, KeyHash>;
-
inline bool operator==(const SkShader::GradientInfo& u, const SkShader::GradientInfo& v) {
return u.fColorCount == v.fColorCount
&& u.fPoint[0] == v.fPoint[0]
diff --git a/src/pdf/SkPDFGraphicState.cpp b/src/pdf/SkPDFGraphicState.cpp
index dc5b2f0..3426878 100644
--- a/src/pdf/SkPDFGraphicState.cpp
+++ b/src/pdf/SkPDFGraphicState.cpp
@@ -8,7 +8,7 @@
#include "SkPDFGraphicState.h"
#include "SkData.h"
-#include "SkPDFCanon.h"
+#include "SkPDFDocument.h"
#include "SkPDFDocumentPriv.h"
#include "SkPDFFormXObject.h"
#include "SkPDFUtils.h"
@@ -55,11 +55,10 @@
SkPDFIndirectReference SkPDFGraphicState::GetGraphicStateForPaint(SkPDFDocument* doc,
const SkPaint& p) {
- SkPDFCanon* canon = doc->canon();
- SkASSERT(canon);
+ SkASSERT(doc);
if (SkPaint::kFill_Style == p.getStyle()) {
SkPDFFillGraphicState fillKey = {p.getColor4f().fA, pdf_blend_mode(p.getBlendMode())};
- auto& fillMap = canon->fFillGSMap;
+ auto& fillMap = doc->fFillGSMap;
if (SkPDFIndirectReference* statePtr = fillMap.find(fillKey)) {
return *statePtr;
}
@@ -79,7 +78,7 @@
SkToU8(p.getStrokeJoin()),
pdf_blend_mode(p.getBlendMode())
};
- auto& sMap = canon->fStrokeGSMap;
+ auto& sMap = doc->fStrokeGSMap;
if (SkPDFIndirectReference* statePtr = sMap.find(strokeKey)) {
return *statePtr;
}
@@ -121,7 +120,6 @@
SkPDFDocument* doc) {
// The practical chances of using the same mask more than once are unlikely
// enough that it's not worth canonicalizing.
- SkPDFCanon* canon = doc->canon();
auto sMaskDict = SkPDFMakeDict("Mask");
if (sMaskMode == kAlpha_SMaskMode) {
sMaskDict->insertName("S", "Alpha");
@@ -130,11 +128,11 @@
}
sMaskDict->insertRef("G", sMask);
if (invert) {
- // let the canon deduplicate this object.
- if (canon->fInvertFunction == SkPDFIndirectReference()) {
- canon->fInvertFunction = make_invert_function(doc);
+ // let the doc deduplicate this object.
+ if (doc->fInvertFunction == SkPDFIndirectReference()) {
+ doc->fInvertFunction = make_invert_function(doc);
}
- sMaskDict->insertRef("TR", canon->fInvertFunction);
+ sMaskDict->insertRef("TR", doc->fInvertFunction);
}
SkPDFDict result("ExtGState");
result.insertObject("SMask", std::move(sMaskDict));
diff --git a/src/pdf/SkPDFGraphicState.h b/src/pdf/SkPDFGraphicState.h
index 9c22e17..7dcdc43 100644
--- a/src/pdf/SkPDFGraphicState.h
+++ b/src/pdf/SkPDFGraphicState.h
@@ -14,7 +14,7 @@
#include "SkPDFTypes.h"
class SkPaint;
-class SkPDFCanon;
+
/** \class SkPDFGraphicState
SkPaint objects roughly correspond to graphic state dictionaries that can
diff --git a/src/pdf/SkPDFShader.cpp b/src/pdf/SkPDFShader.cpp
index 0f2ac72..5301be7 100644
--- a/src/pdf/SkPDFShader.cpp
+++ b/src/pdf/SkPDFShader.cpp
@@ -9,7 +9,7 @@
#include "SkPDFShader.h"
#include "SkData.h"
-#include "SkPDFCanon.h"
+#include "SkPDFDocument.h"
#include "SkPDFDevice.h"
#include "SkPDFDocumentPriv.h"
#include "SkPDFFormXObject.h"
@@ -350,13 +350,12 @@
SkASSERT(shader->asAGradient(nullptr) == SkShader::kNone_GradientType) ;
if (SkImage* skimg = shader->isAImage(&key.fShaderTransform, key.fImageTileModes)) {
key.fBitmapKey = SkBitmapKeyFromImage(skimg);
- SkPDFCanon* canon = doc->canon();
- SkPDFIndirectReference* shaderPtr = canon->fImageShaderMap.find(key);
+ SkPDFIndirectReference* shaderPtr = doc->fImageShaderMap.find(key);
if (shaderPtr) {
return *shaderPtr;
}
SkPDFIndirectReference pdfShader = make_image_shader(doc, key, skimg);
- canon->fImageShaderMap.set(std::move(key), pdfShader);
+ doc->fImageShaderMap.set(std::move(key), pdfShader);
return pdfShader;
}
// Don't bother to de-dup fallback shader.
diff --git a/src/pdf/SkPDFShader.h b/src/pdf/SkPDFShader.h
index f63b022..3d12686 100644
--- a/src/pdf/SkPDFShader.h
+++ b/src/pdf/SkPDFShader.h
@@ -14,7 +14,7 @@
#include "SkPDFTypes.h"
#include "SkShader.h"
-class SkPDFCanon;
+
class SkPDFDocument;
class SkMatrix;
struct SkIRect;
diff --git a/src/pdf/SkPDFTypes.h b/src/pdf/SkPDFTypes.h
index 79c0fe5..6092a6b 100644
--- a/src/pdf/SkPDFTypes.h
+++ b/src/pdf/SkPDFTypes.h
@@ -23,7 +23,7 @@
class SkData;
class SkPDFArray;
-class SkPDFCanon;
+
class SkPDFDict;
class SkPDFDocument;
class SkPDFObject;
diff --git a/tests/PDFPrimitivesTest.cpp b/tests/PDFPrimitivesTest.cpp
index 143ada2..1f62a48 100644
--- a/tests/PDFPrimitivesTest.cpp
+++ b/tests/PDFPrimitivesTest.cpp
@@ -20,14 +20,12 @@
#include "SkImageFilterPriv.h"
#include "SkMakeUnique.h"
#include "SkMatrix.h"
-#include "SkPDFCanon.h"
#include "SkPDFDevice.h"
-#include "SkPDFDocument.h"
#include "SkPDFDocumentPriv.h"
#include "SkPDFFont.h"
#include "SkPDFTypes.h"
-#include "SkPDFUtils.h"
#include "SkPDFUnion.h"
+#include "SkPDFUtils.h"
#include "SkReadBuffer.h"
#include "SkScalar.h"
#include "SkSpecialImage.h"
@@ -307,18 +305,19 @@
// Check that PDF rendering of image filters successfully falls back to
// CPU rasterization.
DEF_TEST(SkPDF_FontCanEmbedTypeface, reporter) {
- SkPDFCanon canon;
+ SkNullWStream nullWStream;
+ SkPDFDocument doc(&nullWStream, SkPDF::Metadata());
const char resource[] = "fonts/Roboto2-Regular_NoEmbed.ttf";
sk_sp<SkTypeface> noEmbedTypeface(MakeResourceAsTypeface(resource));
if (noEmbedTypeface) {
REPORTER_ASSERT(reporter,
- !SkPDFFont::CanEmbedTypeface(noEmbedTypeface.get(), &canon));
+ !SkPDFFont::CanEmbedTypeface(noEmbedTypeface.get(), &doc));
}
sk_sp<SkTypeface> portableTypeface(
sk_tool_utils::create_portable_typeface(nullptr, SkFontStyle()));
REPORTER_ASSERT(reporter,
- SkPDFFont::CanEmbedTypeface(portableTypeface.get(), &canon));
+ SkPDFFont::CanEmbedTypeface(portableTypeface.get(), &doc));
}