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 "SkRegion.h"
15 #include "SkSurfaceProps.h"
16 
17 class SkBitmap;
18 struct SkDrawShadowRec;
19 class SkGlyphRun;
20 class SkGlyphRunList;
21 class SkImageFilterCache;
22 struct SkIRect;
23 class SkMatrix;
24 class SkRasterHandleAllocator;
25 class SkSpecialImage;
26 
27 class 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      */
imageInfo()35     const SkImageInfo& imageInfo() const { return fInfo; }
36 
37     /**
38      *  Return SurfaceProps for this device.
39      */
surfaceProps()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      */
getGlobalBounds(SkIRect * bounds)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 
getGlobalBounds()55     SkIRect getGlobalBounds() const {
56         SkIRect bounds;
57         this->getGlobalBounds(&bounds);
58         return bounds;
59     }
60 
width()61     int width() const {
62         return this->imageInfo().width();
63     }
64 
height()65     int height() const {
66         return this->imageInfo().height();
67     }
68 
isOpaque()69     bool isOpaque() const {
70         return this->imageInfo().isOpaque();
71     }
72 
73     bool writePixels(const SkPixmap&, 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      */
getOrigin()96     const SkIPoint& getOrigin() const { return fOrigin; }
97 
getRasterHandle()98     virtual void* getRasterHandle() const { return nullptr; }
99 
save()100     void save() { this->onSave(); }
restore(const SkMatrix & ctm)101     void restore(const SkMatrix& ctm) {
102         this->onRestore();
103         this->setGlobalCTM(ctm);
104     }
clipRect(const SkRect & rect,SkClipOp op,bool aa)105     void clipRect(const SkRect& rect, SkClipOp op, bool aa) {
106         this->onClipRect(rect, op, aa);
107     }
clipRRect(const SkRRect & rrect,SkClipOp op,bool aa)108     void clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
109         this->onClipRRect(rrect, op, aa);
110     }
clipPath(const SkPath & path,SkClipOp op,bool aa)111     void clipPath(const SkPath& path, SkClipOp op, bool aa) {
112         this->onClipPath(path, op, aa);
113     }
clipRegion(const SkRegion & region,SkClipOp op)114     void clipRegion(const SkRegion& region, SkClipOp op) {
115         this->onClipRegion(region, op);
116     }
androidFramework_setDeviceClipRestriction(SkIRect * mutableClipRestriction)117     void androidFramework_setDeviceClipRestriction(SkIRect* mutableClipRestriction) {
118         this->onSetDeviceClipRestriction(mutableClipRestriction);
119     }
120     bool clipIsWideOpen() const;
121 
ctm()122     const SkMatrix& ctm() const { return fCTM; }
setCTM(const SkMatrix & ctm)123     void setCTM(const SkMatrix& ctm) {
124         fCTM = ctm;
125     }
126     void setGlobalCTM(const SkMatrix& ctm);
validateDevBounds(const SkIRect &)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 
onSave()139     virtual void onSave() {}
onRestore()140     virtual void onRestore() {}
onClipRect(const SkRect & rect,SkClipOp,bool aa)141     virtual void onClipRect(const SkRect& rect, SkClipOp, bool aa) {}
onClipRRect(const SkRRect & rrect,SkClipOp,bool aa)142     virtual void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) {}
onClipPath(const SkPath & path,SkClipOp,bool aa)143     virtual void onClipPath(const SkPath& path, SkClipOp, bool aa) {}
onClipRegion(const SkRegion & deviceRgn,SkClipOp)144     virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp) {}
onSetDeviceClipRestriction(SkIRect * mutableClipRestriction)145     virtual void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) {}
146     virtual bool onClipIsAA() const = 0;
147     virtual void onAsRgnClip(SkRegion*) const = 0;
148     enum ClipType {
149         kEmpty_ClipType,
150         kRect_ClipType,
151         kComplex_ClipType
152     };
153     virtual ClipType onGetClipType() const = 0;
154 
155     /** These are called inside the per-device-layer loop for each draw call.
156      When these are called, we have already applied any saveLayer operations,
157      and are handling any looping from the paint.
158      */
159     virtual void drawPaint(const SkPaint& paint) = 0;
160     virtual void drawPoints(SkCanvas::PointMode mode, size_t count,
161                             const SkPoint[], const SkPaint& paint) = 0;
162     virtual void drawRect(const SkRect& r,
163                           const SkPaint& paint) = 0;
164     virtual void drawRegion(const SkRegion& r,
165                             const SkPaint& paint);
166     virtual void drawOval(const SkRect& oval,
167                           const SkPaint& paint) = 0;
168     /** By the time this is called we know that abs(sweepAngle) is in the range [0, 360). */
169     virtual void drawArc(const SkRect& oval, SkScalar startAngle,
170                          SkScalar sweepAngle, bool useCenter, const SkPaint& paint);
171     virtual void drawRRect(const SkRRect& rr,
172                            const SkPaint& paint) = 0;
173 
174     // Default impl calls drawPath()
175     virtual void drawDRRect(const SkRRect& outer,
176                             const SkRRect& inner, const SkPaint&);
177 
178     // Default impl always calls drawRect() with a solid-color paint, setting it to anti-aliased
179     // only when all edge flags are set.
180     virtual void drawEdgeAARect(const SkRect& r, SkCanvas::QuadAAFlags aa, SkColor color,
181                                 SkBlendMode mode);
182 
183     /**
184      *  If pathIsMutable, then the implementation is allowed to cast path to a
185      *  non-const pointer and modify it in place (as an optimization). Canvas
186      *  may do this to implement helpers such as drawOval, by placing a temp
187      *  path on the stack to hold the representation of the oval.
188      */
189     virtual void drawPath(const SkPath& path,
190                           const SkPaint& paint,
191                           bool pathIsMutable = false) = 0;
192     virtual void drawBitmap(const SkBitmap& bitmap,
193                             SkScalar x,
194                             SkScalar y,
195                             const SkPaint& paint) = 0;
196     virtual void drawSprite(const SkBitmap& bitmap,
197                             int x, int y, const SkPaint& paint) = 0;
198 
199     /**
200      *  The default impl. will create a bitmap-shader from the bitmap,
201      *  and call drawRect with it.
202      */
203     virtual void drawBitmapRect(const SkBitmap&,
204                                 const SkRect* srcOrNull, const SkRect& dst,
205                                 const SkPaint& paint,
206                                 SkCanvas::SrcRectConstraint) = 0;
207     virtual void drawBitmapNine(const SkBitmap&, const SkIRect& center,
208                                 const SkRect& dst, const SkPaint&);
209     virtual void drawBitmapLattice(const SkBitmap&, const SkCanvas::Lattice&,
210                                    const SkRect& dst, const SkPaint&);
211 
212     virtual void drawImage(const SkImage*, SkScalar x, SkScalar y, const SkPaint&);
213     virtual void drawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
214                                const SkPaint&, SkCanvas::SrcRectConstraint);
215     virtual void drawImageNine(const SkImage*, const SkIRect& center,
216                                const SkRect& dst, const SkPaint&);
217     virtual void drawImageLattice(const SkImage*, const SkCanvas::Lattice&,
218                                   const SkRect& dst, const SkPaint&);
219 
220     virtual void drawImageSet(const SkCanvas::ImageSetEntry[], int count, SkFilterQuality,
221                               SkBlendMode);
222 
223     virtual void drawVertices(const SkVertices*, const SkVertices::Bone bones[], int boneCount,
224                               SkBlendMode, const SkPaint&) = 0;
225     virtual void drawShadow(const SkPath&, const SkDrawShadowRec&);
226 
227     virtual void drawGlyphRunList(const SkGlyphRunList& glyphRunList) = 0;
228     // default implementation calls drawVertices
229     virtual void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
230                            const SkPoint texCoords[4], SkBlendMode, const SkPaint& paint);
231 
232     // default implementation calls drawPath
233     virtual void drawAtlas(const SkImage* atlas, const SkRSXform[], const SkRect[],
234                            const SkColor[], int count, SkBlendMode, const SkPaint&);
235 
drawAnnotation(const SkRect &,const char[],SkData *)236     virtual void drawAnnotation(const SkRect&, const char[], SkData*) {}
237 
238     /** The SkDevice passed will be an SkDevice which was returned by a call to
239         onCreateDevice on this device with kNeverTile_TileExpectation.
240      */
241     virtual void drawDevice(SkBaseDevice*, int x, int y, const SkPaint&) = 0;
242 
243     void drawGlyphRunRSXform(const SkFont&, const SkGlyphID[], const SkRSXform[], int count,
244                              SkPoint origin, const SkPaint& paint);
245 
246     virtual void drawDrawable(SkDrawable*, const SkMatrix*, SkCanvas*);
247 
248     virtual void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
249                              SkImage* clipImage, const SkMatrix& clipMatrix);
250     virtual sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&);
251     virtual sk_sp<SkSpecialImage> makeSpecial(const SkImage*);
252     virtual sk_sp<SkSpecialImage> snapSpecial();
setImmutable()253     virtual void setImmutable() {}
254 
255     bool readPixels(const SkPixmap&, int x, int y);
256 
257     virtual sk_sp<SkSpecialImage> snapBackImage(const SkIRect&);    // default returns null
258 
259     ///////////////////////////////////////////////////////////////////////////
260 
context()261     virtual GrContext* context() const { return nullptr; }
262 
263     virtual sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&);
onPeekPixels(SkPixmap *)264     virtual bool onPeekPixels(SkPixmap*) { return false; }
265 
266     /**
267      *  The caller is responsible for "pre-clipping" the dst. The impl can assume that the dst
268      *  image at the specified x,y offset will fit within the device's bounds.
269      *
270      *  This is explicitly asserted in readPixels(), the public way to call this.
271      */
272     virtual bool onReadPixels(const SkPixmap&, int x, int y);
273 
274     /**
275      *  The caller is responsible for "pre-clipping" the src. The impl can assume that the src
276      *  image at the specified x,y offset will fit within the device's bounds.
277      *
278      *  This is explicitly asserted in writePixelsDirect(), the public way to call this.
279      */
280     virtual bool onWritePixels(const SkPixmap&, int x, int y);
281 
onAccessPixels(SkPixmap *)282     virtual bool onAccessPixels(SkPixmap*) { return false; }
283 
284     struct CreateInfo {
285         static SkPixelGeometry AdjustGeometry(const SkImageInfo&, TileUsage, SkPixelGeometry,
286                                               bool preserveLCDText);
287 
288         // The constructor may change the pixel geometry based on other parameters.
CreateInfoCreateInfo289         CreateInfo(const SkImageInfo& info,
290                    TileUsage tileUsage,
291                    SkPixelGeometry geo)
292             : fInfo(info)
293             , fTileUsage(tileUsage)
294             , fPixelGeometry(AdjustGeometry(info, tileUsage, geo, false))
295         {}
296 
CreateInfoCreateInfo297         CreateInfo(const SkImageInfo& info,
298                    TileUsage tileUsage,
299                    SkPixelGeometry geo,
300                    bool preserveLCDText,
301                    bool trackCoverage,
302                    SkRasterHandleAllocator* allocator)
303             : fInfo(info)
304             , fTileUsage(tileUsage)
305             , fPixelGeometry(AdjustGeometry(info, tileUsage, geo, preserveLCDText))
306             , fTrackCoverage(trackCoverage)
307             , fAllocator(allocator)
308         {}
309 
310         const SkImageInfo       fInfo;
311         const TileUsage         fTileUsage;
312         const SkPixelGeometry   fPixelGeometry;
313         const bool              fTrackCoverage = false;
314         SkRasterHandleAllocator* fAllocator = nullptr;
315     };
316 
317     /**
318      *  Create a new device based on CreateInfo. If the paint is not null, then it represents a
319      *  preview of how the new device will be composed with its creator device (this).
320      *
321      *  The subclass may be handed this device in drawDevice(), so it must always return
322      *  a device that it knows how to draw, and that it knows how to identify if it is not of the
323      *  same subclass (since drawDevice is passed a SkBaseDevice*). If the subclass cannot fulfill
324      *  that contract (e.g. PDF cannot support some settings on the paint) it should return NULL,
325      *  and the caller may then decide to explicitly create a bitmapdevice, knowing that later
326      *  it could not call drawDevice with it (but it could call drawSprite or drawBitmap).
327      */
onCreateDevice(const CreateInfo &,const SkPaint *)328     virtual SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) {
329         return nullptr;
330     }
331 
332     // A helper function used by derived classes to log the scale factor of a bitmap or image draw.
333     static void LogDrawScaleFactor(const SkMatrix&, SkFilterQuality);
334 
335 private:
336     friend class SkAndroidFrameworkUtils;
337     friend class SkCanvas;
338     friend struct DeviceCM; //for setMatrixClip
339     friend class SkDraw;
340     friend class SkDrawIter;
341     friend class SkSurface_Raster;
342     friend class DeviceTestingAccess;
343 
344     // Temporarily friend the SkGlyphRunBuilder until drawPosText is gone.
345     friend class SkGlyphRun;
346     friend class SkGlyphRunList;
347     friend class SkGlyphRunBuilder;
348 
349     // used to change the backend's pixels (and possibly config/rowbytes)
350     // but cannot change the width/height, so there should be no change to
351     // any clip information.
352     // TODO: move to SkBitmapDevice
replaceBitmapBackendForRasterSurface(const SkBitmap &)353     virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) {}
354 
forceConservativeRasterClip()355     virtual bool forceConservativeRasterClip() const { return false; }
356 
357     /**
358      * Don't call this!
359      */
accessRenderTargetContext()360     virtual GrRenderTargetContext* accessRenderTargetContext() { return nullptr; }
361 
362     // just called by SkCanvas when built as a layer
363     void setOrigin(const SkMatrix& ctm, int x, int y);
364 
365     /** Causes any deferred drawing to the device to be completed.
366      */
flush()367     virtual void flush() {}
368 
getImageFilterCache()369     virtual SkImageFilterCache* getImageFilterCache() { return nullptr; }
370 
371     friend class SkNoPixelsDevice;
372     friend class SkBitmapDevice;
privateResize(int w,int h)373     void privateResize(int w, int h) {
374         *const_cast<SkImageInfo*>(&fInfo) = fInfo.makeWH(w, h);
375     }
376 
377     SkIPoint             fOrigin;
378     const SkImageInfo    fInfo;
379     const SkSurfaceProps fSurfaceProps;
380     SkMatrix             fCTM;
381 
382     typedef SkRefCnt INHERITED;
383 };
384 
385 class SkNoPixelsDevice : public SkBaseDevice {
386 public:
SkNoPixelsDevice(const SkIRect & bounds,const SkSurfaceProps & props)387     SkNoPixelsDevice(const SkIRect& bounds, const SkSurfaceProps& props)
388             : SkBaseDevice(SkImageInfo::MakeUnknown(bounds.width(), bounds.height()), props)
389     {
390         // this fails if we enable this assert: DiscardableImageMapTest.GetDiscardableImagesInRectMaxImage
391         //SkASSERT(bounds.width() >= 0 && bounds.height() >= 0);
392     }
393 
resetForNextPicture(const SkIRect & bounds)394     void resetForNextPicture(const SkIRect& bounds) {
395         //SkASSERT(bounds.width() >= 0 && bounds.height() >= 0);
396         this->privateResize(bounds.width(), bounds.height());
397     }
398 
399 protected:
400     // We don't track the clip at all (for performance), but we have to respond to some queries.
401     // We pretend to be wide-open. We could pretend to always be empty, but that *seems* worse.
onSave()402     void onSave() override {}
onRestore()403     void onRestore() override {}
onClipRect(const SkRect & rect,SkClipOp,bool aa)404     void onClipRect(const SkRect& rect, SkClipOp, bool aa) override {}
onClipRRect(const SkRRect & rrect,SkClipOp,bool aa)405     void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) override {}
onClipPath(const SkPath & path,SkClipOp,bool aa)406     void onClipPath(const SkPath& path, SkClipOp, bool aa) override {}
onClipRegion(const SkRegion & deviceRgn,SkClipOp)407     void onClipRegion(const SkRegion& deviceRgn, SkClipOp) override {}
onSetDeviceClipRestriction(SkIRect * mutableClipRestriction)408     void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) override {}
onClipIsAA()409     bool onClipIsAA() const override { return false; }
onAsRgnClip(SkRegion * rgn)410     void onAsRgnClip(SkRegion* rgn) const override {
411         rgn->setRect(SkIRect::MakeWH(this->width(), this->height()));
412     }
onGetClipType()413     ClipType onGetClipType() const override {
414         return kRect_ClipType;
415     }
416 
drawPaint(const SkPaint & paint)417     void drawPaint(const SkPaint& paint) override {}
drawPoints(SkCanvas::PointMode,size_t,const SkPoint[],const SkPaint &)418     void drawPoints(SkCanvas::PointMode, size_t, const SkPoint[], const SkPaint&) override {}
drawRect(const SkRect &,const SkPaint &)419     void drawRect(const SkRect&, const SkPaint&) override {}
drawOval(const SkRect &,const SkPaint &)420     void drawOval(const SkRect&, const SkPaint&) override {}
drawRRect(const SkRRect &,const SkPaint &)421     void drawRRect(const SkRRect&, const SkPaint&) override {}
drawPath(const SkPath &,const SkPaint &,bool)422     void drawPath(const SkPath&, const SkPaint&, bool) override {}
drawBitmap(const SkBitmap &,SkScalar x,SkScalar y,const SkPaint &)423     void drawBitmap(const SkBitmap&, SkScalar x, SkScalar y, const SkPaint&) override {}
drawSprite(const SkBitmap &,int,int,const SkPaint &)424     void drawSprite(const SkBitmap&, int, int, const SkPaint&) override {}
drawBitmapRect(const SkBitmap &,const SkRect *,const SkRect &,const SkPaint &,SkCanvas::SrcRectConstraint)425     void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint&,
426                         SkCanvas::SrcRectConstraint) override {}
drawDevice(SkBaseDevice *,int,int,const SkPaint &)427     void drawDevice(SkBaseDevice*, int, int, const SkPaint&) override {}
drawGlyphRunList(const SkGlyphRunList & glyphRunList)428     void drawGlyphRunList(const SkGlyphRunList& glyphRunList) override {}
drawVertices(const SkVertices *,const SkVertices::Bone[],int,SkBlendMode,const SkPaint &)429     void drawVertices(const SkVertices*, const SkVertices::Bone[], int, SkBlendMode,
430                       const SkPaint&) override {}
431 
432 private:
433     typedef SkBaseDevice INHERITED;
434 };
435 
436 class SkAutoDeviceCTMRestore : SkNoncopyable {
437 public:
SkAutoDeviceCTMRestore(SkBaseDevice * device,const SkMatrix & ctm)438     SkAutoDeviceCTMRestore(SkBaseDevice* device, const SkMatrix& ctm)
439         : fDevice(device)
440         , fPrevCTM(device->ctm())
441     {
442         fDevice->setCTM(ctm);
443     }
~SkAutoDeviceCTMRestore()444     ~SkAutoDeviceCTMRestore() {
445         fDevice->setCTM(fPrevCTM);
446     }
447 
448 private:
449     SkBaseDevice*   fDevice;
450     const SkMatrix  fPrevCTM;
451 };
452 
453 #endif
454