GM (and fix) for drawArc capping issue

https://codereview.chromium.org/18271003/



git-svn-id: http://skia.googlecode.com/svn/trunk@9928 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
robertphillips@google.com 2013-07-09 15:03:59 +00:00
parent 387db0a2e5
commit e1b75b4096
3 changed files with 95 additions and 8 deletions

83
gm/arcofzorro.cpp Normal file
View File

@ -0,0 +1,83 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "gm.h"
#include "SkRandom.h"
namespace skiagm {
// This GM draws a lot of arcs in a 'Z' shape. It particularly exercises
// the 'drawArc' code near a singularly of its processing (i.e., near the
// edge of one of its underlying quads).
class ArcOfZorroGM : public GM {
public:
ArcOfZorroGM() {
this->setBGColor(0xFFCCCCCC);
}
protected:
virtual SkString onShortName() SK_OVERRIDE {
return SkString("arcofzorro");
}
virtual SkISize onISize() SK_OVERRIDE {
return make_isize(1000, 1000);
}
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
SkMWCRandom rand;
SkRect rect = SkRect::MakeXYWH(10, 10, 200, 200);
SkPaint p;
p.setStyle(SkPaint::kStroke_Style);
p.setStrokeWidth(35);
int xOffset = 0, yOffset = 0;
int direction = 0;
for (float arc = 134.0f; arc < 136.0f; arc += 0.01f) {
SkColor color = rand.nextU();
color |= 0xff000000;
p.setColor(color);
canvas->save();
canvas->translate(SkIntToScalar(xOffset), SkIntToScalar(yOffset));
canvas->drawArc(rect, 0, arc, false, p);
canvas->restore();
switch (direction) {
case 0:
xOffset += 10;
if (xOffset >= 700) {
direction = 1;
}
break;
case 1:
xOffset -= 10;
yOffset += 10;
if (xOffset < 50) {
direction = 2;
}
break;
case 2:
xOffset += 10;
break;
}
}
}
private:
typedef GM INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
DEF_GM( return SkNEW(ArcOfZorroGM); )
}

View File

@ -4,6 +4,7 @@
'../gm/aaclip.cpp',
'../gm/aarectmodes.cpp',
'../gm/alphagradients.cpp',
'../gm/arcofzorro.cpp',
'../gm/arithmode.cpp',
'../gm/bicubicfilter.cpp',
'../gm/bigmatrix.cpp',

View File

@ -1205,11 +1205,13 @@ static SkScalar quad_solve(SkScalar a, SkScalar b, SkScalar c, SkScalar d)
return count == 1 ? roots[0] : 0;
}
/* given a quad-curve and a point (x,y), chop the quad at that point and return
the new quad's offCurve point. Should only return false if the computed pos
is the start of the curve (i.e. root == 0)
/* given a quad-curve and a point (x,y), chop the quad at that point and place
the new off-curve point and endpoint into 'dest'. The new end point is used
(rather than (x,y)) to compensate for numerical inaccuracies.
Should only return false if the computed pos is the start of the curve
(i.e. root == 0)
*/
static bool quad_pt2OffCurve(const SkPoint quad[3], SkScalar x, SkScalar y, SkPoint* offCurve)
static bool truncate_last_curve(const SkPoint quad[3], SkScalar x, SkScalar y, SkPoint* dest)
{
const SkScalar* base;
SkScalar value;
@ -1230,7 +1232,8 @@ static bool quad_pt2OffCurve(const SkPoint quad[3], SkScalar x, SkScalar y, SkPo
{
SkPoint tmp[5];
SkChopQuadAt(quad, tmp, t);
*offCurve = tmp[1];
dest[0] = tmp[1];
dest[1] = tmp[2];
return true;
} else {
/* t == 0 means either the value triggered a root outside of [0, 1)
@ -1247,7 +1250,8 @@ static bool quad_pt2OffCurve(const SkPoint quad[3], SkScalar x, SkScalar y, SkPo
if ((base[0] < base[4] && value > base[2]) ||
(base[0] > base[4] && value < base[2])) // should root have been 1
{
*offCurve = quad[1];
dest[0] = quad[1];
dest[1].set(x, y);
return true;
}
}
@ -1360,9 +1364,8 @@ int SkBuildQuadArc(const SkVector& uStart, const SkVector& uStop,
memcpy(quadPoints, gQuadCirclePts, (wholeCount + 1) * sizeof(SkPoint));
const SkPoint* arc = &gQuadCirclePts[wholeCount];
if (quad_pt2OffCurve(arc, x, y, &quadPoints[wholeCount + 1]))
if (truncate_last_curve(arc, x, y, &quadPoints[wholeCount + 1]))
{
quadPoints[wholeCount + 2].set(x, y);
wholeCount += 2;
}
pointCount = wholeCount + 1;