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