Add createNewCompatibleDevice. Allow devices to have a NULL factory and saveLayer will fall back on createNewCompatibleDevice.

Review URL: http://codereview.appspot.com/4633044/



git-svn-id: http://skia.googlecode.com/svn/trunk@1625 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 5b2e964..0b6f086 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -434,10 +434,9 @@
         : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
     inc_canvas();
 
-    fDeviceFactory = device->getDeviceFactory();
-    SkASSERT(fDeviceFactory);
-    fDeviceFactory->ref();
-              
+    fDeviceFactory = device->getDeviceFactory();

+    SkSafeRef(fDeviceFactory);
+
     this->init(device);
 }
 
@@ -446,9 +445,8 @@
     inc_canvas();
 
     SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap));
-    fDeviceFactory = device->getDeviceFactory();
-    SkASSERT(fDeviceFactory);
-    fDeviceFactory->ref();
+    fDeviceFactory = device->getDeviceFactory();

+    SkSafeRef(fDeviceFactory);
 
     this->init(device)->unref();
 }
@@ -736,8 +734,9 @@
     bool isOpaque;
     SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque);
 
-    SkDevice* device = this->createDevice(config, ir.width(), ir.height(),
-                                          isOpaque);
+    SkDevice* device = this->createLayerDevice(config, ir.width(), ir.height(),
+                                               isOpaque);
+
     device->setOrigin(ir.fLeft, ir.fTop);
     DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint));
     device->unref();
@@ -1176,11 +1175,32 @@
     }
 }
 
-SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width, int height,
-                                 bool isOpaque) {
-    return fDeviceFactory->newDevice(this, config, width, height, isOpaque, true);
+SkDevice* SkCanvas::createLayerDevice(SkBitmap::Config config,
+                                      int width, int height,
+                                      bool isOpaque) {
+    if (fDeviceFactory) {
+        return fDeviceFactory->newDevice(this, config, width, height,
+                                         isOpaque, true);
+    } else {
+        return this->getDevice()->createCompatibleDeviceForSaveLayer(
+                                config, width, height,
+                                isOpaque);
+    }
 }
 
+SkDevice* SkCanvas::createCompatibleDevice(SkBitmap::Config config, 
+                                           int width, int height,
+                                           bool isOpaque) {
+    SkDevice* device = this->getDevice();
+    if (device) {
+        return device->createCompatibleDevice(config, width, height,
+                                              isOpaque);
+    } else {
+        return NULL;
+    }
+}
+
+
 //////////////////////////////////////////////////////////////////////////////
 //  These are the virtual drawing methods
 //////////////////////////////////////////////////////////////////////////////