| Index: src/core/SkCanvas.cpp | 
| diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp | 
| index 514a45460c23c82c35073686cfd15a522a188514..fbf6c9e83b904acc7df0b08a8b245097d768002d 100644 | 
| --- a/src/core/SkCanvas.cpp | 
| +++ b/src/core/SkCanvas.cpp | 
| @@ -111,13 +111,16 @@ struct DeviceCM { | 
| DeviceCM*           fNext; | 
| SkBaseDevice*       fDevice; | 
| SkRasterClip        fClip; | 
| -    const SkMatrix*     fMatrix; | 
| SkPaint*            fPaint; // may be null (in the future) | 
| +    const SkMatrix*     fMatrix; | 
| +    SkMatrix            fMatrixStorage; | 
| +    const bool          fDeviceIsBitmapDevice; | 
|  | 
| DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas, | 
| -             bool conservativeRasterClip) | 
| +             bool conservativeRasterClip, bool deviceIsBitmapDevice) | 
| : fNext(NULL) | 
| , fClip(conservativeRasterClip) | 
| +        , fDeviceIsBitmapDevice(deviceIsBitmapDevice) | 
| { | 
| if (NULL != device) { | 
| device->ref(); | 
| @@ -180,9 +183,6 @@ struct DeviceCM { | 
| } | 
| #endif | 
| } | 
| - | 
| -private: | 
| -    SkMatrix    fMatrixStorage; | 
| }; | 
|  | 
| /*  This is the record we keep for each save/restore level in the stack. | 
| @@ -486,7 +486,7 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { | 
|  | 
| SkASSERT(sizeof(DeviceCM) <= sizeof(fBaseLayerStorage)); | 
| fMCRec->fLayer = (DeviceCM*)fBaseLayerStorage; | 
| -    new (fBaseLayerStorage) DeviceCM(NULL, NULL, NULL, fConservativeRasterClip); | 
| +    new (fBaseLayerStorage) DeviceCM(NULL, NULL, NULL, fConservativeRasterClip, false); | 
|  | 
| fMCRec->fTopLayer = fMCRec->fLayer; | 
|  | 
| @@ -985,16 +985,27 @@ void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav | 
| return; | 
| } | 
|  | 
| -    SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage; | 
| -    device = device->onCreateDevice(SkBaseDevice::CreateInfo(info, usage, geo), paint); | 
| -    if (NULL == device) { | 
| -        SkErrorInternals::SetError( kInternalError_SkError, | 
| -                                    "Unable to create device for layer."); | 
| -        return; | 
| +    bool forceSpriteOnRestore = false; | 
| +    { | 
| +        const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage; | 
| +        const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo); | 
| +        SkBaseDevice* newDev = device->onCreateDevice(createInfo, paint); | 
| +        if (NULL == newDev) { | 
| +            // If onCreateDevice didn't succeed, try raster (e.g. PDF couldn't handle the paint) | 
| +            newDev = SkBitmapDevice::Create(createInfo.fInfo); | 
| +            if (NULL == newDev) { | 
| +                SkErrorInternals::SetError(kInternalError_SkError, | 
| +                                           "Unable to create device for layer."); | 
| +                return; | 
| +            } | 
| +            forceSpriteOnRestore = true; | 
| +        } | 
| +        device = newDev; | 
| } | 
|  | 
| device->setOrigin(ir.fLeft, ir.fTop); | 
| -    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRasterClip)); | 
| +    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRasterClip, | 
| +                                            forceSpriteOnRestore)); | 
| device->unref(); | 
|  | 
| layer->fNext = fMCRec->fTopLayer; | 
| @@ -1043,7 +1054,7 @@ void SkCanvas::internalRestore() { | 
| if (layer->fNext) { | 
| const SkIPoint& origin = layer->fDevice->getOrigin(); | 
| this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), | 
| -                                     layer->fPaint); | 
| +                                     layer->fPaint, layer->fDeviceIsBitmapDevice); | 
| // reset this, since internalDrawDevice will have set it to true | 
| fDeviceCMDirty = true; | 
| SkDELETE(layer); | 
| @@ -1155,7 +1166,7 @@ void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, | 
| } | 
|  | 
| void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, | 
| -                                  const SkPaint* paint) { | 
| +                                  const SkPaint* paint, bool deviceIsBitmapDevice) { | 
| SkPaint tmp; | 
| if (NULL == paint) { | 
| paint = &tmp; | 
| @@ -1183,6 +1194,9 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, | 
| dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(), | 
| tmpUnfiltered); | 
| } | 
| +        } else if (deviceIsBitmapDevice) { | 
| +            const SkBitmap& src = srcDev->accessBitmap(false); | 
| +            dstDev->drawSprite(iter, src, pos.x(), pos.y(), *paint); | 
| } else { | 
| dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); | 
| } | 
|  |