SkPDF: Glyph Useage Map improvements

Instead of having a fFontGlyphUsage on each device and one on each
document, just have the one on the document, and never merge.

Make fGlyphUsage accesible on SkPDFDocument.

Remove SkPDFGlyphSetMap::merge, ::reset, and SkPDFGlyphSet::merge.

SkPDFGlyphSetMap has an TArray of SkPDFGlyphSet, not TDArray of
SkPDFGlyphSet pointers.  SkPDFGlyphSet and SkPDFBitset get move
constructors.

All tests produce exactly identical output PDFs.

BUG=skia:5434
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2112943002

Review-Url: https://codereview.chromium.org/2112943002
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 204678a..12698dc 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -655,7 +655,6 @@
     , fContentSize(pageSize)
     , fExistingClipRegion(SkIRect::MakeSize(pageSize))
     , fClipStack(nullptr)
-    , fFontGlyphUsage(new SkPDFGlyphSetMap)
     , fRasterDpi(rasterDpi)
     , fDocument(doc) {
     SkASSERT(pageSize.width() > 0);
@@ -675,25 +674,18 @@
 }
 
 SkPDFDevice::~SkPDFDevice() {
-    this->cleanUp(true);
+    this->cleanUp();
 }
 
 void SkPDFDevice::init() {
     fContentEntries.reset();
-    if (fFontGlyphUsage.get() == nullptr) {
-        fFontGlyphUsage.reset(new SkPDFGlyphSetMap);
-    }
 }
 
