SkPDF: in-place font subsetting

Motivation: gross code simplification, also no bitset lookups at draw time.

SkPDFFont owns its glyph useage bitset.

SkPDFSubstituteMap goes away.

SkPDFObject interface is simplified.

SkPDFDocument tracks font usage (as hash set), not glyph usage.

SkPDFFont gets a simpler constructor.

SkPDFFont has first and last glyph set in constructor, not adjusted later.

SkPDFFont implementations are simplified.

SkPDFGlyphSet is replaced with simple SkBitSet.

SkPDFFont sizes its SkBitSets based on glyph count.

SkPDFGlyphSetMap goes away.

SkBitSet is now non-copyable.

SkBitSet now how utility methods to match old SkPDFGlyphSet.

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2253283004

CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Win-MSVC-GCE-CPU-AVX2-x86_64-Release-GDI-Trybot,Test-Win-MSVC-GCE-CPU-AVX2-x86_64-Debug-GDI-Trybot

Review-Url: https://codereview.chromium.org/2253283004
diff --git a/src/pdf/SkPDFDocument.cpp b/src/pdf/SkPDFDocument.cpp
index 4f044c8..75c5de9 100644
--- a/src/pdf/SkPDFDocument.cpp
+++ b/src/pdf/SkPDFDocument.cpp
@@ -23,7 +23,7 @@
 }
 
 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 @@
         // 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 @@
         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::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 @@
 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 @@
     }
 
     // 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;
 }