Index: src/core/SkLinearBitmapPipeline.cpp |
diff --git a/src/core/SkLinearBitmapPipeline.cpp b/src/core/SkLinearBitmapPipeline.cpp |
index 958a945aef035c7721660685eaa5afa2df4a1632..5a4f86daa7a2e83e6f10d53e8f38d41cb1e84a0e 100644 |
--- a/src/core/SkLinearBitmapPipeline.cpp |
+++ b/src/core/SkLinearBitmapPipeline.cpp |
@@ -54,6 +54,19 @@ void span_fallback(SkPoint start, SkScalar length, int count, Stage* stage) { |
} |
} |
+// PointProcessor uses a strategy to help complete the work of the different stages. The strategy |
+// must implement the following methods: |
+// * processPoints(xs, ys) - must mutate the xs and ys for the stage. |
+// * maybeProcessSpan(start, length, count) - This represents a horizontal series of pixels |
+// to work over. |
+// start - is the starting pixel. This is in destination space before the matrix stage, and in |
+// source space after the matrix stage. |
+// length - is this distance between the first pixel center and the last pixel center. Like start, |
+// this is in destination space before the matrix stage, and in source space after. |
+// count - the number of pixels in source space to produce. |
+// next - a pointer to the next stage. |
+// maybeProcessSpan - returns false if it can not process the span and needs to fallback to |
+// point lists for processing. |
template<typename Strategy, typename Next> |
class PointProcessor final : public PointProcessorInterface { |
public: |
@@ -77,7 +90,9 @@ public: |
} |
void pointSpan(SkPoint start, SkScalar length, int count) override { |
- span_fallback(start, length, count, this); |
+ if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) { |
+ span_fallback(start, length, count, this); |
+ } |
} |
private: |
@@ -85,6 +100,7 @@ private: |
Strategy fStrategy; |
}; |
+// See PointProcessor for responsibilities of Strategy. |
template<typename Strategy, typename Next> |
class BilerpProcessor final : public BilerpProcessorInterface { |
public: |
@@ -115,7 +131,9 @@ public: |
} |
void pointSpan(SkPoint start, SkScalar length, int count) override { |
- span_fallback(start, length, count, this); |
+ if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) { |
+ span_fallback(start, length, count, this); |
+ } |
} |
private: |
@@ -143,11 +161,18 @@ public: |
TranslateMatrixStrategy(SkVector offset) |
: fXOffset{X(offset)} |
, fYOffset{Y(offset)} { } |
+ |
void processPoints(Sk4f* xs, Sk4f* ys) { |
*xs = *xs + fXOffset; |
*ys = *ys + fYOffset; |
} |
+ template <typename Next> |
+ bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { |
+ next->pointSpan(start + SkPoint{fXOffset[0], fYOffset[0]}, length, count); |
+ return true; |
+ } |
+ |
private: |
const Sk4f fXOffset, fYOffset; |
}; |
@@ -164,6 +189,15 @@ public: |
*ys = *ys * fYScale + fYOffset; |
} |
+ template <typename Next> |
+ bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { |
+ SkPoint newStart = |
+ SkPoint{X(start) * fXScale[0] + fXOffset[0], Y(start) * fYScale[0] + fYOffset[0]}; |
+ SkScalar newLength = length * fXScale[0]; |
+ next->pointSpan(newStart, newLength, count); |
+ return true; |
+ } |
+ |
private: |
const Sk4f fXOffset, fYOffset; |
const Sk4f fXScale, fYScale; |
@@ -185,6 +219,11 @@ public: |
*ys = newYs; |
} |
+ template <typename Next> |
+ bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { |
+ return false; |
+ } |
+ |
private: |
const Sk4f fXOffset, fYOffset; |
const Sk4f fXScale, fYScale; |
@@ -286,6 +325,11 @@ public: |
*ys = Sk4f::Min(Sk4f::Max(*ys, fYMin), fYMax); |
} |
+ template <typename Next> |
+ bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { |
+ return false; |
+ } |
+ |
private: |
const Sk4f fXMin{SK_FloatNegativeInfinity}; |
const Sk4f fYMin{SK_FloatNegativeInfinity}; |
@@ -314,6 +358,11 @@ public: |
*ys = *ys - baseY; |
} |
+ template <typename Next> |
+ bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { |
+ return false; |
+ } |
+ |
private: |
const Sk4f fXMax{0.0f}; |
const Sk4f fXInvMax{0.0f}; |