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