| Index: src/core/SkLinearBitmapPipeline_core.h
|
| diff --git a/src/core/SkLinearBitmapPipeline_core.h b/src/core/SkLinearBitmapPipeline_core.h
|
| index 9a8ec0e37eb0b7ffd8dd5cf5227e25963a80b724..0541f3cce5ca45804ecd14abd2ab0baf38517d41 100644
|
| --- a/src/core/SkLinearBitmapPipeline_core.h
|
| +++ b/src/core/SkLinearBitmapPipeline_core.h
|
| @@ -8,6 +8,8 @@
|
| #ifndef SkLinearBitmapPipeline_core_DEFINED
|
| #define SkLinearBitmapPipeline_core_DEFINED
|
|
|
| +#include <cmath>
|
| +
|
| // Tweak ABI of functions that pass Sk4f by value to pass them via registers.
|
| #if defined(_MSC_VER) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
|
| #define VECTORCALL __vectorcall
|
| @@ -22,7 +24,7 @@ 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(SkISize s) : fVal((SkScalar)s.fWidth) { }
|
| operator SkScalar () const {return fVal;}
|
| private:
|
| SkScalar fVal;
|
| @@ -32,7 +34,7 @@ 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(SkISize s) : fVal((SkScalar)s.fHeight) { }
|
| operator SkScalar () const {return fVal;}
|
| private:
|
| SkScalar fVal;
|
| @@ -73,7 +75,7 @@ public:
|
| bool completelyWithin(SkScalar xMin, SkScalar xMax) const {
|
| SkScalar sMin, sMax;
|
| std::tie(sMin, sMax) = std::minmax(startX(), endX());
|
| - return xMin <= sMin && sMax <= xMax;
|
| + return xMin <= sMin && sMax < xMax;
|
| }
|
|
|
| void offset(SkScalar offsetX) {
|
| @@ -90,19 +92,37 @@ public:
|
| }
|
|
|
| int dxSteps = SkScalarFloorToInt((breakX - this->startX()) / dx);
|
| +
|
| + // Calculate the values for the span to cleave off.
|
| + SkScalar newLength = dxSteps * dx;
|
| +
|
| if (dxSteps < 0) {
|
| // The span is wholly after breakX.
|
| return Span{{0.0, 0.0}, 0.0f, 0};
|
| - } else if (dxSteps > fCount) {
|
| + } else if (dxSteps >= fCount) {
|
| // The span is wholly before breakX.
|
| Span answer = *this;
|
| this->clear();
|
| return answer;
|
| }
|
|
|
| - // Calculate the values for the span to cleave off.
|
| + // If the last (or first if count = 1) sample lands directly on the boundary. Include it
|
| + // when dx < 0 and exclude it when dx > 0.
|
| + // Reasoning:
|
| + // dx > 0: The sample point on the boundary is part of the next span because the entire
|
| + // pixel is after the boundary.
|
| + // dx < 0: The sample point on the boundary is part of the current span because the
|
| + // entire pixel is before the boundary.
|
| + if (startX() + newLength == breakX && dx > 0) {
|
| + if (dxSteps != 0) {
|
| + dxSteps -= 1;
|
| + newLength -= dx;
|
| + } else {
|
| + return Span{{0.0, 0.0}, 0.0f, 0};
|
| + }
|
| + }
|
| +
|
| SkPoint newStart = fStart;
|
| - SkScalar newLength = dxSteps * dx;
|
| int newCount = dxSteps + 1;
|
| SkASSERT(newCount > 0);
|
|
|
|
|