Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(230)

Unified Diff: src/core/SkScan_Path.cpp

Issue 1893433002: In SkDraw::drawRect, use SkPath for huge rects. Base URL: https://skia.googlesource.com/skia@fixed-assert
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/core/SkScan_Hairline.cpp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkScan_Path.cpp
diff --git a/src/core/SkScan_Path.cpp b/src/core/SkScan_Path.cpp
index 884f785299925794ee747828ef7d2c6dd4b0ebec..40e3e241f2be13ae59d902fb46ff88b5860fb630 100644
--- a/src/core/SkScan_Path.cpp
+++ b/src/core/SkScan_Path.cpp
@@ -545,26 +545,27 @@ void sk_blit_below(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip)
/**
* If the caller is drawing an inverse-fill path, then it pass true for
- * skipRejectTest, so we don't abort drawing just because the src bounds (ir)
+ * skipRejectTest, so we don't abort drawing just because the src bounds
* is outside of the clip.
*/
SkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip,
- const SkIRect& ir, bool skipRejectTest) {
+ const SkIRect& bounds, bool skipRejectTest, bool boundsIsTruncated) {
fBlitter = nullptr; // null means blit nothing
fClipRect = nullptr;
if (clip) {
fClipRect = &clip->getBounds();
- if (!skipRejectTest && !SkIRect::Intersects(*fClipRect, ir)) { // completely clipped out
+ if (!skipRejectTest && !SkIRect::Intersects(*fClipRect, bounds)) { // completely clipped out
return;
}
if (clip->isRect()) {
- if (fClipRect->contains(ir)) {
+ if (!boundsIsTruncated && fClipRect->contains(bounds)) {
fClipRect = nullptr;
} else {
// only need a wrapper blitter if we're horizontally clipped
- if (fClipRect->fLeft > ir.fLeft || fClipRect->fRight < ir.fRight) {
+ if (boundsIsTruncated ||
+ fClipRect->fLeft > bounds.fLeft || fClipRect->fRight < bounds.fRight) {
fRectBlitter.init(blitter, *fClipRect);
blitter = &fRectBlitter;
}
@@ -609,6 +610,8 @@ static inline int round_down_to_int(SkScalar x) {
* which may be slower than calling SkScalarRountToInt(), but gives slightly more accurate
* results. Also rounds top and left using double, flooring when the fraction is exactly 0.5f.
*
+ * When src has huge coordinates, clips dst by clip and returns true.
+ *
* e.g.
* SkScalar left = 0.5f;
* int ileft = SkScalarRoundToInt(left);
@@ -621,10 +624,23 @@ static inline int round_down_to_int(SkScalar x) {
* iright = SkDScalarRoundToInt(right);
* SkASSERT(0 == iright); // <--- succeeds
*/
-static void round_asymmetric_to_int(const SkRect& src, SkIRect* dst) {
+static bool round_asymmetric_to_int(const SkRect& src, const SkIRect& clip, SkIRect* dst) {
SkASSERT(dst);
- dst->set(round_down_to_int(src.fLeft), round_down_to_int(src.fTop),
- SkDScalarRoundToInt(src.fRight), SkDScalarRoundToInt(src.fBottom));
+ static const int32_t kLimit = 32767;
+ const SkIRect max = SkIRect::MakeLTRB(-kLimit, -kLimit, kLimit, kLimit);
+ if (max.contains(src)) {
+ dst->set(round_down_to_int(src.fLeft), round_down_to_int(src.fTop),
+ SkDScalarRoundToInt(src.fRight), SkDScalarRoundToInt(src.fBottom));
+ return false;
+ }
+ SkRect clipped;
+ if (clipped.intersect(src, SkRect::Make(clip))) {
+ dst->set(round_down_to_int(clipped.fLeft), round_down_to_int(clipped.fTop),
+ SkDScalarRoundToInt(clipped.fRight), SkDScalarRoundToInt(clipped.fBottom));
+ } else {
+ dst->setEmpty();
+ }
+ return true;
}
void SkScan::FillPath(const SkPath& path, const SkRegion& origClip,
@@ -650,7 +666,7 @@ void SkScan::FillPath(const SkPath& path, const SkRegion& origClip,
// to generate a bounds that is tighter than the corresponding SkEdges. The edge code basically
// converts the floats to fixed, and then "rounds". If we called round() instead of
// round_asymmetric_to_int() here, we could generate the wrong ir for values like 0.4999997.
- round_asymmetric_to_int(path.getBounds(), &ir);
+ bool irIsClipped = round_asymmetric_to_int(path.getBounds(), clipPtr->getBounds(), &ir);
if (ir.isEmpty()) {
if (path.isInverseFillType()) {
blitter->blitRegion(*clipPtr);
@@ -658,7 +674,7 @@ void SkScan::FillPath(const SkPath& path, const SkRegion& origClip,
return;
}
- SkScanClipper clipper(blitter, clipPtr, ir, path.isInverseFillType());
+ SkScanClipper clipper(blitter, clipPtr, ir, path.isInverseFillType(), irIsClipped);
blitter = clipper.getBlitter();
if (blitter) {
« no previous file with comments | « src/core/SkScan_Hairline.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698