diff options
author | Mike Reed <reed@google.com> | 2018-02-26 17:00:58 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-02-27 15:11:39 +0000 |
commit | 0a3b12bbcec77cb7007e0c3421a84affdc27a146 (patch) | |
tree | 7ab24e63085e13961632cbb74d99e22561a72bd5 /src/core | |
parent | 222346541911c7908418a2ba9d60d27b56821998 (diff) |
keep points as floats until after clipping
Bug: oss-fuzz:6539
Change-Id: Ia91dee2a023c9b17d06948c455b8ea6a1b213e0d
Reviewed-on: https://skia-review.googlesource.com/110501
Reviewed-by: Yuqian Li <liyuqian@google.com>
Commit-Queue: Mike Reed <reed@google.com>
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkDraw.cpp | 58 | ||||
-rw-r--r-- | src/core/SkRectPriv.h | 3 |
2 files changed, 33 insertions, 28 deletions
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index 6f8ee30602..21a89ae5a9 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -233,7 +233,8 @@ struct PtProcRec { const SkRasterClip* fRC; // computed values - SkFixed fRadius; + SkRect fClipBounds; + SkScalar fRadius; typedef void (*Proc)(const PtProcRec&, const SkPoint devPts[], int count, SkBlitter*); @@ -341,37 +342,38 @@ static void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], // square procs (strokeWidth > 0 but matrix is square-scale (sx == sy) +static SkRect make_square_rad(SkPoint center, SkScalar radius) { + return { + center.fX - radius, center.fY - radius, + center.fX + radius, center.fY + radius + }; +} + +static SkXRect make_xrect(const SkRect& r) { + SkASSERT(SkRectPriv::FitsInFixed(r)); + return { + SkScalarToFixed(r.fLeft), SkScalarToFixed(r.fTop), + SkScalarToFixed(r.fRight), SkScalarToFixed(r.fBottom) + }; +} + static void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[], int count, SkBlitter* blitter) { - const SkFixed radius = rec.fRadius; for (int i = 0; i < count; i++) { - SkFixed x = SkScalarToFixed(devPts[i].fX); - SkFixed y = SkScalarToFixed(devPts[i].fY); - - SkXRect r; - r.fLeft = x - radius; - r.fTop = y - radius; - r.fRight = x + radius; - r.fBottom = y + radius; - - SkScan::FillXRect(r, *rec.fRC, blitter); + SkRect r = make_square_rad(devPts[i], rec.fRadius); + if (r.intersect(rec.fClipBounds)) { + SkScan::FillXRect(make_xrect(r), *rec.fRC, blitter); + } } } static void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[], int count, SkBlitter* blitter) { - const SkFixed radius = rec.fRadius; for (int i = 0; i < count; i++) { - SkFixed x = SkScalarToFixed(devPts[i].fX); - SkFixed y = SkScalarToFixed(devPts[i].fY); - - SkXRect r; - r.fLeft = x - radius; - r.fTop = y - radius; - r.fRight = x + radius; - r.fBottom = y + radius; - - SkScan::AntiFillXRect(r, *rec.fRC, blitter); + SkRect r = make_square_rad(devPts[i], rec.fRadius); + if (r.intersect(rec.fClipBounds)) { + SkScan::AntiFillXRect(make_xrect(r), *rec.fRC, blitter); + } } } @@ -398,16 +400,18 @@ bool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint, } } if (radius > 0) { + SkRect clipBounds = SkRect::Make(rc->getBounds()); // if we return true, the caller may assume that the constructed shapes can be represented - // using SkFixed, so we preflight that here, looking at the radius and clip-bounds - if (!SkRectPriv::FitsInFixed(SkRect::Make(rc->getBounds()).makeOutset(radius, radius))) { + // using SkFixed (after clipping), so we preflight that here. + if (!SkRectPriv::FitsInFixed(clipBounds)) { return false; } fMode = mode; fPaint = &paint; fClip = nullptr; fRC = rc; - fRadius = SkScalarToFixed(radius); + fClipBounds = clipBounds; + fRadius = radius; return true; } return false; @@ -443,7 +447,7 @@ PtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) { proc = aa_square_proc; } } else { // BW - if (fRadius <= SK_FixedHalf) { // small radii and hairline + if (fRadius <= 0.5f) { // small radii and hairline if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) { uint32_t value; const SkPixmap* bm = blitter->justAnOpaqueColor(&value); diff --git a/src/core/SkRectPriv.h b/src/core/SkRectPriv.h index d2a2ce4665..3bf90f8be7 100644 --- a/src/core/SkRectPriv.h +++ b/src/core/SkRectPriv.h @@ -47,7 +47,8 @@ public: r->fBottom = SkMaxScalar(pt.fY, r->fBottom); } - // conservative check. will return false for very large values that "could" fit + // Conservative check if r can be expressed in fixed-point. + // Will return false for very large values that might have fit static bool FitsInFixed(const SkRect& r) { return SkFitsInFixed(r.fLeft) && SkFitsInFixed(r.fTop) && SkFitsInFixed(r.fRight) && SkFitsInFixed(r.fBottom); |