implement region-ops
git-svn-id: http://skia.googlecode.com/svn/trunk@2436 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
07faed1102
commit
1c04bf97b6
@ -57,22 +57,19 @@ public:
|
||||
this->setBGColor(0xFFDDDDDD);
|
||||
}
|
||||
|
||||
void build_rgn(SkAAClip* clip, SkRegion::Op op) {
|
||||
clip->setRect(fBase);
|
||||
#if 0
|
||||
SkIRect r = fBase;
|
||||
r.offset(75, 20);
|
||||
rgn->op(r, SkRegion::kUnion_Op);
|
||||
#endif
|
||||
|
||||
static void setAAClip(SkAAClip* clip, const SkIRect& rect) {
|
||||
SkRect r;
|
||||
r.set(fRect);
|
||||
r.set(rect);
|
||||
SkPath path;
|
||||
path.addOval(r);
|
||||
path.addRoundRect(r, SkIntToScalar(5), SkIntToScalar(5));
|
||||
clip->setPath(path);
|
||||
}
|
||||
|
||||
void build_rgn(SkAAClip* clip, SkRegion::Op op) {
|
||||
setAAClip(clip, fBase);
|
||||
|
||||
SkAAClip clip2;
|
||||
clip2.setPath(path);
|
||||
// hack
|
||||
op = SkRegion::kIntersect_Op;
|
||||
setAAClip(&clip2, fRect);
|
||||
clip->op(clip2, op);
|
||||
}
|
||||
|
||||
@ -101,6 +98,17 @@ protected:
|
||||
canvas->drawRect(r, paint);
|
||||
}
|
||||
|
||||
static void outer_frame(SkCanvas* canvas, const SkIRect& rect) {
|
||||
SkRect r;
|
||||
r.set(rect);
|
||||
r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
|
||||
|
||||
SkPaint paint;
|
||||
paint.setColor(SK_ColorGRAY);
|
||||
paint.setStyle(SkPaint::kStroke_Style);
|
||||
canvas->drawRect(r, paint);
|
||||
}
|
||||
|
||||
void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
|
||||
SkAAClip clip;
|
||||
|
||||
@ -115,6 +123,11 @@ protected:
|
||||
paint.setStyle(SkPaint::kStroke_Style);
|
||||
paint.setColor(color);
|
||||
paint_rgn(canvas, clip, paint);
|
||||
|
||||
SkAAClip clip2(clip);
|
||||
clip2.offset(0, 80);
|
||||
outer_frame(canvas, clip2.getBounds());
|
||||
paint_rgn(canvas, clip2, paint);
|
||||
}
|
||||
|
||||
virtual void onDrawContent(SkCanvas* canvas) {
|
||||
@ -135,10 +148,6 @@ protected:
|
||||
textPaint.setTextSize(SK_Scalar1*24);
|
||||
|
||||
this->drawOrig(canvas, false);
|
||||
canvas->save();
|
||||
canvas->translate(SkIntToScalar(200), 0);
|
||||
this->drawRgnOped(canvas, SkRegion::kUnion_Op, SK_ColorBLACK);
|
||||
canvas->restore();
|
||||
|
||||
canvas->translate(0, SkIntToScalar(200));
|
||||
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "SkScan.h"
|
||||
#include "SkThread.h"
|
||||
|
||||
#define kMaxInt32 0x7FFFFFFF
|
||||
|
||||
static inline bool x_in_rect(int x, const SkIRect& rect) {
|
||||
return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
|
||||
}
|
||||
@ -62,9 +64,9 @@ public:
|
||||
Iter(const SkAAClip&);
|
||||
|
||||
bool done() const { return fDone; }
|
||||
int top() const { SkASSERT(!fDone); return fTop; }
|
||||
int bottom() const { SkASSERT(!fDone); return fBottom; }
|
||||
const uint8_t* data() const { SkASSERT(!fDone); return fData; }
|
||||
int top() const { return fTop; }
|
||||
int bottom() const { return fBottom; }
|
||||
const uint8_t* data() const { return fData; }
|
||||
void next();
|
||||
|
||||
private:
|
||||
@ -79,6 +81,8 @@ private:
|
||||
SkAAClip::Iter::Iter(const SkAAClip& clip) {
|
||||
if (clip.isEmpty()) {
|
||||
fDone = true;
|
||||
fTop = fBottom = clip.fBounds.fBottom;
|
||||
fData = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -94,18 +98,21 @@ SkAAClip::Iter::Iter(const SkAAClip& clip) {
|
||||
}
|
||||
|
||||
void SkAAClip::Iter::next() {
|
||||
SkASSERT(!fDone);
|
||||
if (!fDone) {
|
||||
const YOffset* prev = fCurrYOff;
|
||||
const YOffset* curr = prev + 1;
|
||||
SkASSERT(curr <= fStopYOff);
|
||||
|
||||
const YOffset* prev = fCurrYOff;
|
||||
const YOffset* curr = prev + 1;
|
||||
|
||||
if (curr >= fStopYOff) {
|
||||
fDone = true;
|
||||
} else {
|
||||
fTop = fBottom;
|
||||
fBottom += curr->fY - prev->fY;
|
||||
fData += curr->fOffset - prev->fOffset;
|
||||
fCurrYOff = curr;
|
||||
if (curr >= fStopYOff) {
|
||||
fDone = true;
|
||||
fBottom = kMaxInt32;
|
||||
fData = NULL;
|
||||
} else {
|
||||
fBottom += curr->fY - prev->fY;
|
||||
fData += curr->fOffset - prev->fOffset;
|
||||
fCurrYOff = curr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,7 +402,7 @@ public:
|
||||
SkDebugf("\n");
|
||||
}
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
int prevY = -1;
|
||||
for (y = 0; y < fRows.count(); ++y) {
|
||||
const Row& row = fRows[y];
|
||||
@ -635,25 +642,36 @@ public:
|
||||
RowIter(const uint8_t* row, const SkIRect& bounds) {
|
||||
fRow = row;
|
||||
fLeft = bounds.fLeft;
|
||||
fRight = bounds.fLeft + row[0];
|
||||
fBoundsRight = bounds.fRight;
|
||||
SkASSERT(fRight <= fBoundsRight);
|
||||
fDone = false;
|
||||
if (row) {
|
||||
fRight = bounds.fLeft + row[0];
|
||||
SkASSERT(fRight <= fBoundsRight);
|
||||
fAlpha = row[1];
|
||||
fDone = false;
|
||||
} else {
|
||||
fDone = true;
|
||||
fRight = kMaxInt32;
|
||||
fAlpha = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool done() const { return fDone; }
|
||||
int left() const { SkASSERT(!done()); return fLeft; }
|
||||
int right() const { SkASSERT(!done()); return fRight; }
|
||||
U8CPU alpha() const { SkASSERT(!done()); return fRow[1]; }
|
||||
int left() const { return fLeft; }
|
||||
int right() const { return fRight; }
|
||||
U8CPU alpha() const { return fAlpha; }
|
||||
void next() {
|
||||
SkASSERT(!done());
|
||||
if (fRight == fBoundsRight) {
|
||||
fDone = true;
|
||||
} else {
|
||||
fRow += 2;
|
||||
if (!fDone) {
|
||||
fLeft = fRight;
|
||||
fRight += fRow[0];
|
||||
SkASSERT(fRight <= fBoundsRight);
|
||||
if (fRight == fBoundsRight) {
|
||||
fDone = true;
|
||||
fRight = kMaxInt32;
|
||||
fAlpha = 0;
|
||||
} else {
|
||||
fRow += 2;
|
||||
fRight += fRow[0];
|
||||
fAlpha = fRow[1];
|
||||
SkASSERT(fRight <= fBoundsRight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -663,99 +681,94 @@ private:
|
||||
int fRight;
|
||||
int fBoundsRight;
|
||||
bool fDone;
|
||||
uint8_t fAlpha;
|
||||
};
|
||||
|
||||
static void adjust_row(RowIter& iter, int& leftA, int& riteA,
|
||||
int left, int rite) {
|
||||
if (leftA == left) {
|
||||
leftA = rite;
|
||||
if (leftA == riteA) {
|
||||
if (iter.done()) {
|
||||
leftA = 0x7FFFFFFF;
|
||||
riteA = 0x7FFFFFFF;
|
||||
} else {
|
||||
iter.next();
|
||||
leftA = iter.left();
|
||||
riteA = iter.right();
|
||||
}
|
||||
}
|
||||
static void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) {
|
||||
if (rite == riteA) {
|
||||
iter.next();
|
||||
leftA = iter.left();
|
||||
riteA = iter.right();
|
||||
}
|
||||
}
|
||||
|
||||
static bool intersect(int& min, int& max, int boundsMin, int boundsMax) {
|
||||
SkASSERT(min < max);
|
||||
SkASSERT(boundsMin < boundsMax);
|
||||
if (min >= boundsMax || max <= boundsMin) {
|
||||
return false;
|
||||
}
|
||||
if (min < boundsMin) {
|
||||
min = boundsMin;
|
||||
}
|
||||
if (max > boundsMax) {
|
||||
max = boundsMax;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void operatorX(SkAAClip::Builder& builder, int lastY,
|
||||
RowIter& iterA, RowIter& iterB,
|
||||
AlphaProc proc, const SkIRect& bounds) {
|
||||
SkASSERT(!iterA.done());
|
||||
int leftA = iterA.left();
|
||||
int riteA = iterA.right();
|
||||
SkASSERT(!iterB.done());
|
||||
int leftB = iterB.left();
|
||||
int riteB = iterB.right();
|
||||
|
||||
for (;;) {
|
||||
int prevRite = bounds.fLeft;
|
||||
|
||||
do {
|
||||
U8CPU alphaA = 0;
|
||||
U8CPU alphaB = 0;
|
||||
|
||||
int left, rite;
|
||||
if (riteA <= leftB) { // all A
|
||||
|
||||
if (leftA < leftB) {
|
||||
left = leftA;
|
||||
rite = riteA;
|
||||
alphaA = iterA.alpha();
|
||||
} else if (riteB <= leftA) { // all B
|
||||
left = leftB;
|
||||
rite = riteB;
|
||||
alphaB = iterB.alpha();
|
||||
} else {
|
||||
// some overlap
|
||||
alphaA = iterA.alpha();
|
||||
alphaB = iterB.alpha();
|
||||
if (leftA <= leftB) {
|
||||
left = leftA;
|
||||
if (leftA == leftB) {
|
||||
rite = SkMin32(riteA, riteB);
|
||||
} else{
|
||||
rite = leftB;
|
||||
}
|
||||
} else { // leftB < leftA
|
||||
left = leftB;
|
||||
rite = leftA;
|
||||
if (riteA <= leftB) {
|
||||
rite = riteA;
|
||||
} else {
|
||||
rite = leftA = leftB;
|
||||
}
|
||||
} else if (leftB < leftA) {
|
||||
left = leftB;
|
||||
alphaB = iterB.alpha();
|
||||
if (riteB <= leftA) {
|
||||
rite = riteB;
|
||||
} else {
|
||||
rite = leftB = leftA;
|
||||
}
|
||||
} else {
|
||||
left = leftA; // or leftB, since leftA == leftB
|
||||
rite = leftA = leftB = SkMin32(riteA, riteB);
|
||||
alphaA = iterA.alpha();
|
||||
alphaB = iterB.alpha();
|
||||
}
|
||||
|
||||
if (left >= bounds.fRight) {
|
||||
break;
|
||||
}
|
||||
|
||||
SkASSERT(rite <= bounds.fRight);
|
||||
if (left >= bounds.fLeft) {
|
||||
SkASSERT(rite > left);
|
||||
builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left);
|
||||
} else {
|
||||
SkASSERT(rite <= bounds.fLeft);
|
||||
prevRite = rite;
|
||||
}
|
||||
|
||||
if (rite == bounds.fRight) {
|
||||
break;
|
||||
}
|
||||
|
||||
adjust_row(iterA, leftA, riteA, left, rite);
|
||||
adjust_row(iterB, leftB, riteB, left, rite);
|
||||
|
||||
adjust_row(iterA, leftA, riteA, rite);
|
||||
adjust_row(iterB, leftB, riteB, rite);
|
||||
} while (!iterA.done() || !iterB.done());
|
||||
|
||||
if (prevRite < bounds.fRight) {
|
||||
builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite);
|
||||
}
|
||||
}
|
||||
|
||||
static void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA,
|
||||
int top, int bot) {
|
||||
if (topA == top) {
|
||||
topA = bot;
|
||||
if (topA == botA) {
|
||||
if (iter.done()) {
|
||||
topA = 0x7FFFFFFF;
|
||||
botA = 0x7FFFFFFF;
|
||||
} else {
|
||||
iter.next();
|
||||
topA = iter.top();
|
||||
botA = iter.bottom();
|
||||
}
|
||||
}
|
||||
static void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) {
|
||||
if (bot == botA) {
|
||||
iter.next();
|
||||
topA = botA;
|
||||
SkASSERT(botA == iter.top());
|
||||
botA = iter.bottom();
|
||||
}
|
||||
}
|
||||
|
||||
@ -774,61 +787,50 @@ static void operateY(SkAAClip::Builder& builder, const SkAAClip& A,
|
||||
int topB = iterB.top();
|
||||
int botB = iterB.bottom();
|
||||
|
||||
for (;;) {
|
||||
SkASSERT(topA < botA);
|
||||
SkASSERT(topB < botB);
|
||||
|
||||
const uint8_t* rowA = gEmptyRow;
|
||||
const uint8_t* rowB = gEmptyRow;
|
||||
|
||||
// find the vertical
|
||||
do {
|
||||
const uint8_t* rowA = NULL;
|
||||
const uint8_t* rowB = NULL;
|
||||
int top, bot;
|
||||
if (botA <= topB) { // all A
|
||||
|
||||
if (topA < topB) {
|
||||
top = topA;
|
||||
bot = botA;
|
||||
rowA = iterA.data();
|
||||
} else if (botB <= topA) { // all B
|
||||
top = topB;
|
||||
bot = botB;
|
||||
rowB = iterB.data();
|
||||
} else {
|
||||
// some overlap
|
||||
rowA = iterA.data();
|
||||
rowB = iterB.data();
|
||||
if (topA <= topB) {
|
||||
top = topA;
|
||||
if (topA == topB) {
|
||||
bot = SkMin32(botA, botB);
|
||||
} else{
|
||||
bot = topB;
|
||||
}
|
||||
} else { // topB < topA
|
||||
top = topB;
|
||||
bot = topA;
|
||||
if (botA <= topB) {
|
||||
bot = botA;
|
||||
} else {
|
||||
bot = topA = topB;
|
||||
}
|
||||
|
||||
} else if (topB < topA) {
|
||||
top = topB;
|
||||
rowB = iterB.data();
|
||||
if (botB <= topA) {
|
||||
bot = botB;
|
||||
} else {
|
||||
bot = topB = topA;
|
||||
}
|
||||
} else {
|
||||
top = topA; // or topB, since topA == topB
|
||||
bot = topA = topB = SkMin32(botA, botB);
|
||||
rowA = iterA.data();
|
||||
rowB = iterB.data();
|
||||
}
|
||||
|
||||
if (top >= bounds.fBottom) {
|
||||
break;
|
||||
}
|
||||
|
||||
SkASSERT(bot <= bounds.fBottom);
|
||||
if (top >= bounds.fTop) {
|
||||
RowIter rowIterA(rowA, A.getBounds());
|
||||
RowIter rowIterB(rowB, B.getBounds());
|
||||
if (!rowA && !rowB) {
|
||||
builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width());
|
||||
} else if (top >= bounds.fTop) {
|
||||
SkASSERT(bot <= bounds.fBottom);
|
||||
RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds);
|
||||
RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds);
|
||||
operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds);
|
||||
} else {
|
||||
SkASSERT(bot <= bounds.fTop);
|
||||
}
|
||||
|
||||
if (bot == bounds.fBottom) {
|
||||
break;
|
||||
}
|
||||
|
||||
adjust_iter(iterA, topA, botA, top, bot);
|
||||
adjust_iter(iterB, topB, botB, top, bot);
|
||||
}
|
||||
|
||||
adjust_iter(iterA, topA, botA, bot);
|
||||
adjust_iter(iterB, topB, botB, bot);
|
||||
} while (!iterA.done() || !iterB.done());
|
||||
}
|
||||
|
||||
bool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig,
|
||||
@ -884,7 +886,6 @@ bool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig,
|
||||
return !this->isEmpty();
|
||||
}
|
||||
|
||||
SkASSERT(SkIRect::Intersects(clipA->fBounds, clipB->fBounds));
|
||||
SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds));
|
||||
SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds));
|
||||
|
||||
@ -1078,6 +1079,32 @@ const SkBitmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool SkAAClip::offset(int dx, int dy) {
|
||||
if (this->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fBounds.offset(dx, dy);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkAAClip::offset(int dx, int dy, SkAAClip* dst) const {
|
||||
if (this == dst) {
|
||||
return dst->offset(dx, dy);
|
||||
}
|
||||
|
||||
dst->setEmpty();
|
||||
if (this->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sk_atomic_inc(&fRunHead->fRefCnt);
|
||||
dst->fRunHead = fRunHead;
|
||||
dst->fBounds = fBounds;
|
||||
dst->fBounds.offset(dx, dy);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void expand_row_to_mask(uint8_t* SK_RESTRICT mask,
|
||||
const uint8_t* SK_RESTRICT row,
|
||||
int width) {
|
||||
|
@ -42,6 +42,9 @@ public:
|
||||
bool op(const SkRect&, SkRegion::Op);
|
||||
bool op(const SkAAClip&, SkRegion::Op);
|
||||
|
||||
bool offset(int dx, int dy);
|
||||
bool offset(int dx, int dy, SkAAClip* dst) const;
|
||||
|
||||
/**
|
||||
* Allocates a mask the size of the aaclip, and expands its data into
|
||||
* the mask, using kA8_Format
|
||||
|
Loading…
Reference in New Issue
Block a user