| 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);
|
| }
|
| }
|
|
|