Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / include / core / SkShader.h
index acff959..0fbc1b8 100644 (file)
 #include "SkMask.h"
 #include "SkMatrix.h"
 #include "SkPaint.h"
+#include "../gpu/GrColor.h"
 
 class SkPath;
+class SkPicture;
+class SkXfermode;
 class GrContext;
-class GrEffectRef;
+class GrFragmentProcessor;
 
 /** \class SkShader
  *
@@ -33,29 +36,24 @@ class SK_API SkShader : public SkFlattenable {
 public:
     SK_DECLARE_INST_COUNT(SkShader)
 
-    SkShader();
+    SkShader(const SkMatrix* localMatrix = NULL);
     virtual ~SkShader();
 
     /**
-     * Returns true if the local matrix is not an identity matrix.
-     */
-    bool hasLocalMatrix() const { return !fLocalMatrix.isIdentity(); }
-
-    /**
      *  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; }
 
     /**
-     *  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.
+     *  Returns true if the local matrix is not an identity matrix.
+     *
+     *  FIXME: This can be incorrect for a Shader with its own local matrix
+     *  that is also wrapped via CreateLocalMatrixShader.
      */
-    void resetLocalMatrix() { fLocalMatrix.reset(); }
+    bool hasLocalMatrix() const { return !fLocalMatrix.isIdentity(); }
 
     enum TileMode {
         /** replicate the edge color if the shader draws outside of its
@@ -95,7 +93,7 @@ public:
         */
         kIntrinsicly16_Flag = 0x04,
 
-        /** set (after setContext) if the spans only vary in X (const in Y).
+        /** 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().
@@ -111,84 +109,123 @@ public:
     };
 
     /**
-     *  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.
+     *  optimizations.
      */
     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.
+     *  ContextRec acts as a parameter bundle for creating Contexts.
      */
-    virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; }
+    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
+    };
 
-    /**
-     *  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);
+    class Context : public ::SkNoncopyable {
+    public:
+        Context(const SkShader& shader, const ContextRec&);
 
-    /**
-     *  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();
+        virtual ~Context();
 
-    SkDEBUGCODE(bool setContextHasBeenCalled() const { return SkToBool(fInSetContext); })
+        /**
+         *  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; }
 
-    /**
-     *  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;
+        /**
+         *  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; }
 
-    typedef void (*ShadeProc)(void* ctx, int x, int y, SkPMColor[], int count);
-    virtual ShadeProc asAShadeProc(void** ctx);
+        /**
+         *  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;
 
-    /**
-     *  Called only for 16bit devices when getFlags() returns
-     *  kOpaqueAlphaFlag | kHasSpan16_Flag
-     */
-    virtual void shadeSpan16(int x, int y, uint16_t[], int count);
+        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;
+    };
 
     /**
-     *  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.
+     *  Create the actual object that does the shading.
+     *  Size of storage must be >= contextSize.
      */
-    virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);
+    Context* createContext(const ContextRec&, void* storage) const;
 
     /**
-     *  Helper function that returns true if this shader's shadeSpan16() method
-     *  can be called.
+     *  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.
      */
-    bool canCallShadeSpan16() {
-        return SkShader::CanCallShadeSpan16(this->getFlags());
-    }
+    virtual size_t contextSize() const;
 
     /**
      *  Helper to check the flags to know if it is legal to call shadeSpan16()
@@ -317,17 +354,72 @@ public:
     virtual GradientType asAGradient(GradientInfo* info) const;
 
     /**
-     *  If the shader subclass has a GrEffect implementation, this resturns the effect to install.
-     *  The incoming color to the effect has r=g=b=a all extracted from the SkPaint's alpha.
-     *  The output color should be the computed SkShader premul color modulated by the incoming
-     *  color. The GrContext may be used by the effect to create textures. The GPU device does not
-     *  call setContext. Instead we pass the SkPaint here in case the shader needs paint info.
+     *  If the shader subclass is composed of two shaders, return true, and if rec is not NULL,
+     *  fill it out with info about the shader.
+     *
+     *  These are bare pointers; the ownership and reference count are unchanged.
      */
-    virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint& paint) const;
+
+    struct ComposeRec {
+        const SkShader*     fShaderA;
+        const SkShader*     fShaderB;
+        const SkXfermode*   fMode;
+    };
+
+    virtual bool asACompose(ComposeRec* rec) const { return false; }
+
+
+    /**
+     *  Returns true if the shader subclass succeeds in creating an effect or if none is required.
+     *  False is returned if it fails or if there is not an implementation of this method in the
+     *  shader subclass.
+     *
+     *  On success an implementation of this method must inspect the SkPaint and set paintColor to
+     *  the color the effect expects as its input color. If the SkShader wishes to emit a solid
+     *  color then it should set paintColor to that color and not create an effect. Note that
+     *  GrColor is always premul. The common patterns are to convert paint's SkColor to GrColor or
+     *  to extract paint's alpha and replicate it to all channels in paintColor. Upon failure
+     *  paintColor should not be modified. It is not recommended to specialize the effect to
+     *  the paint's color as then many GPU shaders may be generated.
+     *
+     *  The GrContext may be used by the effect to create textures. The GPU device does not
+     *  call createContext. Instead we pass the SkPaint here in case the shader needs paint info.
+     */
+    virtual bool asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix*, GrColor*,
+                                     GrFragmentProcessor**) const;
+
+    /**
+     *  If the shader can represent its "average" luminance in a single color, return true and
+     *  if color is not NULL, return that color. If it cannot, return false and ignore the color
+     *  parameter.
+     *
+     *  Note: if this returns true, the returned color will always be opaque, as only the RGB
+     *  components are used to compute luminance.
+     */
+    bool asLuminanceColor(SkColor*) const;
+
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+    /**
+     *  If the shader is a custom shader which has data the caller might want, call this function
+     *  to get that data.
+     */
+    virtual bool asACustomShader(void** customData) const { return false; }
+#endif
 
     //////////////////////////////////////////////////////////////////////////
     //  Factory methods for stock shaders
 
