API change: SkPath computeBounds -> getBounds

git-svn-id: http://skia.googlecode.com/svn/trunk@140 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@android.com 2009-04-01 18:31:44 +00:00
parent 6c924ad46c
commit d252db03d9
22 changed files with 235 additions and 232 deletions

View File

@ -371,8 +371,14 @@ public:
bounds (i.e. there is nothing complex like a patheffect that would make
the bounds computation expensive.
*/
bool canComputeFastBounds() const;
bool canComputeFastBounds() const {
// use bit-or since no need for early exit
return (reinterpret_cast<uintptr_t>(this->getMaskFilter()) |
reinterpret_cast<uintptr_t>(this->getLooper()) |
reinterpret_cast<uintptr_t>(this->getRasterizer()) |
reinterpret_cast<uintptr_t>(this->getPathEffect())) == 0;
}
/** Only call this if canComputeFastBounds() returned true. This takes a
raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
effects in the paint (e.g. stroking). If needed, it uses the storage
@ -394,7 +400,10 @@ public:
}
}
*/
const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const;
const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const {
return this->getStyle() == kFill_Style ? orig :
this->computeStrokeFastBounds(orig, storage);
}
/** Get the paint's shader object.
<p />
@ -759,7 +768,10 @@ private:
void descriptorProc(const SkMatrix* deviceMatrix,
void (*proc)(const SkDescriptor*, void*),
void* context) const;
const SkRect& computeStrokeFastBounds(const SkRect& orig,
SkRect* storage) const;
enum {
kCanonicalTextSizeForPaths = 64
};

View File

@ -122,32 +122,27 @@ public:
//! Swap contents of this and other. Guaranteed not to throw
void swap(SkPath& other);
enum BoundsType {
/** compute the bounds of the path's control points, may be larger than
with kExact_BoundsType, but may be faster to compute
*/
kFast_BoundsType,
/** compute the exact bounds of the path, may be smaller than with
kFast_BoundsType, but may be slower to compute
*/
kExact_BoundsType
};
/** Compute the bounds of the path, and write the answer into bounds. If the
path contains 0 or 1 points, the bounds is set to (0,0,0,0)
@param bounds Returns the computed bounds of the path
@param btype Specifies if the computed bounds should be exact
(slower) or approximate (faster)
/** Returns the bounds of the path's points. If the path contains 0 or 1
points, the bounds is set to (0,0,0,0), and isEmpty() will return true.
Note: this bounds may be larger than the actual shape, since curves
do not extend as far as their control points.
*/
void computeBounds(SkRect* bounds, BoundsType btype) const;
const SkRect& getBounds() const {
if (fBoundsIsDirty) {
this->computeBounds();
}
return fBounds;
}
/** Calling this will, if the internal cache of the bounds is out of date,
update it so that subsequent calls to computeBounds will be instanteous.
update it so that subsequent calls to getBounds will be instanteous.
This also means that any copies or simple transformations of the path
will inherit the cached bounds.
*/
void updateBoundsCache() const;
*/
void updateBoundsCache() const {
// for now, just calling getBounds() is sufficient
this->getBounds();
}
// Construction methods
@ -564,10 +559,13 @@ public:
private:
SkTDArray<SkPoint> fPts;
SkTDArray<uint8_t> fVerbs;
mutable SkRect fFastBounds;
mutable uint8_t fFastBoundsIsDirty;
mutable SkRect fBounds;
mutable uint8_t fBoundsIsDirty;
uint8_t fFillType;
// called, if dirty, by getBounds()
void computeBounds() const;
friend class Iter;
void cons_moveto();

View File

