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 SkXfermode
     17 
     18     SkXfermode is the base class for objects that are called to implement custom
     19     "transfer-modes" in the drawing pipeline. The static function Create(Modes)
     20     can be called to return an instance of any of the predefined subclasses as
     21     specified in the Modes enum. When an SkXfermode is assigned to an SkPaint,
     22     then objects drawn with that paint have the xfermode applied.
     23 */
     24 class SK_API SkXfermode : public SkFlattenable {
     25 public:
     26     SkXfermode() {}
     27 
     28     virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
     29                         const SkAlpha aa[]);
     30     virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
     31                         const SkAlpha aa[]);
     32     virtual void xfer4444(uint16_t dst[], const SkPMColor src[], int count,
     33                           const SkAlpha aa[]);
     34     virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
     35                         const SkAlpha aa[]);
     36 
     37     /** Enum of possible coefficients to describe some xfermodes
     38      */
     39     enum Coeff {
     40         kZero_Coeff,    /** 0 */
     41         kOne_Coeff,     /** 1 */
     42         kSC_Coeff,      /** src color */
     43         kISC_Coeff,     /** inverse src color (i.e. 1 - sc) */
     44         kDC_Coeff,      /** dst color */
     45         kIDC_Coeff,     /** inverse dst color (i.e. 1 - dc) */
     46         kSA_Coeff,      /** src alpha */
     47         kISA_Coeff,     /** inverse src alpha (i.e. 1 - sa) */
     48         kDA_Coeff,      /** dst alpha */
     49         kIDA_Coeff,     /** inverse dst alpha (i.e. 1 - da) */
     50 
     51         kCoeffCount
     52     };
     53 
     54     /** If the xfermode can be expressed as an equation using the coefficients
     55         in Coeff, then asCoeff() returns true, and sets (if not null) src and
     56         dst accordingly.
     57 
     58             result = src_coeff * src_color + dst_coeff * dst_color;
     59 
     60         As examples, here are some of the porterduff coefficients
     61 
     62         MODE        SRC_COEFF       DST_COEFF
     63         clear       zero            zero
     64         src         one             zero
     65         dst         zero            one
     66         srcover     one             isa
     67         dstover     ida             one
     68      */
     69     virtual bool asCoeff(Coeff* src, Coeff* dst);
     70 
     71     /**
     72      *  The same as calling xfermode->asCoeff(..), except that this also checks
     73      *  if the xfermode is NULL, and if so, treats its as kSrcOver_Mode.
     74      */
     75     static bool AsCoeff(SkXfermode*, Coeff* src, Coeff* dst);
     76 
     77     /** List of predefined xfermodes.
     78         The algebra for the modes uses the following symbols:
     79         Sa, Sc  - source alpha and color
     80         Da, Dc - destination alpha and color (before compositing)
     81         [a, c] - Resulting (alpha, color) values
     82         For these equations, the colors are in premultiplied state.
     83         If no xfermode is specified, kSrcOver is assumed.
     84      */
     85     enum Mode {
     86         kClear_Mode,    //!< [0, 0]
     87         kSrc_Mode,      //!< [Sa, Sc]
     88         kDst_Mode,      //!< [Da, Dc]
     89         kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Rc = Sc + (1 - Sa)*Dc]
     90         kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Rc = Dc + (1 - Da)*Sc]
     91         kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
     92         kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
     93         kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
     94         kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
     95         kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
     96         kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
     97         kXor_Mode,      //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
     98 
     99         // all remaining modes are defined in the SVG Compositing standard
    100         // http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/
    101         kPlus_Mode,
    102         kMultiply_Mode,
    103 
    104         // all above modes can be expressed as pair of src/dst Coeffs
    105         kCoeffModesCnt,
    106 
    107         kScreen_Mode = kCoeffModesCnt,
    108         kOverlay_Mode,
    109         kDarken_Mode,
    110         kLighten_Mode,
    111         kColorDodge_Mode,
    112         kColorBurn_Mode,
    113         kHardLight_Mode,
    114         kSoftLight_Mode,
    115         kDifference_Mode,
    116         kExclusion_Mode,
    117 
    118         kLastMode = kExclusion_Mode
    119     };
    120 
    121     /**
    122      *  If the xfermode is one of the modes in the Mode enum, then asMode()
    123      *  returns true and sets (if not null) mode accordingly. Otherwise it
    124      *  returns false and ignores the mode parameter.
    125      */
    126     virtual bool asMode(Mode* mode);
    127 
    128     /**
    129      *  The same as calling xfermode->asMode(mode), except that this also checks
    130      *  if the xfermode is NULL, and if so, treats its as kSrcOver_Mode.
    131      */
    132     static bool AsMode(SkXfermode*, Mode* mode);
    133 
    134     /**
    135      *  Returns true if the xfermode claims to be the specified Mode. This works
    136      *  correctly even if the xfermode is NULL (which equates to kSrcOver.) Thus
    137      *  you can say this without checking for a null...
    138      *
    139      *  If (SkXfermode::IsMode(paint.getXfermode(),
    140      *                         SkXfermode::kDstOver_Mode)) {
    141      *      ...
    142      *  }
    143      */
    144     static bool IsMode(SkXfermode* xfer, Mode mode);
    145 
    146     /** Return an SkXfermode object for the specified mode.
    147      */
    148     static SkXfermode* Create(Mode mode);
    149 
    150     /** Return a function pointer to a routine that applies the specified
    151         porter-duff transfer mode.
    152      */
    153     static SkXfermodeProc GetProc(Mode mode);
    154 
    155     /** Return a function pointer to a routine that applies the specified
    156         porter-duff transfer mode and srcColor to a 16bit device color. Note,
    157         if the mode+srcColor might return a non-opaque color, then there is not
    158         16bit proc, and this will return NULL.
    159       */
    160     static SkXfermodeProc16 GetProc16(Mode mode, SkColor srcColor);
    161 
    162     /**
    163      *  If the specified mode can be represented by a pair of Coeff, then return
    164      *  true and set (if not NULL) the corresponding coeffs. If the mode is
    165      *  not representable as a pair of Coeffs, return false and ignore the
    166      *  src and dst parameters.
    167      */
    168     static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst);
    169 
    170     // DEPRECATED: call AsMode(...)
    171     static bool IsMode(SkXfermode* xfer, Mode* mode) {
    172         return AsMode(xfer, mode);
    173     }
    174 
    175     SK_DECLARE_FLATTENABLE_REGISTRAR()
    176 protected:
    177     SkXfermode(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {}
    178 
    179     /** The default implementation of xfer32/xfer16/xferA8 in turn call this
    180         method, 1 color at a time (upscaled to a SkPMColor). The default
    181         implmentation of this method just returns dst. If performance is
    182         important, your subclass should override xfer32/xfer16/xferA8 directly.
    183 
    184         This method will not be called directly by the client, so it need not
    185         be implemented if your subclass has overridden xfer32/xfer16/xferA8
    186     */
    187     virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst);
    188 
    189 private:
    190     enum {
    191         kModeCount = kLastMode + 1
    192     };
    193     typedef SkFlattenable INHERITED;
    194 };
    195 
    196 ///////////////////////////////////////////////////////////////////////////////
    197 
    198 /** \class SkProcXfermode
    199 
    200     SkProcXfermode is a xfermode that applies the specified proc to its colors.
    201     This class is not exported to java.
    202 */
    203 class SkProcXfermode : public SkXfermode {
    204 public:
    205     SkProcXfermode(SkXfermodeProc proc) : fProc(proc) {}
    206 
    207     // overrides from SkXfermode
    208     virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
    209                         const SkAlpha aa[]) SK_OVERRIDE;
    210     virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
    211                         const SkAlpha aa[]) SK_OVERRIDE;
    212     virtual void xfer4444(uint16_t dst[], const SkPMColor src[], int count,
    213                           const SkAlpha aa[]) SK_OVERRIDE;
    214     virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
    215                         const SkAlpha aa[]) SK_OVERRIDE;
    216 
    217     // overrides from SkFlattenable
    218     virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
    219     virtual void    flatten(SkFlattenableWriteBuffer&) SK_OVERRIDE;
    220 
    221 protected:
    222     SkProcXfermode(SkFlattenableReadBuffer&);
    223 
    224     // allow subclasses to update this after we unflatten
    225     void setProc(SkXfermodeProc proc) {
    226         fProc = proc;
    227     }
    228 
    229 private:
    230     SkXfermodeProc  fProc;
    231 
    232     static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
    233         return SkNEW_ARGS(SkProcXfermode, (buffer)); }
    234 
    235     typedef SkXfermode INHERITED;
    236 };
    237 
    238 #endif
    239