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 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 while (count >= 4) { | 47 while (count >= 4) { |
48 stage->pointList4(Xs, Ys); | 48 stage->pointList4(Xs, Ys); |
49 Xs = Xs + fourDx; | 49 Xs = Xs + fourDx; |
50 count -= 4; | 50 count -= 4; |
51 } | 51 } |
52 if (count > 0) { | 52 if (count > 0) { |
53 stage->pointListFew(count, Xs, Ys); | 53 stage->pointListFew(count, Xs, Ys); |
54 } | 54 } |
55 } | 55 } |
56 | 56 |
| 57 // PointProcessor uses a strategy to help complete the work of the different sta
ges. The strategy |
| 58 // must implement the following methods: |
| 59 // * processPoints(xs, ys) - must mutate the xs and ys for the stage. |
| 60 // * maybeProcessSpan(start, length, count) - This represents a horizontal serie
s of pixels |
| 61 // to work over. |
| 62 // start - is the starting pixel. This is in destination space before the matr
ix stage, and in |
| 63 // source space after the matrix stage. |
| 64 // length - is this distance between the first pixel center and the last pixel
center. Like start, |
| 65 // this is in destination space before the matrix stage, and in source
space after. |
| 66 // count - the number of pixels in source space to produce. |
| 67 // next - a pointer to the next stage. |
| 68 // maybeProcessSpan - returns false if it can not process the span and needs t
o fallback to |
| 69 // point lists for processing. |
57 template<typename Strategy, typename Next> | 70 template<typename Strategy, typename Next> |
58 class PointProcessor final : public PointProcessorInterface { | 71 class PointProcessor final : public PointProcessorInterface { |
59 public: | 72 public: |
60 template <typename... Args> | 73 template <typename... Args> |
61 PointProcessor(Next* next, Args&&... args) | 74 PointProcessor(Next* next, Args&&... args) |
62 : fNext{next} | 75 : fNext{next} |
63 , fStrategy{std::forward<Args>(args)...}{ } | 76 , fStrategy{std::forward<Args>(args)...}{ } |
64 | 77 |
65 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | 78 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
66 Sk4f newXs = xs; | 79 Sk4f newXs = xs; |
67 Sk4f newYs = ys; | 80 Sk4f newYs = ys; |
68 fStrategy.processPoints(&newXs, &newYs); | 81 fStrategy.processPoints(&newXs, &newYs); |
69 fNext->pointListFew(n, newXs, newYs); | 82 fNext->pointListFew(n, newXs, newYs); |
70 } | 83 } |
71 | 84 |
72 void pointList4(Sk4fArg xs, Sk4fArg ys) override { | 85 void pointList4(Sk4fArg xs, Sk4fArg ys) override { |
73 Sk4f newXs = xs; | 86 Sk4f newXs = xs; |
74 Sk4f newYs = ys; | 87 Sk4f newYs = ys; |
75 fStrategy.processPoints(&newXs, &newYs); | 88 fStrategy.processPoints(&newXs, &newYs); |
76 fNext->pointList4(newXs, newYs); | 89 fNext->pointList4(newXs, newYs); |
77 } | 90 } |
78 | 91 |
79 void pointSpan(SkPoint start, SkScalar length, int count) override { | 92 void pointSpan(SkPoint start, SkScalar length, int count) override { |
80 span_fallback(start, length, count, this); | 93 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) { |
| 94 span_fallback(start, length, count, this); |
| 95 } |
81 } | 96 } |
82 | 97 |
83 private: | 98 private: |
84 Next* const fNext; | 99 Next* const fNext; |
85 Strategy fStrategy; | 100 Strategy fStrategy; |
86 }; | 101 }; |
87 | 102 |
| 103 // See PointProcessor for responsibilities of Strategy. |
88 template<typename Strategy, typename Next> | 104 template<typename Strategy, typename Next> |
89 class BilerpProcessor final : public BilerpProcessorInterface { | 105 class BilerpProcessor final : public BilerpProcessorInterface { |
90 public: | 106 public: |
91 template <typename... Args> | 107 template <typename... Args> |
92 BilerpProcessor(Next* next, Args&&... args) | 108 BilerpProcessor(Next* next, Args&&... args) |
93 : fNext{next} | 109 : fNext{next} |
94 , fStrategy{std::forward<Args>(args)...}{ } | 110 , fStrategy{std::forward<Args>(args)...}{ } |
95 | 111 |
96 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | 112 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
97 Sk4f newXs = xs; | 113 Sk4f newXs = xs; |
(...skipping 10 matching lines...) Expand all Loading... |
108 } | 124 } |
109 | 125 |
110 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { | 126 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { |
111 Sk4f newXs = xs; | 127 Sk4f newXs = xs; |
112 Sk4f newYs = ys; | 128 Sk4f newYs = ys; |
113 fStrategy.processPoints(&newXs, &newYs); | 129 fStrategy.processPoints(&newXs, &newYs); |
114 fNext->bilerpList(newXs, newYs); | 130 fNext->bilerpList(newXs, newYs); |
115 } | 131 } |
116 | 132 |
117 void pointSpan(SkPoint start, SkScalar length, int count) override { | 133 void pointSpan(SkPoint start, SkScalar length, int count) override { |
118 span_fallback(start, length, count, this); | 134 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) { |
| 135 span_fallback(start, length, count, this); |
| 136 } |
119 } | 137 } |
120 | 138 |
121 private: | 139 private: |
122 Next* const fNext; | 140 Next* const fNext; |
123 Strategy fStrategy; | 141 Strategy fStrategy; |
124 }; | 142 }; |
125 | 143 |
126 class SkippedStage final : public BilerpProcessorInterface { | 144 class SkippedStage final : public BilerpProcessorInterface { |
127 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | 145 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
128 SkFAIL("Skipped stage."); | 146 SkFAIL("Skipped stage."); |
129 } | 147 } |
130 void pointList4(Sk4fArg Xs, Sk4fArg Ys) override { | 148 void pointList4(Sk4fArg Xs, Sk4fArg Ys) override { |
131 SkFAIL("Skipped stage."); | 149 SkFAIL("Skipped stage."); |
132 } | 150 } |
133 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { | 151 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { |
134 SkFAIL("Skipped stage."); | 152 SkFAIL("Skipped stage."); |
135 } | 153 } |
136 void pointSpan(SkPoint start, SkScalar length, int count) override { | 154 void pointSpan(SkPoint start, SkScalar length, int count) override { |
137 SkFAIL("Skipped stage."); | 155 SkFAIL("Skipped stage."); |
138 } | 156 } |
139 }; | 157 }; |
140 | 158 |
141 class TranslateMatrixStrategy { | 159 class TranslateMatrixStrategy { |
142 public: | 160 public: |
143 TranslateMatrixStrategy(SkVector offset) | 161 TranslateMatrixStrategy(SkVector offset) |
144 : fXOffset{X(offset)} | 162 : fXOffset{X(offset)} |
145 , fYOffset{Y(offset)} { } | 163 , fYOffset{Y(offset)} { } |
| 164 |
146 void processPoints(Sk4f* xs, Sk4f* ys) { | 165 void processPoints(Sk4f* xs, Sk4f* ys) { |
147 *xs = *xs + fXOffset; | 166 *xs = *xs + fXOffset; |
148 *ys = *ys + fYOffset; | 167 *ys = *ys + fYOffset; |
149 } | 168 } |
150 | 169 |
| 170 template <typename Next> |
| 171 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next)
{ |
| 172 next->pointSpan(start + SkPoint{fXOffset[0], fYOffset[0]}, length, count
); |
| 173 return true; |
| 174 } |
| 175 |
151 private: | 176 private: |
152 const Sk4f fXOffset, fYOffset; | 177 const Sk4f fXOffset, fYOffset; |
153 }; | 178 }; |
154 template <typename Next = PointProcessorInterface> | 179 template <typename Next = PointProcessorInterface> |
155 using TranslateMatrix = PointProcessor<TranslateMatrixStrategy, Next>; | 180 using TranslateMatrix = PointProcessor<TranslateMatrixStrategy, Next>; |
156 | 181 |
157 class ScaleMatrixStrategy { | 182 class ScaleMatrixStrategy { |
158 public: | 183 public: |
159 ScaleMatrixStrategy(SkVector offset, SkVector scale) | 184 ScaleMatrixStrategy(SkVector offset, SkVector scale) |
160 : fXOffset{X(offset)}, fYOffset{Y(offset)} | 185 : fXOffset{X(offset)}, fYOffset{Y(offset)} |
161 , fXScale{X(scale)}, fYScale{Y(scale)} { } | 186 , fXScale{X(scale)}, fYScale{Y(scale)} { } |
162 void processPoints(Sk4f* xs, Sk4f* ys) { | 187 void processPoints(Sk4f* xs, Sk4f* ys) { |
163 *xs = *xs * fXScale + fXOffset; | 188 *xs = *xs * fXScale + fXOffset; |
164 *ys = *ys * fYScale + fYOffset; | 189 *ys = *ys * fYScale + fYOffset; |
165 } | 190 } |
166 | 191 |
| 192 template <typename Next> |
| 193 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next)
{ |
| 194 SkPoint newStart = |
| 195 SkPoint{X(start) * fXScale[0] + fXOffset[0], Y(start) * fYScale[0] +
fYOffset[0]}; |
| 196 SkScalar newLength = length * fXScale[0]; |
| 197 next->pointSpan(newStart, newLength, count); |
| 198 return true; |
| 199 } |
| 200 |
167 private: | 201 private: |
168 const Sk4f fXOffset, fYOffset; | 202 const Sk4f fXOffset, fYOffset; |
169 const Sk4f fXScale, fYScale; | 203 const Sk4f fXScale, fYScale; |
170 }; | 204 }; |
171 template <typename Next = PointProcessorInterface> | 205 template <typename Next = PointProcessorInterface> |
172 using ScaleMatrix = PointProcessor<ScaleMatrixStrategy, Next>; | 206 using ScaleMatrix = PointProcessor<ScaleMatrixStrategy, Next>; |
173 | 207 |
174 class AffineMatrixStrategy { | 208 class AffineMatrixStrategy { |
175 public: | 209 public: |
176 AffineMatrixStrategy(SkVector offset, SkVector scale, SkVector skew) | 210 AffineMatrixStrategy(SkVector offset, SkVector scale, SkVector skew) |
177 : fXOffset{X(offset)}, fYOffset{Y(offset)} | 211 : fXOffset{X(offset)}, fYOffset{Y(offset)} |
178 , fXScale{X(scale)}, fYScale{Y(scale)} | 212 , fXScale{X(scale)}, fYScale{Y(scale)} |
179 , fXSkew{X(skew)}, fYSkew{Y(skew)} { } | 213 , fXSkew{X(skew)}, fYSkew{Y(skew)} { } |
180 void processPoints(Sk4f* xs, Sk4f* ys) { | 214 void processPoints(Sk4f* xs, Sk4f* ys) { |
181 Sk4f newXs = fXScale * *xs + fXSkew * *ys + fXOffset; | 215 Sk4f newXs = fXScale * *xs + fXSkew * *ys + fXOffset; |
182 Sk4f newYs = fYSkew * *xs + fYScale * *ys + fYOffset; | 216 Sk4f newYs = fYSkew * *xs + fYScale * *ys + fYOffset; |
183 | 217 |
184 *xs = newXs; | 218 *xs = newXs; |
185 *ys = newYs; | 219 *ys = newYs; |
186 } | 220 } |
187 | 221 |
| 222 template <typename Next> |
| 223 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next)
{ |
| 224 return false; |
| 225 } |
| 226 |
188 private: | 227 private: |
189 const Sk4f fXOffset, fYOffset; | 228 const Sk4f fXOffset, fYOffset; |
190 const Sk4f fXScale, fYScale; | 229 const Sk4f fXScale, fYScale; |
191 const Sk4f fXSkew, fYSkew; | 230 const Sk4f fXSkew, fYSkew; |
192 }; | 231 }; |
193 template <typename Next = PointProcessorInterface> | 232 template <typename Next = PointProcessorInterface> |
194 using AffineMatrix = PointProcessor<AffineMatrixStrategy, Next>; | 233 using AffineMatrix = PointProcessor<AffineMatrixStrategy, Next>; |
195 | 234 |
196 static PointProcessorInterface* choose_matrix( | 235 static PointProcessorInterface* choose_matrix( |
197 PointProcessorInterface* next, | 236 PointProcessorInterface* next, |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 : fXMin{0.0f} | 318 : fXMin{0.0f} |
280 , fYMin{0.0f} | 319 , fYMin{0.0f} |
281 , fXMax{X(max) - 1.0f} | 320 , fXMax{X(max) - 1.0f} |
282 , fYMax{Y(max) - 1.0f} { } | 321 , fYMax{Y(max) - 1.0f} { } |
283 | 322 |
284 void processPoints(Sk4f* xs, Sk4f* ys) { | 323 void processPoints(Sk4f* xs, Sk4f* ys) { |
285 *xs = Sk4f::Min(Sk4f::Max(*xs, fXMin), fXMax); | 324 *xs = Sk4f::Min(Sk4f::Max(*xs, fXMin), fXMax); |
286 *ys = Sk4f::Min(Sk4f::Max(*ys, fYMin), fYMax); | 325 *ys = Sk4f::Min(Sk4f::Max(*ys, fYMin), fYMax); |
287 } | 326 } |
288 | 327 |
| 328 template <typename Next> |
| 329 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next)
{ |
| 330 return false; |
| 331 } |
| 332 |
289 private: | 333 private: |
290 const Sk4f fXMin{SK_FloatNegativeInfinity}; | 334 const Sk4f fXMin{SK_FloatNegativeInfinity}; |
291 const Sk4f fYMin{SK_FloatNegativeInfinity}; | 335 const Sk4f fYMin{SK_FloatNegativeInfinity}; |
292 const Sk4f fXMax{SK_FloatInfinity}; | 336 const Sk4f fXMax{SK_FloatInfinity}; |
293 const Sk4f fYMax{SK_FloatInfinity}; | 337 const Sk4f fYMax{SK_FloatInfinity}; |
294 }; | 338 }; |
295 template <typename Next = BilerpProcessorInterface> | 339 template <typename Next = BilerpProcessorInterface> |
296 using Clamp = BilerpProcessor<ClampStrategy, Next>; | 340 using Clamp = BilerpProcessor<ClampStrategy, Next>; |
297 | 341 |
298 class RepeatStrategy { | 342 class RepeatStrategy { |
299 public: | 343 public: |
300 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { } | 344 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { } |
301 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { } | 345 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { } |
302 RepeatStrategy(SkSize max) | 346 RepeatStrategy(SkSize max) |
303 : fXMax{X(max)} | 347 : fXMax{X(max)} |
304 , fXInvMax{1.0f / X(max)} | 348 , fXInvMax{1.0f / X(max)} |
305 , fYMax{Y(max)} | 349 , fYMax{Y(max)} |
306 , fYInvMax{1.0f / Y(max)} { } | 350 , fYInvMax{1.0f / Y(max)} { } |
307 | 351 |
308 void processPoints(Sk4f* xs, Sk4f* ys) { | 352 void processPoints(Sk4f* xs, Sk4f* ys) { |
309 Sk4f divX = (*xs * fXInvMax).floor(); | 353 Sk4f divX = (*xs * fXInvMax).floor(); |
310 Sk4f divY = (*ys * fYInvMax).floor(); | 354 Sk4f divY = (*ys * fYInvMax).floor(); |
311 Sk4f baseX = (divX * fXMax); | 355 Sk4f baseX = (divX * fXMax); |
312 Sk4f baseY = (divY * fYMax); | 356 Sk4f baseY = (divY * fYMax); |
313 *xs = *xs - baseX; | 357 *xs = *xs - baseX; |
314 *ys = *ys - baseY; | 358 *ys = *ys - baseY; |
315 } | 359 } |
316 | 360 |
| 361 template <typename Next> |
| 362 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next)
{ |
| 363 return false; |
| 364 } |
| 365 |
317 private: | 366 private: |
318 const Sk4f fXMax{0.0f}; | 367 const Sk4f fXMax{0.0f}; |
319 const Sk4f fXInvMax{0.0f}; | 368 const Sk4f fXInvMax{0.0f}; |
320 const Sk4f fYMax{0.0f}; | 369 const Sk4f fYMax{0.0f}; |
321 const Sk4f fYInvMax{0.0f}; | 370 const Sk4f fYInvMax{0.0f}; |
322 }; | 371 }; |
323 | 372 |
324 template <typename Next = BilerpProcessorInterface> | 373 template <typename Next = BilerpProcessorInterface> |
325 using Repeat = BilerpProcessor<RepeatStrategy, Next>; | 374 using Repeat = BilerpProcessor<RepeatStrategy, Next>; |
326 | 375 |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 if (count == 1) { | 651 if (count == 1) { |
603 fFirstStage->pointListFew(1, Sk4f{x + 0.5f}, Sk4f{y + 0.5f}); | 652 fFirstStage->pointListFew(1, Sk4f{x + 0.5f}, Sk4f{y + 0.5f}); |
604 } else { | 653 } else { |
605 // The count and length arguments start out in a precise relation in ord
er to keep the | 654 // The count and length arguments start out in a precise relation in ord
er to keep the |
606 // math correct through the different stages. Count is the number of pix
el to produce. | 655 // math correct through the different stages. Count is the number of pix
el to produce. |
607 // Since the code samples at pixel centers, length is the distance from
the center of the | 656 // Since the code samples at pixel centers, length is the distance from
the center of the |
608 // first pixel to the center of the last pixel. This implies that length
is count-1. | 657 // first pixel to the center of the last pixel. This implies that length
is count-1. |
609 fFirstStage->pointSpan(SkPoint{x + 0.5f, y + 0.5f}, count - 1, count); | 658 fFirstStage->pointSpan(SkPoint{x + 0.5f, y + 0.5f}, count - 1, count); |
610 } | 659 } |
611 } | 660 } |
OLD | NEW |