aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkScan_Antihair.cpp
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-25 17:37:03 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-25 17:37:03 +0000
commitb03fe429e83d7a32b05a5ee8423e4f62ba6380fa (patch)
treea47b7dcc19407bd795e4dcfde1b1cbf696ece011 /src/core/SkScan_Antihair.cpp
parent1ca015bd5911987ab10fa81f168a5cf3b582f2dd (diff)
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
Diffstat (limited to 'src/core/SkScan_Antihair.cpp')
-rw-r--r--src/core/SkScan_Antihair.cpp295
1 files changed, 208 insertions, 87 deletions
diff --git a/src/core/SkScan_Antihair.cpp b/src/core/SkScan_Antihair.cpp
index 92245d4f33..e133397088 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);
}
}