/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkDeferredCanvas_DEFINED #define SkDeferredCanvas_DEFINED #include "SkCanvas.h" #include "SkDevice.h" #include "SkPicture.h" #include "SkPixelRef.h" /** \class SkDeferredCanvas Subclass of SkCanvas that encapsulates an SkPicture for deferred drawing. The main difference between this class and SkPictureRecord (the canvas provided by SkPicture) is that this is a full drop-in replacement for SkCanvas, while SkPictureRecord only supports draw operations. SkDeferredCanvas will transparently trigger the flushing of deferred draw operations when an attempt is made to access the pixel data. */ class SK_API SkDeferredCanvas : public SkCanvas { public: class DeviceContext; SkDeferredCanvas(); /** Construct a canvas with the specified device to draw into. Equivalent to calling default constructor, then setDevice. @param device Specifies a device for the canvas to draw into. */ explicit SkDeferredCanvas(SkDevice* device); /** Construct a canvas with the specified device to draw into, and * a device context. Equivalent to calling default constructor, then * setDevice. * @param device Specifies a device for the canvas to draw into. * @param deviceContext interface for the device's the graphics context */ explicit SkDeferredCanvas(SkDevice* device, DeviceContext* deviceContext); virtual ~SkDeferredCanvas(); /** * Specify a device to be used by this canvas. Calling setDevice will * release the previously set device, if any. * * @param device The device that the canvas will raw into * @return The device argument, for convenience. */ virtual SkDevice* setDevice(SkDevice* device); /** * Specify a deviceContext to be used by this canvas. Calling * setDeviceContext will release the previously set deviceContext, if any. * A deviceContext must be specified if the device uses a graphics context * that requires some form of state initialization prior to drawing * and/or explicit flushing to synchronize the execution of rendering * operations. * Note: Must be called after the device is set with setDevice. * * @deviceContext interface for the device's the graphics context * @return The deviceContext argument, for convenience. */ DeviceContext* setDeviceContext(DeviceContext* deviceContext); /** * Enable or disable deferred drawing. When deferral is disabled, * pending draw operations are immediately flushed and from then on, * the SkDeferredCanvas behaves just like a regular SkCanvas. * This method must not be called while the save/restore stack is in use. * @param deferred true/false */ void setDeferredDrawing(bool deferred); // Overrides of the SkCanvas interface virtual int save(SaveFlags flags) SK_OVERRIDE; virtual int saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) SK_OVERRIDE; virtual void restore() SK_OVERRIDE; virtual int getSaveCount() const SK_OVERRIDE; virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE; virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE; virtual bool rotate(SkScalar degrees) SK_OVERRIDE; virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE; virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE; virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE; virtual const SkMatrix& getTotalMatrix() const SK_OVERRIDE; virtual bool clipRect(const SkRect& rect, SkRegion::Op op, bool doAntiAlias) SK_OVERRIDE; virtual bool clipPath(const SkPath& path, SkRegion::Op op, bool doAntiAlias) SK_OVERRIDE; virtual bool clipRegion(const SkRegion& deviceRgn, SkRegion::Op op) SK_OVERRIDE; virtual void clear(SkColor) SK_OVERRIDE; virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE; virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) SK_OVERRIDE; virtual void drawRect(const SkRect& rect, const SkPaint& paint) SK_OVERRIDE; virtual void drawPath(const SkPath& path, const SkPaint& paint) SK_OVERRIDE; virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint* paint) SK_OVERRIDE; virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, const SkRect& dst, const SkPaint* paint) SK_OVERRIDE; virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, const SkPaint* paint) SK_OVERRIDE; virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint) SK_OVERRIDE; virtual void drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) SK_OVERRIDE; virtual void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) SK_OVERRIDE; virtual void drawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkPaint& paint) SK_OVERRIDE; virtual void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkPaint& paint) SK_OVERRIDE; virtual void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) SK_OVERRIDE; virtual void drawPicture(SkPicture& picture) SK_OVERRIDE; virtual void drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[], const SkPoint texs[], const SkColor colors[], SkXfermode* xmode, const uint16_t indices[], int indexCount, const SkPaint& paint) SK_OVERRIDE; virtual SkBounder* setBounder(SkBounder* bounder) SK_OVERRIDE; virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE; private: void flushIfNeeded(const SkBitmap& bitmap); public: class DeviceContext : public SkRefCnt { public: virtual void prepareForDraw() {} }; public: class DeferredDevice : public SkDevice { public: /** * Constructor * @param immediateDevice device to be drawn to when flushing * deferred operations * @param deviceContext callback interface for managing graphics * context state, can be NULL. */ DeferredDevice(SkDevice* immediateDevice, DeviceContext* deviceContext = NULL); ~DeferredDevice(); /** * Sets the device context to be use with the device. * @param deviceContext callback interface for managing graphics * context state, can be NULL. */ void setDeviceContext(DeviceContext* deviceContext); /** * Returns the recording canvas. */ SkCanvas* recordingCanvas() const {return fRecordingCanvas;} /** * Returns the immediate (non deferred) canvas. */ SkCanvas* immediateCanvas() const {return fImmediateCanvas;} /** * Returns the immediate (non deferred) device. */ SkDevice* immediateDevice() const {return fImmediateDevice;} void flushPending(); void purgePending(); void flushIfNeeded(const SkBitmap& bitmap); virtual uint32_t getDeviceCapabilities() SK_OVERRIDE; virtual int width() const SK_OVERRIDE; virtual int height() const SK_OVERRIDE; virtual SkGpuRenderTarget* accessRenderTarget() SK_OVERRIDE; virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config, int width, int height, bool isOpaque, Usage usage) SK_OVERRIDE; virtual void writePixels(const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) SK_OVERRIDE; protected: virtual const SkBitmap& onAccessBitmap(SkBitmap*) SK_OVERRIDE; virtual bool onReadPixels(const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) SK_OVERRIDE; // The following methods are no-ops on a deferred device virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {return false;} 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 virtual void clear(SkColor color) {SkASSERT(0);} virtual void drawPaint(const SkDraw&, const SkPaint& paint) {SkASSERT(0);} virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count, const SkPoint[], const SkPaint& paint) {SkASSERT(0);} virtual void drawRect(const SkDraw&, const SkRect& r, const SkPaint& paint) {SkASSERT(0);} virtual void drawPath(const SkDraw&, const SkPath& path, const SkPaint& paint, const SkMatrix* prePathMatrix = NULL, bool pathIsMutable = false) {SkASSERT(0);} virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap, const SkIRect* srcRectOrNull, const SkMatrix& matrix, const SkPaint& paint) {SkASSERT(0);} virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, int x, int y, const SkPaint& paint) {SkASSERT(0);} virtual void drawText(const SkDraw&, const void* text, size_t len, SkScalar x, SkScalar y, const SkPaint& paint) {SkASSERT(0);} virtual void drawPosText(const SkDraw&, const void* text, size_t len, const SkScalar pos[], SkScalar constY, int scalarsPerPos, const SkPaint& paint) {SkASSERT(0);} virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len, const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) {SkASSERT(0);} virtual void drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len, const SkPoint pos[], const SkPaint& paint, const SkPath& path, const SkMatrix* matrix) {SkASSERT(0);} virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount, const SkPoint verts[], const SkPoint texs[], const SkColor colors[], SkXfermode* xmode, const uint16_t indices[], int indexCount, const SkPaint& paint) {SkASSERT(0);} virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y, const SkPaint&) {SkASSERT(0);} private: virtual void flush(); SkPicture fPicture; SkDevice* fImmediateDevice; SkCanvas* fImmediateCanvas; SkCanvas* fRecordingCanvas; DeviceContext* fDeviceContext; bool fBitmapInitialized; }; DeferredDevice* getDeferredDevice() const; protected: virtual SkCanvas* canvasForDrawIter(); private: SkCanvas* drawingCanvas() const; bool isFullFrame(const SkRect*, const SkPaint*) const; void validate() const; void init(); bool fDeferredDrawing; typedef SkCanvas INHERITED; }; #endif