diff --git a/src/core/SkScan_AAAPath.cpp b/src/core/SkScan_AAAPath.cpp index 4925aa1cec..74acefb614 100644 --- a/src/core/SkScan_AAAPath.cpp +++ b/src/core/SkScan_AAAPath.cpp @@ -26,13 +26,11 @@ #include #if defined(SK_DISABLE_AAA) -void SkScan::AAAFillPath(const SkPath& path, SkBlitter* blitter, const SkIRect& ir, - const SkIRect& clipBounds, bool forceRLE) { +void SkScan::AAAFillPath(const SkPath&, SkBlitter*, const SkIRect&, const SkIRect&, bool) { SkDEBUGFAIL("AAA Disabled"); return; } #else -/////////////////////////////////////////////////////////////////////////////// /* @@ -92,15 +90,14 @@ number of scan lines in our algorithm is only about 3 + H while the */ -/////////////////////////////////////////////////////////////////////////////// -static inline void addAlpha(SkAlpha* alpha, SkAlpha delta) { - SkASSERT(*alpha + (int)delta <= 256); - *alpha = SkAlphaRuns::CatchOverflow(*alpha + (int)delta); +static void add_alpha(SkAlpha* alpha, SkAlpha delta) { + SkASSERT(*alpha + delta <= 256); + *alpha = SkAlphaRuns::CatchOverflow(*alpha + delta); } -static inline void safelyAddAlpha(SkAlpha* alpha, SkAlpha delta) { - *alpha = SkTMin(0xFF, *alpha + (int)delta); +static void safely_add_alpha(SkAlpha* alpha, SkAlpha delta) { + *alpha = SkTMin(0xFF, *alpha + delta); } class AdditiveBlitter : public SkBlitter { @@ -174,7 +171,7 @@ public: int getWidth() override { return fClipRect.width(); } - static bool canHandleRect(const SkIRect& bounds) { + static bool CanHandleRect(const SkIRect& bounds) { int width = bounds.width(); if (width > MaskAdditiveBlitter::kMAX_WIDTH) { return false; @@ -188,7 +185,7 @@ public: } // Return a pointer where pointer[x] corresonds to the alpha of (x, y) - inline uint8_t* getRow(int y) { + uint8_t* getRow(int y) { if (y != fY) { fY = y; fRow = fMask.fImage + (y - fMask.fBounds.fTop) * fMask.fRowBytes - fMask.fBounds.fLeft; @@ -211,9 +208,11 @@ private: int fY; }; -MaskAdditiveBlitter::MaskAdditiveBlitter( - SkBlitter* realBlitter, const SkIRect& ir, const SkIRect& clipBounds, bool isInverse) { - SkASSERT(canHandleRect(ir)); +MaskAdditiveBlitter::MaskAdditiveBlitter(SkBlitter* realBlitter, + const SkIRect& ir, + const SkIRect& clipBounds, + bool isInverse) { + SkASSERT(CanHandleRect(ir)); SkASSERT(!isInverse); fRealBlitter = realBlitter; @@ -240,15 +239,15 @@ void MaskAdditiveBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], int } void MaskAdditiveBlitter::blitAntiH(int x, int y, const SkAlpha alpha) { - SkASSERT(x >= fMask.fBounds.fLeft -1); - addAlpha(&this->getRow(y)[x], alpha); + SkASSERT(x >= fMask.fBounds.fLeft - 1); + add_alpha(&this->getRow(y)[x], alpha); } void MaskAdditiveBlitter::blitAntiH(int x, int y, int width, const SkAlpha alpha) { - SkASSERT(x >= fMask.fBounds.fLeft -1); + SkASSERT(x >= fMask.fBounds.fLeft - 1); uint8_t* row = this->getRow(y); for (int i = 0; i < width; ++i) { - addAlpha(&row[x + i], alpha); + add_alpha(&row[x + i], alpha); } } @@ -256,7 +255,7 @@ void MaskAdditiveBlitter::blitV(int x, int y, int height, SkAlpha alpha) { if (alpha == 0) { return; } - SkASSERT(x >= fMask.fBounds.fLeft -1); + SkASSERT(x >= fMask.fBounds.fLeft - 1); // This must be called as if this is a real blitter. // So we directly set alpha rather than adding it. uint8_t* row = this->getRow(y); @@ -267,7 +266,7 @@ void MaskAdditiveBlitter::blitV(int x, int y, int height, SkAlpha alpha) { } void MaskAdditiveBlitter::blitRect(int x, int y, int width, int height) { - SkASSERT(x >= fMask.fBounds.fLeft -1); + SkASSERT(x >= fMask.fBounds.fLeft - 1); // This must be called as if this is a real blitter. // So we directly set alpha rather than adding it. uint8_t* row = this->getRow(y); @@ -277,8 +276,12 @@ void MaskAdditiveBlitter::blitRect(int x, int y, int width, int height) { } } -void MaskAdditiveBlitter::blitAntiRect(int x, int y, int width, int height, - SkAlpha leftAlpha, SkAlpha rightAlpha) { +void MaskAdditiveBlitter::blitAntiRect(int x, + int y, + int width, + int height, + SkAlpha leftAlpha, + SkAlpha rightAlpha) { blitV(x, y, height, leftAlpha); blitV(x + 1 + width, y, height, rightAlpha); blitRect(x + 1, y, width, height); @@ -286,17 +289,24 @@ void MaskAdditiveBlitter::blitAntiRect(int x, int y, int width, int height, class RunBasedAdditiveBlitter : public AdditiveBlitter { public: - RunBasedAdditiveBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkIRect& clipBounds, - bool isInverse); - ~RunBasedAdditiveBlitter() override; + RunBasedAdditiveBlitter(SkBlitter* realBlitter, + const SkIRect& ir, + const SkIRect& clipBounds, + bool isInverse); - SkBlitter* getRealBlitter(bool forceRealBlitter) override; + ~RunBasedAdditiveBlitter() override { + this->flush(); + } + + SkBlitter* getRealBlitter(bool forceRealBlitter) override { + return fRealBlitter; + } void blitAntiH(int x, int y, const SkAlpha antialias[], int len) override; void blitAntiH(int x, int y, const SkAlpha alpha) override; void blitAntiH(int x, int y, int width, const SkAlpha alpha) override; - int getWidth() override; + int getWidth() override { return fWidth; } void flush_if_y_changed(SkFixed y, SkFixed nextY) override { if (SkFixedFloorToInt(y) != SkFixedFloorToInt(nextY)) { @@ -307,14 +317,10 @@ public: protected: SkBlitter* fRealBlitter; - /// Current y coordinate - int fCurrY; - /// Widest row of region to be blitted - int fWidth; - /// Leftmost x coordinate in any row - int fLeft; - /// Initial y coordinate (top of bounds). - int fTop; + int fCurrY; // Current y coordinate. + int fWidth; // Widest row of region to be blitted + int fLeft; // Leftmost x coordinate in any row + int fTop; // Initial y coordinate (top of bounds) // The next three variables are used to track a circular buffer that // contains the values used in SkAlphaRuns. These variables should only @@ -327,22 +333,17 @@ protected: int fOffsetX; - inline bool check(int x, int width) const { - #ifdef SK_DEBUG - if (x < 0 || x + width > fWidth) { - // SkDebugf("Ignore x = %d, width = %d\n", x, width); - } - #endif - return (x >= 0 && x + width <= fWidth); + bool check(int x, int width) const { + return x >= 0 && x + width <= fWidth; } // extra one to store the zero at the end - inline int getRunsSz() const { return (fWidth + 1 + (fWidth + 2)/2) * sizeof(int16_t); } + int getRunsSz() const { return (fWidth + 1 + (fWidth + 2)/2) * sizeof(int16_t); } // This function updates the fRuns variable to point to the next buffer space // with adequate storage for a SkAlphaRuns. It mostly just advances fCurrentRun // and resets fRuns to point to an empty scanline. - inline void advanceRuns() { + void advanceRuns() { const size_t kRunsSz = this->getRunsSz(); fCurrentRun = (fCurrentRun + 1) % fRunsToBuffer; fRuns.fRuns = reinterpret_cast( @@ -352,11 +353,12 @@ protected: } // Blitting 0xFF and 0 is much faster so we snap alphas close to them - inline SkAlpha snapAlpha(SkAlpha alpha) { - return alpha > 247 ? 0xFF : alpha < 8 ? 0 : alpha; + SkAlpha snapAlpha(SkAlpha alpha) { + return alpha > 247 ? 0xFF : + alpha < 8 ? 0x00 : alpha; } - inline void flush() { + void flush() { if (fCurrY >= fTop) { SkASSERT(fCurrentRun < fRunsToBuffer); for (int x = 0; fRuns.fRuns[x]; x += fRuns.fRuns[x]) { @@ -373,7 +375,7 @@ protected: } } - inline void checkY(int y) { + void checkY(int y) { if (y != fCurrY) { this->flush(); fCurrY = y; @@ -381,8 +383,10 @@ protected: } }; -RunBasedAdditiveBlitter::RunBasedAdditiveBlitter( - SkBlitter* realBlitter, const SkIRect& ir, const SkIRect& clipBounds, bool isInverse) { +RunBasedAdditiveBlitter::RunBasedAdditiveBlitter(SkBlitter* realBlitter, + const SkIRect& ir, + const SkIRect& clipBounds, + bool isInverse) { fRealBlitter = realBlitter; SkIRect sectBounds; @@ -413,14 +417,6 @@ RunBasedAdditiveBlitter::RunBasedAdditiveBlitter( fOffsetX = 0; } -RunBasedAdditiveBlitter::~RunBasedAdditiveBlitter() { - this->flush(); -} - -SkBlitter* RunBasedAdditiveBlitter::getRealBlitter(bool forceRealBlitter) { - return fRealBlitter; -} - void RunBasedAdditiveBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], int len) { checkY(y); x -= fLeft; @@ -446,9 +442,10 @@ void RunBasedAdditiveBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], fRuns.fRuns[x + i] = 1; } for (int i = 0; i < len; ++i) { - addAlpha(&fRuns.fAlpha[x + i], antialias[i]); + add_alpha(&fRuns.fAlpha[x + i], antialias[i]); } } + void RunBasedAdditiveBlitter::blitAntiH(int x, int y, const SkAlpha alpha) { checkY(y); x -= fLeft; @@ -475,14 +472,15 @@ void RunBasedAdditiveBlitter::blitAntiH(int x, int y, int width, const SkAlpha a } } -int RunBasedAdditiveBlitter::getWidth() { return fWidth; } - // This exists specifically for concave path filling. // In those cases, we can easily accumulate alpha greater than 0xFF. class SafeRLEAdditiveBlitter : public RunBasedAdditiveBlitter { public: - SafeRLEAdditiveBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkIRect& clipBounds, - bool isInverse) : RunBasedAdditiveBlitter(realBlitter, ir, clipBounds, isInverse) {} + SafeRLEAdditiveBlitter(SkBlitter* realBlitter, + const SkIRect& ir, + const SkIRect& clipBounds, + bool isInverse) + : RunBasedAdditiveBlitter(realBlitter, ir, clipBounds, isInverse) {} void blitAntiH(int x, int y, const SkAlpha antialias[], int len) override; void blitAntiH(int x, int y, const SkAlpha alpha) override; @@ -514,7 +512,7 @@ void SafeRLEAdditiveBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], fRuns.fRuns[x + i] = 1; } for (int i = 0; i < len; ++i) { - safelyAddAlpha(&fRuns.fAlpha[x + i], antialias[i]); + safely_add_alpha(&fRuns.fAlpha[x + i], antialias[i]); } } @@ -529,7 +527,7 @@ void SafeRLEAdditiveBlitter::blitAntiH(int x, int y, const SkAlpha alpha) { if (check(x, 1)) { // Break the run fOffsetX = fRuns.add(x, 0, 1, 0, 0, fOffsetX); - safelyAddAlpha(&fRuns.fAlpha[x], alpha); + safely_add_alpha(&fRuns.fAlpha[x], alpha); } } @@ -545,66 +543,76 @@ void SafeRLEAdditiveBlitter::blitAntiH(int x, int y, int width, const SkAlpha al // Break the run fOffsetX = fRuns.add(x, 0, width, 0, 0, fOffsetX); for(int i = x; i < x + width; i += fRuns.fRuns[i]) { - safelyAddAlpha(&fRuns.fAlpha[i], alpha); + safely_add_alpha(&fRuns.fAlpha[i], alpha); } } } -/////////////////////////////////////////////////////////////////////////////// - // Return the alpha of a trapezoid whose height is 1 -static inline SkAlpha trapezoidToAlpha(SkFixed l1, SkFixed l2) { - SkASSERT(l1 >= 0 && l2 >= 0); - return (l1 + l2) >> 9; -} - -// The alpha of right-triangle (a, a*b), in 16 bits -static inline SkFixed partialTriangleToAlpha16(SkFixed a, SkFixed b) { - SkASSERT(a <= SK_Fixed1); - // SkFixedMul(SkFixedMul(a, a), b) >> 1 - // return ((((a >> 8) * (a >> 8)) >> 8) * (b >> 8)) >> 1; - return (a >> 11) * (a >> 11) * (b >> 11); +static SkAlpha trapezoid_to_alpha(SkFixed l1, SkFixed l2) { + SkASSERT(l1 >= 0 && + l2 >= 0); + SkFixed area = (l1 + l2) / 2; + return SkTo(area >> 8); } // The alpha of right-triangle (a, a*b) -static inline SkAlpha partialTriangleToAlpha(SkFixed a, SkFixed b) { - return (partialTriangleToAlpha16(a, b) >> 8) & 0xFF; +static SkAlpha partial_triangle_to_alpha(SkFixed a, SkFixed b) { + SkASSERT(a <= SK_Fixed1); +#if 0 + // TODO(mtklein): skia:8877 + SkASSERT(b <= SK_Fixed1); +#endif + + // Approximating... + // SkFixed area = SkFixedMul(a, SkFixedMul(a,b)) / 2; + SkFixed area = (a >> 11) * (a >> 11) * (b >> 11); + +#if 0 + // TODO(mtklein): skia:8877 + return SkTo(area >> 8); +#else + return SkTo((area >> 8) & 0xFF); +#endif } -static inline SkAlpha getPartialAlpha(SkAlpha alpha, SkFixed partialHeight) { +static SkAlpha get_partial_alpha(SkAlpha alpha, SkFixed partialHeight) { return SkToU8(SkFixedRoundToInt(alpha * partialHeight)); } -static inline SkAlpha getPartialAlpha(SkAlpha alpha, SkAlpha fullAlpha) { - return ((uint16_t)alpha * fullAlpha) >> 8; +static SkAlpha get_partial_alpha(SkAlpha alpha, SkAlpha fullAlpha) { + return (alpha * fullAlpha) >> 8; } // For SkFixed that's close to SK_Fixed1, we can't convert it to alpha by just shifting right. // For example, when f = SK_Fixed1, right shifting 8 will get 256, but we need 255. // This is rarely the problem so we'll only use this for blitting rectangles. -static inline SkAlpha f2a(SkFixed f) { +static SkAlpha fixed_to_alpha(SkFixed f) { SkASSERT(f <= SK_Fixed1); - return getPartialAlpha(0xFF, f); + return get_partial_alpha(0xFF, f); } // Suppose that line (l1, y)-(r1, y+1) intersects with (l2, y)-(r2, y+1), // approximate (very coarsely) the x coordinate of the intersection. -static inline SkFixed approximateIntersection(SkFixed l1, SkFixed r1, SkFixed l2, SkFixed r2) { - if (l1 > r1) { using std::swap; swap(l1, r1); } - if (l2 > r2) { using std::swap; swap(l2, r2); } - return (SkTMax(l1, l2) + SkTMin(r1, r2)) >> 1; +static SkFixed approximate_intersection(SkFixed l1, SkFixed r1, SkFixed l2, SkFixed r2) { + if (l1 > r1) { std::swap(l1, r1); } + if (l2 > r2) { std::swap(l2, r2); } + return (SkTMax(l1, l2) + SkTMin(r1, r2)) / 2; } // Here we always send in l < SK_Fixed1, and the first alpha we want to compute is alphas[0] -static inline void computeAlphaAboveLine(SkAlpha* alphas, SkFixed l, SkFixed r, - SkFixed dY, SkAlpha fullAlpha) { +static void compute_alpha_above_line(SkAlpha* alphas, + SkFixed l, + SkFixed r, + SkFixed dY, + SkAlpha fullAlpha) { SkASSERT(l <= r); SkASSERT(l >> 16 == 0); int R = SkFixedCeilToInt(r); if (R == 0) { return; } else if (R == 1) { - alphas[0] = getPartialAlpha(((R << 17) - l - r) >> 9, fullAlpha); + alphas[0] = get_partial_alpha(((R << 17) - l - r) >> 9, fullAlpha); } else { SkFixed first = SK_Fixed1 - l; // horizontal edge length of the left-most triangle SkFixed last = r - ((R - 1) << 16); // horizontal edge length of the right-most triangle @@ -615,20 +623,23 @@ static inline void computeAlphaAboveLine(SkAlpha* alphas, SkFixed l, SkFixed r, alphas[i] = alpha16 >> 8; alpha16 += dY; } - alphas[R - 1] = fullAlpha - partialTriangleToAlpha(last, dY); + alphas[R - 1] = fullAlpha - partial_triangle_to_alpha(last, dY); } } // Here we always send in l < SK_Fixed1, and the first alpha we want to compute is alphas[0] -static inline void computeAlphaBelowLine( - SkAlpha* alphas, SkFixed l, SkFixed r, SkFixed dY, SkAlpha fullAlpha) { +static void compute_alpha_below_line(SkAlpha* alphas, + SkFixed l, + SkFixed r, + SkFixed dY, + SkAlpha fullAlpha) { SkASSERT(l <= r); SkASSERT(l >> 16 == 0); int R = SkFixedCeilToInt(r); if (R == 0) { return; } else if (R == 1) { - alphas[0] = getPartialAlpha(trapezoidToAlpha(l, r), fullAlpha); + alphas[0] = get_partial_alpha(trapezoid_to_alpha(l, r), fullAlpha); } else { SkFixed first = SK_Fixed1 - l; // horizontal edge length of the left-most triangle SkFixed last = r - ((R - 1) << 16); // horizontal edge length of the right-most triangle @@ -639,41 +650,54 @@ static inline void computeAlphaBelowLine( alphas[i] = (alpha16 >> 8) & 0xFF; alpha16 += dY; } - alphas[0] = fullAlpha - partialTriangleToAlpha(first, dY); + alphas[0] = fullAlpha - partial_triangle_to_alpha(first, dY); } } // Note that if fullAlpha != 0xFF, we'll multiply alpha by fullAlpha -static SK_ALWAYS_INLINE void blit_single_alpha(AdditiveBlitter* blitter, int y, int x, - SkAlpha alpha, SkAlpha fullAlpha, SkAlpha* maskRow, - bool isUsingMask, bool noRealBlitter, bool needSafeCheck) { +static SK_ALWAYS_INLINE void blit_single_alpha(AdditiveBlitter* blitter, + int y, + int x, + SkAlpha alpha, + SkAlpha fullAlpha, + SkAlpha* maskRow, + bool isUsingMask, + bool noRealBlitter, + bool needSafeCheck) { if (isUsingMask) { if (fullAlpha == 0xFF && !noRealBlitter) { // noRealBlitter is needed for concave paths maskRow[x] = alpha; } else if (needSafeCheck) { - safelyAddAlpha(&maskRow[x], getPartialAlpha(alpha, fullAlpha)); + safely_add_alpha(&maskRow[x], get_partial_alpha(alpha, fullAlpha)); } else { - addAlpha(&maskRow[x], getPartialAlpha(alpha, fullAlpha)); + add_alpha(&maskRow[x], get_partial_alpha(alpha, fullAlpha)); } } else { if (fullAlpha == 0xFF && !noRealBlitter) { blitter->getRealBlitter()->blitV(x, y, 1, alpha); } else { - blitter->blitAntiH(x, y, getPartialAlpha(alpha, fullAlpha)); + blitter->blitAntiH(x, y, get_partial_alpha(alpha, fullAlpha)); } } } -static SK_ALWAYS_INLINE void blit_two_alphas(AdditiveBlitter* blitter, int y, int x, - SkAlpha a1, SkAlpha a2, SkAlpha fullAlpha, SkAlpha* maskRow, - bool isUsingMask, bool noRealBlitter, bool needSafeCheck) { +static SK_ALWAYS_INLINE void blit_two_alphas(AdditiveBlitter* blitter, + int y, + int x, + SkAlpha a1, + SkAlpha a2, + SkAlpha fullAlpha, + SkAlpha* maskRow, + bool isUsingMask, + bool noRealBlitter, + bool needSafeCheck) { if (isUsingMask) { if (needSafeCheck) { - safelyAddAlpha(&maskRow[x], a1); - safelyAddAlpha(&maskRow[x + 1], a2); + safely_add_alpha(&maskRow[x], a1); + safely_add_alpha(&maskRow[x + 1], a2); } else { - addAlpha(&maskRow[x], a1); - addAlpha(&maskRow[x + 1], a2); + add_alpha(&maskRow[x], a1); + add_alpha(&maskRow[x + 1], a2); } } else { if (fullAlpha == 0xFF && !noRealBlitter) { @@ -685,16 +709,21 @@ static SK_ALWAYS_INLINE void blit_two_alphas(AdditiveBlitter* blitter, int y, in } } -// It's important that this is inline. Otherwise it'll be much slower. -static SK_ALWAYS_INLINE void blit_full_alpha(AdditiveBlitter* blitter, int y, int x, int len, - SkAlpha fullAlpha, SkAlpha* maskRow, bool isUsingMask, - bool noRealBlitter, bool needSafeCheck) { +static SK_ALWAYS_INLINE void blit_full_alpha(AdditiveBlitter* blitter, + int y, + int x, + int len, + SkAlpha fullAlpha, + SkAlpha* maskRow, + bool isUsingMask, + bool noRealBlitter, + bool needSafeCheck) { if (isUsingMask) { for (int i = 0; i < len; ++i) { if (needSafeCheck) { - safelyAddAlpha(&maskRow[x + i], fullAlpha); + safely_add_alpha(&maskRow[x + i], fullAlpha); } else { - addAlpha(&maskRow[x + i], fullAlpha); + add_alpha(&maskRow[x + i], fullAlpha); } } } else { @@ -706,25 +735,37 @@ static SK_ALWAYS_INLINE void blit_full_alpha(AdditiveBlitter* blitter, int y, in } } -static void blit_aaa_trapezoid_row(AdditiveBlitter* blitter, int y, - SkFixed ul, SkFixed ur, SkFixed ll, SkFixed lr, - SkFixed lDY, SkFixed rDY, SkAlpha fullAlpha, SkAlpha* maskRow, - bool isUsingMask, bool noRealBlitter, bool needSafeCheck) { +static void blit_aaa_trapezoid_row(AdditiveBlitter* blitter, + int y, + SkFixed ul, + SkFixed ur, + SkFixed ll, + SkFixed lr, + SkFixed lDY, + SkFixed rDY, + SkAlpha fullAlpha, + SkAlpha* maskRow, + bool isUsingMask, + bool noRealBlitter, + bool needSafeCheck) { int L = SkFixedFloorToInt(ul), R = SkFixedCeilToInt(lr); int len = R - L; if (len == 1) { - SkAlpha alpha = trapezoidToAlpha(ur - ul, lr - ll); - blit_single_alpha(blitter, y, L, alpha, fullAlpha, maskRow, isUsingMask, noRealBlitter, - needSafeCheck); + SkAlpha alpha = trapezoid_to_alpha(ur - ul, lr - ll); + blit_single_alpha(blitter, + y, + L, + alpha, + fullAlpha, + maskRow, + isUsingMask, + noRealBlitter, + needSafeCheck); return; } - // SkDebugf("y = %d, len = %d, ul = %f, ur = %f, ll = %f, lr = %f\n", y, len, - // SkFixedToFloat(ul), SkFixedToFloat(ur), SkFixedToFloat(ll), SkFixedToFloat(lr)); - const int kQuickLen = 31; - // This is faster than SkAutoSMalloc<1024> char quickMemory[(sizeof(SkAlpha) * 2 + sizeof(int16_t)) * (kQuickLen + 1)]; SkAlpha* alphas; @@ -748,13 +789,16 @@ static void blit_aaa_trapezoid_row(AdditiveBlitter* blitter, int y, if (uL + 2 == lL) { // We only need to compute two triangles, accelerate this special case SkFixed first = SkIntToFixed(uL) + SK_Fixed1 - ul; SkFixed second = ll - ul - first; - SkAlpha a1 = fullAlpha - partialTriangleToAlpha(first, lDY); - SkAlpha a2 = partialTriangleToAlpha(second, lDY); + SkAlpha a1 = fullAlpha - partial_triangle_to_alpha(first, lDY); + SkAlpha a2 = partial_triangle_to_alpha(second, lDY); alphas[0] = alphas[0] > a1 ? alphas[0] - a1 : 0; alphas[1] = alphas[1] > a2 ? alphas[1] - a2 : 0; } else { - computeAlphaBelowLine(tempAlphas + uL - L, ul - SkIntToFixed(uL), ll - SkIntToFixed(uL), - lDY, fullAlpha); + compute_alpha_below_line(tempAlphas + uL - L, + ul - SkIntToFixed(uL), + ll - SkIntToFixed(uL), + lDY, + fullAlpha); for (int i = uL; i < lL; ++i) { if (alphas[i - L] > tempAlphas[i - L]) { alphas[i - L] -= tempAlphas[i - L]; @@ -769,13 +813,16 @@ static void blit_aaa_trapezoid_row(AdditiveBlitter* blitter, int y, if (uR + 2 == lR) { // We only need to compute two triangles, accelerate this special case SkFixed first = SkIntToFixed(uR) + SK_Fixed1 - ur; SkFixed second = lr - ur - first; - SkAlpha a1 = partialTriangleToAlpha(first, rDY); - SkAlpha a2 = fullAlpha - partialTriangleToAlpha(second, rDY); + SkAlpha a1 = partial_triangle_to_alpha(first, rDY); + SkAlpha a2 = fullAlpha - partial_triangle_to_alpha(second, rDY); alphas[len-2] = alphas[len-2] > a1 ? alphas[len-2] - a1 : 0; alphas[len-1] = alphas[len-1] > a2 ? alphas[len-1] - a2 : 0; } else { - computeAlphaAboveLine(tempAlphas + uR - L, ur - SkIntToFixed(uR), lr - SkIntToFixed(uR), - rDY, fullAlpha); + compute_alpha_above_line(tempAlphas + uR - L, + ur - SkIntToFixed(uR), + lr - SkIntToFixed(uR), + rDY, + fullAlpha); for (int i = uR; i < lR; ++i) { if (alphas[i - L] > tempAlphas[i - L]) { alphas[i - L] -= tempAlphas[i - L]; @@ -788,9 +835,9 @@ static void blit_aaa_trapezoid_row(AdditiveBlitter* blitter, int y, if (isUsingMask) { for (int i = 0; i < len; ++i) { if (needSafeCheck) { - safelyAddAlpha(&maskRow[L + i], alphas[i]); + safely_add_alpha(&maskRow[L + i], alphas[i]); } else { - addAlpha(&maskRow[L + i], alphas[i]); + add_alpha(&maskRow[L + i], alphas[i]); } } } else { @@ -807,28 +854,29 @@ static void blit_aaa_trapezoid_row(AdditiveBlitter* blitter, int y, } } -static SK_ALWAYS_INLINE void blit_trapezoid_row(AdditiveBlitter* blitter, int y, - SkFixed ul, SkFixed ur, SkFixed ll, SkFixed lr, - SkFixed lDY, SkFixed rDY, SkAlpha fullAlpha, - SkAlpha* maskRow, bool isUsingMask, bool noRealBlitter = false, - bool needSafeCheck = false) { +static SK_ALWAYS_INLINE void blit_trapezoid_row(AdditiveBlitter* blitter, + int y, + SkFixed ul, + SkFixed ur, + SkFixed ll, + SkFixed lr, + SkFixed lDY, + SkFixed rDY, + SkAlpha fullAlpha, + SkAlpha* maskRow, + bool isUsingMask, + bool noRealBlitter = false, + bool needSafeCheck = false) { SkASSERT(lDY >= 0 && rDY >= 0); // We should only send in the absolte value if (ul > ur) { -#ifdef SK_DEBUG - // SkDebugf("ul = %f > ur = %f!\n", SkFixedToFloat(ul), SkFixedToFloat(ur)); -#endif return; } // Edge crosses. Approximate it. This should only happend due to precision limit, // so the approximation could be very coarse. if (ll > lr) { -#ifdef SK_DEBUG - // SkDebugf("approximate intersection: %d %f %f\n", y, - // SkFixedToFloat(ll), SkFixedToFloat(lr)); -#endif - ll = lr = approximateIntersection(ul, ll, ur, lr); + ll = lr = approximate_intersection(ul, ll, ur, lr); } if (ul == ur && ll == lr) { @@ -839,8 +887,8 @@ static SK_ALWAYS_INLINE void blit_trapezoid_row(AdditiveBlitter* blitter, int y, // to exclude the area that's not covered by the path. // Swapping (ul, ll) or (ur, lr) won't affect that exclusion // so we'll do that for simplicity. - if (ul > ll) { using std::swap; swap(ul, ll); } - if (ur > lr) { using std::swap; swap(ur, lr); } + if (ul > ll) { std::swap(ul, ll); } + if (ur > lr) { std::swap(ur, lr); } SkFixed joinLeft = SkFixedCeilToFixed(ll); SkFixed joinRite = SkFixedFloorToFixed(ur); @@ -848,14 +896,14 @@ static SK_ALWAYS_INLINE void blit_trapezoid_row(AdditiveBlitter* blitter, int y, if (ul < joinLeft) { int len = SkFixedCeilToInt(joinLeft - ul); if (len == 1) { - SkAlpha alpha = trapezoidToAlpha(joinLeft - ul, joinLeft - ll); + SkAlpha alpha = trapezoid_to_alpha(joinLeft - ul, joinLeft - ll); blit_single_alpha(blitter, y, ul >> 16, alpha, fullAlpha, maskRow, isUsingMask, noRealBlitter, needSafeCheck); } else if (len == 2) { SkFixed first = joinLeft - SK_Fixed1 - ul; SkFixed second = ll - ul - first; - SkAlpha a1 = partialTriangleToAlpha(first, lDY); - SkAlpha a2 = fullAlpha - partialTriangleToAlpha(second, lDY); + SkAlpha a1 = partial_triangle_to_alpha(first, lDY); + SkAlpha a2 = fullAlpha - partial_triangle_to_alpha(second, lDY); blit_two_alphas(blitter, y, ul >> 16, a1, a2, fullAlpha, maskRow, isUsingMask, noRealBlitter, needSafeCheck); } else { @@ -874,14 +922,14 @@ static SK_ALWAYS_INLINE void blit_trapezoid_row(AdditiveBlitter* blitter, int y, if (lr > joinRite) { int len = SkFixedCeilToInt(lr - joinRite); if (len == 1) { - SkAlpha alpha = trapezoidToAlpha(ur - joinRite, lr - joinRite); + SkAlpha alpha = trapezoid_to_alpha(ur - joinRite, lr - joinRite); blit_single_alpha(blitter, y, joinRite >> 16, alpha, fullAlpha, maskRow, isUsingMask, noRealBlitter, needSafeCheck); } else if (len == 2) { SkFixed first = joinRite + SK_Fixed1 - ur; SkFixed second = lr - ur - first; - SkAlpha a1 = fullAlpha - partialTriangleToAlpha(first, rDY); - SkAlpha a2 = partialTriangleToAlpha(second, rDY); + SkAlpha a1 = fullAlpha - partial_triangle_to_alpha(first, rDY); + SkAlpha a2 = partial_triangle_to_alpha(second, rDY); blit_two_alphas(blitter, y, joinRite >> 16, a1, a2, fullAlpha, maskRow, isUsingMask, noRealBlitter, needSafeCheck); } else { @@ -896,8 +944,6 @@ static SK_ALWAYS_INLINE void blit_trapezoid_row(AdditiveBlitter* blitter, int y, } } -/////////////////////////////////////////////////////////////////////////////// - static bool operator<(const SkAnalyticEdge& a, const SkAnalyticEdge& b) { int valuea = a.fUpperY; int valueb = b.fUpperY; @@ -928,40 +974,39 @@ static SkAnalyticEdge* sort_edges(SkAnalyticEdge* list[], int count, SkAnalyticE return list[0]; } +static void validate_sort(const SkAnalyticEdge* edge) { #ifdef SK_DEBUG - static void validate_sort(const SkAnalyticEdge* edge) { - SkFixed y = SkIntToFixed(-32768); + SkFixed y = SkIntToFixed(-32768); - while (edge->fUpperY != SK_MaxS32) { - edge->validate(); - SkASSERT(y <= edge->fUpperY); + while (edge->fUpperY != SK_MaxS32) { + edge->validate(); + SkASSERT(y <= edge->fUpperY); - y = edge->fUpperY; - edge = (SkAnalyticEdge*)edge->fNext; - } + y = edge->fUpperY; + edge = (SkAnalyticEdge*)edge->fNext; } -#else - #define validate_sort(edge) #endif +} // For an edge, we consider it smooth if the Dx doesn't change much, and Dy is large enough // For curves that are updating, the Dx is not changing much if fQDx/fCDx and fQDy/fCDy are // relatively large compared to fQDDx/QCDDx and fQDDy/fCDDy -static inline bool isSmoothEnough(SkAnalyticEdge* thisEdge, SkAnalyticEdge* nextEdge, int stop_y) { +static bool is_smooth_enough(SkAnalyticEdge* thisEdge, + SkAnalyticEdge* nextEdge, + int stop_y) { if (thisEdge->fCurveCount < 0) { const SkCubicEdge& cEdge = static_cast(thisEdge)->fCEdge; int ddshift = cEdge.fCurveShift; return SkAbs32(cEdge.fCDx) >> 1 >= SkAbs32(cEdge.fCDDx) >> ddshift && - SkAbs32(cEdge.fCDy) >> 1 >= SkAbs32(cEdge.fCDDy) >> ddshift && - // current Dy is (fCDy - (fCDDy >> ddshift)) >> dshift - (cEdge.fCDy - (cEdge.fCDDy >> ddshift)) >> cEdge.fCubicDShift >= SK_Fixed1; + SkAbs32(cEdge.fCDy) >> 1 >= SkAbs32(cEdge.fCDDy) >> ddshift && + // current Dy is (fCDy - (fCDDy >> ddshift)) >> dshift + (cEdge.fCDy - (cEdge.fCDDy >> ddshift)) >> cEdge.fCubicDShift >= SK_Fixed1; } else if (thisEdge->fCurveCount > 0) { const SkQuadraticEdge& qEdge = static_cast(thisEdge)->fQEdge; return SkAbs32(qEdge.fQDx) >> 1 >= SkAbs32(qEdge.fQDDx) && - SkAbs32(qEdge.fQDy) >> 1 >= SkAbs32(qEdge.fQDDy) && - // current Dy is (fQDy - fQDDy) >> shift - (qEdge.fQDy - qEdge.fQDDy) >> qEdge.fCurveShift - >= SK_Fixed1; + SkAbs32(qEdge.fQDy) >> 1 >= SkAbs32(qEdge.fQDDy) && + // current Dy is (fQDy - fQDDy) >> shift + (qEdge.fQDy - qEdge.fQDDy) >> qEdge.fCurveShift >= SK_Fixed1; } return SkAbs32(nextEdge->fDX - thisEdge->fDX) <= SK_Fixed1 && // DDx should be small nextEdge->fLowerY - nextEdge->fUpperY >= SK_Fixed1; // Dy should be large @@ -969,15 +1014,17 @@ static inline bool isSmoothEnough(SkAnalyticEdge* thisEdge, SkAnalyticEdge* next // Check if the leftE and riteE are changing smoothly in terms of fDX. // If yes, we can later skip the fractional y and directly jump to integer y. -static inline bool isSmoothEnough(SkAnalyticEdge* leftE, SkAnalyticEdge* riteE, - SkAnalyticEdge* currE, int stop_y) { +static bool is_smooth_enough(SkAnalyticEdge* leftE, + SkAnalyticEdge* riteE, + SkAnalyticEdge* currE, + int stop_y) { if (currE->fUpperY >= SkLeftShift(stop_y, 16)) { return false; // We're at the end so we won't skip anything } if (leftE->fLowerY + SK_Fixed1 < riteE->fLowerY) { - return isSmoothEnough(leftE, currE, stop_y); // Only leftE is changing + return is_smooth_enough(leftE, currE, stop_y); // Only leftE is changing } else if (leftE->fLowerY > riteE->fLowerY + SK_Fixed1) { - return isSmoothEnough(riteE, currE, stop_y); // Only riteE is changing + return is_smooth_enough(riteE, currE, stop_y); // Only riteE is changing } // Now both edges are changing, find the second next edge @@ -987,15 +1034,18 @@ static inline bool isSmoothEnough(SkAnalyticEdge* leftE, SkAnalyticEdge* riteE, } // Ensure that currE is the next left edge and nextCurrE is the next right edge. Swap if not. if (nextCurrE->fUpperX < currE->fUpperX) { - using std::swap; - swap(currE, nextCurrE); + std::swap(currE, nextCurrE); } - return isSmoothEnough(leftE, currE, stop_y) && isSmoothEnough(riteE, nextCurrE, stop_y); + return is_smooth_enough(leftE, currE, stop_y) && is_smooth_enough(riteE, nextCurrE, stop_y); } -static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, - AdditiveBlitter* blitter, int start_y, int stop_y, SkFixed leftBound, SkFixed riteBound, - bool isUsingMask) { +static void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, + AdditiveBlitter* blitter, + int start_y, + int stop_y, + SkFixed leftBound, + SkFixed riteBound, + bool isUsingMask) { validate_sort((SkAnalyticEdge*)prevHead->fNext); SkAnalyticEdge* leftE = (SkAnalyticEdge*) prevHead->fNext; @@ -1004,11 +1054,6 @@ static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, SkFixed y = SkTMax(leftE->fUpperY, riteE->fUpperY); - #ifdef SK_DEBUG - int frac_y_cnt = 0; - int total_y_cnt = 0; - #endif - for (;;) { // We have to check fLowerY first because some edges might be alone (e.g., there's only // a left edge but no right edge in a given y scan line) due to precision limit. @@ -1047,12 +1092,11 @@ static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, if (leftE->fX > riteE->fX || (leftE->fX == riteE->fX && leftE->fDX > riteE->fDX)) { - using std::swap; - swap(leftE, riteE); + std::swap(leftE, riteE); } SkFixed local_bot_fixed = SkMin32(leftE->fLowerY, riteE->fLowerY); - if (isSmoothEnough(leftE, riteE, currE, stop_y)) { + if (is_smooth_enough(leftE, riteE, currE, stop_y)) { local_bot_fixed = SkFixedCeilToFixed(local_bot_fixed); } local_bot_fixed = SkMin32(local_bot_fixed, SkIntToFixed(stop_y)); @@ -1079,13 +1123,13 @@ static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, if (partialTop > 0) { // blit first partial row if (partialLeft > 0) { blitter->blitAntiH(fullLeft - 1, fullTop - 1, - f2a(SkFixedMul(partialTop, partialLeft))); + fixed_to_alpha(SkFixedMul(partialTop, partialLeft))); } blitter->blitAntiH(fullLeft, fullTop - 1, fullRite - fullLeft, - f2a(partialTop)); + fixed_to_alpha(partialTop)); if (partialRite > 0) { blitter->blitAntiH(fullRite, fullTop - 1, - f2a(SkFixedMul(partialTop, partialRite))); + fixed_to_alpha(SkFixedMul(partialTop, partialRite))); } blitter->flush_if_y_changed(y, y + partialTop); } @@ -1094,36 +1138,50 @@ static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, if (fullBot > fullTop && // SkAAClip cannot handle the empty rect so check the non-emptiness here // (bug chromium:662800) - (fullRite > fullLeft || f2a(partialLeft) > 0 || f2a(partialRite) > 0)) { - blitter->getRealBlitter()->blitAntiRect(fullLeft - 1, fullTop, - fullRite - fullLeft, fullBot - fullTop, - f2a(partialLeft), f2a(partialRite)); + (fullRite > fullLeft || + fixed_to_alpha(partialLeft) > 0 || + fixed_to_alpha(partialRite) > 0)) { + blitter->getRealBlitter()->blitAntiRect(fullLeft - 1, + fullTop, + fullRite - fullLeft, + fullBot - fullTop, + fixed_to_alpha(partialLeft), + fixed_to_alpha(partialRite)); } if (partialBot > 0) { // blit last partial row if (partialLeft > 0) { - blitter->blitAntiH(fullLeft - 1, fullBot, - f2a(SkFixedMul(partialBot, partialLeft))); + blitter->blitAntiH(fullLeft - 1, + fullBot, + fixed_to_alpha(SkFixedMul(partialBot, partialLeft))); } - blitter->blitAntiH(fullLeft, fullBot, fullRite - fullLeft, f2a(partialBot)); + blitter->blitAntiH(fullLeft, + fullBot, + fullRite - fullLeft, + fixed_to_alpha(partialBot)); if (partialRite > 0) { - blitter->blitAntiH(fullRite, fullBot, - f2a(SkFixedMul(partialBot, partialRite))); + blitter->blitAntiH(fullRite, + fullBot, + fixed_to_alpha(SkFixedMul(partialBot, partialRite))); } } } else { // left and rite are within the same pixel if (partialTop > 0) { - blitter->blitAntiH(fullLeft - 1, fullTop - 1, 1, - f2a(SkFixedMul(partialTop, rite - left))); + blitter->blitAntiH(fullLeft - 1, + fullTop - 1, + 1, + fixed_to_alpha(SkFixedMul(partialTop, rite - left))); blitter->flush_if_y_changed(y, y + partialTop); } if (fullBot > fullTop) { - blitter->getRealBlitter()->blitV(fullLeft - 1, fullTop, fullBot - fullTop, - f2a(rite - left)); + blitter->getRealBlitter()->blitV(fullLeft - 1, + fullTop, + fullBot - fullTop, + fixed_to_alpha(rite - left)); } if (partialBot > 0) { blitter->blitAntiH(fullLeft - 1, fullBot, 1, - f2a(SkFixedMul(partialBot, rite - left))); + fixed_to_alpha(SkFixedMul(partialBot, rite - left))); } } @@ -1139,13 +1197,6 @@ static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, // Number of blit_trapezoid_row calls we'll have int count = SkFixedCeilToInt(local_bot_fixed) - SkFixedFloorToInt(y); - #ifdef SK_DEBUG - total_y_cnt += count; - frac_y_cnt += ((int)(y & 0xFFFF0000) != y); - if ((int)(y & 0xFFFF0000) != y) { - // SkDebugf("frac_y = %f\n", SkFixedToFloat(y)); - } - #endif // If we're using mask blitter, we advance the mask row in this function // to save some "if" condition checks. @@ -1165,14 +1216,25 @@ static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, SkFixed dY = nextY - y; SkFixed nextLeft = left + SkFixedMul(dLeft, dY); SkFixed nextRite = rite + SkFixedMul(dRite, dY); - SkASSERT((left & kSnapMask) >= leftBound && (rite & kSnapMask) <= riteBound && - (nextLeft & kSnapMask) >= leftBound && - (nextRite & kSnapMask) <= riteBound); - blit_trapezoid_row(blitter, y >> 16, left & kSnapMask, rite & kSnapMask, - nextLeft & kSnapMask, nextRite & kSnapMask, leftE->fDY, riteE->fDY, - getPartialAlpha(0xFF, dY), maskRow, isUsingMask); + SkASSERT((left & kSnapMask) >= leftBound && + (rite & kSnapMask) <= riteBound && + (nextLeft & kSnapMask) >= leftBound && + (nextRite & kSnapMask) <= riteBound); + blit_trapezoid_row(blitter, + y >> 16, + left & kSnapMask, + rite & kSnapMask, + nextLeft & kSnapMask, + nextRite & kSnapMask, + leftE->fDY, + riteE->fDY, + get_partial_alpha(0xFF, dY), + maskRow, + isUsingMask); blitter->flush_if_y_changed(y, nextY); - left = nextLeft; rite = nextRite; y = nextY; + left = nextLeft; + rite = nextRite; + y = nextY; } while (count > 1) { // Full rows in the middle @@ -1181,14 +1243,25 @@ static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, maskRow = static_cast(blitter)->getRow(y >> 16); } SkFixed nextY = y + SK_Fixed1, nextLeft = left + dLeft, nextRite = rite + dRite; - SkASSERT((left & kSnapMask) >= leftBound && (rite & kSnapMask) <= riteBound && - (nextLeft & kSnapMask) >= leftBound && - (nextRite & kSnapMask) <= riteBound); - blit_trapezoid_row(blitter, y >> 16, left & kSnapMask, rite & kSnapMask, - nextLeft & kSnapMask, nextRite & kSnapMask, - leftE->fDY, riteE->fDY, 0xFF, maskRow, isUsingMask); + SkASSERT((left & kSnapMask) >= leftBound && + (rite & kSnapMask) <= riteBound && + (nextLeft & kSnapMask) >= leftBound && + (nextRite & kSnapMask) <= riteBound); + blit_trapezoid_row(blitter, + y >> 16, + left & kSnapMask, + rite & kSnapMask, + nextLeft & kSnapMask, + nextRite & kSnapMask, + leftE->fDY, + riteE->fDY, + 0xFF, + maskRow, + isUsingMask); blitter->flush_if_y_changed(y, nextY); - left = nextLeft; rite = nextRite; y = nextY; + left = nextLeft; + rite = nextRite; + y = nextY; } } @@ -1203,14 +1276,27 @@ static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, // Note that we substract kSnapHalf later so we have to add them to leftBound/riteBound SkFixed nextLeft = SkTMax(left + SkFixedMul(dLeft, dY), leftBound + kSnapHalf); SkFixed nextRite = SkTMin(rite + SkFixedMul(dRite, dY), riteBound + kSnapHalf); - SkASSERT((left & kSnapMask) >= leftBound && (rite & kSnapMask) <= riteBound && - (nextLeft & kSnapMask) >= leftBound && (nextRite & kSnapMask) <= riteBound); - blit_trapezoid_row(blitter, y >> 16, left & kSnapMask, rite & kSnapMask, - nextLeft & kSnapMask, nextRite & kSnapMask, leftE->fDY, riteE->fDY, - getPartialAlpha(0xFF, dY), maskRow, isUsingMask); + SkASSERT((left & kSnapMask) >= leftBound && + (rite & kSnapMask) <= riteBound && + (nextLeft & kSnapMask) >= leftBound && + (nextRite & kSnapMask) <= riteBound); + blit_trapezoid_row(blitter, + y >> 16, + left & kSnapMask, + rite & kSnapMask, + nextLeft & kSnapMask, + nextRite & kSnapMask, + leftE->fDY, + riteE->fDY, + get_partial_alpha(0xFF, dY), + maskRow, + isUsingMask); blitter->flush_if_y_changed(y, local_bot_fixed); - left = nextLeft; rite = nextRite; y = local_bot_fixed; - left -= kSnapHalf; rite -= kSnapHalf; + left = nextLeft; + rite = nextRite; + y = local_bot_fixed; + left -= kSnapHalf; + rite -= kSnapHalf; } leftE->fX = left; @@ -1220,19 +1306,13 @@ static inline void aaa_walk_convex_edges(SkAnalyticEdge* prevHead, END_WALK: ; - #ifdef SK_DEBUG - // SkDebugf("frac_y_cnt = %d, total_y_cnt = %d\n", frac_y_cnt, total_y_cnt); - #endif } -/////////////////////////////////////////////////////////////////////////////// - -static inline void updateNextNextY(SkFixed y, SkFixed nextY, SkFixed* nextNextY) { +static void update_next_next_y(SkFixed y, SkFixed nextY, SkFixed* nextNextY) { *nextNextY = y > nextY && y < *nextNextY ? y : *nextNextY; } -static inline void checkIntersection(const SkAnalyticEdge* edge, SkFixed nextY, SkFixed* nextNextY) -{ +static void check_intersection(const SkAnalyticEdge* edge, SkFixed nextY, SkFixed* nextNextY) { if (edge->fPrev->fPrev && edge->fPrev->fX + edge->fPrev->fDX > edge->fX + edge->fDX) { *nextNextY = nextY + (SK_Fixed1 >> SkAnalyticEdge::kDefaultAccuracy); } @@ -1240,17 +1320,17 @@ static inline void checkIntersection(const SkAnalyticEdge* edge, SkFixed nextY, static void insert_new_edges(SkAnalyticEdge* newEdge, SkFixed y, SkFixed* nextNextY) { if (newEdge->fUpperY > y) { - updateNextNextY(newEdge->fUpperY, y, nextNextY); + update_next_next_y(newEdge->fUpperY, y, nextNextY); return; } SkAnalyticEdge* prev = newEdge->fPrev; if (prev->fX <= newEdge->fX) { while (newEdge->fUpperY <= y) { - checkIntersection(newEdge, y, nextNextY); - updateNextNextY(newEdge->fLowerY, y, nextNextY); + check_intersection(newEdge, y, nextNextY); + update_next_next_y(newEdge->fLowerY, y, nextNextY); newEdge = newEdge->fNext; } - updateNextNextY(newEdge->fUpperY, y, nextNextY); + update_next_next_y(newEdge->fUpperY, y, nextNextY); return; } // find first x pos to insert @@ -1272,12 +1352,12 @@ static void insert_new_edges(SkAnalyticEdge* newEdge, SkFixed y, SkFixed* nextNe remove_edge(newEdge); insert_edge_after(newEdge, start); nextEdge: - checkIntersection(newEdge, y, nextNextY); - updateNextNextY(newEdge->fLowerY, y, nextNextY); + check_intersection(newEdge, y, nextNextY); + update_next_next_y(newEdge->fLowerY, y, nextNextY); start = newEdge; newEdge = next; } while (newEdge->fUpperY <= y); - updateNextNextY(newEdge->fUpperY, y, nextNextY); + update_next_next_y(newEdge->fUpperY, y, nextNextY); } static void validate_edges_for_y(const SkAnalyticEdge* edge, SkFixed y) { @@ -1294,7 +1374,7 @@ static void validate_edges_for_y(const SkAnalyticEdge* edge, SkFixed y) { } // Return true if prev->fX, next->fX are too close in the current pixel row. -static inline bool edges_too_close(SkAnalyticEdge* prev, SkAnalyticEdge* next, SkFixed lowerY) { +static bool edges_too_close(SkAnalyticEdge* prev, SkAnalyticEdge* next, SkFixed lowerY) { // When next->fDX == 0, prev->fX >= next->fX - SkAbs32(next->fDX) would be false // even if prev->fX and next->fX are close and within one pixel (e.g., prev->fX == 0.1, // next->fX == 0.9). Adding SLACK = 1 to the formula would guarantee it to be true if two @@ -1315,45 +1395,79 @@ static inline bool edges_too_close(SkAnalyticEdge* prev, SkAnalyticEdge* next, S // This function exists for the case where the previous rite edge is removed because // its fLowerY <= nextY -static inline bool edges_too_close(int prevRite, SkFixed ul, SkFixed ll) { +static bool edges_too_close(int prevRite, SkFixed ul, SkFixed ll) { return prevRite > SkFixedFloorToInt(ul) || prevRite > SkFixedFloorToInt(ll); } -static inline void blit_saved_trapezoid(SkAnalyticEdge* leftE, SkFixed lowerY, - SkFixed lowerLeft, SkFixed lowerRite, - AdditiveBlitter* blitter, SkAlpha* maskRow, bool isUsingMask, bool noRealBlitter, - SkFixed leftClip, SkFixed rightClip) { +static void blit_saved_trapezoid(SkAnalyticEdge* leftE, + SkFixed lowerY, + SkFixed lowerLeft, + SkFixed lowerRite, + AdditiveBlitter* blitter, + SkAlpha* maskRow, + bool isUsingMask, + bool noRealBlitter, + SkFixed leftClip, + SkFixed rightClip) { SkAnalyticEdge* riteE = leftE->fRiteE; SkASSERT(riteE); SkASSERT(riteE->fNext == nullptr || leftE->fSavedY == riteE->fSavedY); SkASSERT(SkFixedFloorToInt(lowerY - 1) == SkFixedFloorToInt(leftE->fSavedY)); int y = SkFixedFloorToInt(leftE->fSavedY); - // Instead of using f2a(lowerY - leftE->fSavedY), we use the following fullAlpha + // Instead of using fixed_to_alpha(lowerY - leftE->fSavedY), we use the following fullAlpha // to elimiate cumulative error: if there are many fractional y scan lines within the // same row, the former may accumulate the rounding error while the later won't. - SkAlpha fullAlpha = f2a(lowerY - SkIntToFixed(y)) - f2a(leftE->fSavedY - SkIntToFixed(y)); + SkAlpha fullAlpha = fixed_to_alpha(lowerY - SkIntToFixed(y)) + - fixed_to_alpha(leftE->fSavedY - SkIntToFixed(y)); // We need fSavedDY because the (quad or cubic) edge might be updated - blit_trapezoid_row(blitter, y, - SkTMax(leftE->fSavedX, leftClip), SkTMin(riteE->fSavedX, rightClip), - SkTMax(lowerLeft, leftClip), SkTMin(lowerRite, rightClip), - leftE->fSavedDY, riteE->fSavedDY, fullAlpha, maskRow, isUsingMask, - noRealBlitter || - (fullAlpha == 0xFF && (edges_too_close(leftE->fPrev, leftE, lowerY) - || edges_too_close(riteE, riteE->fNext, lowerY))), - true); + blit_trapezoid_row(blitter, + y, + SkTMax(leftE->fSavedX, leftClip), + SkTMin(riteE->fSavedX, rightClip), + SkTMax(lowerLeft, leftClip), + SkTMin(lowerRite, rightClip), + leftE->fSavedDY, + riteE->fSavedDY, + fullAlpha, + maskRow, + isUsingMask, + noRealBlitter || + (fullAlpha == 0xFF && + (edges_too_close(leftE->fPrev, leftE, lowerY) || + edges_too_close(riteE, riteE->fNext, lowerY))), + true); leftE->fRiteE = nullptr; } -static inline void deferred_blit(SkAnalyticEdge* leftE, SkAnalyticEdge* riteE, - SkFixed left, SkFixed leftDY, // don't save leftE->fX/fDY as they may have been updated - SkFixed y, SkFixed nextY, bool isIntegralNextY, bool leftEnds, bool riteEnds, - AdditiveBlitter* blitter, SkAlpha* maskRow, bool isUsingMask, bool noRealBlitter, - SkFixed leftClip, SkFixed rightClip, int yShift) { +static void deferred_blit(SkAnalyticEdge* leftE, + SkAnalyticEdge* riteE, + SkFixed left, + SkFixed leftDY, // don't save leftE->fX/fDY as they may have been updated + SkFixed y, + SkFixed nextY, + bool isIntegralNextY, + bool leftEnds, + bool riteEnds, + AdditiveBlitter* blitter, + SkAlpha* maskRow, + bool isUsingMask, + bool noRealBlitter, + SkFixed leftClip, + SkFixed rightClip, + int yShift) { if (leftE->fRiteE && leftE->fRiteE != riteE) { // leftE's right edge changed. Blit the saved trapezoid. SkASSERT(leftE->fRiteE->fNext == nullptr || leftE->fRiteE->fY == y); - blit_saved_trapezoid(leftE, y, left, leftE->fRiteE->fX, - blitter, maskRow, isUsingMask, noRealBlitter, leftClip, rightClip); + blit_saved_trapezoid(leftE, + y, + left, + leftE->fRiteE->fX, + blitter, + maskRow, + isUsingMask, + noRealBlitter, + leftClip, + rightClip); } if (!leftE->fRiteE) { // Save and defer blitting the trapezoid @@ -1368,15 +1482,31 @@ static inline void deferred_blit(SkAnalyticEdge* leftE, SkAnalyticEdge* riteE, riteE->goY(nextY, yShift); // Always blit when edges end or nextY is integral if (isIntegralNextY || leftEnds || riteEnds) { - blit_saved_trapezoid(leftE, nextY, leftE->fX, riteE->fX, - blitter, maskRow, isUsingMask, noRealBlitter, leftClip, rightClip); + blit_saved_trapezoid(leftE, + nextY, + leftE->fX, + riteE->fX, + blitter, + maskRow, + isUsingMask, + noRealBlitter, + leftClip, + rightClip); } } -static void aaa_walk_edges(SkAnalyticEdge* prevHead, SkAnalyticEdge* nextTail, - SkPath::FillType fillType, AdditiveBlitter* blitter, int start_y, int stop_y, - SkFixed leftClip, SkFixed rightClip, bool isUsingMask, bool forceRLE, bool useDeferred, - bool skipIntersect) { +static void aaa_walk_edges(SkAnalyticEdge* prevHead, + SkAnalyticEdge* nextTail, + SkPath::FillType fillType, + AdditiveBlitter* blitter, + int start_y, + int stop_y, + SkFixed leftClip, + SkFixed rightClip, + bool isUsingMask, + bool forceRLE, + bool useDeferred, + bool skipIntersect) { prevHead->fX = prevHead->fUpperX = leftClip; nextTail->fX = nextTail->fUpperX = rightClip; SkFixed y = SkTMax(prevHead->fNext->fUpperY, SkIntToFixed(start_y)); @@ -1386,9 +1516,9 @@ static void aaa_walk_edges(SkAnalyticEdge* prevHead, SkAnalyticEdge* nextTail, SkAnalyticEdge* edge; for(edge = prevHead->fNext; edge->fUpperY <= y; edge = edge->fNext) { edge->goY(y); - updateNextNextY(edge->fLowerY, y, &nextNextY); + update_next_next_y(edge->fLowerY, y, &nextNextY); } - updateNextNextY(edge->fUpperY, y, &nextNextY); + update_next_next_y(edge->fUpperY, y, &nextNextY); } // returns 1 for evenodd, -1 for winding, regardless of inverse-ness @@ -1399,14 +1529,23 @@ static void aaa_walk_edges(SkAnalyticEdge* prevHead, SkAnalyticEdge* nextTail, if (isInverse && SkIntToFixed(start_y) != y) { int width = SkFixedFloorToInt(rightClip - leftClip); if (SkFixedFloorToInt(y) != start_y) { - blitter->getRealBlitter()->blitRect(SkFixedFloorToInt(leftClip), start_y, - width, SkFixedFloorToInt(y) - start_y); + blitter->getRealBlitter()->blitRect(SkFixedFloorToInt(leftClip), + start_y, + width, + SkFixedFloorToInt(y) - start_y); start_y = SkFixedFloorToInt(y); } SkAlpha* maskRow = isUsingMask ? static_cast(blitter)->getRow(start_y) : nullptr; - blit_full_alpha(blitter, start_y, SkFixedFloorToInt(leftClip), width, - f2a(y - SkIntToFixed(start_y)), maskRow, isUsingMask, false, false); + blit_full_alpha(blitter, + start_y, + SkFixedFloorToInt(leftClip), + width, + fixed_to_alpha(y - SkIntToFixed(start_y)), + maskRow, + isUsingMask, + false, + false); } while (true) { @@ -1434,7 +1573,7 @@ static void aaa_walk_edges(SkAnalyticEdge* prevHead, SkAnalyticEdge* nextTail, SkASSERT(nextY == y + (SK_Fixed1 >> 1)); } - SkAlpha fullAlpha = f2a(nextY - y); + SkAlpha fullAlpha = fixed_to_alpha(nextY - y); // If we're using mask blitter, we advance the mask row in this function // to save some "if" condition checks. @@ -1467,36 +1606,74 @@ static void aaa_walk_edges(SkAnalyticEdge* prevHead, SkAnalyticEdge* nextTail, // currE is a left edge previously, but now it's not. // Blit the trapezoid between fSavedY and y. SkASSERT(currE->fRiteE->fY == y); - blit_saved_trapezoid(currE, y, currE->fX, currE->fRiteE->fX, - blitter, maskRow, isUsingMask, noRealBlitter, leftClip, rightClip); + blit_saved_trapezoid(currE, + y, + currE->fX, + currE->fRiteE->fX, + blitter, + maskRow, + isUsingMask, + noRealBlitter, + leftClip, + rightClip); } if (leftE->fRiteE == currE && !isRite) { // currE is a right edge previously, but now it's not. // Moreover, its corresponding leftE doesn't change (otherwise we'll handle it // in the previous if clause). Hence we blit the trapezoid. - blit_saved_trapezoid(leftE, y, left, currE->fX, - blitter, maskRow, isUsingMask, noRealBlitter, leftClip, rightClip); + blit_saved_trapezoid(leftE, + y, + left, + currE->fX, + blitter, + maskRow, + isUsingMask, + noRealBlitter, + leftClip, + rightClip); } } if (isRite) { if (useDeferred) { - deferred_blit(leftE, currE, left, leftDY, y, nextY, isIntegralNextY, - leftEnds, currEnds, blitter, maskRow, isUsingMask, noRealBlitter, - leftClip, rightClip, yShift); + deferred_blit(leftE, + currE, + left, + leftDY, + y, + nextY, + isIntegralNextY, + leftEnds, + currEnds, + blitter, + maskRow, + isUsingMask, + noRealBlitter, + leftClip, + rightClip, + yShift); } else { SkFixed rite = currE->fX; currE->goY(nextY, yShift); SkFixed nextLeft = SkTMax(leftClip, leftE->fX); rite = SkTMin(rightClip, rite); SkFixed nextRite = SkTMin(rightClip, currE->fX); - blit_trapezoid_row(blitter, y >> 16, left, rite, nextLeft, nextRite, - leftDY, currE->fDY, fullAlpha, maskRow, isUsingMask, - noRealBlitter || (fullAlpha == 0xFF && ( - edges_too_close(prevRite, left, leftE->fX) || - edges_too_close(currE, currE->fNext, nextY) - )), - true); + blit_trapezoid_row(blitter, + y >> 16, + left, + rite, + nextLeft, + nextRite, + leftDY, + currE->fDY, + fullAlpha, + maskRow, + isUsingMask, + noRealBlitter || + (fullAlpha == 0xFF && + (edges_too_close(prevRite, left, leftE->fX) || + edges_too_close(currE, currE->fNext, nextY))), + true); prevRite = SkFixedCeilToInt(SkTMax(rite, currE->fX)); } } else { @@ -1535,22 +1712,30 @@ static void aaa_walk_edges(SkAnalyticEdge* prevHead, SkAnalyticEdge* nextTail, if (currE->fLowerY <= nextY) { remove_edge(currE); } else { - updateNextNextY(currE->fLowerY, nextY, &nextNextY); + update_next_next_y(currE->fLowerY, nextY, &nextNextY); newX = currE->fX; SkASSERT(currE->fLowerY > nextY); if (newX < prevX) { // ripple currE backwards until it is x-sorted // If the crossing edge is a right edge, blit the saved trapezoid. if (leftE->fRiteE == currE && useDeferred) { SkASSERT(leftE->fY == nextY && currE->fY == nextY); - blit_saved_trapezoid(leftE, nextY, leftE->fX, currE->fX, - blitter, maskRow, isUsingMask, noRealBlitter, leftClip, rightClip); + blit_saved_trapezoid(leftE, + nextY, + leftE->fX, + currE->fX, + blitter, + maskRow, + isUsingMask, + noRealBlitter, + leftClip, + rightClip); } backward_insert_edge_based_on_x(currE); } else { prevX = newX; } if (!skipIntersect) { - checkIntersection(currE, nextY, &nextNextY); + check_intersection(currE, nextY, &nextNextY); } } @@ -1561,17 +1746,38 @@ static void aaa_walk_edges(SkAnalyticEdge* prevHead, SkAnalyticEdge* nextTail, // was our right-edge culled away? if (in_interval) { if (useDeferred) { - deferred_blit(leftE, nextTail, left, leftDY, y, nextY, isIntegralNextY, - leftEnds, false, blitter, maskRow, isUsingMask, noRealBlitter, - leftClip, rightClip, yShift); + deferred_blit(leftE, + nextTail, + left, + leftDY, + y, + nextY, + isIntegralNextY, + leftEnds, + false, + blitter, + maskRow, + isUsingMask, + noRealBlitter, + leftClip, + rightClip, + yShift); } else { - blit_trapezoid_row(blitter, y >> 16, - left, rightClip, - SkTMax(leftClip, leftE->fX), rightClip, - leftDY, 0, fullAlpha, maskRow, isUsingMask, - noRealBlitter || - (fullAlpha == 0xFF && edges_too_close(leftE->fPrev, leftE, nextY)), - true); + blit_trapezoid_row(blitter, + y >> 16, + left, + rightClip, + SkTMax(leftClip, leftE->fX), + rightClip, + leftDY, + 0, + fullAlpha, + maskRow, + isUsingMask, + noRealBlitter || + (fullAlpha == 0xFF && + edges_too_close(leftE->fPrev, leftE, nextY)), + true); } } @@ -1589,9 +1795,14 @@ static void aaa_walk_edges(SkAnalyticEdge* prevHead, SkAnalyticEdge* nextTail, } } -static SK_ALWAYS_INLINE void aaa_fill_path(const SkPath& path, const SkIRect& clipRect, - AdditiveBlitter* blitter, int start_y, int stop_y, bool pathContainedInClip, - bool isUsingMask, bool forceRLE) { // forceRLE implies that SkAAClip is calling us +static SK_ALWAYS_INLINE void aaa_fill_path(const SkPath& path, + const SkIRect& clipRect, + AdditiveBlitter* blitter, + int start_y, + int stop_y, + bool pathContainedInClip, + bool isUsingMask, + bool forceRLE) { // forceRLE implies that SkAAClip is calling us SkASSERT(blitter); SkAnalyticEdgeBuilder builder; @@ -1666,8 +1877,13 @@ static SK_ALWAYS_INLINE void aaa_fill_path(const SkPath& path, const SkIRect& cl } if (!path.isInverseFillType() && path.isConvex() && count >= 2) { - aaa_walk_convex_edges(&headEdge, blitter, start_y, stop_y, - leftBound, rightBound, isUsingMask); + aaa_walk_convex_edges(&headEdge, + blitter, + start_y, + stop_y, + leftBound, + rightBound, + isUsingMask); } else { // Only use deferred blitting if there are many edges. bool useDeferred = count > @@ -1677,32 +1893,49 @@ static SK_ALWAYS_INLINE void aaa_fill_path(const SkPath& path, const SkIRect& cl // give us enough fractional scan lines. bool skipIntersect = path.countPoints() > (stop_y - start_y) * 2; - aaa_walk_edges(&headEdge, &tailEdge, path.getFillType(), blitter, start_y, stop_y, - leftBound, rightBound, isUsingMask, forceRLE, useDeferred, skipIntersect); + aaa_walk_edges(&headEdge, + &tailEdge, + path.getFillType(), + blitter, + start_y, + stop_y, + leftBound, + rightBound, + isUsingMask, + forceRLE, + useDeferred, + skipIntersect); } } -/////////////////////////////////////////////////////////////////////////////// - -void SkScan::AAAFillPath(const SkPath& path, SkBlitter* blitter, const SkIRect& ir, - const SkIRect& clipBounds, bool forceRLE) { +void SkScan::AAAFillPath(const SkPath& path, + SkBlitter* blitter, + const SkIRect& ir, + const SkIRect& clipBounds, + bool forceRLE) { bool containedInClip = clipBounds.contains(ir); bool isInverse = path.isInverseFillType(); // The mask blitter (where we store intermediate alpha values directly in a mask, and then call // the real blitter once in the end to blit the whole mask) is faster than the RLE blitter when - // the blit region is small enough (i.e., canHandleRect(ir)). When isInverse is true, the blit + // the blit region is small enough (i.e., CanHandleRect(ir)). When isInverse is true, the blit // region is no longer the rectangle ir so we won't use the mask blitter. The caller may also // use the forceRLE flag to force not using the mask blitter. Also, when the path is a simple // rect, preparing a mask and blitting it might have too much overhead. Hence we'll use // blitFatAntiRect to avoid the mask and its overhead. - if (MaskAdditiveBlitter::canHandleRect(ir) && !isInverse && !forceRLE) { + if (MaskAdditiveBlitter::CanHandleRect(ir) && !isInverse && !forceRLE) { // blitFatAntiRect is slower than the normal AAA flow without MaskAdditiveBlitter. // Hence only tryBlitFatAntiRect when MaskAdditiveBlitter would have been used. if (!TryBlitFatAntiRect(blitter, path, clipBounds)) { MaskAdditiveBlitter additiveBlitter(blitter, ir, clipBounds, isInverse); - aaa_fill_path(path, clipBounds, &additiveBlitter, ir.fTop, ir.fBottom, - containedInClip, true, forceRLE); + aaa_fill_path(path, + clipBounds, + &additiveBlitter, + ir.fTop, + ir.fBottom, + containedInClip, + true, + forceRLE); } } else if (!isInverse && path.isConvex()) { // If the filling area is convex (i.e., path.isConvex && !isInverse), our simpler @@ -1710,15 +1943,27 @@ void SkScan::AAAFillPath(const SkPath& path, SkBlitter* blitter, const SkIRect& // SafeRLEAdditiveBlitter (which is slow due to clamping). The basic RLE blitter // RunBasedAdditiveBlitter would suffice. RunBasedAdditiveBlitter additiveBlitter(blitter, ir, clipBounds, isInverse); - aaa_fill_path(path, clipBounds, &additiveBlitter, ir.fTop, ir.fBottom, - containedInClip, false, forceRLE); + aaa_fill_path(path, + clipBounds, + &additiveBlitter, + ir.fTop, + ir.fBottom, + containedInClip, + false, + forceRLE); } else { // If the filling area might not be convex, the more involved aaa_walk_edges would // be called and we have to clamp the alpha downto 255. The SafeRLEAdditiveBlitter // does that at a cost of performance. SafeRLEAdditiveBlitter additiveBlitter(blitter, ir, clipBounds, isInverse); - aaa_fill_path(path, clipBounds, &additiveBlitter, ir.fTop, ir.fBottom, - containedInClip, false, forceRLE); + aaa_fill_path(path, + clipBounds, + &additiveBlitter, + ir.fTop, + ir.fBottom, + containedInClip, + false, + forceRLE); } } #endif //defined(SK_DISABLE_AAA)