Chromium Code Reviews| Index: src/core/SkCanvas.cpp |
| diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp |
| index 0bd9eb357944bf4de88f101f68382cbf68ecab07..0cec1da4b75d2bb64a2e92a704eaf2ef0bccc1a3 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; |
| @@ -983,16 +983,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) { |
|
robertphillips
2015/04/29 14:55:54
"If device creation didn't succeed," ?
"If device
reed1
2015/04/29 15:20:47
Done.
|
| + // If the device didn't success, try raster (e.g. PDF perhaps 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; |
| @@ -1041,7 +1052,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); |
| @@ -1153,7 +1164,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; |
| @@ -1181,6 +1192,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); |
| } |