LCOV - code coverage report
Current view: top level - gfx/skia/skia/include/core - SkShader.h (source / functions) Hit Total Coverage
Test: output.info Lines: 7 35 20.0 %
Date: 2017-07-14 16:53:18 Functions: 5 20 25.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2006 The Android Open Source Project
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #ifndef SkShader_DEFINED
       9             : #define SkShader_DEFINED
      10             : 
      11             : #include "SkBitmap.h"
      12             : #include "SkFilterQuality.h"
      13             : #include "SkFlattenable.h"
      14             : #include "SkImageInfo.h"
      15             : #include "SkMask.h"
      16             : #include "SkMatrix.h"
      17             : #include "SkPaint.h"
      18             : #include "../gpu/GrColor.h"
      19             : 
      20             : class SkArenaAlloc;
      21             : class SkColorFilter;
      22             : class SkColorSpace;
      23             : class SkImage;
      24             : class SkPath;
      25             : class SkPicture;
      26             : class SkRasterPipeline;
      27             : class GrContext;
      28             : class GrFragmentProcessor;
      29             : 
      30             : /** \class SkShader
      31             :  *
      32             :  *  Shaders specify the source color(s) for what is being drawn. If a paint
      33             :  *  has no shader, then the paint's color is used. If the paint has a
      34             :  *  shader, then the shader's color(s) are use instead, but they are
      35             :  *  modulated by the paint's alpha. This makes it easy to create a shader
      36             :  *  once (e.g. bitmap tiling or gradient) and then change its transparency
      37             :  *  w/o having to modify the original shader... only the paint's alpha needs
      38             :  *  to be modified.
      39             :  */
      40             : class SK_API SkShader : public SkFlattenable {
      41             : public:
      42             :     SkShader(const SkMatrix* localMatrix = NULL);
      43             :     ~SkShader() override;
      44             : 
      45             :     /**
      46             :      *  Returns the local matrix.
      47             :      *
      48             :      *  FIXME: This can be incorrect for a Shader with its own local matrix
      49             :      *  that is also wrapped via CreateLocalMatrixShader.
      50             :      */
      51           2 :     const SkMatrix& getLocalMatrix() const { return fLocalMatrix; }
      52             : 
      53             :     enum TileMode {
      54             :         /** replicate the edge color if the shader draws outside of its
      55             :          *  original bounds
      56             :          */
      57             :         kClamp_TileMode,
      58             : 
      59             :         /** repeat the shader's image horizontally and vertically */
      60             :         kRepeat_TileMode,
      61             : 
      62             :         /** repeat the shader's image horizontally and vertically, alternating
      63             :          *  mirror images so that adjacent images always seam
      64             :          */
      65             :         kMirror_TileMode,
      66             : 
      67             : #if 0
      68             :         /** only draw within the original domain, return 0 everywhere else */
      69             :         kDecal_TileMode,
      70             : #endif
      71             :     };
      72             : 
      73             :     enum {
      74             :         kTileModeCount = kMirror_TileMode + 1
      75             :     };
      76             : 
      77             :     // override these in your subclass
      78             : 
      79             :     enum Flags {
      80             :         //!< set if all of the colors will be opaque
      81             :         kOpaqueAlpha_Flag = 1 << 0,
      82             : 
      83             :         /** set if the spans only vary in X (const in Y).
      84             :             e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
      85             :             that varies from left-to-right. This flag specifies this for
      86             :             shadeSpan().
      87             :          */
      88             :         kConstInY32_Flag = 1 << 1,
      89             : 
      90             :         /** hint for the blitter that 4f is the preferred shading mode.
      91             :          */
      92             :         kPrefers4f_Flag  = 1 << 2,
      93             :     };
      94             : 
      95             :     /**
      96             :      *  Returns true if the shader is guaranteed to produce only opaque
      97             :      *  colors, subject to the SkPaint using the shader to apply an opaque
      98             :      *  alpha value. Subclasses should override this to allow some
      99             :      *  optimizations.
     100             :      */
     101           0 :     virtual bool isOpaque() const { return false; }
     102             : 
     103             :     /**
     104             :      *  Returns true if the shader is guaranteed to produce only a single color.
     105             :      *  Subclasses can override this to allow loop-hoisting optimization.
     106             :      */
     107           0 :     virtual bool isConstant() const { return false; }
     108             : 
     109             :     /**
     110             :      *  ContextRec acts as a parameter bundle for creating Contexts.
     111             :      */
     112             :     struct ContextRec {
     113             :         enum DstType {
     114             :             kPMColor_DstType, // clients prefer shading into PMColor dest
     115             :             kPM4f_DstType,    // clients prefer shading into PM4f dest
     116             :         };
     117             : 
     118         166 :         ContextRec(const SkPaint& paint, const SkMatrix& matrix, const SkMatrix* localM,
     119             :                    DstType dstType, SkColorSpace* dstColorSpace)
     120         166 :             : fPaint(&paint)
     121             :             , fMatrix(&matrix)
     122             :             , fLocalMatrix(localM)
     123             :             , fPreferredDstType(dstType)
     124         166 :             , fDstColorSpace(dstColorSpace) {}
     125             : 
     126             :         const SkPaint*  fPaint;            // the current paint associated with the draw
     127             :         const SkMatrix* fMatrix;           // the current matrix in the canvas
     128             :         const SkMatrix* fLocalMatrix;      // optional local matrix
     129             :         const DstType   fPreferredDstType; // the "natural" client dest type
     130             :         SkColorSpace*   fDstColorSpace;    // the color space of the dest surface (if any)
     131             :     };
     132             : 
     133             :     class Context : public ::SkNoncopyable {
     134             :     public:
     135             :         Context(const SkShader& shader, const ContextRec&);
     136             : 
     137             :         virtual ~Context();
     138             : 
     139             :         /**
     140             :          *  Called sometimes before drawing with this shader. Return the type of
     141             :          *  alpha your shader will return. The default implementation returns 0.
     142             :          *  Your subclass should override if it can (even sometimes) report a
     143             :          *  non-zero value, since that will enable various blitters to perform
     144             :          *  faster.
     145             :          */
     146          25 :         virtual uint32_t getFlags() const { return 0; }
     147             : 
     148             :         /**
     149             :          *  Called for each span of the object being drawn. Your subclass should
     150             :          *  set the appropriate colors (with premultiplied alpha) that correspond
     151             :          *  to the specified device coordinates.
     152             :          */
     153             :         virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
     154             : 
     155             :         virtual void shadeSpan4f(int x, int y, SkPM4f[], int count);
     156             : 
     157             :         struct BlitState;
     158             :         typedef void (*BlitBW)(BlitState*,
     159             :                                int x, int y, const SkPixmap&, int count);
     160             :         typedef void (*BlitAA)(BlitState*,
     161             :                                int x, int y, const SkPixmap&, int count, const SkAlpha[]);
     162             : 
     163             :         struct BlitState {
     164             :             // inputs
     165             :             Context*    fCtx;
     166             :             SkBlendMode fMode;
     167             : 
     168             :             // outputs
     169             :             enum { N = 2 };
     170             :             void*       fStorage[N];
     171             :             BlitBW      fBlitBW;
     172             :             BlitAA      fBlitAA;
     173             :         };
     174             : 
     175             :         // Returns true if one or more of the blitprocs are set in the BlitState
     176           0 :         bool chooseBlitProcs(const SkImageInfo& info, BlitState* state) {
     177           0 :             state->fBlitBW = nullptr;
     178           0 :             state->fBlitAA = nullptr;
     179           0 :             if (this->onChooseBlitProcs(info, state)) {
     180           0 :                 SkASSERT(state->fBlitBW || state->fBlitAA);
     181           0 :                 return true;
     182             :             }
     183           0 :             return false;
     184             :         }
     185             : 
     186             :         /**
     187             :          * The const void* ctx is only const because all the implementations are const.
     188             :          * This can be changed to non-const if a new shade proc needs to change the ctx.
     189             :          */
     190             :         typedef void (*ShadeProc)(const void* ctx, int x, int y, SkPMColor[], int count);
     191             :         virtual ShadeProc asAShadeProc(void** ctx);
     192             : 
     193             :         /**
     194             :          *  Similar to shadeSpan, but only returns the alpha-channel for a span.
     195             :          *  The default implementation calls shadeSpan() and then extracts the alpha
     196             :          *  values from the returned colors.
     197             :          */
     198             :         virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);
     199             : 
     200             :         // Notification from blitter::blitMask in case we need to see the non-alpha channels
     201           0 :         virtual void set3DMask(const SkMask*) {}
     202             : 
     203             :     protected:
     204             :         // Reference to shader, so we don't have to dupe information.
     205             :         const SkShader& fShader;
     206             : 
     207             :         enum MatrixClass {
     208             :             kLinear_MatrixClass,            // no perspective
     209             :             kFixedStepInX_MatrixClass,      // fast perspective, need to call fixedStepInX() each
     210             :                                             // scanline
     211             :             kPerspective_MatrixClass        // slow perspective, need to mappoints each pixel
     212             :         };
     213             :         static MatrixClass ComputeMatrixClass(const SkMatrix&);
     214             : 
     215          79 :         uint8_t         getPaintAlpha() const { return fPaintAlpha; }
     216          42 :         const SkMatrix& getTotalInverse() const { return fTotalInverse; }
     217             :         MatrixClass     getInverseClass() const { return (MatrixClass)fTotalInverseClass; }
     218           0 :         const SkMatrix& getCTM() const { return fCTM; }
     219             : 
     220           0 :         virtual bool onChooseBlitProcs(const SkImageInfo&, BlitState*) { return false; }
     221             : 
     222             :     private:
     223             :         SkMatrix    fCTM;
     224             :         SkMatrix    fTotalInverse;
     225             :         uint8_t     fPaintAlpha;
     226             :         uint8_t     fTotalInverseClass;
     227             : 
     228             :         typedef SkNoncopyable INHERITED;
     229             :     };
     230             : 
     231             :     /**
     232             :      * Make a context using the memory provided by the arena.
     233             :      *
     234             :      * @return pointer to context or nullptr if can't be created
     235             :      */
     236             :     Context* makeContext(const ContextRec&, SkArenaAlloc*) const;
     237             : 
     238             : #ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP
     239             :     /**
     240             :      *  Returns true if this shader is just a bitmap, and if not null, returns the bitmap,
     241             :      *  localMatrix, and tilemodes. If this is not a bitmap, returns false and ignores the
     242             :      *  out-parameters.
     243             :      */
     244             :     bool isABitmap(SkBitmap* outTexture, SkMatrix* outMatrix, TileMode xy[2]) const {
     245             :         return this->onIsABitmap(outTexture, outMatrix, xy);
     246             :     }
     247             : 
     248             :     bool isABitmap() const {
     249             :         return this->isABitmap(nullptr, nullptr, nullptr);
     250             :     }
     251             : #endif
     252             : 
     253             :     /**
     254             :      *  Iff this shader is backed by a single SkImage, return its ptr (the caller must ref this
     255             :      *  if they want to keep it longer than the lifetime of the shader). If not, return nullptr.
     256             :      */
     257           0 :     SkImage* isAImage(SkMatrix* localMatrix, TileMode xy[2]) const {
     258           0 :         return this->onIsAImage(localMatrix, xy);
     259             :     }
     260             : 
     261           0 :     bool isAImage() const {
     262           0 :         return this->isAImage(nullptr, nullptr) != nullptr;
     263             :     }
     264             : 
     265             :     /**
     266             :      *  If the shader subclass can be represented as a gradient, asAGradient
     267             :      *  returns the matching GradientType enum (or kNone_GradientType if it
     268             :      *  cannot). Also, if info is not null, asAGradient populates info with
     269             :      *  the relevant (see below) parameters for the gradient.  fColorCount
     270             :      *  is both an input and output parameter.  On input, it indicates how
     271             :      *  many entries in fColors and fColorOffsets can be used, if they are
     272             :      *  non-NULL.  After asAGradient has run, fColorCount indicates how
     273             :      *  many color-offset pairs there are in the gradient.  If there is
     274             :      *  insufficient space to store all of the color-offset pairs, fColors
     275             :      *  and fColorOffsets will not be altered.  fColorOffsets specifies
     276             :      *  where on the range of 0 to 1 to transition to the given color.
     277             :      *  The meaning of fPoint and fRadius is dependant on the type of gradient.
     278             :      *
     279             :      *  None:
     280             :      *      info is ignored.
     281             :      *  Color:
     282             :      *      fColorOffsets[0] is meaningless.
     283             :      *  Linear:
     284             :      *      fPoint[0] and fPoint[1] are the end-points of the gradient
     285             :      *  Radial:
     286             :      *      fPoint[0] and fRadius[0] are the center and radius
     287             :      *  Conical:
     288             :      *      fPoint[0] and fRadius[0] are the center and radius of the 1st circle
     289             :      *      fPoint[1] and fRadius[1] are the center and radius of the 2nd circle
     290             :      *  Sweep:
     291             :      *      fPoint[0] is the center of the sweep.
     292             :      */
     293             : 
     294             :     enum GradientType {
     295             :         kNone_GradientType,
     296             :         kColor_GradientType,
     297             :         kLinear_GradientType,
     298             :         kRadial_GradientType,
     299             :         kSweep_GradientType,
     300             :         kConical_GradientType,
     301             :         kLast_GradientType = kConical_GradientType
     302             :     };
     303             : 
     304             :     struct GradientInfo {
     305             :         int         fColorCount;    //!< In-out parameter, specifies passed size
     306             :                                     //   of fColors/fColorOffsets on input, and
     307             :                                     //   actual number of colors/offsets on
     308             :                                     //   output.
     309             :         SkColor*    fColors;        //!< The colors in the gradient.
     310             :         SkScalar*   fColorOffsets;  //!< The unit offset for color transitions.
     311             :         SkPoint     fPoint[2];      //!< Type specific, see above.
     312             :         SkScalar    fRadius[2];     //!< Type specific, see above.
     313             :         TileMode    fTileMode;      //!< The tile mode used.
     314             :         uint32_t    fGradientFlags; //!< see SkGradientShader::Flags
     315             :     };
     316             : 
     317             :     virtual GradientType asAGradient(GradientInfo* info) const;
     318             : 
     319             :     /**
     320             :      *  If the shader subclass is composed of two shaders, return true, and if rec is not NULL,
     321             :      *  fill it out with info about the shader.
     322             :      *
     323             :      *  These are bare pointers; the ownership and reference count are unchanged.
     324             :      */
     325             : 
     326             :     struct ComposeRec {
     327             :         const SkShader*     fShaderA;
     328             :         const SkShader*     fShaderB;
     329             :         SkBlendMode         fBlendMode;
     330             :     };
     331             : 
     332           0 :     virtual bool asACompose(ComposeRec*) const { return false; }
     333             : 
     334             : #if SK_SUPPORT_GPU
     335             :     struct AsFPArgs {
     336           0 :         AsFPArgs() {}
     337           0 :         AsFPArgs(GrContext* context,
     338             :                  const SkMatrix* viewMatrix,
     339             :                  const SkMatrix* localMatrix,
     340             :                  SkFilterQuality filterQuality,
     341             :                  SkColorSpace* dstColorSpace)
     342           0 :             : fContext(context)
     343             :             , fViewMatrix(viewMatrix)
     344             :             , fLocalMatrix(localMatrix)
     345             :             , fFilterQuality(filterQuality)
     346           0 :             , fDstColorSpace(dstColorSpace) {}
     347             : 
     348             :         GrContext*                    fContext;
     349             :         const SkMatrix*               fViewMatrix;
     350             :         const SkMatrix*               fLocalMatrix;
     351             :         SkFilterQuality               fFilterQuality;
     352             :         SkColorSpace*                 fDstColorSpace;
     353             :     };
     354             : 
     355             :     /**
     356             :      *  Returns a GrFragmentProcessor that implements the shader for the GPU backend. NULL is
     357             :      *  returned if there is no GPU implementation.
     358             :      *
     359             :      *  The GPU device does not call SkShader::createContext(), instead we pass the view matrix,
     360             :      *  local matrix, and filter quality directly.
     361             :      *
     362             :      *  The GrContext may be used by the to create textures that are required by the returned
     363             :      *  processor.
     364             :      *
     365             :      *  The returned GrFragmentProcessor should expect an unpremultiplied input color and
     366             :      *  produce a premultiplied output.
     367             :      */
     368             :     virtual sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const;
     369             : #endif
     370             : 
     371             :     /**
     372             :      *  If the shader can represent its "average" luminance in a single color, return true and
     373             :      *  if color is not NULL, return that color. If it cannot, return false and ignore the color
     374             :      *  parameter.
     375             :      *
     376             :      *  Note: if this returns true, the returned color will always be opaque, as only the RGB
     377             :      *  components are used to compute luminance.
     378             :      */
     379             :     bool asLuminanceColor(SkColor*) const;
     380             : 
     381             :     //////////////////////////////////////////////////////////////////////////
     382             :     //  Methods to create combinations or variants of shaders
     383             : 
     384             :     /**
     385             :      *  Return a shader that will apply the specified localMatrix to this shader.
     386             :      *  The specified matrix will be applied before any matrix associated with this shader.
     387             :      */
     388             :     sk_sp<SkShader> makeWithLocalMatrix(const SkMatrix&) const;
     389             : 
     390             :     /**
     391             :      *  Create a new shader that produces the same colors as invoking this shader and then applying
     392             :      *  the colorfilter.
     393             :      */
     394             :     sk_sp<SkShader> makeWithColorFilter(sk_sp<SkColorFilter>) const;
     395             : 
     396             :     //////////////////////////////////////////////////////////////////////////
     397             :     //  Factory methods for stock shaders
     398             : 
     399             :     /**
     400             :      *  Call this to create a new "empty" shader, that will not draw anything.
     401             :      */
     402             :     static sk_sp<SkShader> MakeEmptyShader();
     403             : 
     404             :     /**
     405             :      *  Call this to create a new shader that just draws the specified color. This should always
     406             :      *  draw the same as a paint with this color (and no shader).
     407             :      */
     408             :     static sk_sp<SkShader> MakeColorShader(SkColor);
     409             : 
     410             :     /**
     411             :      *  Create a shader that draws the specified color (in the specified colorspace).
     412             :      *
     413             :      *  This works around the limitation that SkPaint::setColor() only takes byte values, and does
     414             :      *  not support specific colorspaces.
     415             :      */
     416             :     static sk_sp<SkShader> MakeColorShader(const SkColor4f&, sk_sp<SkColorSpace>);
     417             : 
     418             :     static sk_sp<SkShader> MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src, SkBlendMode);
     419             : 
     420             :     /** Call this to create a new shader that will draw with the specified bitmap.
     421             :      *
     422             :      *  If the bitmap cannot be used (e.g. has no pixels, or its dimensions
     423             :      *  exceed implementation limits (currently at 64K - 1)) then SkEmptyShader
     424             :      *  may be returned.
     425             :      *
     426             :      *  If the src is kA8_Config then that mask will be colorized using the color on
     427             :      *  the paint.
     428             :      *
     429             :      *  @param src  The bitmap to use inside the shader
     430             :      *  @param tmx  The tiling mode to use when sampling the bitmap in the x-direction.
     431             :      *  @param tmy  The tiling mode to use when sampling the bitmap in the y-direction.
     432             :      *  @return     Returns a new shader object. Note: this function never returns null.
     433             :     */
     434             :     static sk_sp<SkShader> MakeBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
     435             :                                             const SkMatrix* localMatrix = nullptr);
     436             : 
     437             :     // NOTE: You can create an SkImage Shader with SkImage::newShader().
     438             : 
     439             :     /** Call this to create a new shader that will draw with the specified picture.
     440             :      *
     441             :      *  @param src  The picture to use inside the shader (if not NULL, its ref count
     442             :      *              is incremented). The SkPicture must not be changed after
     443             :      *              successfully creating a picture shader.
     444             :      *  @param tmx  The tiling mode to use when sampling the bitmap in the x-direction.
     445             :      *  @param tmy  The tiling mode to use when sampling the bitmap in the y-direction.
     446             :      *  @param tile The tile rectangle in picture coordinates: this represents the subset
     447             :      *              (or superset) of the picture used when building a tile. It is not
     448             :      *              affected by localMatrix and does not imply scaling (only translation
     449             :      *              and cropping). If null, the tile rect is considered equal to the picture
     450             :      *              bounds.
     451             :      *  @return     Returns a new shader object. Note: this function never returns null.
     452             :     */
     453             :     static sk_sp<SkShader> MakePictureShader(sk_sp<SkPicture> src, TileMode tmx, TileMode tmy,
     454             :                                              const SkMatrix* localMatrix, const SkRect* tile);
     455             : 
     456             :     /**
     457             :      *  If this shader can be represented by another shader + a localMatrix, return that shader and
     458             :      *  the localMatrix. If not, return nullptr and ignore the localMatrix parameter.
     459             :      */
     460             :     virtual sk_sp<SkShader> makeAsALocalMatrixShader(SkMatrix* localMatrix) const;
     461             : 
     462             :     SK_TO_STRING_VIRT()
     463           0 :     SK_DEFINE_FLATTENABLE_TYPE(SkShader)
     464             :     SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
     465             : 
     466             :     bool appendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
     467             :                       const SkMatrix& ctm, const SkPaint&) const;
     468             : 
     469             : protected:
     470             :     void flatten(SkWriteBuffer&) const override;
     471             : 
     472             :     bool computeTotalInverse(const ContextRec&, SkMatrix* totalInverse) const;
     473             : 
     474             :     /**
     475             :      * Specialize creating a SkShader context using the supplied allocator.
     476             :      * @return pointer to context owned by the arena allocator.
     477             :      */
     478           0 :     virtual Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const {
     479           0 :         return nullptr;
     480             :     }
     481             : 
     482           0 :     virtual bool onAsLuminanceColor(SkColor*) const {
     483           0 :         return false;
     484             :     }
     485             : 
     486             : #ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP
     487             :     virtual bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode[2]) const {
     488             :         return false;
     489             :     }
     490             : #endif
     491             : 
     492           0 :     virtual SkImage* onIsAImage(SkMatrix*, TileMode[2]) const {
     493           0 :         return nullptr;
     494             :     }
     495             : 
     496             :     virtual bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
     497             :                                 const SkMatrix&, const SkPaint&,
     498             :                                 const SkMatrix* /*local matrix*/) const;
     499             : 
     500             : private:
     501             :     // This is essentially const, but not officially so it can be modified in
     502             :     // constructors.
     503             :     SkMatrix fLocalMatrix;
     504             : 
     505             :     // So the SkLocalMatrixShader can whack fLocalMatrix in its SkReadBuffer constructor.
     506             :     friend class SkLocalMatrixShader;
     507             :     friend class SkBitmapProcLegacyShader;    // for computeTotalInverse()
     508             : 
     509             :     typedef SkFlattenable INHERITED;
     510             : };
     511             : 
     512             : #endif

Generated by: LCOV version 1.13