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