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 struct SkDrawShadowRec; 19 class SkImageFilterCache; 20 struct SkIRect; 21 class SkMatrix; 22 class SkRasterHandleAllocator; 23 class SkRegion; 24 class SkSpecialImage; 25 class GrRenderTarget; 26 27 class SK_API 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 SkImageInfo&, const void*, size_t rowBytes, 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 139 /** 140 * Returns the text-related flags, possibly modified based on the state of the 141 * device (e.g. support for LCD). 142 */ 143 uint32_t filterTextFlags(const SkPaint&) const; 144 onShouldDisableLCD(const SkPaint &)145 virtual bool onShouldDisableLCD(const SkPaint&) const { return false; } 146 onSave()147 virtual void onSave() {} onRestore()148 virtual void onRestore() {} onClipRect(const SkRect & rect,SkClipOp,bool aa)149 virtual void onClipRect(const SkRect& rect, SkClipOp, bool aa) {} onClipRRect(const SkRRect & rrect,SkClipOp,bool aa)150 virtual void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) {} onClipPath(const SkPath & path,SkClipOp,bool aa)151 virtual void onClipPath(const SkPath& path, SkClipOp, bool aa) {} onClipRegion(const SkRegion & deviceRgn,SkClipOp)152 virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp) {} onSetDeviceClipRestriction(SkIRect * mutableClipRestriction)153 virtual void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) {} 154 virtual bool onClipIsAA() const = 0; 155 virtual void onAsRgnClip(SkRegion*) const = 0; 156 enum ClipType { 157 kEmpty_ClipType, 158 kRect_ClipType, 159 kComplex_ClipType 160 }; 161 virtual ClipType onGetClipType() const = 0; 162 163 /** These are called inside the per-device-layer loop for each draw call. 164 When these are called, we have already applied any saveLayer operations, 165 and are handling any looping from the paint, and any effects from the 166 DrawFilter. 167 */ 168 virtual void drawPaint(const SkPaint& paint) = 0; 169 virtual void drawPoints(SkCanvas::PointMode mode, size_t count, 170 const SkPoint[], const SkPaint& paint) = 0; 171 virtual void drawRect(const SkRect& r, 172 const SkPaint& paint) = 0; 173 virtual void drawRegion(const SkRegion& r, 174 const SkPaint& paint); 175 virtual void drawOval(const SkRect& oval, 176 const SkPaint& paint) = 0; 177 /** By the time this is called we know that abs(sweepAngle) is in the range [0, 360). */ 178 virtual void drawArc(const SkRect& oval, SkScalar startAngle, 179 SkScalar sweepAngle, bool useCenter, const SkPaint& paint); 180 virtual void drawRRect(const SkRRect& rr, 181 const SkPaint& paint) = 0; 182 183 // Default impl calls drawPath() 184 virtual void drawDRRect(const SkRRect& outer, 185 const SkRRect& inner, const SkPaint&); 186 187 /** 188 * If pathIsMutable, then the implementation is allowed to cast path to a 189 * non-const pointer and modify it in place (as an optimization). Canvas 190 * may do this to implement helpers such as drawOval, by placing a temp 191 * path on the stack to hold the representation of the oval. 192 * 193 * If prePathMatrix is not null, it should logically be applied before any 194 * stroking or other effects. If there are no effects on the paint that 195 * affect the geometry/rasterization, then the pre matrix can just be 196 * pre-concated with the current matrix. 197 */ 198 virtual void drawPath(const SkPath& path, 199 const SkPaint& paint, 200 const SkMatrix* prePathMatrix = NULL, 201 bool pathIsMutable = false) = 0; 202 virtual void drawBitmap(const SkBitmap& bitmap, 203 SkScalar x, 204 SkScalar y, 205 const SkPaint& paint) = 0; 206 virtual void drawSprite(const SkBitmap& bitmap, 207 int x, int y, const SkPaint& paint) = 0; 208 209 /** 210 * The default impl. will create a bitmap-shader from the bitmap, 211 * and call drawRect with it. 212 */ 213 virtual void drawBitmapRect(const SkBitmap&, 214 const SkRect* srcOrNull, const SkRect& dst, 215 const SkPaint& paint, 216 SkCanvas::SrcRectConstraint) = 0; 217 virtual void drawBitmapNine(const SkBitmap&, const SkIRect& center, 218 const SkRect& dst, const SkPaint&); 219 virtual void drawBitmapLattice(const SkBitmap&, const SkCanvas::Lattice&, 220 const SkRect& dst, const SkPaint&); 221 222 virtual void drawImage(const SkImage*, SkScalar x, SkScalar y, const SkPaint&); 223 virtual void drawImageRect(const SkImage*, const SkRect* src, const SkRect& dst, 224 const SkPaint&, SkCanvas::SrcRectConstraint); 225 virtual void drawImageNine(const SkImage*, const SkIRect& center, 226 const SkRect& dst, const SkPaint&); 227 virtual void drawImageLattice(const SkImage*, const SkCanvas::Lattice&, 228 const SkRect& dst, const SkPaint&); 229 230 /** 231 * Does not handle text decoration. 232 * Decorations (underline and stike-thru) will be handled by SkCanvas. 233 */ 234 virtual void drawText(const void* text, size_t len, 235 SkScalar x, SkScalar y, const SkPaint& paint) = 0; 236 virtual void drawPosText(const void* text, size_t len, 237 const SkScalar pos[], int scalarsPerPos, 238 const SkPoint& offset, const SkPaint& paint) = 0; 239 virtual void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) = 0; 240 virtual void drawShadow(const SkPath&, const SkDrawShadowRec&); 241 242 // default implementation unrolls the blob runs. 243 virtual void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y, 244 const SkPaint& paint, SkDrawFilter* drawFilter); 245 // default implementation calls drawVertices 246 virtual void drawPatch(const SkPoint cubics[12], const SkColor colors[4], 247 const SkPoint texCoords[4], SkBlendMode, bool interpColorsLinearly, 248 const SkPaint& paint); 249 250 // default implementation calls drawPath 251 virtual void drawAtlas(const SkImage* atlas, const SkRSXform[], const SkRect[], 252 const SkColor[], int count, SkBlendMode, const SkPaint&); 253 drawAnnotation(const SkRect &,const char[],SkData *)254 virtual void drawAnnotation(const SkRect&, const char[], SkData*) {} 255 256 /** The SkDevice passed will be an SkDevice which was returned by a call to 257 onCreateDevice on this device with kNeverTile_TileExpectation. 258 */ 259 virtual void drawDevice(SkBaseDevice*, int x, int y, 260 const SkPaint&) = 0; 261 262 virtual void drawTextOnPath(const void* text, size_t len, const SkPath&, 263 const SkMatrix*, const SkPaint&); 264 virtual void drawTextRSXform(const void* text, size_t len, const SkRSXform[], 265 const SkPaint&); 266 267 virtual void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&, 268 SkImage* clipImage, const SkMatrix& clipMatrix); 269 virtual sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&); 270 virtual sk_sp<SkSpecialImage> makeSpecial(const SkImage*); 271 virtual sk_sp<SkSpecialImage> snapSpecial(); 272 273 bool readPixels(const SkImageInfo&, void* dst, size_t rowBytes, int x, int y); 274 275 /////////////////////////////////////////////////////////////////////////// 276 context()277 virtual GrContext* context() const { return nullptr; } 278 279 virtual sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&); onPeekPixels(SkPixmap *)280 virtual bool onPeekPixels(SkPixmap*) { return false; } 281 282 /** 283 * The caller is responsible for "pre-clipping" the dst. The impl can assume that the dst 284 * image at the specified x,y offset will fit within the device's bounds. 285 * 286 * This is explicitly asserted in readPixels(), the public way to call this. 287 */ 288 virtual bool onReadPixels(const SkImageInfo&, void*, size_t, int x, int y); 289 290 /** 291 * The caller is responsible for "pre-clipping" the src. The impl can assume that the src 292 * image at the specified x,y offset will fit within the device's bounds. 293 * 294 * This is explicitly asserted in writePixelsDirect(), the public way to call this. 295 */ 296 virtual bool onWritePixels(const SkImageInfo&, const void*, size_t, int x, int y); 297 onAccessPixels(SkPixmap *)298 virtual bool onAccessPixels(SkPixmap*) { return false; } 299 300 struct CreateInfo { 301 static SkPixelGeometry AdjustGeometry(const SkImageInfo&, TileUsage, SkPixelGeometry, 302 bool preserveLCDText); 303 304 // The constructor may change the pixel geometry based on other parameters. CreateInfoCreateInfo305 CreateInfo(const SkImageInfo& info, 306 TileUsage tileUsage, 307 SkPixelGeometry geo) 308 : fInfo(info) 309 , fTileUsage(tileUsage) 310 , fPixelGeometry(AdjustGeometry(info, tileUsage, geo, false)) 311 {} 312 CreateInfoCreateInfo313 CreateInfo(const SkImageInfo& info, 314 TileUsage tileUsage, 315 SkPixelGeometry geo, 316 bool preserveLCDText, 317 SkRasterHandleAllocator* allocator) 318 : fInfo(info) 319 , fTileUsage(tileUsage) 320 , fPixelGeometry(AdjustGeometry(info, tileUsage, geo, preserveLCDText)) 321 , fAllocator(allocator) 322 {} 323 324 const SkImageInfo fInfo; 325 const TileUsage fTileUsage; 326 const SkPixelGeometry fPixelGeometry; 327 SkRasterHandleAllocator* fAllocator = nullptr; 328 }; 329 330 /** 331 * Create a new device based on CreateInfo. If the paint is not null, then it represents a 332 * preview of how the new device will be composed with its creator device (this). 333 * 334 * The subclass may be handed this device in drawDevice(), so it must always return 335 * a device that it knows how to draw, and that it knows how to identify if it is not of the 336 * same subclass (since drawDevice is passed a SkBaseDevice*). If the subclass cannot fulfill 337 * that contract (e.g. PDF cannot support some settings on the paint) it should return NULL, 338 * and the caller may then decide to explicitly create a bitmapdevice, knowing that later 339 * it could not call drawDevice with it (but it could call drawSprite or drawBitmap). 340 */ onCreateDevice(const CreateInfo &,const SkPaint *)341 virtual SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) { 342 return NULL; 343 } 344 345 // A helper function used by derived classes to log the scale factor of a bitmap or image draw. 346 static void LogDrawScaleFactor(const SkMatrix&, SkFilterQuality); 347 348 private: 349 friend class SkCanvas; 350 friend struct DeviceCM; //for setMatrixClip 351 friend class SkDraw; 352 friend class SkDrawIter; 353 friend class SkDeviceFilteredPaint; 354 friend class SkNoPixelsBitmapDevice; 355 friend class SkSurface_Raster; 356 friend class DeviceTestingAccess; 357 358 // used to change the backend's pixels (and possibly config/rowbytes) 359 // but cannot change the width/height, so there should be no change to 360 // any clip information. 361 // TODO: move to SkBitmapDevice replaceBitmapBackendForRasterSurface(const SkBitmap &)362 virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) {} 363 forceConservativeRasterClip()364 virtual bool forceConservativeRasterClip() const { return false; } 365 366 /** 367 * Don't call this! 368 */ accessRenderTargetContext()369 virtual GrRenderTargetContext* accessRenderTargetContext() { return nullptr; } 370 371 // just called by SkCanvas when built as a layer 372 void setOrigin(const SkMatrix& ctm, int x, int y); 373 374 /** Causes any deferred drawing to the device to be completed. 375 */ flush()376 virtual void flush() {} 377 getImageFilterCache()378 virtual SkImageFilterCache* getImageFilterCache() { return NULL; } 379 380 friend class SkNoPixelsDevice; 381 friend class SkBitmapDevice; privateResize(int w,int h)382 void privateResize(int w, int h) { 383 *const_cast<SkImageInfo*>(&fInfo) = fInfo.makeWH(w, h); 384 } 385 386 SkIPoint fOrigin; 387 const SkImageInfo fInfo; 388 const SkSurfaceProps fSurfaceProps; 389 SkMatrix fCTM; 390 391 typedef SkRefCnt INHERITED; 392 }; 393 394 class SkAutoDeviceCTMRestore : SkNoncopyable { 395 public: SkAutoDeviceCTMRestore(SkBaseDevice * device,const SkMatrix & ctm)396 SkAutoDeviceCTMRestore(SkBaseDevice* device, const SkMatrix& ctm) 397 : fDevice(device) 398 , fPrevCTM(device->ctm()) 399 { 400 fDevice->setCTM(ctm); 401 } ~SkAutoDeviceCTMRestore()402 ~SkAutoDeviceCTMRestore() { 403 fDevice->setCTM(fPrevCTM); 404 } 405 406 private: 407 SkBaseDevice* fDevice; 408 const SkMatrix fPrevCTM; 409 }; 410 411 #endif 412