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 #include "SkPM4f.h" | 9 #include "SkPM4f.h" |
10 | 10 |
11 #include <algorithm> | 11 #include <algorithm> |
12 #include <cmath> | 12 #include <cmath> |
13 #include <limits> | 13 #include <limits> |
14 #include "SkColor.h" | 14 #include "SkColor.h" |
15 #include "SkSize.h" | 15 #include "SkSize.h" |
16 | 16 |
17 struct X { | 17 struct X { |
18 explicit X(SkScalar val) : fVal{val} { } | 18 explicit X(SkScalar val) : fVal{val} { } |
19 explicit X(SkPoint pt) : fVal{pt.fX} { } | 19 explicit X(SkPoint pt) : fVal{pt.fX} { } |
20 explicit X(SkSize s) : fVal{s.fWidth} { } | 20 explicit X(SkSize s) : fVal{s.fWidth} { } |
21 explicit X(SkISize s) : fVal(s.fWidth) { } | 21 explicit X(SkISize s) : fVal(s.fWidth) { } |
22 operator float () const {return fVal;} | 22 operator float () const {return fVal;} |
23 private: | 23 private: |
24 float fVal; | 24 float fVal; |
25 }; | 25 }; |
26 | 26 |
27 struct Y { | 27 struct Y { |
28 explicit Y(SkScalar val) : fVal{val} { } | 28 explicit Y(SkScalar val) : fVal{val} { } |
29 explicit Y(SkPoint pt) : fVal{pt.fY} { } | 29 explicit Y(SkPoint pt) : fVal{pt.fY} { } |
30 explicit Y(SkSize s) : fVal{s.fHeight} { } | 30 explicit Y(SkSize s) : fVal{s.fHeight} { } |
31 explicit Y(SkISize s) : fVal(s.fHeight) { } | 31 explicit Y(SkISize s) : fVal(s.fHeight) { } |
32 operator float () const {return fVal;} | 32 operator float () const {return fVal;} |
33 private: | 33 private: |
34 float fVal; | 34 float fVal; |
35 }; | 35 }; |
36 | 36 |
| 37 template <typename Stage> |
| 38 void span_fallback(SkPoint start, SkScalar length, int count, Stage* stage) { |
| 39 // If count == 1 use PointListFew instead. |
| 40 SkASSERT(count > 1); |
| 41 |
| 42 float dx = length / (count - 1); |
| 43 Sk4f Xs = Sk4f(X(start)) + Sk4f{0.0f, 1.0f, 2.0f, 3.0f} * Sk4f{dx}; |
| 44 Sk4f Ys{Y(start)}; |
| 45 Sk4f fourDx = {4.0f * dx}; |
| 46 |
| 47 while (count >= 4) { |
| 48 stage->pointList4(Xs, Ys); |
| 49 Xs = Xs + fourDx; |
| 50 count -= 4; |
| 51 } |
| 52 if (count > 0) { |
| 53 stage->pointListFew(count, Xs, Ys); |
| 54 } |
| 55 } |
| 56 |
37 template<typename Strategy, typename Next> | 57 template<typename Strategy, typename Next> |
38 class PointProcessor final : public PointProcessorInterface { | 58 class PointProcessor final : public PointProcessorInterface { |
39 public: | 59 public: |
40 template <typename... Args> | 60 template <typename... Args> |
41 PointProcessor(Next* next, Args&&... args) | 61 PointProcessor(Next* next, Args&&... args) |
42 : fNext{next} | 62 : fNext{next} |
43 , fStrategy{std::forward<Args>(args)...}{ } | 63 , fStrategy{std::forward<Args>(args)...}{ } |
44 | 64 |
45 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | 65 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
46 Sk4f newXs = xs; | 66 Sk4f newXs = xs; |
47 Sk4f newYs = ys; | 67 Sk4f newYs = ys; |
48 fStrategy.processPoints(&newXs, &newYs); | 68 fStrategy.processPoints(&newXs, &newYs); |
49 fNext->pointListFew(n, newXs, newYs); | 69 fNext->pointListFew(n, newXs, newYs); |
50 } | 70 } |
51 | 71 |
52 void pointList4(Sk4fArg xs, Sk4fArg ys) override { | 72 void pointList4(Sk4fArg xs, Sk4fArg ys) override { |
53 Sk4f newXs = xs; | 73 Sk4f newXs = xs; |
54 Sk4f newYs = ys; | 74 Sk4f newYs = ys; |
55 fStrategy.processPoints(&newXs, &newYs); | 75 fStrategy.processPoints(&newXs, &newYs); |
56 fNext->pointList4(newXs, newYs); | 76 fNext->pointList4(newXs, newYs); |
57 } | 77 } |
58 | 78 |
| 79 void pointSpan(SkPoint start, SkScalar length, int count) override { |
| 80 span_fallback(start, length, count, this); |
| 81 } |
| 82 |
59 private: | 83 private: |
60 Next* const fNext; | 84 Next* const fNext; |
61 Strategy fStrategy; | 85 Strategy fStrategy; |
62 }; | 86 }; |
63 | 87 |
64 template<typename Strategy, typename Next> | 88 template<typename Strategy, typename Next> |
65 class BilerpProcessor final : public BilerpProcessorInterface { | 89 class BilerpProcessor final : public BilerpProcessorInterface { |
66 public: | 90 public: |
67 template <typename... Args> | 91 template <typename... Args> |
68 BilerpProcessor(Next* next, Args&&... args) | 92 BilerpProcessor(Next* next, Args&&... args) |
(...skipping 14 matching lines...) Expand all Loading... |
83 fNext->pointList4(newXs, newYs); | 107 fNext->pointList4(newXs, newYs); |
84 } | 108 } |
85 | 109 |
86 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { | 110 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { |
87 Sk4f newXs = xs; | 111 Sk4f newXs = xs; |
88 Sk4f newYs = ys; | 112 Sk4f newYs = ys; |
89 fStrategy.processPoints(&newXs, &newYs); | 113 fStrategy.processPoints(&newXs, &newYs); |
90 fNext->bilerpList(newXs, newYs); | 114 fNext->bilerpList(newXs, newYs); |
91 } | 115 } |
92 | 116 |
| 117 void pointSpan(SkPoint start, SkScalar length, int count) override { |
| 118 span_fallback(start, length, count, this); |
| 119 } |
| 120 |
93 private: | 121 private: |
94 Next* const fNext; | 122 Next* const fNext; |
95 Strategy fStrategy; | 123 Strategy fStrategy; |
96 }; | 124 }; |
97 | 125 |
98 class SkippedStage final : public BilerpProcessorInterface { | 126 class SkippedStage final : public BilerpProcessorInterface { |
99 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | 127 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
100 SkFAIL("Skipped stage."); | 128 SkFAIL("Skipped stage."); |
101 } | 129 } |
102 void pointList4(Sk4fArg Xs, Sk4fArg Ys) override { | 130 void pointList4(Sk4fArg Xs, Sk4fArg Ys) override { |
103 SkFAIL("Skipped stage."); | 131 SkFAIL("Skipped stage."); |
104 } | 132 } |
105 virtual void bilerpList(Sk4fArg xs, Sk4fArg ys) override { | 133 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { |
| 134 SkFAIL("Skipped stage."); |
| 135 } |
| 136 void pointSpan(SkPoint start, SkScalar length, int count) override { |
106 SkFAIL("Skipped stage."); | 137 SkFAIL("Skipped stage."); |
107 } | 138 } |
108 }; | 139 }; |
109 | 140 |
110 class TranslateMatrixStrategy { | 141 class TranslateMatrixStrategy { |
111 public: | 142 public: |
112 TranslateMatrixStrategy(SkVector offset) | 143 TranslateMatrixStrategy(SkVector offset) |
113 : fXOffset{X(offset)} | 144 : fXOffset{X(offset)} |
114 , fYOffset{Y(offset)} { } | 145 , fYOffset{Y(offset)} { } |
115 void processPoints(Sk4f* xs, Sk4f* ys) { | 146 void processPoints(Sk4f* xs, Sk4f* ys) { |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 void pointList4(Sk4fArg xs, Sk4fArg ys) override { | 239 void pointList4(Sk4fArg xs, Sk4fArg ys) override { |
209 // px00 px10 px01 px11 | 240 // px00 px10 px01 px11 |
210 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f}, | 241 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f}, |
211 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f}; | 242 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f}; |
212 fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYOffsets); | 243 fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYOffsets); |
213 fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYOffsets); | 244 fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYOffsets); |
214 fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYOffsets); | 245 fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYOffsets); |
215 fNext->bilerpList(Sk4f{xs[3]} + kXOffsets, Sk4f{ys[3]} + kYOffsets); | 246 fNext->bilerpList(Sk4f{xs[3]} + kXOffsets, Sk4f{ys[3]} + kYOffsets); |
216 } | 247 } |
217 | 248 |
| 249 void pointSpan(SkPoint start, SkScalar length, int count) override { |
| 250 span_fallback(start, length, count, this); |
| 251 } |
| 252 |
218 private: | 253 private: |
219 Next* const fNext; | 254 Next* const fNext; |
220 }; | 255 }; |
221 | 256 |
222 static PointProcessorInterface* choose_filter( | 257 static PointProcessorInterface* choose_filter( |
223 BilerpProcessorInterface* next, | 258 BilerpProcessorInterface* next, |
224 SkFilterQuality filterQuailty, | 259 SkFilterQuality filterQuailty, |
225 SkLinearBitmapPipeline::FilterStage* filterProc) { | 260 SkLinearBitmapPipeline::FilterStage* filterProc) { |
226 if (SkFilterQuality::kNone_SkFilterQuality == filterQuailty) { | 261 if (SkFilterQuality::kNone_SkFilterQuality == filterQuailty) { |
227 filterProc->Initialize<SkippedStage>(); | 262 filterProc->Initialize<SkippedStage>(); |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 fNext->place4Pixels(px0, px1, px2, px3); | 483 fNext->place4Pixels(px0, px1, px2, px3); |
449 } | 484 } |
450 | 485 |
451 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { | 486 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { |
452 Sk4f px00, px10, px01, px11; | 487 Sk4f px00, px10, px01, px11; |
453 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11); | 488 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11); |
454 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); | 489 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); |
455 fNext->placePixel(pixel); | 490 fNext->placePixel(pixel); |
456 } | 491 } |
457 | 492 |
| 493 void pointSpan(SkPoint start, SkScalar length, int count) override { |
| 494 span_fallback(start, length, count, this); |
| 495 } |
| 496 |
458 private: | 497 private: |
459 PixelPlacerInterface* const fNext; | 498 PixelPlacerInterface* const fNext; |
460 SourceStrategy fStrategy; | 499 SourceStrategy fStrategy; |
461 }; | 500 }; |
462 | 501 |
463 static BilerpProcessorInterface* choose_pixel_sampler( | 502 static BilerpProcessorInterface* choose_pixel_sampler( |
464 PixelPlacerInterface* next, | 503 PixelPlacerInterface* next, |
465 const SkPixmap& srcPixmap, | 504 const SkPixmap& srcPixmap, |
466 SkLinearBitmapPipeline::SampleStage* sampleStage) { | 505 SkLinearBitmapPipeline::SampleStage* sampleStage) { |
467 const SkImageInfo& imageInfo = srcPixmap.info(); | 506 const SkImageInfo& imageInfo = srcPixmap.info(); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
550 // identity matrix, the matrix stage is skipped, and the tilerStage is the f
irst stage. | 589 // identity matrix, the matrix stage is skipped, and the tilerStage is the f
irst stage. |
551 auto placementStage = choose_pixel_placer(srcImageInfo.alphaType(), &fPixelS
tage); | 590 auto placementStage = choose_pixel_placer(srcImageInfo.alphaType(), &fPixelS
tage); |
552 auto samplerStage = choose_pixel_sampler(placementStage, srcPixmap, &fSamp
leStage); | 591 auto samplerStage = choose_pixel_sampler(placementStage, srcPixmap, &fSamp
leStage); |
553 auto tilerStage = choose_tiler(samplerStage, size, xTile, yTile, &fTileX
OrBothStage, | 592 auto tilerStage = choose_tiler(samplerStage, size, xTile, yTile, &fTileX
OrBothStage, |
554 &fTileYStage); | 593 &fTileYStage); |
555 auto filterStage = choose_filter(tilerStage, filterQuality, &fFilterStage
); | 594 auto filterStage = choose_filter(tilerStage, filterQuality, &fFilterStage
); |
556 fFirstStage = choose_matrix(filterStage, inverse, &fMatrixStage); | 595 fFirstStage = choose_matrix(filterStage, inverse, &fMatrixStage); |
557 } | 596 } |
558 | 597 |
559 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { | 598 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { |
| 599 SkASSERT(count > 0); |
560 fPixelStage->setDestination(dst); | 600 fPixelStage->setDestination(dst); |
561 | 601 // Adjust points by 0.5, 0.5 to sample from the center of the pixels. |
562 Sk4f Xs = Sk4f(x) + Sk4f{0.5f, 1.5f, 2.5f, 3.5f}; | 602 if (count == 1) { |
563 Sk4f Ys(y); | 603 fFirstStage->pointListFew(1, Sk4f{x + 0.5f}, Sk4f{y + 0.5f}); |
564 Sk4f fours{4.0f}; | 604 } else { |
565 | 605 // The count and length arguments start out in a precise relation in ord
er to keep the |
566 while (count >= 4) { | 606 // math correct through the different stages. Count is the number of pix
el to produce. |
567 fFirstStage->pointList4(Xs, Ys); | 607 // Since the code samples at pixel centers, length is the distance from
the center of the |
568 Xs = Xs + fours; | 608 // first pixel to the center of the last pixel. This implies that length
is count-1. |
569 count -= 4; | 609 fFirstStage->pointSpan(SkPoint{x + 0.5f, y + 0.5f}, count - 1, count); |
570 } | |
571 if (count > 0) { | |
572 fFirstStage->pointListFew(count, Xs, Ys); | |
573 } | 610 } |
574 } | 611 } |
OLD | NEW |