@ -41,20 +41,38 @@ public:
virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
const SkAlpha aa[]);
/** Enum of possible coefficients to describe some xfermodes
*/
enum Coeff {
kZero_Coeff,
kOne_Coeff,
kSC_Coeff,
kISC_Coeff,
kDC_Coeff,
kIDC_Coeff,
kSA_Coeff,
kISA_Coeff,
kDA_Coeff,
kIDA_Coeff,
kZero_Coeff, /** 0 */
kOne_Coeff, /** 1 */
kSC_Coeff, /** src color */
kISC_Coeff, /** inverse src color (i.e. 1 - sc) */
kDC_Coeff, /** dst color */
kIDC_Coeff, /** inverse dst color (i.e. 1 - dc) */
kSA_Coeff, /** src alpha */
kISA_Coeff, /** inverse src alpha (i.e. 1 - sa) */
kDA_Coeff, /** dst alpha */
kIDA_Coeff, /** inverse dst alpha (i.e. 1 - da) */
kCoeffCount
};
/** If the xfermode can be expressed as an equation using the coefficients
in Coeff, then asCoeff() returns true, and sets (if not null) src and
dst accordingly.
result = src_coeff * src_color + dst_coeff * dst_color;
As examples, here are some of the porterduff coefficients
MODE SRC_COEFF DST_COEFF
clear zero zero
src one zero
dst zero one
srcover one isa
dstover ida one
*/
virtual bool asCoeff(Coeff* src, Coeff* dst);
protected:

View File

@ -13,9 +13,7 @@ static void test_circlebounds(SkCanvas* canvas) {
SkRect r = { 1.39999998, 1, 21.3999996, 21 };
SkPath p;
p.addOval(r);
SkRect r2;
p.computeBounds(&r2, SkPath::kFast_BoundsType);
SkASSERT(r == r2);
SkASSERT(r == p.getBounds());
#endif
}

View File

@ -29,8 +29,7 @@ static void lettersToBitmap(SkBitmap* dst, const char chars[],
original.getTextWidths(&chars[i], 1, &width);
x += width;
}
SkRect bounds;
path.computeBounds(&bounds, SkPath::kExact_BoundsType);
SkRect bounds = path.getBounds();
SkScalar sw = -original.getStrokeWidth();
bounds.inset(sw, sw);
path.offset(-bounds.fLeft, -bounds.fTop);
@ -76,8 +75,7 @@ static void lettersToBitmap2(SkBitmap* dst, const char chars[],
original.getTextWidths(&chars[i], 1, &width);
x += width;
}
SkRect bounds;
path.computeBounds(&bounds, SkPath::kExact_BoundsType);
SkRect bounds = path.getBounds();
SkScalar sw = -original.getStrokeWidth();
bounds.inset(sw, sw);
path.offset(-bounds.fLeft, -bounds.fTop);

View File

