aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkCanvas.h12
-rw-r--r--include/core/SkDevice.h35
-rw-r--r--include/gpu/SkGpuDevice.h9
-rw-r--r--include/pdf/SkPDFDevice.h9
-rw-r--r--include/utils/SkDeferredCanvas.h3
-rw-r--r--src/core/SkCanvas.cpp24
-rw-r--r--src/core/SkDevice.cpp13
-rw-r--r--src/gpu/SkGpuDevice.cpp40
-rw-r--r--src/pdf/SkPDFDevice.cpp19
9 files changed, 124 insertions, 40 deletions
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index fc95f9ae6c..8fa73f6ac1 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -888,6 +888,15 @@ public:
*/
const SkRegion& getTotalClip() const;
+ /** Return the clip stack. The clip stack stores all the individual
+ * clips organized by the save/restore frame in which they were
+ * added.
+ * @return the current clip stack ("list" of individual clip elements)
+ */
+ const SkClipStack* getClipStack() const {
+ return &fClipStack;
+ }
+
void setExternalMatrix(const SkMatrix* = NULL);
class ClipVisitor {
@@ -973,8 +982,7 @@ private:
SkDevice* fLastDeviceToGainFocus;
int fSaveLayerCount; // number of successful saveLayer calls
- void prepareForDeviceDraw(SkDevice*, const SkMatrix&, const SkRegion&,
- const SkClipStack& clipStack);
+ void prepareForDeviceDraw(SkDevice*, const SkMatrix&, const SkRegion&);
bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
void updateDeviceCMCache();
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 184fb6f3bd..5cf5c502c5 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -138,6 +138,32 @@ public:
*/
const SkIPoint& getOrigin() const { return fOrigin; }
+ /**
+ * onAttachToCanvas is invoked whenever a device is installed in a canvas
+ * (i.e., setDevice, saveLayer (for the new device created by the save),
+ * and SkCanvas' SkDevice & SkBitmap -taking ctors). It allows the
+ * devices to prepare for drawing (e.g., locking their pixels, etc.)
+ */
+ virtual void onAttachToCanvas(SkCanvas* canvas) {
+ this->lockPixels();
+#ifdef SK_DEBUG
+ fAttachedToCanvas = true;
+#endif
+ };
+
+ /**
+ * onDetachFromCanvas notifies a device that it will no longer be drawn to.
+ * It gives the device a chance to clean up (e.g., unlock its pixels). It
+ * is invoked from setDevice (for the displaced device), restore and
+ * possibly from SkCanvas' dtor.
+ */
+ virtual void onDetachFromCanvas() {
+ this->unlockPixels();
+#ifdef SK_DEBUG
+ fAttachedToCanvas = false;
+#endif
+ };
+
protected:
enum Usage {
kGeneral_Usage,
@@ -177,8 +203,9 @@ protected:
/** Called when this device gains focus (i.e becomes the current device
for drawing).
*/
- virtual void gainFocus(SkCanvas*, const SkMatrix&, const SkRegion&,
- const SkClipStack&) {}
+ virtual void gainFocus(const SkMatrix&, const SkRegion&) {
+ SkASSERT(fAttachedToCanvas);
+ }
/** Clears the entire device to the specified color (including alpha).
* Ignores the clip.
@@ -376,6 +403,10 @@ private:
SkIPoint fOrigin;
SkMetaData* fMetaData;
+#ifdef SK_DEBUG
+ bool fAttachedToCanvas;
+#endif
+
typedef SkRefCnt INHERITED;
};
diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h
index 40444a975c..2390cdb44c 100644
--- a/include/gpu/SkGpuDevice.h
+++ b/include/gpu/SkGpuDevice.h
@@ -55,8 +55,7 @@ public:
* Override from SkGpuDevice, so we can set our FBO to be the render target
* The canvas parameter must be a SkGpuCanvas
*/
- virtual void gainFocus(SkCanvas*, const SkMatrix&, const SkRegion&,
- const SkClipStack& clipStack) SK_OVERRIDE;
+ virtual void gainFocus(const SkMatrix&, const SkRegion&) SK_OVERRIDE;
virtual SkGpuRenderTarget* accessRenderTarget() SK_OVERRIDE;
@@ -101,6 +100,9 @@ public:
virtual void flush();
+ virtual void onAttachToCanvas(SkCanvas* canvas) SK_OVERRIDE;
+ virtual void onDetachFromCanvas() SK_OVERRIDE;
+
/**
* Make's this device's rendertarget current in the underlying 3D API.
* Also implicitly flushes.
@@ -131,6 +133,9 @@ private:
GrSkDrawProcs* fDrawProcs;
+ // the clip stack - on loan to us from SkCanvas so it can be NULL.
+ const SkClipStack* fClipStack;
+
// state for our offscreen render-target
TexCache fCache;
GrTexture* fTexture;
diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h
index 354729d7c5..589cde965f 100644
--- a/include/pdf/SkPDFDevice.h
+++ b/include/pdf/SkPDFDevice.h
@@ -100,6 +100,9 @@ public:
virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
const SkPaint&) SK_OVERRIDE;
+ virtual void onAttachToCanvas(SkCanvas* canvas) SK_OVERRIDE;
+ virtual void onDetachFromCanvas() SK_OVERRIDE;
+
enum DrawingArea {
kContent_DrawingArea, // Drawing area for the page content.
kMargin_DrawingArea, // Drawing area for the margin content.
@@ -190,6 +193,8 @@ private:
ContentEntry* fLastMarginContentEntry;
DrawingArea fDrawingArea;
+ const SkClipStack* fClipStack;
+
// Accessor and setter functions based on the current DrawingArea.
SkTScopedPtr<ContentEntry>* getContentEntries();
ContentEntry* getLastContentEntry();
@@ -258,9 +263,7 @@ private:
*/
void copyContentEntriesToData(ContentEntry* entry, SkWStream* data) const;
- // Disable the default copy and assign implementation.
- SkPDFDevice(const SkPDFDevice&);
- void operator=(const SkPDFDevice&);
+ typedef SkDevice INHERITED;
};
#endif
diff --git a/include/utils/SkDeferredCanvas.h b/include/utils/SkDeferredCanvas.h
index dd2c1f0c4a..8964e9e20a 100644
--- a/include/utils/SkDeferredCanvas.h
+++ b/include/utils/SkDeferredCanvas.h
@@ -221,9 +221,6 @@ public:
virtual void setMatrixClip(const SkMatrix&, const SkRegion&,
const SkClipStack&) SK_OVERRIDE
{}
- virtual void gainFocus(SkCanvas*, const SkMatrix&, const SkRegion&,
- const SkClipStack&) SK_OVERRIDE
- {}
// None of the following drawing methods should ever get called on the
// deferred device
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 7d1ecbf8e9..c40275d5f8 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -78,11 +78,11 @@ struct DeviceCM {
const SkMatrix* fMVMatrix;
const SkMatrix* fExtMatrix;
- DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint)
+ DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas)
: fNext(NULL) {
if (NULL != device) {
device->ref();
- device->lockPixels();
+ device->onAttachToCanvas(canvas);
}
fDevice = device;
fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
@@ -90,7 +90,7 @@ struct DeviceCM {
~DeviceCM() {
if (NULL != fDevice) {
- fDevice->unlockPixels();
+ fDevice->onDetachFromCanvas();
fDevice->unref();
}
SkDELETE(fPaint);
@@ -256,7 +256,7 @@ public:
}
// fCurrLayer may be NULL now
- fCanvas->prepareForDeviceDraw(fDevice, *fMatrix, *fClip, *fClipStack);
+ fCanvas->prepareForDeviceDraw(fDevice, *fMatrix, *fClip);
return true;
}
return false;
@@ -460,7 +460,7 @@ SkDevice* SkCanvas::init(SkDevice* device) {
fMCRec = (MCRec*)fMCStack.push_back();
new (fMCRec) MCRec(NULL, 0);
- fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL));
+ fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL));
fMCRec->fTopLayer = fMCRec->fLayer;
fMCRec->fNext = NULL;
@@ -558,14 +558,11 @@ SkDevice* SkCanvas::setDevice(SkDevice* device) {
return device;
}
- /* Notify the devices that they are going in/out of scope, so they can do
- things like lock/unlock their pixels, etc.
- */
if (device) {
- device->lockPixels();
+ device->onAttachToCanvas(this);
}
if (rootDevice) {
- rootDevice->unlockPixels();
+ rootDevice->onDetachFromCanvas();
}
SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
@@ -682,11 +679,10 @@ void SkCanvas::updateDeviceCMCache() {
}
void SkCanvas::prepareForDeviceDraw(SkDevice* device, const SkMatrix& matrix,
- const SkRegion& clip,
- const SkClipStack& clipStack) {
+ const SkRegion& clip) {
SkASSERT(device);
if (fLastDeviceToGainFocus != device) {
- device->gainFocus(this, matrix, clip, clipStack);
+ device->gainFocus(matrix, clip);
fLastDeviceToGainFocus = device;
}
}
@@ -843,7 +839,7 @@ int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
}
device->setOrigin(ir.fLeft, ir.fTop);
- DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint));
+ DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, this));
device->unref();
layer->fNext = fMCRec->fTopLayer;
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 95664c88b5..4cd9310121 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -20,12 +20,21 @@ SK_DEFINE_INST_COUNT(SkDevice)
///////////////////////////////////////////////////////////////////////////////
-SkDevice::SkDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {
+SkDevice::SkDevice(const SkBitmap& bitmap)
+ : fBitmap(bitmap)
+#ifdef SK_DEBUG
+ , fAttachedToCanvas(false)
+#endif
+{
fOrigin.setZero();
fMetaData = NULL;
}
-SkDevice::SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque) {
+SkDevice::SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque)
+#ifdef SK_DEBUG
+ : fAttachedToCanvas(false)
+#endif
+{
fOrigin.setZero();
fMetaData = NULL;
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 11543136a6..6443fa28e7 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -165,12 +165,14 @@ static SkBitmap make_bitmap(GrContext* context, GrRenderTarget* renderTarget) {
}
SkGpuDevice::SkGpuDevice(GrContext* context, GrTexture* texture)
-: SkDevice(make_bitmap(context, texture->asRenderTarget())) {
+: SkDevice(make_bitmap(context, texture->asRenderTarget()))
+, fClipStack(NULL) {
this->initFromRenderTarget(context, texture->asRenderTarget());
}
SkGpuDevice::SkGpuDevice(GrContext* context, GrRenderTarget* renderTarget)
-: SkDevice(make_bitmap(context, renderTarget)) {
+: SkDevice(make_bitmap(context, renderTarget))
+, fClipStack(NULL) {
this->initFromRenderTarget(context, renderTarget);
}
@@ -211,7 +213,8 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
SkBitmap::Config config,
int width,
int height)
- : SkDevice(config, width, height, false /*isOpaque*/) {
+ : SkDevice(config, width, height, false /*isOpaque*/)
+ , fClipStack(NULL) {
fNeedPrepareRenderTarget = false;
fDrawProcs = NULL;
@@ -342,6 +345,19 @@ void SkGpuDevice::writePixels(const SkBitmap& bitmap, int x, int y,
config, bitmap.getPixels(), bitmap.rowBytes());
}
+void SkGpuDevice::onAttachToCanvas(SkCanvas* canvas) {
+ INHERITED::onAttachToCanvas(canvas);
+
+ // Canvas promises that this ptr is valid until onDetachFromCanvas is called
+ fClipStack = canvas->getClipStack();
+}
+
+void SkGpuDevice::onDetachFromCanvas() {
+ INHERITED::onDetachFromCanvas();
+
+ fClipStack = NULL;
+}
+
///////////////////////////////////////////////////////////////////////////////
static void convert_matrixclip(GrContext* context, const SkMatrix& matrix,
@@ -366,13 +382,15 @@ static void convert_matrixclip(GrContext* context, const SkMatrix& matrix,
// call this ever each draw call, to ensure that the context reflects our state,
// and not the state from some other canvas/device
void SkGpuDevice::prepareRenderTarget(const SkDraw& draw) {
+ GrAssert(NULL != fClipStack);
+
if (fNeedPrepareRenderTarget ||
fContext->getRenderTarget() != fRenderTarget) {
fContext->setRenderTarget(fRenderTarget);
- SkASSERT(draw.fClipStack);
+ SkASSERT(draw.fClipStack && draw.fClipStack == fClipStack);
convert_matrixclip(fContext, *draw.fMatrix,
- *draw.fClipStack, *draw.fClip, this->getOrigin());
+ *fClipStack, *draw.fClip, this->getOrigin());
fNeedPrepareRenderTarget = false;
}
}
@@ -384,14 +402,15 @@ void SkGpuDevice::setMatrixClip(const SkMatrix& matrix, const SkRegion& clip,
fNeedPrepareRenderTarget = true;
}
-void SkGpuDevice::gainFocus(SkCanvas* canvas, const SkMatrix& matrix,
- const SkRegion& clip, const SkClipStack& clipStack) {
+void SkGpuDevice::gainFocus(const SkMatrix& matrix, const SkRegion& clip) {
+
+ GrAssert(NULL != fClipStack);
fContext->setRenderTarget(fRenderTarget);
- this->INHERITED::gainFocus(canvas, matrix, clip, clipStack);
+ this->INHERITED::gainFocus(matrix, clip);
- convert_matrixclip(fContext, matrix, clipStack, clip, this->getOrigin());
+ convert_matrixclip(fContext, matrix, *fClipStack, clip, this->getOrigin());
DO_DEFERRED_CLEAR;
}
@@ -1964,7 +1983,8 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
GrTexture* texture,
TexCache cacheEntry,
bool needClear)
- : SkDevice(make_bitmap(context, texture->asRenderTarget())) {
+ : SkDevice(make_bitmap(context, texture->asRenderTarget()))
+ , fClipStack(NULL) {
GrAssert(texture && texture->asRenderTarget());
GrAssert(NULL == cacheEntry.texture() || texture == cacheEntry.texture());
this->initFromRenderTarget(context, texture->asRenderTarget());
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index d05b640682..55aae8dd56 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -514,7 +514,8 @@ SkPDFDevice::SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
fPageSize(pageSize),
fContentSize(contentSize),
fLastContentEntry(NULL),
- fLastMarginContentEntry(NULL) {
+ fLastMarginContentEntry(NULL),
+ fClipStack(NULL) {
// Skia generally uses the top left as the origin but PDF natively has the
// origin at the bottom left. This matrix corrects for that. But that only
// needs to be done once, we don't do it when layering.
@@ -538,7 +539,8 @@ SkPDFDevice::SkPDFDevice(const SkISize& layerSize,
fExistingClipStack(existingClipStack),
fExistingClipRegion(existingClipRegion),
fLastContentEntry(NULL),
- fLastMarginContentEntry(NULL) {
+ fLastMarginContentEntry(NULL),
+ fClipStack(NULL) {
fInitialTransform.reset();
this->init();
}
@@ -945,6 +947,19 @@ void SkPDFDevice::drawDevice(const SkDraw& d, SkDevice* device, int x, int y,
fFontGlyphUsage->merge(pdfDevice->getFontGlyphUsage());
}
+void SkPDFDevice::onAttachToCanvas(SkCanvas* canvas) {
+ INHERITED::onAttachToCanvas(canvas);
+
+ // Canvas promises that this ptr is valid until onDetachFromCanvas is called
+ fClipStack = canvas->getClipStack();
+}
+
+void SkPDFDevice::onDetachFromCanvas() {
+ INHERITED::onDetachFromCanvas();
+
+ fClipStack = NULL;
+}
+
ContentEntry* SkPDFDevice::getLastContentEntry() {
if (fDrawingArea == kContent_DrawingArea) {
return fLastContentEntry;