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*/ 24class SK_API SkXfermode : public SkFlattenable { 25public: 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() 176protected: 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 189private: 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*/ 203class SkProcXfermode : public SkXfermode { 204public: 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 221protected: 222 SkProcXfermode(SkFlattenableReadBuffer&); 223 224 // allow subclasses to update this after we unflatten 225 void setProc(SkXfermodeProc proc) { 226 fProc = proc; 227 } 228 229private: 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