Altered arcTo's canonical points to (usually) be convex
https://codereview.appspot.com/6709051/ This will require rebaselining of: degeneratesegments, shadertext & shadertext2 git-svn-id: http://skia.googlecode.com/svn/trunk@5997 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
872017694b
commit
b95eaa8d08
@ -672,6 +672,8 @@ private:
|
||||
};
|
||||
|
||||
// Chrome creates its own round rects with each corner possibly being different
|
||||
// Note: PathTest::test_arb_round_rect_is_convex performs almost exactly
|
||||
// the same test (but with no drawing)
|
||||
class ArbRoundRectBench : public SkBenchmark {
|
||||
protected:
|
||||
SkString fName;
|
||||
@ -727,8 +729,7 @@ protected:
|
||||
add_corner_arc(path, r, xCorner, yCorner, 90);
|
||||
add_corner_arc(path, r, xCorner, yCorner, 180);
|
||||
|
||||
// TODO: re-enable once arcTo convexity issue is resolved
|
||||
//SkASSERT(path->isConvex());
|
||||
SkASSERT(path->isConvex());
|
||||
}
|
||||
|
||||
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
|
||||
@ -741,6 +742,9 @@ protected:
|
||||
paint.setAntiAlias(true);
|
||||
|
||||
SkScalar radius = rand.nextUScalar1() * 30;
|
||||
if (radius < SK_Scalar1) {
|
||||
continue;
|
||||
}
|
||||
r.fLeft = rand.nextUScalar1() * 300;
|
||||
r.fTop = rand.nextUScalar1() * 300;
|
||||
r.fRight = r.fLeft + 2 * radius;
|
||||
|
@ -1254,28 +1254,47 @@ static bool quad_pt2OffCurve(const SkPoint quad[3], SkScalar x, SkScalar y, SkPo
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef SK_SCALAR_IS_FLOAT
|
||||
// Due to floating point issues (i.e., 1.0f - SK_ScalarRoot2Over2 !=
|
||||
// SK_ScalarRoot2Over2 - SK_ScalarTanPIOver8) a cruder root2over2
|
||||
// approximation is required to make the quad circle points convex. The
|
||||
// root of the problem is that with the root2over2 value in SkScalar.h
|
||||
// the arcs really are ever so slightly concave. Some alternative fixes
|
||||
// to this problem (besides just arbitrarily pushing out the mid-point as
|
||||
// is done here) are:
|
||||
// Adjust all the points (not just the middle) to both better approximate
|
||||
// the curve and remain convex
|
||||
// Switch over to using cubics rather then quads
|
||||
// Use a different method to create the mid-point (e.g., compute
|
||||
// the two side points, average them, then move it out as needed
|
||||
#define SK_ScalarRoot2Over2_QuadCircle 0.7072f
|
||||
#else
|
||||
#define SK_ScalarRoot2Over2_QuadCircle SK_FixedRoot2Over2
|
||||
#endif
|
||||
|
||||
|
||||
static const SkPoint gQuadCirclePts[kSkBuildQuadArcStorage] = {
|
||||
{ SK_Scalar1, 0 },
|
||||
{ SK_Scalar1, SK_ScalarTanPIOver8 },
|
||||
{ SK_ScalarRoot2Over2, SK_ScalarRoot2Over2 },
|
||||
{ SK_ScalarTanPIOver8, SK_Scalar1 },
|
||||
{ SK_Scalar1, 0 },
|
||||
{ SK_Scalar1, SK_ScalarTanPIOver8 },
|
||||
{ SK_ScalarRoot2Over2_QuadCircle, SK_ScalarRoot2Over2_QuadCircle },
|
||||
{ SK_ScalarTanPIOver8, SK_Scalar1 },
|
||||
|
||||
{ 0, SK_Scalar1 },
|
||||
{ -SK_ScalarTanPIOver8, SK_Scalar1 },
|
||||
{ -SK_ScalarRoot2Over2, SK_ScalarRoot2Over2 },
|
||||
{ -SK_Scalar1, SK_ScalarTanPIOver8 },
|
||||
{ 0, SK_Scalar1 },
|
||||
{ -SK_ScalarTanPIOver8, SK_Scalar1 },
|
||||
{ -SK_ScalarRoot2Over2_QuadCircle, SK_ScalarRoot2Over2_QuadCircle },
|
||||
{ -SK_Scalar1, SK_ScalarTanPIOver8 },
|
||||
|
||||
{ -SK_Scalar1, 0 },
|
||||
{ -SK_Scalar1, -SK_ScalarTanPIOver8 },
|
||||
{ -SK_ScalarRoot2Over2, -SK_ScalarRoot2Over2 },
|
||||
{ -SK_ScalarTanPIOver8, -SK_Scalar1 },
|
||||
{ -SK_Scalar1, 0 },
|
||||
{ -SK_Scalar1, -SK_ScalarTanPIOver8 },
|
||||
{ -SK_ScalarRoot2Over2_QuadCircle, -SK_ScalarRoot2Over2_QuadCircle },
|
||||
{ -SK_ScalarTanPIOver8, -SK_Scalar1 },
|
||||
|
||||
{ 0, -SK_Scalar1 },
|
||||
{ SK_ScalarTanPIOver8, -SK_Scalar1 },
|
||||
{ SK_ScalarRoot2Over2, -SK_ScalarRoot2Over2 },
|
||||
{ SK_Scalar1, -SK_ScalarTanPIOver8 },
|
||||
{ 0, -SK_Scalar1 },
|
||||
{ SK_ScalarTanPIOver8, -SK_Scalar1 },
|
||||
{ SK_ScalarRoot2Over2_QuadCircle, -SK_ScalarRoot2Over2_QuadCircle },
|
||||
{ SK_Scalar1, -SK_ScalarTanPIOver8 },
|
||||
|
||||
{ SK_Scalar1, 0 }
|
||||
{ SK_Scalar1, 0 }
|
||||
};
|
||||
|
||||
int SkBuildQuadArc(const SkVector& uStart, const SkVector& uStop,
|
||||
|
@ -77,6 +77,72 @@ static void test_isfinite_after_transform(skiatest::Reporter* reporter) {
|
||||
REPORTER_ASSERT(reporter, path.getBounds().isEmpty());
|
||||
}
|
||||
|
||||
static void add_corner_arc(SkPath* path, const SkRect& rect,
|
||||
SkScalar xIn, SkScalar yIn,
|
||||
int startAngle)
|
||||
{
|
||||
|
||||
SkScalar rx = SkMinScalar(rect.width(), xIn);
|
||||
SkScalar ry = SkMinScalar(rect.height(), yIn);
|
||||
|
||||
SkRect arcRect;
|
||||
arcRect.set(-rx, -ry, rx, ry);
|
||||
switch (startAngle) {
|
||||
case 0:
|
||||
arcRect.offset(rect.fRight - arcRect.fRight, rect.fBottom - arcRect.fBottom);
|
||||
break;
|
||||
case 90:
|
||||
arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fBottom - arcRect.fBottom);
|
||||
break;
|
||||
case 180:
|
||||
arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fTop - arcRect.fTop);
|
||||
break;
|
||||
case 270:
|
||||
arcRect.offset(rect.fRight - arcRect.fRight, rect.fTop - arcRect.fTop);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
path->arcTo(arcRect, SkIntToScalar(startAngle), SkIntToScalar(90), false);
|
||||
}
|
||||
|
||||
static void make_arb_round_rect(SkPath* path, const SkRect& r,
|
||||
SkScalar xCorner, SkScalar yCorner) {
|
||||
// we are lazy here and use the same x & y for each corner
|
||||
add_corner_arc(path, r, xCorner, yCorner, 270);
|
||||
add_corner_arc(path, r, xCorner, yCorner, 0);
|
||||
add_corner_arc(path, r, xCorner, yCorner, 90);
|
||||
add_corner_arc(path, r, xCorner, yCorner, 180);
|
||||
}
|
||||
|
||||
// Chrome creates its own round rects with each corner possibly being different.
|
||||
// Performance will suffer if they are not convex.
|
||||
// Note: PathBench::ArbRoundRectBench performs almost exactly
|
||||
// the same test (but with drawing)
|
||||
static void test_arb_round_rect_is_convex(skiatest::Reporter* reporter) {
|
||||
SkRandom rand;
|
||||
SkRect r;
|
||||
|
||||
for (int i = 0; i < 5000; ++i) {
|
||||
|
||||
SkScalar radius = rand.nextUScalar1() * 30;
|
||||
if (radius < SK_Scalar1) {
|
||||
continue;
|
||||
}
|
||||
r.fLeft = rand.nextUScalar1() * 300;
|
||||
r.fTop = rand.nextUScalar1() * 300;
|
||||
r.fRight = r.fLeft + 2 * radius;
|
||||
r.fBottom = r.fTop + 2 * radius;
|
||||
|
||||
SkPath temp;
|
||||
|
||||
make_arb_round_rect(&temp, r, r.width() / 10, r.height() / 15);
|
||||
|
||||
REPORTER_ASSERT(reporter, temp.isConvex());
|
||||
}
|
||||
}
|
||||
|
||||
static void test_rect_isfinite(skiatest::Reporter* reporter) {
|
||||
const SkScalar inf = SK_ScalarInfinity;
|
||||
const SkScalar nan = SK_ScalarNaN;
|
||||
@ -1616,6 +1682,7 @@ static void TestPath(skiatest::Reporter* reporter) {
|
||||
test_isfinite(reporter);
|
||||
test_isfinite_after_transform(reporter);
|
||||
test_tricky_cubic(reporter);
|
||||
test_arb_round_rect_is_convex(reporter);
|
||||
}
|
||||
|
||||
#include "TestClassDef.h"
|
||||
|
Loading…
Reference in New Issue
Block a user