michael@0: michael@0: /* michael@0: * Copyright 2013 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef SkBitmapDevice_DEFINED michael@0: #define SkBitmapDevice_DEFINED michael@0: michael@0: #include "SkDevice.h" michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: class SK_API SkBitmapDevice : public SkBaseDevice { michael@0: public: michael@0: SK_DECLARE_INST_COUNT(SkBitmapDevice) michael@0: michael@0: /** michael@0: * Construct a new device with the specified bitmap as its backend. It is michael@0: * valid for the bitmap to have no pixels associated with it. In that case, michael@0: * any drawing to this device will have no effect. michael@0: */ michael@0: SkBitmapDevice(const SkBitmap& bitmap); michael@0: michael@0: /** michael@0: * Construct a new device with the specified bitmap as its backend. It is michael@0: * valid for the bitmap to have no pixels associated with it. In that case, michael@0: * any drawing to this device will have no effect. michael@0: */ michael@0: SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties); michael@0: michael@0: #ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG michael@0: /** michael@0: * Create a new raster device and have the pixels be automatically michael@0: * allocated. The rowBytes of the device will be computed automatically michael@0: * based on the config and the width. michael@0: * michael@0: * @param config The desired config for the pixels. If the request cannot michael@0: * be met, the closest matching support config will be used. michael@0: * @param width width (in pixels) of the device michael@0: * @param height height (in pixels) of the device michael@0: * @param isOpaque Set to true if it is known that all of the pixels will michael@0: * be drawn to opaquely. Used as an accelerator when drawing michael@0: * these pixels to another device. michael@0: */ michael@0: SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque = false); michael@0: michael@0: /** michael@0: * Create a new raster device and have the pixels be automatically michael@0: * allocated. The rowBytes of the device will be computed automatically michael@0: * based on the config and the width. michael@0: * michael@0: * @param config The desired config for the pixels. If the request cannot michael@0: * be met, the closest matching support config will be used. michael@0: * @param width width (in pixels) of the device michael@0: * @param height height (in pixels) of the device michael@0: * @param isOpaque Set to true if it is known that all of the pixels will michael@0: * be drawn to opaquely. Used as an accelerator when drawing michael@0: * these pixels to another device. michael@0: * @param deviceProperties Properties which affect compositing. michael@0: */ michael@0: SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque, michael@0: const SkDeviceProperties& deviceProperties); michael@0: #endif michael@0: static SkBitmapDevice* Create(const SkImageInfo&, michael@0: const SkDeviceProperties* = NULL); michael@0: michael@0: /** Return the width of the device (in pixels). michael@0: */ michael@0: virtual int width() const SK_OVERRIDE { return fBitmap.width(); } michael@0: /** Return the height of the device (in pixels). michael@0: */ michael@0: virtual int height() const SK_OVERRIDE { return fBitmap.height(); } michael@0: michael@0: /** Returns true if the device's bitmap's config treats every pixels as michael@0: implicitly opaque. michael@0: */ michael@0: virtual bool isOpaque() const SK_OVERRIDE { return fBitmap.isOpaque(); } michael@0: michael@0: /** Return the bitmap config of the device's pixels michael@0: */ michael@0: virtual SkBitmap::Config config() const SK_OVERRIDE { return fBitmap.config(); } michael@0: michael@0: virtual SkImageInfo imageInfo() const SK_OVERRIDE; michael@0: michael@0: #ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG michael@0: /** michael@0: * DEPRECATED: This will be made protected once WebKit stops using it. michael@0: * Instead use Canvas' writePixels method. michael@0: * michael@0: * Similar to draw sprite, this method will copy the pixels in bitmap onto michael@0: * the device, with the top/left corner specified by (x, y). The pixel michael@0: * values in the device are completely replaced: there is no blending. michael@0: * michael@0: * Currently if bitmap is backed by a texture this is a no-op. This may be michael@0: * relaxed in the future. michael@0: * michael@0: * If the bitmap has config kARGB_8888_Config then the config8888 param michael@0: * will determines how the pixel valuess are intepreted. If the bitmap is michael@0: * not kARGB_8888_Config then this parameter is ignored. michael@0: */ michael@0: virtual void writePixels(const SkBitmap& bitmap, int x, int y, michael@0: SkCanvas::Config8888 config8888) SK_OVERRIDE; michael@0: #endif michael@0: /** michael@0: * Return the device's associated gpu render target, or NULL. michael@0: */ michael@0: virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; } michael@0: michael@0: protected: michael@0: /** michael@0: * Device may filter the text flags for drawing text here. If it wants to michael@0: * make a change to the specified values, it should write them into the michael@0: * textflags parameter (output) and return true. If the paint is fine as michael@0: * is, then ignore the textflags parameter and return false. michael@0: * michael@0: * The baseclass SkDevice filters based on its depth and blitters. michael@0: */ michael@0: virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE; michael@0: michael@0: /** Clears the entire device to the specified color (including alpha). michael@0: * Ignores the clip. michael@0: */ michael@0: virtual void clear(SkColor color) SK_OVERRIDE; michael@0: michael@0: /** These are called inside the per-device-layer loop for each draw call. michael@0: When these are called, we have already applied any saveLayer operations, michael@0: and are handling any looping from the paint, and any effects from the michael@0: DrawFilter. michael@0: */ michael@0: virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE; michael@0: virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count, michael@0: const SkPoint[], const SkPaint& paint) SK_OVERRIDE; michael@0: virtual void drawRect(const SkDraw&, const SkRect& r, michael@0: const SkPaint& paint) SK_OVERRIDE; michael@0: virtual void drawOval(const SkDraw&, const SkRect& oval, michael@0: const SkPaint& paint) SK_OVERRIDE; michael@0: virtual void drawRRect(const SkDraw&, const SkRRect& rr, michael@0: const SkPaint& paint) SK_OVERRIDE; michael@0: michael@0: /** michael@0: * If pathIsMutable, then the implementation is allowed to cast path to a michael@0: * non-const pointer and modify it in place (as an optimization). Canvas michael@0: * may do this to implement helpers such as drawOval, by placing a temp michael@0: * path on the stack to hold the representation of the oval. michael@0: * michael@0: * If prePathMatrix is not null, it should logically be applied before any michael@0: * stroking or other effects. If there are no effects on the paint that michael@0: * affect the geometry/rasterization, then the pre matrix can just be michael@0: * pre-concated with the current matrix. michael@0: */ michael@0: virtual void drawPath(const SkDraw&, const SkPath& path, michael@0: const SkPaint& paint, michael@0: const SkMatrix* prePathMatrix = NULL, michael@0: bool pathIsMutable = false) SK_OVERRIDE; michael@0: virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap, michael@0: const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE; michael@0: virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, michael@0: int x, int y, const SkPaint& paint) SK_OVERRIDE; michael@0: michael@0: /** michael@0: * The default impl. will create a bitmap-shader from the bitmap, michael@0: * and call drawRect with it. michael@0: */ michael@0: virtual void drawBitmapRect(const SkDraw&, const SkBitmap&, michael@0: const SkRect* srcOrNull, const SkRect& dst, michael@0: const SkPaint& paint, michael@0: SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE; michael@0: michael@0: /** michael@0: * Does not handle text decoration. michael@0: * Decorations (underline and stike-thru) will be handled by SkCanvas. michael@0: */ michael@0: virtual void drawText(const SkDraw&, const void* text, size_t len, michael@0: SkScalar x, SkScalar y, const SkPaint& paint) SK_OVERRIDE; michael@0: virtual void drawPosText(const SkDraw&, const void* text, size_t len, michael@0: const SkScalar pos[], SkScalar constY, michael@0: int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE; michael@0: virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len, michael@0: const SkPath& path, const SkMatrix* matrix, michael@0: const SkPaint& paint) SK_OVERRIDE; michael@0: virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount, michael@0: const SkPoint verts[], const SkPoint texs[], michael@0: const SkColor colors[], SkXfermode* xmode, michael@0: const uint16_t indices[], int indexCount, michael@0: const SkPaint& paint) SK_OVERRIDE; michael@0: /** The SkBaseDevice passed will be an SkBaseDevice which was returned by a call to michael@0: onCreateDevice on this device with kSaveLayer_Usage. michael@0: */ michael@0: virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, michael@0: const SkPaint&) SK_OVERRIDE; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////// michael@0: michael@0: /** Update as needed the pixel value in the bitmap, so that the caller can michael@0: access the pixels directly. Note: only the pixels field should be michael@0: altered. The config/width/height/rowbytes must remain unchanged. michael@0: @return the device contents as a bitmap michael@0: */ michael@0: virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE; michael@0: michael@0: SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); } michael@0: // just for subclasses, to assign a custom pixelref michael@0: SkPixelRef* setPixelRef(SkPixelRef* pr) { michael@0: fBitmap.setPixelRef(pr); michael@0: return pr; michael@0: } michael@0: michael@0: /** michael@0: * Implements readPixels API. The caller will ensure that: michael@0: * 1. bitmap has pixel config kARGB_8888_Config. michael@0: * 2. bitmap has pixels. michael@0: * 3. The rectangle (x, y, x + bitmap->width(), y + bitmap->height()) is michael@0: * contained in the device bounds. michael@0: */ michael@0: virtual bool onReadPixels(const SkBitmap&, int x, int y, SkCanvas::Config8888) SK_OVERRIDE; michael@0: virtual bool onWritePixels(const SkImageInfo&, const void*, size_t, int, int) SK_OVERRIDE; michael@0: virtual void* onAccessPixels(SkImageInfo* info, size_t* rowBytes) SK_OVERRIDE; michael@0: michael@0: /** Called when this device is installed into a Canvas. Balanced by a call michael@0: to unlockPixels() when the device is removed from a Canvas. michael@0: */ michael@0: virtual void lockPixels() SK_OVERRIDE; michael@0: virtual void unlockPixels() SK_OVERRIDE; michael@0: michael@0: /** michael@0: * Returns true if the device allows processing of this imagefilter. If michael@0: * false is returned, then the filter is ignored. This may happen for michael@0: * some subclasses that do not support pixel manipulations after drawing michael@0: * has occurred (e.g. printing). The default implementation returns true. michael@0: */ michael@0: virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE; michael@0: michael@0: /** michael@0: * Override and return true for filters that the device can handle michael@0: * intrinsically. Doing so means that SkCanvas will pass-through this michael@0: * filter to drawSprite and drawDevice (and potentially filterImage). michael@0: * Returning false means the SkCanvas will have apply the filter itself, michael@0: * and just pass the resulting image to the device. michael@0: */ michael@0: virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE; michael@0: michael@0: /** michael@0: * Related (but not required) to canHandleImageFilter, this method returns michael@0: * true if the device could apply the filter to the src bitmap and return michael@0: * the result (and updates offset as needed). michael@0: * If the device does not recognize or support this filter, michael@0: * it just returns false and leaves result and offset unchanged. michael@0: */ michael@0: virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&, michael@0: SkBitmap* result, SkIPoint* offset) SK_OVERRIDE; michael@0: michael@0: private: michael@0: friend class SkCanvas; michael@0: friend struct DeviceCM; //for setMatrixClip michael@0: friend class SkDraw; michael@0: friend class SkDrawIter; michael@0: friend class SkDeviceFilteredPaint; michael@0: friend class SkDeviceImageFilterProxy; michael@0: michael@0: friend class SkSurface_Raster; michael@0: michael@0: // used to change the backend's pixels (and possibly config/rowbytes) michael@0: // but cannot change the width/height, so there should be no change to michael@0: // any clip information. michael@0: virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE; michael@0: michael@0: #ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG michael@0: // in support of legacy constructors michael@0: void init(SkBitmap::Config config, int width, int height, bool isOpaque); michael@0: #endif michael@0: michael@0: virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) SK_OVERRIDE; michael@0: michael@0: /** Causes any deferred drawing to the device to be completed. michael@0: */ michael@0: virtual void flush() SK_OVERRIDE {} michael@0: michael@0: virtual SkSurface* newSurface(const SkImageInfo&) SK_OVERRIDE; michael@0: virtual const void* peekPixels(SkImageInfo*, size_t* rowBytes) SK_OVERRIDE; michael@0: michael@0: SkBitmap fBitmap; michael@0: michael@0: typedef SkBaseDevice INHERITED; michael@0: }; michael@0: michael@0: #endif // SkBitmapDevice_DEFINED