PDF: Now threadsafe!

The PDF canvas is now just as threadsafe as any other Skia canvas.

DM updated to thread PDF tests.

SkDocument_PDF now owns SkPDFCanon, and pointers to that canon are
passed around to all classes that need access to the canon.

BUG=skia:2683

Review URL: https://codereview.chromium.org/944643002
diff --git a/dm/DMSrcSink.h b/dm/DMSrcSink.h
index abf3ef8..8cd92a6 100644
--- a/dm/DMSrcSink.h
+++ b/dm/DMSrcSink.h
@@ -42,8 +42,8 @@
     virtual const char* fileExtension() const  = 0;
 };
 
-enum { kAnyThread_Enclave, kGPU_Enclave, kPDFSink_Enclave };
-static const int kNumEnclaves = kPDFSink_Enclave + 1;
+enum { kAnyThread_Enclave, kGPU_Enclave };
+static const int kNumEnclaves = kGPU_Enclave + 1;
 
 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
@@ -115,7 +115,7 @@
     PDFSink();
 
     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const SK_OVERRIDE;
-    int enclave() const SK_OVERRIDE { return kPDFSink_Enclave; }
+    int enclave() const SK_OVERRIDE { return kAnyThread_Enclave; }
     const char* fileExtension() const SK_OVERRIDE { return "pdf"; }
 };
 
diff --git a/src/doc/SkDocument_PDF.cpp b/src/doc/SkDocument_PDF.cpp
index e73b888..468111c 100644
--- a/src/doc/SkDocument_PDF.cpp
+++ b/src/doc/SkDocument_PDF.cpp
@@ -13,7 +13,7 @@
 class SkDocument_PDF : public SkDocument {
 public:
     SkDocument_PDF(SkWStream* stream,
-                   void (*doneProc)(SkWStream*,bool),
+                   void (*doneProc)(SkWStream*, bool),
                    SkScalar rasterDpi)
         : SkDocument(stream, doneProc)
         , fDoc(SkNEW(SkPDFDocument))
diff --git a/src/pdf/SkPDFBitmap.cpp b/src/pdf/SkPDFBitmap.cpp
index b65709c..f8742a6 100644
--- a/src/pdf/SkPDFBitmap.cpp
+++ b/src/pdf/SkPDFBitmap.cpp
@@ -247,13 +247,12 @@
     pdfDict.emitObject(stream, catalog);
 }
 
-SkPDFBitmap::SkPDFBitmap(const SkBitmap& bm, SkPDFObject* smask)
-    : fBitmap(bm), fSMask(smask) {}
+SkPDFBitmap::SkPDFBitmap(SkPDFCanon* canon,
+                         const SkBitmap& bm,
+                         SkPDFObject* smask)
+    : fCanon(canon), fBitmap(bm), fSMask(smask) {}
 
-SkPDFBitmap::~SkPDFBitmap() {
-    SkAutoMutexAcquire autoMutexAcquire(SkPDFCanon::GetBitmapMutex());
-    SkPDFCanon::GetCanon().removeBitmap(this);
-}
+SkPDFBitmap::~SkPDFBitmap() { fCanon->removeBitmap(this); }
 
 ////////////////////////////////////////////////////////////////////////////////
 static bool is_transparent(const SkBitmap& bm) {
@@ -275,9 +274,10 @@
     return true;
 }
 
-// TODO(halcanary): SkPDFBitmap::Create should take a SkPDFCanon* parameter.
-SkPDFBitmap* SkPDFBitmap::Create(const SkBitmap& bitmap,
+SkPDFBitmap* SkPDFBitmap::Create(SkPDFCanon* canon,
+                                 const SkBitmap& bitmap,
                                  const SkIRect& subset) {
+    SkASSERT(canon);
     if (kN32_SkColorType != bitmap.colorType()) {
         // TODO(halcanary): support other colortypes.
         return NULL;
@@ -299,9 +299,7 @@
         bm = copy;
     }
 
-    SkAutoMutexAcquire autoMutexAcquire(SkPDFCanon::GetBitmapMutex());
-    SkPDFCanon& canon = SkPDFCanon::GetCanon();
-    SkPDFBitmap* pdfBitmap = canon.findBitmap(bm);
+    SkPDFBitmap* pdfBitmap = canon->findBitmap(bm);
     if (pdfBitmap) {
         return SkRef(pdfBitmap);
     }
@@ -314,7 +312,7 @@
         // are refed by the SkPDFBitmap).
         smask = SkNEW_ARGS(PDFAlphaBitmap, (bm));
     }
-    pdfBitmap = SkNEW_ARGS(SkPDFBitmap, (bm, smask));
-    canon.addBitmap(pdfBitmap);
+    pdfBitmap = SkNEW_ARGS(SkPDFBitmap, (canon, bm, smask));
+    canon->addBitmap(pdfBitmap);
     return pdfBitmap;
 }
diff --git a/src/pdf/SkPDFBitmap.h b/src/pdf/SkPDFBitmap.h
index 922db8f..eae6877 100644
--- a/src/pdf/SkPDFBitmap.h
+++ b/src/pdf/SkPDFBitmap.h
@@ -10,6 +10,8 @@
 #include "SkPDFTypes.h"
 #include "SkBitmap.h"
 
+class SkPDFCanon;
+
 /**
  * SkPDFBitmap wraps a SkBitmap and serializes it as an image Xobject.
  * It is designed to use a minimal amout of memory, aside from refing
@@ -24,7 +26,9 @@
     // Returns NULL on unsupported bitmap;
     // TODO(halcanary): support other bitmap colortypes and replace
     // SkPDFImage.
-    static SkPDFBitmap* Create(const SkBitmap&, const SkIRect& subset);
+    static SkPDFBitmap* Create(SkPDFCanon*,
+                               const SkBitmap&,
+                               const SkIRect& subset);
     ~SkPDFBitmap();
     void emitObject(SkWStream*, SkPDFCatalog*) SK_OVERRIDE;
     void addResources(SkTSet<SkPDFObject*>* resourceSet,
@@ -36,9 +40,10 @@
     }
 
 private:
+    SkPDFCanon* const fCanon;
     const SkBitmap fBitmap;
     const SkAutoTUnref<SkPDFObject> fSMask;
-    SkPDFBitmap(const SkBitmap&, SkPDFObject*);
+    SkPDFBitmap(SkPDFCanon*, const SkBitmap&, SkPDFObject*);
     void emitDict(SkWStream*, SkPDFCatalog*, size_t, bool) const;
 };
 
diff --git a/src/pdf/SkPDFCanon.cpp b/src/pdf/SkPDFCanon.cpp
index 268a53a..8bbe835 100644
--- a/src/pdf/SkPDFCanon.cpp
+++ b/src/pdf/SkPDFCanon.cpp
@@ -5,7 +5,6 @@
  * found in the LICENSE file.
  */
 
