gfx/skia/trunk/include/core/SkShader.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/include/core/SkShader.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,376 @@
     1.4 +/*
     1.5 + * Copyright 2006 The Android Open Source Project
     1.6 + *
     1.7 + * Use of this source code is governed by a BSD-style license that can be
     1.8 + * found in the LICENSE file.
     1.9 + */
    1.10 +
    1.11 +
    1.12 +#ifndef SkShader_DEFINED
    1.13 +#define SkShader_DEFINED
    1.14 +
    1.15 +#include "SkBitmap.h"
    1.16 +#include "SkFlattenable.h"
    1.17 +#include "SkMask.h"
    1.18 +#include "SkMatrix.h"
    1.19 +#include "SkPaint.h"
    1.20 +
    1.21 +class SkPath;
    1.22 +class GrContext;
    1.23 +class GrEffectRef;
    1.24 +
    1.25 +/** \class SkShader
    1.26 + *
    1.27 + *  Shaders specify the source color(s) for what is being drawn. If a paint
    1.28 + *  has no shader, then the paint's color is used. If the paint has a
    1.29 + *  shader, then the shader's color(s) are use instead, but they are
    1.30 + *  modulated by the paint's alpha. This makes it easy to create a shader
    1.31 + *  once (e.g. bitmap tiling or gradient) and then change its transparency
    1.32 + *  w/o having to modify the original shader... only the paint's alpha needs
    1.33 + *  to be modified.
    1.34 + */
    1.35 +class SK_API SkShader : public SkFlattenable {
    1.36 +public:
    1.37 +    SK_DECLARE_INST_COUNT(SkShader)
    1.38 +
    1.39 +    SkShader();
    1.40 +    virtual ~SkShader();
    1.41 +
    1.42 +    /**
    1.43 +     * Returns true if the local matrix is not an identity matrix.
    1.44 +     */
    1.45 +    bool hasLocalMatrix() const { return !fLocalMatrix.isIdentity(); }
    1.46 +
    1.47 +    /**
    1.48 +     *  Returns the local matrix.
    1.49 +     */
    1.50 +    const SkMatrix& getLocalMatrix() const { return fLocalMatrix; }
    1.51 +
    1.52 +    /**
    1.53 +     *  Set the shader's local matrix.
    1.54 +     *  @param localM   The shader's new local matrix.
    1.55 +     */
    1.56 +    void setLocalMatrix(const SkMatrix& localM) { fLocalMatrix = localM; }
    1.57 +
    1.58 +    /**
    1.59 +     *  Reset the shader's local matrix to identity.
    1.60 +     */
    1.61 +    void resetLocalMatrix() { fLocalMatrix.reset(); }
    1.62 +
    1.63 +    enum TileMode {
    1.64 +        /** replicate the edge color if the shader draws outside of its
    1.65 +         *  original bounds
    1.66 +         */
    1.67 +        kClamp_TileMode,
    1.68 +
    1.69 +        /** repeat the shader's image horizontally and vertically */
    1.70 +        kRepeat_TileMode,
    1.71 +
    1.72 +        /** repeat the shader's image horizontally and vertically, alternating
    1.73 +         *  mirror images so that adjacent images always seam
    1.74 +         */
    1.75 +        kMirror_TileMode,
    1.76 +
    1.77 +#if 0
    1.78 +        /** only draw within the original domain, return 0 everywhere else */
    1.79 +        kDecal_TileMode,
    1.80 +#endif
    1.81 +
    1.82 +        kTileModeCount
    1.83 +    };
    1.84 +
    1.85 +    // override these in your subclass
    1.86 +
    1.87 +    enum Flags {
    1.88 +        //!< set if all of the colors will be opaque
    1.89 +        kOpaqueAlpha_Flag  = 0x01,
    1.90 +
    1.91 +        //! set if this shader's shadeSpan16() method can be called
    1.92 +        kHasSpan16_Flag = 0x02,
    1.93 +
    1.94 +        /** Set this bit if the shader's native data type is instrinsically 16
    1.95 +            bit, meaning that calling the 32bit shadeSpan() entry point will
    1.96 +            mean the the impl has to up-sample 16bit data into 32bit. Used as a
    1.97 +            a means of clearing a dither request if the it will have no effect
    1.98 +        */
    1.99 +        kIntrinsicly16_Flag = 0x04,
   1.100 +
   1.101 +        /** set (after setContext) if the spans only vary in X (const in Y).
   1.102 +            e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
   1.103 +            that varies from left-to-right. This flag specifies this for
   1.104 +            shadeSpan().
   1.105 +         */
   1.106 +        kConstInY32_Flag = 0x08,
   1.107 +
   1.108 +        /** same as kConstInY32_Flag, but is set if this is true for shadeSpan16
   1.109 +            which may not always be the case, since shadeSpan16 may be
   1.110 +            predithered, which would mean it was not const in Y, even though
   1.111 +            the 32bit shadeSpan() would be const.
   1.112 +         */
   1.113 +        kConstInY16_Flag = 0x10
   1.114 +    };
   1.115 +
   1.116 +    /**
   1.117 +     *  Called sometimes before drawing with this shader. Return the type of
   1.118 +     *  alpha your shader will return. The default implementation returns 0.
   1.119 +     *  Your subclass should override if it can (even sometimes) report a
   1.120 +     *  non-zero value, since that will enable various blitters to perform
   1.121 +     *  faster.
   1.122 +     */
   1.123 +    virtual uint32_t getFlags() { return 0; }
   1.124 +
   1.125 +    /**
   1.126 +     *  Returns true if the shader is guaranteed to produce only opaque
   1.127 +     *  colors, subject to the SkPaint using the shader to apply an opaque
   1.128 +     *  alpha value. Subclasses should override this to allow some
   1.129 +     *  optimizations.  isOpaque() can be called at any time, unlike getFlags,
   1.130 +     *  which only works properly when the context is set.
   1.131 +     */
   1.132 +    virtual bool isOpaque() const { return false; }
   1.133 +
   1.134 +    /**
   1.135 +     *  Return the alpha associated with the data returned by shadeSpan16(). If
   1.136 +     *  kHasSpan16_Flag is not set, this value is meaningless.
   1.137 +     */
   1.138 +    virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; }
   1.139 +
   1.140 +    /**
   1.141 +     *  Called once before drawing, with the current paint and device matrix.
   1.142 +     *  Return true if your shader supports these parameters, or false if not.
   1.143 +     *  If false is returned, nothing will be drawn. If true is returned, then
   1.144 +     *  a balancing call to endContext() will be made before the next call to
   1.145 +     *  setContext.
   1.146 +     *
   1.147 +     *  Subclasses should be sure to call their INHERITED::setContext() if they
   1.148 +     *  override this method.
   1.149 +     */
   1.150 +    virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
   1.151 +                            const SkMatrix& matrix);
   1.152 +
   1.153 +    /**
   1.154 +     *  Assuming setContext returned true, endContext() will be called when
   1.155 +     *  the draw using the shader has completed. It is an error for setContext
   1.156 +     *  to be called twice w/o an intervening call to endContext().
   1.157 +     *
   1.158 +     *  Subclasses should be sure to call their INHERITED::endContext() if they
   1.159 +     *  override this method.
   1.160 +     */
   1.161 +    virtual void endContext();
   1.162 +
   1.163 +    SkDEBUGCODE(bool setContextHasBeenCalled() const { return SkToBool(fInSetContext); })
   1.164 +
   1.165 +    /**
   1.166 +     *  Called for each span of the object being drawn. Your subclass should
   1.167 +     *  set the appropriate colors (with premultiplied alpha) that correspond
   1.168 +     *  to the specified device coordinates.
   1.169 +     */
   1.170 +    virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
   1.171 +
   1.172 +    typedef void (*ShadeProc)(void* ctx, int x, int y, SkPMColor[], int count);
   1.173 +    virtual ShadeProc asAShadeProc(void** ctx);
   1.174 +
   1.175 +    /**
   1.176 +     *  Called only for 16bit devices when getFlags() returns
   1.177 +     *  kOpaqueAlphaFlag | kHasSpan16_Flag
   1.178 +     */
   1.179 +    virtual void shadeSpan16(int x, int y, uint16_t[], int count);
   1.180 +
   1.181 +    /**
   1.182 +     *  Similar to shadeSpan, but only returns the alpha-channel for a span.
   1.183 +     *  The default implementation calls shadeSpan() and then extracts the alpha
   1.184 +     *  values from the returned colors.
   1.185 +     */
   1.186 +    virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);
   1.187 +
   1.188 +    /**
   1.189 +     *  Helper function that returns true if this shader's shadeSpan16() method
   1.190 +     *  can be called.
   1.191 +     */
   1.192 +    bool canCallShadeSpan16() {
   1.193 +        return SkShader::CanCallShadeSpan16(this->getFlags());
   1.194 +    }
   1.195 +
   1.196 +    /**
   1.197 +     *  Helper to check the flags to know if it is legal to call shadeSpan16()
   1.198 +     */
   1.199 +    static bool CanCallShadeSpan16(uint32_t flags) {
   1.200 +        return (flags & kHasSpan16_Flag) != 0;
   1.201 +    }
   1.202 +
   1.203 +    /**
   1.204 +     Gives method bitmap should be read to implement a shader.
   1.205 +     Also determines number and interpretation of "extra" parameters returned
   1.206 +     by asABitmap
   1.207 +     */
   1.208 +    enum BitmapType {
   1.209 +        kNone_BitmapType,   //<! Shader is not represented as a bitmap
   1.210 +        kDefault_BitmapType,//<! Access bitmap using local coords transformed
   1.211 +                            //   by matrix. No extras
   1.212 +        kRadial_BitmapType, //<! Access bitmap by transforming local coordinates
   1.213 +                            //   by the matrix and taking the distance of result
   1.214 +                            //   from  (0,0) as bitmap column. Bitmap is 1 pixel
   1.215 +                            //   tall. No extras
   1.216 +        kSweep_BitmapType,  //<! Access bitmap by transforming local coordinates
   1.217 +                            //   by the matrix and taking the angle of result
   1.218 +                            //   to (0,0) as bitmap x coord, where angle = 0 is
   1.219 +                            //   bitmap left edge of bitmap = 2pi is the
   1.220 +                            //   right edge. Bitmap is 1 pixel tall. No extras
   1.221 +        kTwoPointRadial_BitmapType,
   1.222 +                            //<! Matrix transforms to space where (0,0) is
   1.223 +                            //   the center of the starting circle.  The second
   1.224 +                            //   circle will be centered (x, 0) where x  may be
   1.225 +                            //   0. The post-matrix space is normalized such
   1.226 +                            //   that 1 is the second radius - first radius.
   1.227 +                            //   Three extra parameters are returned:
   1.228 +                            //      0: x-offset of second circle center
   1.229 +                            //         to first.
   1.230 +                            //      1: radius of first circle in post-matrix
   1.231 +                            //         space
   1.232 +                            //      2: the second radius minus the first radius
   1.233 +                            //         in pre-transformed space.
   1.234 +        kTwoPointConical_BitmapType,
   1.235 +                            //<! Matrix transforms to space where (0,0) is
   1.236 +                            //   the center of the starting circle.  The second
   1.237 +                            //   circle will be centered (x, 0) where x  may be
   1.238 +                            //   0.
   1.239 +                            //   Three extra parameters are returned:
   1.240 +                            //      0: x-offset of second circle center
   1.241 +                            //         to first.
   1.242 +                            //      1: radius of first circle
   1.243 +                            //      2: the second radius minus the first radius
   1.244 +        kLinear_BitmapType, //<! Access bitmap using local coords transformed
   1.245 +                            //   by matrix. No extras
   1.246 +
   1.247 +       kLast_BitmapType = kLinear_BitmapType
   1.248 +    };
   1.249 +    /** Optional methods for shaders that can pretend to be a bitmap/texture
   1.250 +        to play along with opengl. Default just returns kNone_BitmapType and
   1.251 +        ignores the out parameters.
   1.252 +
   1.253 +        @param outTexture if non-NULL will be the bitmap representing the shader
   1.254 +                          after return.
   1.255 +        @param outMatrix  if non-NULL will be the matrix to apply to vertices
   1.256 +                          to access the bitmap after return.
   1.257 +        @param xy         if non-NULL will be the tile modes that should be
   1.258 +                          used to access the bitmap after return.
   1.259 +        @param twoPointRadialParams Two extra return values needed for two point
   1.260 +                                    radial bitmaps. The first is the x-offset of
   1.261 +                                    the second point and the second is the radius
   1.262 +                                    about the first point.
   1.263 +    */
   1.264 +    virtual BitmapType asABitmap(SkBitmap* outTexture, SkMatrix* outMatrix,
   1.265 +                         TileMode xy[2]) const;
   1.266 +
   1.267 +    /**
   1.268 +     *  If the shader subclass can be represented as a gradient, asAGradient
   1.269 +     *  returns the matching GradientType enum (or kNone_GradientType if it
   1.270 +     *  cannot). Also, if info is not null, asAGradient populates info with
   1.271 +     *  the relevant (see below) parameters for the gradient.  fColorCount
   1.272 +     *  is both an input and output parameter.  On input, it indicates how
   1.273 +     *  many entries in fColors and fColorOffsets can be used, if they are
   1.274 +     *  non-NULL.  After asAGradient has run, fColorCount indicates how
   1.275 +     *  many color-offset pairs there are in the gradient.  If there is
   1.276 +     *  insufficient space to store all of the color-offset pairs, fColors
   1.277 +     *  and fColorOffsets will not be altered.  fColorOffsets specifies
   1.278 +     *  where on the range of 0 to 1 to transition to the given color.
   1.279 +     *  The meaning of fPoint and fRadius is dependant on the type of gradient.
   1.280 +     *
   1.281 +     *  None:
   1.282 +     *      info is ignored.
   1.283 +     *  Color:
   1.284 +     *      fColorOffsets[0] is meaningless.
   1.285 +     *  Linear:
   1.286 +     *      fPoint[0] and fPoint[1] are the end-points of the gradient
   1.287 +     *  Radial:
   1.288 +     *      fPoint[0] and fRadius[0] are the center and radius
   1.289 +     *  Radial2:
   1.290 +     *      fPoint[0] and fRadius[0] are the center and radius of the 1st circle
   1.291 +     *      fPoint[1] and fRadius[1] are the center and radius of the 2nd circle
   1.292 +     *  Sweep:
   1.293 +     *      fPoint[0] is the center of the sweep.
   1.294 +     */
   1.295 +
   1.296 +    enum GradientType {
   1.297 +        kNone_GradientType,
   1.298 +        kColor_GradientType,
   1.299 +        kLinear_GradientType,
   1.300 +        kRadial_GradientType,
   1.301 +        kRadial2_GradientType,
   1.302 +        kSweep_GradientType,
   1.303 +        kConical_GradientType,
   1.304 +        kLast_GradientType = kConical_GradientType
   1.305 +    };
   1.306 +
   1.307 +    struct GradientInfo {
   1.308 +        int         fColorCount;    //!< In-out parameter, specifies passed size
   1.309 +                                    //   of fColors/fColorOffsets on input, and
   1.310 +                                    //   actual number of colors/offsets on
   1.311 +                                    //   output.
   1.312 +        SkColor*    fColors;        //!< The colors in the gradient.
   1.313 +        SkScalar*   fColorOffsets;  //!< The unit offset for color transitions.
   1.314 +        SkPoint     fPoint[2];      //!< Type specific, see above.
   1.315 +        SkScalar    fRadius[2];     //!< Type specific, see above.
   1.316 +        TileMode    fTileMode;      //!< The tile mode used.
   1.317 +        uint32_t    fGradientFlags; //!< see SkGradientShader::Flags
   1.318 +    };
   1.319 +
   1.320 +    virtual GradientType asAGradient(GradientInfo* info) const;
   1.321 +
   1.322 +    /**
   1.323 +     *  If the shader subclass has a GrEffect implementation, this resturns the effect to install.
   1.324 +     *  The incoming color to the effect has r=g=b=a all extracted from the SkPaint's alpha.
   1.325 +     *  The output color should be the computed SkShader premul color modulated by the incoming
   1.326 +     *  color. The GrContext may be used by the effect to create textures. The GPU device does not
   1.327 +     *  call setContext. Instead we pass the SkPaint here in case the shader needs paint info.
   1.328 +     */
   1.329 +    virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint& paint) const;
   1.330 +
   1.331 +    //////////////////////////////////////////////////////////////////////////
   1.332 +    //  Factory methods for stock shaders
   1.333 +
   1.334 +    /** Call this to create a new shader that will draw with the specified bitmap.
   1.335 +     *
   1.336 +     *  If the bitmap cannot be used (e.g. has no pixels, or its dimensions
   1.337 +     *  exceed implementation limits (currently at 64K - 1)) then SkEmptyShader
   1.338 +     *  may be returned.
   1.339 +     *
   1.340 +     *  If the src is kA8_Config then that mask will be colorized using the color on
   1.341 +     *  the paint.
   1.342 +     *
   1.343 +     *  @param src  The bitmap to use inside the shader
   1.344 +     *  @param tmx  The tiling mode to use when sampling the bitmap in the x-direction.
   1.345 +     *  @param tmy  The tiling mode to use when sampling the bitmap in the y-direction.
   1.346 +     *  @return     Returns a new shader object. Note: this function never returns null.
   1.347 +    */
   1.348 +    static SkShader* CreateBitmapShader(const SkBitmap& src,
   1.349 +                                        TileMode tmx, TileMode tmy);
   1.350 +
   1.351 +    SK_TO_STRING_VIRT()
   1.352 +    SK_DEFINE_FLATTENABLE_TYPE(SkShader)
   1.353 +
   1.354 +protected:
   1.355 +    enum MatrixClass {
   1.356 +        kLinear_MatrixClass,            // no perspective
   1.357 +        kFixedStepInX_MatrixClass,      // fast perspective, need to call fixedStepInX() each scanline
   1.358 +        kPerspective_MatrixClass        // slow perspective, need to mappoints each pixel
   1.359 +    };
   1.360 +    static MatrixClass ComputeMatrixClass(const SkMatrix&);
   1.361 +
   1.362 +    // These can be called by your subclass after setContext() has been called
   1.363 +    uint8_t             getPaintAlpha() const { return fPaintAlpha; }
   1.364 +    const SkMatrix&     getTotalInverse() const { return fTotalInverse; }
   1.365 +    MatrixClass         getInverseClass() const { return (MatrixClass)fTotalInverseClass; }
   1.366 +
   1.367 +    SkShader(SkReadBuffer& );
   1.368 +    virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
   1.369 +private:
   1.370 +    SkMatrix            fLocalMatrix;
   1.371 +    SkMatrix            fTotalInverse;
   1.372 +    uint8_t             fPaintAlpha;
   1.373 +    uint8_t             fTotalInverseClass;
   1.374 +    SkDEBUGCODE(SkBool8 fInSetContext;)
   1.375 +
   1.376 +    typedef SkFlattenable INHERITED;
   1.377 +};
   1.378 +
   1.379 +#endif

mercurial