Core skia changes to prepare for Gr AA Hairline renderer

Review URL: http://codereview.appspot.com/4940045/



git-svn-id: http://skia.googlecode.com/svn/trunk@2160 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2011-08-23 14:39:01 +00:00
parent 8214587a79
commit 647a804c3d
8 changed files with 139 additions and 33 deletions

View File

@ -105,7 +105,11 @@ void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* locOrNull,
dst[0..3] and dst[3..6]
*/
void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], SkScalar t);
void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], const SkScalar t[],
/** Given a src cubic bezier, chop it at the specified t values,
where 0 < t < 1, and return the new cubics in dst:
dst[0..3],dst[3..6],...,dst[3*t_count..3*(t_count+1)]
*/
void SkChopCubicAt(const SkPoint src[4], SkPoint dst[], const SkScalar t[],
int t_count);
/** Given a src cubic bezier, chop it at the specified t == 1/2,
@ -141,8 +145,8 @@ int SkChopCubicAtXExtrema(const SkPoint src[4], SkPoint dst[10]);
*/
int SkFindCubicInflections(const SkPoint src[4], SkScalar tValues[2]);
/** Return 1 for no chop, or 2 for having chopped the cubic at its
inflection point.
/** Return 1 for no chop, 2 for having chopped the cubic at a single
inflection point, 3 for having chopped at 2 inflection points.
*/
int SkChopCubicAtInflections(const SkPoint src[4], SkPoint dst[10]);

View File

@ -364,6 +364,31 @@ public:
this->mapPoints(pts, pts, count);
}
/** Like mapPoints but with custom byte stride between the points. Stride
* should be a multiple of sizeof(SkScalar).
*/
void mapPointsWithStride(SkPoint pts[], size_t stride, int count) const {
SkASSERT(stride >= sizeof(SkPoint));
SkASSERT(0 == stride % sizeof(SkScalar));
for (int i = 0; i < count; ++i) {
this->mapPoints(pts, pts, 1);
pts = (SkPoint*)((intptr_t)pts + stride);
}
}
/** Like mapPoints but with custom byte stride between the points.
*/
void mapPointsWithStride(SkPoint dst[], SkPoint src[],
size_t stride, int count) const {
SkASSERT(stride >= sizeof(SkPoint));
SkASSERT(0 == stride % sizeof(SkScalar));
for (int i = 0; i < count; ++i) {
this->mapPoints(dst, src, 1);
src = (SkPoint*)((intptr_t)src + stride);
dst = (SkPoint*)((intptr_t)dst + stride);
}
}
void mapXY(SkScalar x, SkScalar y, SkPoint* result) const {
SkASSERT(result);
this->getMapXYProc()(*this, x, y, result);
@ -411,13 +436,6 @@ public:
return this->mapRect(rect, *rect);
}
void mapPointsWithStride(SkPoint pts[], size_t stride, int count) const {
for (int i = 0; i < count; ++i) {
this->mapPoints(pts, pts, 1);
pts = (SkPoint*)((intptr_t)pts + stride);
}
}
/** Return the mean radius of a circle after it has been mapped by
this matrix. NOTE: in perspective this value assumes the circle
has its center at the origin.

View File

@ -361,14 +361,68 @@ struct SK_API SkPoint {
SkScalar dy = fY - pt.fY;
return SkScalarMul(dx, dx) + SkScalarMul(dy, dy);
}
SkScalar distanceToLineSegmentBetweenSqd(const SkPoint& a,
/**
* The side of a point relative to a line. If the line is from a to b then
* the values are consistent with the sign of (b-a) cross (pt-a)
*/
enum Side {
kLeft_Side = -1,
kOn_Side = 0,
kRight_Side = 1
};
/**
* Returns the squared distance to the infinite line between two pts. Also
* optionally returns the side of the line that the pt falls on (looking
* along line from a to b)
*/
SkScalar distanceToLineBetweenSqd(const SkPoint& a,
const SkPoint& b,
Side* side = NULL) const;
/**
* Returns the distance to the infinite line between two pts. Also
* optionally returns the side of the line that the pt falls on (looking
* along the line from a to b)
*/
SkScalar distanceToLineBetween(const SkPoint& a,
const SkPoint& b,
Side* side = NULL) const {
return SkScalarSqrt(this->distanceToLineBetweenSqd(a, b, side));
}
/**
* Returns the squared distance to the line segment between pts a and b
*/
SkScalar distanceToLineSegmentBetweenSqd(const SkPoint& a,
const SkPoint& b) const;
SkScalar distanceToLineSegmentBetween(const SkPoint& a,
/**
* Returns the distance to the line segment between pts a and b.
*/
SkScalar distanceToLineSegmentBetween(const SkPoint& a,
const SkPoint& b) const {
return SkScalarSqrt(this->distanceToLineSegmentBetweenSqd(a, b));
}
/**
* Make this vector be orthogonal to vec. Looking down vec the
* new vector will point in direction indicated by side (which
* must be kLeft_Side or kRight_Side).
*/
void setOrthog(const SkPoint& vec, Side side = kLeft_Side) {
// vec could be this
SkScalar tmp = vec.fX;
if (kLeft_Side == side) {
fX = -vec.fY;
fY = tmp;
} else {
SkASSERT(kRight_Side == side);
fX = vec.fY;
fY = -tmp;
}
}
};
typedef SkPoint SkVector;

