Protect much of SkDevice and clarify usage of drawDevice.

http://codereview.appspot.com/4798069/



git-svn-id: http://skia.googlecode.com/svn/trunk@2066 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bungeman@google.com 2011-08-08 19:41:56 +00:00
Родитель 3f69b54d45
Коммит 88edf1e507
3 изменённых файлов: 97 добавлений и 84 удалений

Просмотреть файл

@ -16,20 +16,17 @@
#include "SkColor.h" #include "SkColor.h"
class SkClipStack; class SkClipStack;
class SkDevice;
class SkDraw; class SkDraw;
struct SkIRect; struct SkIRect;
class SkMatrix; class SkMatrix;
class SkMetaData; class SkMetaData;
class SkRegion; class SkRegion;
// This is an opaque classes, not interpreted by skia // This is an opaque class, not interpreted by skia
class SkGpuRenderTarget; class SkGpuRenderTarget;
class SK_API SkDevice : public SkRefCnt { class SK_API SkDevice : public SkRefCnt {
public: public:
// SkDevice();
/** /**
* Construct a new device with the specified bitmap as its backend. It is * Construct a new device with the specified bitmap as its backend. It is
* valid for the bitmap to have no pixels associated with it. In that case, * valid for the bitmap to have no pixels associated with it. In that case,
@ -69,6 +66,8 @@ public:
int width, int height, int width, int height,
bool isOpaque); bool isOpaque);
SkMetaData& getMetaData();
enum Capabilities { enum Capabilities {
kGL_Capability = 0x1, //!< mask indicating GL support kGL_Capability = 0x1, //!< mask indicating GL support
kVector_Capability = 0x2, //!< mask indicating a vector representation kVector_Capability = 0x2, //!< mask indicating a vector representation
@ -83,29 +82,18 @@ public:
*/ */
virtual int height() const { return fBitmap.height(); } virtual int height() const { return fBitmap.height(); }
/** /** Return the bounds of the device
* Return the device's origin: its offset in device coordinates from
* the default origin in its canvas' matrix/clip
*/
const SkIPoint& getOrigin() const { return fOrigin; }
/** Return the bitmap config of the device's pixels
*/ */
SkBitmap::Config config() const { return fBitmap.getConfig(); } void getBounds(SkIRect* bounds) const;
/** Returns true if the device's bitmap's config treats every pixels as /** Returns true if the device's bitmap's config treats every pixels as
implicitly opaque. implicitly opaque.
*/ */
bool isOpaque() const { return fBitmap.isOpaque(); } bool isOpaque() const { return fBitmap.isOpaque(); }
/** Return the bounds of the device /** Return the bitmap config of the device's pixels
*/ */
void getBounds(SkIRect* bounds) const; SkBitmap::Config config() const { return fBitmap.getConfig(); }
/** Return true if the specified rectangle intersects the bounds of the
device. If sect is not NULL and there is an intersection, sect returns
the intersection.
*/
bool intersects(const SkIRect& r, SkIRect* sect = NULL) const;
/** Return the bitmap associated with this device. Call this each time you need /** Return the bitmap associated with this device. Call this each time you need
to access the bitmap, as it notifies the subclass to perform any flushing to access the bitmap, as it notifies the subclass to perform any flushing
@ -115,27 +103,59 @@ public:
*/ */
const SkBitmap& accessBitmap(bool changePixels); const SkBitmap& accessBitmap(bool changePixels);
/** Clears the entire device to the specified color (including alpha). /**
* Ignores the clip. * Copy the pixels from the device into bitmap. Returns true on success.
* If false is returned, then the bitmap parameter is left unchanged.
* The bitmap parameter is treated as output-only, and will be completely
* overwritten (if the method returns true).
*/ */
virtual void clear(SkColor color); virtual bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
/** /**
* Deprecated name for clear. * Similar to draw sprite, this method will copy the pixels in bitmap onto
* the device, with the top/left corner specified by (x, y). The pixel
* values in the device are completely replaced: there is no blending.
*/ */
void eraseColor(SkColor eraseColor) { this->clear(eraseColor); } virtual void writePixels(const SkBitmap& bitmap, int x, int y);
/** Called when this device is installed into a Canvas. Balanaced by a call
to unlockPixels() when the device is removed from a Canvas.
*/
virtual void lockPixels();
virtual void unlockPixels();
/** /**
* Return the device's associated gpu render target, or NULL. * Return the device's associated gpu render target, or NULL.
*/ */
virtual SkGpuRenderTarget* accessRenderTarget() { return NULL; } virtual SkGpuRenderTarget* accessRenderTarget() { return NULL; }
protected:
enum Usage {
kGeneral_Usage,
kSaveLayer_Usage, // <! internal use only
};
/**
* Return the device's origin: its offset in device coordinates from
* the default origin in its canvas' matrix/clip
*/
const SkIPoint& getOrigin() const { return fOrigin; }
/** Return true if the specified rectangle intersects the bounds of the
device. If sect is not NULL and there is an intersection, sect returns
the intersection.
*/
bool intersects(const SkIRect& r, SkIRect* sect = NULL) const;
struct TextFlags {
uint32_t fFlags; // SkPaint::getFlags()
SkPaint::Hinting fHinting;
};
/**
* Device may filter the text flags for drawing text here. If it wants to
* make a change to the specified values, it should write them into the
* textflags parameter (output) and return true. If the paint is fine as
* is, then ignore the textflags parameter and return false.
*
* The baseclass SkDevice filters based on its depth and blitters.
*/
virtual bool filterTextFlags(const SkPaint& paint, TextFlags*);
/** /**
* Called with the correct matrix and clip before this device is drawn * Called with the correct matrix and clip before this device is drawn
* to using those settings. If your subclass overrides this, be sure to * to using those settings. If your subclass overrides this, be sure to
@ -157,24 +177,15 @@ public:
virtual void gainFocus(SkCanvas*, const SkMatrix&, const SkRegion&, virtual void gainFocus(SkCanvas*, const SkMatrix&, const SkRegion&,
const SkClipStack&) {} const SkClipStack&) {}
/** Causes any deferred drawing to the device to be completed. /** Clears the entire device to the specified color (including alpha).
* Ignores the clip.
*/ */
virtual void flush() {} virtual void clear(SkColor color);
/** /**
* Copy the pixels from the device into bitmap. Returns true on success. * Deprecated name for clear.
* If false is returned, then the bitmap parameter is left unchanged.
* The bitmap parameter is treated as output-only, and will be completely
* overwritten (if the method returns true).
*/ */
virtual bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap); void eraseColor(SkColor eraseColor) { this->clear(eraseColor); }
/**
* Similar to draw sprite, this method will copy the pixels in bitmap onto
* the device, with the top/left corner specified by (x, y). The pixel
* values in the device are completely replaced: there is no blending.
*/
virtual void writePixels(const SkBitmap& bitmap, int x, int y);
/** These are called inside the per-device-layer loop for each draw call. /** These are called inside the per-device-layer loop for each draw call.
When these are called, we have already applied any saveLayer operations, When these are called, we have already applied any saveLayer operations,
@ -224,47 +235,20 @@ public:
const SkColor colors[], SkXfermode* xmode, const SkColor colors[], SkXfermode* xmode,
const uint16_t indices[], int indexCount, const uint16_t indices[], int indexCount,
const SkPaint& paint); const SkPaint& paint);
/** The SkDevice passed will be an SkDevice which was returned by a call to
onCreateCompatibleDevice on this device with kSaveLayer_Usage.
*/
virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y, virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
const SkPaint&); const SkPaint&);
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
SkMetaData& getMetaData();
struct TextFlags {
uint32_t fFlags; // SkPaint::getFlags()
SkPaint::Hinting fHinting;
};
/**
* Device may filter the text flags for drawing text here. If it wants to
* make a change to the specified values, it should write them into the
* textflags parameter (output) and return true. If the paint is fine as
* is, then ignore the textflags parameter and return false.
*
* The baseclass SkDevice filters based on its depth and blitters.
*/
virtual bool filterTextFlags(const SkPaint& paint, TextFlags*);
protected:
/** Update as needed the pixel value in the bitmap, so that the caller can access /** Update as needed the pixel value in the bitmap, so that the caller can access
the pixels directly. Note: only the pixels field should be altered. The config/width/height/rowbytes the pixels directly. Note: only the pixels field should be altered. The config/width/height/rowbytes
must remain unchanged. must remain unchanged.
*/ */
virtual void onAccessBitmap(SkBitmap*); virtual void onAccessBitmap(SkBitmap*);
enum Usage {
kGeneral_Usage,
kSaveLayer_Usage, // <! internal use only
};
/**
* subclasses should override this to implement createCompatibleDevice.
*/
virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
int width, int height,
bool isOpaque,
Usage usage);
SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); } SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
// just for subclasses, to assign a custom pixelref // just for subclasses, to assign a custom pixelref
SkPixelRef* setPixelRef(SkPixelRef* pr, size_t offset) { SkPixelRef* setPixelRef(SkPixelRef* pr, size_t offset) {
@ -272,8 +256,19 @@ protected:
return pr; return pr;
} }
/** Called when this device is installed into a Canvas. Balanaced by a call
to unlockPixels() when the device is removed from a Canvas.
*/
virtual void lockPixels();
virtual void unlockPixels();
private: private:
friend class SkCanvas; friend class SkCanvas;
friend struct DeviceCM; //for setMatrixClip
friend class SkDraw;
friend class SkDrawIter;
friend class SkDeviceFilteredPaint;
// just called by SkCanvas when built as a layer // just called by SkCanvas when built as a layer
void setOrigin(int x, int y) { fOrigin.set(x, y); } void setOrigin(int x, int y) { fOrigin.set(x, y); }
// just called by SkCanvas for saveLayer // just called by SkCanvas for saveLayer
@ -281,6 +276,18 @@ private:
int width, int height, int width, int height,
bool isOpaque); bool isOpaque);
/**
* Subclasses should override this to implement createCompatibleDevice.
*/
virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
int width, int height,
bool isOpaque,
Usage usage);
/** Causes any deferred drawing to the device to be completed.
*/
virtual void flush() {}
SkBitmap fBitmap; SkBitmap fBitmap;
SkIPoint fOrigin; SkIPoint fOrigin;
SkMetaData* fMetaData; SkMetaData* fMetaData;

