/* * 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" #include "../gpu/GrColor.h" class SkPath; class SkPicture; class SkXfermode; class GrContext; class GrFragmentProcessor; /** \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(const SkMatrix* localMatrix = NULL); virtual ~SkShader(); /** * Returns the local matrix. * * FIXME: This can be incorrect for a Shader with its own local matrix * that is also wrapped via CreateLocalMatrixShader. */ const SkMatrix& getLocalMatrix() const { return fLocalMatrix; } 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 }; enum { kTileModeCount = kMirror_TileMode + 1 }; // 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 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 }; /** * 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. */ virtual bool isOpaque() const { return false; } /** * ContextRec acts as a parameter bundle for creating Contexts. */ struct ContextRec { ContextRec() : fDevice(NULL), fPaint(NULL), fMatrix(NULL), fLocalMatrix(NULL) {} ContextRec(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) : fDevice(&device) , fPaint(&paint) , fMatrix(&matrix) , fLocalMatrix(NULL) {} const SkBitmap* fDevice; // the bitmap we are drawing into const SkPaint* fPaint; // the current paint associated with the draw const SkMatrix* fMatrix; // the current matrix in the canvas const SkMatrix* fLocalMatrix; // optional local matrix }; class Context : public ::SkNoncopyable { public: Context(const SkShader& shader, const ContextRec&); virtual ~Context(); /** * 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() const { return 0; } /** * 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 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()); } // Notification from blitter::blitMask in case we need to see the non-alpha channels virtual void set3DMask(const SkMask*) {} protected: // Reference to shader, so we don't have to dupe information. const SkShader& fShader; enum MatrixClass { kLinear_MatrixClass, // no perspective kFixedStepInX_MatrixClass, // fast perspective, need to call fixedStepInX() each // scanline kPerspective_MatrixClass // slow perspective, need to mappoints each pixel }; static MatrixClass ComputeMatrixClass(const SkMatrix&); uint8_t getPaintAlpha() const { return fPaintAlpha; } const SkMatrix& getTotalInverse() const { return fTotalInverse; } MatrixClass getInverseClass() const { return (MatrixClass)fTotalInverseClass; } const SkMatrix& getCTM() const { return fCTM; } private: SkMatrix fCTM; SkMatrix fTotalInverse; uint8_t fPaintAlpha; uint8_t fTotalInverseClass; typedef SkNoncopyable INHERITED; }; /** * Create the actual object that does the shading. * Size of storage must be >= contextSize. */ Context* createContext(const ContextRec&, void* storage) const; /** * Return the size of a Context returned by createContext. * * Override this if your subclass overrides createContext, to return the correct size of * your subclass' context. */ virtual size_t contextSize() const; /** * 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, //