Chromium Code Reviews| Index: src/core/SkCanvas.cpp |
| diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp |
| index 6beb26e4cad9c42d70b99e44f7d62f867a15e222..0075586f752330dc60b463e8775be5fefba8a2ec 100644 |
| --- a/src/core/SkCanvas.cpp |
| +++ b/src/core/SkCanvas.cpp |
| @@ -67,6 +67,19 @@ void SkCanvas::predrawNotify() { |
| /////////////////////////////////////////////////////////////////////////////// |
| +static uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) { |
| + const uint32_t propFlags = props.flags(); |
| + if (propFlags & SkSurfaceProps::kDisallowDither_Flag) { |
| + flags &= ~SkPaint::kDither_Flag; |
| + } |
| + if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) { |
| + flags &= ~SkPaint::kAntiAlias_Flag; |
| + } |
| + return flags; |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| /* This is the record we keep for each SkBaseDevice that the user installs. |
| The clip/matrix/proc are fields that reflect the top of the save/restore |
| stack. Whenever the canvas changes, it marks a dirty flag, and then before |
| @@ -250,12 +263,12 @@ private: |
| class AutoDrawLooper { |
| public: |
| - AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, |
| + AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint, |
| bool skipLayerForImageFilter = false, |
| const SkRect* bounds = NULL) : fOrigPaint(paint) { |
| fCanvas = canvas; |
| fFilter = canvas->getDrawFilter(); |
| - fPaint = NULL; |
| + fPaint = &fOrigPaint; |
|
bsalomon
2014/09/18 18:43:33
SkTCopyOnFirstWrite?
reed1
2014/09/18 21:03:12
? fPaint is a pointer, so this line is free.
bsalomon
2014/09/18 21:20:24
Init'ing a SkTCopyOnFirstWrite isn't costly and it
|
| fSaveCount = canvas->getSaveCount(); |
| fDoClearImageFilter = false; |
| fDone = false; |
| @@ -280,6 +293,15 @@ public: |
| // can we be marked as simple? |
| fIsSimple = !fFilter && !fDoClearImageFilter; |
| } |
| + |
| + uint32_t oldFlags = paint.getFlags(); |
| + fNewPaintFlags = filter_paint_flags(props, oldFlags); |
| + if (fIsSimple && (fNewPaintFlags != oldFlags)) { |
| + SkPaint* paint = fLazyPaint.set(fOrigPaint); |
|
bsalomon
2014/09/18 18:43:33
fPaint->writable()->setFlags(fNewPaintFlags);
|
| + paint->setFlags(fNewPaintFlags); |
| + fPaint = paint; |
| + // if we're not simple, doNext() will take care of calling setFlags() |
| + } |
| } |
| ~AutoDrawLooper() { |
| @@ -299,7 +321,6 @@ public: |
| return false; |
| } else if (fIsSimple) { |
| fDone = true; |
| - fPaint = &fOrigPaint; |
| return !fPaint->nothingToDraw(); |
| } else { |
| return this->doNext(drawType); |
| @@ -313,6 +334,7 @@ private: |
| SkDrawFilter* fFilter; |
| const SkPaint* fPaint; |
| int fSaveCount; |
| + uint32_t fNewPaintFlags; |
| bool fDoClearImageFilter; |
| bool fDone; |
| bool fIsSimple; |
| @@ -328,6 +350,7 @@ bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { |
| SkASSERT(fLooperContext || fFilter || fDoClearImageFilter); |
| SkPaint* paint = fLazyPaint.set(fOrigPaint); |
| + paint->setFlags(fNewPaintFlags); |
| if (fDoClearImageFilter) { |
| paint->setImageFilter(NULL); |
| @@ -363,18 +386,19 @@ bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { |
| } |
| #include "SkColorPriv.h" |
| +#include "SkDeviceProperties.h" |
| ////////// macros to place around the internal draw calls ////////////////// |
| #define LOOPER_BEGIN_DRAWDEVICE(paint, type) \ |
| this->predrawNotify(); \ |
| - AutoDrawLooper looper(this, paint, true); \ |
| + AutoDrawLooper looper(this, fProps, paint, true); \ |
| while (looper.next(type)) { \ |
| SkDrawIter iter(this); |
| #define LOOPER_BEGIN(paint, type, bounds) \ |
| this->predrawNotify(); \ |
| - AutoDrawLooper looper(this, paint, false, bounds); \ |
| + AutoDrawLooper looper(this, fProps, paint, false, bounds); \ |
| while (looper.next(type)) { \ |
| SkDrawIter iter(this); |
| @@ -382,6 +406,10 @@ bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { |
| //////////////////////////////////////////////////////////////////////////// |
| +void SkCanvas::setupDevice(SkBaseDevice* device) { |
| + device->setPixelGeometry(fProps.pixelGeometry()); |
| +} |
| + |
| SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { |
| fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag); |
| fCachedLocalClipBounds.setEmpty(); |
| @@ -393,10 +421,6 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { |
| fCullCount = 0; |
| fMetaData = NULL; |
| - if (device && device->forceConservativeRasterClip()) { |
| - fConservativeRasterClip = true; |
| - } |
| - |
| fMCRec = (MCRec*)fMCStack.push_back(); |
| new (fMCRec) MCRec(fConservativeRasterClip); |
| @@ -406,6 +430,10 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { |
| fSurfaceBase = NULL; |
| if (device) { |
| + this->setupDevice(device); |
| + if (device->forceConservativeRasterClip()) { |
| + fConservativeRasterClip = true; |
| + } |
| device->onAttachToCanvas(this); |
| fMCRec->fLayer->fDevice = SkRef(device); |
| fMCRec->fRasterClip.setRect(SkIRect::MakeWH(device->width(), device->height())); |
| @@ -415,6 +443,7 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { |
| SkCanvas::SkCanvas() |
| : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
| + , fProps(SkSurfaceProps::kLegacyFontHost_InitType) |
| { |
| inc_canvas(); |
| @@ -436,8 +465,17 @@ private: |
| typedef SkBitmapDevice INHERITED; |
| }; |
| +static SkSurfaceProps props_or_default(const SkSurfaceProps* props) { |
| + if (props) { |
| + return *props; |
| + } else { |
| + return SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType); |
| + } |
| +} |
| + |
| SkCanvas::SkCanvas(int width, int height) |
| : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
| + , fProps(SkSurfaceProps::kLegacyFontHost_InitType) |
| { |
| inc_canvas(); |
| @@ -446,14 +484,16 @@ SkCanvas::SkCanvas(int width, int height) |
| SkCanvas::SkCanvas(int width, int height, InitFlags flags) |
| : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
| + , fProps(SkSurfaceProps::kLegacyFontHost_InitType) |
| { |
| inc_canvas(); |
| this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (width, height)), flags)->unref(); |
| } |
| -SkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags) |
| +SkCanvas::SkCanvas(SkBaseDevice* device, const SkSurfaceProps* props, InitFlags flags) |
| : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
| + , fProps(props_or_default(props)) |
| { |
| inc_canvas(); |
| @@ -462,18 +502,31 @@ SkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags) |
| SkCanvas::SkCanvas(SkBaseDevice* device) |
| : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
| + , fProps(SkSurfaceProps::kLegacyFontHost_InitType) |
| { |
| inc_canvas(); |
| this->init(device, kDefault_InitFlags); |
| } |
| -SkCanvas::SkCanvas(const SkBitmap& bitmap) |
| +SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props) |
| : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
| + , fProps(props) |
| { |
| inc_canvas(); |
| + |
| + SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap))); |
| + this->init(device, kDefault_InitFlags); |
| +} |
| - this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)), kDefault_InitFlags)->unref(); |
| +SkCanvas::SkCanvas(const SkBitmap& bitmap) |
| + : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
| + , fProps(SkSurfaceProps::kLegacyFontHost_InitType) |
| +{ |
| + inc_canvas(); |
| + |
| + SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap))); |
| + this->init(device, kDefault_InitFlags); |
| } |
| SkCanvas::~SkCanvas() { |
| @@ -564,6 +617,7 @@ SkBaseDevice* SkCanvas::setRootDevice(SkBaseDevice* device) { |
| SkRefCnt_SafeAssign(rec->fLayer->fDevice, device); |
| rootDevice = device; |
| + this->setupDevice(device); |
| fDeviceCMDirty = true; |
| @@ -899,6 +953,7 @@ int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Save |
| SkDebugf("Unable to create device for layer."); |
| return count; |
| } |
| + this->setupDevice(device); |
| device->setOrigin(ir.fLeft, ir.fTop); |
| DeviceCM* layer = SkNEW_ARGS(DeviceCM, |