1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/include/core/SkXfermode.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,295 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2006 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#ifndef SkXfermode_DEFINED 1.14 +#define SkXfermode_DEFINED 1.15 + 1.16 +#include "SkFlattenable.h" 1.17 +#include "SkColor.h" 1.18 + 1.19 +class GrEffectRef; 1.20 +class GrTexture; 1.21 +class SkString; 1.22 + 1.23 +/** \class SkXfermode 1.24 + * 1.25 + * SkXfermode is the base class for objects that are called to implement custom 1.26 + * "transfer-modes" in the drawing pipeline. The static function Create(Modes) 1.27 + * can be called to return an instance of any of the predefined subclasses as 1.28 + * specified in the Modes enum. When an SkXfermode is assigned to an SkPaint, 1.29 + * then objects drawn with that paint have the xfermode applied. 1.30 + * 1.31 + * All subclasses are required to be reentrant-safe : it must be legal to share 1.32 + * the same instance between several threads. 1.33 + */ 1.34 +class SK_API SkXfermode : public SkFlattenable { 1.35 +public: 1.36 + SK_DECLARE_INST_COUNT(SkXfermode) 1.37 + 1.38 + virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count, 1.39 + const SkAlpha aa[]) const; 1.40 + virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count, 1.41 + const SkAlpha aa[]) const; 1.42 + virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count, 1.43 + const SkAlpha aa[]) const; 1.44 + 1.45 + /** Enum of possible coefficients to describe some xfermodes 1.46 + */ 1.47 + enum Coeff { 1.48 + kZero_Coeff, /** 0 */ 1.49 + kOne_Coeff, /** 1 */ 1.50 + kSC_Coeff, /** src color */ 1.51 + kISC_Coeff, /** inverse src color (i.e. 1 - sc) */ 1.52 + kDC_Coeff, /** dst color */ 1.53 + kIDC_Coeff, /** inverse dst color (i.e. 1 - dc) */ 1.54 + kSA_Coeff, /** src alpha */ 1.55 + kISA_Coeff, /** inverse src alpha (i.e. 1 - sa) */ 1.56 + kDA_Coeff, /** dst alpha */ 1.57 + kIDA_Coeff, /** inverse dst alpha (i.e. 1 - da) */ 1.58 + 1.59 + kCoeffCount 1.60 + }; 1.61 + 1.62 + /** If the xfermode can be expressed as an equation using the coefficients 1.63 + in Coeff, then asCoeff() returns true, and sets (if not null) src and 1.64 + dst accordingly. 1.65 + 1.66 + result = src_coeff * src_color + dst_coeff * dst_color; 1.67 + 1.68 + As examples, here are some of the porterduff coefficients 1.69 + 1.70 + MODE SRC_COEFF DST_COEFF 1.71 + clear zero zero 1.72 + src one zero 1.73 + dst zero one 1.74 + srcover one isa 1.75 + dstover ida one 1.76 + */ 1.77 + virtual bool asCoeff(Coeff* src, Coeff* dst) const; 1.78 + 1.79 + /** 1.80 + * The same as calling xfermode->asCoeff(..), except that this also checks 1.81 + * if the xfermode is NULL, and if so, treats it as kSrcOver_Mode. 1.82 + */ 1.83 + static bool AsCoeff(const SkXfermode*, Coeff* src, Coeff* dst); 1.84 + 1.85 + /** List of predefined xfermodes. 1.86 + The algebra for the modes uses the following symbols: 1.87 + Sa, Sc - source alpha and color 1.88 + Da, Dc - destination alpha and color (before compositing) 1.89 + [a, c] - Resulting (alpha, color) values 1.90 + For these equations, the colors are in premultiplied state. 1.91 + If no xfermode is specified, kSrcOver is assumed. 1.92 + The modes are ordered by those that can be expressed as a pair of Coeffs, followed by those 1.93 + that aren't Coeffs but have separable r,g,b computations, and finally 1.94 + those that are not separable. 1.95 + */ 1.96 + enum Mode { 1.97 + kClear_Mode, //!< [0, 0] 1.98 + kSrc_Mode, //!< [Sa, Sc] 1.99 + kDst_Mode, //!< [Da, Dc] 1.100 + kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Sc + (1 - Sa)*Dc] 1.101 + kDstOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Dc + (1 - Da)*Sc] 1.102 + kSrcIn_Mode, //!< [Sa * Da, Sc * Da] 1.103 + kDstIn_Mode, //!< [Sa * Da, Sa * Dc] 1.104 + kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)] 1.105 + kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)] 1.106 + kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc] 1.107 + kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)] 1.108 + kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] 1.109 + kPlus_Mode, //!< [Sa + Da, Sc + Dc] 1.110 + kModulate_Mode, // multiplies all components (= alpha and color) 1.111 + 1.112 + // Following blend modes are defined in the CSS Compositing standard: 1.113 + // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending 1.114 + kScreen_Mode, 1.115 + kLastCoeffMode = kScreen_Mode, 1.116 + 1.117 + kOverlay_Mode, 1.118 + kDarken_Mode, 1.119 + kLighten_Mode, 1.120 + kColorDodge_Mode, 1.121 + kColorBurn_Mode, 1.122 + kHardLight_Mode, 1.123 + kSoftLight_Mode, 1.124 + kDifference_Mode, 1.125 + kExclusion_Mode, 1.126 + kMultiply_Mode, 1.127 + kLastSeparableMode = kMultiply_Mode, 1.128 + 1.129 + kHue_Mode, 1.130 + kSaturation_Mode, 1.131 + kColor_Mode, 1.132 + kLuminosity_Mode, 1.133 + kLastMode = kLuminosity_Mode 1.134 + }; 1.135 + 1.136 + /** 1.137 + * Gets the name of the Mode as a string. 1.138 + */ 1.139 + static const char* ModeName(Mode); 1.140 + 1.141 + /** 1.142 + * If the xfermode is one of the modes in the Mode enum, then asMode() 1.143 + * returns true and sets (if not null) mode accordingly. Otherwise it 1.144 + * returns false and ignores the mode parameter. 1.145 + */ 1.146 + virtual bool asMode(Mode* mode) const; 1.147 + 1.148 + /** 1.149 + * The same as calling xfermode->asMode(mode), except that this also checks 1.150 + * if the xfermode is NULL, and if so, treats it as kSrcOver_Mode. 1.151 + */ 1.152 + static bool AsMode(const SkXfermode*, Mode* mode); 1.153 + 1.154 + /** 1.155 + * Returns true if the xfermode claims to be the specified Mode. This works 1.156 + * correctly even if the xfermode is NULL (which equates to kSrcOver.) Thus 1.157 + * you can say this without checking for a null... 1.158 + * 1.159 + * If (SkXfermode::IsMode(paint.getXfermode(), 1.160 + * SkXfermode::kDstOver_Mode)) { 1.161 + * ... 1.162 + * } 1.163 + */ 1.164 + static bool IsMode(const SkXfermode* xfer, Mode mode); 1.165 + 1.166 + /** Return an SkXfermode object for the specified mode. 1.167 + */ 1.168 + static SkXfermode* Create(Mode mode); 1.169 + 1.170 + /** Return a function pointer to a routine that applies the specified 1.171 + porter-duff transfer mode. 1.172 + */ 1.173 + static SkXfermodeProc GetProc(Mode mode); 1.174 + 1.175 + /** Return a function pointer to a routine that applies the specified 1.176 + porter-duff transfer mode and srcColor to a 16bit device color. Note, 1.177 + if the mode+srcColor might return a non-opaque color, then there is not 1.178 + 16bit proc, and this will return NULL. 1.179 + */ 1.180 + static SkXfermodeProc16 GetProc16(Mode mode, SkColor srcColor); 1.181 + 1.182 + /** 1.183 + * If the specified mode can be represented by a pair of Coeff, then return 1.184 + * true and set (if not NULL) the corresponding coeffs. If the mode is 1.185 + * not representable as a pair of Coeffs, return false and ignore the 1.186 + * src and dst parameters. 1.187 + */ 1.188 + static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst); 1.189 + 1.190 + SK_ATTR_DEPRECATED("use AsMode(...)") 1.191 + static bool IsMode(const SkXfermode* xfer, Mode* mode) { 1.192 + return AsMode(xfer, mode); 1.193 + } 1.194 + 1.195 + /** A subclass may implement this factory function to work with the GPU backend. It is legal 1.196 + to call this with all params NULL to simply test the return value. If effect is non-NULL 1.197 + then the xfermode may optionally allocate an effect to return and the caller as *effect. 1.198 + The caller will install it and own a ref to it. Since the xfermode may or may not assign 1.199 + *effect, the caller should set *effect to NULL beforehand. background specifies the 1.200 + texture to use as the background for compositing, and should be accessed in the effect's 1.201 + fragment shader. If NULL, the effect should request access to destination color 1.202 + (setWillReadDstColor()), and use that in the fragment shader (builder->dstColor()). 1.203 + */ 1.204 + virtual bool asNewEffect(GrEffectRef** effect, GrTexture* background = NULL) const; 1.205 + 1.206 + /** Returns true if the xfermode can be expressed as coeffs (src, dst), or as an effect 1.207 + (effect). This helper calls the asCoeff() and asNewEffect() virtuals. If the xfermode is 1.208 + NULL, it is treated as kSrcOver_Mode. It is legal to call this with all params NULL to 1.209 + simply test the return value. effect, src, and dst must all be NULL or all non-NULL. 1.210 + */ 1.211 + static bool AsNewEffectOrCoeff(SkXfermode*, 1.212 + GrEffectRef** effect, 1.213 + Coeff* src, 1.214 + Coeff* dst, 1.215 + GrTexture* background = NULL); 1.216 + 1.217 + SK_TO_STRING_PUREVIRT() 1.218 + SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() 1.219 + SK_DEFINE_FLATTENABLE_TYPE(SkXfermode) 1.220 + 1.221 +protected: 1.222 + SkXfermode(SkReadBuffer& rb) : SkFlattenable(rb) {} 1.223 + 1.224 + /** The default implementation of xfer32/xfer16/xferA8 in turn call this 1.225 + method, 1 color at a time (upscaled to a SkPMColor). The default 1.226 + implmentation of this method just returns dst. If performance is 1.227 + important, your subclass should override xfer32/xfer16/xferA8 directly. 1.228 + 1.229 + This method will not be called directly by the client, so it need not 1.230 + be implemented if your subclass has overridden xfer32/xfer16/xferA8 1.231 + */ 1.232 + virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const; 1.233 + 1.234 +#ifdef SK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS 1.235 +public: 1.236 +#endif 1.237 + SkXfermode() {} 1.238 + 1.239 +private: 1.240 + enum { 1.241 + kModeCount = kLastMode + 1 1.242 + }; 1.243 + 1.244 + friend class SkGraphics; 1.245 + static void Term(); 1.246 + 1.247 + typedef SkFlattenable INHERITED; 1.248 +}; 1.249 + 1.250 +/////////////////////////////////////////////////////////////////////////////// 1.251 + 1.252 +/** \class SkProcXfermode 1.253 + 1.254 + SkProcXfermode is a xfermode that applies the specified proc to its colors. 1.255 + This class is not exported to java. 1.256 +*/ 1.257 +class SkProcXfermode : public SkXfermode { 1.258 +public: 1.259 + static SkProcXfermode* Create(SkXfermodeProc proc) { 1.260 + return SkNEW_ARGS(SkProcXfermode, (proc)); 1.261 + } 1.262 + 1.263 + // overrides from SkXfermode 1.264 + virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count, 1.265 + const SkAlpha aa[]) const SK_OVERRIDE; 1.266 + virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count, 1.267 + const SkAlpha aa[]) const SK_OVERRIDE; 1.268 + virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count, 1.269 + const SkAlpha aa[]) const SK_OVERRIDE; 1.270 + 1.271 + SK_TO_STRING_OVERRIDE() 1.272 + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcXfermode) 1.273 + 1.274 +protected: 1.275 + SkProcXfermode(SkReadBuffer&); 1.276 + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; 1.277 + 1.278 + // allow subclasses to update this after we unflatten 1.279 + void setProc(SkXfermodeProc proc) { 1.280 + fProc = proc; 1.281 + } 1.282 + 1.283 + SkXfermodeProc getProc() const { 1.284 + return fProc; 1.285 + } 1.286 + 1.287 +#ifdef SK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS 1.288 +public: 1.289 +#endif 1.290 + SkProcXfermode(SkXfermodeProc proc) : fProc(proc) {} 1.291 + 1.292 +private: 1.293 + SkXfermodeProc fProc; 1.294 + 1.295 + typedef SkXfermode INHERITED; 1.296 +}; 1.297 + 1.298 +#endif