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