-#include "SkLazyPtr.h"
 #include "SkPDFBitmap.h"
 #include "SkPDFCanon.h"
 #include "SkPDFFont.h"
@@ -14,32 +13,12 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-SK_DECLARE_STATIC_MUTEX(gSkPDFCanonFontMutex);
-SK_DECLARE_STATIC_MUTEX(gSkPDFCanonShaderMutex);
-SK_DECLARE_STATIC_MUTEX(gSkPDFCanonPaintMutex);
-SK_DECLARE_STATIC_MUTEX(gSkPDFCanonBitmapMutex);
-
-SkBaseMutex& SkPDFCanon::GetFontMutex() { return gSkPDFCanonFontMutex; }
-SkBaseMutex& SkPDFCanon::GetShaderMutex() { return gSkPDFCanonShaderMutex; }
-SkBaseMutex& SkPDFCanon::GetPaintMutex() { return gSkPDFCanonPaintMutex; }
-SkBaseMutex& SkPDFCanon::GetBitmapMutex() { return gSkPDFCanonBitmapMutex; }
-
 SkPDFCanon::SkPDFCanon() {}
 
 SkPDFCanon::~SkPDFCanon() {}
 
-SK_DECLARE_STATIC_LAZY_PTR(SkPDFCanon, singleton);
-
-SkPDFCanon& SkPDFCanon::GetCanon() { return *singleton.get(); }
-
 ////////////////////////////////////////////////////////////////////////////////
 
-static void assert_mutex_held(const SkPDFCanon* canon, SkBaseMutex& mutex) {
-    if (canon == singleton.get()) {
-        mutex.assertHeld();
-    }
-}
-
 template <class T> T* assert_ptr(T* p) { SkASSERT(p); return p; }
 
 template <typename T>
