Line data Source code
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 59 : 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 : */
34 1572 : const SkImageInfo& imageInfo() const { return fInfo; }
35 :
36 : /**
37 : * Return SurfaceProps for this device.
38 : */
39 85 : const SkSurfaceProps& surfaceProps() const {
40 85 : 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 129 : void getGlobalBounds(SkIRect* bounds) const {
49 129 : SkASSERT(bounds);
50 129 : const SkIPoint& origin = this->getOrigin();
51 129 : bounds->setXYWH(origin.x(), origin.y(), this->width(), this->height());
52 129 : }
53 :
54 129 : SkIRect getGlobalBounds() const {
55 : SkIRect bounds;
56 129 : this->getGlobalBounds(&bounds);
57 129 : return bounds;
58 : }
59 :
60 703 : int width() const {
61 703 : return this->imageInfo().width();
62 : }
63 :
64 703 : int height() const {
65 703 : return this->imageInfo().height();
66 : }
67 :
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 : */
95 1379 : const SkIPoint& getOrigin() const { return fOrigin; }
96 :
97 0 : virtual void* getRasterHandle() const { return nullptr; }
98 :
99 617 : void save() { this->onSave(); }
100 617 : void restore(const SkMatrix& ctm) {
101 617 : this->onRestore();
102 617 : this->setGlobalCTM(ctm);
103 617 : }
104 532 : void clipRect(const SkRect& rect, SkClipOp op, bool aa) {
105 532 : this->onClipRect(rect, op, aa);
106 532 : }
107 0 : void clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
108 0 : this->onClipRRect(rrect, op, aa);
109 0 : }
110 39 : void clipPath(const SkPath& path, SkClipOp op, bool aa) {
111 39 : this->onClipPath(path, op, aa);
112 39 : }
113 24 : void clipRegion(const SkRegion& region, SkClipOp op) {
114 24 : this->onClipRegion(region, op);
115 24 : }
116 85 : void androidFramework_setDeviceClipRestriction(SkIRect* mutableClipRestriction) {
117 85 : this->onSetDeviceClipRestriction(mutableClipRestriction);
118 85 : }
119 : bool clipIsWideOpen() const;
120 :
121 1167 : const SkMatrix& ctm() const { return fCTM; }
122 0 : void setCTM(const SkMatrix& ctm) {
123 0 : fCTM = ctm;
124 0 : }
125 : void setGlobalCTM(const SkMatrix& ctm);
126 0 : 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 0 : virtual bool onShouldDisableLCD(const SkPaint&) const { return false; }
145 :
146 0 : virtual void onSave() {}
147 0 : virtual void onRestore() {}
148 0 : virtual void onClipRect(const SkRect& rect, SkClipOp, bool aa) {}
149 0 : virtual void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) {}
150 0 : virtual void onClipPath(const SkPath& path, SkClipOp, bool aa) {}
151 0 : virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp) {}
152 0 : 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 :
248 0 : 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 :
270 0 : virtual GrContext* context() const { return nullptr; }
271 :
272 : virtual sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&);
273 0 : 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 :
291 0 : virtual bool onAccessPixels(SkPixmap*) { return false; }
292 :
293 22 : 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.
298 : 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 :
306 22 : CreateInfo(const SkImageInfo& info,
307 : TileUsage tileUsage,
308 : SkPixelGeometry geo,
309 : bool preserveLCDText,
310 : SkRasterHandleAllocator* allocator)
311 22 : : fInfo(info)
312 : , fTileUsage(tileUsage)
313 22 : , fPixelGeometry(AdjustGeometry(info, tileUsage, geo, preserveLCDText))
314 44 : , fAllocator(allocator)
315 22 : {}
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 : */
334 0 : virtual SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) {
335 0 : 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
355 0 : virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) {}
356 :
357 63 : virtual bool forceConservativeRasterClip() const { return false; }
358 :
359 : /**
360 : * Don't call this!
361 : */
362 0 : 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 : */
369 47 : virtual void flush() {}
370 :
371 0 : virtual SkImageFilterCache* getImageFilterCache() { return NULL; }
372 :
373 : friend class SkNoPixelsDevice;
374 : friend class SkBitmapDevice;
375 0 : void privateResize(int w, int h) {
376 0 : *const_cast<SkImageInfo*>(&fInfo) = fInfo.makeWH(w, h);
377 0 : }
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:
389 0 : SkAutoDeviceCTMRestore(SkBaseDevice* device, const SkMatrix& ctm)
390 0 : : fDevice(device)
391 0 : , fPrevCTM(device->ctm())
392 : {
393 0 : fDevice->setCTM(ctm);
394 0 : }
395 0 : ~SkAutoDeviceCTMRestore() {
396 0 : fDevice->setCTM(fPrevCTM);
397 0 : }
398 :
399 : private:
400 : SkBaseDevice* fDevice;
401 : const SkMatrix fPrevCTM;
402 : };
403 :
404 : #endif
|