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