Index: src/core/SkLinearBitmapPipeline.cpp |
diff --git a/src/core/SkLinearBitmapPipeline.cpp b/src/core/SkLinearBitmapPipeline.cpp |
index 1565b7e32bce8ac0d8cf1b8e8af3faf79e620b31..958a945aef035c7721660685eaa5afa2df4a1632 100644 |
--- a/src/core/SkLinearBitmapPipeline.cpp |
+++ b/src/core/SkLinearBitmapPipeline.cpp |
@@ -16,9 +16,9 @@ |
struct X { |
explicit X(SkScalar val) : fVal{val} { } |
- explicit X(SkPoint pt) : fVal{pt.fX} { } |
- explicit X(SkSize s) : fVal{s.fWidth} { } |
- explicit X(SkISize s) : fVal(s.fWidth) { } |
+ explicit X(SkPoint pt) : fVal{pt.fX} { } |
+ explicit X(SkSize s) : fVal{s.fWidth} { } |
+ explicit X(SkISize s) : fVal(s.fWidth) { } |
operator float () const {return fVal;} |
private: |
float fVal; |
@@ -26,14 +26,34 @@ private: |
struct Y { |
explicit Y(SkScalar val) : fVal{val} { } |
- explicit Y(SkPoint pt) : fVal{pt.fY} { } |
- explicit Y(SkSize s) : fVal{s.fHeight} { } |
- explicit Y(SkISize s) : fVal(s.fHeight) { } |
+ explicit Y(SkPoint pt) : fVal{pt.fY} { } |
+ explicit Y(SkSize s) : fVal{s.fHeight} { } |
+ explicit Y(SkISize s) : fVal(s.fHeight) { } |
operator float () const {return fVal;} |
private: |
float fVal; |
}; |
+template <typename Stage> |
+void span_fallback(SkPoint start, SkScalar length, int count, Stage* stage) { |
+ // If count == 1 use PointListFew instead. |
+ SkASSERT(count > 1); |
+ |
+ float dx = length / (count - 1); |
+ Sk4f Xs = Sk4f(X(start)) + Sk4f{0.0f, 1.0f, 2.0f, 3.0f} * Sk4f{dx}; |
+ Sk4f Ys{Y(start)}; |
+ Sk4f fourDx = {4.0f * dx}; |
+ |
+ while (count >= 4) { |
+ stage->pointList4(Xs, Ys); |
+ Xs = Xs + fourDx; |
+ count -= 4; |
+ } |
+ if (count > 0) { |
+ stage->pointListFew(count, Xs, Ys); |
+ } |
+} |
+ |
template<typename Strategy, typename Next> |
class PointProcessor final : public PointProcessorInterface { |
public: |
@@ -56,6 +76,10 @@ public: |
fNext->pointList4(newXs, newYs); |
} |
+ void pointSpan(SkPoint start, SkScalar length, int count) override { |
+ span_fallback(start, length, count, this); |
+ } |
+ |
private: |
Next* const fNext; |
Strategy fStrategy; |
@@ -90,6 +114,10 @@ public: |
fNext->bilerpList(newXs, newYs); |
} |
+ void pointSpan(SkPoint start, SkScalar length, int count) override { |
+ span_fallback(start, length, count, this); |
+ } |
+ |
private: |
Next* const fNext; |
Strategy fStrategy; |
@@ -102,7 +130,10 @@ class SkippedStage final : public BilerpProcessorInterface { |
void pointList4(Sk4fArg Xs, Sk4fArg Ys) override { |
SkFAIL("Skipped stage."); |
} |
- virtual void bilerpList(Sk4fArg xs, Sk4fArg ys) override { |
+ void bilerpList(Sk4fArg xs, Sk4fArg ys) override { |
+ SkFAIL("Skipped stage."); |
+ } |
+ void pointSpan(SkPoint start, SkScalar length, int count) override { |
SkFAIL("Skipped stage."); |
} |
}; |
@@ -215,6 +246,10 @@ public: |
fNext->bilerpList(Sk4f{xs[3]} + kXOffsets, Sk4f{ys[3]} + kYOffsets); |
} |
+ void pointSpan(SkPoint start, SkScalar length, int count) override { |
+ span_fallback(start, length, count, this); |
+ } |
+ |
private: |
Next* const fNext; |
}; |
@@ -455,6 +490,10 @@ public: |
fNext->placePixel(pixel); |
} |
+ void pointSpan(SkPoint start, SkScalar length, int count) override { |
+ span_fallback(start, length, count, this); |
+ } |
+ |
private: |
PixelPlacerInterface* const fNext; |
SourceStrategy fStrategy; |
@@ -557,18 +596,16 @@ SkLinearBitmapPipeline::SkLinearBitmapPipeline( |
} |
void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { |
+ SkASSERT(count > 0); |
fPixelStage->setDestination(dst); |
- |
- Sk4f Xs = Sk4f(x) + Sk4f{0.5f, 1.5f, 2.5f, 3.5f}; |
- Sk4f Ys(y); |
- Sk4f fours{4.0f}; |
- |
- while (count >= 4) { |
- fFirstStage->pointList4(Xs, Ys); |
- Xs = Xs + fours; |
- count -= 4; |
- } |
- if (count > 0) { |
- fFirstStage->pointListFew(count, Xs, Ys); |
+ // Adjust points by 0.5, 0.5 to sample from the center of the pixels. |
+ if (count == 1) { |
+ fFirstStage->pointListFew(1, Sk4f{x + 0.5f}, Sk4f{y + 0.5f}); |
+ } else { |
+ // The count and length arguments start out in a precise relation in order to keep the |
+ // math correct through the different stages. Count is the number of pixel to produce. |
+ // Since the code samples at pixel centers, length is the distance from the center of the |
+ // first pixel to the center of the last pixel. This implies that length is count-1. |
+ fFirstStage->pointSpan(SkPoint{x + 0.5f, y + 0.5f}, count - 1, count); |
} |
} |