aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/SkAAClip.cpp38
-rw-r--r--src/core/SkBlitter.cpp20
-rw-r--r--src/core/SkScan_AntiPath.cpp58
3 files changed, 62 insertions, 54 deletions
diff --git a/src/core/SkAAClip.cpp b/src/core/SkAAClip.cpp
index cb49178e35..fd5d8979bd 100644
--- a/src/core/SkAAClip.cpp
+++ b/src/core/SkAAClip.cpp
@@ -930,7 +930,36 @@ public:
SkASSERT(fBounds.contains(x + width - 1, y + height - 1));
this->addRun(x, y, 0xFF, width);
- // we assum the rect must be all we'll see for these scanlines
+ // we assume the rect must be all we'll see for these scanlines
+ // so we ensure our row goes all the way to our right
+ this->flushRowH(fCurrRow);
+
+ y -= fBounds.fTop;
+ SkASSERT(y == fCurrRow->fY);
+ fCurrRow->fY = y + height - 1;
+ }
+
+ void addAntiRectRun(int x, int y, int width, int height,
+ SkAlpha leftAlpha, SkAlpha rightAlpha) {
+ SkASSERT(fBounds.contains(x + width - 1, y + height - 1));
+ SkASSERT(width >= 0);
+
+ // Conceptually we're always adding 3 runs, but we should
+ // merge or omit them if possible.
+ if (leftAlpha == 0xFF) {
+ width++;
+ } else if (leftAlpha > 0) {
+ this->addRun(x++, y, leftAlpha, 1);
+ }
+ if (rightAlpha == 0xFF) {
+ width++;
+ }
+ this->addRun(x, y, 0xFF, width);
+ if (rightAlpha > 0 && rightAlpha < 255) {
+ this->addRun(x + width, y, rightAlpha, 1);
+ }
+
+ // we assume the rect must be all we'll see for these scanlines
// so we ensure our row goes all the way to our right
this->flushRowH(fCurrRow);
@@ -1113,6 +1142,7 @@ public:
}
}
+ // Must evaluate clips in scan-line order, so can't allow blitV()
virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE
{ unexpected(); }
@@ -1121,6 +1151,12 @@ public:
fBuilder->addRectRun(x, y, width, height);
}
+ virtual void blitAntiRect(int x, int y, int width, int height,
+ SkAlpha leftAlpha, SkAlpha rightAlpha) SK_OVERRIDE {
+ this->recordMinY(y);
+ fBuilder->addAntiRectRun(x, y, width, height, leftAlpha, rightAlpha);
+ }
+
virtual void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE
{ unexpected(); }
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
index 307d51b340..17cba4776d 100644
--- a/src/core/SkBlitter.cpp
+++ b/src/core/SkBlitter.cpp
@@ -52,6 +52,16 @@ void SkBlitter::blitRect(int x, int y, int width, int height) {
}
}
+/// Default implementation doesn't check for any easy optimizations
+/// such as alpha == 0 or 255; also uses blitV(), which some subclasses
+/// may not support.
+void SkBlitter::blitAntiRect(int x, int y, int width, int height,
+ SkAlpha leftAlpha, SkAlpha rightAlpha) {
+ this->blitV(x, y, height, leftAlpha);
+ this->blitRect(x + 1, y, width, height);
+ this->blitV(x + width - 1, y, height, rightAlpha);
+}
+
//////////////////////////////////////////////////////////////////////////////
static inline void bits_to_runs(SkBlitter* blitter, int x, int y,
@@ -118,7 +128,8 @@ void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
int rite_mask = 0xFF << (8 - (rite_edge & 7));
int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3);
- // check for empty right mask, so we don't read off the end (or go slower than we need to)
+ // check for empty right mask, so we don't read off the end
+ // (or go slower than we need to)
if (rite_mask == 0) {
SkASSERT(full_runs >= 0);
full_runs -= 1;
@@ -128,8 +139,8 @@ void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
full_runs -= 1;
}
- // back up manually so we can keep in sync with our byte-aligned src
- // have cx reflect our actual starting x-coord
+ // Back up manually so we can keep in sync with our byte-aligned
+ // src; have cx reflect our actual starting x-coord.
cx -= left_edge & 7;
if (full_runs < 0) {
@@ -141,7 +152,8 @@ void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
}
} else {
while (--height >= 0) {
- bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, rite_mask);
+ bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2,
+ rite_mask);
bits += mask_rowBytes;
cy += 1;
}
diff --git a/src/core/SkScan_AntiPath.cpp b/src/core/SkScan_AntiPath.cpp
index bf9866ec97..36005c173a 100644
--- a/src/core/SkScan_AntiPath.cpp
+++ b/src/core/SkScan_AntiPath.cpp
@@ -219,42 +219,7 @@ void SuperBlitter::blitH(int x, int y, int width) {
#endif
}
-static void set_left_rite_runs(SkAlphaRuns& runs, int ileft, U8CPU leftA,
- int n, U8CPU riteA) {
- SkASSERT(leftA <= 0xFF);
- SkASSERT(riteA <= 0xFF);
-
- int16_t* run = runs.fRuns;
- uint8_t* aa = runs.fAlpha;
-
- if (ileft > 0) {
- run[0] = ileft;
- aa[0] = 0;
- run += ileft;
- aa += ileft;
- }
-
- SkASSERT(leftA < 0xFF);
- if (leftA > 0) {
- *run++ = 1;
- *aa++ = leftA;
- }
-
- if (n > 0) {
- run[0] = n;
- aa[0] = 0xFF;
- run += n;
- aa += n;
- }
-
- SkASSERT(riteA < 0xFF);
- if (riteA > 0) {
- *run++ = 1;
- *aa++ = riteA;
- }
- run[0] = 0;
-}
-
+// All parameters are in supersampled space.
void SuperBlitter::blitRect(int x, int y, int width, int height) {
SkASSERT(width > 0);
SkASSERT(height > 0);
@@ -275,6 +240,7 @@ void SuperBlitter::blitRect(int x, int y, int width, int height) {
int stop_y = (y + height) >> SHIFT;
int count = stop_y - start_y;
if (count > 0) {
+
y += count << SHIFT;
height -= count << SHIFT;
@@ -318,19 +284,9 @@ void SuperBlitter::blitRect(int x, int y, int width, int height) {
const int coverageR = coverage_to_alpha(xrite) << SHIFT;
SkASSERT(n + (coverageR != 0) <= fWidth);
- for (int i = start_y; i < stop_y; ++i) {
- // note: we should only need to call set_left_rite once, but
- // our clipping blitters sometimes modify runs/alpha in-place,
- // so for now we reset fRuns each time :(
- //
- // TODO:
- // - don't modify in-place, or at least tell us when you're going to
- // - pass height down to blitAntiH (blitAntiHV) so that aaclip and
- // other can take advantage of the vertical-repeat explicitly
- //
- set_left_rite_runs(fRuns, ileft, coverageL, n, coverageR);
- fRealBlitter->blitAntiH(fLeft, i, fRuns.fAlpha, fRuns.fRuns);
- }
+ fRealBlitter->blitAntiRect(ileft + fLeft, start_y, n, count,
+ coverageL > 0 ? coverageL : 255,
+ coverageR > 0 ? coverageR : 255);
// preamble for our next call to blitH()
fCurrIY = stop_y - 1;
@@ -360,6 +316,10 @@ public:
virtual void blitH(int x, int y, int width) SK_OVERRIDE;
+ // TODO: blitAntiRect() if we ever have performance problems -
+ // but the gains aren't expected to be nearly as large as for
+ // SuperBlitter.
+
static bool CanHandleRect(const SkIRect& bounds) {
#ifdef FORCE_RLE
return false;