+    /**
+     *  Call this to create a new "empty" shader, that will not draw anything.
+     */
+    static SkShader* CreateEmptyShader();
+
+    /**
+     *  Call this to create a new shader that just draws the specified color. This should always
+     *  draw the same as a paint with this color (and no shader).
+     */
+    static SkShader* CreateColorShader(SkColor);
+
     /** Call this to create a new shader that will draw with the specified bitmap.
      *
      *  If the bitmap cannot be used (e.g. has no pixels, or its dimensions
@@ -343,32 +435,73 @@ public:
      *  @return     Returns a new shader object. Note: this function never returns null.
     */
     static SkShader* CreateBitmapShader(const SkBitmap& src,
-                                        TileMode tmx, TileMode tmy);
+                                        TileMode tmx, TileMode tmy,
+                                        const SkMatrix* localMatrix = NULL);
+
+    /** Call this to create a new shader that will draw with the specified picture.
+     *
+     *  @param src  The picture to use inside the shader (if not NULL, its ref count
+     *              is incremented). The SkPicture must not be changed after
+     *              successfully creating a picture shader.
+     *              FIXME: src cannot be const due to SkCanvas::drawPicture
+     *  @param tmx  The tiling mode to use when sampling the bitmap in the x-direction.
+     *  @param tmy  The tiling mode to use when sampling the bitmap in the y-direction.
+     *  @param tile The tile rectangle in picture coordinates: this represents the subset
+     *              (or superset) of the picture used when building a tile. It is not
+     *              affected by localMatrix and does not imply scaling (only translation
+     *              and cropping). If null, the tile rect is considered equal to the picture
+     *              bounds.
+     *  @return     Returns a new shader object. Note: this function never returns null.
+    */
+    static SkShader* CreatePictureShader(SkPicture* src,
+                                         TileMode tmx, TileMode tmy,
+                                         const SkMatrix* localMatrix,
+                                         const SkRect* tile);
+
+    /**
+     *  Return a shader that will apply the specified localMatrix to the proxy shader.
+     *  The specified matrix will be applied before any matrix associated with the proxy.
+     *
+     *  Note: ownership of the proxy is not transferred (though a ref is taken).
+     */
+    static SkShader* CreateLocalMatrixShader(SkShader* proxy, const SkMatrix& localMatrix);
+
+    /**
+     *  If this shader can be represented by another shader + a localMatrix, return that shader
+     *  and, if not NULL, the localMatrix. If not, return NULL and ignore the localMatrix parameter.
+     *
+     *  Note: the returned shader (if not NULL) will have been ref'd, and it is the responsibility
+     *  of the caller to balance that with unref() when they are done.
+     */
+    virtual SkShader* refAsALocalMatrixShader(SkMatrix* localMatrix) const;
 
     SK_TO_STRING_VIRT()
     SK_DEFINE_FLATTENABLE_TYPE(SkShader)
 
 protected:
-    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&);
-
-    // These can be called by your subclass after setContext() has been called
-    uint8_t             getPaintAlpha() const { return fPaintAlpha; }
-    const SkMatrix&     getTotalInverse() const { return fTotalInverse; }
-    MatrixClass         getInverseClass() const { return (MatrixClass)fTotalInverseClass; }
-
+#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
     SkShader(SkReadBuffer& );
+#endif
     virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
+
+    bool computeTotalInverse(const ContextRec&, SkMatrix* totalInverse) const;
+
+    /**
+     *  Your subclass must also override contextSize() if it overrides onCreateContext().
+     *  Base class impl returns NULL.
+     */
+    virtual Context* onCreateContext(const ContextRec&, void* storage) const;
+
+    virtual bool onAsLuminanceColor(SkColor*) const {
+        return false;
+    }
 private:
-    SkMatrix            fLocalMatrix;
-    SkMatrix            fTotalInverse;
-    uint8_t             fPaintAlpha;
-    uint8_t             fTotalInverseClass;
-    SkDEBUGCODE(SkBool8 fInSetContext;)
+    // This is essentially const, but not officially so it can be modified in
+    // constructors.
+    SkMatrix fLocalMatrix;
+
+    // So the SkLocalMatrixShader can whack fLocalMatrix in its SkReadBuffer constructor.
+    friend class SkLocalMatrixShader;
 
     typedef SkFlattenable INHERITED;
 };