1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SkXfermode_DEFINED 18 #define SkXfermode_DEFINED 19 20 #include "SkFlattenable.h" 21 #include "SkColor.h" 22 23 /** \class SkXfermode 24 25 SkXfermode is the base class for objects that are called to implement custom 26 "transfer-modes" in the drawing pipeline. The static function Create(Modes) 27 can be called to return an instance of any of the predefined subclasses as 28 specified in the Modes enum. When an SkXfermode is assigned to an SkPaint, 29 then objects drawn with that paint have the xfermode applied. 30 */ 31 class SK_API SkXfermode : public SkFlattenable { 32 public: SkXfermode()33 SkXfermode() {} 34 35 virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count, 36 const SkAlpha aa[]); 37 virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count, 38 const SkAlpha aa[]); 39 virtual void xfer4444(uint16_t dst[], const SkPMColor src[], int count, 40 const SkAlpha aa[]); 41 virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count, 42 const SkAlpha aa[]); 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 /** If the xfermode can be expressed as an equation using the coefficients 62 in Coeff, then asCoeff() returns true, and sets (if not null) src and 63 dst accordingly. 64 65 result = src_coeff * src_color + dst_coeff * dst_color; 66 67 As examples, here are some of the porterduff coefficients 68 69 MODE SRC_COEFF DST_COEFF 70 clear zero zero 71 src one zero 72 dst zero one 73 srcover one isa 74 dstover ida one 75 */ 76 virtual bool asCoeff(Coeff* src, Coeff* dst); 77 78 /** 79 * The same as calling xfermode->asCoeff(..), except that this also checks 80 * if the xfermode is NULL, and if so, treats its as kSrcOver_Mode. 81 */ 82 static bool AsCoeff(SkXfermode*, Coeff* src, Coeff* dst); 83 84 /** List of predefined xfermodes. 85 The algebra for the modes uses the following symbols: 86 Sa, Sc - source alpha and color 87 Da, Dc - destination alpha and color (before compositing) 88 [a, c] - Resulting (alpha, color) values 89 For these equations, the colors are in premultiplied state. 90 If no xfermode is specified, kSrcOver is assumed. 91 */ 92 enum Mode { 93 kClear_Mode, //!< [0, 0] 94 kSrc_Mode, //!< [Sa, Sc] 95 kDst_Mode, //!< [Da, Dc] 96 kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Sc + (1 - Sa)*Dc] 97 kDstOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Dc + (1 - Da)*Sc] 98 kSrcIn_Mode, //!< [Sa * Da, Sc * Da] 99 kDstIn_Mode, //!< [Sa * Da, Sa * Dc] 100 kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)] 101 kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)] 102 kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc] 103 kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)] 104 kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] 105 106 // all remaining modes are defined in the SVG Compositing standard 107 // http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/ 108 kPlus_Mode, 109 kMultiply_Mode, 110 111 // all above modes can be expressed as pair of src/dst Coeffs 112 kCoeffModesCnt, 113 114 kScreen_Mode = kCoeffModesCnt, 115 kOverlay_Mode, 116 kDarken_Mode, 117 kLighten_Mode, 118 kColorDodge_Mode, 119 kColorBurn_Mode, 120 kHardLight_Mode, 121 kSoftLight_Mode, 122 kDifference_Mode, 123 kExclusion_Mode, 124 125 kLastMode = kExclusion_Mode 126 }; 127 128 /** 129 * If the xfermode is one of the modes in the Mode enum, then asMode() 130 * returns true and sets (if not null) mode accordingly. Otherwise it 131 * returns false and ignores the mode parameter. 132 */ 133 virtual bool asMode(Mode* mode); 134 135 /** 136 * The same as calling xfermode->asMode(mode), except that this also checks 137 * if the xfermode is NULL, and if so, treats its as kSrcOver_Mode. 138 */ 139 static bool AsMode(SkXfermode*, Mode* mode); 140 141 /** Return an SkXfermode object for the specified mode. 142 */ 143 static SkXfermode* Create(Mode mode); 144 145 /** Return a function pointer to a routine that applies the specified 146 porter-duff transfer mode. 147 */ 148 static SkXfermodeProc GetProc(Mode mode); 149 150 /** Return a function pointer to a routine that applies the specified 151 porter-duff transfer mode and srcColor to a 16bit device color. Note, 152 if the mode+srcColor might return a non-opaque color, then there is not 153 16bit proc, and this will return NULL. 154 */ 155 static SkXfermodeProc16 GetProc16(Mode mode, SkColor srcColor); 156 157 /** 158 * If the specified mode can be represented by a pair of Coeff, then return 159 * true and set (if not NULL) the corresponding coeffs. If the mode is 160 * not representable as a pair of Coeffs, return false and ignore the 161 * src and dst parameters. 162 */ 163 static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst); 164 165 // DEPRECATED: call AsMode(...) IsMode(SkXfermode * xfer,Mode * mode)166 static bool IsMode(SkXfermode* xfer, Mode* mode) { 167 return AsMode(xfer, mode); 168 } 169 170 protected: SkXfermode(SkFlattenableReadBuffer & rb)171 SkXfermode(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {} 172 173 /** The default implementation of xfer32/xfer16/xferA8 in turn call this 174 method, 1 color at a time (upscaled to a SkPMColor). The default 175 implmentation of this method just returns dst. If performance is 176 important, your subclass should override xfer32/xfer16/xferA8 directly. 177 178 This method will not be called directly by the client, so it need not 179 be implemented if your subclass has overridden xfer32/xfer16/xferA8 180 */ 181 virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst); 182 183 private: 184 enum { 185 kModeCount = kLastMode + 1 186 }; 187 typedef SkFlattenable INHERITED; 188 }; 189 190 /////////////////////////////////////////////////////////////////////////////// 191 192 /** \class SkProcXfermode 193 194 SkProcXfermode is a xfermode that applies the specified proc to its colors. 195 This class is not exported to java. 196 */ 197 class SkProcXfermode : public SkXfermode { 198 public: SkProcXfermode(SkXfermodeProc proc)199 SkProcXfermode(SkXfermodeProc proc) : fProc(proc) {} 200 201 // overrides from SkXfermode 202 virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count, 203 const SkAlpha aa[]); 204 virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count, 205 const SkAlpha aa[]); 206 virtual void xfer4444(uint16_t dst[], const SkPMColor src[], int count, 207 const SkAlpha aa[]); 208 virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count, 209 const SkAlpha aa[]); 210 211 // overrides from SkFlattenable getFactory()212 virtual Factory getFactory() { return CreateProc; } 213 virtual void flatten(SkFlattenableWriteBuffer&); 214 215 protected: 216 SkProcXfermode(SkFlattenableReadBuffer&); 217 218 private: 219 SkXfermodeProc fProc; 220 CreateProc(SkFlattenableReadBuffer & buffer)221 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 222 return SkNEW_ARGS(SkProcXfermode, (buffer)); } 223 224 typedef SkXfermode INHERITED; 225 }; 226 227 #endif 228