@ -784,6 +784,64 @@ static void delete_blitter(void* blitter)
SkDELETE((SkBlitter*)blitter);
}
static bool just_solid_color(const SkPaint& paint) {
if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) {
SkShader* shader = paint.getShader();
if (NULL == shader ||
(shader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
return true;
}
}
return false;
}
/** By analyzing the paint (with an xfermode), we may decide we can take
special action. This enum lists our possible actions
*/
enum XferInterp {
kNormal_XferInterp, // no special interpretation, draw normally
kSrcOver_XferInterp, // draw as if in srcover mode
kSkipDrawing_XferInterp // draw nothing
};
static XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer,
SkBitmap::Config deviceConfig) {
SkPorterDuff::Mode mode;
if (SkPorterDuff::IsMode(xfer, &mode)) {
switch (mode) {
case SkPorterDuff::kSrc_Mode:
if (just_solid_color(paint)) {
return kSrcOver_XferInterp;
}
break;
case SkPorterDuff::kDst_Mode:
return kSkipDrawing_XferInterp;
case SkPorterDuff::kSrcOver_Mode:
return kSrcOver_XferInterp;
case SkPorterDuff::kDstOver_Mode:
if (SkBitmap::kRGB_565_Config == deviceConfig) {
return kSkipDrawing_XferInterp;
}
break;
case SkPorterDuff::kSrcIn_Mode:
if (SkBitmap::kRGB_565_Config == deviceConfig &&
just_solid_color(paint)) {
return kSrcOver_XferInterp;
}
break;
case SkPorterDuff::kDstIn_Mode:
if (just_solid_color(paint)) {
return kSkipDrawing_XferInterp;
}
break;
default:
break;
}
}
return kNormal_XferInterp;
}
SkBlitter* SkBlitter::Choose(const SkBitmap& device,
const SkMatrix& matrix,
const SkPaint& paint,
@ -813,6 +871,19 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device,
}
SkXfermode* mode = paint.getXfermode();
if (NULL != mode) {
switch (interpret_xfermode(paint, mode, device.config())) {
case kSrcOver_XferInterp:
mode = NULL;
break;
case kSkipDrawing_XferInterp:
SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
return blitter;
default:
break;
}
}
if (NULL == shader && (NULL != mode || paint.getColorFilter() != NULL))
{
// xfermodes require shaders for our current set of blitters

View File

@ -879,58 +879,33 @@ void SkCanvas::computeLocalClipBoundsCompareType() const {
}
}
/* current impl ignores edgetype, and relies on
getLocalClipBoundsCompareType(), which always returns a value assuming
antialiasing (worst case)
*/
bool SkCanvas::quickReject(const SkRect& rect, EdgeType) const {
/* current impl ignores edgetype, and relies on
getLocalClipBoundsCompareType(), which always returns a value assuming
antialiasing (worst case)
*/
if (fMCRec->fRegion->isEmpty()) {
return true;
}
// check for empty user rect (horizontal)
SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft);
SkScalarCompareType userR = SkScalarToCompareType(rect.fRight);
if (userL >= userR) {
return true;
}
// check for empty user rect (vertical)
const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
// for speed, do the most likely reject compares first
SkScalarCompareType userT = SkScalarToCompareType(rect.fTop);
SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom);
if (userT >= userB) {
if (userT >= clipR.fBottom || userB <= clipR.fTop) {
return true;
}
// check if we are completely outside of the local clip bounds
const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
return userL >= clipR.fRight || userT >= clipR.fBottom ||
userR <= clipR.fLeft || userB <= clipR.fTop;
SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft);
SkScalarCompareType userR = SkScalarToCompareType(rect.fRight);
if (userL >= clipR.fRight || userR <= clipR.fLeft) {
return true;
}
return false;
}
bool SkCanvas::quickReject(const SkPath& path, EdgeType et) const {
if (fMCRec->fRegion->isEmpty() || path.isEmpty()) {
return true;
}
if (fMCRec->fMatrix->rectStaysRect()) {
SkRect r;
path.computeBounds(&r, SkPath::kFast_BoundsType);
return this->quickReject(r, et);
}
SkPath dstPath;
SkRect r;
SkIRect ir;
path.transform(*fMCRec->fMatrix, &dstPath);
dstPath.computeBounds(&r, SkPath::kFast_BoundsType);
r.round(&ir);
if (kAA_EdgeType == et) {
ir.inset(-1, -1);
}
return fMCRec->fRegion->quickReject(ir);
return path.isEmpty() || this->quickReject(path.getBounds(), et);
}
bool SkCanvas::quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const {
@ -947,6 +922,7 @@ bool SkCanvas::quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const {
SkScalarCompareType userB = SkScalarToCompareType(bottom);
// check for invalid user Y coordinates (i.e. empty)
// reed: why do we need to do this check, since it slows us down?
if (userT >= userB) {
return true;
}
@ -1063,9 +1039,9 @@ void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
if (paint.canComputeFastBounds()) {
SkRect r;
path.computeBounds(&r, SkPath::kFast_BoundsType);
if (this->quickReject(paint.computeFastBounds(r, &r),
SkRect storage;
const SkRect& bounds = path.getBounds();
if (this->quickReject(paint.computeFastBounds(bounds, &storage),
paint2EdgeType(&paint))) {
return;
}

View File

@ -2236,10 +2236,8 @@ bool SkBounder::doRect(const SkRect& rect, const SkPaint& paint) {
}
bool SkBounder::doPath(const SkPath& path, const SkPaint& paint, bool doFill) {
SkRect bounds;
SkIRect r;
path.computeBounds(&bounds, SkPath::kFast_BoundsType);
SkIRect r;
const SkRect& bounds = path.getBounds();
if (doFill) {
bounds.round(&r);
@ -2276,8 +2274,7 @@ static bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds,
// init our bounds from the path
{
SkRect pathBounds;
devPath.computeBounds(&pathBounds, SkPath::kExact_BoundsType);
SkRect pathBounds = devPath.getBounds();
pathBounds.inset(-SK_ScalarHalf, -SK_ScalarHalf);
pathBounds.roundOut(bounds);
}

View File

@ -1517,36 +1517,24 @@ bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const
return width != 0; // return true if we're filled, or false if we're hairline (width == 0)
}
bool SkPaint::canComputeFastBounds() const {
// use bit-or since no need for early exit
return (reinterpret_cast<uintptr_t>(this->getMaskFilter()) |
reinterpret_cast<uintptr_t>(this->getLooper()) |
reinterpret_cast<uintptr_t>(this->getRasterizer()) |
reinterpret_cast<uintptr_t>(this->getPathEffect())) == 0;
}
const SkRect& SkPaint::computeFastBounds(const SkRect& src,
SkRect* storage) const {
const SkRect& SkPaint::computeStrokeFastBounds(const SkRect& src,
SkRect* storage) const {
SkASSERT(storage);
if (this->getStyle() != SkPaint::kFill_Style) {
// if we're stroked, outset the rect by the radius (and join type)
SkScalar radius = SkScalarHalf(this->getStrokeWidth());
if (0 == radius) { // hairline
radius = SK_Scalar1;
} else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
SkScalar scale = this->getStrokeMiter();
if (scale > SK_Scalar1) {
radius = SkScalarMul(radius, scale);
}
SkASSERT(this->getStyle() != SkPaint::kFill_Style);
// since we're stroked, outset the rect by the radius (and join type)
SkScalar radius = SkScalarHalf(this->getStrokeWidth());
if (0 == radius) { // hairline
radius = SK_Scalar1;
} else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
SkScalar scale = this->getStrokeMiter();
if (scale > SK_Scalar1) {
radius = SkScalarMul(radius, scale);
}
storage->set(src.fLeft - radius, src.fTop - radius,
src.fRight + radius, src.fBottom + radius);
return *storage;
}
// no adjustments needed, just return the original rect
return src;
storage->set(src.fLeft - radius, src.fTop - radius,
src.fRight + radius, src.fBottom + radius);
return *storage;
}
////////////////////////////////////////////////////////////////////////////////////////

View File

@ -27,7 +27,7 @@
It captures some state about the path up front (i.e. if it already has a
cached bounds), and the if it can, it updates the cache bounds explicitly,
avoiding the need to revisit all of the points in computeBounds().
avoiding the need to revisit all of the points in getBounds().
*/
class SkAutoPathBoundsUpdate {
public:
@ -43,11 +43,11 @@ public:
~SkAutoPathBoundsUpdate() {
if (fEmpty) {
fPath->fFastBounds = fRect;
fPath->fFastBoundsIsDirty = false;
fPath->fBounds = fRect;
fPath->fBoundsIsDirty = false;
} else if (!fDirty) {
fPath->fFastBounds.join(fRect);
fPath->fFastBoundsIsDirty = false;
fPath->fBounds.join(fRect);
fPath->fBoundsIsDirty = false;
}
}
@ -60,14 +60,14 @@ private:
// returns true if we should proceed
void init(const SkPath* path) {
fPath = path;
fDirty = path->fFastBoundsIsDirty;
fDirty = path->fBoundsIsDirty;
fEmpty = path->isEmpty();
// Cannot use fRect for our bounds unless we know it is sorted
fRect.sort();
}
};
static void compute_fast_bounds(SkRect* bounds, const SkTDArray<SkPoint>& pts) {
static void compute_pt_bounds(SkRect* bounds, const SkTDArray<SkPoint>& pts) {
if (pts.count() <= 1) { // we ignore just 1 point (moveto)
bounds->set(0, 0, 0, 0);
} else {
@ -91,7 +91,7 @@ static void compute_fast_bounds(SkRect* bounds, const SkTDArray<SkPoint>& pts) {
////////////////////////////////////////////////////////////////////////////
SkPath::SkPath() : fFastBoundsIsDirty(true), fFillType(kWinding_FillType) {}
SkPath::SkPath() : fBoundsIsDirty(true), fFillType(kWinding_FillType) {}
SkPath::SkPath(const SkPath& src) {
SkDEBUGCODE(src.validate();)
@ -106,11 +106,11 @@ SkPath& SkPath::operator=(const SkPath& src) {
SkDEBUGCODE(src.validate();)
if (this != &src) {
fFastBounds = src.fFastBounds;
fPts = src.fPts;
fVerbs = src.fVerbs;
fFillType = src.fFillType;
fFastBoundsIsDirty = src.fFastBoundsIsDirty;
fBounds = src.fBounds;
fPts = src.fPts;
fVerbs = src.fVerbs;
fFillType = src.fFillType;
fBoundsIsDirty = src.fBoundsIsDirty;
}
SkDEBUGCODE(this->validate();)
return *this;
@ -125,11 +125,11 @@ void SkPath::swap(SkPath& other) {
SkASSERT(&other != NULL);
if (this != &other) {
SkTSwap<SkRect>(fFastBounds, other.fFastBounds);
SkTSwap<SkRect>(fBounds, other.fBounds);
fPts.swap(other.fPts);
fVerbs.swap(other.fVerbs);
SkTSwap<uint8_t>(fFillType, other.fFillType);
SkTSwap<uint8_t>(fFastBoundsIsDirty, other.fFastBoundsIsDirty);
SkTSwap<uint8_t>(fBoundsIsDirty, other.fBoundsIsDirty);
}
}
@ -138,7 +138,7 @@ void SkPath::reset() {
fPts.reset();
fVerbs.reset();
fFastBoundsIsDirty = true;
fBoundsIsDirty = true;
}
void SkPath::rewind() {
@ -146,7 +146,7 @@ void SkPath::rewind() {
fPts.rewind();
fVerbs.rewind();
fFastBoundsIsDirty = true;
fBoundsIsDirty = true;
}
bool SkPath::isEmpty() const {
@ -198,20 +198,12 @@ void SkPath::setLastPt(SkScalar x, SkScalar y) {
}
}
#define ALWAYS_FAST_BOUNDS_FOR_NOW true
void SkPath::computeBounds(SkRect* bounds, BoundsType bt) const {
void SkPath::computeBounds() const {
SkDEBUGCODE(this->validate();)
SkASSERT(fBoundsIsDirty);
SkASSERT(bounds);
// we BoundsType for now
if (fFastBoundsIsDirty) {
fFastBoundsIsDirty = false;
compute_fast_bounds(&fFastBounds, fPts);
}
*bounds = fFastBounds;
fBoundsIsDirty = false;
compute_pt_bounds(&fBounds, fPts);
}
//////////////////////////////////////////////////////////////////////////////
@ -240,7 +232,7 @@ void SkPath::moveTo(SkScalar x, SkScalar y) {
}
pt->set(x, y);
fFastBoundsIsDirty = true;
fBoundsIsDirty = true;
}
void SkPath::rMoveTo(SkScalar x, SkScalar y) {
@ -259,7 +251,7 @@ void SkPath::lineTo(SkScalar x, SkScalar y) {
fPts.append()->set(x, y);
*fVerbs.append() = kLine_Verb;
fFastBoundsIsDirty = true;
fBoundsIsDirty = true;
}
void SkPath::rLineTo(SkScalar x, SkScalar y) {
@ -281,7 +273,7 @@ void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
pts[1].set(x2, y2);
*fVerbs.append() = kQuad_Verb;
fFastBoundsIsDirty = true;
fBoundsIsDirty = true;
}
void SkPath::rQuadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
@ -304,7 +296,7 @@ void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
pts[2].set(x3, y3);
*fVerbs.append() = kCubic_Verb;
fFastBoundsIsDirty = true;
fBoundsIsDirty = true;
}
void SkPath::rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
@ -899,13 +891,13 @@ void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const {
matrix.mapPoints(dst->fPts.begin(), dst->fPts.count());
} else {
// remember that dst might == this, so be sure to check
// fFastBoundsIsDirty before we set it
if (!fFastBoundsIsDirty && matrix.rectStaysRect() && fPts.count() > 1) {
// fBoundsIsDirty before we set it
if (!fBoundsIsDirty && matrix.rectStaysRect() && fPts.count() > 1) {
// if we're empty, fastbounds should not be mapped
matrix.mapRect(&dst->fFastBounds, fFastBounds);
dst->fFastBoundsIsDirty = false;
matrix.mapRect(&dst->fBounds, fBounds);
dst->fBoundsIsDirty = false;
} else {
dst->fFastBoundsIsDirty = true;
dst->fBoundsIsDirty = true;
}
if (this != dst) {
@ -918,14 +910,6 @@ void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const {
}
}
void SkPath::updateBoundsCache() const {
if (fFastBoundsIsDirty) {
SkRect r;
this->computeBounds(&r, kFast_BoundsType);
SkASSERT(!fFastBoundsIsDirty);
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
@ -1220,7 +1204,7 @@ void SkPath::unflatten(SkFlattenableReadBuffer& buffer) {
buffer.read(fPts.begin(), sizeof(SkPoint) * fPts.count());
buffer.read(fVerbs.begin(), fVerbs.count());
fFastBoundsIsDirty = true;
fBoundsIsDirty = true;
SkDEBUGCODE(this->validate();)
}
@ -1291,14 +1275,14 @@ void SkPath::validate() const {
fPts.validate();
fVerbs.validate();
if (!fFastBoundsIsDirty) {
if (!fBoundsIsDirty) {
SkRect bounds;
compute_fast_bounds(&bounds, fPts);
compute_pt_bounds(&bounds, fPts);
// can't call contains(), since it returns false if the rect is empty
SkASSERT(fFastBounds.fLeft <= bounds.fLeft);
SkASSERT(fFastBounds.fTop <= bounds.fTop);
SkASSERT(fFastBounds.fRight >= bounds.fRight);
SkASSERT(fFastBounds.fBottom >= bounds.fBottom);
SkASSERT(fBounds.fLeft <= bounds.fLeft);
SkASSERT(fBounds.fTop <= bounds.fTop);
SkASSERT(fBounds.fRight >= bounds.fRight);
SkASSERT(fBounds.fBottom >= bounds.fBottom);
}
}

View File

@ -138,9 +138,7 @@ bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op) {
validate();
if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
SkRect bounds;
path.computeBounds(&bounds, SkPath::kFast_BoundsType);
return this->INHERITED::clipRect(bounds, op);
return this->INHERITED::clipRect(path.getBounds(), op);
} else {
return this->INHERITED::clipPath(path, op);
}

View File

@ -271,11 +271,8 @@ void SkScalerContext::getMetrics(SkGlyph* glyph) {
}
} else {
// just use devPath
SkRect r;
SkIRect ir;
devPath.computeBounds(&r, SkPath::kExact_BoundsType);
r.roundOut(&ir);
devPath.getBounds().roundOut(&ir);
glyph->fLeft = ir.fLeft;
glyph->fTop = ir.fTop;

View File

@ -350,11 +350,8 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& clip,
return;
}
SkRect r;
SkIRect ir;
path.computeBounds(&r, SkPath::kFast_BoundsType);
r.roundOut(&ir);
SkIRect ir;
path.getBounds().roundOut(&ir);
if (ir.isEmpty()) {
return;
}

View File

@ -248,11 +248,8 @@ static void hair_path(const SkPath& path, const SkRegion* clip, SkBlitter* blitt
if (clip)
{
SkRect bounds;
SkIRect ibounds;
path.computeBounds(&bounds, SkPath::kFast_BoundsType);
bounds.roundOut(&ibounds);
SkIRect ibounds;
path.getBounds().roundOut(&ibounds);
ibounds.inset(-1, -1);
if (clip->quickReject(ibounds))

View File

@ -582,11 +582,8 @@ void SkScan::FillPath(const SkPath& path, const SkRegion& clip,
return;
}
SkRect r;
SkIRect ir;
path.computeBounds(&r, SkPath::kFast_BoundsType);
r.round(&ir);
path.getBounds().round(&ir);
if (ir.isEmpty()) {
if (path.isInverseFillType()) {
blitter->blitRegion(clip);

View File

@ -538,8 +538,7 @@ void SkStroke::setJoin(SkPaint::Join join) {
routine
*/
static int needs_to_shrink(const SkPath& path) {
SkRect r;
path.computeBounds(&r, SkPath::kFast_BoundsType);
const SkRect& r = path.getBounds();
SkFixed mask = SkAbs32(r.fLeft);
mask |= SkAbs32(r.fTop);
mask |= SkAbs32(r.fRight);

View File

@ -45,12 +45,10 @@ bool Sk2DPathEffect::filterPath(SkPath* dst, const SkPath& src, SkScalar* width)
{
Sk2DPathEffectBlitter blitter(this, dst);
SkPath tmp;
SkRect bounds;
SkIRect ir;
src.transform(fInverse, &tmp);
tmp.computeBounds(&bounds, SkPath::kExact_BoundsType);
bounds.round(&ir);
tmp.getBounds().round(&ir);
if (!ir.isEmpty()) {
// need to pass a clip to fillpath, required for inverse filltypes,
// even though those do not make sense for this patheffect

View File

@ -443,9 +443,7 @@ static int worst_case_edge_count(const SkPath& path) {
}
void SkGL::DrawPath(const SkPath& path, bool useTex, SkGLClipIter* clipIter) {
SkRect bounds;
path.computeBounds(&bounds, SkPath::kFast_BoundsType);
const SkRect& bounds = path.getBounds();
if (bounds.isEmpty()) {
return;
}

View File

@ -53,9 +53,7 @@ static void toString(const SkPath& path, SkString* str) {
if (path.isEmpty()) {
str->set("path:empty");
} else {
SkRect bounds;
path.computeBounds(&bounds, SkPath::kFast_BoundsType);
toString(bounds, str);
toString(path.getBounds(), str);
#if 1
SkString s;
dumpVerbs(path, &s);

View File

@ -11,16 +11,11 @@ static void TestPath(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, p == p2);
REPORTER_ASSERT(reporter, !(p != p2));
// initialize bounds to not-empty
bounds.set(0, 0, SK_Scalar1, SK_Scalar1);
p.computeBounds(&bounds, SkPath::kFast_BoundsType);
REPORTER_ASSERT(reporter, bounds.isEmpty());
REPORTER_ASSERT(reporter, p.getBounds().isEmpty());
bounds.set(0, 0, SK_Scalar1, SK_Scalar1);
p.addRect(bounds);
bounds2.setEmpty();
p.computeBounds(&bounds2, SkPath::kFast_BoundsType);
REPORTER_ASSERT(reporter, bounds == bounds2);
REPORTER_ASSERT(reporter, bounds == p.getBounds());
REPORTER_ASSERT(reporter, p != p2);
REPORTER_ASSERT(reporter, !(p == p2));
@ -35,8 +30,7 @@ static void TestPath(skiatest::Reporter* reporter) {
bounds.offset(SK_Scalar1*3, SK_Scalar1*4);
p.offset(SK_Scalar1*3, SK_Scalar1*4);
p.computeBounds(&bounds2, SkPath::kFast_BoundsType);
REPORTER_ASSERT(reporter, bounds == bounds2);
REPORTER_ASSERT(reporter, bounds == p.getBounds());
#if 0 // isRect needs to be implemented
REPORTER_ASSERT(reporter, p.isRect(NULL));

View File

@ -1,9 +1,11 @@
#include <iostream>
#include "SkGraphics.h"
#include "Test.h"
using namespace skiatest;
// need to explicitly declare this, or we get some weird infinite loop llist
template TestRegistry* TestRegistry::gHead;
class Iter {
public:
Iter(Reporter* r) : fReporter(r) {
@ -35,13 +37,13 @@ static const char* result2string(Reporter::Result result) {
return result == Reporter::kPassed ? "passed" : "FAILED";
}
class PrintfReporter : public Reporter {
class DebugfReporter : public Reporter {
protected:
virtual void onStart(Test* test) {
printf("Running %s...\n", test->getName());
SkDebugf("Running %s...\n", test->getName());
}
virtual void onReport(const char desc[], Reporter::Result result) {
printf("\t%s: %s\n", result2string(result), desc);
SkDebugf("\t%s: %s\n", result2string(result), desc);
}
virtual void onEnd(Test* test) {}
};
@ -59,7 +61,7 @@ public:
int main (int argc, char * const argv[]) {
SkAutoGraphics ag;
PrintfReporter reporter;
DebugfReporter reporter;
Iter iter(&reporter);
Test* test;
@ -71,7 +73,7 @@ int main (int argc, char * const argv[]) {
int total = reporter.countTests();
int passed = reporter.countResults(Reporter::kPassed);
int failed = reporter.countResults(Reporter::kFailed);
printf("Tests=%d Passed=%d (%g%%) Failed=%d (%g%%)\n", total,
SkDebugf("Tests=%d Passed=%d (%g%%) Failed=%d (%g%%)\n", total,
passed, passed * 100.f / total,
failed, failed * 100.f / total);

View File

@ -68,8 +68,6 @@
008C4D980F77DAEE0056981C /* SampleHairline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 008C4D970F77DAEE0056981C /* SampleHairline.cpp */; };
009CC9190F65918A002185BE /* SampleFontScalerTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 009CC9180F65918A002185BE /* SampleFontScalerTest.cpp */; };
00A41E4B0EFC312F00C9CBEB /* SampleArc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A41E4A0EFC312F00C9CBEB /* SampleArc.cpp */; };
00FACE3C0F7D0E6600F8A7FF /* SkLargeBlock_malloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00FACE3B0F7D0E6600F8A7FF /* SkLargeBlock_malloc.cpp */; };
00FACE680F7D23DD00F8A7FF /* SkWriter32_largeBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00FACE5C0F7D209700F8A7FF /* SkWriter32_largeBlock.cpp */; };
0156F80407C56A3000C6122B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0156F80307C56A3000C6122B /* Foundation.framework */; };
01FC44D507BD3BB800D228F4 /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 01FC44D407BD3BB800D228F4 /* Quartz.framework */; };
8D0C4E8D0486CD37000505A6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */; };
@ -186,10 +184,6 @@
009CC9180F65918A002185BE /* SampleFontScalerTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleFontScalerTest.cpp; path = ../../samplecode/SampleFontScalerTest.cpp; sourceTree = SOURCE_ROOT; };
00A41E4A0EFC312F00C9CBEB /* SampleArc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleArc.cpp; path = ../../samplecode/SampleArc.cpp; sourceTree = SOURCE_ROOT; };
00D6B5CB0F72DC4300C466B9 /* SampleFuzz.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleFuzz.cpp; path = ../../samplecode/SampleFuzz.cpp; sourceTree = SOURCE_ROOT; };
00FACE3B0F7D0E6600F8A7FF /* SkLargeBlock_malloc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkLargeBlock_malloc.cpp; path = ../../src/utils/SkLargeBlock_malloc.cpp; sourceTree = SOURCE_ROOT; };
00FACE3F0F7D167400F8A7FF /* SkLargeBlock_remap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkLargeBlock_remap.cpp; path = ../../src/utils/SkLargeBlock_remap.cpp; sourceTree = SOURCE_ROOT; };
00FACE5C0F7D209700F8A7FF /* SkWriter32_largeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkWriter32_largeBlock.cpp; path = ../../src/utils/SkWriter32_largeBlock.cpp; sourceTree = SOURCE_ROOT; };
00FACE600F7D22CF00F8A7FF /* SkWriter32_noLargeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkWriter32_noLargeBlock.cpp; path = ../../src/utils/SkWriter32_noLargeBlock.cpp; sourceTree = SOURCE_ROOT; };
0156F80307C56A3000C6122B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
01FC44D407BD3BB800D228F4 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = /System/Library/Frameworks/Quartz.framework; sourceTree = "<absolute>"; };
0867D6ABFE840B52C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@ -337,10 +331,6 @@
002884490EFAA35C0083E387 /* core.xcodeproj */,
002884B40EFAB69F0083E387 /* maccore.xcodeproj */,
00003C8C0EFC230E000FF73A /* effects.xcodeproj */,
00FACE3B0F7D0E6600F8A7FF /* SkLargeBlock_malloc.cpp */,
00FACE3F0F7D167400F8A7FF /* SkLargeBlock_remap.cpp */,
00FACE5C0F7D209700F8A7FF /* SkWriter32_largeBlock.cpp */,
00FACE600F7D22CF00F8A7FF /* SkWriter32_noLargeBlock.cpp */,
);
name = CICarbonSample;
sourceTree = "<group>";
@ -529,8 +519,6 @@
007A7CB30F01658C00A2D6EE /* SamplePicture.cpp in Sources */,
0041CE440F00A12400695E8C /* SampleLines.cpp in Sources */,
008C4D980F77DAEE0056981C /* SampleHairline.cpp in Sources */,
00FACE3C0F7D0E6600F8A7FF /* SkLargeBlock_malloc.cpp in Sources */,
00FACE680F7D23DD00F8A7FF /* SkWriter32_largeBlock.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};