Просмотреть файл

@ -70,6 +70,12 @@ public:
return false; return false;
} }
virtual void setMatrixClip(const SkMatrix& m, const SkRegion& r,
const SkClipStack& c)
{
SkDevice::setMatrixClip(m, r, c);
}
/** These are called inside the per-device-layer loop for each draw call. /** These are called inside the per-device-layer loop for each draw call.
When these are called, we have already applied any saveLayer operations, When these are called, we have already applied any saveLayer operations,
and are handling any looping from the paint, and any effects from the and are handling any looping from the paint, and any effects from the

Просмотреть файл

@ -71,7 +71,7 @@ struct DeviceCM {
const SkMatrix* fMVMatrix; const SkMatrix* fMVMatrix;
const SkMatrix* fExtMatrix; const SkMatrix* fExtMatrix;
DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint) DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint)
: fNext(NULL) { : fNext(NULL) {
if (NULL != device) { if (NULL != device) {
device->ref(); device->ref();
@ -79,15 +79,15 @@ struct DeviceCM {
} }
fDevice = device; fDevice = device;
fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
} }
~DeviceCM() { ~DeviceCM() {
if (NULL != fDevice) { if (NULL != fDevice) {
fDevice->unlockPixels(); fDevice->unlockPixels();
fDevice->unref(); fDevice->unref();
} }
SkDELETE(fPaint); SkDELETE(fPaint);
} }
void updateMC(const SkMatrix& totalMatrix, const SkRegion& totalClip, void updateMC(const SkMatrix& totalMatrix, const SkRegion& totalClip,
const SkClipStack& clipStack, SkRegion* updateClip) { const SkClipStack& clipStack, SkRegion* updateClip) {
@ -163,7 +163,7 @@ public:
reference counted, since the real owner is either our fLayer field, reference counted, since the real owner is either our fLayer field,
or a previous one in a lower level.) or a previous one in a lower level.)
*/ */
DeviceCM* fTopLayer; DeviceCM* fTopLayer;
MCRec(const MCRec* prev, int flags) { MCRec(const MCRec* prev, int flags) {
if (NULL != prev) { if (NULL != prev) {
@ -749,7 +749,7 @@ void SkCanvas::internalRestore() {
fLocalBoundsCompareTypeDirtyBW = true; fLocalBoundsCompareTypeDirtyBW = true;
fClipStack.restore(); fClipStack.restore();
// reserve our layer (if any) // reserve our layer (if any)
DeviceCM* layer = fMCRec->fLayer; // may be null DeviceCM* layer = fMCRec->fLayer; // may be null
// now detach it from fMCRec so we can pop(). Gets freed after its drawn // now detach it from fMCRec so we can pop(). Gets freed after its drawn
fMCRec->fLayer = NULL; fMCRec->fLayer = NULL;
@ -772,7 +772,7 @@ void SkCanvas::internalRestore() {
fDeviceCMDirty = true; fDeviceCMDirty = true;
} }
SkDELETE(layer); SkDELETE(layer);
} }
SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1); SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1);
} }
@ -1153,7 +1153,7 @@ void SkCanvas::setExternalMatrix(const SkMatrix* matrix) {
SkDevice* SkCanvas::createLayerDevice(SkBitmap::Config config, SkDevice* SkCanvas::createLayerDevice(SkBitmap::Config config,
int width, int height, int width, int height,
bool isOpaque) { bool isOpaque) {
SkDevice* device = this->getDevice(); SkDevice* device = this->getTopDevice();
if (device) { if (device) {
return device->createCompatibleDeviceForSaveLayer(config, width, height, return device->createCompatibleDeviceForSaveLayer(config, width, height,
isOpaque); isOpaque);