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