Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Side by Side Diff: src/core/Sk4pxXfermode.h

Issue 1214443002: Color dodge and burn with SkPMFloat. (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: alphas(). 41/39 + 231/241 Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/core/SkPMFloat.h » ('j') | src/core/SkPMFloat.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #ifndef Sk4pxXfermode_DEFINED 8 #ifndef Sk4pxXfermode_DEFINED
9 #define Sk4pxXfermode_DEFINED 9 #define Sk4pxXfermode_DEFINED
10 10
11 #include "Sk4px.h" 11 #include "Sk4px.h"
12 #include "SkPMFloat.h"
12 13
13 // This file is possibly included into multiple .cpp files. 14 // This file is possibly included into multiple .cpp files.
14 // Each gets its own independent instantiation by wrapping in an anonymous names pace. 15 // Each gets its own independent instantiation by wrapping in an anonymous names pace.
15 namespace { 16 namespace {
16 17
18 // Most xfermodes can be done most efficiently 4 pixels at a time in 8 or 16-bit fixed point.
17 #define XFERMODE(Name) \ 19 #define XFERMODE(Name) \
18 struct Name { \ 20 struct Name { \
19 static Sk4px Xfer(const Sk4px&, const Sk4px&); \ 21 static Sk4px Xfer(const Sk4px&, const Sk4px&); \
20 static const SkXfermode::Mode kMode = SkXfermode::k##Name##_Mode; \ 22 static const SkXfermode::Mode kMode = SkXfermode::k##Name##_Mode; \
21 }; \ 23 }; \
22 inline Sk4px Name::Xfer(const Sk4px& s, const Sk4px& d) 24 inline Sk4px Name::Xfer(const Sk4px& s, const Sk4px& d)
23 25
24 XFERMODE(Clear) { return Sk4px::DupPMColor(0); } 26 XFERMODE(Clear) { return Sk4px::DupPMColor(0); }
25 XFERMODE(Src) { return s; } 27 XFERMODE(Src) { return s; }
26 XFERMODE(Dst) { return d; } 28 XFERMODE(Dst) { return d; }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 } 92 }
91 XFERMODE(Lighten) { 93 XFERMODE(Lighten) {
92 auto sda = s.approxMulDiv255(d.alphas()), 94 auto sda = s.approxMulDiv255(d.alphas()),
93 dsa = d.approxMulDiv255(s.alphas()); 95 dsa = d.approxMulDiv255(s.alphas());
94 auto srcover = s + (d - dsa), 96 auto srcover = s + (d - dsa),
95 dstover = d + (s - sda); 97 dstover = d + (s - sda);
96 auto alphas = srcover, 98 auto alphas = srcover,
97 colors = (sda < dsa).thenElse(dstover, srcover); 99 colors = (sda < dsa).thenElse(dstover, srcover);
98 return alphas.zeroColors() + colors.zeroAlphas(); 100 return alphas.zeroColors() + colors.zeroAlphas();
99 } 101 }
102 #undef XFERMODE
100 103
104 // Some xfermodes use math like divide or sqrt that's best done in floats 1 pixe l at a time.
105 #define XFERMODE(Name) \
106 struct Name { \
107 static SkPMFloat Xfer(const SkPMFloat&, const SkPMFloat&); \
108 static const SkXfermode::Mode kMode = SkXfermode::k##Name##_Mode; \
109 }; \
110 inline SkPMFloat Name::Xfer(const SkPMFloat& s, const SkPMFloat& d)
111
112 XFERMODE(ColorDodge) {
113 auto sa = s.alphas(),
114 da = d.alphas(),
115 isa = Sk4f(1)-sa,
116 ida = Sk4f(1)-da;
117
118 auto srcover = s + d*isa,
119 dstover = d + s*ida;
120
121 auto colors = (d == Sk4f(0)).thenElse(dstover,
122 (s == sa).thenElse(srcover,
123 sa * Sk4f::Min(da, (d*sa)*(sa-s).approxInvert()) + s*ida + d*isa));
124
125 return srcover * SkPMFloat(1,0,0,0) + colors * SkPMFloat(0,1,1,1);
126 }
127 XFERMODE(ColorBurn) {
128 auto sa = s.alphas(),
129 da = d.alphas(),
130 isa = Sk4f(1)-sa,
131 ida = Sk4f(1)-da;
132
133 auto srcover = s + d*isa,
134 dstover = d + s*ida;
135
136 auto colors = (d == da).thenElse(dstover,
137 (s == Sk4f(0)).thenElse(srcover,
138 sa*(da-Sk4f::Min(da, (da-d)*sa*s.approxInvert())) + s*ida + d*isa));
139
140 return srcover * SkPMFloat(1,0,0,0) + colors * SkPMFloat(0,1,1,1);
141 }
101 #undef XFERMODE 142 #undef XFERMODE
102 143
103 // A reasonable fallback mode for doing AA is to simply apply the transfermode f irst, 144 // A reasonable fallback mode for doing AA is to simply apply the transfermode f irst,
104 // then linearly interpolate the AA. 145 // then linearly interpolate the AA.
105 template <typename Mode> 146 template <typename Mode>
106 static Sk4px xfer_aa(const Sk4px& s, const Sk4px& d, const Sk4px& aa) { 147 static Sk4px xfer_aa(const Sk4px& s, const Sk4px& d, const Sk4px& aa) {
107 Sk4px bw = Mode::Xfer(s, d); 148 Sk4px bw = Mode::Xfer(s, d);
108 return (bw * aa + d * aa.inv()).div255(); 149 return (bw * aa + d * aa.inv()).div255();
109 } 150 }
110 151
(...skipping 22 matching lines...) Expand all
133 }); 174 });
134 } else { 175 } else {
135 Sk4px::MapDstSrcAlpha(n, dst, src, aa, 176 Sk4px::MapDstSrcAlpha(n, dst, src, aa,
136 [&](const Sk4px& dst4, const Sk4px& src4, const Sk4px& alpha ) { 177 [&](const Sk4px& dst4, const Sk4px& src4, const Sk4px& alpha ) {
137 return xfer_aa<ProcType>(src4, dst4, alpha); 178 return xfer_aa<ProcType>(src4, dst4, alpha);
138 }); 179 });
139 } 180 }
140 } 181 }
141 182
142 private: 183 private:
143 SkT4pxXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kM ode) {} 184 SkT4pxXfermode(const ProcCoeff& rec) : INHERITED(rec, ProcType::kMode) {}
144 185
145 typedef SkProcCoeffXfermode INHERITED; 186 typedef SkProcCoeffXfermode INHERITED;
146 }; 187 };
188
189 template <typename ProcType>
190 class SkTPMFloatXfermode : public SkProcCoeffXfermode {
191 public:
192 static SkProcCoeffXfermode* Create(const ProcCoeff& rec) {
193 return SkNEW_ARGS(SkTPMFloatXfermode, (rec));
194 }
195
196 void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[ ]) const override {
197 for (int i = 0; i < n; i++) {
198 SkPMFloat s(src[i]),
199 d(dst[i]),
200 b(ProcType::Xfer(s,d));
201 if (aa) {
202 SkPMFloat a = Sk4f(aa[i]) * Sk4f(1.0f/255);
203 b = b*a + d*(Sk4f(1)-a);
204 }
205 dst[i] = b.round();
206 }
207 }
208
209 private:
210 SkTPMFloatXfermode(const ProcCoeff& rec) : INHERITED(rec, ProcType::kMode) { }
211
212 typedef SkProcCoeffXfermode INHERITED;
213 };
147 214
148 static SkProcCoeffXfermode* SkCreate4pxXfermode(const ProcCoeff& rec, SkXfermode ::Mode mode) { 215 static SkProcCoeffXfermode* SkCreate4pxXfermode(const ProcCoeff& rec, SkXfermode ::Mode mode) {
149 #if !defined(SK_CPU_ARM32) || defined(SK_ARM_HAS_NEON) 216 #if !defined(SK_CPU_ARM32) || defined(SK_ARM_HAS_NEON)
150 switch (mode) { 217 switch (mode) {
151 case SkXfermode::kClear_Mode: return SkT4pxXfermode<Clear>::Create( rec); 218 case SkXfermode::kClear_Mode: return SkT4pxXfermode<Clear>::Create( rec);
152 case SkXfermode::kSrc_Mode: return SkT4pxXfermode<Src>::Create(re c); 219 case SkXfermode::kSrc_Mode: return SkT4pxXfermode<Src>::Create(re c);
153 case SkXfermode::kDst_Mode: return SkT4pxXfermode<Dst>::Create(re c); 220 case SkXfermode::kDst_Mode: return SkT4pxXfermode<Dst>::Create(re c);
154 case SkXfermode::kSrcOver_Mode: return SkT4pxXfermode<SrcOver>::Creat e(rec); 221 case SkXfermode::kSrcOver_Mode: return SkT4pxXfermode<SrcOver>::Creat e(rec);
155 case SkXfermode::kDstOver_Mode: return SkT4pxXfermode<DstOver>::Creat e(rec); 222 case SkXfermode::kDstOver_Mode: return SkT4pxXfermode<DstOver>::Creat e(rec);
156 case SkXfermode::kSrcIn_Mode: return SkT4pxXfermode<SrcIn>::Create( rec); 223 case SkXfermode::kSrcIn_Mode: return SkT4pxXfermode<SrcIn>::Create( rec);
157 case SkXfermode::kDstIn_Mode: return SkT4pxXfermode<DstIn>::Create( rec); 224 case SkXfermode::kDstIn_Mode: return SkT4pxXfermode<DstIn>::Create( rec);
158 case SkXfermode::kSrcOut_Mode: return SkT4pxXfermode<SrcOut>::Create (rec); 225 case SkXfermode::kSrcOut_Mode: return SkT4pxXfermode<SrcOut>::Create (rec);
159 case SkXfermode::kDstOut_Mode: return SkT4pxXfermode<DstOut>::Create (rec); 226 case SkXfermode::kDstOut_Mode: return SkT4pxXfermode<DstOut>::Create (rec);
160 case SkXfermode::kSrcATop_Mode: return SkT4pxXfermode<SrcATop>::Creat e(rec); 227 case SkXfermode::kSrcATop_Mode: return SkT4pxXfermode<SrcATop>::Creat e(rec);
161 case SkXfermode::kDstATop_Mode: return SkT4pxXfermode<DstATop>::Creat e(rec); 228 case SkXfermode::kDstATop_Mode: return SkT4pxXfermode<DstATop>::Creat e(rec);
162 case SkXfermode::kXor_Mode: return SkT4pxXfermode<Xor>::Create(re c); 229 case SkXfermode::kXor_Mode: return SkT4pxXfermode<Xor>::Create(re c);
163 case SkXfermode::kPlus_Mode: return SkT4pxXfermode<Plus>::Create(r ec); 230 case SkXfermode::kPlus_Mode: return SkT4pxXfermode<Plus>::Create(r ec);
164 case SkXfermode::kModulate_Mode: return SkT4pxXfermode<Modulate>::Crea te(rec); 231 case SkXfermode::kModulate_Mode: return SkT4pxXfermode<Modulate>::Crea te(rec);
165 case SkXfermode::kScreen_Mode: return SkT4pxXfermode<Screen>::Create (rec); 232 case SkXfermode::kScreen_Mode: return SkT4pxXfermode<Screen>::Create (rec);
166 case SkXfermode::kMultiply_Mode: return SkT4pxXfermode<Multiply>::Crea te(rec); 233 case SkXfermode::kMultiply_Mode: return SkT4pxXfermode<Multiply>::Crea te(rec);
167 case SkXfermode::kDifference_Mode: return SkT4pxXfermode<Difference>::Cr eate(rec); 234 case SkXfermode::kDifference_Mode: return SkT4pxXfermode<Difference>::Cr eate(rec);
168 case SkXfermode::kExclusion_Mode: return SkT4pxXfermode<Exclusion>::Cre ate(rec); 235 case SkXfermode::kExclusion_Mode: return SkT4pxXfermode<Exclusion>::Cre ate(rec);
169 #if !defined(SK_SUPPORT_LEGACY_XFERMODES) // For staging in Chrome (layout test s). 236 #if !defined(SK_SUPPORT_LEGACY_XFERMODES) // For staging in Chrome (layout test s).
170 case SkXfermode::kHardLight_Mode: return SkT4pxXfermode<HardLight>::Cre ate(rec); 237 case SkXfermode::kHardLight_Mode: return SkT4pxXfermode<HardLight>::Cre ate(rec);
171 case SkXfermode::kOverlay_Mode: return SkT4pxXfermode<Overlay>::Creat e(rec); 238 case SkXfermode::kOverlay_Mode: return SkT4pxXfermode<Overlay>::Creat e(rec);
172 case SkXfermode::kDarken_Mode: return SkT4pxXfermode<Darken>::Create (rec); 239 case SkXfermode::kDarken_Mode: return SkT4pxXfermode<Darken>::Create (rec);
173 case SkXfermode::kLighten_Mode: return SkT4pxXfermode<Lighten>::Creat e(rec); 240 case SkXfermode::kLighten_Mode: return SkT4pxXfermode<Lighten>::Creat e(rec);
241
242 case SkXfermode::kColorDodge_Mode: return SkTPMFloatXfermode<ColorDodge> ::Create(rec);
243 case SkXfermode::kColorBurn_Mode: return SkTPMFloatXfermode<ColorBurn>: :Create(rec);
174 #endif 244 #endif
175 default: break; 245 default: break;
176 } 246 }
177 #endif 247 #endif
178 return nullptr; 248 return nullptr;
179 } 249 }
180 250
181 } // namespace 251 } // namespace
182 252
183 #endif//Sk4pxXfermode_DEFINED 253 #endif//Sk4pxXfermode_DEFINED
OLDNEW
« no previous file with comments | « no previous file | src/core/SkPMFloat.h » ('j') | src/core/SkPMFloat.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698