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 "SkCanvas.h"
     13 #include "SkColor.h"
     14 #include "SkSurfaceProps.h"
     15 
     16 class SkBitmap;
     17 class SkDrawFilter;
     18 class SkImageFilterCache;
     19 struct SkIRect;
     20 class SkMatrix;
     21 class SkRasterHandleAllocator;
     22 class SkRegion;
     23 class SkSpecialImage;
     24 class GrRenderTarget;
     25 
     26 class SK_API SkBaseDevice : public SkRefCnt {
     27 public:
     28     SkBaseDevice(const SkImageInfo&, const SkSurfaceProps&);
     29 
     30     /**
     31      *  Return ImageInfo for this device. If the canvas is not backed by pixels
     32      *  (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
     33      */
     34     const SkImageInfo& imageInfo() const { return fInfo; }
     35 
     36     /**
     37      *  Return SurfaceProps for this device.
     38      */
     39     const SkSurfaceProps& surfaceProps() const {
     40         return fSurfaceProps;
     41     }
     42 
     43     /**
     44      *  Return the bounds of the device in the coordinate space of the root
     45      *  canvas. The root device will have its top-left at 0,0, but other devices
     46      *  such as those associated with saveLayer may have a non-zero origin.
     47      */
     48     void getGlobalBounds(SkIRect* bounds) const {
     49         SkASSERT(bounds);
     50         const SkIPoint& origin = this->getOrigin();
     51         bounds->setXYWH(origin.x(), origin.y(), this->width(), this->height());
     52     }
     53 
     54     SkIRect getGlobalBounds() const {
     55         SkIRect bounds;
     56         this->getGlobalBounds(&bounds);
     57         return bounds;
     58     }
     59 
     60     int width() const {
     61         return this->imageInfo().width();
     62     }
     63 
     64     int height() const {
     65         return this->imageInfo().height();
     66     }
     67 
     68     bool isOpaque() const {
     69         return this->imageInfo().isOpaque();
     70     }
     71 
     72     bool writePixels(const SkImageInfo&, const void*, size_t rowBytes, int x, int y);
     73 
     74     /**
     75      *  Try to get write-access to the pixels behind the device. If successful, this returns true
     76      *  and fills-out the pixmap parameter. On success it also bumps the genID of the underlying
     77      *  bitmap.
     78      *
     79      *  On failure, returns false and ignores the pixmap parameter.
     80      */
     81     bool accessPixels(SkPixmap* pmap);
     82 
     83     /**
     84      *  Try to get read-only-access to the pixels behind the device. If successful, this returns
     85      *  true and fills-out the pixmap parameter.
     86      *
     87      *  On failure, returns false and ignores the pixmap parameter.
     88      */
     89     bool peekPixels(SkPixmap*);
     90 
     91     /**
     92      *  Return the device's origin: its offset in device coordinates from
     93      *  the default origin in its canvas' matrix/clip
     94      */
     95     const SkIPoint& getOrigin() const { return fOrigin; }
     96 
     97     virtual void* getRasterHandle() const { return nullptr; }
     98 
     99     void save() { this->onSave(); }
    100     void restore(const SkMatrix& ctm) {
    101         this->onRestore();
    102         this->setGlobalCTM(ctm);
    103     }
    104     void clipRect(const SkRect& rect, SkClipOp op, bool aa) {
    105         this->onClipRect(rect, op, aa);
    106     }
    107     void clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
    108         this->onClipRRect(rrect, op, aa);
    109     }
    110     void clipPath(const SkPath& path, SkClipOp op, bool aa) {
    111         this->onClipPath(path, op, aa);
    112     }
    113     void clipRegion(const SkRegion& region, SkClipOp op) {
    114         this->onClipRegion(region, op);
    115     }
    116     void androidFramework_setDeviceClipRestriction(SkIRect* mutableClipRestriction) {
    117         this->onSetDeviceClipRestriction(mutableClipRestriction);
    118     }
    119     bool clipIsWideOpen() const;
    120 
    121     const SkMatrix& ctm() const { return fCTM; }
    122     void setCTM(const SkMatrix& ctm) {
    123         fCTM = ctm;
    124     }
    125     void setGlobalCTM(const SkMatrix& ctm);
    126     virtual void validateDevBounds(const SkIRect&) {}
    127 
    128 protected:
    129     enum TileUsage {
    130         kPossible_TileUsage,    //!< the created device may be drawn tiled
    131         kNever_TileUsage,       //!< the created device will never be drawn tiled
    132     };
    133 
    134     struct TextFlags {
    135         uint32_t    fFlags;     // SkPaint::getFlags()
    136     };
    137 
    138     /**
    139      * Returns the text-related flags, possibly modified based on the state of the
    140      * device (e.g. support for LCD).
    141      */
    142     uint32_t filterTextFlags(const SkPaint&) const;
    143 
    144     virtual bool onShouldDisableLCD(const SkPaint&) const { return false; }
    145 
    146     virtual void onSave() {}
    147     virtual void onRestore() {}
    148     virtual void onClipRect(const SkRect& rect, SkClipOp, bool aa) {}
    149     virtual void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) {}
    150     virtual void onClipPath(const SkPath& path, SkClipOp, bool aa) {}
    151     virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp) {}
    152     virtual void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) {}
    153     virtual bool onClipIsAA() const = 0;
    154     virtual void onAsRgnClip(SkRegion*) const = 0;
    155     enum ClipType {
    156         kEmpty_ClipType,
    157         kRect_ClipType,
    158         kComplex_ClipType
    159     };
    160     virtual ClipType onGetClipType() const = 0;
    161 
    162     /** These are called inside the per-device-layer loop for each draw call.
    163      When these are called, we have already applied any saveLayer operations,
    164      and are handling any looping from the paint, and any effects from the
    165      DrawFilter.
    166      */
    167     virtual void drawPaint(const SkPaint& paint) = 0;
    168     virtual void drawPoints(SkCanvas::PointMode mode, size_t count,
    169                             const SkPoint[], const SkPaint& paint) = 0;
    170     virtual void drawRect(const SkRect& r,
    171                           const SkPaint& paint) = 0;
    172     virtual void drawRegion(const SkRegion& r,
    173                             const SkPaint& paint);
    174     virtual void drawOval(const SkRect& oval,
    175                           const SkPaint& paint) = 0;
    176     /** By the time this is called we know that abs(sweepAngle) is in the range [0, 360). */
    177     virtual void drawArc(const SkRect& oval, SkScalar startAngle,
    178                          SkScalar sweepAngle, bool useCenter, const SkPaint& paint);
    179     virtual void drawRRect(const SkRRect& rr,
    180                            const SkPaint& paint) = 0;
    181 
    182     // Default impl calls drawPath()
    183     virtual void drawDRRect(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 SkPath& path,
    198                           const SkPaint& paint,
    199                           const SkMatrix* prePathMatrix = NULL,
    200                           bool pathIsMutable = false) = 0;
    201     virtual void drawBitmap(const SkBitmap& bitmap,
    202                             const SkMatrix& matrix, const SkPaint& paint) = 0;
    203     virtual void drawSprite(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 SkBitmap&,
    211                                 const SkRect* srcOrNull, const SkRect& dst,
    212                                 const SkPaint& paint,
    213                                 SkCanvas::SrcRectConstraint) = 0;
    214     virtual void drawBitmapNine(const SkBitmap&, const SkIRect& center,
    215                                 const SkRect& dst, const SkPaint&);
    216     virtual void drawBitmapLattice(const SkBitmap&, const SkCanvas::Lattice&,
    217                                    const SkRect& dst, const SkPaint&);
    218 
    219     virtual void drawImage(const SkImage*, SkScalar x, SkScalar y, const SkPaint&);
    220     virtual void drawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
    221                                const SkPaint&, SkCanvas::SrcRectConstraint);
    222     virtual void drawImageNine(const SkImage*, const SkIRect& center,
    223                                const SkRect& dst, const SkPaint&);
    224     virtual void drawImageLattice(const SkImage*, const SkCanvas::Lattice&,
    225                                   const SkRect& dst, const SkPaint&);
    226 
    227     /**
    228      *  Does not handle text decoration.
    229      *  Decorations (underline and stike-thru) will be handled by SkCanvas.
    230      */
    231     virtual void drawText(const void* text, size_t len,
    232                           SkScalar x, SkScalar y, const SkPaint& paint) = 0;
    233     virtual void drawPosText(const void* text, size_t len,
    234                              const SkScalar pos[], int scalarsPerPos,
    235                              const SkPoint& offset, const SkPaint& paint) = 0;
    236     virtual void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) = 0;
    237     // default implementation unrolls the blob runs.
    238     virtual void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y,
    239                               const SkPaint& paint, SkDrawFilter* drawFilter);
    240     // default implementation calls drawVertices
    241     virtual void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
    242                            const SkPoint texCoords[4], SkBlendMode, const SkPaint& paint);
    243 
    244     // default implementation calls drawPath
    245     virtual void drawAtlas(const SkImage* atlas, const SkRSXform[], const SkRect[],
    246                            const SkColor[], int count, SkBlendMode, const SkPaint&);
    247 
    248     virtual void drawAnnotation(const SkRect&, const char[], SkData*) {}
    249 
    250     /** The SkDevice passed will be an SkDevice which was returned by a call to
    251         onCreateDevice on this device with kNeverTile_TileExpectation.
    252      */
    253     virtual void drawDevice(SkBaseDevice*, int x, int y,
    254                             const SkPaint&) = 0;
    255 
    256     virtual void drawTextOnPath(const void* text, size_t len, const SkPath&,
    257                                 const SkMatrix*, const SkPaint&);
    258     virtual void drawTextRSXform(const void* text, size_t len, const SkRSXform[],
    259                                  const SkPaint&);
    260 
    261     virtual void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&);
    262     virtual sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&);
    263     virtual sk_sp<SkSpecialImage> makeSpecial(const SkImage*);
    264     virtual sk_sp<SkSpecialImage> snapSpecial();
    265 
    266     bool readPixels(const SkImageInfo&, void* dst, size_t rowBytes, int x, int y);
    267 
    268     ///////////////////////////////////////////////////////////////////////////
    269 
    270     virtual GrContext* context() const { return nullptr; }
    271 
    272     virtual sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&);
    273     virtual bool onPeekPixels(SkPixmap*) { return false; }
    274 
    275     /**
    276      *  The caller is responsible for "pre-clipping" the dst. The impl can assume that the dst
    277      *  image at the specified x,y offset will fit within the device's bounds.
    278      *
    279      *  This is explicitly asserted in readPixels(), the public way to call this.
    280      */
    281     virtual bool onReadPixels(const SkImageInfo&, void*, size_t, int x, int y);
    282 
    283     /**
    284      *  The caller is responsible for "pre-clipping" the src. The impl can assume that the src
    285      *  image at the specified x,y offset will fit within the device's bounds.
    286      *
    287      *  This is explicitly asserted in writePixelsDirect(), the public way to call this.
    288      */
    289     virtual bool onWritePixels(const SkImageInfo&, const void*, size_t, int x, int y);
    290 
    291     virtual bool onAccessPixels(SkPixmap*) { return false; }
    292 
    293     struct CreateInfo {
    294         static SkPixelGeometry AdjustGeometry(const SkImageInfo&, TileUsage, SkPixelGeometry,
    295                                               bool preserveLCDText);
    296 
    297         // The constructor may change the pixel geometry based on other parameters.
    298         CreateInfo(const SkImageInfo& info,
    299                    TileUsage tileUsage,
    300                    SkPixelGeometry geo)
    301             : fInfo(info)
    302             , fTileUsage(tileUsage)
    303             , fPixelGeometry(AdjustGeometry(info, tileUsage, geo, false))
    304         {}
    305 
    306         CreateInfo(const SkImageInfo& info,
    307                    TileUsage tileUsage,
    308                    SkPixelGeometry geo,
    309                    bool preserveLCDText,
    310                    SkRasterHandleAllocator* allocator)
    311             : fInfo(info)
    312             , fTileUsage(tileUsage)
    313             , fPixelGeometry(AdjustGeometry(info, tileUsage, geo, preserveLCDText))
    314             , fAllocator(allocator)
    315         {}
    316 
    317         const SkImageInfo       fInfo;
    318         const TileUsage         fTileUsage;
    319         const SkPixelGeometry   fPixelGeometry;
    320         SkRasterHandleAllocator* fAllocator = nullptr;
    321     };
    322 
    323     /**
    324      *  Create a new device based on CreateInfo. If the paint is not null, then it represents a
    325      *  preview of how the new device will be composed with its creator device (this).
    326      *
    327      *  The subclass may be handed this device in drawDevice(), so it must always return
    328      *  a device that it knows how to draw, and that it knows how to identify if it is not of the
    329      *  same subclass (since drawDevice is passed a SkBaseDevice*). If the subclass cannot fulfill
    330      *  that contract (e.g. PDF cannot support some settings on the paint) it should return NULL,
    331      *  and the caller may then decide to explicitly create a bitmapdevice, knowing that later
    332      *  it could not call drawDevice with it (but it could call drawSprite or drawBitmap).
    333      */
    334     virtual SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) {
    335         return NULL;
    336     }
    337 
    338     // A helper function used by derived classes to log the scale factor of a bitmap or image draw.
    339     static void LogDrawScaleFactor(const SkMatrix&, SkFilterQuality);
    340 
    341 private:
    342     friend class SkCanvas;
    343     friend struct DeviceCM; //for setMatrixClip
    344     friend class SkDraw;
    345     friend class SkDrawIter;
    346     friend class SkDeviceFilteredPaint;
    347     friend class SkNoPixelsBitmapDevice;
    348     friend class SkSurface_Raster;
    349     friend class DeviceTestingAccess;
    350 
    351     // used to change the backend's pixels (and possibly config/rowbytes)
    352     // but cannot change the width/height, so there should be no change to
    353     // any clip information.
    354     // TODO: move to SkBitmapDevice
    355     virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) {}
    356 
    357     virtual bool forceConservativeRasterClip() const { return false; }
    358 
    359     /**
    360      * Don't call this!
    361      */
    362     virtual GrRenderTargetContext* accessRenderTargetContext() { return nullptr; }
    363 
    364     // just called by SkCanvas when built as a layer
    365     void setOrigin(const SkMatrix& ctm, int x, int y);
    366 
    367     /** Causes any deferred drawing to the device to be completed.
    368      */
    369     virtual void flush() {}
    370 
    371     virtual SkImageFilterCache* getImageFilterCache() { return NULL; }
    372 
    373     friend class SkNoPixelsDevice;
    374     friend class SkBitmapDevice;
    375     void privateResize(int w, int h) {
    376         *const_cast<SkImageInfo*>(&fInfo) = fInfo.makeWH(w, h);
    377     }
    378 
    379     SkIPoint             fOrigin;
    380     const SkImageInfo    fInfo;
    381     const SkSurfaceProps fSurfaceProps;
    382     SkMatrix             fCTM;
    383 
    384     typedef SkRefCnt INHERITED;
    385 };
    386 
    387 class SkAutoDeviceCTMRestore : SkNoncopyable {
    388 public:
    389     SkAutoDeviceCTMRestore(SkBaseDevice* device, const SkMatrix& ctm)
    390         : fDevice(device)
    391         , fPrevCTM(device->ctm())
    392     {
    393         fDevice->setCTM(ctm);
    394     }
    395     ~SkAutoDeviceCTMRestore() {
    396         fDevice->setCTM(fPrevCTM);
    397     }
    398 
    399 private:
    400     SkBaseDevice*   fDevice;
    401     const SkMatrix  fPrevCTM;
    402 };
    403 
    404 #endif
    405