• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "include/core/SkCanvas.h"
12 #include "include/core/SkColor.h"
13 #include "include/core/SkRefCnt.h"
14 #include "include/core/SkRegion.h"
15 #include "include/core/SkSurfaceProps.h"
16 #include "include/private/SkNoncopyable.h"
17 
18 class SkBitmap;
19 struct SkDrawShadowRec;
20 class SkCanvasMatrix;
21 class SkGlyphRun;
22 class SkGlyphRunList;
23 class SkImageFilterCache;
24 struct SkIRect;
25 class SkMatrix;
26 class SkRasterHandleAllocator;
27 class SkSpecialImage;
28 
29 class SkBaseDevice : public SkRefCnt {
30 public:
31     SkBaseDevice(const SkImageInfo&, const SkSurfaceProps&);
32 
33     /**
34      *  Return ImageInfo for this device. If the canvas is not backed by pixels
35      *  (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
36      */
imageInfo()37     const SkImageInfo& imageInfo() const { return fInfo; }
38 
39     /**
40      *  Return SurfaceProps for this device.
41      */
surfaceProps()42     const SkSurfaceProps& surfaceProps() const {
43         return fSurfaceProps;
44     }
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      */
getGlobalBounds(SkIRect * bounds)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 
getGlobalBounds()57     SkIRect getGlobalBounds() const {
58         SkIRect bounds;
59         this->getGlobalBounds(&bounds);
60         return bounds;
61     }
62 
width()63     int width() const {
64         return this->imageInfo().width();
65     }
66 
height()67     int height() const {
68         return this->imageInfo().height();
69     }
70 
isOpaque()71     bool isOpaque() const {
72         return this->imageInfo().isOpaque();
73     }
74 
75     bool writePixels(const SkPixmap&, int x, int y);
76 
77     /**
78      *  Try to get write-access to the pixels behind the device. If successful, this returns true
79      *  and fills-out the pixmap parameter. On success it also bumps the genID of the underlying
80      *  bitmap.
81      *
82      *  On failure, returns false and ignores the pixmap parameter.
83      */
84     bool accessPixels(SkPixmap* pmap);
85 
86     /**
87      *  Try to get read-only-access to the pixels behind the device. If successful, this returns
88      *  true and fills-out the pixmap parameter.
89      *
90      *  On failure, returns false and ignores the pixmap parameter.
91      */
92     bool peekPixels(SkPixmap*);
93 
94     /**
95      *  Return the device's origin: its offset in device coordinates from
96      *  the default origin in its canvas' matrix/clip
97      */
getOrigin()98     const SkIPoint& getOrigin() const { return fOrigin; }
99 
getRasterHandle()100     virtual void* getRasterHandle() const { return nullptr; }
101 
save()102     void save() { this->onSave(); }
restore(const SkCanvasMatrix & ctm)103     void restore(const SkCanvasMatrix& ctm) {
104         this->onRestore();
105         this->setGlobalCTM(ctm);
106     }
restoreLocal(const SkMatrix & localToDevice)107     void restoreLocal(const SkMatrix& localToDevice) {
108         this->onRestore();
109         this->setLocalToDevice(localToDevice);
110     }
clipRect(const SkRect & rect,SkClipOp op,bool aa)111     void clipRect(const SkRect& rect, SkClipOp op, bool aa) {
112         this->onClipRect(rect, op, aa);
113     }
clipRRect(const SkRRect & rrect,SkClipOp op,bool aa)114     void clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
115         this->onClipRRect(rrect, op, aa);
116     }
clipPath(const SkPath & path,SkClipOp op,bool aa)117     void clipPath(const SkPath& path, SkClipOp op, bool aa) {
118         this->onClipPath(path, op, aa);
119     }
clipRegion(const SkRegion & region,SkClipOp op)120     void clipRegion(const SkRegion& region, SkClipOp op) {
121         this->onClipRegion(region, op);
122     }
androidFramework_setDeviceClipRestriction(SkIRect * mutableClipRestriction)123     void androidFramework_setDeviceClipRestriction(SkIRect* mutableClipRestriction) {
124         this->onSetDeviceClipRestriction(mutableClipRestriction);
125     }
clipIsWideOpen()126     bool clipIsWideOpen() const {
127         return this->onClipIsWideOpen();
128     }
129 
localToDevice()130     const SkMatrix& localToDevice() const { return fLocalToDevice; }
setLocalToDevice(const SkMatrix & localToDevice)131     void setLocalToDevice(const SkMatrix& localToDevice) {
132         fLocalToDevice = localToDevice;
133     }
134     void setGlobalCTM(const SkCanvasMatrix& ctm);
validateDevBounds(const SkIRect &)135     virtual void validateDevBounds(const SkIRect&) {}
136 
android_utils_clipWithStencil()137     virtual bool android_utils_clipWithStencil() { return false; }
138 
139 protected:
140     enum TileUsage {
141         kPossible_TileUsage,    //!< the created device may be drawn tiled
142         kNever_TileUsage,       //!< the created device will never be drawn tiled
143     };
144 
145     struct TextFlags {
146         uint32_t    fFlags;     // SkPaint::getFlags()
147     };
148 
onSave()149     virtual void onSave() {}
onRestore()150     virtual void onRestore() {}
onClipRect(const SkRect & rect,SkClipOp,bool aa)151     virtual void onClipRect(const SkRect& rect, SkClipOp, bool aa) {}
onClipRRect(const SkRRect & rrect,SkClipOp,bool aa)152     virtual void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) {}
onClipPath(const SkPath & path,SkClipOp,bool aa)153     virtual void onClipPath(const SkPath& path, SkClipOp, bool aa) {}
onClipRegion(const SkRegion & deviceRgn,SkClipOp)154     virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp) {}
onSetDeviceClipRestriction(SkIRect * mutableClipRestriction)155     virtual void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) {}
156     virtual bool onClipIsAA() const = 0;
157     virtual bool onClipIsWideOpen() const = 0;
158     virtual void onAsRgnClip(SkRegion*) const = 0;
159     enum class ClipType {
160         kEmpty,
161         kRect,
162         kComplex
163     };
164     virtual ClipType onGetClipType() const = 0;
165 
166     /** These are called inside the per-device-layer loop for each draw call.
167      When these are called, we have already applied any saveLayer operations,
168      and are handling any looping from the paint.
169      */
170     virtual void drawPaint(const SkPaint& paint) = 0;
171     virtual void drawPoints(SkCanvas::PointMode mode, size_t count,
172                             const SkPoint[], const SkPaint& paint) = 0;
173     virtual void drawRect(const SkRect& r,
174                           const SkPaint& paint) = 0;
175     virtual void drawRegion(const SkRegion& r,
176                             const SkPaint& paint);
177     virtual void drawOval(const SkRect& oval,
178                           const SkPaint& paint) = 0;
179     /** By the time this is called we know that abs(sweepAngle) is in the range [0, 360). */
180     virtual void drawArc(const SkRect& oval, SkScalar startAngle,
181                          SkScalar sweepAngle, bool useCenter, const SkPaint& paint);
182     virtual void drawRRect(const SkRRect& rr,
183                            const SkPaint& paint) = 0;
184 
185     // Default impl calls drawPath()
186     virtual void drawDRRect(const SkRRect& outer,
187                             const SkRRect& inner, const SkPaint&);
188 
189     /**
190      *  If pathIsMutable, then the implementation is allowed to cast path to a
191      *  non-const pointer and modify it in place (as an optimization). Canvas
192      *  may do this to implement helpers such as drawOval, by placing a temp
193      *  path on the stack to hold the representation of the oval.
194      */
195     virtual void drawPath(const SkPath& path,
196                           const SkPaint& paint,
197                           bool pathIsMutable = false) = 0;
198     virtual void drawSprite(const SkBitmap& bitmap,
199                             int x, int y, const SkPaint& paint) = 0;
200 
201     /**
202      *  The default impl. will create a bitmap-shader from the bitmap,
203      *  and call drawRect with it.
204      */
205     virtual void drawBitmapRect(const SkBitmap&,
206                                 const SkRect* srcOrNull, const SkRect& dst,
207                                 const SkPaint& paint,
208                                 SkCanvas::SrcRectConstraint) = 0;
209     virtual void drawBitmapNine(const SkBitmap&, const SkIRect& center,
210                                 const SkRect& dst, const SkPaint&);
211     virtual void drawBitmapLattice(const SkBitmap&, const SkCanvas::Lattice&,
212                                    const SkRect& dst, const SkPaint&);
213 
214     virtual void drawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
215                                const SkPaint&, SkCanvas::SrcRectConstraint);
216     virtual void drawImageNine(const SkImage*, const SkIRect& center,
217                                const SkRect& dst, const SkPaint&);
218     virtual void drawImageLattice(const SkImage*, const SkCanvas::Lattice&,
219                                   const SkRect& dst, const SkPaint&);
220 
221     virtual void drawVertices(const SkVertices*, const SkVertices::Bone bones[], int boneCount,
222                               SkBlendMode, const SkPaint&) = 0;
223     virtual void drawShadow(const SkPath&, const SkDrawShadowRec&);
224 
225     virtual void drawGlyphRunList(const SkGlyphRunList& glyphRunList) = 0;
226     // default implementation calls drawVertices
227     virtual void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
228                            const SkPoint texCoords[4], SkBlendMode, const SkPaint& paint);
229 
230     // default implementation calls drawPath
231     virtual void drawAtlas(const SkImage* atlas, const SkRSXform[], const SkRect[],
232                            const SkColor[], int count, SkBlendMode, const SkPaint&);
233 
drawAnnotation(const SkRect &,const char[],SkData *)234     virtual void drawAnnotation(const SkRect&, const char[], SkData*) {}
235 
236     // Default impl always calls drawRect() with a solid-color paint, setting it to anti-aliased
237     // only when all edge flags are set. If there's a clip region, it draws that using drawPath,
238     // or uses clipPath().
239     virtual void drawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4],
240                                 SkCanvas::QuadAAFlags aaFlags, const SkColor4f& color,
241                                 SkBlendMode mode);
242     // Default impl uses drawImageRect per entry, being anti-aliased only when an entry's edge flags
243     // are all set. If there's a clip region, it will be applied using clipPath().
244     virtual void drawEdgeAAImageSet(const SkCanvas::ImageSetEntry[], int count,
245                                     const SkPoint dstClips[], const SkMatrix preViewMatrices[],
246                                     const SkPaint& paint, SkCanvas::SrcRectConstraint);
247 
248     /** The SkDevice passed will be an SkDevice which was returned by a call to
249         onCreateDevice on this device with kNeverTile_TileExpectation.
250      */
251     virtual void drawDevice(SkBaseDevice*, int x, int y, const SkPaint&) = 0;
252 
253     void drawGlyphRunRSXform(const SkFont&, const SkGlyphID[], const SkRSXform[], int count,
254                              SkPoint origin, const SkPaint& paint);
255 
256     virtual void drawDrawable(SkDrawable*, const SkMatrix*, SkCanvas*);
257 
258     virtual void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
259                              SkImage* clipImage, const SkMatrix& clipMatrix);
260     virtual sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&);
261     virtual sk_sp<SkSpecialImage> makeSpecial(const SkImage*);
262     // Get a view of the entire device's current contents as an image.
263     sk_sp<SkSpecialImage> snapSpecial();
264     // Snap the 'subset' contents from this device, possibly as a read-only view. If 'forceCopy'
265     // is true then the returned image's pixels must not be affected by subsequent draws into the
266     // device. When 'forceCopy' is false, the image can be a view into the device's pixels
267     // (avoiding a copy for performance, at the expense of safety). Default returns null.
268     virtual sk_sp<SkSpecialImage> snapSpecial(const SkIRect& subset, bool forceCopy = false);
269 
setImmutable()270     virtual void setImmutable() {}
271 
272     bool readPixels(const SkPixmap&, int x, int y);
273 
274     ///////////////////////////////////////////////////////////////////////////
275 
context()276     virtual GrContext* context() const { return nullptr; }
277 
278     virtual sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&);
onPeekPixels(SkPixmap *)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 
onAccessPixels(SkPixmap *)297     virtual bool onAccessPixels(SkPixmap*) { return false; }
298 
299     struct CreateInfo {
300         static SkPixelGeometry AdjustGeometry(TileUsage, SkPixelGeometry);
301 
302         // The constructor may change the pixel geometry based on other parameters.
CreateInfoCreateInfo303         CreateInfo(const SkImageInfo& info,
304                    TileUsage tileUsage,
305                    SkPixelGeometry geo,
306                    bool trackCoverage,
307                    SkRasterHandleAllocator* allocator)
308             : fInfo(info)
309             , fTileUsage(tileUsage)
310             , fPixelGeometry(AdjustGeometry(tileUsage, geo))
311             , fTrackCoverage(trackCoverage)
312             , fAllocator(allocator)
313         {}
314 
315         const SkImageInfo       fInfo;
316         const TileUsage         fTileUsage;
317         const SkPixelGeometry   fPixelGeometry;
318         const bool              fTrackCoverage = false;
319         SkRasterHandleAllocator* fAllocator = nullptr;
320     };
321 
322     /**
323      *  Create a new device based on CreateInfo. If the paint is not null, then it represents a
324      *  preview of how the new device will be composed with its creator device (this).
325      *
326      *  The subclass may be handed this device in drawDevice(), so it must always return
327      *  a device that it knows how to draw, and that it knows how to identify if it is not of the
328      *  same subclass (since drawDevice is passed a SkBaseDevice*). If the subclass cannot fulfill
329      *  that contract (e.g. PDF cannot support some settings on the paint) it should return NULL,
330      *  and the caller may then decide to explicitly create a bitmapdevice, knowing that later
331      *  it could not call drawDevice with it (but it could call drawSprite or drawBitmap).
332      */
onCreateDevice(const CreateInfo &,const SkPaint *)333     virtual SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) {
334         return nullptr;
335     }
336 
337     // A helper function used by derived classes to log the scale factor of a bitmap or image draw.
338     static void LogDrawScaleFactor(const SkMatrix& view, const SkMatrix& srcToDst, SkFilterQuality);
339 
340 private:
341     friend class SkAndroidFrameworkUtils;
342     friend class SkCanvas;
343     friend struct DeviceCM; //for setMatrixClip
344     friend class SkDraw;
345     friend class SkDrawIter;
346     friend class SkSurface_Raster;
347     friend class DeviceTestingAccess;
348 
349     // Temporarily friend the SkGlyphRunBuilder until drawPosText is gone.
350     friend class SkGlyphRun;
351     friend class SkGlyphRunList;
352     friend class SkGlyphRunBuilder;
353 
354     // used to change the backend's pixels (and possibly config/rowbytes)
355     // but cannot change the width/height, so there should be no change to
356     // any clip information.
357     // TODO: move to SkBitmapDevice
replaceBitmapBackendForRasterSurface(const SkBitmap &)358     virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) {}
359 
forceConservativeRasterClip()360     virtual bool forceConservativeRasterClip() const { return false; }
361 
362     /**
363      * Don't call this!
364      */
accessRenderTargetContext()365     virtual GrRenderTargetContext* accessRenderTargetContext() { return nullptr; }
366 
367     // just called by SkCanvas when built as a layer
368     void setOrigin(const SkMatrix& ctm, int x, int y);
369 
370     /** Causes any deferred drawing to the device to be completed.
371      */
flush()372     virtual void flush() {}
373 
getImageFilterCache()374     virtual SkImageFilterCache* getImageFilterCache() { return nullptr; }
375 
376     friend class SkNoPixelsDevice;
377     friend class SkBitmapDevice;
privateResize(int w,int h)378     void privateResize(int w, int h) {
379         *const_cast<SkImageInfo*>(&fInfo) = fInfo.makeWH(w, h);
380     }
381 
382     SkIPoint             fOrigin;
383     const SkImageInfo    fInfo;
384     const SkSurfaceProps fSurfaceProps;
385     SkMatrix             fLocalToDevice;
386 
387     typedef SkRefCnt INHERITED;
388 };
389 
390 class SkNoPixelsDevice : public SkBaseDevice {
391 public:
392     SkNoPixelsDevice(const SkIRect& bounds, const SkSurfaceProps& props,
393                      sk_sp<SkColorSpace> colorSpace = nullptr)
394             : SkBaseDevice(SkImageInfo::Make(bounds.size(), kUnknown_SkColorType,
395                                              kUnknown_SkAlphaType, std::move(colorSpace)),
396                            props) {
397         // this fails if we enable this assert: DiscardableImageMapTest.GetDiscardableImagesInRectMaxImage
398         //SkASSERT(bounds.width() >= 0 && bounds.height() >= 0);
399 
400         this->setOrigin(SkMatrix::I(), bounds.left(), bounds.top());
401     }
402 
resetForNextPicture(const SkIRect & bounds)403     void resetForNextPicture(const SkIRect& bounds) {
404         //SkASSERT(bounds.width() >= 0 && bounds.height() >= 0);
405         this->privateResize(bounds.width(), bounds.height());
406         this->setOrigin(SkMatrix::I(), bounds.left(), bounds.top());
407     }
408 
409 protected:
410     // We don't track the clip at all (for performance), but we have to respond to some queries.
411     // We pretend to be wide-open. We could pretend to always be empty, but that *seems* worse.
onSave()412     void onSave() override {}
onRestore()413     void onRestore() override {}
onClipRect(const SkRect & rect,SkClipOp,bool aa)414     void onClipRect(const SkRect& rect, SkClipOp, bool aa) override {}
onClipRRect(const SkRRect & rrect,SkClipOp,bool aa)415     void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) override {}
onClipPath(const SkPath & path,SkClipOp,bool aa)416     void onClipPath(const SkPath& path, SkClipOp, bool aa) override {}
onClipRegion(const SkRegion & deviceRgn,SkClipOp)417     void onClipRegion(const SkRegion& deviceRgn, SkClipOp) override {}
onSetDeviceClipRestriction(SkIRect * mutableClipRestriction)418     void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) override {}
onClipIsAA()419     bool onClipIsAA() const override { return false; }
onClipIsWideOpen()420     bool onClipIsWideOpen() const override { return true; }
onAsRgnClip(SkRegion * rgn)421     void onAsRgnClip(SkRegion* rgn) const override {
422         rgn->setRect(SkIRect::MakeWH(this->width(), this->height()));
423     }
onGetClipType()424     ClipType onGetClipType() const override {
425         return ClipType::kRect;
426     }
427 
drawPaint(const SkPaint & paint)428     void drawPaint(const SkPaint& paint) override {}
drawPoints(SkCanvas::PointMode,size_t,const SkPoint[],const SkPaint &)429     void drawPoints(SkCanvas::PointMode, size_t, const SkPoint[], const SkPaint&) override {}
drawRect(const SkRect &,const SkPaint &)430     void drawRect(const SkRect&, const SkPaint&) override {}
drawOval(const SkRect &,const SkPaint &)431     void drawOval(const SkRect&, const SkPaint&) override {}
drawRRect(const SkRRect &,const SkPaint &)432     void drawRRect(const SkRRect&, const SkPaint&) override {}
drawPath(const SkPath &,const SkPaint &,bool)433     void drawPath(const SkPath&, const SkPaint&, bool) override {}
drawSprite(const SkBitmap &,int,int,const SkPaint &)434     void drawSprite(const SkBitmap&, int, int, const SkPaint&) override {}
drawBitmapRect(const SkBitmap &,const SkRect *,const SkRect &,const SkPaint &,SkCanvas::SrcRectConstraint)435     void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint&,
436                         SkCanvas::SrcRectConstraint) override {}
drawDevice(SkBaseDevice *,int,int,const SkPaint &)437     void drawDevice(SkBaseDevice*, int, int, const SkPaint&) override {}
drawGlyphRunList(const SkGlyphRunList & glyphRunList)438     void drawGlyphRunList(const SkGlyphRunList& glyphRunList) override {}
drawVertices(const SkVertices *,const SkVertices::Bone[],int,SkBlendMode,const SkPaint &)439     void drawVertices(const SkVertices*, const SkVertices::Bone[], int, SkBlendMode,
440                       const SkPaint&) override {}
441 
442 private:
443     typedef SkBaseDevice INHERITED;
444 };
445 
446 class SkAutoDeviceTransformRestore : SkNoncopyable {
447 public:
SkAutoDeviceTransformRestore(SkBaseDevice * device,const SkMatrix & localToDevice)448     SkAutoDeviceTransformRestore(SkBaseDevice* device, const SkMatrix& localToDevice)
449         : fDevice(device)
450         , fPrevLocalToDevice(device->localToDevice())
451     {
452         fDevice->setLocalToDevice(localToDevice);
453     }
~SkAutoDeviceTransformRestore()454     ~SkAutoDeviceTransformRestore() {
455         fDevice->setLocalToDevice(fPrevLocalToDevice);
456     }
457 
458 private:
459     SkBaseDevice*   fDevice;
460     const SkMatrix  fPrevLocalToDevice;
461 };
462 
463 #endif
464