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>
This commit is contained in:
Mike Reed 2018-02-26 17:00:58 -05:00 committed by Skia Commit-Bot
parent 2223465419
commit 0a3b12bbce
2 changed files with 33 additions and 28 deletions

View File

@ -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);

View File

@ -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);