cull edges that are to the right of the clip

BUG=skia:

Review URL: https://codereview.chromium.org/913503002
This commit is contained in:
reed 2015-02-09 08:33:07 -08:00 committed by Commit bot
parent 70a8ca8351
commit 31223e0cb7
7 changed files with 30 additions and 24 deletions

View File

@ -80,7 +80,7 @@ static void setShiftedClip(SkRect* dst, const SkIRect& src, int shift) {
} }
int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shiftUp, int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shiftUp,
bool clipToTheRight) { bool canCullToTheRight) {
SkPath::Iter iter(path, true); SkPath::Iter iter(path, true);
SkPoint pts[4]; SkPoint pts[4];
SkPath::Verb verb; SkPath::Verb verb;
@ -115,7 +115,7 @@ int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shift
break; break;
case SkPath::kLine_Verb: { case SkPath::kLine_Verb: {
SkPoint lines[SkLineClipper::kMaxPoints]; SkPoint lines[SkLineClipper::kMaxPoints];
int lineCount = SkLineClipper::ClipLine(pts, clip, lines, clipToTheRight); int lineCount = SkLineClipper::ClipLine(pts, clip, lines, canCullToTheRight);
SkASSERT(lineCount <= SkLineClipper::kMaxClippedLineSegments); SkASSERT(lineCount <= SkLineClipper::kMaxClippedLineSegments);
for (int i = 0; i < lineCount; i++) { for (int i = 0; i < lineCount; i++) {
if (edge->setLine(lines[i], lines[i + 1], shiftUp)) { if (edge->setLine(lines[i], lines[i + 1], shiftUp)) {
@ -162,13 +162,13 @@ static void handle_quad(SkEdgeBuilder* builder, const SkPoint pts[3]) {
} }
int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip, int shiftUp, int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip, int shiftUp,
bool clipToTheRight) { bool canCullToTheRight) {
fAlloc.reset(); fAlloc.reset();
fList.reset(); fList.reset();
fShiftUp = shiftUp; fShiftUp = shiftUp;
if (SkPath::kLine_SegmentMask == path.getSegmentMasks()) { if (SkPath::kLine_SegmentMask == path.getSegmentMasks()) {
return this->buildPoly(path, iclip, shiftUp, clipToTheRight); return this->buildPoly(path, iclip, shiftUp, canCullToTheRight);
} }
SkAutoConicToQuads quadder; SkAutoConicToQuads quadder;
@ -181,7 +181,7 @@ int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip, int shiftUp,
if (iclip) { if (iclip) {
SkRect clip; SkRect clip;
setShiftedClip(&clip, *iclip, shiftUp); setShiftedClip(&clip, *iclip, shiftUp);
SkEdgeClipper clipper; SkEdgeClipper clipper(canCullToTheRight);
while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) {
switch (verb) { switch (verb) {
@ -192,7 +192,7 @@ int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip, int shiftUp,
break; break;
case SkPath::kLine_Verb: { case SkPath::kLine_Verb: {
SkPoint lines[SkLineClipper::kMaxPoints]; SkPoint lines[SkLineClipper::kMaxPoints];
int lineCount = SkLineClipper::ClipLine(pts, clip, lines, clipToTheRight); int lineCount = SkLineClipper::ClipLine(pts, clip, lines, canCullToTheRight);
for (int i = 0; i < lineCount; i++) { for (int i = 0; i < lineCount; i++) {
this->addLine(&lines[i]); this->addLine(&lines[i]);
} }

View File

@ -148,7 +148,9 @@ void SkEdgeClipper::clipMonoQuad(const SkPoint srcPts[3], const SkRect& clip) {
return; return;
} }
if (pts[0].fX >= clip.fRight) { // wholly to the right if (pts[0].fX >= clip.fRight) { // wholly to the right
this->appendVLine(clip.fRight, pts[0].fY, pts[2].fY, reverse); if (!this->canCullToTheRight()) {
this->appendVLine(clip.fRight, pts[0].fY, pts[2].fY, reverse);
}
return; return;
} }
@ -350,7 +352,9 @@ void SkEdgeClipper::clipMonoCubic(const SkPoint src[4], const SkRect& clip) {
return; return;
} }
if (pts[0].fX >= clip.fRight) { // wholly to the right if (pts[0].fX >= clip.fRight) { // wholly to the right
this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse); if (!this->canCullToTheRight()) {
this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse);
}
return; return;
} }

View File

@ -17,14 +17,19 @@
*/ */
class SkEdgeClipper { class SkEdgeClipper {
public: public:
SkEdgeClipper(bool canCullToTheRight) : fCanCullToTheRight(canCullToTheRight) {}
bool clipQuad(const SkPoint pts[3], const SkRect& clip); bool clipQuad(const SkPoint pts[3], const SkRect& clip);
bool clipCubic(const SkPoint pts[4], const SkRect& clip); bool clipCubic(const SkPoint pts[4], const SkRect& clip);
SkPath::Verb next(SkPoint pts[]); SkPath::Verb next(SkPoint pts[]);
bool canCullToTheRight() const { return fCanCullToTheRight; }
private: private:
SkPoint* fCurrPoint; SkPoint* fCurrPoint;
SkPath::Verb* fCurrVerb; SkPath::Verb* fCurrVerb;
const bool fCanCullToTheRight;
enum { enum {
kMaxVerbs = 13, kMaxVerbs = 13,

View File

@ -1,10 +1,10 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "SkLineClipper.h" #include "SkLineClipper.h"
template <typename T> T pin_unsorted(T value, T limit0, T limit1) { template <typename T> T pin_unsorted(T value, T limit0, T limit1) {
@ -172,12 +172,8 @@ static void sect_with_horizontal_test_for_pin_results() {
} }
#endif #endif
int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip, int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip, SkPoint lines[],
SkPoint lines[], bool canClipToTheRight) { bool canCullToTheRight) {
#if 1
// Disable this while we investigate layouttest failures
canClipToTheRight = false;
#endif
#ifdef SK_DEBUG #ifdef SK_DEBUG
{ {
@ -246,7 +242,7 @@ int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip,
result = tmp; result = tmp;
reverse = false; reverse = false;
} else if (tmp[index0].fX >= clip.fRight) { // wholly to the right } else if (tmp[index0].fX >= clip.fRight) { // wholly to the right
if (canClipToTheRight) { if (canCullToTheRight) {
return 0; return 0;
} }
tmp[0].fX = tmp[1].fX = clip.fRight; tmp[0].fX = tmp[1].fX = clip.fRight;

View File

@ -30,7 +30,7 @@ public:
3rd segment: lines[2]..lines[3] 3rd segment: lines[2]..lines[3]
*/ */
static int ClipLine(const SkPoint pts[2], const SkRect& clip, static int ClipLine(const SkPoint pts[2], const SkRect& clip,
SkPoint lines[kMaxPoints], bool canClipToTheRight); SkPoint lines[kMaxPoints], bool canCullToTheRight);
/* Intersect the line segment against the rect. If there is a non-empty /* Intersect the line segment against the rect. If there is a non-empty
resulting segment, return true and set dst[] to that segment. If not, resulting segment, return true and set dst[] to that segment. If not,
@ -40,8 +40,7 @@ public:
segments on the sides to show where the line extended beyond the segments on the sides to show where the line extended beyond the
left or right sides. IntersectLine does not. left or right sides. IntersectLine does not.
*/ */
static bool IntersectLine(const SkPoint src[2], const SkRect& clip, static bool IntersectLine(const SkPoint src[2], const SkRect& clip, SkPoint dst[2]);
SkPoint dst[2]);
}; };
#endif #endif

View File

@ -431,12 +431,14 @@ void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitte
SkEdgeBuilder builder; SkEdgeBuilder builder;
// If we're convex, then we need both edges, even the right edge is past the clip // If we're convex, then we need both edges, even the right edge is past the clip
const bool cullToTheRight = !path.isConvex(); const bool canCullToTheRight = !path.isConvex();
int count = builder.build(path, clipRect, shiftEdgesUp, canCullToTheRight);
SkASSERT(count >= 0);
int count = builder.build(path, clipRect, shiftEdgesUp, cullToTheRight);
SkEdge** list = builder.edgeList(); SkEdge** list = builder.edgeList();
if (count < 2) { if (0 == count) {
if (path.isInverseFillType()) { if (path.isInverseFillType()) {
/* /*
* Since we are in inverse-fill, our caller has already drawn above * Since we are in inverse-fill, our caller has already drawn above
@ -458,7 +460,6 @@ void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitte
rect.height() << shiftEdgesUp); rect.height() << shiftEdgesUp);
} }
} }
return; return;
} }
@ -498,6 +499,7 @@ void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitte
} }
if (path.isConvex() && (NULL == proc)) { if (path.isConvex() && (NULL == proc)) {
SkASSERT(count >= 2); // convex walker does not handle missing right edges
walk_convex_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, NULL); walk_convex_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, NULL);
} else { } else {
int rightEdge; int rightEdge;

View File

@ -48,7 +48,7 @@ static void test_hairclipping(skiatest::Reporter* reporter) {
} }
static void test_edgeclipper() { static void test_edgeclipper() {
SkEdgeClipper clipper; SkEdgeClipper clipper(false);
const SkPoint pts[] = { const SkPoint pts[] = {
{ 3.0995476e+010f, 42.929779f }, { 3.0995476e+010f, 42.929779f },