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