@@ -68,7 +47,6 @@
 SkPDFFont* SkPDFCanon::findFont(uint32_t fontID,
                                 uint16_t glyphID,
                                 SkPDFFont** relatedFontPtr) const {
-    assert_mutex_held(this, gSkPDFCanonFontMutex);
     SkASSERT(relatedFontPtr);
 
     SkPDFFont* relatedFont = NULL;
@@ -87,7 +65,6 @@
 }
 
 void SkPDFCanon::addFont(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID) {
-    assert_mutex_held(this, gSkPDFCanonFontMutex);
     SkPDFCanon::FontRec* rec = fFontRecords.push();
     rec->fFont = font;
     rec->fFontID = fontID;
@@ -95,7 +72,6 @@
 }
 
 void SkPDFCanon::removeFont(SkPDFFont* pdfFont) {
-    assert_mutex_held(this, gSkPDFCanonFontMutex);
     for (int i = 0; i < fFontRecords.count(); i++) {
         if (fFontRecords[i].fFont == pdfFont) {
             fFontRecords.removeShuffle(i);
@@ -109,15 +85,12 @@
 
 SkPDFFunctionShader* SkPDFCanon::findFunctionShader(
         const SkPDFShader::State& state) const {
-    assert_mutex_held(this, gSkPDFCanonShaderMutex);
     return find_item(fFunctionShaderRecords, state);
 }
 void SkPDFCanon::addFunctionShader(SkPDFFunctionShader* pdfShader) {
-    assert_mutex_held(this, gSkPDFCanonShaderMutex);
     fFunctionShaderRecords.push(assert_ptr(pdfShader));
 }
 void SkPDFCanon::removeFunctionShader(SkPDFFunctionShader* pdfShader) {
-    assert_mutex_held(this, gSkPDFCanonShaderMutex);
     SkAssertResult(remove_item(&fFunctionShaderRecords, pdfShader));
 }
 
@@ -125,15 +98,12 @@
 
 SkPDFAlphaFunctionShader* SkPDFCanon::findAlphaShader(
         const SkPDFShader::State& state) const {
-    assert_mutex_held(this, gSkPDFCanonShaderMutex);
     return find_item(fAlphaShaderRecords, state);
 }
 void SkPDFCanon::addAlphaShader(SkPDFAlphaFunctionShader* pdfShader) {
-    assert_mutex_held(this, gSkPDFCanonShaderMutex);
     fAlphaShaderRecords.push(assert_ptr(pdfShader));
 }
 void SkPDFCanon::removeAlphaShader(SkPDFAlphaFunctionShader* pdfShader) {
-    assert_mutex_held(this, gSkPDFCanonShaderMutex);
     SkAssertResult(remove_item(&fAlphaShaderRecords, pdfShader));
 }
 
@@ -141,50 +111,41 @@
 
 SkPDFImageShader* SkPDFCanon::findImageShader(
         const SkPDFShader::State& state) const {
-    assert_mutex_held(this, gSkPDFCanonShaderMutex);
     return find_item(fImageShaderRecords, state);
 }
 
 void SkPDFCanon::addImageShader(SkPDFImageShader* pdfShader) {
-    assert_mutex_held(this, gSkPDFCanonShaderMutex);
     fImageShaderRecords.push(assert_ptr(pdfShader));
 }
 
 void SkPDFCanon::removeImageShader(SkPDFImageShader* pdfShader) {
-    assert_mutex_held(this, gSkPDFCanonShaderMutex);
     SkAssertResult(remove_item(&fImageShaderRecords, pdfShader));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 SkPDFGraphicState* SkPDFCanon::findGraphicState(const SkPaint& paint) const {
-    assert_mutex_held(this, gSkPDFCanonPaintMutex);
     return find_item(fGraphicStateRecords, paint);
 }
 
 void SkPDFCanon::addGraphicState(SkPDFGraphicState* state) {
-    assert_mutex_held(this, gSkPDFCanonPaintMutex);
     fGraphicStateRecords.push(assert_ptr(state));
 }
 
 void SkPDFCanon::removeGraphicState(SkPDFGraphicState* pdfGraphicState) {
-    assert_mutex_held(this, gSkPDFCanonPaintMutex);
     SkAssertResult(remove_item(&fGraphicStateRecords, pdfGraphicState));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 SkPDFBitmap* SkPDFCanon::findBitmap(const SkBitmap& bm) const {
-    assert_mutex_held(this, gSkPDFCanonBitmapMutex);
     return find_item(fBitmapRecords, bm);
 }
 
 void SkPDFCanon::addBitmap(SkPDFBitmap* pdfBitmap) {
-    assert_mutex_held(this, gSkPDFCanonBitmapMutex);
     fBitmapRecords.push(assert_ptr(pdfBitmap));
 }
 
 void SkPDFCanon::removeBitmap(SkPDFBitmap* pdfBitmap) {
-    assert_mutex_held(this, gSkPDFCanonBitmapMutex);
     SkAssertResult(remove_item(&fBitmapRecords, pdfBitmap));
 }
diff --git a/src/pdf/SkPDFCanon.h b/src/pdf/SkPDFCanon.h
index 7c5cdf7..369106a 100644
--- a/src/pdf/SkPDFCanon.h
+++ b/src/pdf/SkPDFCanon.h
@@ -8,42 +8,33 @@
 #define SkPDFCanon_DEFINED
 
 #include "SkPDFShader.h"
-#include "SkThread.h"
 #include "SkTDArray.h"
 
-struct SkIRect;
 class SkBitmap;
-class SkMatrix;
 class SkPDFFont;
 class SkPDFGraphicState;
 class SkPDFBitmap;
 class SkPaint;
 
-// This class's fields and methods will eventually become part of
-// SkPDFDocument/SkDocument_PDF.  For now, it exists as a singleton to
-// preflight that transition.  This replaces three global arrays in
-// SkPDFFont, SkPDFShader, and SkPDFGraphicsContext.
-//
-// IF YOU ARE LOOKING AT THIS API PLEASE DO NOT WRITE THE CHANGE
-// YOU ARE ABOUT TO WRITE WITHOUT TALKING TO HALCANARY@.
-//
-// Note that this class does not create, delete, reference or
-// dereference the SkPDFObject objects that it indexes.  It is up to
-// the caller to manage the lifetime of these objects.
+/**
+ *  The SkPDFCanon canonicalizes objects across PDF pages(SkPDFDevices).
+ *
+ *  The PDF backend works correctly if:
+ *  -  There is no more than one SkPDFCanon for each thread.
+ *  -  Every SkPDFDevice is given a pointer to a SkPDFCanon on creation.
+ *  -  All SkPDFDevices in a document share the same SkPDFCanon.
+ *  The SkDocument_PDF class makes this happen by owning a single
+ *  SkPDFCanon.
+ *
+ *  Note that this class does not create, delete, reference or
+ *  dereference the SkPDFObject objects that it indexes.  It is up to
+ *  the caller to manage the lifetime of these objects.
+ */
 class SkPDFCanon : SkNoncopyable {
 public:
     SkPDFCanon();
     ~SkPDFCanon();
 
-    static SkPDFCanon& GetCanon();
-
-    // This mutexes will be removed once this class is subsumed into
-    // SkPDFDocument.
-    static SkBaseMutex& GetFontMutex();
-    static SkBaseMutex& GetShaderMutex();
-    static SkBaseMutex& GetPaintMutex();
-    static SkBaseMutex& GetBitmapMutex();
-
     // Returns exact match if there is one.  If not, it returns NULL.
     // If there is no exact match, but there is a related font, we
     // still return NULL, but also set *relatedFont.
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 7c0aaa2..90f0a4a 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -737,7 +737,7 @@
     fLastMarginContentEntry = NULL;
     fDrawingArea = kContent_DrawingArea;
     if (fFontGlyphUsage.get() == NULL) {
-        fFontGlyphUsage.reset(new SkPDFGlyphSetMap());
+        fFontGlyphUsage.reset(SkNEW(SkPDFGlyphSetMap));
     }
 }
 
@@ -1896,8 +1896,10 @@
         fInitialTransform.mapRect(&boundsTemp);
         boundsTemp.roundOut(&bounds);
 
-        pdfShader.reset(SkPDFShader::GetPDFShader(*shader, transform, bounds,
-                        SkIntToScalar(fRasterDpi) / DPI_FOR_RASTER_SCALE_ONE));
+        SkScalar rasterScale =
+                SkIntToScalar(fRasterDpi) / DPI_FOR_RASTER_SCALE_ONE;
+        pdfShader.reset(SkPDFShader::GetPDFShader(
+                fCanon, fRasterDpi, *shader, transform, bounds, rasterScale));
 
         if (pdfShader.get()) {
             // pdfShader has been canonicalized so we can directly compare
@@ -1928,12 +1930,12 @@
     SkAutoTUnref<SkPDFGraphicState> newGraphicState;
     if (color == paint.getColor()) {
         newGraphicState.reset(
-                SkPDFGraphicState::GetGraphicStateForPaint(paint));
+                SkPDFGraphicState::GetGraphicStateForPaint(fCanon, paint));
     } else {
         SkPaint newPaint = paint;
         newPaint.setColor(color);
         newGraphicState.reset(
-                SkPDFGraphicState::GetGraphicStateForPaint(newPaint));
+                SkPDFGraphicState::GetGraphicStateForPaint(fCanon, newPaint));
     }
     int resourceIndex = addGraphicStateResource(newGraphicState.get());
     entry->fGraphicStateIndex = resourceIndex;
@@ -1989,8 +1991,8 @@
 }
 
 int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) {
-    SkAutoTUnref<SkPDFFont> newFont(SkPDFFont::GetFontResource(typeface,
-                                                               glyphID));
+    SkAutoTUnref<SkPDFFont> newFont(
+            SkPDFFont::GetFontResource(fCanon, typeface, glyphID));
     int resourceIndex = fFontResources.find(newFont.get());
     if (resourceIndex < 0) {
         resourceIndex = fFontResources.count();
@@ -2133,7 +2135,7 @@
     }
 
     SkAutoTUnref<SkPDFObject> image(
-            SkPDFCreateImageObject(*bitmap, subset));
+            SkPDFCreateImageObject(fCanon, *bitmap, subset));
     if (!image) {
         return;
     }
@@ -2141,4 +2143,3 @@
     SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()),
                                 &content.entry()->fContent);
 }
-
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp
index 426fbaf..f386b71 100644
--- a/src/pdf/SkPDFFont.cpp
+++ b/src/pdf/SkPDFFont.cpp
@@ -747,12 +747,7 @@
  * from each page and combine it and ask for a resource with that subset.
  */
 
