handle clipping large triangles
originally found by fuzzer. Bug: skia: Change-Id: I45007a619f13936153c0db8a60b3631a2c9db20c Reviewed-on: https://skia-review.googlesource.com/101741 Reviewed-by: Cary Clark <caryclark@google.com> Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
parent
ab2621d3e2
commit
63227ca63b
@ -759,9 +759,19 @@ void SkScan::FillTriangle(const SkPoint pts[], const SkRasterClip& clip,
|
||||
}
|
||||
|
||||
SkRect r;
|
||||
SkIRect ir;
|
||||
r.set(pts, 3);
|
||||
r.round(&ir);
|
||||
// If r is too large (larger than can easily fit in SkFixed) then we need perform geometric
|
||||
// clipping. This is a bit of work, so we just call the general FillPath() to handle it.
|
||||
// Use FixedMax/2 as the limit so we can subtract two edges and still store that in Fixed.
|
||||
const SkScalar limit = SK_MaxS16 >> 1;
|
||||
if (!SkRect::MakeLTRB(-limit, -limit, limit, limit).contains(r)) {
|
||||
SkPath path;
|
||||
path.addPoly(pts, 3, false);
|
||||
FillPath(path, clip, blitter);
|
||||
return;
|
||||
}
|
||||
|
||||
SkIRect ir = r.round();
|
||||
if (ir.isEmpty() || !SkIRect::Intersects(ir, clip.getBounds())) {
|
||||
return;
|
||||
}
|
||||
|
@ -5,7 +5,10 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkCanvas.h"
|
||||
#include "SkSurface.h"
|
||||
#include "SkVertices.h"
|
||||
#include "sk_pixel_iter.h"
|
||||
#include "Test.h"
|
||||
|
||||
static bool equal(const SkVertices* v0, const SkVertices* v1) {
|
||||
@ -86,3 +89,30 @@ DEF_TEST(Vertices, reporter) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_triangle(SkCanvas* canvas, const SkPoint pts[], SkColor c) {
|
||||
SkColor colors[] = { c, c, c };
|
||||
auto verts = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, 3, pts, nullptr, colors);
|
||||
canvas->drawVertices(verts, SkBlendMode::kSrc, SkPaint());
|
||||
}
|
||||
|
||||
DEF_TEST(Vertices_clipping, reporter) {
|
||||
// A very large triangle has to be geometrically clipped (since its "fast" clipping is
|
||||
// normally done in after building SkFixed coordinates). Check that we handle this.
|
||||
// (and don't assert).
|
||||
auto surf = SkSurface::MakeRasterN32Premul(3, 3);
|
||||
|
||||
SkPoint pts[] = { { -10, 1 }, { -10, 2 }, { 1e9f, 1.5f } };
|
||||
fill_triangle(surf->getCanvas(), pts, SK_ColorBLACK);
|
||||
|
||||
sk_tool_utils::PixelIter iter(surf.get());
|
||||
SkIPoint loc;
|
||||
while (void* addr = iter.next(&loc)) {
|
||||
SkPMColor c = *(SkPMColor*)addr;
|
||||
if (loc.fY == 1) {
|
||||
REPORTER_ASSERT(reporter, c == 0xFF000000);
|
||||
} else {
|
||||
REPORTER_ASSERT(reporter, c == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
61
tools/sk_pixel_iter.h
Normal file
61
tools/sk_pixel_iter.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef sk_pixel_iter_DEFINED
|
||||
#define sk_pixel_iter_DEFINED
|
||||
|
||||
#include "SkPixmap.h"
|
||||
#include "SkSurface.h"
|
||||
|
||||
namespace sk_tool_utils {
|
||||
|
||||
class PixelIter {
|
||||
public:
|
||||
PixelIter();
|
||||
PixelIter(SkSurface* surf) {
|
||||
SkPixmap pm;
|
||||
if (!surf->peekPixels(&pm)) {
|
||||
pm.reset();
|
||||
}
|
||||
this->reset(pm);
|
||||
}
|
||||
|
||||
void reset(const SkPixmap& pm) {
|
||||
fPM = pm;
|
||||
fLoc = { -1, 0 };
|
||||
}
|
||||
|
||||
void* next(SkIPoint* loc = nullptr) {
|
||||
if (!fPM.addr()) {
|
||||
return nullptr;
|
||||
}
|
||||
fLoc.fX += 1;
|
||||
if (fLoc.fX >= fPM.width()) {
|
||||
fLoc.fX = 0;
|
||||
if (++fLoc.fY >= fPM.height()) {
|
||||
this->setDone();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (loc) {
|
||||
*loc = fLoc;
|
||||
}
|
||||
return fPM.writable_addr(fLoc.fX, fLoc.fY);
|
||||
}
|
||||
|
||||
void setDone() {
|
||||
fPM.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
SkPixmap fPM;
|
||||
SkIPoint fLoc;
|
||||
};
|
||||
|
||||
} // namespace sk_tool_utils
|
||||
|
||||
#endif // sk_tool_utils_DEFINED
|
Loading…
Reference in New Issue
Block a user