/* * Copyright 2010 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file.
*/
struct SkArc; class SkBitmap; class SkColorSpace; class SkMesh; struct SkDrawShadowRec; class SkImageFilter; class SkRasterHandleAllocator; class SkSpecialImage; class GrRecordingContext; class SkData; class SkDrawable; class SkImage; class SkPaint; class SkPath; class SkPixmap; class SkRRect; class SkSurface; class SkVertices; enum SkColorType : int; enumclass SkBlendMode; enumclass SkScalerContextFlags : uint32_t; struct SkRSXform;
namespace sktext { class GlyphRunList;
}
namespace skif { class Backend; class Mapping;
} namespace skgpu::ganesh { class Device;
} namespace skgpu::graphite { class Device; class Recorder;
} namespace sktext::gpu { class SubRunControl; class Slug;
}
struct SkStrikeDeviceInfo { const SkSurfaceProps fSurfaceProps; const SkScalerContextFlags fScalerContextFlags; // This is a pointer so this can be compiled without SK_GPU_SUPPORT. const sktext::gpu::SubRunControl* const fSubRunControl;
};
/** * SkDevice is the internal API and implementation that SkCanvas will use to perform rendering and * implement the saveLayer abstraction. A device wraps some pixel allocation (for non-document based * devices) or wraps some other container that stores rendering operations. The drawing operations * perform equivalently to their corresponding functions in SkCanvas except that the canvas is * responsible for all SkImageFilters. An image filter is applied by automatically creating a layer, * drawing the filter-less paint into the layer, and then evaluating the filter on the layer's * image. * * Each layer in an SkCanvas stack is represented by an SkDevice instance that was created by the * parent SkDevice (up to the canvas's base device). In most cases these devices will be pixel * aligned with one another but may differ in size based on the known extent of the active clip. In * complex image filtering scenarios, they may not be axis aligned, although the effective pixel * size should remain approximately equal across all devices in a canvas. * * While SkCanvas manages a single stack of layers and canvas transforms, SkDevice does not have a * stack of transforms. Instead, it has a single active transform that is modified as needed by * SkCanvas. However, SkDevices are the means by which SkCanvas manages the clip stack because each * layer's clip stack starts anew (although the layer's results are then clipped by its parent's * stack when it is restored).
*/ class SkDevice : public SkRefCnt { public:
SkDevice(const SkImageInfo&, const SkSurfaceProps&);
// -- Surface properties and metadata
/** * Return ImageInfo for this device. If the canvas is not backed by pixels * (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
*/ const SkImageInfo& imageInfo() const { return fInfo; }
int width() const { return this->imageInfo().width(); } int height() const { return this->imageInfo().height(); }
/** * Write the pixels in 'src' into this Device at the specified x,y offset. The caller is * responsible for "pre-clipping" the src.
*/ bool writePixels(const SkPixmap& src, int x, int y) { return this->onWritePixels(src, x, y); }
/** * Read pixels from this Device at the specified x,y offset into dst. The caller is * responsible for "pre-clipping" the dst
*/ bool readPixels(const SkPixmap& dst, int x, int y) { return this->onReadPixels(dst, x, y); }
/** * Try to get write-access to the pixels behind the device. If successful, this returns true * and fills-out the pixmap parameter. On success it also bumps the genID of the underlying * bitmap. * * On failure, returns false and ignores the pixmap parameter.
*/ bool accessPixels(SkPixmap* pmap);
/** * Try to get read-only-access to the pixels behind the device. If successful, this returns * true and fills-out the pixmap parameter. * * On failure, returns false and ignores the pixmap parameter.
*/ bool peekPixels(SkPixmap*);
// -- Device's transform (both current transform affecting draws, and its fixed global mapping)
/** * Returns the transformation that maps from the local space to the device's coordinate space.
*/ const SkM44& localToDevice44() const { return fLocalToDevice; } const SkMatrix& localToDevice() const { return fLocalToDevice33; }
/** * Return the device's coordinate space transform: this maps from the device's coordinate space * into the global canvas' space (or root device space). This includes the translation * necessary to account for the device's origin.
*/ const SkM44& deviceToGlobal() const { return fDeviceToGlobal; } /** * Return the inverse of getDeviceToGlobal(), mapping from the global canvas' space (or root * device space) into this device's coordinate space.
*/ const SkM44& globalToDevice() const { return fGlobalToDevice; } /** * DEPRECATED: This asserts that 'getDeviceToGlobal' is a translation matrix with integer * components. In the future some SkDevices will have more complex device-to-global transforms, * so getDeviceToGlobal() or getRelativeTransform() should be used instead.
*/
SkIPoint getOrigin() const; /** * Returns true when this device's pixel grid is axis aligned with the global coordinate space, * and any relative translation between the two spaces is in integer pixel units.
*/ bool isPixelAlignedToGlobal() const; /** * Get the transformation from this device's coordinate system to the provided device space. * This transform can be used to draw this device into the provided device, such that once * that device is drawn to the root device, the net effect will be that this device's contents * have been transformed by the global CTM.
*/
SkMatrix getRelativeTransform(const SkDevice&) const;
/** * Return the bounds of the device in the coordinate space of the root canvas. The root device * will have its top-left at 0,0, but other devices such as those associated with saveLayer may * have a non-zero origin.
*/ void getGlobalBounds(SkIRect* bounds) const {
SkASSERT(bounds);
*bounds = SkMatrixPriv::MapRect(fDeviceToGlobal, SkRect::Make(this->bounds())).roundOut();
}
/** * Returns the bounding box of the current clip, in this device's coordinate space. No pixels * outside of these bounds will be touched by draws unless the clip is further modified (at * which point this will return the updated bounds).
*/ virtual SkIRect devClipBounds() const = 0;
// TEMPORARY: Whether or not SkCanvas should use an layer and image filters to simulate // mask filters and then draw the filtered mask using drawCoverageMask. Unlike regular // layers, the color type passed to SkDevice::createDevice() will always be an alpha-only // color type. Eventually this will be the only way that mask filters are handled (barring // dedicated fast-paths for blurs on [r]rects and text). virtualbool useDrawCoverageMaskForMaskFilters() const { returnfalse; }
// SkCanvas uses NoPixelsDevice when createDevice fails; but then it needs to be able to // inspect a layer's device to know if calling drawDevice() later is allowed. virtualbool isNoPixelsDevice() const { returnfalse; }
// Marking an SkDevice immutable declares the intent that rendering to the device is // complete, allowing it to be sampled as an image without requiring a copy. Drawing // operations may not function and may assert if invoked after setImmutable() is called. virtualvoid setImmutable() {}
/** * Create a new device based on CreateInfo. If the paint is not null, then it represents a * preview of how the new device will be composed with its creator device (this). * * The subclass may be handed this device in drawDevice(), so it must always return a device * that it knows how to draw, and that it knows how to identify if it is not of the same * subclass (since drawDevice is passed a SkDevice*). If the subclass cannot fulfill that * contract (e.g. PDF cannot support some settings on the paint) it should return NULL, and the * caller may then decide to explicitly create a bitmapdevice, knowing that later it could not * call drawDevice with it (but it could call drawSprite or drawBitmap).
*/ virtual sk_sp<SkDevice> createDevice(const CreateInfo&, const SkPaint*) { return nullptr; }
// -- Drawing routines (called after saveLayers and imagefilter operations are applied)
/** * If pathIsMutable, then the implementation is allowed to cast path to a * non-const pointer and modify it in place (as an optimization). Canvas * may do this to implement helpers such as drawOval, by placing a temp * path on the stack to hold the representation of the oval.
*/ virtualvoid drawPath(const SkPath& path, const SkPaint& paint, bool pathIsMutable = false) = 0;
virtualvoid drawImageRect(const SkImage*, const SkRect* src, const SkRect& dst, const SkSamplingOptions&, const SkPaint&,
SkCanvas::SrcRectConstraint) = 0; // Return true if canvas calls to drawImage or drawImageRect should try to // be drawn in a tiled way. virtualbool shouldDrawAsTiledImageRect() const { returnfalse; } virtualbool drawAsTiledImageRect(SkCanvas*, const SkImage*, const SkRect* src, const SkRect& dst, const SkSamplingOptions&, const SkPaint&,
SkCanvas::SrcRectConstraint) { returnfalse; }
/** * If skipColorXform is true, then the implementation should assume that the provided * vertex colors are already in the destination color space.
*/ virtualvoid drawVertices(const SkVertices*,
sk_sp<SkBlender>, const SkPaint&, bool skipColorXform = false) = 0; virtualvoid drawMesh(const SkMesh& mesh, sk_sp<SkBlender>, const SkPaint&) = 0; virtualvoid drawShadow(const SkPath&, const SkDrawShadowRec&);
// Default impl always calls drawRect() with a solid-color paint, setting it to anti-aliased // only when all edge flags are set. If there's a clip region, it draws that using drawPath, // or uses clipPath(). virtualvoid drawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4],
SkCanvas::QuadAAFlags aaFlags, const SkColor4f& color,
SkBlendMode mode); // Default impl uses drawImageRect per entry, being anti-aliased only when an entry's edge flags // are all set. If there's a clip region, it will be applied using clipPath(). virtualvoid drawEdgeAAImageSet(const SkCanvas::ImageSetEntry[], int count, const SkPoint dstClips[], const SkMatrix preViewMatrices[], const SkSamplingOptions&, const SkPaint&,
SkCanvas::SrcRectConstraint);
// Snap the 'subset' contents from this device, possibly as a read-only view. If 'forceCopy' // is true then the returned image's pixels must not be affected by subsequent draws into the // device. When 'forceCopy' is false, the image can be a view into the device's pixels // (avoiding a copy for performance, at the expense of safety). Default returns null. virtual sk_sp<SkSpecialImage> snapSpecial(const SkIRect& subset, bool forceCopy = false); // Can return null if unable to perform scaling as part of the copy, even if snapSpecial() w/o // scaling would succeed. virtual sk_sp<SkSpecialImage> snapSpecialScaled(const SkIRect& subset, const SkISize& dstDims); // Get a view of the entire device's current contents as an image.
sk_sp<SkSpecialImage> snapSpecial();
/** * The SkDevice passed will be an SkDevice which was returned by a call to * createDevice on this device with kNeverTile_TileExpectation. * * The default implementation calls snapSpecial() and drawSpecial() with the relative transform * from the input device to this device. The provided SkPaint cannot have a mask filter or * image filter, and any shader is ignored.
*/ virtualvoid drawDevice(SkDevice*, const SkSamplingOptions&, const SkPaint&);
/** * Draw the special image's subset to this device, subject to the given matrix transform instead * of the device's current local to device matrix. * * If 'constraint' is kFast, the rendered geometry of the image still reflects the extent of * the SkSpecialImage's subset, but it's assumed that the pixel data beyond the subset is valid * (e.g. SkSpecialImage::makeSubset() was called to crop a larger image).
*/ virtualvoid drawSpecial(SkSpecialImage*, const SkMatrix& localToDevice, const SkSamplingOptions&, const SkPaint&,
SkCanvas::SrcRectConstraint constraint =
SkCanvas::kStrict_SrcRectConstraint);
/** * Draw the special image's subset to this device, treating its alpha channel as coverage for * the draw and ignoring any RGB channels that might be present. This will be drawn using the * provided matrix transform instead of the device's current local to device matrix. * * Coverage values beyond the image's subset are treated as 0 (i.e. kDecal tiling). Color values * before coverage are determined as normal by the SkPaint, ignoring style, path effects, * mask filters and image filters. The local coords of any SkShader on the paint should be * relative to the SkDevice's current matrix (i.e. 'maskToDevice' determines how the coverage * mask aligns with device-space, but otherwise shading proceeds like other draws).
*/ virtualvoid drawCoverageMask(const SkSpecialImage*, const SkMatrix& maskToDevice, const SkSamplingOptions&, const SkPaint&);
/** * Draw rrect with an optimized path for analytic blurs, if provided by the device.
*/ virtualbool drawBlurredRRect(const SkRRect&, const SkPaint&, float deviceSigma) { returnfalse;
}
/** * Evaluate 'filter' and draw the final output into this device using 'paint'. The 'mapping' * defines the parameter-to-layer space transform used to evaluate the image filter on 'src', * and the layer-to-device space transform that is used to draw the result into this device. * Since 'mapping' fully specifies the transform, this draw function ignores the current * local-to-device matrix (i.e. just like drawSpecial and drawDevice). * * The final paint must not have an image filter or mask filter set on it; a shader is ignored. * The provided color type will be used for any intermediate surfaces that need to be created as * part of filter evaluation. It does not have to be src's color type or this Device's type.
*/ void drawFilteredImage(const skif::Mapping& mapping, SkSpecialImage* src, SkColorType ct, const SkImageFilter*, const SkSamplingOptions&, const SkPaint&);
protected: // DEPRECATED: Can be deleted once SkCanvas::onDrawImage() uses skif::FilterResult so don't // bother re-arranging. virtual sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&); virtual sk_sp<SkSpecialImage> makeSpecial(const SkImage*);
// Configure the device's coordinate spaces, specifying both how its device image maps back to // the global space (via 'deviceToGlobal') and the initial CTM of the device (via // 'localToDevice', i.e. what geometry drawn into this device will be transformed with). // // (bufferOriginX, bufferOriginY) defines where the (0,0) pixel the device's backing buffer // is anchored in the device space. The final device-to-global matrix stored by the SkDevice // will include a pre-translation by T(deviceOriginX, deviceOriginY), and the final // local-to-device matrix will have a post-translation of T(-deviceOriginX, -deviceOriginY). void setDeviceCoordinateSystem(const SkM44& deviceToGlobal, const SkM44& globalToDevice, const SkM44& localToDevice, int bufferOriginX, int bufferOriginY); // Convenience to configure the device to be axis-aligned with the root canvas, but with a // unique origin. void setOrigin(const SkM44& globalCTM, int x, int y) {
this->setDeviceCoordinateSystem(SkM44(), SkM44(), globalCTM, x, y);
}
// Returns whether or not localToDevice() has changed since the last call to this function. bool checkLocalToDeviceDirty() { bool wasDirty = fLocalToDeviceDirty;
fLocalToDeviceDirty = false; return wasDirty;
}
private: friendclass SkCanvas; // for setOrigin/setDeviceCoordinateSystem friendclass DeviceTestingAccess;
// Defaults to a CPU image filtering backend. virtual sk_sp<skif::Backend> createImageFilteringBackend(const SkSurfaceProps& surfaceProps,
SkColorType colorType) const;
// Implementations can assume that the device from (x,y) to (w,h) will fit within dst. virtualbool onReadPixels(const SkPixmap&, int x, int y) { returnfalse; }
// Implementations can assume that the src image placed at 'x,y' will fit within the device. virtualbool onWritePixels(const SkPixmap&, int x, int y) { returnfalse; }
// Only called with glyphRunLists that do not contain RSXForm. virtualvoid onDrawGlyphRunList(SkCanvas*, const sktext::GlyphRunList&, const SkPaint& paint) = 0;
const SkImageInfo fInfo; const SkSurfaceProps fSurfaceProps;
SkM44 fLocalToDevice; // fDeviceToGlobal and fGlobalToDevice are inverses of each other; there are never that many // SkDevices, so pay the memory cost to avoid recalculating the inverse.
SkM44 fDeviceToGlobal;
SkM44 fGlobalToDevice;
// fLocalToDevice but as a 3x3.
SkMatrix fLocalToDevice33;
// fLocalToDevice is the device CTM, not the global CTM. // It maps from local space to the device's coordinate space. // fDeviceToGlobal * fLocalToDevice will match the canvas' CTM. // // setGlobalCTM and setLocalToDevice are intentionally not virtual for performance reasons. // However, track a dirty bit for subclasses that want to defer local-to-device dependent // calculations until needed for a clip or draw. bool fLocalToDeviceDirty = true;
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.