-SkPDFFont::~SkPDFFont() {
-    {
-        SkAutoMutexAcquire lock(SkPDFCanon::GetFontMutex());
-        SkPDFCanon::GetCanon().removeFont(this);
-    }
-}
+SkPDFFont::~SkPDFFont() { fCanon->removeFont(this); }
 
 SkTypeface* SkPDFFont::typeface() {
     return fTypeface.get();
@@ -804,16 +799,16 @@
 }
 
 // static
-SkPDFFont* SkPDFFont::GetFontResource(SkTypeface* typeface, uint16_t glyphID) {
+SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon,
+                                      SkTypeface* typeface,
+                                      uint16_t glyphID) {
+    SkASSERT(canon);
     SkAutoResolveDefaultTypeface autoResolve(typeface);
     typeface = autoResolve.get();
     const uint32_t fontID = typeface->uniqueID();
 
-    SkAutoMutexAcquire lock(SkPDFCanon::GetFontMutex());
     SkPDFFont* relatedFont;
-    SkPDFFont* pdfFont =
-            SkPDFCanon::GetCanon().findFont(fontID, glyphID, &relatedFont);
-    if (pdfFont) {
+    if (SkPDFFont* pdfFont = canon->findFont(fontID, glyphID, &relatedFont)) {
         return SkRef(pdfFont);
     }
 
@@ -857,25 +852,27 @@
 #endif
     }
 
-    SkPDFFont* font = Create(fontMetrics.get(), typeface, glyphID,
-                             relatedFontDescriptor);
-    SkPDFCanon::GetCanon().addFont(font, fontID, font->fFirstGlyphID);
-    return font;  // Return the reference new SkPDFFont() created.
+    SkPDFFont* font = SkPDFFont::Create(canon, fontMetrics.get(), typeface,
+                                        glyphID, relatedFontDescriptor);
+    canon->addFont(font, fontID, font->fFirstGlyphID);
+    return font;
 }
 
 SkPDFFont* SkPDFFont::getFontSubset(const SkPDFGlyphSet*) {
     return NULL;  // Default: no support.
 }
 
