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(...)") IsMode(const SkXfermode * xfer,Mode * mode)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); GetLCD64Proc(uint32_t)249 static LCD64Proc GetLCD64Proc(uint32_t) { return nullptr; } 250 251 protected: SkXfermode()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