Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #ifndef SkXfermode_DEFINED
     11 #define SkXfermode_DEFINED
     12 
     13 #include "SkFlattenable.h"
     14 #include "SkColor.h"
     15 
     16 class GrFragmentProcessor;
     17 class GrTexture;
     18 class GrXPFactory;
     19 class SkString;
     20 
     21 struct SkPM4f;
     22 typedef SkPM4f (*SkXfermodeProc4f)(const SkPM4f& src, const SkPM4f& dst);
     23 
     24 /** \class SkXfermode
     25  *
     26  *  SkXfermode is the base class for objects that are called to implement custom
     27  *  "transfer-modes" in the drawing pipeline. The static function Create(Modes)
     28  *  can be called to return an instance of any of the predefined subclasses as
     29  *  specified in the Modes enum. When an SkXfermode is assigned to an SkPaint,
     30  *  then objects drawn with that paint have the xfermode applied.
     31  *
     32  *  All subclasses are required to be reentrant-safe : it must be legal to share
     33  *  the same instance between several threads.
     34  */
     35 class SK_API SkXfermode : public SkFlattenable {
     36 public:
     37     virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
     38                         const SkAlpha aa[]) const;
     39     virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
     40                         const SkAlpha aa[]) const;
     41     virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
     42                         const SkAlpha aa[]) const;
     43 
     44     /** Enum of possible coefficients to describe some xfermodes
     45      */
     46     enum Coeff {
     47         kZero_Coeff,    /** 0 */
     48         kOne_Coeff,     /** 1 */
     49         kSC_Coeff,      /** src color */
     50         kISC_Coeff,     /** inverse src color (i.e. 1 - sc) */
     51         kDC_Coeff,      /** dst color */
     52         kIDC_Coeff,     /** inverse dst color (i.e. 1 - dc) */
     53         kSA_Coeff,      /** src alpha */
     54         kISA_Coeff,     /** inverse src alpha (i.e. 1 - sa) */
     55         kDA_Coeff,      /** dst alpha */
     56         kIDA_Coeff,     /** inverse dst alpha (i.e. 1 - da) */
     57 
     58         kCoeffCount
     59     };
     60 
     61     /** List of predefined xfermodes.
     62         The algebra for the modes uses the following symbols:
     63         Sa, Sc  - source alpha and color
     64         Da, Dc - destination alpha and color (before compositing)
     65         [a, c] - Resulting (alpha, color) values
     66         For these equations, the colors are in premultiplied state.
     67         If no xfermode is specified, kSrcOver is assumed.
     68         The modes are ordered by those that can be expressed as a pair of Coeffs, followed by those
     69         that aren't Coeffs but have separable r,g,b computations, and finally
     70         those that are not separable.
     71      */
     72     enum Mode {
     73         kClear_Mode,    //!< [0, 0]
     74         kSrc_Mode,      //!< [Sa, Sc]
     75         kDst_Mode,      //!< [Da, Dc]
     76         kSrcOver_Mode,  //!< [Sa + Da * (1 - Sa), Sc + Dc * (1 - Sa)]
     77         kDstOver_Mode,  //!< [Da + Sa * (1 - Da), Dc + Sc * (1 - Da)]
     78         kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
     79         kDstIn_Mode,    //!< [Da * Sa, Dc * Sa]
     80         kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
     81         kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
     82         kSrcATop_Mode,  //!< [Da, Sc * Da + Dc * (1 - Sa)]
     83         kDstATop_Mode,  //!< [Sa, Dc * Sa + Sc * (1 - Da)]
     84         kXor_Mode,      //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa)]
     85         kPlus_Mode,     //!< [Sa + Da, Sc + Dc]
     86         kModulate_Mode, // multiplies all components (= alpha and color)
     87 
     88         // Following blend modes are defined in the CSS Compositing standard:
     89         // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending
     90         kScreen_Mode,
     91         kLastCoeffMode = kScreen_Mode,
     92 
     93         kOverlay_Mode,
     94         kDarken_Mode,
     95         kLighten_Mode,
     96         kColorDodge_Mode,
     97         kColorBurn_Mode,
     98         kHardLight_Mode,
     99         kSoftLight_Mode,
    100         kDifference_Mode,
    101         kExclusion_Mode,
    102         kMultiply_Mode,
    103         kLastSeparableMode = kMultiply_Mode,
    104 
    105         kHue_Mode,
    106         kSaturation_Mode,
    107         kColor_Mode,
    108         kLuminosity_Mode,
    109         kLastMode = kLuminosity_Mode
    110     };
    111 
    112     /**
    113      * Gets the name of the Mode as a string.
    114      */
    115     static const char* ModeName(Mode);
    116 
    117     /**
    118      *  If the xfermode is one of the modes in the Mode enum, then asMode()
    119      *  returns true and sets (if not null) mode accordingly. Otherwise it
    120      *  returns false and ignores the mode parameter.
    121      */
    122     virtual bool asMode(Mode* mode) const;
    123 
    124     /**
    125      *  The same as calling xfermode->asMode(mode), except that this also checks
    126      *  if the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
    127      */
    128     static bool AsMode(const SkXfermode*, Mode* mode);
    129 
    130     /**
    131      *  Returns true if the xfermode claims to be the specified Mode. This works
    132      *  correctly even if the xfermode is NULL (which equates to kSrcOver.) Thus
    133      *  you can say this without checking for a null...
    134      *
    135      *  If (SkXfermode::IsMode(paint.getXfermode(),
    136      *                         SkXfermode::kDstOver_Mode)) {
    137      *      ...
    138      *  }
    139      */
    140     static bool IsMode(const SkXfermode* xfer, Mode mode);
    141 
    142     /** Return an SkXfermode object for the specified mode.
    143      */
    144     static SkXfermode* Create(Mode mode);
    145 
    146     /** Return a function pointer to a routine that applies the specified
    147         porter-duff transfer mode.
    148      */
    149     static SkXfermodeProc GetProc(Mode mode);
    150     static SkXfermodeProc4f GetProc4f(Mode);
    151 
    152     virtual SkXfermodeProc4f getProc4f() const;
    153 
    154     /**
    155      *  If the specified mode can be represented by a pair of Coeff, then return
    156      *  true and set (if not NULL) the corresponding coeffs. If the mode is
    157      *  not representable as a pair of Coeffs, return false and ignore the
    158      *  src and dst parameters.
    159      */
    160     static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst);
    161 
    162     SK_ATTR_DEPRECATED("use AsMode(...)")
    163     static bool IsMode(const SkXfermode* xfer, Mode* mode) {
    164         return AsMode(xfer, mode);
    165     }
    166 
    167     /**
    168      * Returns whether or not the xfer mode can support treating coverage as alpha
    169      */
    170     virtual bool supportsCoverageAsAlpha() const;
    171 
    172     /**
    173      *  The same as calling xfermode->supportsCoverageAsAlpha(), except that this also checks if
    174      *  the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
    175      */
    176     static bool SupportsCoverageAsAlpha(const SkXfermode* xfer);
    177 
    178     enum SrcColorOpacity {
    179         // The src color is known to be opaque (alpha == 255)
    180         kOpaque_SrcColorOpacity = 0,
    181         // The src color is known to be fully transparent (color == 0)
    182         kTransparentBlack_SrcColorOpacity = 1,
    183         // The src alpha is known to be fully transparent (alpha == 0)
    184         kTransparentAlpha_SrcColorOpacity = 2,
    185         // The src color opacity is unknown
    186         kUnknown_SrcColorOpacity = 3
    187     };
    188 
    189     /**
    190      * Returns whether or not the result of the draw with the xfer mode will be opaque or not. The
    191      * input to this call is an enum describing known information about the opacity of the src color
    192      * that will be given to the xfer mode.
    193      */
    194     virtual bool isOpaque(SrcColorOpacity opacityType) const;
    195 
    196     /**
    197      *  The same as calling xfermode->isOpaque(...), except that this also checks if
    198      *  the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
    199      */
    200     static bool IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType);
    201 
    202 #if SK_SUPPORT_GPU
    203     /** Used by the SkXfermodeImageFilter to blend two colors via a GrFragmentProcessor.
    204         The input to the returned FP is the src color. The dst color is
    205         provided by the dst param which becomes a child FP of the returned FP.
    206         It is legal for the function to return a null output. This indicates that
    207         the output of the blend is simply the src color.
    208      */
    209     virtual const GrFragmentProcessor* getFragmentProcessorForImageFilter(
    210                                                             const GrFragmentProcessor* dst) const;
    211 
    212     /** A subclass must implement this factory function to work with the GPU backend.
    213         The xfermode will return a factory for which the caller will get a ref. It is up
    214         to the caller to install it. XferProcessors cannot use a background texture.
    215       */
    216     virtual GrXPFactory* asXPFactory() const;
    217 #endif
    218 
    219     SK_TO_STRING_PUREVIRT()
    220     SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
    221     SK_DEFINE_FLATTENABLE_TYPE(SkXfermode)
    222 
    223     enum D32Flags {
    224         kSrcIsOpaque_D32Flag  = 1 << 0,
    225         kSrcIsSingle_D32Flag  = 1 << 1,
    226         kDstIsSRGB_D32Flag    = 1 << 2,
    227     };
    228     typedef void (*D32Proc)(const SkXfermode*, uint32_t dst[], const SkPM4f src[],
    229                             int count, const SkAlpha coverage[]);
    230     static D32Proc GetD32Proc(SkXfermode*, uint32_t flags);
    231 
    232     enum D64Flags {
    233         kSrcIsOpaque_D64Flag  = 1 << 0,
    234         kSrcIsSingle_D64Flag  = 1 << 1,
    235         kDstIsFloat16_D64Flag = 1 << 2, // else U16 bit components
    236     };
    237     typedef void (*D64Proc)(const SkXfermode*, uint64_t dst[], const SkPM4f src[], int count,
    238                             const SkAlpha coverage[]);
    239     static D64Proc GetD64Proc(SkXfermode*, uint32_t flags);
    240 
    241     enum LCDFlags {
    242         kSrcIsOpaque_LCDFlag    = 1 << 0,   // else src(s) may have alpha < 1
    243         kSrcIsSingle_LCDFlag    = 1 << 1,   // else src[count]
    244         kDstIsLinearInt_LCDFlag = 1 << 2,   // else srgb/half-float
    245     };
    246     typedef void (*LCD32Proc)(uint32_t* dst, const SkPM4f* src, int count, const uint16_t lcd[]);
    247     typedef void (*LCD64Proc)(uint64_t* dst, const SkPM4f* src, int count, const uint16_t lcd[]);
    248     static LCD32Proc GetLCD32Proc(uint32_t flags);
    249     static LCD64Proc GetLCD64Proc(uint32_t) { return nullptr; }
    250 
    251 protected:
    252     SkXfermode() {}
    253     /** The default implementation of xfer32/xfer16/xferA8 in turn call this
    254         method, 1 color at a time (upscaled to a SkPMColor). The default
    255         implementation of this method just returns dst. If performance is
    256         important, your subclass should override xfer32/xfer16/xferA8 directly.
    257 
    258         This method will not be called directly by the client, so it need not
    259         be implemented if your subclass has overridden xfer32/xfer16/xferA8
    260     */
    261     virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const;
    262 
    263     virtual D32Proc onGetD32Proc(uint32_t flags) const;
    264     virtual D64Proc onGetD64Proc(uint32_t flags) const;
    265 
    266 private:
    267     enum {
    268         kModeCount = kLastMode + 1
    269     };
    270 
    271     typedef SkFlattenable INHERITED;
    272 };
    273 
    274 #endif
    275