SkDevice.h revision a1c3d78f224874833920c8017f4287a3ec538779
1
2/*
3 * Copyright 2010 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#ifndef SkDevice_DEFINED
11#define SkDevice_DEFINED
12
13#include "SkRefCnt.h"
14#include "SkBitmap.h"
15#include "SkCanvas.h"
16#include "SkColor.h"
17
18class SkClipStack;
19class SkDraw;
20struct SkIRect;
21class SkMatrix;
22class SkMetaData;
23class SkRegion;
24
25// This is an opaque class, not interpreted by skia
26class SkGpuRenderTarget;
27
28class SK_API SkDevice : public SkRefCnt {
29public:
30    SK_DECLARE_INST_COUNT(SkDevice)
31
32    /**
33     *  Construct a new device with the specified bitmap as its backend. It is
34     *  valid for the bitmap to have no pixels associated with it. In that case,
35     *  any drawing to this device will have no effect.
36    */
37    SkDevice(const SkBitmap& bitmap);
38
39    /**
40     *  Create a new raster device and have the pixels be automatically
41     *  allocated. The rowBytes of the device will be computed automatically
42     *  based on the config and the width.
43     *
44     *  @param config   The desired config for the pixels. If the request cannot
45     *                  be met, the closest matching support config will be used.
46     *  @param width    width (in pixels) of the device
47     *  @param height   height (in pixels) of the device
48     *  @param isOpaque Set to true if it is known that all of the pixels will
49     *                  be drawn to opaquely. Used as an accelerator when drawing
50     *                  these pixels to another device.
51     */
52    SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque = false);
53
54    virtual ~SkDevice();
55
56    /**
57     *  Creates a device that is of the same type as this device (e.g. SW-raster,
58     *  GPU, or PDF). The backing store for this device is created automatically
59     *  (e.g. offscreen pixels or FBO or whatever is appropriate).
60     *
61     *  @param width    width of the device to create
62     *  @param height   height of the device to create
63     *  @param isOpaque performance hint, set to true if you know that you will
64     *                  draw into this device such that all of the pixels will
65     *                  be opaque.
66     */
67    SkDevice* createCompatibleDevice(SkBitmap::Config config,
68                                     int width, int height,
69                                     bool isOpaque);
70
71    SkMetaData& getMetaData();
72
73    enum Capabilities {
74        kGL_Capability     = 0x1,  //!< mask indicating GL support
75        kVector_Capability = 0x2,  //!< mask indicating a vector representation
76        kAll_Capabilities  = 0x3
77    };
78    virtual uint32_t getDeviceCapabilities() { return 0; }
79
80    /** Return the width of the device (in pixels).
81    */
82    virtual int width() const { return fBitmap.width(); }
83    /** Return the height of the device (in pixels).
84    */
85    virtual int height() const { return fBitmap.height(); }
86
87    /**
88     *  Return the bounds of the device in the coordinate space of the root
89     *  canvas. The root device will have its top-left at 0,0, but other devices
90     *  such as those associated with saveLayer may have a non-zero origin.
91     */
92    void getGlobalBounds(SkIRect* bounds) const;
93
94    /** Returns true if the device's bitmap's config treats every pixels as
95        implicitly opaque.
96    */
97    bool isOpaque() const { return fBitmap.isOpaque(); }
98
99    /** Return the bitmap config of the device's pixels
100    */
101    SkBitmap::Config config() const { return fBitmap.getConfig(); }
102
103    /** Return the bitmap associated with this device. Call this each time you need
104        to access the bitmap, as it notifies the subclass to perform any flushing
105        etc. before you examine the pixels.
106        @param changePixels set to true if the caller plans to change the pixels
107        @return the device's bitmap
108    */
109    const SkBitmap& accessBitmap(bool changePixels);
110
111    /**
112     *  DEPRECATED: This will be made protected once WebKit stops using it.
113     *              Instead use Canvas' writePixels method.
114     *
115     *  Similar to draw sprite, this method will copy the pixels in bitmap onto
116     *  the device, with the top/left corner specified by (x, y). The pixel
117     *  values in the device are completely replaced: there is no blending.
118     *
119     *  Currently if bitmap is backed by a texture this is a no-op. This may be
120     *  relaxed in the future.
121     *
122     *  If the bitmap has config kARGB_8888_Config then the config8888 param
123     *  will determines how the pixel valuess are intepreted. If the bitmap is
124     *  not kARGB_8888_Config then this parameter is ignored.
125     */
126    virtual void writePixels(const SkBitmap& bitmap, int x, int y,
127                             SkCanvas::Config8888 config8888 = SkCanvas::kNative_Premul_Config8888);
128
129    /**
130     * Return the device's associated gpu render target, or NULL.
131     */
132    virtual SkGpuRenderTarget* accessRenderTarget() { return NULL; }
133
134
135    /**
136     *  Return the device's origin: its offset in device coordinates from
137     *  the default origin in its canvas' matrix/clip
138     */
139    const SkIPoint& getOrigin() const { return fOrigin; }
140
141    /**
142     * onAttachToCanvas is invoked whenever a device is installed in a canvas
143     * (i.e., setDevice, saveLayer (for the new device created by the save),
144     * and SkCanvas' SkDevice & SkBitmap -taking ctors). It allows the
145     * devices to prepare for drawing (e.g., locking their pixels, etc.)
146     */
147    virtual void onAttachToCanvas(SkCanvas* canvas) {
148        SkASSERT(!fAttachedToCanvas);
149        this->lockPixels();
150#ifdef SK_DEBUG
151        fAttachedToCanvas = true;
152#endif
153    };
154
155    /**
156     * onDetachFromCanvas notifies a device that it will no longer be drawn to.
157     * It gives the device a chance to clean up (e.g., unlock its pixels). It
158     * is invoked from setDevice (for the displaced device), restore and
159     * possibly from SkCanvas' dtor.
160     */
161    virtual void onDetachFromCanvas() {
162        SkASSERT(fAttachedToCanvas);
163        this->unlockPixels();
164#ifdef SK_DEBUG
165        fAttachedToCanvas = false;
166#endif
167    };
168
169protected:
170    enum Usage {
171       kGeneral_Usage,
172       kSaveLayer_Usage  // <! internal use only
173    };
174
175    struct TextFlags {
176        uint32_t            fFlags;     // SkPaint::getFlags()
177        SkPaint::Hinting    fHinting;
178    };
179
180    /**
181     *  Device may filter the text flags for drawing text here. If it wants to
182     *  make a change to the specified values, it should write them into the
183     *  textflags parameter (output) and return true. If the paint is fine as
184     *  is, then ignore the textflags parameter and return false.
185     *
186     *  The baseclass SkDevice filters based on its depth and blitters.
187     */
188    virtual bool filterTextFlags(const SkPaint& paint, TextFlags*);
189
190    /** Clears the entire device to the specified color (including alpha).
191     *  Ignores the clip.
192     */
193    virtual void clear(SkColor color);
194
195    /**
196     * Deprecated name for clear.
197     */
198    void eraseColor(SkColor eraseColor) { this->clear(eraseColor); }
199
200    /** These are called inside the per-device-layer loop for each draw call.
201     When these are called, we have already applied any saveLayer operations,
202     and are handling any looping from the paint, and any effects from the
203     DrawFilter.
204     */
205    virtual void drawPaint(const SkDraw&, const SkPaint& paint);
206    virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count,
207                            const SkPoint[], const SkPaint& paint);
208    virtual void drawRect(const SkDraw&, const SkRect& r,
209                          const SkPaint& paint);
210    /**
211     *  If pathIsMutable, then the implementation is allowed to cast path to a
212     *  non-const pointer and modify it in place (as an optimization). Canvas
213     *  may do this to implement helpers such as drawOval, by placing a temp
214     *  path on the stack to hold the representation of the oval.
215     *
216     *  If prePathMatrix is not null, it should logically be applied before any
217     *  stroking or other effects. If there are no effects on the paint that
218     *  affect the geometry/rasterization, then the pre matrix can just be
219     *  pre-concated with the current matrix.
220     */
221    virtual void drawPath(const SkDraw&, const SkPath& path,
222                          const SkPaint& paint,
223                          const SkMatrix* prePathMatrix = NULL,
224                          bool pathIsMutable = false);
225    virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
226                            const SkIRect* srcRectOrNull,
227                            const SkMatrix& matrix, const SkPaint& paint);
228    virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
229                            int x, int y, const SkPaint& paint);
230
231    /**
232     *  The default impl. will create a bitmap-shader from the bitmap,
233     *  and call drawRect with it.
234     */
235    virtual void drawBitmapRect(const SkDraw&, const SkBitmap&,
236                                const SkRect* srcOrNull, const SkRect& dst,
237                                const SkPaint& paint);
238
239    /**
240     *  Does not handle text decoration.
241     *  Decorations (underline and stike-thru) will be handled by SkCanvas.
242     */
243    virtual void drawText(const SkDraw&, const void* text, size_t len,
244                          SkScalar x, SkScalar y, const SkPaint& paint);
245    virtual void drawPosText(const SkDraw&, const void* text, size_t len,
246                             const SkScalar pos[], SkScalar constY,
247                             int scalarsPerPos, const SkPaint& paint);
248    virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
249                                const SkPath& path, const SkMatrix* matrix,
250                                const SkPaint& paint);
251#ifdef SK_BUILD_FOR_ANDROID
252    virtual void drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len,
253                                   const SkPoint pos[], const SkPaint& paint,
254                                   const SkPath& path, const SkMatrix* matrix);
255#endif
256    virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
257                              const SkPoint verts[], const SkPoint texs[],
258                              const SkColor colors[], SkXfermode* xmode,
259                              const uint16_t indices[], int indexCount,
260                              const SkPaint& paint);
261    /** The SkDevice passed will be an SkDevice which was returned by a call to
262        onCreateCompatibleDevice on this device with kSaveLayer_Usage.
263     */
264    virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
265                            const SkPaint&);
266
267    /**
268     *  On success (returns true), copy the device pixels into the bitmap.
269     *  On failure, the bitmap parameter is left unchanged and false is
270     *  returned.
271     *
272     *  The device's pixels are converted to the bitmap's config. The only
273     *  supported config is kARGB_8888_Config, though this is likely to be
274     *  relaxed in  the future. The meaning of config kARGB_8888_Config is
275     *  modified by the enum param config8888. The default value interprets
276     *  kARGB_8888_Config as SkPMColor
277     *
278     *  If the bitmap has pixels already allocated, the device pixels will be
279     *  written there. If not, bitmap->allocPixels() will be called
280     *  automatically. If the bitmap is backed by a texture readPixels will
281     *  fail.
282     *
283     *  The actual pixels written is the intersection of the device's bounds,
284     *  and the rectangle formed by the bitmap's width,height and the specified
285     *  x,y. If bitmap pixels extend outside of that intersection, they will not
286     *  be modified.
287     *
288     *  Other failure conditions:
289     *    * If the device is not a raster device (e.g. PDF) then readPixels will
290     *      fail.
291     *    * If bitmap is texture-backed then readPixels will fail. (This may be
292     *      relaxed in the future.)
293     */
294    bool readPixels(SkBitmap* bitmap,
295                    int x, int y,
296                    SkCanvas::Config8888 config8888);
297
298    ///////////////////////////////////////////////////////////////////////////
299
300    /** Update as needed the pixel value in the bitmap, so that the caller can
301        access the pixels directly. Note: only the pixels field should be
302        altered. The config/width/height/rowbytes must remain unchanged.
303        @param bitmap The device's bitmap
304        @return Echo the bitmap parameter, or an alternate (shadow) bitmap
305            maintained by the subclass.
306    */
307    virtual const SkBitmap& onAccessBitmap(SkBitmap*);
308
309    SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
310    // just for subclasses, to assign a custom pixelref
311    SkPixelRef* setPixelRef(SkPixelRef* pr, size_t offset) {
312        fBitmap.setPixelRef(pr, offset);
313        return pr;
314    }
315
316    /**
317     * Implements readPixels API. The caller will ensure that:
318     *  1. bitmap has pixel config kARGB_8888_Config.
319     *  2. bitmap has pixels.
320     *  3. The rectangle (x, y, x + bitmap->width(), y + bitmap->height()) is
321     *     contained in the device bounds.
322     */
323    virtual bool onReadPixels(const SkBitmap& bitmap,
324                              int x, int y,
325                              SkCanvas::Config8888 config8888);
326
327    /** Called when this device is installed into a Canvas. Balanaced by a call
328        to unlockPixels() when the device is removed from a Canvas.
329    */
330    virtual void lockPixels();
331    virtual void unlockPixels();
332
333    /**
334     *  Returns true if the device allows processing of this imagefilter. If
335     *  false is returned, then the filter is ignored. This may happen for
336     *  some subclasses that do not support pixel manipulations after drawing
337     *  has occurred (e.g. printing). The default implementation returns true.
338     */
339    virtual bool allowImageFilter(SkImageFilter*);
340
341    /**
342     *  Override and return true for filters that the device can handle
343     *  intrinsically. Doing so means that SkCanvas will pass-through this
344     *  filter to drawSprite and drawDevice (and potentially filterImage).
345     *  Returning false means the SkCanvas will have apply the filter itself,
346     *  and just pass the resulting image to the device.
347     */
348    virtual bool canHandleImageFilter(SkImageFilter*);
349
350    /**
351     *  Related (but not required) to canHandleImageFilter, this method returns
352     *  true if the device could apply the filter to the src bitmap and return
353     *  the result (and updates offset as needed).
354     *  If the device does not recognize or support this filter,
355     *  it just returns false and leaves result and offset unchanged.
356     */
357    virtual bool filterImage(SkImageFilter*, const SkBitmap&, const SkMatrix&,
358                             SkBitmap* result, SkIPoint* offset);
359
360    // This is equal kBGRA_Premul_Config8888 or kRGBA_Premul_Config8888 if
361    // either is identical to kNative_Premul_Config8888. Otherwise, -1.
362    static const SkCanvas::Config8888 kPMColorAlias;
363
364private:
365    friend class SkCanvas;
366    friend class SkDraw;
367    friend class SkDrawIter;
368    friend class SkDeviceFilteredPaint;
369    friend class SkDeviceImageFilterProxy;
370
371    friend class SkSurface_Raster;
372    // used to change the backend's pixels (and possibly config/rowbytes)
373    // but cannot change the width/height, so there should be no change to
374    // any clip information.
375    void replaceBitmapBackendForRasterSurface(const SkBitmap&);
376
377    // just called by SkCanvas when built as a layer
378    void setOrigin(int x, int y) { fOrigin.set(x, y); }
379    // just called by SkCanvas for saveLayer
380    SkDevice* createCompatibleDeviceForSaveLayer(SkBitmap::Config config,
381                                                 int width, int height,
382                                                 bool isOpaque);
383
384    /**
385     * Subclasses should override this to implement createCompatibleDevice.
386     */
387    virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
388                                               int width, int height,
389                                               bool isOpaque,
390                                               Usage usage);
391
392    /** Causes any deferred drawing to the device to be completed.
393     */
394    virtual void flush() {}
395
396    SkBitmap    fBitmap;
397    SkIPoint    fOrigin;
398    SkMetaData* fMetaData;
399
400#ifdef SK_DEBUG
401    bool        fAttachedToCanvas;
402#endif
403
404    typedef SkRefCnt INHERITED;
405};
406
407#endif
408