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