From b03fe429e83d7a32b05a5ee8423e4f62ba6380fa Mon Sep 17 00:00:00 2001 From: "reed@google.com" Date: Thu, 25 Oct 2012 17:37:03 +0000 Subject: [PATCH] use subclasses instead of function-ptrs for hairline specializations. 1. enables easy grouping of procs, e.g. cap -vs- line 2. easy to extend for more shared state (e.g. gamma table, etc.) git-svn-id: http://skia.googlecode.com/svn/trunk@6119 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/core/SkScan_Antihair.cpp | 295 ++++++++++++++++++++++++++++++------------- 1 file changed, 208 insertions(+), 87 deletions(-) diff --git a/src/core/SkScan_Antihair.cpp b/src/core/SkScan_Antihair.cpp index 92245d4..e133397 100644 --- a/src/core/SkScan_Antihair.cpp +++ b/src/core/SkScan_Antihair.cpp @@ -68,10 +68,10 @@ static inline int SmallDot6Scale(int value, int dot6) { static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, U8CPU alpha) { SkASSERT(count > 0); - + int16_t runs[HLINE_STACK_BUFFER + 1]; uint8_t aa[HLINE_STACK_BUFFER]; - + aa[0] = ApplyGamma(gGammaTable, alpha); do { int n = count; @@ -86,45 +86,82 @@ static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, } while (count > 0); } -static SkFixed hline(int x, int stopx, SkFixed fy, SkFixed /*slope*/, - SkBlitter* blitter, int mod64) { - SkASSERT(x < stopx); - int count = stopx - x; - fy += SK_Fixed1/2; +class SkAntiHairBlitter { +public: + SkAntiHairBlitter() : fBlitter(NULL) {} - int y = fy >> 16; - uint8_t a = (uint8_t)(fy >> 8); + SkBlitter* getBlitter() const { return fBlitter; } - // lower line - unsigned ma = SmallDot6Scale(a, mod64); - if (ma) { - call_hline_blitter(blitter, x, y, count, ma); + void setup(SkBlitter* blitter) { + fBlitter = blitter; } - // upper line - ma = SmallDot6Scale(255 - a, mod64); - if (ma) { - call_hline_blitter(blitter, x, y - 1, count, ma); - } + virtual SkFixed drawCap(int x, SkFixed fy, SkFixed slope, int mod64) = 0; + virtual SkFixed drawLine(int x, int stopx, SkFixed fy, SkFixed slope) = 0; - return fy - SK_Fixed1/2; -} +private: + SkBlitter* fBlitter; +}; -static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, - SkBlitter* blitter, int mod64) { - SkASSERT(x < stopx); - -#ifdef TEST_GAMMA - const uint8_t* gamma = gGammaTable; -#endif - int16_t runs[2]; - uint8_t aa[1]; +class HLine_SkAntiHairBlitter : public SkAntiHairBlitter { +public: + virtual SkFixed drawCap(int x, SkFixed fy, SkFixed slope, int mod64) SK_OVERRIDE { + fy += SK_Fixed1/2; + + int y = fy >> 16; + uint8_t a = (uint8_t)(fy >> 8); + + // lower line + unsigned ma = SmallDot6Scale(a, mod64); + if (ma) { + call_hline_blitter(this->getBlitter(), x, y, 1, ma); + } + + // upper line + ma = SmallDot6Scale(255 - a, mod64); + if (ma) { + call_hline_blitter(this->getBlitter(), x, y - 1, 1, ma); + } + + return fy - SK_Fixed1/2; + } - runs[0] = 1; - runs[1] = 0; + virtual SkFixed drawLine(int x, int stopx, SkFixed fy, + SkFixed slope) SK_OVERRIDE { + SkASSERT(x < stopx); + int count = stopx - x; + fy += SK_Fixed1/2; + + int y = fy >> 16; + uint8_t a = (uint8_t)(fy >> 8); + + // lower line + if (a) { + call_hline_blitter(this->getBlitter(), x, y, count, a); + } + + // upper line + a = 255 - a; + if (a) { + call_hline_blitter(this->getBlitter(), x, y - 1, count, a); + } + + return fy - SK_Fixed1/2; + } +}; + +class Horish_SkAntiHairBlitter : public SkAntiHairBlitter { +public: + virtual SkFixed drawCap(int x, SkFixed fy, SkFixed dy, int mod64) SK_OVERRIDE { + int16_t runs[2]; + uint8_t aa[1]; + + runs[0] = 1; + runs[1] = 0; + + fy += SK_Fixed1/2; + SkBlitter* blitter = this->getBlitter(); - fy += SK_Fixed1/2; - do { int lower_y = fy >> 16; uint8_t a = (uint8_t)(fy >> 8); unsigned ma = SmallDot6Scale(a, mod64); @@ -144,64 +181,140 @@ static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, SkASSERT(runs[1] == 0); } fy += dy; - } while (++x < stopx); - - return fy - SK_Fixed1/2; -} - -static SkFixed vline(int y, int stopy, SkFixed fx, SkFixed /*slope*/, - SkBlitter* blitter, int mod64) { - SkASSERT(y < stopy); - fx += SK_Fixed1/2; - - int x = fx >> 16; - int a = (uint8_t)(fx >> 8); - - unsigned ma = SmallDot6Scale(a, mod64); - if (ma) { - blitter->blitV(x, y, stopy - y, ApplyGamma(gGammaTable, ma)); + + return fy - SK_Fixed1/2; } - ma = SmallDot6Scale(255 - a, mod64); - if (ma) { - blitter->blitV(x - 1, y, stopy - y, ApplyGamma(gGammaTable, ma)); + + virtual SkFixed drawLine(int x, int stopx, SkFixed fy, SkFixed dy) SK_OVERRIDE { + SkASSERT(x < stopx); + + int16_t runs[2]; + uint8_t aa[1]; + + runs[0] = 1; + runs[1] = 0; + + fy += SK_Fixed1/2; + SkBlitter* blitter = this->getBlitter(); + do { + int lower_y = fy >> 16; + uint8_t a = (uint8_t)(fy >> 8); + if (a) { + aa[0] = a; + blitter->blitAntiH(x, lower_y, aa, runs); + // the clipping blitters might edit runs, but should not affect us + SkASSERT(runs[0] == 1); + SkASSERT(runs[1] == 0); + } + a = 255 - a; + if (a) { + aa[0] = a; + blitter->blitAntiH(x, lower_y - 1, aa, runs); + // the clipping blitters might edit runs, but should not affect us + SkASSERT(runs[0] == 1); + SkASSERT(runs[1] == 0); + } + fy += dy; + } while (++x < stopx); + + return fy - SK_Fixed1/2; + } +}; + +class VLine_SkAntiHairBlitter : public SkAntiHairBlitter { +public: + virtual SkFixed drawCap(int y, SkFixed fx, SkFixed dx, int mod64) SK_OVERRIDE { + SkASSERT(0 == dx); + fx += SK_Fixed1/2; + + int x = fx >> 16; + int a = (uint8_t)(fx >> 8); + + unsigned ma = SmallDot6Scale(a, mod64); + if (ma) { + this->getBlitter()->blitV(x, y, 1, ma); + } + ma = SmallDot6Scale(255 - a, mod64); + if (ma) { + this->getBlitter()->blitV(x - 1, y, 1, ma); + } + + return fx - SK_Fixed1/2; } - return fx - SK_Fixed1/2; -} - -static SkFixed vertish(int y, int stopy, SkFixed fx, SkFixed dx, - SkBlitter* blitter, int mod64) { - SkASSERT(y < stopy); -#ifdef TEST_GAMMA - const uint8_t* gamma = gGammaTable; -#endif - int16_t runs[3]; - uint8_t aa[2]; - - runs[0] = 1; - runs[2] = 0; - - fx += SK_Fixed1/2; - do { + virtual SkFixed drawLine(int y, int stopy, SkFixed fx, SkFixed dx) SK_OVERRIDE { + SkASSERT(y < stopy); + SkASSERT(0 == dx); + fx += SK_Fixed1/2; + + int x = fx >> 16; + int a = (uint8_t)(fx >> 8); + + if (a) { + this->getBlitter()->blitV(x, y, stopy - y, a); + } + a = 255 - a; + if (a) { + this->getBlitter()->blitV(x - 1, y, stopy - y, a); + } + + return fx - SK_Fixed1/2; + } +}; + +class Vertish_SkAntiHairBlitter : public SkAntiHairBlitter { +public: + virtual SkFixed drawCap(int y, SkFixed fx, SkFixed dx, int mod64) SK_OVERRIDE { + int16_t runs[3]; + uint8_t aa[2]; + + runs[0] = 1; + runs[2] = 0; + + fx += SK_Fixed1/2; int x = fx >> 16; uint8_t a = (uint8_t)(fx >> 8); - - aa[0] = ApplyGamma(gamma, SmallDot6Scale(255 - a, mod64)); - aa[1] = ApplyGamma(gamma, SmallDot6Scale(a, mod64)); + + aa[0] = SmallDot6Scale(255 - a, mod64); + aa[1] = SmallDot6Scale(a, mod64); // the clippng blitters might overwrite this guy, so we have to reset it each time runs[1] = 1; - blitter->blitAntiH(x - 1, y, aa, runs); + this->getBlitter()->blitAntiH(x - 1, y, aa, runs); // the clipping blitters might edit runs, but should not affect us SkASSERT(runs[0] == 1); SkASSERT(runs[2] == 0); fx += dx; - } while (++y < stopy); - - return fx - SK_Fixed1/2; -} + + return fx - SK_Fixed1/2; + } + + virtual SkFixed drawLine(int y, int stopy, SkFixed fx, SkFixed dx) SK_OVERRIDE { + SkASSERT(y < stopy); + int16_t runs[3]; + uint8_t aa[2]; + + runs[0] = 1; + runs[2] = 0; + + fx += SK_Fixed1/2; + do { + int x = fx >> 16; + uint8_t a = (uint8_t)(fx >> 8); + + aa[0] = 255 - a; + aa[1] = a; + // the clippng blitters might overwrite this guy, so we have to reset it each time + runs[1] = 1; + this->getBlitter()->blitAntiH(x - 1, y, aa, runs); + // the clipping blitters might edit runs, but should not affect us + SkASSERT(runs[0] == 1); + SkASSERT(runs[2] == 0); + fx += dx; + } while (++y < stopy); -typedef SkFixed (*LineProc)(int istart, int istop, SkFixed fstart, - SkFixed slope, SkBlitter*, int); + return fx - SK_Fixed1/2; + } +}; static inline SkFixed fastfixdiv(SkFDot6 a, SkFDot6 b) { SkASSERT((a << 16 >> 16) == a); @@ -268,7 +381,12 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, int scaleStart, scaleStop; int istart, istop; SkFixed fstart, slope; - LineProc proc; + + HLine_SkAntiHairBlitter hline_blitter; + Horish_SkAntiHairBlitter horish_blitter; + VLine_SkAntiHairBlitter vline_blitter; + Vertish_SkAntiHairBlitter vertish_blitter; + SkAntiHairBlitter* hairBlitter = NULL; if (SkAbs32(x1 - x0) > SkAbs32(y1 - y0)) { // mostly horizontal if (x0 > x1) { // we want to go left-to-right @@ -281,12 +399,12 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, fstart = SkFDot6ToFixed(y0); if (y0 == y1) { // completely horizontal, take fast case slope = 0; - proc = hline; + hairBlitter = &hline_blitter; } else { slope = fastfixdiv(y1 - y0, x1 - x0); SkASSERT(slope >= -SK_Fixed1 && slope <= SK_Fixed1); fstart += (slope * (32 - (x0 & 63)) + 32) >> 6; - proc = horish; + hairBlitter = &horish_blitter; } SkASSERT(istop > istart); @@ -351,12 +469,12 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, return; // nothing to do } slope = 0; - proc = vline; + hairBlitter = &vline_blitter; } else { slope = fastfixdiv(x1 - x0, y1 - y0); SkASSERT(slope <= SK_Fixed1 && slope >= -SK_Fixed1); fstart += (slope * (32 - (y0 & 63)) + 32) >> 6; - proc = vertish; + hairBlitter = &vertish_blitter; } SkASSERT(istop > istart); @@ -415,14 +533,17 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, blitter = &rectClipper; } - fstart = proc(istart, istart + 1, fstart, slope, blitter, scaleStart); + SkASSERT(hairBlitter); + hairBlitter->setup(blitter); + + fstart = hairBlitter->drawCap(istart, fstart, slope, scaleStart); istart += 1; int fullSpans = istop - istart - (scaleStop > 0); if (fullSpans > 0) { - fstart = proc(istart, istart + fullSpans, fstart, slope, blitter, 64); + fstart = hairBlitter->drawLine(istart, istart + fullSpans, fstart, slope); } if (scaleStop > 0) { - proc(istop - 1, istop, fstart, slope, blitter, scaleStop); + hairBlitter->drawCap(istop - 1, fstart, slope, scaleStop); } } -- 2.7.4