increase intermediate precision when chopping lines. This avoids returning a
computed value that is accidentally outside of the original range. git-svn-id: http://skia.googlecode.com/svn/trunk@971 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
918261018f
commit
160f2c0e17
@ -6,8 +6,19 @@ static SkScalar sect_with_horizontal(const SkPoint src[2], SkScalar Y) {
|
||||
if (SkScalarNearlyZero(dy)) {
|
||||
return SkScalarAve(src[0].fX, src[1].fX);
|
||||
} else {
|
||||
#ifdef SK_SCALAR_IS_FLOAT
|
||||
// need the extra precision so we don't compute a value that exceeds
|
||||
// our original limits
|
||||
double X0 = src[0].fX;
|
||||
double Y0 = src[0].fY;
|
||||
double X1 = src[1].fX;
|
||||
double Y1 = src[1].fY;
|
||||
double result = X0 + ((double)Y - Y0) * (X1 - X0) / (Y1 - Y0);
|
||||
return (float)result;
|
||||
#else
|
||||
return src[0].fX + SkScalarMulDiv(Y - src[0].fY, src[1].fX - src[0].fX,
|
||||
dy);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,8 +28,19 @@ static SkScalar sect_with_vertical(const SkPoint src[2], SkScalar X) {
|
||||
if (SkScalarNearlyZero(dx)) {
|
||||
return SkScalarAve(src[0].fY, src[1].fY);
|
||||
} else {
|
||||
#ifdef SK_SCALAR_IS_FLOAT
|
||||
// need the extra precision so we don't compute a value that exceeds
|
||||
// our original limits
|
||||
double X0 = src[0].fX;
|
||||
double Y0 = src[0].fY;
|
||||
double X1 = src[1].fX;
|
||||
double Y1 = src[1].fY;
|
||||
double result = Y0 + ((double)X - X0) * (Y1 - Y0) / (X1 - X0);
|
||||
return (float)result;
|
||||
#else
|
||||
return src[0].fY + SkScalarMulDiv(X - src[0].fX, src[1].fY - src[0].fY,
|
||||
dx);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,6 +128,19 @@ bool SkLineClipper::IntersectLine(const SkPoint src[2], const SkRect& clip,
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
// return value between the two limits, where the limits are either ascending
|
||||
// or descending.
|
||||
static bool is_between_unsorted(SkScalar value,
|
||||
SkScalar limit0, SkScalar limit1) {
|
||||
if (limit0 < limit1) {
|
||||
return limit0 <= value && value <= limit1;
|
||||
} else {
|
||||
return limit1 <= value && value <= limit0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip,
|
||||
SkPoint lines[]) {
|
||||
int index0, index1;
|
||||
@ -135,9 +170,11 @@ int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip,
|
||||
// now compute intersections
|
||||
if (pts[index0].fY < clip.fTop) {
|
||||
tmp[index0].set(sect_with_horizontal(pts, clip.fTop), clip.fTop);
|
||||
SkASSERT(is_between_unsorted(tmp[index0].fX, pts[0].fX, pts[1].fX));
|
||||
}
|
||||
if (tmp[index1].fY > clip.fBottom) {
|
||||
tmp[index1].set(sect_with_horizontal(pts, clip.fBottom), clip.fBottom);
|
||||
SkASSERT(is_between_unsorted(tmp[index1].fX, pts[0].fX, pts[1].fX));
|
||||
}
|
||||
|
||||
// Chop it into 1..3 segments that are wholly within the clip in X.
|
||||
@ -173,14 +210,16 @@ int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip,
|
||||
if (tmp[index0].fX < clip.fLeft) {
|
||||
r->set(clip.fLeft, tmp[index0].fY);
|
||||
r += 1;
|
||||
r->set(clip.fLeft, sect_with_vertical(pts, clip.fLeft));
|
||||
r->set(clip.fLeft, sect_with_vertical(tmp, clip.fLeft));
|
||||
SkASSERT(is_between_unsorted(r->fY, tmp[0].fY, tmp[1].fY));
|
||||
} else {
|
||||
*r = tmp[index0];
|
||||
}
|
||||
r += 1;
|
||||
|
||||
if (tmp[index1].fX > clip.fRight) {
|
||||
r->set(clip.fRight, sect_with_vertical(pts, clip.fRight));
|
||||
r->set(clip.fRight, sect_with_vertical(tmp, clip.fRight));
|
||||
SkASSERT(is_between_unsorted(r->fY, tmp[0].fY, tmp[1].fY));
|
||||
r += 1;
|
||||
r->set(clip.fRight, tmp[index1].fY);
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user