1/*
2 * Copyright 2010 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkDevice_DEFINED
9#define SkDevice_DEFINED
10
11#include "SkRefCnt.h"
12#include "SkBitmap.h"
13#include "SkCanvas.h"
14#include "SkColor.h"
15#include "SkImageFilter.h"
16
17class SkClipStack;
18class SkDraw;
19struct SkIRect;
20class SkMatrix;
21class SkMetaData;
22class SkRegion;
23struct SkDeviceProperties;
24class GrRenderTarget;
25
26class SK_API SkBaseDevice : public SkRefCnt {
27public:
28    SK_DECLARE_INST_COUNT(SkBaseDevice)
29
30    /**
31     *  Construct a new device.
32    */
33    SkBaseDevice();
34    virtual ~SkBaseDevice();
35
36    SkBaseDevice* createCompatibleDevice(const SkImageInfo&);
37
38    SkMetaData& getMetaData();
39
40    /**
41     *  Return ImageInfo for this device. If the canvas is not backed by pixels
42     *  (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
43     */
44    virtual SkImageInfo imageInfo() const;
45
46    /**
47     *  Return the bounds of the device in the coordinate space of the root
48     *  canvas. The root device will have its top-left at 0,0, but other devices
49     *  such as those associated with saveLayer may have a non-zero origin.
50     */
51    void getGlobalBounds(SkIRect* bounds) const {
52        SkASSERT(bounds);
53        const SkIPoint& origin = this->getOrigin();
54        bounds->setXYWH(origin.x(), origin.y(), this->width(), this->height());
55    }
56
57    int width() const {
58        return this->imageInfo().width();
59    }
60
61    int height() const {
62        return this->imageInfo().height();
63    }
64
65    bool isOpaque() const {
66        return this->imageInfo().isOpaque();
67    }
68
69    /** Return the bitmap associated with this device. Call this each time you need
70        to access the bitmap, as it notifies the subclass to perform any flushing
71        etc. before you examine the pixels.
72        @param changePixels set to true if the caller plans to change the pixels
73        @return the device's bitmap
74    */
75    const SkBitmap& accessBitmap(bool changePixels);
76
77    bool writePixels(const SkImageInfo&, const void*, size_t rowBytes, int x, int y);
78
79    void* accessPixels(SkImageInfo* info, size_t* rowBytes);
80
81    /**
82     * Return the device's associated gpu render target, or NULL.
83     */
84    virtual GrRenderTarget* accessRenderTarget() { return NULL; }
85
86
87    /**
88     *  Return the device's origin: its offset in device coordinates from
89     *  the default origin in its canvas' matrix/clip
90     */
91    const SkIPoint& getOrigin() const { return fOrigin; }
92
93    /**
94     * onAttachToCanvas is invoked whenever a device is installed in a canvas
95     * (i.e., setDevice, saveLayer (for the new device created by the save),
96     * and SkCanvas' SkBaseDevice & SkBitmap -taking ctors). It allows the
97     * devices to prepare for drawing (e.g., locking their pixels, etc.)
98     */
99    virtual void onAttachToCanvas(SkCanvas*) {
100        SkASSERT(!fAttachedToCanvas);
101        this->lockPixels();
102#ifdef SK_DEBUG
103        fAttachedToCanvas = true;
104#endif
105    };
106
107    /**
108     * onDetachFromCanvas notifies a device that it will no longer be drawn to.
109     * It gives the device a chance to clean up (e.g., unlock its pixels). It
110     * is invoked from setDevice (for the displaced device), restore and
111     * possibly from SkCanvas' dtor.
112     */
113    virtual void onDetachFromCanvas() {
114        SkASSERT(fAttachedToCanvas);
115        this->unlockPixels();
116#ifdef SK_DEBUG
117        fAttachedToCanvas = false;
118#endif
119    };
120
121protected:
122    enum Usage {
123       kGeneral_Usage,
124       kSaveLayer_Usage,  // <! internal use only
125       kImageFilter_Usage // <! internal use only
126    };
127
128    struct TextFlags {
129        uint32_t    fFlags;     // SkPaint::getFlags()
130    };
131
132    /**
133     *  Device may filter the text flags for drawing text here. If it wants to
134     *  make a change to the specified values, it should write them into the
135     *  textflags parameter (output) and return true. If the paint is fine as
136     *  is, then ignore the textflags parameter and return false.
137     */
138    virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) { return false; }
139
140    /**
141     *
142     *  DEPRECATED: This will be removed in a future change. Device subclasses
143     *  should use the matrix and clip from the SkDraw passed to draw functions.
144     *
145     *  Called with the correct matrix and clip before this device is drawn
146     *  to using those settings. If your subclass overrides this, be sure to
147     *  call through to the base class as well.
148     *
149     *  The clipstack is another view of the clip. It records the actual
150     *  geometry that went into building the region. It is present for devices
151     *  that want to parse it, but is not required: the region is a complete
152     *  picture of the current clip. (i.e. if you regionize all of the geometry
153     *  in the clipstack, you will arrive at an equivalent region to the one
154     *  passed in).
155     */
156     virtual void setMatrixClip(const SkMatrix&, const SkRegion&,
157                                const SkClipStack&) {};
158
159    /** Clears the entire device to the specified color (including alpha).
160     *  Ignores the clip.
161     */
162    virtual void clear(SkColor color) = 0;
163
164    SK_ATTR_DEPRECATED("use clear() instead")
165    void eraseColor(SkColor eraseColor) { this->clear(eraseColor); }
166
167    /** These are called inside the per-device-layer loop for each draw call.
168     When these are called, we have already applied any saveLayer operations,
169     and are handling any looping from the paint, and any effects from the
170     DrawFilter.
171     */
172    virtual void drawPaint(const SkDraw&, const SkPaint& paint) = 0;
173    virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count,
174                            const SkPoint[], const SkPaint& paint) = 0;
175    virtual void drawRect(const SkDraw&, const SkRect& r,
176                          const SkPaint& paint) = 0;
177    virtual void drawOval(const SkDraw&, const SkRect& oval,
178                          const SkPaint& paint) = 0;
179    virtual void drawRRect(const SkDraw&, const SkRRect& rr,
180                           const SkPaint& paint) = 0;
181
182    // Default impl calls drawPath()
183    virtual void drawDRRect(const SkDraw&, const SkRRect& outer,
184                            const SkRRect& inner, const SkPaint&);
185
186    /**
187     *  If pathIsMutable, then the implementation is allowed to cast path to a
188     *  non-const pointer and modify it in place (as an optimization). Canvas
189     *  may do this to implement helpers such as drawOval, by placing a temp
190     *  path on the stack to hold the representation of the oval.
191     *
192     *  If prePathMatrix is not null, it should logically be applied before any
193     *  stroking or other effects. If there are no effects on the paint that
194     *  affect the geometry/rasterization, then the pre matrix can just be
195     *  pre-concated with the current matrix.
196     */
197    virtual void drawPath(const SkDraw&, const SkPath& path,
198                          const SkPaint& paint,
199                          const SkMatrix* prePathMatrix = NULL,
200                          bool pathIsMutable = false) = 0;
201    virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
202                            const SkMatrix& matrix, const SkPaint& paint) = 0;
203    virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
204                            int x, int y, const SkPaint& paint) = 0;
205
206    /**
207     *  The default impl. will create a bitmap-shader from the bitmap,
208     *  and call drawRect with it.
209     */
210    virtual void drawBitmapRect(const SkDraw&, const SkBitmap&,
211                                const SkRect* srcOrNull, const SkRect& dst,
212                                const SkPaint& paint,
213                                SkCanvas::DrawBitmapRectFlags flags) = 0;
214
215    /**
216     *  Does not handle text decoration.
217     *  Decorations (underline and stike-thru) will be handled by SkCanvas.
218     */
219    virtual void drawText(const SkDraw&, const void* text, size_t len,
220                          SkScalar x, SkScalar y, const SkPaint& paint) = 0;
221    virtual void drawPosText(const SkDraw&, const void* text, size_t len,
222                             const SkScalar pos[], SkScalar constY,
223                             int scalarsPerPos, const SkPaint& paint) = 0;
224    virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
225                                const SkPath& path, const SkMatrix* matrix,
226                                const SkPaint& paint) = 0;
227    virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
228                              const SkPoint verts[], const SkPoint texs[],
229                              const SkColor colors[], SkXfermode* xmode,
230                              const uint16_t indices[], int indexCount,
231                              const SkPaint& paint) = 0;
232    // default implementation unrolls the blob runs.
233    virtual void drawTextBlob(const SkDraw&, const SkTextBlob*, SkScalar x, SkScalar y,
234                              const SkPaint& paint);
235    // default implementation calls drawVertices
236    virtual void drawPatch(const SkDraw&, const SkPoint cubics[12], const SkColor colors[4],
237                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
238    /** The SkDevice passed will be an SkDevice which was returned by a call to
239        onCreateDevice on this device with kSaveLayer_Usage.
240     */
241    virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
242                            const SkPaint&) = 0;
243
244    bool readPixels(const SkImageInfo&, void* dst, size_t rowBytes, int x, int y);
245
246    ///////////////////////////////////////////////////////////////////////////
247
248    /** Update as needed the pixel value in the bitmap, so that the caller can
249        access the pixels directly.
250        @return The device contents as a bitmap
251    */
252    virtual const SkBitmap& onAccessBitmap() = 0;
253
254    /** Called when this device is installed into a Canvas. Balanced by a call
255        to unlockPixels() when the device is removed from a Canvas.
256    */
257    virtual void lockPixels() {}
258    virtual void unlockPixels() {}
259
260    /**
261     *  Returns true if the device allows processing of this imagefilter. If
262     *  false is returned, then the filter is ignored. This may happen for
263     *  some subclasses that do not support pixel manipulations after drawing
264     *  has occurred (e.g. printing). The default implementation returns true.
265     */
266    virtual bool allowImageFilter(const SkImageFilter*) { return true; }
267
268    /**
269     *  Override and return true for filters that the device can handle
270     *  intrinsically. Doing so means that SkCanvas will pass-through this
271     *  filter to drawSprite and drawDevice (and potentially filterImage).
272     *  Returning false means the SkCanvas will have apply the filter itself,
273     *  and just pass the resulting image to the device.
274     */
275    virtual bool canHandleImageFilter(const SkImageFilter*) { return false; }
276
277    /**
278     *  Related (but not required) to canHandleImageFilter, this method returns
279     *  true if the device could apply the filter to the src bitmap and return
280     *  the result (and updates offset as needed).
281     *  If the device does not recognize or support this filter,
282     *  it just returns false and leaves result and offset unchanged.
283     */
284    virtual bool filterImage(const SkImageFilter*, const SkBitmap&,
285                             const SkImageFilter::Context& ctx,
286                             SkBitmap* result, SkIPoint* offset) {
287        return false;
288    }
289
290protected:
291    // default impl returns NULL
292    virtual SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&);
293
294    // default impl returns NULL
295    virtual const void* peekPixels(SkImageInfo*, size_t* rowBytes);
296
297    /**
298     *  The caller is responsible for "pre-clipping" the dst. The impl can assume that the dst
299     *  image at the specified x,y offset will fit within the device's bounds.
300     *
301     *  This is explicitly asserted in readPixels(), the public way to call this.
302     */
303    virtual bool onReadPixels(const SkImageInfo&, void*, size_t, int x, int y);
304
305    /**
306     *  The caller is responsible for "pre-clipping" the src. The impl can assume that the src
307     *  image at the specified x,y offset will fit within the device's bounds.
308     *
309     *  This is explicitly asserted in writePixelsDirect(), the public way to call this.
310     */
311    virtual bool onWritePixels(const SkImageInfo&, const void*, size_t, int x, int y);
312
313    /**
314     *  Default impl returns NULL.
315     */
316    virtual void* onAccessPixels(SkImageInfo* info, size_t* rowBytes);
317
318    /**
319     *  Leaky properties are those which the device should be applying but it isn't.
320     *  These properties will be applied by the draw, when and as it can.
321     *  If the device does handle a property, that property should be set to the identity value
322     *  for that property, effectively making it non-leaky.
323     */
324    const SkDeviceProperties& getLeakyProperties() const {
325        return *fLeakyProperties;
326    }
327
328    /**
329     *  PRIVATE / EXPERIMENTAL -- do not call
330     *  Construct an acceleration object and attach it to 'picture'
331     */
332    virtual void EXPERIMENTAL_optimize(const SkPicture* picture);
333
334    /**
335     *  PRIVATE / EXPERIMENTAL -- do not call
336     *  This entry point gives the backend an opportunity to take over the rendering
337     *  of 'picture'. If optimization data is available (due to an earlier
338     *  'optimize' call) this entry point should make use of it and return true
339     *  if all rendering has been done. If false is returned, SkCanvas will
340     *  perform its own rendering pass. It is acceptable for the backend
341     *  to perform some device-specific warm up tasks and then let SkCanvas
342     *  perform the main rendering loop (by return false from here).
343     */
344    virtual bool EXPERIMENTAL_drawPicture(SkCanvas*, const SkPicture*, const SkMatrix*,
345                                          const SkPaint*);
346
347    void setPixelGeometry(SkPixelGeometry geo);
348
349private:
350    friend class SkCanvas;
351    friend struct DeviceCM; //for setMatrixClip
352    friend class SkDraw;
353    friend class SkDrawIter;
354    friend class SkDeviceFilteredPaint;
355    friend class SkDeviceImageFilterProxy;
356    friend class SkDeferredDevice;    // for newSurface
357
358    friend class SkSurface_Raster;
359
360    // used to change the backend's pixels (and possibly config/rowbytes)
361    // but cannot change the width/height, so there should be no change to
362    // any clip information.
363    // TODO: move to SkBitmapDevice
364    virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) {}
365
366    virtual bool forceConservativeRasterClip() const { return false; }
367
368    // just called by SkCanvas when built as a layer
369    void setOrigin(int x, int y) { fOrigin.set(x, y); }
370    // just called by SkCanvas for saveLayer
371    SkBaseDevice* createCompatibleDeviceForSaveLayer(const SkImageInfo&);
372    // just called by SkCanvas for imagefilter
373    SkBaseDevice* createCompatibleDeviceForImageFilter(const SkImageInfo&);
374
375    virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) {
376        return NULL;
377    }
378
379    /** Causes any deferred drawing to the device to be completed.
380     */
381    virtual void flush() {}
382
383    virtual SkImageFilter::Cache* getImageFilterCache() { return NULL; }
384
385    SkIPoint    fOrigin;
386    SkMetaData* fMetaData;
387    SkDeviceProperties* fLeakyProperties;   // will always exist.
388
389#ifdef SK_DEBUG
390    bool        fAttachedToCanvas;
391#endif
392
393    typedef SkRefCnt INHERITED;
394};
395
396#endif
397