-void SkPDFDevice::cleanUp(bool clearFontUsage) {
+void SkPDFDevice::cleanUp() {
     fGraphicStateResources.unrefAll();
     fXObjectResources.unrefAll();
     fFontResources.unrefAll();
     fShaderResources.unrefAll();
-
-    if (clearFontUsage) {
-        fFontGlyphUsage->reset();
-    }
 }
 
 void SkPDFDevice::drawAnnotation(const SkDraw& d, const SkRect& rect, const char key[],
@@ -1174,6 +1166,8 @@
 
     SkTDArray<uint16_t> glyphIDsCopy(glyphIDs, numGlyphs);
 
+    SkPDFGlyphSetMap* fontGlyphUsage = fDocument->getGlyphUsage();
+
     while (numGlyphs > consumedGlyphCount) {
         this->updateFont(textPaint, glyphIDs[consumedGlyphCount], content.entry());
         SkPDFFont* font = content.entry()->fState.fFont;
@@ -1181,7 +1175,7 @@
         int availableGlyphs = font->glyphsToPDFFontEncoding(
                 glyphIDsCopy.begin() + consumedGlyphCount,
                 numGlyphs - consumedGlyphCount);
-        fFontGlyphUsage->noteGlyphUsage(
+        fontGlyphUsage->noteGlyphUsage(
                 font,  glyphIDsCopy.begin() + consumedGlyphCount,
                 availableGlyphs);
         write_wide_string(&content.entry()->fContent,
@@ -1243,6 +1237,7 @@
     SkPaint::GlyphCacheProc glyphCacheProc = textPaint.getGlyphCacheProc(true);
     content.entry()->fContent.writeText("BT\n");
     this->updateFont(textPaint, glyphIDs[0], content.entry());
+    SkPDFGlyphSetMap* fontGlyphUsage = fDocument->getGlyphUsage();
     for (size_t i = 0; i < numGlyphs; i++) {
         SkPDFFont* font = content.entry()->fState.fFont;
         uint16_t encodedValue = glyphIDs[i];
@@ -1257,7 +1252,7 @@
             }
         }
 
-        fFontGlyphUsage->noteGlyphUsage(font, &encodedValue, 1);
+        fontGlyphUsage->noteGlyphUsage(font, &encodedValue, 1);
         SkScalar x = offset.x() + pos[i * scalarsPerPos];
         SkScalar y = offset.y() + (2 == scalarsPerPos ? pos[i * scalarsPerPos + 1] : 0);
 
@@ -1325,9 +1320,6 @@
     auto xObject = sk_make_sp<SkPDFFormXObject>(pdfDevice);
     SkPDFUtils::DrawFormXObject(this->addXObjectResource(xObject.get()),
                                 &content.entry()->fContent);
-
-    // Merge glyph sets from the drawn device.
-    fFontGlyphUsage->merge(pdfDevice->getFontGlyphUsage());
 }
 
 SkImageInfo SkPDFDevice::imageInfo() const {
@@ -1558,7 +1550,7 @@
     // We always draw the form xobjects that we create back into the device, so
     // we simply preserve the font usage instead of pulling it out and merging
     // it back in later.
-    cleanUp(false);  // Reset this device to have no content.
+    cleanUp();  // Reset this device to have no content.
     init();
     return xobject;
 }
diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h
index 4dded73..7c7ddf4 100644
--- a/src/pdf/SkPDFDevice.h
+++ b/src/pdf/SkPDFDevice.h
@@ -30,7 +30,6 @@
 class SkPDFDict;
 class SkPDFFont;
 class SkPDFFormXObject;
-class SkPDFGlyphSetMap;
 class SkPDFObject;
 class SkRRect;
 
@@ -159,13 +158,6 @@
         return fInitialTransform;
     }
 
-    /** Returns a SkPDFGlyphSetMap which represents glyph usage of every font
-     *  that shows on this device.
-     */
-    const SkPDFGlyphSetMap& getFontGlyphUsage() const {
-        return *(fFontGlyphUsage.get());
-    }
-
     SkPDFCanon* getCanon() const;
 
     // It is important to not confuse GraphicStateEntry with SkPDFGraphicState, the
@@ -265,9 +257,6 @@
 
     const SkClipStack* fClipStack;
 
-    // Glyph ids used for each font on this device.
-    std::unique_ptr<SkPDFGlyphSetMap> fFontGlyphUsage;
-
     SkScalar fRasterDpi;
 
     SkBitmap fLegacyBitmap;
@@ -283,7 +272,7 @@
     SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;
 
     void init();
-    void cleanUp(bool clearFontUsage);
+    void cleanUp();
     SkPDFFormXObject* createFormXObjectFromDevice();
 
     void drawFormXObjectWithMask(int xObjectIndex,
diff --git a/src/pdf/SkPDFDocument.cpp b/src/pdf/SkPDFDocument.cpp
index c56d1ca..221f240 100644
--- a/src/pdf/SkPDFDocument.cpp
+++ b/src/pdf/SkPDFDocument.cpp
@@ -270,7 +270,6 @@
     fCanvas->flush();
     fCanvas.reset(nullptr);
     SkASSERT(fPageDevice);
-    fGlyphUsage.merge(fPageDevice->getFontGlyphUsage());
     auto page = sk_make_sp<SkPDFDict>("Page");
     page->insertObject("Resources", fPageDevice->makeResourceDict());
     page->insertObject("MediaBox", fPageDevice->copyMediaBox());
@@ -293,6 +292,7 @@
     fPages.reset();
     fCanon.reset();
     renew(&fObjectSerializer);
+    renew(&fGlyphUsage);
 }
 
 #ifdef SK_SUPPORT_LEGACY_DOCUMENT_API
@@ -356,6 +356,7 @@
         fPages.reset();
         fCanon.reset();
         renew(&fObjectSerializer);
+        renew(&fGlyphUsage);
         return false;
     }
     auto docCatalog = sk_make_sp<SkPDFDict>("Catalog");
@@ -377,7 +378,7 @@
     // Build font subsetting info before calling addObjectRecursively().
     for (const auto& entry : fGlyphUsage) {
         sk_sp<SkPDFFont> subsetFont(
-                entry.fFont->getFontSubset(entry.fGlyphSet));
+                entry.fFont->getFontSubset(&entry.fGlyphSet));
         if (subsetFont) {
             fObjectSerializer.fSubstituteMap.setSubstitute(
                     entry.fFont, subsetFont.get());
@@ -389,6 +390,7 @@
     fObjectSerializer.serializeFooter(this->getStream(), docCatalog, fID);
     fCanon.reset();
     renew(&fObjectSerializer);
+    renew(&fGlyphUsage);
     return true;
 }
 
diff --git a/src/pdf/SkPDFDocument.h b/src/pdf/SkPDFDocument.h
index ec4ffd7..86562fe 100644
--- a/src/pdf/SkPDFDocument.h
+++ b/src/pdf/SkPDFDocument.h
@@ -75,6 +75,7 @@
      */
     void serialize(const sk_sp<SkPDFObject>&);
     SkPDFCanon* canon() { return &fCanon; }
+    SkPDFGlyphSetMap* getGlyphUsage() { return &fGlyphUsage; }
 
 private:
     SkPDFObjectSerializer fObjectSerializer;
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp
index bdde6d6..99b6335 100644
--- a/src/pdf/SkPDFFont.cpp
+++ b/src/pdf/SkPDFFont.cpp
@@ -652,41 +652,17 @@
     return fBitSet.isBitSet(glyphID);
 }
 
-void SkPDFGlyphSet::merge(const SkPDFGlyphSet& usage) {
-    fBitSet.orBits(usage.fBitSet);
-}
-
 void SkPDFGlyphSet::exportTo(SkTDArray<unsigned int>* glyphIDs) const {
     fBitSet.exportTo(glyphIDs);
 }
-
+ 
 ///////////////////////////////////////////////////////////////////////////////
 // class SkPDFGlyphSetMap
 ///////////////////////////////////////////////////////////////////////////////
