• 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 "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      */
imageInfo()34     const SkImageInfo& imageInfo() const { return fInfo; }
35 
36     /**
37      *  Return SurfaceProps for this device.
38      */
surfaceProps()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      */
getGlobalBounds(SkIRect * bounds)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 
getGlobalBounds()54     SkIRect getGlobalBounds() const {
55         SkIRect bounds;
56         this->getGlobalBounds(&bounds);
57         return bounds;
58     }
59 
width()60     int width() const {
61         return this->imageInfo().width();
62     }
63 
height()64     int height() const {
65         return this->imageInfo().height();
66     }
67 
isOpaque()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      */
getOrigin()95     const SkIPoint& getOrigin() const { return fOrigin; }
96 
getRasterHandle()97     virtual void* getRasterHandle() const { return nullptr; }
98 
save()99     void save() { this->onSave(); }
restore(const SkMatrix & ctm)100     void restore(const SkMatrix& ctm) {
101         this->onRestore();
102         this->setGlobalCTM(ctm);
103     }
clipRect(const SkRect & rect,SkClipOp op,bool aa)104     void clipRect(const SkRect& rect, SkClipOp op, bool aa) {
105         this->onClipRect(rect, op, aa);
106     }
clipRRect(const SkRRect & rrect,SkClipOp op,bool aa)107     void clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
108         this->onClipRRect(rrect, op, aa);
109     }
clipPath(const SkPath & path,SkClipOp op,bool aa)110     void clipPath(const SkPath& path, SkClipOp op, bool aa) {
111         this->onClipPath(path, op, aa);
112     }
clipRegion(const SkRegion & region,SkClipOp op)113     void clipRegion(const SkRegion& region, SkClipOp op) {
114         this->onClipRegion(region, op);
115     }
androidFramework_setDeviceClipRestriction(SkIRect * mutableClipRestriction)116     void androidFramework_setDeviceClipRestriction(SkIRect* mutableClipRestriction) {
117         this->onSetDeviceClipRestriction(mutableClipRestriction);
118     }
119     bool clipIsWideOpen() const;
120 
ctm()121     const SkMatrix& ctm() const { return fCTM; }
setCTM(const SkMatrix & ctm)122     void setCTM(const SkMatrix& ctm) {
123         fCTM = ctm;
124     }
125     void setGlobalCTM(const SkMatrix& ctm);
validateDevBounds(const SkIRect &)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 
onShouldDisableLCD(const SkPaint &)144     virtual bool onShouldDisableLCD(const SkPaint&) const { return false; }
145 
onSave()146     virtual void onSave() {}
onRestore()147     virtual void onRestore() {}
onClipRect(const SkRect & rect,SkClipOp,bool aa)148     virtual void onClipRect(const SkRect& rect, SkClipOp, bool aa) {}
onClipRRect(const SkRRect & rrect,SkClipOp,bool aa)149     virtual void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) {}
onClipPath(const SkPath & path,SkClipOp,bool aa)150     virtual void onClipPath(const SkPath& path, SkClipOp, bool aa) {}
onClipRegion(const SkRegion & deviceRgn,SkClipOp)151     virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp) {}
onSetDeviceClipRestriction(SkIRect * mutableClipRestriction)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 
drawAnnotation(const SkRect &,const char[],SkData *)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 
context()270     virtual GrContext* context() const { return nullptr; }
271 
272     virtual sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&);
onPeekPixels(SkPixmap *)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 
onAccessPixels(SkPixmap *)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.
CreateInfoCreateInfo298         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 
CreateInfoCreateInfo306         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      */
onCreateDevice(const CreateInfo &,const SkPaint *)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
replaceBitmapBackendForRasterSurface(const SkBitmap &)355     virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) {}
356 
forceConservativeRasterClip()357     virtual bool forceConservativeRasterClip() const { return false; }
358 
359     /**
360      * Don't call this!
361      */
accessRenderTargetContext()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      */
flush()369     virtual void flush() {}
370 
getImageFilterCache()371     virtual SkImageFilterCache* getImageFilterCache() { return NULL; }
372 
373     friend class SkNoPixelsDevice;
374     friend class SkBitmapDevice;
privateResize(int w,int h)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:
SkAutoDeviceCTMRestore(SkBaseDevice * device,const SkMatrix & ctm)389     SkAutoDeviceCTMRestore(SkBaseDevice* device, const SkMatrix& ctm)
390         : fDevice(device)
391         , fPrevCTM(device->ctm())
392     {
393         fDevice->setCTM(ctm);
394     }
~SkAutoDeviceCTMRestore()395     ~SkAutoDeviceCTMRestore() {
396         fDevice->setCTM(fPrevCTM);
397     }
398 
399 private:
400     SkBaseDevice*   fDevice;
401     const SkMatrix  fPrevCTM;
402 };
403 
404 #endif
405