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 "SkImageFilter.h"
     16 
     17 class SkClipStack;
     18 class SkDraw;
     19 struct SkIRect;
     20 class SkMatrix;
     21 class SkMetaData;
     22 class SkRegion;
     23 struct SkDeviceProperties;
     24 class GrRenderTarget;
     25 
     26 class SK_API SkBaseDevice : public SkRefCnt {
     27 public:
     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 
    121 protected:
    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 
    290 protected:
    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 
    349 private:
    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