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