SkPDF: SkPDFGraphicState Lookup hashtabled

In Release, running `dm --src skp --config pdf`, I get a
speedup of about 1.2%.

SkPDFGraphicState class:
-   Holds the subset of SkPaint that maps to a PDF Graphics
    State
-   These fields are easily comparable, making hashtable
    comparisons easy.

SkPDFCanon:
-   findGraphicState() takes a SkPDFGraphicState, not a SkPaint
-   fGraphicStateRecords is a SkHashSet, not a SkTDArray

SkPDFGraphicState:
-   mode_for_pdf() replaces logic inside equivalent(), but is
    only called once per lookup.
-   emitObject() no longer modifies the SkPDFGraphicState to
    cache the SkPDFDict stucture.  (Since it is de-duped,
    this get no speedup).
-   Static Functions that don't use the canon return a plain
    SkPDFDict now.  No need for fPopulated.

SkTHash.h
-   SkHashSet::forall added

SkPDFDevice; SkPDFShader
-   Updated for new SkPDFGraphicState interface.

BUG=skia:3585

Review URL: https://codereview.chromium.org/1046293002
diff --git a/src/pdf/SkPDFGraphicState.h b/src/pdf/SkPDFGraphicState.h
index 85a324b..dddf439 100644
--- a/src/pdf/SkPDFGraphicState.h
+++ b/src/pdf/SkPDFGraphicState.h
@@ -13,19 +13,17 @@
 #include "SkPaint.h"
 #include "SkPDFTypes.h"
 #include "SkTemplates.h"
+#include "SkChecksum.h"
 
+class SkPDFCanon;
 class SkPDFFormXObject;
 
 /** \class SkPDFGraphicState
     SkPaint objects roughly correspond to graphic state dictionaries that can
     be installed. So that a given dictionary is only output to the pdf file
-    once, we want to canonicalize them. Static methods in this class manage
-    a weakly referenced set of SkPDFGraphicState objects: when the last
-    reference to a SkPDFGraphicState is removed, it removes itself from the
-    static set of objects.
-
+    once, we want to canonicalize them.
 */
-class SkPDFGraphicState : public SkPDFDict {
+class SkPDFGraphicState : public SkPDFObject {
     SK_DECLARE_INST_COUNT(SkPDFGraphicState)
 public:
     enum SkPDFSMaskMode {
@@ -33,8 +31,6 @@
         kLuminosity_SMaskMode
     };
 
-    virtual ~SkPDFGraphicState();
-
     // Override emitObject so that we can populate the dictionary on
     // demand.
     virtual void emitObject(SkWStream* stream,
@@ -57,32 +53,37 @@
      *  @param sMask     The form xobject to use as a soft mask.
      *  @param invert    Indicates if the alpha of the sMask should be inverted.
      *  @param sMaskMode Whether to use alpha or luminosity for the sMask.
+     *
+     *  These are not de-duped.
      */
-    static SkPDFGraphicState* GetSMaskGraphicState(SkPDFFormXObject* sMask,
-                                                   bool invert,
-                                                   SkPDFSMaskMode sMaskMode);
+    static SkPDFDict* GetSMaskGraphicState(SkPDFFormXObject* sMask,
+                                           bool invert,
+                                           SkPDFSMaskMode sMaskMode);
 
     /** Get a graphic state that only unsets the soft mask. The reference
      *  count of the object is incremented and it is the caller's responsibility
      *  to unreference it when done. This is needed to accommodate the weak
      *  reference pattern used when the returned object is new and has no
      *  other references.
+     *
+     *  The returned object is a singleton.
      */
-    static SkPDFGraphicState* GetNoSMaskGraphicState();
+    static SkPDFDict* GetNoSMaskGraphicState();
 
-    bool equals(const SkPaint&) const;
-
-    // Only public for SK_DECLARE_STATIC_LAZY_PTR
-    static SkPDFGraphicState* CreateNoSMaskGraphicState();
+    bool operator==(const SkPDFGraphicState& rhs) const {
+        return 0 == memcmp(&fStrokeWidth, &rhs.fStrokeWidth, 12);
+    }
+    uint32_t hash() const { return SkChecksum::Murmur3(&fStrokeWidth, 12); }
 
 private:
-    const SkPaint fPaint;
-    bool fPopulated;
+    const SkScalar fStrokeWidth;
+    const SkScalar fStrokeMiter;
+    const uint8_t fAlpha;
+    const uint8_t fStrokeCap;   // SkPaint::Cap
+    const uint8_t fStrokeJoin;  // SkPaint::Join
+    const uint8_t fMode;        // SkXfermode::Mode
 
-    SkPDFGraphicState();
-    SkPDFGraphicState(const SkPaint& paint);
-
-    void populateDict();
+    SkPDFGraphicState(const SkPaint&);
 
     typedef SkPDFDict INHERITED;
 };