View File

@ -429,9 +429,10 @@ struct SK_API SkRect {
this->offset(delta.fX, delta.fY);
}
/** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards,
making the rectangle narrower. If dx is negative, then the sides are moved outwards,
making the rectangle wider. The same hods true for dy and the top and bottom.
/** Inset the rectangle by (dx,dy). If dx is positive, then the sides are
moved inwards, making the rectangle narrower. If dx is negative, then
the sides are moved outwards, making the rectangle wider. The same holds
true for dy and the top and bottom.
*/
void inset(SkScalar dx, SkScalar dy) {
fLeft += dx;
@ -440,6 +441,13 @@ struct SK_API SkRect {
fBottom -= dy;
}
/** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
moved outwards, making the rectangle wider. If dx is negative, then the
sides are moved inwards, making the rectangle narrower. The same hods
true for dy and the top and bottom.
*/
void outset(SkScalar dx, SkScalar dy) { this->inset(-dx, -dy); }
/** If this rectangle intersects r, return true and set this rectangle to that
intersection, otherwise return false and do not change this rectangle.
If either rectangle is empty, do nothing and return false.

View File

@ -288,6 +288,20 @@
#define SkScalarCeil(x) SkScalarCeilToInt(x)
#define SkScalarRound(x) SkScalarRoundToInt(x)
/**
* Returns -1 || 0 || 1 depending on the sign of value:
* -1 if x < 0
* 0 if x == 0
* 1 if x > 0
*/
static inline int SkScalarSignAsInt(SkScalar x) {
return x < 0 ? -1 : (x > 0);
}
// Scalar result version of above
static inline SkScalar SkScalarSignAsScalar(SkScalar x) {
return x < 0 ? -SK_Scalar1 : ((x > 0) ? SK_Scalar1 : 0);
}
#define SK_ScalarNearlyZero (SK_Scalar1 / (1 << 12))

View File

@ -1419,21 +1419,11 @@ void SkPath::validate() const {
///////////////////////////////////////////////////////////////////////////////
/**
* Returns -1 || 0 || 1 depending on the sign of value:
* -1 if value < 0
* 0 if vlaue == 0
* 1 if value > 0
*/
static int SkScalarSign(SkScalar value) {
return value < 0 ? -1 : (value > 0);
}
static int sign(SkScalar x) { return x < 0; }
#define kValueNeverReturnedBySign 2
static int CrossProductSign(const SkVector& a, const SkVector& b) {
return SkScalarSign(SkPoint::CrossProduct(a, b));
return SkScalarSignAsInt(SkPoint::CrossProduct(a, b));
}
// only valid for a single contour

View File

@ -359,7 +359,25 @@ bool SkPoint::setLength(SkFixed ox, SkFixed oy, SkFixed length) {
///////////////////////////////////////////////////////////////////////////////
SkScalar SkPoint::distanceToLineSegmentBetweenSqd(const SkPoint& a,
SkScalar SkPoint::distanceToLineBetweenSqd(const SkPoint& a,
const SkPoint& b,
Side* side) const {
SkVector u = b - a;
SkVector v = *this - a;
SkScalar uLengthSqd = u.lengthSqd();
SkScalar det = u.cross(v);
if (NULL != side) {
SkASSERT(-1 == SkPoint::kLeft_Side &&
0 == SkPoint::kOn_Side &&
1 == kRight_Side);
*side = (Side) SkScalarSignAsInt(det);
}
return SkScalarMulDiv(det, det, uLengthSqd);
}
SkScalar SkPoint::distanceToLineSegmentBetweenSqd(const SkPoint& a,
const SkPoint& b) const {
// See comments to distanceToLineBetweenSqd. If the projection of c onto
// u is between a and b then this returns the same result as that

View File

@ -28,8 +28,8 @@ static double getseconds() {
}
// returns +1 or -1, depending on the sign of x
// returns +1 if x is zero
static SkScalar SkScalarSign(SkScalar x) {
// returns +1 if z is zero
static SkScalar SkScalarSignNonZero(SkScalar x) {
SkScalar sign = SK_Scalar1;
if (x < 0) {
sign = -sign;
@ -41,9 +41,9 @@ static void unit_axis_align(SkVector* unit) {
const SkScalar TOLERANCE = SkDoubleToScalar(0.15);
if (SkScalarAbs(unit->fX) < TOLERANCE) {
unit->fX = 0;
unit->fY = SkScalarSign(unit->fY);
unit->fY = SkScalarSignNonZero(unit->fY);
} else if (SkScalarAbs(unit->fY) < TOLERANCE) {
unit->fX = SkScalarSign(unit->fX);
unit->fX = SkScalarSignNonZero(unit->fX);
unit->fY = 0;
}
}