OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 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 #include "SkLinearBitmapPipeline.h" | 8 #include "SkLinearBitmapPipeline.h" |
9 | 9 |
10 struct X { | 10 struct X { |
11 explicit X(SkScalar val) : fVal{val} { } | 11 explicit X(SkScalar val) : fVal{val} { } |
12 explicit X(SkPoint pt) : fVal{pt.fX} { } | 12 explicit X(SkPoint pt) : fVal{pt.fX} { } |
13 explicit X(SkSize s) : fVal{s.fWidth} { } | 13 explicit X(SkSize s) : fVal{s.fWidth} { } |
14 explicit X(SkISize s) : fVal(s.fWidth) { } | 14 explicit X(SkISize s) : fVal(s.fWidth) { } |
15 operator float () const {return fVal;} | 15 operator float () const {return fVal;} |
16 private: | 16 private: |
17 float fVal; | 17 float fVal; |
18 }; | 18 }; |
19 | 19 |
20 struct Y { | 20 struct Y { |
21 explicit Y(SkScalar val) : fVal{val} { } | 21 explicit Y(SkScalar val) : fVal{val} { } |
22 explicit Y(SkPoint pt) : fVal{pt.fY} { } | 22 explicit Y(SkPoint pt) : fVal{pt.fY} { } |
23 explicit Y(SkSize s) : fVal{s.fHeight} { } | 23 explicit Y(SkSize s) : fVal{s.fHeight} { } |
24 explicit Y(SkISize s) : fVal(s.fHeight) { } | 24 explicit Y(SkISize s) : fVal(s.fHeight) { } |
25 | |
26 operator float () const {return fVal;} | 25 operator float () const {return fVal;} |
27 private: | 26 private: |
28 float fVal; | 27 float fVal; |
29 }; | 28 }; |
30 | 29 |
31 template<typename Strategy, typename Next> | 30 template<typename Strategy, typename Next> |
32 class PointProcessor : public PointProcessorInterface { | 31 class PointProcessor final : public PointProcessorInterface { |
33 public: | 32 public: |
34 template <typename... Args> | 33 template <typename... Args> |
35 PointProcessor(Next* next, Args&&... args) | 34 PointProcessor(Next* next, Args&&... args) |
36 : fNext{next} | 35 : fNext{next} |
37 , fStrategy{std::forward<Args>(args)...}{ } | 36 , fStrategy{std::forward<Args>(args)...}{ } |
38 | 37 |
39 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | 38 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
40 Sk4f newXs = xs; | 39 Sk4f newXs = xs; |
41 Sk4f newYs = ys; | 40 Sk4f newYs = ys; |
42 fStrategy.processPoints(&newXs, &newYs); | 41 fStrategy.processPoints(&newXs, &newYs); |
43 fNext->pointListFew(n, newXs, newYs); | 42 fNext->pointListFew(n, newXs, newYs); |
44 } | 43 } |
45 | 44 |
46 void pointList4(Sk4fArg xs, Sk4fArg ys) override { | 45 void pointList4(Sk4fArg xs, Sk4fArg ys) override { |
47 Sk4f newXs = xs; | 46 Sk4f newXs = xs; |
48 Sk4f newYs = ys; | 47 Sk4f newYs = ys; |
49 fStrategy.processPoints(&newXs, &newYs); | 48 fStrategy.processPoints(&newXs, &newYs); |
50 fNext->pointList4(newXs, newYs); | 49 fNext->pointList4(newXs, newYs); |
51 } | 50 } |
52 | 51 |
53 private: | 52 private: |
54 Next* const fNext; | 53 Next* const fNext; |
55 Strategy fStrategy; | 54 Strategy fStrategy; |
56 }; | 55 }; |
57 | 56 |
58 class SkippedStage final : public PointProcessorInterface { | 57 template<typename Strategy, typename Next> |
58 class BilerpProcessor final : public BilerpProcessorInterface { | |
59 public: | |
60 template <typename... Args> | |
61 BilerpProcessor(Next* next, Args&&... args) | |
62 : fNext{next} | |
63 , fStrategy{std::forward<Args>(args)...}{ } | |
64 | |
59 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | 65 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
60 SkFAIL("Abort tiler."); | 66 Sk4f newXs = xs; |
67 Sk4f newYs = ys; | |
68 fStrategy.processPoints(&newXs, &newYs); | |
69 fNext->pointListFew(n, newXs, newYs); | |
70 } | |
71 | |
72 void pointList4(Sk4fArg xs, Sk4fArg ys) override { | |
73 Sk4f newXs = xs; | |
74 Sk4f newYs = ys; | |
75 fStrategy.processPoints(&newXs, &newYs); | |
76 fNext->pointList4(newXs, newYs); | |
77 } | |
78 | |
79 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { | |
80 Sk4f newXs = xs; | |
81 Sk4f newYs = ys; | |
82 fStrategy.processPoints(&newXs, &newYs); | |
83 fNext->bilerpList(newXs, newYs); | |
84 } | |
85 | |
86 private: | |
87 Next* const fNext; | |
88 Strategy fStrategy; | |
89 }; | |
90 | |
91 class SkippedStage final : public BilerpProcessorInterface { | |
92 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | |
93 SkFAIL("Skipped stage."); | |
61 } | 94 } |
62 void pointList4(Sk4fArg Xs, Sk4fArg Ys) override { | 95 void pointList4(Sk4fArg Xs, Sk4fArg Ys) override { |
63 SkFAIL("Abort point processor."); | 96 SkFAIL("Skipped stage."); |
97 } | |
98 virtual void bilerpList(Sk4fArg xs, Sk4fArg ys) override { | |
99 SkFAIL("Skipped stage."); | |
64 } | 100 } |
65 }; | 101 }; |
66 | 102 |
67 class TranslateMatrixStrategy { | 103 class TranslateMatrixStrategy { |
68 public: | 104 public: |
69 TranslateMatrixStrategy(SkVector offset) | 105 TranslateMatrixStrategy(SkVector offset) |
70 : fXOffset{X(offset)} | 106 : fXOffset{X(offset)} |
71 , fYOffset{Y(offset)} { } | 107 , fYOffset{Y(offset)} { } |
72 void processPoints(Sk4f* xs, Sk4f* ys) { | 108 void processPoints(Sk4f* xs, Sk4f* ys) { |
73 *xs = *xs + fXOffset; | 109 *xs = *xs + fXOffset; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
140 matrixProc->Initialize<TranslateMatrix<>>( | 176 matrixProc->Initialize<TranslateMatrix<>>( |
141 next, | 177 next, |
142 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}); | 178 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}); |
143 } else { | 179 } else { |
144 matrixProc->Initialize<SkippedStage>(); | 180 matrixProc->Initialize<SkippedStage>(); |
145 return next; | 181 return next; |
146 } | 182 } |
147 return matrixProc->get(); | 183 return matrixProc->get(); |
148 } | 184 } |
149 | 185 |
186 template <typename Next = BilerpProcessorInterface> | |
187 class ExpandBilerp final : public PointProcessorInterface { | |
188 public: | |
189 ExpandBilerp(Next* next) : fNext{next} { } | |
190 | |
191 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | |
192 SkASSERT(0 < n && n < 4); | |
193 // px00 px10 px01 px11 | |
194 const Sk4f kXOffsets{0.0f, 1.0f, 0.0f, 1.0f}, | |
195 kYOffsets{0.0f, 0.0f, 1.0f, 1.0f}; | |
196 if (n >= 1) fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYO ffsets); | |
197 if (n >= 2) fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYO ffsets); | |
198 if (n >= 3) fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYO ffsets); | |
199 } | |
200 | |
201 void pointList4(Sk4fArg xs, Sk4fArg ys) override { | |
202 // px00 px10 px01 px11 | |
203 const Sk4f kXOffsets{0.0f, 1.0f, 0.0f, 1.0f}, | |
204 kYOffsets{0.0f, 0.0f, 1.0f, 1.0f}; | |
205 fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYOffsets); | |
206 fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYOffsets); | |
207 fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYOffsets); | |
208 fNext->bilerpList(Sk4f{xs[3]} + kXOffsets, Sk4f{ys[3]} + kYOffsets); | |
209 } | |
210 | |
211 private: | |
212 Next* const fNext; | |
213 }; | |
214 | |
215 static PointProcessorInterface* choose_filter( | |
216 BilerpProcessorInterface* next, | |
217 SkFilterQuality filterQuailty, | |
218 SkLinearBitmapPipeline::FilterStage* filterProc) { | |
219 if (SkFilterQuality::kNone_SkFilterQuality == filterQuailty) { | |
220 filterProc->Initialize<SkippedStage>(); | |
221 return next; | |
222 } else { | |
223 filterProc->Initialize<ExpandBilerp<>>(next); | |
224 return filterProc->get(); | |
225 } | |
226 } | |
227 | |
150 class ClampStrategy { | 228 class ClampStrategy { |
151 public: | 229 public: |
152 ClampStrategy(X max) | 230 ClampStrategy(X max) |
153 : fXMin{0.0f} | 231 : fXMin{0.0f} |
154 , fXMax{max - 1.0f} { } | 232 , fXMax{max - 1.0f} { } |
155 ClampStrategy(Y max) | 233 ClampStrategy(Y max) |
156 : fYMin{0.0f} | 234 : fYMin{0.0f} |
157 , fYMax{max - 1.0f} { } | 235 , fYMax{max - 1.0f} { } |
158 ClampStrategy(SkSize max) | 236 ClampStrategy(SkSize max) |
159 : fXMin{0.0f} | 237 : fXMin{0.0f} |
160 , fYMin{0.0f} | 238 , fYMin{0.0f} |
161 , fXMax{X(max) - 1.0f} | 239 , fXMax{X(max) - 1.0f} |
162 , fYMax{Y(max) - 1.0f} { } | 240 , fYMax{Y(max) - 1.0f} { } |
163 | 241 |
164 void processPoints(Sk4f* xs, Sk4f* ys) { | 242 void processPoints(Sk4f* xs, Sk4f* ys) { |
165 *xs = Sk4f::Min(Sk4f::Max(*xs, fXMin), fXMax); | 243 *xs = Sk4f::Min(Sk4f::Max(*xs, fXMin), fXMax); |
166 *ys = Sk4f::Min(Sk4f::Max(*ys, fYMin), fYMax); | 244 *ys = Sk4f::Min(Sk4f::Max(*ys, fYMin), fYMax); |
167 } | 245 } |
168 | 246 |
169 private: | 247 private: |
170 const Sk4f fXMin{SK_FloatNegativeInfinity}; | 248 const Sk4f fXMin{SK_FloatNegativeInfinity}; |
171 const Sk4f fYMin{SK_FloatNegativeInfinity}; | 249 const Sk4f fYMin{SK_FloatNegativeInfinity}; |
172 const Sk4f fXMax{SK_FloatInfinity}; | 250 const Sk4f fXMax{SK_FloatInfinity}; |
173 const Sk4f fYMax{SK_FloatInfinity}; | 251 const Sk4f fYMax{SK_FloatInfinity}; |
174 }; | 252 }; |
175 template <typename Next = PointProcessorInterface> | 253 template <typename Next = BilerpProcessorInterface> |
176 using Clamp = PointProcessor<ClampStrategy, Next>; | 254 using Clamp = BilerpProcessor<ClampStrategy, Next>; |
177 | 255 |
178 class RepeatStrategy { | 256 class RepeatStrategy { |
179 public: | 257 public: |
180 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { } | 258 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { } |
181 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { } | 259 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { } |
182 RepeatStrategy(SkSize max) | 260 RepeatStrategy(SkSize max) |
183 : fXMax{X(max)} | 261 : fXMax{X(max)} |
184 , fXInvMax{1.0f / X(max)} | 262 , fXInvMax{1.0f / X(max)} |
185 , fYMax{Y(max)} | 263 , fYMax{Y(max)} |
186 , fYInvMax{1.0f / Y(max)} { } | 264 , fYInvMax{1.0f / Y(max)} { } |
187 | 265 |
188 void processPoints(Sk4f* xs, Sk4f* ys) { | 266 void processPoints(Sk4f* xs, Sk4f* ys) { |
189 Sk4f divX = (*xs * fXInvMax).floor(); | 267 Sk4f divX = (*xs * fXInvMax).floor(); |
190 Sk4f divY = (*ys * fYInvMax).floor(); | 268 Sk4f divY = (*ys * fYInvMax).floor(); |
191 Sk4f baseX = (divX * fXMax); | 269 Sk4f baseX = (divX * fXMax); |
192 Sk4f baseY = (divY * fYMax); | 270 Sk4f baseY = (divY * fYMax); |
193 *xs = *xs - baseX; | 271 *xs = *xs - baseX; |
194 *ys = *ys - baseY; | 272 *ys = *ys - baseY; |
195 } | 273 } |
196 | 274 |
197 private: | 275 private: |
198 const Sk4f fXMax{0.0f}; | 276 const Sk4f fXMax{0.0f}; |
199 const Sk4f fXInvMax{0.0f}; | 277 const Sk4f fXInvMax{0.0f}; |
200 const Sk4f fYMax{0.0f}; | 278 const Sk4f fYMax{0.0f}; |
201 const Sk4f fYInvMax{0.0f}; | 279 const Sk4f fYInvMax{0.0f}; |
202 }; | 280 }; |
203 | 281 |
204 template <typename Next = PointProcessorInterface> | 282 template <typename Next = BilerpProcessorInterface> |
205 using Repeat = PointProcessor<RepeatStrategy, Next>; | 283 using Repeat = BilerpProcessor<RepeatStrategy, Next>; |
206 | 284 |
207 static PointProcessorInterface* choose_tiler( | 285 static BilerpProcessorInterface* choose_tiler( |
208 PointProcessorInterface* next, | 286 BilerpProcessorInterface* next, |
209 SkSize dimensions, | 287 SkSize dimensions, |
210 SkShader::TileMode xMode, | 288 SkShader::TileMode xMode, |
211 SkShader::TileMode yMode, | 289 SkShader::TileMode yMode, |
212 SkLinearBitmapPipeline::TileStage* tileProcXOrBoth, | 290 SkLinearBitmapPipeline::TileStage* tileProcXOrBoth, |
213 SkLinearBitmapPipeline::TileStage* tileProcY) { | 291 SkLinearBitmapPipeline::TileStage* tileProcY) { |
214 if (xMode == yMode) { | 292 if (xMode == yMode) { |
215 switch (xMode) { | 293 switch (xMode) { |
216 case SkShader::kClamp_TileMode: | 294 case SkShader::kClamp_TileMode: |
217 tileProcXOrBoth->Initialize<Clamp<>>(next, dimensions); | 295 tileProcXOrBoth->Initialize<Clamp<>>(next, dimensions); |
218 break; | 296 break; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
300 pixel = pixel * Sk4f{1.0f/255.0f}; | 378 pixel = pixel * Sk4f{1.0f/255.0f}; |
301 if (colorProfile == kSRGB_SkColorProfileType) { | 379 if (colorProfile == kSRGB_SkColorProfileType) { |
302 pixel = sRGBFast::sRGBToLinear(pixel); | 380 pixel = sRGBFast::sRGBToLinear(pixel); |
303 } | 381 } |
304 return pixel; | 382 return pixel; |
305 } | 383 } |
306 const uint32_t* const fSrc; | 384 const uint32_t* const fSrc; |
307 const Sk4i fWidth; | 385 const Sk4i fWidth; |
308 }; | 386 }; |
309 | 387 |
388 // Explaination of the math: | |
389 // 1 - x x | |
390 // +--------+--------+ | |
391 // | | | | |
392 // 1 - y | px00 | px10 | | |
393 // | | | | |
394 // +--------+--------+ | |
395 // | | | | |
396 // y | px01 | px11 | | |
397 // | | | | |
398 // +--------+--------+ | |
399 // | |
400 // | |
401 // Given a pixelxy each is multiplied by a different factor derived from the fra ctional part of x | |
402 // and y: | |
403 // * px00 -> (1 - x)(1 - y) = 1 - x - y + xy | |
404 // * px10 -> x(1 - y) = x - xy | |
405 // * px01 -> (1 - x)y = y - xy | |
406 // * px11 -> xy | |
407 // So x * y is calculated first and then used to calculate all the other factors . | |
mtklein
2016/02/17 23:46:55
This is beautiful. Nominated for favorite code sn
herb_g
2016/02/18 03:49:06
Acknowledged.
| |
408 static Sk4f bilerp4(Sk4fArg xs, Sk4fArg ys, Sk4fArg px00, Sk4fArg px10, | |
409 Sk4fArg px01, Sk4fArg px11) { | |
410 // Calculate fractional xs and ys. | |
411 Sk4f fxs = xs - xs.floor(); | |
412 Sk4f fys = ys - ys.floor(); | |
413 Sk4f fxys{fxs * fys}; | |
414 Sk4f sum = px11 * fxys; | |
415 sum = sum + px01 * (fys - fxys); | |
416 sum = sum + px10 * (fxs - fxys); | |
417 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys); | |
418 return sum; | |
419 } | |
420 | |
310 template <typename SourceStrategy> | 421 template <typename SourceStrategy> |
311 class Sampler final : public PointProcessorInterface { | 422 class Sampler final : public BilerpProcessorInterface { |
312 public: | 423 public: |
313 template <typename... Args> | 424 template <typename... Args> |
314 Sampler(PixelPlacerInterface* next, Args&&... args) | 425 Sampler(PixelPlacerInterface* next, Args&&... args) |
315 : fNext{next} | 426 : fNext{next} |
316 , fStrategy{std::forward<Args>(args)...} { } | 427 , fStrategy{std::forward<Args>(args)...} { } |
317 | 428 |
318 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | 429 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
319 SkASSERT(0 < n && n < 4); | 430 SkASSERT(0 < n && n < 4); |
320 Sk4f px0, px1, px2; | 431 Sk4f px0, px1, px2; |
321 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2); | 432 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2); |
322 if (n >= 1) fNext->placePixel(px0); | 433 if (n >= 1) fNext->placePixel(px0); |
323 if (n >= 2) fNext->placePixel(px1); | 434 if (n >= 2) fNext->placePixel(px1); |
324 if (n >= 3) fNext->placePixel(px2); | 435 if (n >= 3) fNext->placePixel(px2); |
325 } | 436 } |
326 | 437 |
327 void pointList4(Sk4fArg xs, Sk4fArg ys) override { | 438 void pointList4(Sk4fArg xs, Sk4fArg ys) override { |
328 Sk4f px0, px1, px2, px3; | 439 Sk4f px0, px1, px2, px3; |
329 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3); | 440 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3); |
330 fNext->place4Pixels(px0, px1, px2, px3); | 441 fNext->place4Pixels(px0, px1, px2, px3); |
331 } | 442 } |
332 | 443 |
444 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { | |
445 Sk4f px00, px10, px01, px11; | |
446 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11); | |
447 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); | |
448 fNext->placePixel(pixel); | |
449 } | |
450 | |
333 private: | 451 private: |
334 PixelPlacerInterface* const fNext; | 452 PixelPlacerInterface* const fNext; |
335 SourceStrategy fStrategy; | 453 SourceStrategy fStrategy; |
336 }; | 454 }; |
337 | 455 |
338 static PointProcessorInterface* choose_pixel_sampler( | 456 static BilerpProcessorInterface* choose_pixel_sampler( |
339 PixelPlacerInterface* next, | 457 PixelPlacerInterface* next, |
340 const SkImageInfo& imageInfo, | 458 const SkImageInfo& imageInfo, |
341 const void* imageData, | 459 const void* imageData, |
342 SkLinearBitmapPipeline::SampleStage* sampleStage) { | 460 SkLinearBitmapPipeline::SampleStage* sampleStage) { |
343 switch (imageInfo.colorType()) { | 461 switch (imageInfo.colorType()) { |
344 case kRGBA_8888_SkColorType: | 462 case kRGBA_8888_SkColorType: |
345 case kBGRA_8888_SkColorType: | 463 case kBGRA_8888_SkColorType: |
346 if (kN32_SkColorType == imageInfo.colorType()) { | 464 if (kN32_SkColorType == imageInfo.colorType()) { |
347 if (imageInfo.profileType() == kSRGB_SkColorProfileType) { | 465 if (imageInfo.profileType() == kSRGB_SkColorProfileType) { |
348 sampleStage->Initialize<Sampler<Passthrough8888<kSRGB_SkColo rProfileType>>>( | 466 sampleStage->Initialize<Sampler<Passthrough8888<kSRGB_SkColo rProfileType>>>( |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
408 placerStage->Initialize<PlaceFPPixel<kUnpremul_SkAlphaType>>(); | 526 placerStage->Initialize<PlaceFPPixel<kUnpremul_SkAlphaType>>(); |
409 } else { | 527 } else { |
410 // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType | 528 // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType |
411 placerStage->Initialize<PlaceFPPixel<kPremul_SkAlphaType>>(); | 529 placerStage->Initialize<PlaceFPPixel<kPremul_SkAlphaType>>(); |
412 } | 530 } |
413 return placerStage->get(); | 531 return placerStage->get(); |
414 } | 532 } |
415 | 533 |
416 SkLinearBitmapPipeline::SkLinearBitmapPipeline( | 534 SkLinearBitmapPipeline::SkLinearBitmapPipeline( |
417 const SkMatrix& inverse, | 535 const SkMatrix& inverse, |
536 SkFilterQuality filterQuality, | |
418 SkShader::TileMode xTile, SkShader::TileMode yTile, | 537 SkShader::TileMode xTile, SkShader::TileMode yTile, |
419 const SkImageInfo& srcImageInfo, | 538 const SkImageInfo& srcImageInfo, |
420 const void* srcImageData) { | 539 const void* srcImageData) { |
421 SkSize size; | 540 SkSize size; |
422 size = srcImageInfo.dimensions(); | 541 size = srcImageInfo.dimensions(); |
423 | 542 |
424 // As the stages are built, the chooser function may skip a stage. For examp le, with the | 543 // As the stages are built, the chooser function may skip a stage. For examp le, with the |
425 // identity matrix, the matrix stage is skipped, and the tilerStage is the f irst stage. | 544 // identity matrix, the matrix stage is skipped, and the tilerStage is the f irst stage. |
426 auto placementStage = choose_pixel_placer(srcImageInfo.alphaType(), &fPixelS tage); | 545 auto placementStage = choose_pixel_placer(srcImageInfo.alphaType(), &fPixelS tage); |
427 auto samplerStage = choose_pixel_sampler(placementStage, srcImageInfo, | 546 auto samplerStage = choose_pixel_sampler(placementStage, srcImageInfo, |
428 srcImageData, &fSampleStage); | 547 srcImageData, &fSampleStage); |
429 auto tilerStage = choose_tiler(samplerStage, size, xTile, yTile, &fTileX OrBothStage, | 548 auto tilerStage = choose_tiler(samplerStage, size, xTile, yTile, &fTileX OrBothStage, |
430 &fTileYStage); | 549 &fTileYStage); |
431 fFirstStage = choose_matrix(tilerStage, inverse, &fMatrixStage); | 550 auto filterStage = choose_filter(tilerStage, filterQuality, &fFilterStage ); |
551 fFirstStage = choose_matrix(filterStage, inverse, &fMatrixStage); | |
432 } | 552 } |
433 | 553 |
434 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { | 554 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { |
435 fPixelStage->setDestination(dst); | 555 fPixelStage->setDestination(dst); |
436 | 556 |
437 Sk4f Xs = Sk4f(x) + Sk4f{0.5f, 1.5f, 2.5f, 3.5f}; | 557 Sk4f Xs = Sk4f(x) + Sk4f{0.5f, 1.5f, 2.5f, 3.5f}; |
438 Sk4f Ys(y); | 558 Sk4f Ys(y); |
439 Sk4f fours{4.0f}; | 559 Sk4f fours{4.0f}; |
440 | 560 |
441 while (count >= 4) { | 561 while (count >= 4) { |
442 fFirstStage->pointList4(Xs, Ys); | 562 fFirstStage->pointList4(Xs, Ys); |
443 Xs = Xs + fours; | 563 Xs = Xs + fours; |
444 count -= 4; | 564 count -= 4; |
445 } | 565 } |
446 if (count > 0) { | 566 if (count > 0) { |
447 fFirstStage->pointListFew(count, Xs, Ys); | 567 fFirstStage->pointListFew(count, Xs, Ys); |
448 } | 568 } |
449 } | 569 } |
OLD | NEW |