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 
     26 class 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 SkPixmap&, 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 = nullptr,
    200                           bool pathIsMutable = false) = 0;
    201     virtual void drawBitmap(const SkBitmap& bitmap,
    202                             SkScalar x,
    203                             SkScalar y,
    204                             const SkPaint& paint) = 0;
    205     virtual void drawSprite(const SkBitmap& bitmap,
    206                             int x, int y, const SkPaint& paint) = 0;
    207 
    208     /**
    209      *  The default impl. will create a bitmap-shader from the bitmap,
    210      *  and call drawRect with it.
    211      */
    212     virtual void drawBitmapRect(const SkBitmap&,
    213                                 const SkRect* srcOrNull, const SkRect& dst,
    214                                 const SkPaint& paint,
    215                                 SkCanvas::SrcRectConstraint) = 0;
    216     virtual void drawBitmapNine(const SkBitmap&, const SkIRect& center,
    217                                 const SkRect& dst, const SkPaint&);
    218     virtual void drawBitmapLattice(const SkBitmap&, const SkCanvas::Lattice&,
    219                                    const SkRect& dst, const SkPaint&);
    220 
    221     virtual void drawImage(const SkImage*, SkScalar x, SkScalar y, const SkPaint&);
    222     virtual void drawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
    223                                const SkPaint&, SkCanvas::SrcRectConstraint);
    224     virtual void drawImageNine(const SkImage*, const SkIRect& center,
    225                                const SkRect& dst, const SkPaint&);
    226     virtual void drawImageLattice(const SkImage*, const SkCanvas::Lattice&,
    227                                   const SkRect& dst, const SkPaint&);
    228 
    229     /**
    230      *  Does not handle text decoration.
    231      *  Decorations (underline and stike-thru) will be handled by SkCanvas.
    232      */
    233     virtual void drawText(const void* text, size_t len,
    234                           SkScalar x, SkScalar y, const SkPaint& paint) = 0;
    235     virtual void drawPosText(const void* text, size_t len,
    236                              const SkScalar pos[], int scalarsPerPos,
    237                              const SkPoint& offset, const SkPaint& paint) = 0;
    238     virtual void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) = 0;
    239     virtual void drawShadow(const SkPath&, const SkDrawShadowRec&);
    240 
    241     // default implementation unrolls the blob runs.
    242     virtual void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y,
    243                               const SkPaint& paint, SkDrawFilter* drawFilter);
    244     // default implementation calls drawVertices
    245     virtual void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
    246                            const SkPoint texCoords[4], SkBlendMode, bool interpColorsLinearly,
    247                            const SkPaint& paint);
    248 
    249     // default implementation calls drawPath
    250     virtual void drawAtlas(const SkImage* atlas, const SkRSXform[], const SkRect[],
    251                            const SkColor[], int count, SkBlendMode, const SkPaint&);
    252 
    253     virtual void drawAnnotation(const SkRect&, const char[], SkData*) {}
    254 
    255     /** The SkDevice passed will be an SkDevice which was returned by a call to
    256         onCreateDevice on this device with kNeverTile_TileExpectation.
    257      */
    258     virtual void drawDevice(SkBaseDevice*, int x, int y,
    259                             const SkPaint&) = 0;
    260 
    261     virtual void drawTextOnPath(const void* text, size_t len, const SkPath&,
    262                                 const SkMatrix*, const SkPaint&);
    263     virtual void drawTextRSXform(const void* text, size_t len, const SkRSXform[],
    264                                  const SkPaint&);
    265 
    266     virtual void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
    267                              SkImage* clipImage, const SkMatrix& clipMatrix);
    268     virtual sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&);
    269     virtual sk_sp<SkSpecialImage> makeSpecial(const SkImage*);
    270     virtual sk_sp<SkSpecialImage> snapSpecial();
    271 
    272     bool readPixels(const SkPixmap&, int x, int y);
    273 
    274     ///////////////////////////////////////////////////////////////////////////
    275 
    276     virtual GrContext* context() const { return nullptr; }
    277 
    278     virtual sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&);
    279     virtual bool onPeekPixels(SkPixmap*) { return false; }
    280 
    281     /**
    282      *  The caller is responsible for "pre-clipping" the dst. The impl can assume that the dst
    283      *  image at the specified x,y offset will fit within the device's bounds.
    284      *
    285      *  This is explicitly asserted in readPixels(), the public way to call this.
    286      */
    287     virtual bool onReadPixels(const SkPixmap&, int x, int y);
    288 
    289     /**
    290      *  The caller is responsible for "pre-clipping" the src. The impl can assume that the src
    291      *  image at the specified x,y offset will fit within the device's bounds.
    292      *
    293      *  This is explicitly asserted in writePixelsDirect(), the public way to call this.
    294      */
    295     virtual bool onWritePixels(const SkPixmap&, int x, int y);
    296 
    297     virtual bool onAccessPixels(SkPixmap*) { return false; }
    298 
    299     struct CreateInfo {
    300         static SkPixelGeometry AdjustGeometry(const SkImageInfo&, TileUsage, SkPixelGeometry,
    301                                               bool preserveLCDText);
    302 
    303         // The constructor may change the pixel geometry based on other parameters.
    304         CreateInfo(const SkImageInfo& info,
    305                    TileUsage tileUsage,
    306                    SkPixelGeometry geo)
    307             : fInfo(info)
    308             , fTileUsage(tileUsage)
    309             , fPixelGeometry(AdjustGeometry(info, tileUsage, geo, false))
    310         {}
    311 
    312         CreateInfo(const SkImageInfo& info,
    313                    TileUsage tileUsage,
    314                    SkPixelGeometry geo,
    315                    bool preserveLCDText,
    316                    SkRasterHandleAllocator* allocator)
    317             : fInfo(info)
    318             , fTileUsage(tileUsage)
    319             , fPixelGeometry(AdjustGeometry(info, tileUsage, geo, preserveLCDText))
    320             , fAllocator(allocator)
    321         {}
    322 
    323         const SkImageInfo       fInfo;
    324         const TileUsage         fTileUsage;
    325         const SkPixelGeometry   fPixelGeometry;
    326         SkRasterHandleAllocator* fAllocator = nullptr;
    327     };
    328 
    329     /**
    330      *  Create a new device based on CreateInfo. If the paint is not null, then it represents a
    331      *  preview of how the new device will be composed with its creator device (this).
    332      *
    333      *  The subclass may be handed this device in drawDevice(), so it must always return
    334      *  a device that it knows how to draw, and that it knows how to identify if it is not of the
    335      *  same subclass (since drawDevice is passed a SkBaseDevice*). If the subclass cannot fulfill
    336      *  that contract (e.g. PDF cannot support some settings on the paint) it should return NULL,
    337      *  and the caller may then decide to explicitly create a bitmapdevice, knowing that later
    338      *  it could not call drawDevice with it (but it could call drawSprite or drawBitmap).
    339      */
    340     virtual SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) {
    341         return nullptr;
    342     }
    343 
    344     // A helper function used by derived classes to log the scale factor of a bitmap or image draw.
    345     static void LogDrawScaleFactor(const SkMatrix&, SkFilterQuality);
    346 
    347 private:
    348     friend class SkAndroidFrameworkUtils;
    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 SkSurface_Raster;
    355     friend class DeviceTestingAccess;
    356 
    357     // used to change the backend's pixels (and possibly config/rowbytes)
    358     // but cannot change the width/height, so there should be no change to
    359     // any clip information.
    360     // TODO: move to SkBitmapDevice
    361     virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) {}
    362 
    363     virtual bool forceConservativeRasterClip() const { return false; }
    364 
    365     /**
    366      * Don't call this!
    367      */
    368     virtual GrRenderTargetContext* accessRenderTargetContext() { return nullptr; }
    369 
    370     // just called by SkCanvas when built as a layer
    371     void setOrigin(const SkMatrix& ctm, int x, int y);
    372 
    373     /** Causes any deferred drawing to the device to be completed.
    374      */
    375     virtual void flush() {}
    376 
    377     virtual SkImageFilterCache* getImageFilterCache() { return nullptr; }
    378 
    379     friend class SkNoPixelsDevice;
    380     friend class SkBitmapDevice;
    381     void privateResize(int w, int h) {
    382         *const_cast<SkImageInfo*>(&fInfo) = fInfo.makeWH(w, h);
    383     }
    384 
    385     SkIPoint             fOrigin;
    386     const SkImageInfo    fInfo;
    387     const SkSurfaceProps fSurfaceProps;
    388     SkMatrix             fCTM;
    389 
    390     typedef SkRefCnt INHERITED;
    391 };
    392 
    393 class SkAutoDeviceCTMRestore : SkNoncopyable {
    394 public:
    395     SkAutoDeviceCTMRestore(SkBaseDevice* device, const SkMatrix& ctm)
    396         : fDevice(device)
    397         , fPrevCTM(device->ctm())
    398     {
    399         fDevice->setCTM(ctm);
    400     }
    401     ~SkAutoDeviceCTMRestore() {
    402         fDevice->setCTM(fPrevCTM);
    403     }
    404 
    405 private:
    406     SkBaseDevice*   fDevice;
    407     const SkMatrix  fPrevCTM;
    408 };
    409 
    410 #endif
    411