-SkPDFGlyphSetMap::FontGlyphSetPair::FontGlyphSetPair(SkPDFFont* font,
-                                                     SkPDFGlyphSet* glyphSet)
-        : fFont(font),
-          fGlyphSet(glyphSet) {
-}
 
-SkPDFGlyphSetMap::SkPDFGlyphSetMap() {
-}
+SkPDFGlyphSetMap::SkPDFGlyphSetMap() {}
 
 SkPDFGlyphSetMap::~SkPDFGlyphSetMap() {
-    reset();
-}
-
-void SkPDFGlyphSetMap::merge(const SkPDFGlyphSetMap& usage) {
-    for (int i = 0; i < usage.fMap.count(); ++i) {
-        SkPDFGlyphSet* myUsage = getGlyphSetForFont(usage.fMap[i].fFont);
-        myUsage->merge(*(usage.fMap[i].fGlyphSet));
-    }
-}
-
-void SkPDFGlyphSetMap::reset() {
-    for (int i = 0; i < fMap.count(); ++i) {
-        delete fMap[i].fGlyphSet;  // Should not be nullptr.
-    }
     fMap.reset();
 }
 
@@ -702,14 +678,12 @@
     int index = fMap.count();
     for (int i = 0; i < index; ++i) {
         if (fMap[i].fFont == font) {
-            return fMap[i].fGlyphSet;
+            return &fMap[i].fGlyphSet;
         }
     }
-    fMap.append();
-    index = fMap.count() - 1;
-    fMap[index].fFont = font;
-    fMap[index].fGlyphSet = new SkPDFGlyphSet();
-    return fMap[index].fGlyphSet;
+    FontGlyphSetPair& pair = fMap.push_back();
+    pair.fFont = font;
+    return &pair.fGlyphSet;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/pdf/SkPDFFont.h b/src/pdf/SkPDFFont.h
index 79a05a8..0d73745 100644
--- a/src/pdf/SkPDFFont.h
+++ b/src/pdf/SkPDFFont.h
@@ -21,10 +21,10 @@
 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 merge(const SkPDFGlyphSet& usage);
     void exportTo(SkTDArray<uint32_t>* glyphIDs) const;
 
 private:
@@ -33,11 +33,15 @@
 
 class SkPDFGlyphSetMap : SkNoncopyable {
 public:
-    struct FontGlyphSetPair {
-        FontGlyphSetPair(SkPDFFont* font, SkPDFGlyphSet* glyphSet);
-
+    struct FontGlyphSetPair : SkNoncopyable {
+        FontGlyphSetPair() : fFont(nullptr) {}
+        FontGlyphSetPair(FontGlyphSetPair&& o)
+            : fFont(o.fFont)
+            , fGlyphSet(std::move(o.fGlyphSet)) {
+            o.fFont = nullptr;
+        }
         SkPDFFont* fFont;
-        SkPDFGlyphSet* fGlyphSet;
+        SkPDFGlyphSet fGlyphSet;
     };
 
     SkPDFGlyphSetMap();
@@ -46,16 +50,13 @@
     const FontGlyphSetPair* begin() const { return fMap.begin(); }
     const FontGlyphSetPair* end() const { return fMap.end(); }
 
-    void merge(const SkPDFGlyphSetMap& usage);
-    void reset();
-
     void noteGlyphUsage(SkPDFFont* font, const uint16_t* glyphIDs,
                         int numGlyphs);
 
 private:
     SkPDFGlyphSet* getGlyphSetForFont(SkPDFFont* font);
 
-    SkTDArray<FontGlyphSetPair> fMap;
+    SkTArray<FontGlyphSetPair> fMap;
 };
 
 
diff --git a/src/utils/SkBitSet.cpp b/src/utils/SkBitSet.cpp
index 7d03dfc..0a1ecac 100755
--- a/src/utils/SkBitSet.cpp
+++ b/src/utils/SkBitSet.cpp
@@ -21,6 +21,14 @@
     *this = source;
 }
 
+SkBitSet::SkBitSet(SkBitSet&& source)
+    : fBitData(source.fBitData.release())
+    , fDwordCount(source.fDwordCount)
+    , fBitCount(source.fBitCount) {
+    source.fDwordCount = 0;
+    source.fBitCount = 0;
+}
+
 SkBitSet& SkBitSet::operator=(const SkBitSet& rhs) {
     if (this == &rhs) {
         return *this;
diff --git a/src/utils/SkBitSet.h b/src/utils/SkBitSet.h
index 802b9e1..6882752 100644
--- a/src/utils/SkBitSet.h
+++ b/src/utils/SkBitSet.h
@@ -18,6 +18,7 @@
      */
     explicit SkBitSet(int numberOfBits);
     explicit SkBitSet(const SkBitSet& source);
+    explicit SkBitSet(SkBitSet&&);
 
     SkBitSet& operator=(const SkBitSet& rhs);
     bool operator==(const SkBitSet& rhs);