fix winding bug in lineclipper
expose path.dump() all the time UP arrow now toggles a grid of clip rects in sample app git-svn-id: http://skia.googlecode.com/svn/trunk@443 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
90209caa68
commit
e522ca5d5f
@ -547,11 +547,8 @@ public:
|
|||||||
Verb autoClose(SkPoint pts[2]);
|
Verb autoClose(SkPoint pts[2]);
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef SK_DEBUG
|
|
||||||
/** @cond UNIT_TEST */
|
|
||||||
void dump(bool forceClose, const char title[] = NULL) const;
|
void dump(bool forceClose, const char title[] = NULL) const;
|
||||||
/** @endcond */
|
void dump() const;
|
||||||
#endif
|
|
||||||
|
|
||||||
void flatten(SkFlattenableWriteBuffer&) const;
|
void flatten(SkFlattenableWriteBuffer&) const;
|
||||||
void unflatten(SkFlattenableReadBuffer&);
|
void unflatten(SkFlattenableReadBuffer&);
|
||||||
|
@ -96,7 +96,8 @@ public:
|
|||||||
void offset(SkScalar dx, SkScalar dy);
|
void offset(SkScalar dx, SkScalar dy);
|
||||||
|
|
||||||
/** Call this to have the view draw into the specified canvas. */
|
/** Call this to have the view draw into the specified canvas. */
|
||||||
void draw(SkCanvas* canvas);
|
virtual void draw(SkCanvas* canvas);
|
||||||
|
|
||||||
/** Call this to invalidate part of all of a view, requesting that the view's
|
/** Call this to invalidate part of all of a view, requesting that the view's
|
||||||
draw method be called. The rectangle parameter specifies the part of the view
|
draw method be called. The rectangle parameter specifies the part of the view
|
||||||
that should be redrawn. If it is null, it specifies the entire view bounds.
|
that should be redrawn. If it is null, it specifies the entire view bounds.
|
||||||
|
@ -129,6 +129,8 @@ public:
|
|||||||
SampleWindow(void* hwnd);
|
SampleWindow(void* hwnd);
|
||||||
virtual ~SampleWindow();
|
virtual ~SampleWindow();
|
||||||
|
|
||||||
|
virtual void draw(SkCanvas* canvas);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void onDraw(SkCanvas* canvas);
|
virtual void onDraw(SkCanvas* canvas);
|
||||||
virtual bool onHandleKey(SkKey key);
|
virtual bool onHandleKey(SkKey key);
|
||||||
@ -167,6 +169,7 @@ private:
|
|||||||
CanvasType fCanvasType;
|
CanvasType fCanvasType;
|
||||||
|
|
||||||
bool fUseClip;
|
bool fUseClip;
|
||||||
|
bool fNClip;
|
||||||
bool fRepeatDrawing;
|
bool fRepeatDrawing;
|
||||||
bool fAnimating;
|
bool fAnimating;
|
||||||
bool fRotate;
|
bool fRotate;
|
||||||
@ -210,6 +213,7 @@ SampleWindow::SampleWindow(void* hwnd) : INHERITED(hwnd) {
|
|||||||
|
|
||||||
fCanvasType = kRaster_CanvasType;
|
fCanvasType = kRaster_CanvasType;
|
||||||
fUseClip = false;
|
fUseClip = false;
|
||||||
|
fNClip = false;
|
||||||
fRepeatDrawing = false;
|
fRepeatDrawing = false;
|
||||||
fAnimating = false;
|
fAnimating = false;
|
||||||
fRotate = false;
|
fRotate = false;
|
||||||
@ -237,6 +241,33 @@ SampleWindow::~SampleWindow() {
|
|||||||
delete fGLCanvas;
|
delete fGLCanvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define XCLIP_N 4
|
||||||
|
#define YCLIP_N 1
|
||||||
|
|
||||||
|
void SampleWindow::draw(SkCanvas* canvas) {
|
||||||
|
if (fNClip) {
|
||||||
|
// this->INHERITED::draw(canvas);
|
||||||
|
// SkBitmap orig = capture_bitmap(canvas);
|
||||||
|
|
||||||
|
const SkScalar w = this->width();
|
||||||
|
const SkScalar h = this->height();
|
||||||
|
const SkScalar cw = w / XCLIP_N;
|
||||||
|
const SkScalar ch = h / YCLIP_N;
|
||||||
|
for (int y = 0; y < YCLIP_N; y++) {
|
||||||
|
for (int x = 0; x < XCLIP_N; x++) {
|
||||||
|
SkAutoCanvasRestore acr(canvas, true);
|
||||||
|
SkRect r = {
|
||||||
|
x * cw, y * ch, (x + 1) * cw, (y + 1) * ch
|
||||||
|
};
|
||||||
|
canvas->clipRect(r);
|
||||||
|
this->INHERITED::draw(canvas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this->INHERITED::draw(canvas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SampleWindow::onDraw(SkCanvas* canvas) {
|
void SampleWindow::onDraw(SkCanvas* canvas) {
|
||||||
if (fRepeatDrawing) {
|
if (fRepeatDrawing) {
|
||||||
this->inval(NULL);
|
this->inval(NULL);
|
||||||
@ -511,7 +542,7 @@ bool SampleWindow::onHandleKey(SkKey key) {
|
|||||||
this->inval(NULL);
|
this->inval(NULL);
|
||||||
return true;
|
return true;
|
||||||
case kUp_SkKey:
|
case kUp_SkKey:
|
||||||
fUseClip = !fUseClip;
|
fNClip = !fNClip;
|
||||||
this->updateTitle();
|
this->updateTitle();
|
||||||
this->inval(NULL);
|
this->inval(NULL);
|
||||||
return true;
|
return true;
|
||||||
@ -604,7 +635,9 @@ void SampleWindow::updateTitle() {
|
|||||||
if (fRotate) {
|
if (fRotate) {
|
||||||
title.prepend("<R> ");
|
title.prepend("<R> ");
|
||||||
}
|
}
|
||||||
|
if (fNClip) {
|
||||||
|
title.prepend("<C> ");
|
||||||
|
}
|
||||||
this->setTitle(title.c_str());
|
this->setTitle(title.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,21 +124,26 @@ int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip,
|
|||||||
SkPoint resultStorage[kMaxPoints];
|
SkPoint resultStorage[kMaxPoints];
|
||||||
SkPoint* result; // points to our results, either tmp or resultStorage
|
SkPoint* result; // points to our results, either tmp or resultStorage
|
||||||
int lineCount = 1;
|
int lineCount = 1;
|
||||||
|
bool reverse;
|
||||||
|
|
||||||
if (pts[0].fX < pts[1].fX) {
|
if (pts[0].fX < pts[1].fX) {
|
||||||
index0 = 0;
|
index0 = 0;
|
||||||
index1 = 1;
|
index1 = 1;
|
||||||
|
reverse = false;
|
||||||
} else {
|
} else {
|
||||||
index0 = 1;
|
index0 = 1;
|
||||||
index1 = 0;
|
index1 = 0;
|
||||||
|
reverse = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp[index1].fX <= clip.fLeft) { // wholly to the left
|
if (tmp[index1].fX <= clip.fLeft) { // wholly to the left
|
||||||
tmp[0].fX = tmp[1].fX = clip.fLeft;
|
tmp[0].fX = tmp[1].fX = clip.fLeft;
|
||||||
result = tmp;
|
result = tmp;
|
||||||
|
reverse = false;
|
||||||
} else if (tmp[index0].fX >= clip.fRight) { // wholly to the right
|
} else if (tmp[index0].fX >= clip.fRight) { // wholly to the right
|
||||||
tmp[0].fX = tmp[1].fX = clip.fRight;
|
tmp[0].fX = tmp[1].fX = clip.fRight;
|
||||||
result = tmp;
|
result = tmp;
|
||||||
|
reverse = false;
|
||||||
} else {
|
} else {
|
||||||
result = resultStorage;
|
result = resultStorage;
|
||||||
SkPoint* r = result;
|
SkPoint* r = result;
|
||||||
@ -164,7 +169,7 @@ int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now copy the results into the caller's lines[] parameter
|
// Now copy the results into the caller's lines[] parameter
|
||||||
if (0 == index1) {
|
if (reverse) {
|
||||||
// copy the pts in reverse order to maintain winding order
|
// copy the pts in reverse order to maintain winding order
|
||||||
for (int i = 0; i <= lineCount; i++) {
|
for (int i = 0; i <= lineCount; i++) {
|
||||||
lines[lineCount - i] = result[i];
|
lines[lineCount - i] = result[i];
|
||||||
|
@ -1222,30 +1222,6 @@ void SkPath::unflatten(SkFlattenableReadBuffer& buffer) {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifdef SK_DEBUG
|
|
||||||
|
|
||||||
void SkPath::validate() const {
|
|
||||||
SkASSERT(this != NULL);
|
|
||||||
SkASSERT((fFillType & ~3) == 0);
|
|
||||||
fPts.validate();
|
|
||||||
fVerbs.validate();
|
|
||||||
|
|
||||||
if (!fBoundsIsDirty) {
|
|
||||||
SkRect bounds;
|
|
||||||
compute_pt_bounds(&bounds, fPts);
|
|
||||||
if (fPts.count() <= 1) {
|
|
||||||
// if we're empty, fBounds may be empty but translated, so we can't
|
|
||||||
// necessarily compare to bounds directly
|
|
||||||
// try path.addOval(2, 2, 2, 2) which is empty, but the bounds will
|
|
||||||
// be [2, 2, 2, 2]
|
|
||||||
SkASSERT(bounds.isEmpty());
|
|
||||||
SkASSERT(fBounds.isEmpty());
|
|
||||||
} else {
|
|
||||||
fBounds.contains(bounds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkPath::dump(bool forceClose, const char title[]) const {
|
void SkPath::dump(bool forceClose, const char title[]) const {
|
||||||
Iter iter(*this, forceClose);
|
Iter iter(*this, forceClose);
|
||||||
SkPoint pts[4];
|
SkPoint pts[4];
|
||||||
@ -1306,4 +1282,31 @@ void SkPath::dump(bool forceClose, const char title[]) const {
|
|||||||
SkDebugf("path: done %s\n", title ? title : "");
|
SkDebugf("path: done %s\n", title ? title : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkPath::dump() const {
|
||||||
|
this->dump(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SK_DEBUG
|
||||||
|
void SkPath::validate() const {
|
||||||
|
SkASSERT(this != NULL);
|
||||||
|
SkASSERT((fFillType & ~3) == 0);
|
||||||
|
fPts.validate();
|
||||||
|
fVerbs.validate();
|
||||||
|
|
||||||
|
if (!fBoundsIsDirty) {
|
||||||
|
SkRect bounds;
|
||||||
|
compute_pt_bounds(&bounds, fPts);
|
||||||
|
if (fPts.count() <= 1) {
|
||||||
|
// if we're empty, fBounds may be empty but translated, so we can't
|
||||||
|
// necessarily compare to bounds directly
|
||||||
|
// try path.addOval(2, 2, 2, 2) which is empty, but the bounds will
|
||||||
|
// be [2, 2, 2, 2]
|
||||||
|
SkASSERT(bounds.isEmpty());
|
||||||
|
SkASSERT(fBounds.isEmpty());
|
||||||
|
} else {
|
||||||
|
fBounds.contains(bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user