diff options
author | 2009-04-01 18:31:44 +0000 | |
---|---|---|
committer | 2009-04-01 18:31:44 +0000 | |
commit | d252db03d9650013b545ef9781fe993c07f8f314 (patch) | |
tree | 85afe2a17d58115d5e62225487e27308c7ad5f82 | |
parent | 6c924ad46c89955e78e071c792ef00df9910b42f (diff) |
API change: SkPath computeBounds -> getBounds
git-svn-id: http://skia.googlecode.com/svn/trunk@140 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | include/core/SkPaint.h | 20 | ||||
-rw-r--r-- | include/core/SkPath.h | 46 | ||||
-rw-r--r-- | include/core/SkXfermode.h | 38 | ||||
-rw-r--r-- | samplecode/SampleCircle.cpp | 4 | ||||
-rw-r--r-- | samplecode/SampleStrokeText.cpp | 6 | ||||
-rw-r--r-- | src/core/SkBlitter.cpp | 71 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 62 | ||||
-rw-r--r-- | src/core/SkDraw.cpp | 9 | ||||
-rw-r--r-- | src/core/SkPaint.cpp | 42 | ||||
-rw-r--r-- | src/core/SkPath.cpp | 90 | ||||
-rw-r--r-- | src/core/SkPictureRecord.cpp | 4 | ||||
-rw-r--r-- | src/core/SkScalerContext.cpp | 5 | ||||
-rw-r--r-- | src/core/SkScan_AntiPath.cpp | 7 | ||||
-rw-r--r-- | src/core/SkScan_Hairline.cpp | 7 | ||||
-rw-r--r-- | src/core/SkScan_Path.cpp | 5 | ||||
-rw-r--r-- | src/core/SkStroke.cpp | 3 | ||||
-rw-r--r-- | src/effects/Sk2DPathEffect.cpp | 4 | ||||
-rw-r--r-- | src/gl/SkGL.cpp | 4 | ||||
-rw-r--r-- | src/utils/SkDumpCanvas.cpp | 4 | ||||
-rw-r--r-- | tests/PathTest.cpp | 12 | ||||
-rw-r--r-- | tests/main.cpp | 14 | ||||
-rw-r--r-- | xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj | 12 |
22 files changed, 236 insertions, 233 deletions
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h index fc390ab819..fd35292be3 100644 --- a/include/core/SkPaint.h +++ b/include/core/SkPaint.h @@ -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 }; diff --git a/include/core/SkPath.h b/include/core/SkPath.h index 4cedcde453..be49ebdd65 100644 --- a/include/core/SkPath.h +++ b/include/core/SkPath.h @@ -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) - */ - void computeBounds(SkRect* bounds, BoundsType btype) const; + /** 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. + */ + 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(); diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h index f7e6510f83..6a7edecc3f 100644 --- a/include/core/SkXfermode.h +++ b/include/core/SkXfermode.h @@ -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: diff --git a/samplecode/SampleCircle.cpp b/samplecode/SampleCircle.cpp index bfb92d4930..3f39dbd3fd 100644 --- a/samplecode/SampleCircle.cpp +++ b/samplecode/SampleCircle.cpp @@ -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 } diff --git a/samplecode/SampleStrokeText.cpp b/samplecode/SampleStrokeText.cpp index 0627d51e97..2743897b8c 100644 --- a/samplecode/SampleStrokeText.cpp +++ b/samplecode/SampleStrokeText.cpp @@ -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); diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp index 920842937c..25303ac6b8 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -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 diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 16c94c28c0..199c1b0b97 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -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; } diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index 60c474a970..93b5d4e6c8 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -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); } diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index da70c74fe5..1441385bfc 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -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; } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp index da90227125..0cb50fb551 100644 --- a/src/core/SkPath.cpp +++ b/src/core/SkPath.cpp @@ -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); } } diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp index ed47d64f91..77756a9746 100644 --- a/src/core/SkPictureRecord.cpp +++ b/src/core/SkPictureRecord.cpp @@ -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); } diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index b271970ddc..cc3eb1aa25 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -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; diff --git a/src/core/SkScan_AntiPath.cpp b/src/core/SkScan_AntiPath.cpp index 422d060255..f2f117a35f 100644 --- a/src/core/SkScan_AntiPath.cpp +++ b/src/core/SkScan_AntiPath.cpp @@ -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; } diff --git a/src/core/SkScan_Hairline.cpp b/src/core/SkScan_Hairline.cpp index 6a66754c01..b95996820e 100644 --- a/src/core/SkScan_Hairline.cpp +++ b/src/core/SkScan_Hairline.cpp @@ -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)) diff --git a/src/core/SkScan_Path.cpp b/src/core/SkScan_Path.cpp index fcf1530c80..ead1b8573a 100644 --- a/src/core/SkScan_Path.cpp +++ b/src/core/SkScan_Path.cpp @@ -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); diff --git a/src/core/SkStroke.cpp b/src/core/SkStroke.cpp index 86dff488cb..30d524ed9b 100644 --- a/src/core/SkStroke.cpp +++ b/src/core/SkStroke.cpp @@ -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); diff --git a/src/effects/Sk2DPathEffect.cpp b/src/effects/Sk2DPathEffect.cpp index 405b194f1f..603deb7ce4 100644 --- a/src/effects/Sk2DPathEffect.cpp +++ b/src/effects/Sk2DPathEffect.cpp @@ -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 diff --git a/src/gl/SkGL.cpp b/src/gl/SkGL.cpp index 0634709c2b..89bcdf4bc2 100644 --- a/src/gl/SkGL.cpp +++ b/src/gl/SkGL.cpp @@ -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; } diff --git a/src/utils/SkDumpCanvas.cpp b/src/utils/SkDumpCanvas.cpp index a0c85fe429..1ef444cb70 100644 --- a/src/utils/SkDumpCanvas.cpp +++ b/src/utils/SkDumpCanvas.cpp @@ -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); diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp index 383ad030c5..0e44719220 100644 --- a/tests/PathTest.cpp +++ b/tests/PathTest.cpp @@ -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)); diff --git a/tests/main.cpp b/tests/main.cpp index 7975de0e54..13f8817b70 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -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); diff --git a/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj b/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj index 813856b9c2..24777c7c5d 100644 --- a/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj +++ b/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj @@ -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; }; |