/* * Copyright 2006 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. */ #ifndef SkShader_DEFINED #define SkShader_DEFINED #include "SkBitmap.h" #include "SkFlattenable.h" #include "SkMask.h" #include "SkMatrix.h" #include "SkPaint.h" class SkPath; class GrContext; class GrEffect; class GrEffectStage; /** \class SkShader * * Shaders specify the source color(s) for what is being drawn. If a paint * has no shader, then the paint's color is used. If the paint has a * shader, then the shader's color(s) are use instead, but they are * modulated by the paint's alpha. This makes it easy to create a shader * once (e.g. bitmap tiling or gradient) and then change its transparency * w/o having to modify the original shader... only the paint's alpha needs * to be modified. */ class SK_API SkShader : public SkFlattenable { public: SK_DECLARE_INST_COUNT(SkShader) SkShader(); virtual ~SkShader(); /** * Returns true if the local matrix is not an identity matrix. */ bool hasLocalMatrix() const { return !fLocalMatrix.isIdentity(); } /** * Returns the local matrix. */ const SkMatrix& getLocalMatrix() const { return fLocalMatrix; } /** * Set the shader's local matrix. * @param localM The shader's new local matrix. */ void setLocalMatrix(const SkMatrix& localM) { fLocalMatrix = localM; } /** * Reset the shader's local matrix to identity. */ void resetLocalMatrix() { fLocalMatrix.reset(); } enum TileMode { /** replicate the edge color if the shader draws outside of its * original bounds */ kClamp_TileMode, /** repeat the shader's image horizontally and vertically */ kRepeat_TileMode, /** repeat the shader's image horizontally and vertically, alternating * mirror images so that adjacent images always seam */ kMirror_TileMode, #if 0 /** only draw within the original domain, return 0 everywhere else */ kDecal_TileMode, #endif kTileModeCount }; // override these in your subclass enum Flags { //!< set if all of the colors will be opaque kOpaqueAlpha_Flag = 0x01, //! set if this shader's shadeSpan16() method can be called kHasSpan16_Flag = 0x02, /** Set this bit if the shader's native data type is instrinsically 16 bit, meaning that calling the 32bit shadeSpan() entry point will mean the the impl has to up-sample 16bit data into 32bit. Used as a a means of clearing a dither request if the it will have no effect */ kIntrinsicly16_Flag = 0x04, /** set (after setContext) if the spans only vary in X (const in Y). e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient that varies from left-to-right. This flag specifies this for shadeSpan(). */ kConstInY32_Flag = 0x08, /** same as kConstInY32_Flag, but is set if this is true for shadeSpan16 which may not always be the case, since shadeSpan16 may be predithered, which would mean it was not const in Y, even though the 32bit shadeSpan() would be const. */ kConstInY16_Flag = 0x10 }; /** * Called sometimes before drawing with this shader. Return the type of * alpha your shader will return. The default implementation returns 0. * Your subclass should override if it can (even sometimes) report a * non-zero value, since that will enable various blitters to perform * faster. */ virtual uint32_t getFlags() { return 0; } /** * Returns true if the shader is guaranteed to produce only opaque * colors, subject to the SkPaint using the shader to apply an opaque * alpha value. Subclasses should override this to allow some * optimizations. isOpaque() can be called at any time, unlike getFlags, * which only works properly when the context is set. */ virtual bool isOpaque() const { return false; } /** * Return the alpha associated with the data returned by shadeSpan16(). If * kHasSpan16_Flag is not set, this value is meaningless. */ virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; } /** * Called once before drawing, with the current paint and device matrix. * Return true if your shader supports these parameters, or false if not. * If false is returned, nothing will be drawn. If true is returned, then * a balancing call to endContext() will be made before the next call to * setContext. * * Subclasses should be sure to call their INHERITED::setContext() if they * override this method. */ virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix); /** * Assuming setContext returned true, endContext() will be called when * the draw using the shader has completed. It is an error for setContext * to be called twice w/o an intervening call to endContext(). * * Subclasses should be sure to call their INHERITED::endContext() if they * override this method. */ virtual void endContext(); SkDEBUGCODE(bool setContextHasBeenCalled() const { return SkToBool(fInSetContext); }) /** * Called for each span of the object being drawn. Your subclass should * set the appropriate colors (with premultiplied alpha) that correspond * to the specified device coordinates. */ virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0; typedef void (*ShadeProc)(void* ctx, int x, int y, SkPMColor[], int count); virtual ShadeProc asAShadeProc(void** ctx); /** * Called only for 16bit devices when getFlags() returns * kOpaqueAlphaFlag | kHasSpan16_Flag */ virtual void shadeSpan16(int x, int y, uint16_t[], int count); /** * Similar to shadeSpan, but only returns the alpha-channel for a span. * The default implementation calls shadeSpan() and then extracts the alpha * values from the returned colors. */ virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count); /** * Helper function that returns true if this shader's shadeSpan16() method * can be called. */ bool canCallShadeSpan16() { return SkShader::CanCallShadeSpan16(this->getFlags()); } /** * Helper to check the flags to know if it is legal to call shadeSpan16() */ static bool CanCallShadeSpan16(uint32_t flags) { return (flags & kHasSpan16_Flag) != 0; } /** Gives method bitmap should be read to implement a shader. Also determines number and interpretation of "extra" parameters returned by asABitmap */ enum BitmapType { kNone_BitmapType, //