aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/PDFBench.cpp5
-rw-r--r--src/pdf/SkPDFBitmap.cpp34
-rw-r--r--src/pdf/SkPDFDevice.cpp11
-rw-r--r--src/pdf/SkPDFDevice.h4
-rw-r--r--src/pdf/SkPDFDocument.cpp33
-rw-r--r--src/pdf/SkPDFDocument.h9
-rw-r--r--src/pdf/SkPDFFont.cpp243
-rw-r--r--src/pdf/SkPDFFont.h73
-rw-r--r--src/pdf/SkPDFGraphicState.cpp5
-rw-r--r--src/pdf/SkPDFGraphicState.h3
-rw-r--r--src/pdf/SkPDFMakeToUnicodeCmap.cpp4
-rw-r--r--src/pdf/SkPDFMakeToUnicodeCmap.h4
-rw-r--r--src/pdf/SkPDFMetadata.cpp5
-rw-r--r--src/pdf/SkPDFTypes.cpp120
-rw-r--r--src/pdf/SkPDFTypes.h73
-rwxr-xr-xsrc/utils/SkBitSet.cpp21
-rw-r--r--src/utils/SkBitSet.h18
-rw-r--r--tests/BitSetTest.cpp3
-rw-r--r--tests/PDFGlyphsToUnicodeTest.cpp12
-rw-r--r--tests/PDFPrimitivesTest.cpp48
20 files changed, 222 insertions, 506 deletions
diff --git a/bench/PDFBench.cpp b/bench/PDFBench.cpp
index 5b33e8ca15..1010f74ab5 100644
--- a/bench/PDFBench.cpp
+++ b/bench/PDFBench.cpp
@@ -30,14 +30,13 @@ struct NullWStream : public SkWStream {
static void test_pdf_object_serialization(const sk_sp<SkPDFObject> object) {
// SkDebugWStream wStream;
NullWStream wStream;
- SkPDFSubstituteMap substitutes;
SkPDFObjNumMap objNumMap;
- objNumMap.addObjectRecursively(object.get(), substitutes);
+ objNumMap.addObjectRecursively(object.get());
for (int i = 0; i < objNumMap.objects().count(); ++i) {
SkPDFObject* object = objNumMap.objects()[i].get();
wStream.writeDecAsText(i + 1);
wStream.writeText(" 0 obj\n");
- object->emitObject(&wStream, objNumMap, substitutes);
+ object->emitObject(&wStream, objNumMap);
wStream.writeText("\nendobj\n");
}
}
diff --git a/src/pdf/SkPDFBitmap.cpp b/src/pdf/SkPDFBitmap.cpp
index 772745ca50..2d789d04d8 100644
--- a/src/pdf/SkPDFBitmap.cpp
+++ b/src/pdf/SkPDFBitmap.cpp
@@ -346,8 +346,7 @@ static void emit_image_xobject(SkWStream* stream,
const SkImage* image,
bool alpha,
const sk_sp<SkPDFObject>& smask,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) {
+ const SkPDFObjNumMap& objNumMap) {
SkBitmap bitmap;
image_get_ro_pixels(image, &bitmap); // TODO(halcanary): test
SkAutoLockPixels autoLockPixels(bitmap); // with malformed images.
@@ -385,7 +384,7 @@ static void emit_image_xobject(SkWStream* stream,
pdfDict.insertInt("BitsPerComponent", 8);
pdfDict.insertName("Filter", "FlateDecode");
pdfDict.insertInt("Length", asset->getLength());
- pdfDict.emitObject(stream, objNumMap, substitutes);
+ pdfDict.emitObject(stream, objNumMap);
pdf_stream_begin(stream);
stream->writeStream(asset.get(), asset->getLength());
@@ -400,10 +399,9 @@ class PDFAlphaBitmap final : public SkPDFObject {
public:
PDFAlphaBitmap(sk_sp<SkImage> image) : fImage(std::move(image)) { SkASSERT(fImage); }
void emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& subs) const override {
+ const SkPDFObjNumMap& objNumMap) const override {
SkASSERT(fImage);
- emit_image_xobject(stream, fImage.get(), true, nullptr, objNumMap, subs);
+ emit_image_xobject(stream, fImage.get(), true, nullptr, objNumMap);
}
void drop() override { fImage = nullptr; }
@@ -419,19 +417,12 @@ namespace {
class PDFDefaultBitmap final : public SkPDFObject {
public:
void emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& subs) const override {
+ const SkPDFObjNumMap& objNumMap) const override {
SkASSERT(fImage);
- emit_image_xobject(stream, fImage.get(), false, fSMask, objNumMap, subs);
+ emit_image_xobject(stream, fImage.get(), false, fSMask, objNumMap);
}
- void addResources(SkPDFObjNumMap* catalog,
- const SkPDFSubstituteMap& subs) const override {
- SkASSERT(fImage);
- if (fSMask.get()) {
- SkPDFObject* obj = subs.getSubstitute(fSMask.get());
- SkASSERT(obj);
- catalog->addObjectRecursively(obj, subs);
- }
+ void addResources(SkPDFObjNumMap* catalog) const override {
+ catalog->addObjectRecursively(fSMask.get());
}
void drop() override { fImage = nullptr; fSMask = nullptr; }
PDFDefaultBitmap(sk_sp<SkImage> image, sk_sp<SkPDFObject> smask)
@@ -458,15 +449,12 @@ public:
bool fIsYUV;
PDFJpegBitmap(SkISize size, SkData* data, bool isYUV)
: fSize(size), fData(SkRef(data)), fIsYUV(isYUV) { SkASSERT(data); }
- void emitObject(SkWStream*,
- const SkPDFObjNumMap&,
- const SkPDFSubstituteMap&) const override;
+ void emitObject(SkWStream*, const SkPDFObjNumMap&) const override;
void drop() override { fData = nullptr; }
};
void PDFJpegBitmap::emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substituteMap) const {
+ const SkPDFObjNumMap& objNumMap) const {
SkASSERT(fData);
SkPDFDict pdfDict("XObject");
pdfDict.insertName("Subtype", "Image");
@@ -481,7 +469,7 @@ void PDFJpegBitmap::emitObject(SkWStream* stream,
pdfDict.insertName("Filter", "DCTDecode");
pdfDict.insertInt("ColorTransform", 0);
pdfDict.insertInt("Length", SkToInt(fData->size()));
- pdfDict.emitObject(stream, objNumMap, substituteMap);
+ pdfDict.emitObject(stream, objNumMap);
pdf_stream_begin(stream);
stream->write(fData->data(), fData->size());
pdf_stream_end(stream);
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 290c1c4f56..edf17280ef 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -1153,7 +1153,6 @@ void SkPDFDevice::internalDrawText(
font->multiByteGlyphs(),
defaultPositioning,
offset);
- SkPDFGlyphSetMap* fontGlyphUsage = fDocument->getGlyphUsage();
const SkGlyphID* const glyphsEnd = glyphs + glyphCount;
while (glyphs < glyphsEnd) {
@@ -1184,7 +1183,7 @@ void SkPDFDevice::internalDrawText(
return;
}
}
- fontGlyphUsage->noteGlyphUsage(font, glyphs, stretch);
+ font->noteGlyphUsage(glyphs, stretch);
if (defaultPositioning) {
(void)font->glyphsToPDFFontEncoding(glyphs, SkToInt(glyphsEnd - glyphs));
while (stretch-- > 0) {
@@ -1318,10 +1317,6 @@ sk_sp<SkPDFDict> SkPDFDevice::makeResourceDict() const {
&fonts);
}
-const SkTDArray<SkPDFFont*>& SkPDFDevice::getFontResources() const {
- return fFontResources;
-}
-
sk_sp<SkPDFArray> SkPDFDevice::copyMediaBox() const {
auto mediaBox = sk_make_sp<SkPDFArray>();
mediaBox->reserve(4);
@@ -1948,9 +1943,9 @@ int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) {
}
int resourceIndex = fFontResources.find(newFont.get());
if (resourceIndex < 0) {
+ fDocument->registerFont(newFont.get());
resourceIndex = fFontResources.count();
- fFontResources.push(newFont.get());
- newFont.get()->ref();
+ fFontResources.push(newFont.release());
}
return resourceIndex;
}
diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h
index 364cc61688..4a860281e3 100644
--- a/src/pdf/SkPDFDevice.h
+++ b/src/pdf/SkPDFDevice.h
@@ -126,10 +126,6 @@ public:
/** Create the resource dictionary for this device. */
sk_sp<SkPDFDict> makeResourceDict() const;
- /** Get the fonts used on this device.
- */
- const SkTDArray<SkPDFFont*>& getFontResources() const;
-
/** Add our annotations (link to urls and destinations) to the supplied
* array.
* @param array Array to add annotations to.
diff --git a/src/pdf/SkPDFDocument.cpp b/src/pdf/SkPDFDocument.cpp
index 4f044c8771..75c5de91e3 100644
--- a/src/pdf/SkPDFDocument.cpp
+++ b/src/pdf/SkPDFDocument.cpp
@@ -23,7 +23,7 @@ SkPDFObjectSerializer::~SkPDFObjectSerializer() {
}
void SkPDFObjectSerializer::addObjectRecursively(const sk_sp<SkPDFObject>& object) {
- fObjNumMap.addObjectRecursively(object.get(), fSubstituteMap);
+ fObjNumMap.addObjectRecursively(object.get());
}
#define SKPDF_MAGIC "\xD3\xEB\xE9\xE1"
@@ -58,10 +58,9 @@ void SkPDFObjectSerializer::serializeObjects(SkWStream* wStream) {
// the head of the linked list of free objects."
SkASSERT(fOffsets.count() == fNextToBeSerialized);
fOffsets.push(this->offset(wStream));
- SkASSERT(object == fSubstituteMap.getSubstitute(object));
wStream->writeDecAsText(index);
wStream->writeText(" 0 obj\n"); // Generation number is always 0.
- object->emitObject(wStream, fObjNumMap, fSubstituteMap);
+ object->emitObject(wStream, fObjNumMap);
wStream->writeText("\nendobj\n");
object->drop();
++fNextToBeSerialized;
@@ -93,7 +92,7 @@ void SkPDFObjectSerializer::serializeFooter(SkWStream* wStream,
trailerDict.insertObject("ID", std::move(id));
}
wStream->writeText("trailer\n");
- trailerDict.emitObject(wStream, fObjNumMap, fSubstituteMap);
+ trailerDict.emitObject(wStream, fObjNumMap);
wStream->writeText("\nstartxref\n");
wStream->writeBigDecAsText(xRefFileOffset);
wStream->writeText("\n%%EOF");
@@ -246,11 +245,15 @@ void SkPDFDocument::onEndPage() {
}
void SkPDFDocument::onAbort() {
+ this->reset();
+}
+
+void SkPDFDocument::reset() {
fCanvas.reset(nullptr);
fPages.reset();
fCanon.reset();
renew(&fObjectSerializer);
- renew(&fGlyphUsage);
+ fFonts.reset();
}
#ifdef SK_SUPPORT_LEGACY_DOCUMENT_API
@@ -419,10 +422,7 @@ static sk_sp<SkPDFArray> make_srgb_output_intents() {
bool SkPDFDocument::onClose(SkWStream* stream) {
SkASSERT(!fCanvas.get());
if (fPages.empty()) {
- fPages.reset();
- fCanon.reset();
- renew(&fObjectSerializer);
- renew(&fGlyphUsage);
+ this->reset();
return false;
}
auto docCatalog = sk_make_sp<SkPDFDict>("Catalog");
@@ -442,21 +442,12 @@ bool SkPDFDocument::onClose(SkWStream* stream) {
}
// Build font subsetting info before calling addObjectRecursively().
- for (const auto& entry : fGlyphUsage) {
- sk_sp<SkPDFObject> subsetFont =
- entry.fFont->getFontSubset(&fCanon, &entry.fGlyphSet);
- if (subsetFont) {
- fObjectSerializer.fSubstituteMap.setSubstitute(
- entry.fFont, subsetFont.get());
- }
- }
-
+ SkPDFCanon* canon = &fCanon;
+ fFonts.foreach([canon](SkPDFFont* p){ p->getFontSubset(canon); });
fObjectSerializer.addObjectRecursively(docCatalog);
fObjectSerializer.serializeObjects(this->getStream());
fObjectSerializer.serializeFooter(this->getStream(), docCatalog, fID);
- fCanon.reset();
- renew(&fObjectSerializer);
- renew(&fGlyphUsage);
+ this->reset();
return true;
}
diff --git a/src/pdf/SkPDFDocument.h b/src/pdf/SkPDFDocument.h
index 86562fe42e..5221dd2728 100644
--- a/src/pdf/SkPDFDocument.h
+++ b/src/pdf/SkPDFDocument.h
@@ -25,7 +25,6 @@ sk_sp<SkDocument> SkPDFMakeDocument(SkWStream* stream,
// keep similar functionality together.
struct SkPDFObjectSerializer : SkNoncopyable {
SkPDFObjNumMap fObjNumMap;
- SkPDFSubstituteMap fSubstituteMap;
SkTDArray<int32_t> fOffsets;
sk_sp<SkPDFObject> fInfoDict;
size_t fBaseOffset;
@@ -70,18 +69,16 @@ public:
It might go without saying that objects should not be changed
after calling serialize, since those changes will be too late.
- The same goes for changes to the SkPDFSubstituteMap that effect
- the object or its dependencies.
*/
void serialize(const sk_sp<SkPDFObject>&);
SkPDFCanon* canon() { return &fCanon; }
- SkPDFGlyphSetMap* getGlyphUsage() { return &fGlyphUsage; }
+ void registerFont(SkPDFFont* f) { fFonts.add(f); }
private:
SkPDFObjectSerializer fObjectSerializer;
SkPDFCanon fCanon;
- SkPDFGlyphSetMap fGlyphUsage;
SkTArray<sk_sp<SkPDFDict>> fPages;
+ SkTHashSet<SkPDFFont*> fFonts;
sk_sp<SkPDFDict> fDests;
sk_sp<SkPDFDevice> fPageDevice;
sk_sp<SkCanvas> fCanvas;
@@ -90,6 +87,8 @@ private:
SkScalar fRasterDpi;
SkDocument::PDFMetadata fMetadata;
bool fPDFA;
+
+ void reset();
};
#endif // SkPDFDocument_DEFINED
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp
index 290061a491..887f95001f 100644
--- a/src/pdf/SkPDFFont.cpp
+++ b/src/pdf/SkPDFFont.cpp
@@ -37,50 +37,27 @@ namespace {
// non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1)
static const int kPdfSymbolic = 4;
-class SkPDFType0Font final : public SkPDFFont {
-public:
- SkPDFType0Font(const SkAdvancedTypefaceMetrics& info,
- sk_sp<SkTypeface> typeface,
- SkAdvancedTypefaceMetrics::FontType type);
+struct SkPDFType0Font final : public SkPDFFont {
+ SkPDFType0Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&);
virtual ~SkPDFType0Font();
- sk_sp<SkPDFObject> getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) override;
-#ifdef SK_DEBUG
- void emitObject(SkWStream*,
- const SkPDFObjNumMap&,
- const SkPDFSubstituteMap&) const override;
-#endif
-
-private:
+ void getFontSubset(SkPDFCanon*) override;
#ifdef SK_DEBUG
+ void emitObject(SkWStream*, const SkPDFObjNumMap&) const override;
bool fPopulated;
#endif
- bool populate(const SkPDFGlyphSet* subset,
- const SkAdvancedTypefaceMetrics& metrics);
typedef SkPDFDict INHERITED;
};
-class SkPDFType1Font final : public SkPDFFont {
-public:
- SkPDFType1Font(const SkAdvancedTypefaceMetrics& info,
- sk_sp<SkTypeface> typeface,
- uint16_t glyphID,
- SkPDFCanon* canon);
+struct SkPDFType1Font final : public SkPDFFont {
+ SkPDFType1Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&, SkPDFCanon*);
virtual ~SkPDFType1Font() {}
+ void getFontSubset(SkPDFCanon*) override {} // TODO(halcanary): implement
};
-class SkPDFType3Font final : public SkPDFFont {
-public:
- SkPDFType3Font(const SkAdvancedTypefaceMetrics& info,
- sk_sp<SkTypeface> typeface,
- SkAdvancedTypefaceMetrics::FontType fontType,
- uint16_t glyphID);
+struct SkPDFType3Font final : public SkPDFFont {
+ SkPDFType3Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&);
virtual ~SkPDFType3Font() {}
- void emitObject(SkWStream*,
- const SkPDFObjNumMap&,
- const SkPDFSubstituteMap&) const override {
- SkDEBUGFAIL("should call getFontSubset!");
- }
- sk_sp<SkPDFObject> getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) override;
+ void getFontSubset(SkPDFCanon*) override;
};
///////////////////////////////////////////////////////////////////////////////
@@ -143,58 +120,6 @@ static sk_sp<SkPDFArray> makeFontBBox(SkIRect glyphBBox, uint16_t emSize) {
}
} // namespace
-
-///////////////////////////////////////////////////////////////////////////////
-// class SkPDFGlyphSet
-///////////////////////////////////////////////////////////////////////////////
-
-SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) {
-}
-
-void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) {
- for (int i = 0; i < numGlyphs; ++i) {
- fBitSet.setBit(glyphIDs[i], true);
- }
-}
-
-bool SkPDFGlyphSet::has(uint16_t glyphID) const {
- return fBitSet.isBitSet(glyphID);
-}
-
-void SkPDFGlyphSet::exportTo(SkTDArray<unsigned int>* glyphIDs) const {
- fBitSet.exportTo(glyphIDs);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// class SkPDFGlyphSetMap
-///////////////////////////////////////////////////////////////////////////////
-
-SkPDFGlyphSetMap::SkPDFGlyphSetMap() {}
-
-SkPDFGlyphSetMap::~SkPDFGlyphSetMap() {
- fMap.reset();
-}
-
-void SkPDFGlyphSetMap::noteGlyphUsage(SkPDFFont* font, const uint16_t* glyphIDs,
- int numGlyphs) {
- SkPDFGlyphSet* subset = getGlyphSetForFont(font);
- if (subset) {
- subset->set(glyphIDs, numGlyphs);
- }
-}
-
-SkPDFGlyphSet* SkPDFGlyphSetMap::getGlyphSetForFont(SkPDFFont* font) {
- int index = fMap.count();
- for (int i = 0; i < index; ++i) {
- if (fMap[i].fFont == font) {
- return &fMap[i].fGlyphSet;
- }
- }
- FontGlyphSetPair& pair = fMap.push_back();
- pair.fFont = font;
- return &pair.fGlyphSet;
-}
-
///////////////////////////////////////////////////////////////////////////////
// class SkPDFFont
///////////////////////////////////////////////////////////////////////////////
@@ -322,47 +247,46 @@ SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon,
return nullptr;
}
+ SkGlyphID firstNonZeroGlyph;
+ SkGlyphID lastGlyph;
+ if (multibyte) {
+ firstNonZeroGlyph = 1;
+ lastGlyph = SkToU16(glyphCount - 1);
+ } else {
+ firstNonZeroGlyph = firstGlyph;
+ lastGlyph = SkToU16(SkTMin<int>(glyphCount - 1,
+ 254 + (int)firstGlyph));
+ }
+ SkPDFFont::Info info = {std::move(typeface), firstNonZeroGlyph, lastGlyph, type};
sk_sp<SkPDFFont> font;
switch (type) {
case SkAdvancedTypefaceMetrics::kType1CID_Font:
case SkAdvancedTypefaceMetrics::kTrueType_Font:
SkASSERT(multibyte);
- font = sk_make_sp<SkPDFType0Font>(metrics,
- std::move(typeface),
- type);
+ font = sk_make_sp<SkPDFType0Font>(std::move(info), metrics);
break;
case SkAdvancedTypefaceMetrics::kType1_Font:
SkASSERT(!multibyte);
- font = sk_make_sp<SkPDFType1Font>(metrics,
- std::move(typeface),
- glyphID,
- canon);
+ font = sk_make_sp<SkPDFType1Font>(std::move(info), metrics, canon);
break;
default:
SkASSERT(!multibyte);
// Type3 is our fallback font.
- font = sk_make_sp<SkPDFType3Font>(metrics,
- std::move(typeface),
- type,
- glyphID);
+ font = sk_make_sp<SkPDFType3Font>(std::move(info), metrics);
break;
}
canon->fFontMap.set(fontID, SkRef(font.get()));
return font.release(); // TODO(halcanary) return sk_sp<SkPDFFont>.
}
-sk_sp<SkPDFObject> SkPDFFont::getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) {
- return nullptr; // Default: no support.
-}
-
-SkPDFFont::SkPDFFont(sk_sp<SkTypeface> typeface,
- SkAdvancedTypefaceMetrics::FontType fontType)
+SkPDFFont::SkPDFFont(SkPDFFont::Info info)
: SkPDFDict("Font")
- , fTypeface(std::move(typeface))
- , fFirstGlyphID(1)
- , fFontType(fontType) {
+ , fTypeface(std::move(info.fTypeface))
+ , fGlyphUsage(info.fLastGlyphID + 1) // TODO(halcanary): Adjust mapping?
+ , fFirstGlyphID(info.fFirstGlyphID)
+ , fLastGlyphID(info.fLastGlyphID)
+ , fFontType(info.fFontType) {
SkASSERT(fTypeface);
- fLastGlyphID = SkToU16(fTypeface->countGlyphs() - 1);
}
static void add_common_font_descriptor_entries(SkPDFDict* descriptor,
@@ -388,50 +312,25 @@ static void add_common_font_descriptor_entries(SkPDFDict* descriptor,
}
}
-void SkPDFFont::adjustGlyphRangeForSingleByteEncoding(SkGlyphID glyphID) {
- // Single byte glyph encoding supports a max of 255 glyphs.
- fFirstGlyphID = first_glyph_for_single_byte_encoding(glyphID);
- if (fLastGlyphID > fFirstGlyphID + 255 - 1) {
- fLastGlyphID = fFirstGlyphID + 255 - 1;
- }
-}
-
///////////////////////////////////////////////////////////////////////////////
// class SkPDFType0Font
///////////////////////////////////////////////////////////////////////////////
-SkPDFType0Font::SkPDFType0Font(const SkAdvancedTypefaceMetrics& info,
- sk_sp<SkTypeface> typeface,
- SkAdvancedTypefaceMetrics::FontType fontType)
- : SkPDFFont(std::move(typeface), fontType) {
+SkPDFType0Font::SkPDFType0Font(
+ SkPDFFont::Info info,
+ const SkAdvancedTypefaceMetrics& metrics)
+ : SkPDFFont(std::move(info)) {
SkDEBUGCODE(fPopulated = false);
- if (!can_subset(info)) {
- this->populate(nullptr, info);
- }
}
SkPDFType0Font::~SkPDFType0Font() {}
-sk_sp<SkPDFObject> SkPDFType0Font::getFontSubset(SkPDFCanon* canon,
- const SkPDFGlyphSet* subset) {
- const SkAdvancedTypefaceMetrics* metrics =
- SkPDFFont::GetMetrics(this->typeface(), canon);
- SkASSERT(metrics);
- if (!metrics || !can_subset(*metrics)) {
- return nullptr;
- }
- auto newSubset = sk_make_sp<SkPDFType0Font>(
- *metrics, this->refTypeface(), this->getType());
- newSubset->populate(subset, *metrics);
- return newSubset;
-}
#ifdef SK_DEBUG
void SkPDFType0Font::emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const {
+ const SkPDFObjNumMap& objNumMap) const {
SkASSERT(fPopulated);
- return INHERITED::emitObject(stream, objNumMap, substitutes);
+ return INHERITED::emitObject(stream, objNumMap);
}
#endif
@@ -488,8 +387,12 @@ static sk_sp<SkPDFObject> get_subset_font_stream(
}
#endif // SK_SFNTLY_SUBSETTER
-bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset,
- const SkAdvancedTypefaceMetrics& metrics) {
+void SkPDFType0Font::getFontSubset(SkPDFCanon* canon) {
+ const SkAdvancedTypefaceMetrics* metricsPtr =
+ SkPDFFont::GetMetrics(this->typeface(), canon);
+ SkASSERT(metricsPtr);
+ if (!metricsPtr) { return; }
+ const SkAdvancedTypefaceMetrics& metrics = *metricsPtr;
SkASSERT(can_embed(metrics));
SkAdvancedTypefaceMetrics::FontType type = this->getType();
SkTypeface* face = this->typeface();
@@ -504,24 +407,22 @@ bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset,
std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex));
SkASSERT(fontAsset);
if (!fontAsset) {
- return false;
+ return;
}
size_t fontSize = fontAsset->getLength();
SkASSERT(fontSize > 0);
if (fontSize == 0) {
- return false;
+ return;
}
#ifdef SK_SFNTLY_SUBSETTER
- if (can_subset(metrics) && subset) {
+ if (can_subset(metrics)) {
// Generate glyph id array. in format needed by sfntly
SkTDArray<uint32_t> glyphIDs;
- if (subset) {
- if (!subset->has(0)) {
- glyphIDs.push(0); // Always include glyph 0.
- }
- subset->exportTo(&glyphIDs);
+ if (!this->glyphUsage().has(0)) {
+ glyphIDs.push(0); // Always include glyph 0.
}
+ this->glyphUsage().exportTo(&glyphIDs);
sk_sp<SkPDFObject> subsetStream = get_subset_font_stream(
std::move(fontAsset), glyphIDs, name.c_str());
if (subsetStream) {
@@ -542,7 +443,7 @@ bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset,
SkASSERT(fontData);
SkASSERT(fontData->getLength() > 0);
if (!fontData || 0 == fontData->getLength()) {
- return false;
+ return;
}
auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontData));
fontStream->dict()->insertName("Subtype", "CIDFontType0c");
@@ -574,11 +475,10 @@ bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset,
uint16_t emSize = metrics.fEmSize;
int16_t defaultWidth = 0;
- const SkBitSet* bitSet = subset ? &subset->bitSet() : nullptr;
{
SkAutoGlyphCache glyphCache = vector_cache(face);
sk_sp<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray(
- glyphCache.get(), bitSet, emSize, &defaultWidth);
+ glyphCache.get(), &this->glyphUsage(), emSize, &defaultWidth);
if (widths && widths->size() > 0) {
newCIDFont->insertObject("W", std::move(widths));
}
@@ -598,13 +498,13 @@ bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset,
if (metrics.fGlyphToUnicode.count() > 0) {
this->insertObjRef("ToUnicode",
SkPDFMakeToUnicodeCmap(metrics.fGlyphToUnicode,
- subset,
+ &this->glyphUsage(),
multiByteGlyphs(),
firstGlyphID(),
lastGlyphID()));
}
SkDEBUGCODE(fPopulated = true);
- return true;
+ return;
}
///////////////////////////////////////////////////////////////////////////////
@@ -679,24 +579,22 @@ static void populate_type_1_font(SkPDFDict* font,
font->insertObject("Encoding", std::move(encoding));
}
-SkPDFType1Font::SkPDFType1Font(const SkAdvancedTypefaceMetrics& info,
- sk_sp<SkTypeface> typeface,
- uint16_t glyphID,
+SkPDFType1Font::SkPDFType1Font(SkPDFFont::Info info,
+ const SkAdvancedTypefaceMetrics& metrics,
SkPDFCanon* canon)
- : SkPDFFont(std::move(typeface), SkAdvancedTypefaceMetrics::kType1_Font)
+ : SkPDFFont(std::move(info))
{
SkFontID fontID = this->typeface()->uniqueID();
sk_sp<SkPDFDict> fontDescriptor;
if (SkPDFDict** ptr = canon->fFontDescriptors.find(fontID)) {
fontDescriptor = sk_ref_sp(*ptr);
} else {
- fontDescriptor = make_type1_font_descriptor(this->typeface(), info);
+ fontDescriptor = make_type1_font_descriptor(this->typeface(), metrics);
canon->fFontDescriptors.set(fontID, SkRef(fontDescriptor.get()));
}
this->insertObjRef("FontDescriptor", std::move(fontDescriptor));
- this->adjustGlyphRangeForSingleByteEncoding(glyphID);
// TODO(halcanary): subset this (advances and names).
- populate_type_1_font(this, info, this->typeface(),
+ populate_type_1_font(this, metrics, this->typeface(),
this->firstGlyphID(), this->lastGlyphID());
}
@@ -738,7 +636,7 @@ static void add_type3_font_info(SkPDFCanon* canon,
SkPDFDict* font,
SkTypeface* typeface,
SkScalar emSize,
- const SkPDFGlyphSet* subset,
+ const SkBitSet& subset,
SkGlyphID firstGlyphID,
SkGlyphID lastGlyphID) {
SkASSERT(lastGlyphID >= firstGlyphID);
@@ -770,7 +668,7 @@ static void add_type3_font_info(SkPDFCanon* canon,
sk_sp<SkPDFStream> emptyStream;
for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) {
- bool skipGlyph = subset && gID != 0 && !subset->has(gID);
+ bool skipGlyph = gID != 0 && !subset.has(gID);
SkString characterName;
SkScalar advance = 0.0f;
SkIRect glyphBBox;
@@ -827,7 +725,7 @@ static void add_type3_font_info(SkPDFCanon* canon,
if (metrics /* && metrics->fGlyphToUnicode.count() > 0 */) {
font->insertObjRef("ToUnicode",
SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode,
- subset,
+ &subset,
false,
firstGlyphID,
lastGlyphID));
@@ -837,29 +735,20 @@ static void add_type3_font_info(SkPDFCanon* canon,
font->insertObject("CharProcs", std::move(charProcs));
}
-SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics& info,
- sk_sp<SkTypeface> typeface,
- SkAdvancedTypefaceMetrics::FontType fontType,
- uint16_t glyphID)
- : SkPDFFont(std::move(typeface), fontType) {
- this->adjustGlyphRangeForSingleByteEncoding(glyphID);
-}
+SkPDFType3Font::SkPDFType3Font(SkPDFFont::Info info,
+ const SkAdvancedTypefaceMetrics& metrics)
+ : SkPDFFont(std::move(info)) {}
-sk_sp<SkPDFObject> SkPDFType3Font::getFontSubset(SkPDFCanon* canon,
- const SkPDFGlyphSet* usage) {
- // All fonts are subset before serialization.
- // TODO(halcanary): all fonts should follow this pattern.
+void SkPDFType3Font::getFontSubset(SkPDFCanon* canon) {
const SkAdvancedTypefaceMetrics* info =
SkPDFFont::GetMetrics(this->typeface(), canon);
SkASSERT(info);
uint16_t emSize = info->fEmSize > 0 ? info->fEmSize : 1000;
- auto font = sk_make_sp<SkPDFDict>("Font");
- add_type3_font_info(canon, font.get(), this->typeface(), (SkScalar)emSize, usage,
+ add_type3_font_info(canon, this, this->typeface(), (SkScalar)emSize,
+ this->glyphUsage(),
this->firstGlyphID(), this->lastGlyphID());
- return font;
}
-
////////////////////////////////////////////////////////////////////////////////
bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) {
diff --git a/src/pdf/SkPDFFont.h b/src/pdf/SkPDFFont.h
index f2f1df4c24..abf164c013 100644
--- a/src/pdf/SkPDFFont.h
+++ b/src/pdf/SkPDFFont.h
@@ -18,48 +18,6 @@
class SkPDFCanon;
class SkPDFFont;
-class SkPDFGlyphSet : SkNoncopyable {
-public:
- SkPDFGlyphSet();
- SkPDFGlyphSet(SkPDFGlyphSet&& o) : fBitSet(std::move(o.fBitSet)) {}
-
- void set(const uint16_t* glyphIDs, int numGlyphs);
- bool has(uint16_t glyphID) const;
- void exportTo(SkTDArray<uint32_t>* glyphIDs) const;
- const SkBitSet& bitSet() const { return fBitSet; }
-
-private:
- SkBitSet fBitSet;
-};
-
-class SkPDFGlyphSetMap : SkNoncopyable {
-public:
- struct FontGlyphSetPair : SkNoncopyable {
- FontGlyphSetPair() : fFont(nullptr) {}
- FontGlyphSetPair(FontGlyphSetPair&& o)
- : fFont(o.fFont)
- , fGlyphSet(std::move(o.fGlyphSet)) {
- o.fFont = nullptr;
- }
- SkPDFFont* fFont;
- SkPDFGlyphSet fGlyphSet;
- };
-
- SkPDFGlyphSetMap();
- ~SkPDFGlyphSetMap();
-
- const FontGlyphSetPair* begin() const { return fMap.begin(); }
- const FontGlyphSetPair* end() const { return fMap.end(); }
-
- void noteGlyphUsage(SkPDFFont* font, const uint16_t* glyphIDs,
- int numGlyphs);
-
-private:
- SkPDFGlyphSet* getGlyphSetForFont(SkPDFFont* font);
-
- SkTArray<FontGlyphSetPair> fMap;
-};
-
/** \class SkPDFFont
A PDF Object class representing a font. The font may have resources
attached to it in order to embed the font. SkPDFFonts are canonicalized
@@ -112,6 +70,10 @@ public:
int glyphsToPDFFontEncodingCount(const SkGlyphID* glyphIDs,
int numGlyphs) const;
+ void noteGlyphUsage(const SkGlyphID* glyphs, int count) {
+ fGlyphUsage.setAll(glyphs, count);
+ }
+
/** Get the font resource for the passed typeface and glyphID. The
* reference count of the object is incremented and it is the caller's
* responsibility to unreference it when done. This is needed to
@@ -128,14 +90,10 @@ public:
static const SkAdvancedTypefaceMetrics* GetMetrics(SkTypeface* typeface,
SkPDFCanon* canon);
- /** Subset the font based on usage set. Returns a SkPDFFont instance with
- * subset.
- * @param usage Glyph subset requested.
- * @return nullptr if font does not support subsetting, a new instance
- * of SkPDFFont otherwise.
+ /** Subset the font based on current usage.
+ * Must be called before emitObject().
*/
- virtual sk_sp<SkPDFObject> getFontSubset(SkPDFCanon* canon,
- const SkPDFGlyphSet* usage);
+ virtual void getFontSubset(SkPDFCanon*) = 0;
/**
* Return false iff the typeface has its NotEmbeddable flag set.
@@ -145,23 +103,24 @@ public:
protected:
// Common constructor to handle common members.
- SkPDFFont(sk_sp<SkTypeface> typeface,
- SkAdvancedTypefaceMetrics::FontType fontType);
+ struct Info {
+ sk_sp<SkTypeface> fTypeface;
+ SkGlyphID fFirstGlyphID;
+ SkGlyphID fLastGlyphID;
+ SkAdvancedTypefaceMetrics::FontType fFontType;
+ };
+ SkPDFFont(Info);
SkGlyphID firstGlyphID() const { return fFirstGlyphID; }
SkGlyphID lastGlyphID() const { return fLastGlyphID; }
-
+ const SkBitSet& glyphUsage() const { return fGlyphUsage; }
sk_sp<SkTypeface> refTypeface() const { return fTypeface; }
- /** Set fFirstGlyphID and fLastGlyphID to span at most 255 glyphs,
- * including the passed glyphID.
- */
- void adjustGlyphRangeForSingleByteEncoding(SkGlyphID glyphID);
-
void drop() override;
private:
sk_sp<SkTypeface> fTypeface;
+ SkBitSet fGlyphUsage;
// The glyph IDs accessible with this font. For Type1 (non CID) fonts,
// this will be a subset if the font has more than 255 glyphs.
diff --git a/src/pdf/SkPDFGraphicState.cpp b/src/pdf/SkPDFGraphicState.cpp
index 5a603ce8da..a78c4c51b5 100644
--- a/src/pdf/SkPDFGraphicState.cpp
+++ b/src/pdf/SkPDFGraphicState.cpp
@@ -176,8 +176,7 @@ sk_sp<SkPDFDict> SkPDFGraphicState::MakeNoSmaskGraphicState() {
void SkPDFGraphicState::emitObject(
SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const {
+ const SkPDFObjNumMap& objNumMap) const {
auto dict = sk_make_sp<SkPDFDict>("ExtGState");
dict->insertName("Type", "ExtGState");
@@ -207,5 +206,5 @@ void SkPDFGraphicState::emitObject(
dict->insertScalar("ML", fStrokeMiter);
dict->insertBool("SA", true); // SA = Auto stroke adjustment.
dict->insertName("BM", as_blend_mode(xferMode));
- dict->emitObject(stream, objNumMap, substitutes);
+ dict->emitObject(stream, objNumMap);
}
diff --git a/src/pdf/SkPDFGraphicState.h b/src/pdf/SkPDFGraphicState.h
index 49723bd723..0c2e4a0f49 100644
--- a/src/pdf/SkPDFGraphicState.h
+++ b/src/pdf/SkPDFGraphicState.h
@@ -31,8 +31,7 @@ public:
// Override emitObject so that we can populate the dictionary on
// demand.
void emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const override;
+ const SkPDFObjNumMap& objNumMap) const override;
/** Get the graphic state for the passed SkPaint. The reference count of
* the object is incremented and it is the caller's responsibility to
diff --git a/src/pdf/SkPDFMakeToUnicodeCmap.cpp b/src/pdf/SkPDFMakeToUnicodeCmap.cpp
index 6fd8b1ca16..5186cbbda1 100644
--- a/src/pdf/SkPDFMakeToUnicodeCmap.cpp
+++ b/src/pdf/SkPDFMakeToUnicodeCmap.cpp
@@ -149,7 +149,7 @@ static void append_bfrange_section(const SkTDArray<BFRange>& bfrange,
// one of them), the possible savings by aggressive optimization is 416KB
// pre-compressed and does not provide enough motivation for implementation.
void SkPDFAppendCmapSections(const SkTDArray<SkUnichar>& glyphToUnicode,
- const SkPDFGlyphSet* subset,
+ const SkBitSet* subset,
SkDynamicMemoryWStream* cmap,
bool multiByteGlyphs,
SkGlyphID firstGlyphID,
@@ -212,7 +212,7 @@ void SkPDFAppendCmapSections(const SkTDArray<SkUnichar>& glyphToUnicode,
sk_sp<SkPDFStream> SkPDFMakeToUnicodeCmap(
const SkTDArray<SkUnichar>& glyphToUnicode,
- const SkPDFGlyphSet* subset,
+ const SkBitSet* subset,
bool multiByteGlyphs,
SkGlyphID firstGlyphID,
SkGlyphID lastGlyphID) {
diff --git a/src/pdf/SkPDFMakeToUnicodeCmap.h b/src/pdf/SkPDFMakeToUnicodeCmap.h
index 1bd8930742..0c4d1c37dd 100644
--- a/src/pdf/SkPDFMakeToUnicodeCmap.h
+++ b/src/pdf/SkPDFMakeToUnicodeCmap.h
@@ -13,14 +13,14 @@
sk_sp<SkPDFStream> SkPDFMakeToUnicodeCmap(
const SkTDArray<SkUnichar>& glyphToUnicode,
- const SkPDFGlyphSet* subset,
+ const SkBitSet* subset,
bool multiByteGlyphs,
SkGlyphID firstGlyphID,
SkGlyphID lastGlyphID);
// Exposed for unit testing.
void SkPDFAppendCmapSections(const SkTDArray<SkUnichar>& glyphToUnicode,
- const SkPDFGlyphSet* subset,
+ const SkBitSet* subset,
SkDynamicMemoryWStream* cmap,
bool multiByteGlyphs,
SkGlyphID firstGlyphID,
diff --git a/src/pdf/SkPDFMetadata.cpp b/src/pdf/SkPDFMetadata.cpp
index 259249671f..46fe461be5 100644
--- a/src/pdf/SkPDFMetadata.cpp
+++ b/src/pdf/SkPDFMetadata.cpp
@@ -168,12 +168,11 @@ class PDFXMLObject final : public SkPDFObject {
public:
PDFXMLObject(SkString xml) : fXML(std::move(xml)) {}
void emitObject(SkWStream* stream,
- const SkPDFObjNumMap& omap,
- const SkPDFSubstituteMap& smap) const override {
+ const SkPDFObjNumMap& omap) const override {
SkPDFDict dict("Metadata");
dict.insertName("Subtype", "XML");
dict.insertInt("Length", fXML.size());
- dict.emitObject(stream, omap, smap);
+ dict.emitObject(stream, omap);
static const char streamBegin[] = " stream\n";
stream->write(streamBegin, strlen(streamBegin));
// Do not compress this. The standard requires that a
diff --git a/src/pdf/SkPDFTypes.cpp b/src/pdf/SkPDFTypes.cpp
index 6bf6afc611..838b5efeb9 100644
--- a/src/pdf/SkPDFTypes.cpp
+++ b/src/pdf/SkPDFTypes.cpp
@@ -113,8 +113,7 @@ static void write_name_escaped(SkWStream* o, const char* name) {
}
void SkPDFUnion::emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const {
+ const SkPDFObjNumMap& objNumMap) const {
switch (fType) {
case Type::kInt:
stream->writeDecAsText(fIntValue);
@@ -147,20 +146,18 @@ void SkPDFUnion::emitObject(SkWStream* stream,
pun(fSkString)->size());
return;
case Type::kObjRef:
- stream->writeDecAsText(objNumMap.getObjectNumber(
- substitutes.getSubstitute(fObject)));
+ stream->writeDecAsText(objNumMap.getObjectNumber(fObject));
stream->writeText(" 0 R"); // Generation number is always 0.
return;
case Type::kObject:
- fObject->emitObject(stream, objNumMap, substitutes);
+ fObject->emitObject(stream, objNumMap);
return;
default:
SkDEBUGFAIL("SkPDFUnion::emitObject with bad type");
}
}
-void SkPDFUnion::addResources(SkPDFObjNumMap* objNumMap,
- const SkPDFSubstituteMap& substituteMap) const {
+void SkPDFUnion::addResources(SkPDFObjNumMap* objNumMap) const {
switch (fType) {
case Type::kInt:
case Type::kColorComponent:
@@ -171,13 +168,11 @@ void SkPDFUnion::addResources(SkPDFObjNumMap* objNumMap,
case Type::kNameSkS:
case Type::kStringSkS:
return; // These have no resources.
- case Type::kObjRef: {
- SkPDFObject* obj = substituteMap.getSubstitute(fObject);
- objNumMap->addObjectRecursively(obj, substituteMap);
+ case Type::kObjRef:
+ objNumMap->addObjectRecursively(fObject);
return;
- }
case Type::kObject:
- fObject->addResources(objNumMap, substituteMap);
+ fObject->addResources(objNumMap);
return;
default:
SkDEBUGFAIL("SkPDFUnion::addResources with bad type");
@@ -253,13 +248,11 @@ SkPDFUnion SkPDFUnion::Object(sk_sp<SkPDFObject> objSp) {
#if 0 // Enable if needed.
void SkPDFAtom::emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const {
- fValue.emitObject(stream, objNumMap, substitutes);
+ const SkPDFObjNumMap& objNumMap) const {
+ fValue.emitObject(stream, objNumMap);
}
-void SkPDFAtom::addResources(SkPDFObjNumMap* map,
- const SkPDFSubstituteMap& substitutes) const {
- fValue.addResources(map, substitutes);
+void SkPDFAtom::addResources(SkPDFObjNumMap* map) const {
+ fValue.addResources(map);
}
#endif // 0
@@ -282,12 +275,11 @@ void SkPDFArray::reserve(int length) {
}
void SkPDFArray::emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const {
+ const SkPDFObjNumMap& objNumMap) const {
SkASSERT(!fDumped);
stream->writeText("[");
for (int i = 0; i < fValues.count(); i++) {
- fValues[i].emitObject(stream, objNumMap, substitutes);
+ fValues[i].emitObject(stream, objNumMap);
if (i + 1 < fValues.count()) {
stream->writeText(" ");
}
@@ -295,11 +287,10 @@ void SkPDFArray::emitObject(SkWStream* stream,
stream->writeText("]");
}
-void SkPDFArray::addResources(SkPDFObjNumMap* catalog,
- const SkPDFSubstituteMap& substitutes) const {
+void SkPDFArray::addResources(SkPDFObjNumMap* catalog) const {
SkASSERT(!fDumped);
for (const SkPDFUnion& value : fValues) {
- value.addResources(catalog, substitutes);
+ value.addResources(catalog);
}
}
@@ -364,33 +355,30 @@ SkPDFDict::SkPDFDict(const char type[]) {
}
void SkPDFDict::emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const {
+ const SkPDFObjNumMap& objNumMap) const {
stream->writeText("<<");
- this->emitAll(stream, objNumMap, substitutes);
+ this->emitAll(stream, objNumMap);
stream->writeText(">>");
}
void SkPDFDict::emitAll(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const {
+ const SkPDFObjNumMap& objNumMap) const {
SkASSERT(!fDumped);
for (int i = 0; i < fRecords.count(); i++) {
- fRecords[i].fKey.emitObject(stream, objNumMap, substitutes);
+ fRecords[i].fKey.emitObject(stream, objNumMap);
stream->writeText(" ");
- fRecords[i].fValue.emitObject(stream, objNumMap, substitutes);
+ fRecords[i].fValue.emitObject(stream, objNumMap);
if (i + 1 < fRecords.count()) {
stream->writeText("\n");
}
}
}
-void SkPDFDict::addResources(SkPDFObjNumMap* catalog,
- const SkPDFSubstituteMap& substitutes) const {
+void SkPDFDict::addResources(SkPDFObjNumMap* catalog) const {
SkASSERT(!fDumped);
for (int i = 0; i < fRecords.count(); i++) {
- fRecords[i].fKey.addResources(catalog, substitutes);
- fRecords[i].fValue.addResources(catalog, substitutes);
+ fRecords[i].fKey.addResources(catalog);
+ fRecords[i].fValue.addResources(catalog);
}
}
@@ -463,20 +451,17 @@ void SkPDFSharedStream::drop() {
#ifdef SK_PDF_LESS_COMPRESSION
void SkPDFSharedStream::emitObject(
SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const {
+ const SkPDFObjNumMap& objNumMap) const {
SkASSERT(fAsset);
std::unique_ptr<SkStreamAsset> dup(fAsset->duplicate());
SkASSERT(dup && dup->hasLength());
size_t length = dup->getLength();
stream->writeText("<<");
- fDict.emitAll(stream, objNumMap, substitutes);
+ fDict.emitAll(stream, objNumMap);
stream->writeText("\n");
- SkPDFUnion::Name("Length").emitObject(
- stream, objNumMap, substitutes);
+ SkPDFUnion::Name("Length").emitObject(stream, objNumMap);
stream->writeText(" ");
- SkPDFUnion::Int(length).emitObject(
- stream, objNumMap, substitutes);
+ SkPDFUnion::Int(length).emitObject(stream, objNumMap);
stream->writeText("\n>>stream\n");
SkStreamCopy(stream, dup.get());
stream->writeText("\nendstream");
@@ -484,8 +469,7 @@ void SkPDFSharedStream::emitObject(
#else
void SkPDFSharedStream::emitObject(
SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const {
+ const SkPDFObjNumMap& objNumMap) const {
SkASSERT(fAsset);
SkDynamicMemoryWStream buffer;
SkDeflateWStream deflateWStream(&buffer);
@@ -496,15 +480,15 @@ void SkPDFSharedStream::emitObject(
deflateWStream.finalize();
size_t length = buffer.bytesWritten();
stream->writeText("<<");
- fDict.emitAll(stream, objNumMap, substitutes);
+ fDict.emitAll(stream, objNumMap);
stream->writeText("\n");
- SkPDFUnion::Name("Length").emitObject(stream, objNumMap, substitutes);
+ SkPDFUnion::Name("Length").emitObject(stream, objNumMap);
stream->writeText(" ");
- SkPDFUnion::Int(length).emitObject(stream, objNumMap, substitutes);
+ SkPDFUnion::Int(length).emitObject(stream, objNumMap);
stream->writeText("\n");
- SkPDFUnion::Name("Filter").emitObject(stream, objNumMap, substitutes);
+ SkPDFUnion::Name("Filter").emitObject(stream, objNumMap);
stream->writeText(" ");
- SkPDFUnion::Name("FlateDecode").emitObject(stream, objNumMap, substitutes);
+ SkPDFUnion::Name("FlateDecode").emitObject(stream, objNumMap);
stream->writeText(">>");
stream->writeText(" stream\n");
buffer.writeToStream(stream);
@@ -513,9 +497,9 @@ void SkPDFSharedStream::emitObject(
#endif
void SkPDFSharedStream::addResources(
- SkPDFObjNumMap* catalog, const SkPDFSubstituteMap& substitutes) const {
+ SkPDFObjNumMap* catalog) const {
SkASSERT(fAsset);
- fDict.addResources(catalog, substitutes);
+ fDict.addResources(catalog);
}
@@ -534,10 +518,9 @@ SkPDFStream::SkPDFStream() {}
SkPDFStream::~SkPDFStream() {}
-void SkPDFStream::addResources(
- SkPDFObjNumMap* catalog, const SkPDFSubstituteMap& substitutes) const {
+void SkPDFStream::addResources(SkPDFObjNumMap* catalog) const {
SkASSERT(fCompressedData);
- fDict.addResources(catalog, substitutes);
+ fDict.addResources(catalog);
}
void SkPDFStream::drop() {
@@ -546,10 +529,9 @@ void SkPDFStream::drop() {
}
void SkPDFStream::emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const {
+ const SkPDFObjNumMap& objNumMap) const {
SkASSERT(fCompressedData);
- fDict.emitObject(stream, objNumMap, substitutes);
+ fDict.emitObject(stream, objNumMap);
// duplicate (a cheap operation) preserves const on fCompressedData.
std::unique_ptr<SkStreamAsset> dup(fCompressedData->duplicate());
SkASSERT(dup);
@@ -594,25 +576,6 @@ void SkPDFStream::setData(std::unique_ptr<SkStreamAsset> stream) {
////////////////////////////////////////////////////////////////////////////////
-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;
@@ -622,10 +585,9 @@ bool SkPDFObjNumMap::addObject(SkPDFObject* obj) {
return true;
}
-void SkPDFObjNumMap::addObjectRecursively(SkPDFObject* obj,
- const SkPDFSubstituteMap& subs) {
+void SkPDFObjNumMap::addObjectRecursively(SkPDFObject* obj) {
if (obj && this->addObject(obj)) {
- obj->addResources(this, subs);
+ obj->addResources(this);
}
}
diff --git a/src/pdf/SkPDFTypes.h b/src/pdf/SkPDFTypes.h
index cdfef6cb92..201d62b2ef 100644
--- a/src/pdf/SkPDFTypes.h
+++ b/src/pdf/SkPDFTypes.h
@@ -17,7 +17,6 @@
class SkData;
class SkPDFObjNumMap;
class SkPDFObject;
-class SkPDFSubstituteMap;
class SkStreamAsset;
class SkString;
class SkWStream;
@@ -41,16 +40,14 @@ public:
* @param stream The writable output stream to send the output to.
*/
virtual void emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const = 0;
+ const SkPDFObjNumMap& objNumMap) const = 0;
/**
* Adds all transitive dependencies of this object to the
* catalog. Implementations should respect the catalog's object
* substitution map.
*/
- virtual void addResources(SkPDFObjNumMap* catalog,
- const SkPDFSubstituteMap& substitutes) const {}
+ virtual void addResources(SkPDFObjNumMap* catalog) const {}
/**
* Release all resources associated with this SkPDFObject. It is
@@ -121,10 +118,8 @@ public:
/** These two non-virtual methods mirror SkPDFObject's
corresponding virtuals. */
- void emitObject(SkWStream*,
- const SkPDFObjNumMap&,
- const SkPDFSubstituteMap&) const;
- void addResources(SkPDFObjNumMap*, const SkPDFSubstituteMap&) const;
+ void emitObject(SkWStream*, const SkPDFObjNumMap&) const;
+ void addResources(SkPDFObjNumMap*) const;
bool isName() const;
@@ -171,9 +166,8 @@ static_assert(sizeof(SkString) == sizeof(void*), "SkString_size");
class SkPDFAtom final : public SkPDFObject {
public:
void emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) final;
- void addResources(SkPDFObjNumMap*, const SkPDFSubstituteMap&) const final;
+ const SkPDFObjNumMap& objNumMap) final;
+ void addResources(SkPDFObjNumMap* const final;
SkPDFAtom(SkPDFUnion&& v) : fValue(std::move(v) {}
private:
@@ -197,10 +191,8 @@ public:
// The SkPDFObject interface.
void emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const override;
- void addResources(SkPDFObjNumMap*,
- const SkPDFSubstituteMap&) const override;
+ const SkPDFObjNumMap& objNumMap) const override;
+ void addResources(SkPDFObjNumMap*) const override;
void drop() override;
/** The size of the array.
@@ -247,10 +239,8 @@ public:
// The SkPDFObject interface.
void emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const override;
- void addResources(SkPDFObjNumMap*,
- const SkPDFSubstituteMap&) const override;
+ const SkPDFObjNumMap& objNumMap) const override;
+ void addResources(SkPDFObjNumMap*) const override;
void drop() override;
/** The size of the dictionary.
@@ -282,8 +272,7 @@ public:
/** Emit the dictionary, without the "<<" and ">>".
*/
void emitAll(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const;
+ const SkPDFObjNumMap& objNumMap) const;
private:
struct Record {
@@ -312,10 +301,8 @@ public:
~SkPDFSharedStream();
SkPDFDict* dict() { return &fDict; }
void emitObject(SkWStream*,
- const SkPDFObjNumMap&,
- const SkPDFSubstituteMap&) const override;
- void addResources(SkPDFObjNumMap*,
- const SkPDFSubstituteMap&) const override;
+ const SkPDFObjNumMap&) const override;
+ void addResources(SkPDFObjNumMap*) const override;
void drop() override;
private:
@@ -346,9 +333,8 @@ public:
// The SkPDFObject interface.
void emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const override;
- void addResources(SkPDFObjNumMap*, const SkPDFSubstituteMap&) const final;
+ const SkPDFObjNumMap& objNumMap) const override;
+ void addResources(SkPDFObjNumMap*) const final;
void drop() override;
protected:
@@ -383,9 +369,8 @@ public:
/** Add the passed object to the catalog, as well as all its dependencies.
* @param obj The object to add. If nullptr, this is a noop.
- * @param subs Will be passed to obj->addResources().
*/
- void addObjectRecursively(SkPDFObject* obj, const SkPDFSubstituteMap& subs);
+ void addObjectRecursively(SkPDFObject* obj);
/** Get the object number for the passed object.
* @param obj The object of interest.
@@ -401,32 +386,6 @@ private:
////////////////////////////////////////////////////////////////////////////////
-/** \class SkPDFSubstituteMap
-
- The PDF Substitute Map manages substitute objects and owns the
- substitutes.
-*/
-class SkPDFSubstituteMap : SkNoncopyable {
-public:
- ~SkPDFSubstituteMap();
- /** Set substitute object for the passed object.
- Refs substitute.
- */
- void setSubstitute(SkPDFObject* original, SkPDFObject* substitute);
-
- /** Find and return any substitute object set for the passed object. If
- * there is none, return the passed object.
- */
- SkPDFObject* getSubstitute(SkPDFObject* object) const;
-
- SkPDFObject* operator()(SkPDFObject* o) const {
- return this->getSubstitute(o);
- }
-
-private:
- SkTHashMap<SkPDFObject*, SkPDFObject*> fSubstituteMap;
-};
-
#ifdef SK_PDF_IMAGE_STATS
extern SkAtomic<int> gDrawImageCalls;
extern SkAtomic<int> gJpegImageObjects;
diff --git a/src/utils/SkBitSet.cpp b/src/utils/SkBitSet.cpp
index 0a1ecacf8a..4323ffb6d3 100755
--- a/src/utils/SkBitSet.cpp
+++ b/src/utils/SkBitSet.cpp
@@ -16,11 +16,6 @@ SkBitSet::SkBitSet(int numberOfBits)
fBitData.set(sk_calloc_throw(fDwordCount * sizeof(uint32_t)));
}
-SkBitSet::SkBitSet(const SkBitSet& source)
- : fBitData(nullptr), fDwordCount(0), fBitCount(0) {
- *this = source;
-}
-
SkBitSet::SkBitSet(SkBitSet&& source)
: fBitData(source.fBitData.release())
, fDwordCount(source.fDwordCount)
@@ -29,15 +24,15 @@ SkBitSet::SkBitSet(SkBitSet&& source)
source.fBitCount = 0;
}
-SkBitSet& SkBitSet::operator=(const SkBitSet& rhs) {
- if (this == &rhs) {
- return *this;
+SkBitSet& SkBitSet::operator=(SkBitSet&& rhs) {
+ if (this != &rhs) {
+ fBitCount = rhs.fBitCount;
+ fDwordCount = rhs.fDwordCount;
+ fBitData.reset(); // Free old pointer.
+ fBitData.set(rhs.fBitData.release());
+ rhs.fBitCount = 0;
+ rhs.fDwordCount = 0;
}
- fBitCount = rhs.fBitCount;
- fBitData.reset();
- fDwordCount = rhs.fDwordCount;
- fBitData.set(sk_malloc_throw(fDwordCount * sizeof(uint32_t)));
- memcpy(fBitData.get(), rhs.fBitData.get(), fDwordCount * sizeof(uint32_t));
return *this;
}
diff --git a/src/utils/SkBitSet.h b/src/utils/SkBitSet.h
index 6882752bc0..1e35c9120f 100644
--- a/src/utils/SkBitSet.h
+++ b/src/utils/SkBitSet.h
@@ -17,10 +17,11 @@ public:
/** NumberOfBits must be greater than zero.
*/
explicit SkBitSet(int numberOfBits);
- explicit SkBitSet(const SkBitSet& source);
- explicit SkBitSet(SkBitSet&&);
+ SkBitSet(const SkBitSet&) = delete;
+ SkBitSet(SkBitSet&&);
+ SkBitSet& operator=(const SkBitSet&) = delete;
+ SkBitSet& operator=(SkBitSet&& rhs);
- SkBitSet& operator=(const SkBitSet& rhs);
bool operator==(const SkBitSet& rhs);
bool operator!=(const SkBitSet& rhs);
@@ -39,6 +40,15 @@ public:
*chunk &= ~mask;
}
}
+ void set(int index) { this->setBit(index, true); }
+
+ template<typename T>
+ void setAll(T* array, int len) {
+ static_assert(std::is_integral<T>::value, "T is integral");
+ for (int i = 0; i < len; ++i) {
+ this->set(static_cast<int>(array[i]));
+ }
+ }
/** Test if bit index is set.
*/
@@ -46,6 +56,7 @@ public:
uint32_t mask = 1 << (index & 31);
return SkToBool(*this->internalGet(index) & mask);
}
+ bool has(int index) const { return this->isBitSet(index); }
/** Or bits from source. false is returned if this doesn't have the same
* bit count as source.
@@ -56,6 +67,7 @@ public:
*/
template<typename T>
void exportTo(SkTDArray<T>* array) const {
+ static_assert(std::is_integral<T>::value, "T is integral");
SkASSERT(array);
uint32_t* data = reinterpret_cast<uint32_t*>(fBitData.get());
for (unsigned int i = 0; i < fDwordCount; ++i) {
diff --git a/tests/BitSetTest.cpp b/tests/BitSetTest.cpp
index da023763ba..716f414670 100644
--- a/tests/BitSetTest.cpp
+++ b/tests/BitSetTest.cpp
@@ -70,7 +70,4 @@ DEF_TEST(BitSet, reporter) {
set3.setBit(0, true);
REPORTER_ASSERT(reporter, set2 == set3);
set3.clearAll();
- set3 = set2;
- set2 = set2;
- REPORTER_ASSERT(reporter, set2 == set3);
}
diff --git a/tests/PDFGlyphsToUnicodeTest.cpp b/tests/PDFGlyphsToUnicodeTest.cpp
index b8157caeea..d83ce664bc 100644
--- a/tests/PDFGlyphsToUnicodeTest.cpp
+++ b/tests/PDFGlyphsToUnicodeTest.cpp
@@ -5,12 +5,14 @@
* found in the LICENSE file.
*/
+#include "SkBitSet.h"
#include "SkData.h"
-#include "SkPDFFont.h"
#include "SkPDFMakeToUnicodeCmap.h"
#include "SkStream.h"
#include "Test.h"
+static const int kMaximumGlyphCount = SK_MaxU16 + 1;
+
static bool stream_equals(const SkDynamicMemoryWStream& stream, size_t offset,
const char* buffer, size_t len) {
sk_sp<SkData> data(stream.copyToData());
@@ -26,7 +28,7 @@ static bool stream_equals(const SkDynamicMemoryWStream& stream, size_t offset,
DEF_TEST(ToUnicode, reporter) {
SkTDArray<SkUnichar> glyphToUnicode;
SkTDArray<uint16_t> glyphsInSubset;
- SkPDFGlyphSet subset;
+ SkBitSet subset(kMaximumGlyphCount);
glyphToUnicode.push(0); // 0
glyphToUnicode.push(0); // 1
@@ -65,7 +67,7 @@ DEF_TEST(ToUnicode, reporter) {
glyphToUnicode.push(0x1013);
SkDynamicMemoryWStream buffer;
- subset.set(glyphsInSubset.begin(), glyphsInSubset.count());
+ subset.setAll(glyphsInSubset.begin(), glyphsInSubset.count());
SkPDFAppendCmapSections(glyphToUnicode, &subset, &buffer, true, 0, 0xFFFF);
char expectedResult[] =
@@ -136,7 +138,7 @@ endbfrange\n";
glyphToUnicode.reset();
glyphsInSubset.reset();
- SkPDFGlyphSet subset2;
+ SkBitSet subset2(kMaximumGlyphCount);
// Test mapping:
// I n s t a l
@@ -154,7 +156,7 @@ endbfrange\n";
glyphsInSubset.push(0x57);
SkDynamicMemoryWStream buffer2;
- subset2.set(glyphsInSubset.begin(), glyphsInSubset.count());
+ subset2.setAll(glyphsInSubset.begin(), glyphsInSubset.count());
SkPDFAppendCmapSections(glyphToUnicode, &subset2, &buffer2, true, 0, 0xffff);
char expectedResult2[] =
diff --git a/tests/PDFPrimitivesTest.cpp b/tests/PDFPrimitivesTest.cpp
index 554f1ee720..1faecb516a 100644
--- a/tests/PDFPrimitivesTest.cpp
+++ b/tests/PDFPrimitivesTest.cpp
@@ -31,21 +31,14 @@
#define DUMMY_TEXT "DCT compessed stream."
-namespace {
-struct Catalog {
- SkPDFSubstituteMap substitutes;
- SkPDFObjNumMap numbers;
-};
-} // namespace
-
template <typename T>
-static SkString emit_to_string(T& obj, Catalog* catPtr = nullptr) {
- Catalog catalog;
+static SkString emit_to_string(T& obj, SkPDFObjNumMap* catPtr = nullptr) {
+ SkPDFObjNumMap catalog;
SkDynamicMemoryWStream buffer;
if (!catPtr) {
catPtr = &catalog;
}
- obj.emitObject(&buffer, catPtr->numbers, catPtr->substitutes);
+ obj.emitObject(&buffer, *catPtr);
SkString tmp(buffer.bytesWritten());
buffer.copyTo(tmp.writable_str());
return tmp;
@@ -148,9 +141,9 @@ static void TestObjectRef(skiatest::Reporter* reporter) {
sk_sp<SkPDFArray> a2(new SkPDFArray);
a2->appendObjRef(a1);
- Catalog catalog;
- catalog.numbers.addObject(a1.get());
- REPORTER_ASSERT(reporter, catalog.numbers.getObjectNumber(a1.get()) == 1);
+ SkPDFObjNumMap catalog;
+ catalog.addObject(a1.get());
+ REPORTER_ASSERT(reporter, catalog.getObjectNumber(a1.get()) == 1);
SkString result = emit_to_string(*a2, &catalog);
// If appendObjRef misbehaves, then the result would
@@ -158,22 +151,6 @@ static void TestObjectRef(skiatest::Reporter* reporter) {
assert_eq(reporter, result, "[1 0 R]");
}
-static void TestSubstitute(skiatest::Reporter* reporter) {
- sk_sp<SkPDFDict> proxy(new SkPDFDict());
- sk_sp<SkPDFDict> stub(new SkPDFDict());
-
- proxy->insertInt("Value", 33);
- stub->insertInt("Value", 44);
-
- SkPDFSubstituteMap substituteMap;
- substituteMap.setSubstitute(proxy.get(), stub.get());
- SkPDFObjNumMap catalog;
- catalog.addObject(proxy.get());
-
- REPORTER_ASSERT(reporter, stub.get() == substituteMap.getSubstitute(proxy.get()));
- REPORTER_ASSERT(reporter, proxy.get() != substituteMap.getSubstitute(stub.get()));
-}
-
// This test used to assert without the fix submitted for
// http://code.google.com/p/skia/issues/detail?id=1083.
// SKP files might have invalid glyph ids. This test ensures they are ignored,
@@ -283,9 +260,9 @@ static void TestPDFArray(skiatest::Reporter* reporter) {
"(Another String) [-1]]");
sk_sp<SkPDFArray> referencedArray(new SkPDFArray);
- Catalog catalog;
- catalog.numbers.addObject(referencedArray.get());
- REPORTER_ASSERT(reporter, catalog.numbers.getObjectNumber(
+ SkPDFObjNumMap catalog;
+ catalog.addObject(referencedArray.get());
+ REPORTER_ASSERT(reporter, catalog.getObjectNumber(
referencedArray.get()) == 1);
array->appendObjRef(std::move(referencedArray));
@@ -347,9 +324,9 @@ static void TestPDFDict(skiatest::Reporter* reporter) {
assert_emit_eq(reporter, *dict, "<</Type /DType>>");
sk_sp<SkPDFArray> referencedArray(new SkPDFArray);
- Catalog catalog;
- catalog.numbers.addObject(referencedArray.get());
- REPORTER_ASSERT(reporter, catalog.numbers.getObjectNumber(
+ SkPDFObjNumMap catalog;
+ catalog.addObject(referencedArray.get());
+ REPORTER_ASSERT(reporter, catalog.getObjectNumber(
referencedArray.get()) == 1);
dict->insertObjRef("n1", std::move(referencedArray));
SkString result = emit_to_string(*dict, &catalog);
@@ -363,7 +340,6 @@ DEF_TEST(PDFPrimitives, reporter) {
TestPDFStream(reporter);
TestObjectNumberMap(reporter);
TestObjectRef(reporter);
- TestSubstitute(reporter);
test_issue1083();
}