-SkPDFFont::SkPDFFont(const SkAdvancedTypefaceMetrics* info,
+SkPDFFont::SkPDFFont(SkPDFCanon* canon,
+                     const SkAdvancedTypefaceMetrics* info,
                      SkTypeface* typeface,
                      SkPDFDict* relatedFontDescriptor)
-        : SkPDFDict("Font"),
-          fTypeface(ref_or_default(typeface)),
-          fFirstGlyphID(1),
-          fLastGlyphID(info ? info->fLastGlyphID : 0),
-          fFontInfo(SkSafeRef(info)),
-          fDescriptor(SkSafeRef(relatedFontDescriptor)) {
+    : SkPDFDict("Font")
+    , fCanon(canon)
+    , fTypeface(ref_or_default(typeface))
+    , fFirstGlyphID(1)
+    , fLastGlyphID(info ? info->fLastGlyphID : 0)
+    , fFontInfo(SkSafeRef(info))
+    , fDescriptor(SkSafeRef(relatedFontDescriptor)) {
     if (info == NULL ||
             info->fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag) {
         fFontType = SkAdvancedTypefaceMetrics::kOther_Font;
@@ -885,8 +882,10 @@
 }
 
 // static
-SkPDFFont* SkPDFFont::Create(const SkAdvancedTypefaceMetrics* info,
-                             SkTypeface* typeface, uint16_t glyphID,
+SkPDFFont* SkPDFFont::Create(SkPDFCanon* canon,
+                             const SkAdvancedTypefaceMetrics* info,
+                             SkTypeface* typeface,
+                             uint16_t glyphID,
                              SkPDFDict* relatedFontDescriptor) {
     SkAdvancedTypefaceMetrics::FontType type =
         info ? info->fType : SkAdvancedTypefaceMetrics::kOther_Font;
@@ -894,26 +893,22 @@
     if (info &&
             (info->fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag)) {
         NOT_IMPLEMENTED(true, true);
-        return new SkPDFType3Font(info,
-                                  typeface,
-                                  glyphID);
+        return new SkPDFType3Font(canon, info, typeface, glyphID);
     }
     if (type == SkAdvancedTypefaceMetrics::kType1CID_Font ||
         type == SkAdvancedTypefaceMetrics::kTrueType_Font) {
         SkASSERT(relatedFontDescriptor == NULL);
-        return new SkPDFType0Font(info, typeface);
+        return new SkPDFType0Font(canon, info, typeface);
     }
     if (type == SkAdvancedTypefaceMetrics::kType1_Font) {
-        return new SkPDFType1Font(info,
-                                  typeface,
-                                  glyphID,
+        return new SkPDFType1Font(canon, info, typeface, glyphID,
                                   relatedFontDescriptor);
     }
 
     SkASSERT(type == SkAdvancedTypefaceMetrics::kCFF_Font ||
              type == SkAdvancedTypefaceMetrics::kOther_Font);
 
-    return new SkPDFType3Font(info, typeface, glyphID);
+    return new SkPDFType3Font(canon, info, typeface, glyphID);
 }
 
 const SkAdvancedTypefaceMetrics* SkPDFFont::fontInfo() {
@@ -1001,9 +996,10 @@
 // class SkPDFType0Font
 ///////////////////////////////////////////////////////////////////////////////
 
-SkPDFType0Font::SkPDFType0Font(const SkAdvancedTypefaceMetrics* info,
+SkPDFType0Font::SkPDFType0Font(SkPDFCanon* canon,
+                               const SkAdvancedTypefaceMetrics* info,
                                SkTypeface* typeface)
-        : SkPDFFont(info, typeface, NULL) {
+    : SkPDFFont(canon, info, typeface, NULL) {
     SkDEBUGCODE(fPopulated = false);
     if (!canSubset()) {
         populate(NULL);
@@ -1016,7 +1012,8 @@
     if (!canSubset()) {
         return NULL;
     }
-    SkPDFType0Font* newSubset = new SkPDFType0Font(fontInfo(), typeface());
+    SkPDFType0Font* newSubset =
+            new SkPDFType0Font(fCanon, fontInfo(), typeface());
     newSubset->populate(subset);
     return newSubset;
 }
@@ -1034,7 +1031,7 @@
     insertName("Encoding", "Identity-H");
 
     SkAutoTUnref<SkPDFCIDFont> newCIDFont(
-            new SkPDFCIDFont(fontInfo(), typeface(), subset));
+            new SkPDFCIDFont(fCanon, fontInfo(), typeface(), subset));
     SkAutoTUnref<SkPDFArray> descendantFonts(new SkPDFArray());
     descendantFonts->append(new SkPDFObjRef(newCIDFont.get()))->unref();
     insert("DescendantFonts", descendantFonts.get());
@@ -1049,9 +1046,11 @@
 // class SkPDFCIDFont
 ///////////////////////////////////////////////////////////////////////////////
 
-SkPDFCIDFont::SkPDFCIDFont(const SkAdvancedTypefaceMetrics* info,
-                           SkTypeface* typeface, const SkPDFGlyphSet* subset)
-        : SkPDFFont(info, typeface, NULL) {
+SkPDFCIDFont::SkPDFCIDFont(SkPDFCanon* canon,
+                           const SkAdvancedTypefaceMetrics* info,
+                           SkTypeface* typeface,
+                           const SkPDFGlyphSet* subset)
+    : SkPDFFont(canon, info, typeface, NULL) {
     populate(subset);
 }
 
@@ -1202,11 +1201,12 @@
 // class SkPDFType1Font
 ///////////////////////////////////////////////////////////////////////////////
 
-SkPDFType1Font::SkPDFType1Font(const SkAdvancedTypefaceMetrics* info,
+SkPDFType1Font::SkPDFType1Font(SkPDFCanon* canon,
+                               const SkAdvancedTypefaceMetrics* info,
                                SkTypeface* typeface,
                                uint16_t glyphID,
                                SkPDFDict* relatedFontDescriptor)
-        : SkPDFFont(info, typeface, relatedFontDescriptor) {
+    : SkPDFFont(canon, info, typeface, relatedFontDescriptor) {
     populate(glyphID);
 }
 
@@ -1329,10 +1329,11 @@
 // class SkPDFType3Font
 ///////////////////////////////////////////////////////////////////////////////
 
-SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics* info,
+SkPDFType3Font::SkPDFType3Font(SkPDFCanon* canon,
+                               const SkAdvancedTypefaceMetrics* info,
                                SkTypeface* typeface,
                                uint16_t glyphID)
-        : SkPDFFont(info, typeface, NULL) {
+    : SkPDFFont(canon, info, typeface, NULL) {
     populate(glyphID);
 }
 
diff --git a/src/pdf/SkPDFFont.h b/src/pdf/SkPDFFont.h
index 81ffd90..105ae8d 100644
--- a/src/pdf/SkPDFFont.h
+++ b/src/pdf/SkPDFFont.h
@@ -18,6 +18,7 @@
 #include "SkTypeface.h"
 
 class SkPaint;
+class SkPDFCanon;
 class SkPDFCatalog;
 class SkPDFFont;
 
@@ -126,7 +127,9 @@
      *  @param typeface  The typeface to find.
      *  @param glyphID   Specify which section of a large font is of interest.
      */
-    static SkPDFFont* GetFontResource(SkTypeface* typeface, uint16_t glyphID);
+    static SkPDFFont* GetFontResource(SkPDFCanon* canon,
+                                      SkTypeface* typeface,
+                                      uint16_t glyphID);
 
     /** Subset the font based on usage set. Returns a SkPDFFont instance with
      *  subset.
@@ -148,8 +151,12 @@
                          uint16_t searchGlyphID);
 
 protected:
+    SkPDFCanon* const fCanon;
+
     // Common constructor to handle common members.
-    SkPDFFont(const SkAdvancedTypefaceMetrics* fontInfo, SkTypeface* typeface,
+    SkPDFFont(SkPDFCanon* canon,
+              const SkAdvancedTypefaceMetrics* fontInfo,
+              SkTypeface* typeface,
               SkPDFDict* relatedFontDescriptor);
 
     // Accessors for subclass.
@@ -176,8 +183,10 @@
     void populateToUnicodeTable(const SkPDFGlyphSet* subset);
 
     // Create instances of derived types based on fontInfo.
-    static SkPDFFont* Create(const SkAdvancedTypefaceMetrics* fontInfo,
-                             SkTypeface* typeface, uint16_t glyphID,
+    static SkPDFFont* Create(SkPDFCanon* canon,
+                             const SkAdvancedTypefaceMetrics* fontInfo,
+                             SkTypeface* typeface,
+                             uint16_t glyphID,
                              SkPDFDict* relatedFontDescriptor);
 
     static bool Find(uint32_t fontID, uint16_t glyphID, int* index);
diff --git a/src/pdf/SkPDFFontImpl.h b/src/pdf/SkPDFFontImpl.h
index eaec8f9..2556822 100644
--- a/src/pdf/SkPDFFontImpl.h
+++ b/src/pdf/SkPDFFontImpl.h
@@ -28,7 +28,9 @@
     typedef SkPDFDict INHERITED;
 #endif
 
-    SkPDFType0Font(const SkAdvancedTypefaceMetrics* info, SkTypeface* typeface);
+    SkPDFType0Font(SkPDFCanon* canon,
+                   const SkAdvancedTypefaceMetrics* info,
+                   SkTypeface* typeface);
 
     bool populate(const SkPDFGlyphSet* subset);
 };
@@ -41,7 +43,9 @@
 private:
     friend class SkPDFType0Font;  // to access the constructor
 
-    SkPDFCIDFont(const SkAdvancedTypefaceMetrics* info, SkTypeface* typeface,
+    SkPDFCIDFont(SkPDFCanon* canon,
+                 const SkAdvancedTypefaceMetrics* info,
+                 SkTypeface* typeface,
                  const SkPDFGlyphSet* subset);
 
     bool populate(const SkPDFGlyphSet* subset);
@@ -57,8 +61,11 @@
 private:
     friend class SkPDFFont;  // to access the constructor
 
-    SkPDFType1Font(const SkAdvancedTypefaceMetrics* info, SkTypeface* typeface,
-                   uint16_t glyphID, SkPDFDict* relatedFontDescriptor);
+    SkPDFType1Font(SkPDFCanon* canon,
+                   const SkAdvancedTypefaceMetrics* info,
+                   SkTypeface* typeface,
+                   uint16_t glyphID,
+                   SkPDFDict* relatedFontDescriptor);
 
     bool populate(int16_t glyphID);
     bool addFontDescriptor(int16_t defaultWidth);
@@ -74,8 +81,10 @@
 private:
     friend class SkPDFFont;  // to access the constructor
 
-    SkPDFType3Font(const SkAdvancedTypefaceMetrics* info,
-                   SkTypeface* typeface, uint16_t glyphID);
+    SkPDFType3Font(SkPDFCanon* canon,
+                   const SkAdvancedTypefaceMetrics* info,
+                   SkTypeface* typeface,
+                   uint16_t glyphID);
 
     bool populate(uint16_t glyphID);
 };
diff --git a/src/pdf/SkPDFGraphicState.cpp b/src/pdf/SkPDFGraphicState.cpp
index 46aa1d1..4ec0821 100644
--- a/src/pdf/SkPDFGraphicState.cpp
+++ b/src/pdf/SkPDFGraphicState.cpp
@@ -113,9 +113,8 @@
 }
 
 SkPDFGraphicState::~SkPDFGraphicState() {
-    SkAutoMutexAcquire lock(SkPDFCanon::GetPaintMutex());
-    if (!fSMask) {
-        SkPDFCanon::GetCanon().removeGraphicState(this);
+    if (fCanon) {
+        fCanon->removeGraphicState(this);
     }
 }
 
@@ -126,15 +125,14 @@
 
 // static
 SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(
-        const SkPaint& paint) {
-    SkAutoMutexAcquire lock(SkPDFCanon::GetPaintMutex());
-    SkPDFGraphicState* pdfGraphicState =
-            SkPDFCanon::GetCanon().findGraphicState(paint);
+        SkPDFCanon* canon, const SkPaint& paint) {
+    SkASSERT(canon);
+    SkPDFGraphicState* pdfGraphicState = canon->findGraphicState(paint);
     if (pdfGraphicState) {
         return SkRef(pdfGraphicState);
     }
-    pdfGraphicState = new SkPDFGraphicState(paint);
-    SkPDFCanon::GetCanon().addGraphicState(pdfGraphicState);
+    pdfGraphicState = new SkPDFGraphicState(canon, paint);
+    canon->addGraphicState(pdfGraphicState);
     return pdfGraphicState;
 }
 
@@ -181,7 +179,6 @@
 
     SkPDFGraphicState* result = new SkPDFGraphicState;
     result->fPopulated = true;
-    result->fSMask = true;
     result->insertName("Type", "ExtGState");
     result->insert("SMask", sMaskDict.get());
 
@@ -195,7 +192,6 @@
 SkPDFGraphicState* SkPDFGraphicState::CreateNoSMaskGraphicState() {
     SkPDFGraphicState* noSMaskGS = SkNEW(SkPDFGraphicState);
     noSMaskGS->fPopulated = true;
-    noSMaskGS->fSMask = true;
     noSMaskGS->insertName("Type", "ExtGState");
     noSMaskGS->insertName("SMask", "None");
     return noSMaskGS;
@@ -211,15 +207,10 @@
 }
 
 SkPDFGraphicState::SkPDFGraphicState()
-    : fPopulated(false),
-      fSMask(false) {
-}
+    : fCanon(NULL), fPopulated(false) {}
 
-SkPDFGraphicState::SkPDFGraphicState(const SkPaint& paint)
-    : fPaint(paint),
-      fPopulated(false),
-      fSMask(false) {
-}
+SkPDFGraphicState::SkPDFGraphicState(SkPDFCanon* canon, const SkPaint& paint)
+    : fCanon(canon), fPaint(paint), fPopulated(false) {}
 
 // populateDict and operator== have to stay in sync with each other.
 void SkPDFGraphicState::populateDict() {
diff --git a/src/pdf/SkPDFGraphicState.h b/src/pdf/SkPDFGraphicState.h
index a759d56..b26e4a0 100644
--- a/src/pdf/SkPDFGraphicState.h
+++ b/src/pdf/SkPDFGraphicState.h
@@ -47,7 +47,8 @@
      *  other references.
      *  @param paint  The SkPaint to emulate.
      */
-    static SkPDFGraphicState* GetGraphicStateForPaint(const SkPaint& paint);
+    static SkPDFGraphicState* GetGraphicStateForPaint(SkPDFCanon* canon,
+                                                      const SkPaint& paint);
 
     /** Make a graphic state that only sets the passed soft mask. The
      *  reference count of the object is incremented and it is the caller's
@@ -74,12 +75,12 @@
     static SkPDFGraphicState* CreateNoSMaskGraphicState();
 
 private:
+    SkPDFCanon* const fCanon;
     const SkPaint fPaint;
     bool fPopulated;
-    bool fSMask;
 
     SkPDFGraphicState();
-    explicit SkPDFGraphicState(const SkPaint& paint);
+    SkPDFGraphicState(SkPDFCanon* canon, const SkPaint& paint);
 
     void populateDict();
 
diff --git a/src/pdf/SkPDFImage.cpp b/src/pdf/SkPDFImage.cpp
index 788b647..666a008 100644
--- a/src/pdf/SkPDFImage.cpp
+++ b/src/pdf/SkPDFImage.cpp
@@ -687,10 +687,10 @@
 }  // namespace
 #endif
 
-SkPDFObject* SkPDFCreateImageObject(
-        const SkBitmap& bitmap,
-        const SkIRect& subset) {
-    if (SkPDFObject* pdfBitmap = SkPDFBitmap::Create(bitmap, subset)) {
+SkPDFObject* SkPDFCreateImageObject(SkPDFCanon* canon,
+                                    const SkBitmap& bitmap,
+                                    const SkIRect& subset) {
+    if (SkPDFObject* pdfBitmap = SkPDFBitmap::Create(canon, bitmap, subset)) {
         return pdfBitmap;
     }
 #if 0  // reenable when we can figure out the JPEG colorspace
diff --git a/src/pdf/SkPDFImage.h b/src/pdf/SkPDFImage.h
index 8e36542..64be971 100644
--- a/src/pdf/SkPDFImage.h
+++ b/src/pdf/SkPDFImage.h
@@ -24,7 +24,9 @@
 /**
  *  Return the mose efficient availible encoding of the given bitmap.
  */
-SkPDFObject* SkPDFCreateImageObject(const SkBitmap&, const SkIRect& subset);
+SkPDFObject* SkPDFCreateImageObject(SkPDFCanon* canon,
+                                    const SkBitmap&,
+                                    const SkIRect& subset);
 
 /** \class SkPDFImage
 
diff --git a/src/pdf/SkPDFShader.cpp b/src/pdf/SkPDFShader.cpp
index 979ef3f..21d767d 100644
--- a/src/pdf/SkPDFShader.cpp
+++ b/src/pdf/SkPDFShader.cpp
@@ -507,13 +507,12 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state)
-    : SkPDFDict("Pattern"), fShaderState(state) {}
+SkPDFFunctionShader::SkPDFFunctionShader(SkPDFCanon* canon,
+                                         SkPDFShader::State* state)
+    : SkPDFDict("Pattern"), fCanon(canon), fShaderState(state) {}
 
 SkPDFFunctionShader::~SkPDFFunctionShader() {
-    SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex());
-    SkPDFCanon::GetCanon().removeFunctionShader(this);
-    lock.release();
+    fCanon->removeFunctionShader(this);
     fResources.unrefAll();
 }
 
@@ -523,37 +522,37 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShader::State* state)
-    : fShaderState(state) {}
+SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFCanon* canon,
+                                                   SkPDFShader::State* state)
+    : fCanon(canon), fShaderState(state) {}
 
 bool SkPDFAlphaFunctionShader::equals(const SkPDFShader::State& state) const {
     return state == *fShaderState;
 }
 
 SkPDFAlphaFunctionShader::~SkPDFAlphaFunctionShader() {
-    SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex());
-    SkPDFCanon::GetCanon().removeAlphaShader(this);
+    fCanon->removeAlphaShader(this);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
-SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state)
-    : fShaderState(state) {}
+SkPDFImageShader::SkPDFImageShader(SkPDFCanon* canon, SkPDFShader::State* state)
+    : fCanon(canon), fShaderState(state) {}
 
 bool SkPDFImageShader::equals(const SkPDFShader::State& state) const {
     return state == *fShaderState;
 }
 
 SkPDFImageShader::~SkPDFImageShader() {
-    SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex());
-    SkPDFCanon::GetCanon().removeImageShader(this);
-    lock.release();
+    fCanon->removeImageShader(this);
     fResources.unrefAll();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 static SkPDFObject* get_pdf_shader_by_state(
+        SkPDFCanon* canon,
+        SkScalar dpi,
         SkAutoTDelete<SkPDFShader::State>* autoState) {
     const SkPDFShader::State& state = **autoState;
     if (state.fType == SkShader::kNone_GradientType && state.fImage.isNull()) {
@@ -563,28 +562,31 @@
         // second shader, then applying the layer to the original drawing.
         return NULL;
     } else if (state.fType == SkShader::kNone_GradientType) {
-        SkPDFObject* shader = SkPDFCanon::GetCanon().findImageShader(state);
-        return shader ? SkRef(shader) : SkPDFImageShader::Create(autoState);
-    } else if (state.GradientHasAlpha()) {
-        SkPDFObject* shader = SkPDFCanon::GetCanon().findAlphaShader(state);
+        SkPDFObject* shader = canon->findImageShader(state);
         return shader ? SkRef(shader)
-                      : SkPDFAlphaFunctionShader::Create(autoState);
+                      : SkPDFImageShader::Create(canon, dpi, autoState);
+    } else if (state.GradientHasAlpha()) {
+        SkPDFObject* shader = canon->findAlphaShader(state);
+        return shader ? SkRef(shader)
+                      : SkPDFAlphaFunctionShader::Create(canon, dpi, autoState);
     } else {
-        SkPDFObject* shader = SkPDFCanon::GetCanon().findFunctionShader(state);
-        return shader ? SkRef(shader) : SkPDFFunctionShader::Create(autoState);
+        SkPDFObject* shader = canon->findFunctionShader(state);
+        return shader ? SkRef(shader)
+                      : SkPDFFunctionShader::Create(canon, autoState);
     }
 }
 
 // static
-SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader,
+SkPDFObject* SkPDFShader::GetPDFShader(SkPDFCanon* canon,
+                                       SkScalar dpi,
+                                       const SkShader& shader,
                                        const SkMatrix& matrix,
                                        const SkIRect& surfaceBBox,
                                        SkScalar rasterScale) {
     // There is only one mutex becasue we don't know which one we'll need.
-    SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex());
     SkAutoTDelete<SkPDFShader::State> state(
             SkNEW_ARGS(State, (shader, matrix, surfaceBBox, rasterScale)));
-    return get_pdf_shader_by_state(&state);
+    return get_pdf_shader_by_state(canon, dpi, &state);
 }
 
 static SkPDFResourceDict* get_gradient_resource_dict(
@@ -647,14 +649,14 @@
  * luminosity mode. The shader pattern extends to the bbox.
  */
 static SkPDFGraphicState* create_smask_graphic_state(
-        const SkPDFShader::State& state) {
+        SkPDFCanon* canon, SkScalar dpi, const SkPDFShader::State& state) {
     SkRect bbox;
     bbox.set(state.fBBox);
 
     SkAutoTDelete<SkPDFShader::State> alphaToLuminosityState(
             state.CreateAlphaToLuminosityState());
     SkAutoTUnref<SkPDFObject> luminosityShader(
-            get_pdf_shader_by_state(&alphaToLuminosityState));
+            get_pdf_shader_by_state(canon, dpi, &alphaToLuminosityState));
 
     SkAutoTDelete<SkStream> alphaStream(create_pattern_fill_content(-1, bbox));
 
@@ -670,6 +672,8 @@
 }
 
 SkPDFAlphaFunctionShader* SkPDFAlphaFunctionShader::Create(
+        SkPDFCanon* canon,
+        SkScalar dpi,
         SkAutoTDelete<SkPDFShader::State>* autoState) {
     const SkPDFShader::State& state = **autoState;
     SkRect bbox;
@@ -677,17 +681,19 @@
 
     SkAutoTDelete<SkPDFShader::State> opaqueState(state.CreateOpaqueState());
 
-    SkPDFObject* colorShader = get_pdf_shader_by_state(&opaqueState);
+    SkPDFObject* colorShader =
+            get_pdf_shader_by_state(canon, dpi, &opaqueState);
     if (!colorShader) {
         return NULL;
     }
 
     // Create resource dict with alpha graphics state as G0 and
     // pattern shader as P0, then write content stream.
-    SkAutoTUnref<SkPDFGraphicState> alphaGs(create_smask_graphic_state(state));
+    SkAutoTUnref<SkPDFGraphicState> alphaGs(
+            create_smask_graphic_state(canon, dpi, state));
 
     SkPDFAlphaFunctionShader* alphaFunctionShader =
-            SkNEW_ARGS(SkPDFAlphaFunctionShader, (autoState->detach()));
+            SkNEW_ARGS(SkPDFAlphaFunctionShader, (canon, autoState->detach()));
 
     alphaFunctionShader->fColorShader.reset(colorShader);
 
@@ -701,7 +707,7 @@
     populate_tiling_pattern_dict(alphaFunctionShader, bbox,
                                  alphaFunctionShader->fResourceDict.get(),
                                  SkMatrix::I());
-    SkPDFCanon::GetCanon().addAlphaShader(alphaFunctionShader);
+    canon->addAlphaShader(alphaFunctionShader);
     return alphaFunctionShader;
 }
 
@@ -774,7 +780,7 @@
 }
 
 SkPDFFunctionShader* SkPDFFunctionShader::Create(
-        SkAutoTDelete<SkPDFShader::State>* autoState) {
+        SkPDFCanon* canon, SkAutoTDelete<SkPDFShader::State>* autoState) {
     const SkPDFShader::State& state = **autoState;
 
     SkString (*codeFunction)(const SkShader::GradientInfo& info,
@@ -893,7 +899,7 @@
             SkPDFUtils::MatrixToArray(finalMatrix));
 
     SkPDFFunctionShader* pdfFunctionShader =
-            SkNEW_ARGS(SkPDFFunctionShader, (autoState->detach()));
+            SkNEW_ARGS(SkPDFFunctionShader, (canon, autoState->detach()));
 
     pdfFunctionShader->fResources.push(function);
     // Pass ownership to resource list.
@@ -902,11 +908,13 @@
     pdfFunctionShader->insert("Matrix", matrixArray.get());
     pdfFunctionShader->insert("Shading", pdfShader.get());
 
-    SkPDFCanon::GetCanon().addFunctionShader(pdfFunctionShader);
+    canon->addFunctionShader(pdfFunctionShader);
     return pdfFunctionShader;
 }
 
 SkPDFImageShader* SkPDFImageShader::Create(
+        SkPDFCanon* canon,
+        SkScalar dpi,
         SkAutoTDelete<SkPDFShader::State>* autoState) {
     const SkPDFShader::State& state = **autoState;
 
@@ -945,7 +953,7 @@
     SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()),
                                  SkScalarRoundToInt(deviceBounds.height()));
     SkAutoTUnref<SkPDFDevice> patternDevice(
-            SkPDFDevice::CreateUnflipped(size, 72.0f, NULL));
+            SkPDFDevice::CreateUnflipped(size, dpi, canon));
     SkCanvas canvas(patternDevice.get());
 
     SkRect patternBBox;
@@ -1107,17 +1115,15 @@
     SkAutoTDelete<SkStream> content(patternDevice->content());
 
     SkPDFImageShader* imageShader =
-            SkNEW_ARGS(SkPDFImageShader, (autoState->detach()));
+            SkNEW_ARGS(SkPDFImageShader, (canon, autoState->detach()));
     imageShader->setData(content.get());
 
-    populate_tiling_pattern_dict(imageShader, 
-                                 patternBBox,
-                                 patternDevice->getResourceDict(),
-                                 finalMatrix);
+    populate_tiling_pattern_dict(imageShader, patternBBox,
+                                 patternDevice->getResourceDict(), finalMatrix);
 
     imageShader->fShaderState->fImage.unlockPixels();
 
-    SkPDFCanon::GetCanon().addImageShader(imageShader);
+    canon->addImageShader(imageShader);
     return imageShader;
 }
 
diff --git a/src/pdf/SkPDFShader.h b/src/pdf/SkPDFShader.h
index 3fb962a..5be47a3 100644
--- a/src/pdf/SkPDFShader.h
+++ b/src/pdf/SkPDFShader.h
@@ -14,6 +14,7 @@
 #include "SkPDFStream.h"
 #include "SkPDFTypes.h"
 
+class SkPDFCanon;
 class SkMatrix;
 class SkShader;
 struct SkIRect;
@@ -42,7 +43,9 @@
      *  @param rasterScale Additional scale to be applied for early
      *                     rasterization.
      */
-    static SkPDFObject* GetPDFShader(const SkShader& shader,
+    static SkPDFObject* GetPDFShader(SkPDFCanon* canon,
+                                     SkScalar dpi,
+                                     const SkShader& shader,
                                      const SkMatrix& matrix,
                                      const SkIRect& surfaceBBox,
                                      SkScalar rasterScale);
@@ -52,14 +55,16 @@
     SK_DECLARE_INST_COUNT(SkPDFFunctionShader);
 
 public:
-    static SkPDFFunctionShader* Create(SkAutoTDelete<SkPDFShader::State>*);
+    static SkPDFFunctionShader* Create(SkPDFCanon*,
+                                       SkAutoTDelete<SkPDFShader::State>*);
     virtual ~SkPDFFunctionShader();
     bool equals(const SkPDFShader::State&) const;
 
 private:
+    SkPDFCanon* fCanon;
     SkAutoTDelete<const SkPDFShader::State> fShaderState;
     SkTDArray<SkPDFObject*> fResources;
-    explicit SkPDFFunctionShader(SkPDFShader::State* state);
+    SkPDFFunctionShader(SkPDFCanon*, SkPDFShader::State*);
     typedef SkPDFDict INHERITED;
 };
 
@@ -70,27 +75,33 @@
  */
 class SkPDFAlphaFunctionShader : public SkPDFStream {
 public:
-    static SkPDFAlphaFunctionShader* Create(SkAutoTDelete<SkPDFShader::State>*);
+    static SkPDFAlphaFunctionShader* Create(SkPDFCanon*,
+                                            SkScalar dpi,
+                                            SkAutoTDelete<SkPDFShader::State>*);
     virtual ~SkPDFAlphaFunctionShader();
     bool equals(const SkPDFShader::State&) const;
 
 private:
+    SkPDFCanon* fCanon;
     SkAutoTDelete<const SkPDFShader::State> fShaderState;
     SkAutoTUnref<SkPDFObject> fColorShader;
     SkAutoTUnref<SkPDFResourceDict> fResourceDict;
-    explicit SkPDFAlphaFunctionShader(SkPDFShader::State* state);
+    SkPDFAlphaFunctionShader(SkPDFCanon*, SkPDFShader::State*);
 };
 
 class SkPDFImageShader : public SkPDFStream {
 public:
-    static SkPDFImageShader* Create(SkAutoTDelete<SkPDFShader::State>*);
+    static SkPDFImageShader* Create(SkPDFCanon*,
+                                    SkScalar dpi,
+                                    SkAutoTDelete<SkPDFShader::State>*);
     virtual ~SkPDFImageShader();
     bool equals(const SkPDFShader::State&) const;
 
 private:
+    SkPDFCanon* fCanon;
     SkAutoTDelete<const SkPDFShader::State> fShaderState;
     SkTSet<SkPDFObject*> fResources;
-    explicit SkPDFImageShader(SkPDFShader::State* state);
+    SkPDFImageShader(SkPDFCanon*, SkPDFShader::State*);
 };
 
 #endif