use quads for mixed radius rrects
Create a specialized version of adding a pair of corner quads that avoids the overhead of the full arc machinery. This is on the way to changing Chrome to calling Skia directly to create fully general round rects rather than rolling their own. R=robertphillips@google.com, reed@google.com Author: caryclark@google.com Review URL: https://codereview.chromium.org/60203002 git-svn-id: http://skia.googlecode.com/svn/trunk@12190 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
c78b8f2f73
commit
42feaaf0a5
@ -950,41 +950,6 @@ static int build_arc_points(const SkRect& oval, SkScalar startAngle,
|
||||
&matrix, pts);
|
||||
}
|
||||
|
||||
static void add_corner_arc(SkPath* path, const SkRect& rect,
|
||||
SkScalar rx, SkScalar ry, int startAngle,
|
||||
SkPath::Direction dir, bool forceMoveTo) {
|
||||
// These two asserts are not sufficient, since really we want to know
|
||||
// that the pair of radii (e.g. left and right, or top and bottom) sum
|
||||
// to <= dimension, but we don't have that data here, so we just have
|
||||
// these conservative asserts.
|
||||
SkASSERT(0 <= rx && rx <= rect.width());
|
||||
SkASSERT(0 <= ry && ry <= rect.height());
|
||||
|
||||
SkRect r;
|
||||
r.set(-rx, -ry, rx, ry);
|
||||
|
||||
switch (startAngle) {
|
||||
case 0:
|
||||
r.offset(rect.fRight - r.fRight, rect.fBottom - r.fBottom);
|
||||
break;
|
||||
case 90:
|
||||
r.offset(rect.fLeft - r.fLeft, rect.fBottom - r.fBottom);
|
||||
break;
|
||||
case 180: r.offset(rect.fLeft - r.fLeft, rect.fTop - r.fTop); break;
|
||||
case 270: r.offset(rect.fRight - r.fRight, rect.fTop - r.fTop); break;
|
||||
default: SkDEBUGFAIL("unexpected startAngle in add_corner_arc");
|
||||
}
|
||||
|
||||
SkScalar start = SkIntToScalar(startAngle);
|
||||
SkScalar sweep = SkIntToScalar(90);
|
||||
if (SkPath::kCCW_Direction == dir) {
|
||||
start += sweep;
|
||||
sweep = -sweep;
|
||||
}
|
||||
|
||||
path->arcTo(r, start, sweep, forceMoveTo);
|
||||
}
|
||||
|
||||
void SkPath::addRoundRect(const SkRect& rect, const SkScalar radii[],
|
||||
Direction dir) {
|
||||
SkRRect rrect;
|
||||
@ -992,6 +957,131 @@ void SkPath::addRoundRect(const SkRect& rect, const SkScalar radii[],
|
||||
this->addRRect(rrect, dir);
|
||||
}
|
||||
|
||||
/* The inline clockwise and counterclockwise round rect quad approximations
|
||||
make it easier to see the symmetry patterns used by add corner quads.
|
||||
Clockwise corner value
|
||||
path->lineTo(rect.fLeft, rect.fTop + ry); 0 upper left
|
||||
path->quadTo(rect.fLeft, rect.fTop + offPtY,
|
||||
rect.fLeft + midPtX, rect.fTop + midPtY);
|
||||
path->quadTo(rect.fLeft + offPtX, rect.fTop,
|
||||
rect.fLeft + rx, rect.fTop);
|
||||
|
||||
path->lineTo(rect.fRight - rx, rect.fTop); 1 upper right
|
||||
path->quadTo(rect.fRight - offPtX, rect.fTop,
|
||||
rect.fRight - midPtX, rect.fTop + midPtY);
|
||||
path->quadTo(rect.fRight, rect.fTop + offPtY,
|
||||
rect.fRight, rect.fTop + ry);
|
||||
|
||||
path->lineTo(rect.fRight, rect.fBottom - ry); 2 lower right
|
||||
path->quadTo(rect.fRight, rect.fBottom - offPtY,
|
||||
rect.fRight - midPtX, rect.fBottom - midPtY);
|
||||
path->quadTo(rect.fRight - offPtX, rect.fBottom,
|
||||
rect.fRight - rx, rect.fBottom);
|
||||
|
||||
path->lineTo(rect.fLeft + rx, rect.fBottom); 3 lower left
|
||||
path->quadTo(rect.fLeft + offPtX, rect.fBottom,
|
||||
rect.fLeft + midPtX, rect.fBottom - midPtY);
|
||||
path->quadTo(rect.fLeft, rect.fBottom - offPtY,
|
||||
rect.fLeft, rect.fBottom - ry);
|
||||
|
||||
Counterclockwise
|
||||
path->lineTo(rect.fLeft, rect.fBottom - ry); 3 lower left
|
||||
path->quadTo(rect.fLeft, rect.fBottom - offPtY,
|
||||
rect.fLeft + midPtX, rect.fBottom - midPtY);
|
||||
path->quadTo(rect.fLeft + offPtX, rect.fBottom,
|
||||
rect.fLeft + rx, rect.fBottom);
|
||||
|
||||
path->lineTo(rect.fRight - rx, rect.fBottom); 2 lower right
|
||||
path->quadTo(rect.fRight - offPtX, rect.fBottom,
|
||||
rect.fRight - midPtX, rect.fBottom - midPtY);
|
||||
path->quadTo(rect.fRight, rect.fBottom - offPtY,
|
||||
rect.fRight, rect.fBottom - ry);
|
||||
|
||||
path->lineTo(rect.fRight, rect.fTop + ry); 1 upper right
|
||||
path->quadTo(rect.fRight, rect.fTop + offPtY,
|
||||
rect.fRight - midPtX, rect.fTop + midPtY);
|
||||
path->quadTo(rect.fRight - offPtX, rect.fTop,
|
||||
rect.fRight - rx, rect.fTop);
|
||||
|
||||
path->lineTo(rect.fLeft + rx, rect.fTop); 0 upper left
|
||||
path->quadTo(rect.fLeft + offPtX, rect.fTop,
|
||||
rect.fLeft + midPtX, rect.fTop + midPtY);
|
||||
path->quadTo(rect.fLeft, rect.fTop + offPtY,
|
||||
rect.fLeft, rect.fTop + ry);
|
||||
*/
|
||||
static void add_corner_quads(SkPath* path, const SkRRect& rrect,
|
||||
SkRRect::Corner corner, SkPath::Direction dir) {
|
||||
const SkRect& rect = rrect.rect();
|
||||
const SkVector& radii = rrect.radii(corner);
|
||||
SkScalar rx = radii.fX;
|
||||
SkScalar ry = radii.fY;
|
||||
// The mid point of the quadratic arc approximation is half way between the two
|
||||
// control points.
|
||||
SkScalar midPtX = rx - rx * (SK_Scalar1 + SK_ScalarTanPIOver8) / 2;
|
||||
SkScalar midPtY = ry - ry * (SK_Scalar1 + SK_ScalarTanPIOver8) / 2;
|
||||
SkScalar offPtX = rx - rx * SK_ScalarTanPIOver8;
|
||||
SkScalar offPtY = ry - ry * SK_ScalarTanPIOver8;
|
||||
static const int kCornerPts = 5;
|
||||
SkScalar xOff[kCornerPts];
|
||||
SkScalar yOff[kCornerPts];
|
||||
|
||||
if ((corner & 1) == (dir == SkPath::kCCW_Direction)) { // corners always alternate direction
|
||||
SkASSERT(dir == SkPath::kCCW_Direction
|
||||
? corner == SkRRect::kLowerLeft_Corner || corner == SkRRect::kUpperRight_Corner
|
||||
: corner == SkRRect::kUpperLeft_Corner || corner == SkRRect::kLowerRight_Corner);
|
||||
xOff[0] = xOff[1] = 0;
|
||||
xOff[2] = midPtX;
|
||||
xOff[3] = offPtX;
|
||||
xOff[4] = rx;
|
||||
yOff[0] = ry;
|
||||
yOff[1] = offPtY;
|
||||
yOff[2] = midPtY;
|
||||
yOff[3] = yOff[4] = 0;
|
||||
} else {
|
||||
xOff[0] = rx;
|
||||
xOff[1] = offPtX;
|
||||
xOff[2] = midPtX;
|
||||
xOff[3] = xOff[4] = 0;
|
||||
yOff[0] = yOff[1] = 0;
|
||||
yOff[2] = midPtY;
|
||||
yOff[3] = offPtY;
|
||||
yOff[4] = ry;
|
||||
}
|
||||
if ((corner - 1) & 2) {
|
||||
SkASSERT(corner == SkRRect::kLowerLeft_Corner || corner == SkRRect::kUpperLeft_Corner);
|
||||
for (int i = 0; i < kCornerPts; ++i) {
|
||||
xOff[i] = rect.fLeft + xOff[i];
|
||||
}
|
||||
} else {
|
||||
SkASSERT(corner == SkRRect::kLowerRight_Corner || corner == SkRRect::kUpperRight_Corner);
|
||||
for (int i = 0; i < kCornerPts; ++i) {
|
||||
xOff[i] = rect.fRight - xOff[i];
|
||||
}
|
||||
}
|
||||
if (corner < SkRRect::kLowerRight_Corner) {
|
||||
for (int i = 0; i < kCornerPts; ++i) {
|
||||
yOff[i] = rect.fTop + yOff[i];
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < kCornerPts; ++i) {
|
||||
yOff[i] = rect.fBottom - yOff[i];
|
||||
}
|
||||
}
|
||||
|
||||
SkPoint lastPt;
|
||||
SkAssertResult(path->getLastPt(&lastPt));
|
||||
if (lastPt.fX != xOff[0] || lastPt.fY != yOff[0]) {
|
||||
path->lineTo(xOff[0], yOff[0]);
|
||||
}
|
||||
if (rx || ry) {
|
||||
path->quadTo(xOff[1], yOff[1], xOff[2], yOff[2]);
|
||||
path->quadTo(xOff[3], yOff[3], xOff[4], yOff[4]);
|
||||
} else {
|
||||
path->lineTo(xOff[2], yOff[2]);
|
||||
path->lineTo(xOff[4], yOff[4]);
|
||||
}
|
||||
}
|
||||
|
||||
void SkPath::addRRect(const SkRRect& rrect, Direction dir) {
|
||||
assert_known_direction(dir);
|
||||
|
||||
@ -1005,22 +1095,32 @@ void SkPath::addRRect(const SkRRect& rrect, Direction dir) {
|
||||
this->addRect(bounds, dir);
|
||||
} else if (rrect.isOval()) {
|
||||
this->addOval(bounds, dir);
|
||||
#ifdef SK_IGNORE_QUAD_RR_CORNERS_OPT
|
||||
} else if (rrect.isSimple()) {
|
||||
const SkVector& rad = rrect.getSimpleRadii();
|
||||
this->addRoundRect(bounds, rad.x(), rad.y(), dir);
|
||||
#endif
|
||||
} else {
|
||||
SkAutoPathBoundsUpdate apbu(this, bounds);
|
||||
fDirection = this->hasOnlyMoveTos() ? dir : kUnknown_Direction;
|
||||
|
||||
SkAutoPathBoundsUpdate apbu(this, bounds);
|
||||
SkAutoDisableDirectionCheck(this);
|
||||
|
||||
this->incReserve(21);
|
||||
if (kCW_Direction == dir) {
|
||||
add_corner_arc(this, bounds, rrect.fRadii[0].fX, rrect.fRadii[0].fY, 180, dir, true);
|
||||
add_corner_arc(this, bounds, rrect.fRadii[1].fX, rrect.fRadii[1].fY, 270, dir, false);
|
||||
add_corner_arc(this, bounds, rrect.fRadii[2].fX, rrect.fRadii[2].fY, 0, dir, false);
|
||||
add_corner_arc(this, bounds, rrect.fRadii[3].fX, rrect.fRadii[3].fY, 90, dir, false);
|
||||
this->moveTo(bounds.fLeft,
|
||||
bounds.fBottom - rrect.fRadii[SkRRect::kLowerLeft_Corner].fY);
|
||||
add_corner_quads(this, rrect, SkRRect::kUpperLeft_Corner, dir);
|
||||
add_corner_quads(this, rrect, SkRRect::kUpperRight_Corner, dir);
|
||||
add_corner_quads(this, rrect, SkRRect::kLowerRight_Corner, dir);
|
||||
add_corner_quads(this, rrect, SkRRect::kLowerLeft_Corner, dir);
|
||||
} else {
|
||||
add_corner_arc(this, bounds, rrect.fRadii[0].fX, rrect.fRadii[0].fY, 180, dir, true);
|
||||
add_corner_arc(this, bounds, rrect.fRadii[3].fX, rrect.fRadii[3].fY, 90, dir, false);
|
||||
add_corner_arc(this, bounds, rrect.fRadii[2].fX, rrect.fRadii[2].fY, 0, dir, false);
|
||||
add_corner_arc(this, bounds, rrect.fRadii[1].fX, rrect.fRadii[1].fY, 270, dir, false);
|
||||
this->moveTo(bounds.fLeft,
|
||||
bounds.fTop + rrect.fRadii[SkRRect::kUpperLeft_Corner].fY);
|
||||
add_corner_quads(this, rrect, SkRRect::kLowerLeft_Corner, dir);
|
||||
add_corner_quads(this, rrect, SkRRect::kLowerRight_Corner, dir);
|
||||
add_corner_quads(this, rrect, SkRRect::kUpperRight_Corner, dir);
|
||||
add_corner_quads(this, rrect, SkRRect::kUpperLeft_Corner, dir);
|
||||
}
|
||||
this->close();
|
||||
}
|
||||
@ -1056,6 +1156,7 @@ void SkPath::addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SK_IGNORE_QUAD_RR_CORNERS_OPT
|
||||
SkScalar w = rect.width();
|
||||
SkScalar halfW = SkScalarHalf(w);
|
||||
SkScalar h = rect.height();
|
||||
@ -1083,133 +1184,68 @@ void SkPath::addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
|
||||
} else if (skip_vert) {
|
||||
ry = halfH;
|
||||
}
|
||||
#ifdef SK_IGNORE_QUAD_RR_CORNERS_OPT
|
||||
SkScalar sx = SkScalarMul(rx, CUBIC_ARC_FACTOR);
|
||||
SkScalar sy = SkScalarMul(ry, CUBIC_ARC_FACTOR);
|
||||
|
||||
this->incReserve(17);
|
||||
#else
|
||||
// The mid point of the quadratic arc approximation is half way between the two
|
||||
// control points. The float epsilon adjustment moves the on curve point out by
|
||||
// two bits, distributing the convex test error between the round rect approximation
|
||||
// and the convex cross product sign equality test.
|
||||
SkScalar midPtX = rx * (SK_Scalar1 + SK_ScalarTanPIOver8 + FLT_EPSILON * 4) / 2;
|
||||
SkScalar midPtY = ry * (SK_Scalar1 + SK_ScalarTanPIOver8 + FLT_EPSILON * 4) / 2;
|
||||
|
||||
SkScalar offPtX = rx * SK_ScalarTanPIOver8;
|
||||
SkScalar offPtY = ry * SK_ScalarTanPIOver8;
|
||||
|
||||
this->incReserve(21);
|
||||
#endif
|
||||
this->moveTo(rect.fRight - rx, rect.fTop); // top-right
|
||||
if (dir == kCCW_Direction) {
|
||||
if (!skip_hori) {
|
||||
this->lineTo(rect.fLeft + rx, rect.fTop); // top
|
||||
}
|
||||
#ifdef SK_IGNORE_QUAD_RR_CORNERS_OPT
|
||||
this->cubicTo(rect.fLeft + rx - sx, rect.fTop,
|
||||
rect.fLeft, rect.fTop + ry - sy,
|
||||
rect.fLeft, rect.fTop + ry); // top-left
|
||||
#else
|
||||
this->quadTo(rect.fLeft + rx - offPtX, rect.fTop,
|
||||
rect.fLeft + rx - midPtX, rect.fTop + ry - midPtY);
|
||||
this->quadTo(rect.fLeft, rect.fTop + ry - offPtY,
|
||||
rect.fLeft, rect.fTop + ry);
|
||||
#endif
|
||||
if (!skip_vert) {
|
||||
this->lineTo(rect.fLeft, rect.fBottom - ry); // left
|
||||
}
|
||||
#ifdef SK_IGNORE_QUAD_RR_CORNERS_OPT
|
||||
this->cubicTo(rect.fLeft, rect.fBottom - ry + sy,
|
||||
rect.fLeft + rx - sx, rect.fBottom,
|
||||
rect.fLeft + rx, rect.fBottom); // bot-left
|
||||
#else
|
||||
this->quadTo(rect.fLeft, rect.fBottom - ry + offPtY,
|
||||
rect.fLeft + rx - midPtX, rect.fBottom - ry + midPtY);
|
||||
this->quadTo(rect.fLeft + rx - offPtX, rect.fBottom,
|
||||
rect.fLeft + rx, rect.fBottom);
|
||||
#endif
|
||||
if (!skip_hori) {
|
||||
this->lineTo(rect.fRight - rx, rect.fBottom); // bottom
|
||||
}
|
||||
#ifdef SK_IGNORE_QUAD_RR_CORNERS_OPT
|
||||
this->cubicTo(rect.fRight - rx + sx, rect.fBottom,
|
||||
rect.fRight, rect.fBottom - ry + sy,
|
||||
rect.fRight, rect.fBottom - ry); // bot-right
|
||||
#else
|
||||
this->quadTo(rect.fRight - rx + offPtX, rect.fBottom,
|
||||
rect.fRight - rx + midPtX, rect.fBottom - ry + midPtY);
|
||||
this->quadTo(rect.fRight, rect.fBottom - ry + offPtY,
|
||||
rect.fRight, rect.fBottom - ry);
|
||||
#endif
|
||||
if (!skip_vert) {
|
||||
this->lineTo(rect.fRight, rect.fTop + ry); // right
|
||||
}
|
||||
#ifdef SK_IGNORE_QUAD_RR_CORNERS_OPT
|
||||
this->cubicTo(rect.fRight, rect.fTop + ry - sy,
|
||||
rect.fRight - rx + sx, rect.fTop,
|
||||
rect.fRight - rx, rect.fTop); // top-right
|
||||
#else
|
||||
this->quadTo(rect.fRight, rect.fTop + ry - offPtY,
|
||||
rect.fRight - rx + midPtX, rect.fTop + ry - midPtY);
|
||||
this->quadTo(rect.fRight - rx + offPtX, rect.fTop,
|
||||
rect.fRight - rx, rect.fTop);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef SK_IGNORE_QUAD_RR_CORNERS_OPT
|
||||
this->cubicTo(rect.fRight - rx + sx, rect.fTop,
|
||||
rect.fRight, rect.fTop + ry - sy,
|
||||
rect.fRight, rect.fTop + ry); // top-right
|
||||
#else
|
||||
this->quadTo(rect.fRight - rx + offPtX, rect.fTop,
|
||||
rect.fRight - rx + midPtX, rect.fTop + ry - midPtY);
|
||||
this->quadTo(rect.fRight, rect.fTop + ry - offPtY,
|
||||
rect.fRight, rect.fTop + ry);
|
||||
#endif
|
||||
if (!skip_vert) {
|
||||
this->lineTo(rect.fRight, rect.fBottom - ry); // right
|
||||
}
|
||||
#ifdef SK_IGNORE_QUAD_RR_CORNERS_OPT
|
||||
this->cubicTo(rect.fRight, rect.fBottom - ry + sy,
|
||||
rect.fRight - rx + sx, rect.fBottom,
|
||||
rect.fRight - rx, rect.fBottom); // bot-right
|
||||
#else
|
||||
this->quadTo(rect.fRight, rect.fBottom - ry + offPtY,
|
||||
rect.fRight - rx + midPtX, rect.fBottom - ry + midPtY);
|
||||
this->quadTo(rect.fRight - rx + offPtX, rect.fBottom,
|
||||
rect.fRight - rx, rect.fBottom);
|
||||
#endif
|
||||
if (!skip_hori) {
|
||||
this->lineTo(rect.fLeft + rx, rect.fBottom); // bottom
|
||||
}
|
||||
#ifdef SK_IGNORE_QUAD_RR_CORNERS_OPT
|
||||
this->cubicTo(rect.fLeft + rx - sx, rect.fBottom,
|
||||
rect.fLeft, rect.fBottom - ry + sy,
|
||||
rect.fLeft, rect.fBottom - ry); // bot-left
|
||||
#else
|
||||
this->quadTo(rect.fLeft + rx - offPtX, rect.fBottom,
|
||||
rect.fLeft + rx - midPtX, rect.fBottom - ry + midPtY);
|
||||
this->quadTo(rect.fLeft, rect.fBottom - ry + offPtY,
|
||||
rect.fLeft, rect.fBottom - ry);
|
||||
#endif
|
||||
if (!skip_vert) {
|
||||
this->lineTo(rect.fLeft, rect.fTop + ry); // left
|
||||
}
|
||||
#ifdef SK_IGNORE_QUAD_RR_CORNERS_OPT
|
||||
this->cubicTo(rect.fLeft, rect.fTop + ry - sy,
|
||||
rect.fLeft + rx - sx, rect.fTop,
|
||||
rect.fLeft + rx, rect.fTop); // top-left
|
||||
#else
|
||||
this->quadTo(rect.fLeft, rect.fTop + ry - offPtY,
|
||||
rect.fLeft + rx - midPtX, rect.fTop + ry - midPtY);
|
||||
this->quadTo(rect.fLeft + rx - offPtX, rect.fTop,
|
||||
rect.fLeft + rx, rect.fTop);
|
||||
#endif
|
||||
if (!skip_hori) {
|
||||
this->lineTo(rect.fRight - rx, rect.fTop); // top
|
||||
}
|
||||
}
|
||||
this->close();
|
||||
#else
|
||||
SkRRect rrect;
|
||||
rrect.setRectXY(rect, rx, ry);
|
||||
this->addRRect(rrect, dir);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SkPath::addOval(const SkRect& oval, Direction dir) {
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "SkPathEffect.h"
|
||||
#include "SkRandom.h"
|
||||
#include "SkReader32.h"
|
||||
#include "SkRRect.h"
|
||||
#include "SkSize.h"
|
||||
#include "SkSurface.h"
|
||||
#include "SkTypes.h"
|
||||
@ -2572,6 +2573,33 @@ static void test_empty(skiatest::Reporter* reporter, const SkPath& p) {
|
||||
REPORTER_ASSERT(reporter, !(p != empty));
|
||||
}
|
||||
|
||||
static void test_rrect_is_convex(skiatest::Reporter* reporter, SkPath* path) {
|
||||
REPORTER_ASSERT(reporter, path->isConvex());
|
||||
path->setConvexity(SkPath::kUnknown_Convexity);
|
||||
REPORTER_ASSERT(reporter, path->isConvex());
|
||||
path->reset();
|
||||
}
|
||||
|
||||
static void test_rrect(skiatest::Reporter* reporter) {
|
||||
SkPath p;
|
||||
SkRRect rr;
|
||||
SkVector radii[] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
|
||||
SkRect r = {10, 20, 30, 40};
|
||||
rr.setRectRadii(r, radii);
|
||||
p.addRRect(rr);
|
||||
test_rrect_is_convex(reporter, &p);
|
||||
p.addRRect(rr, SkPath::kCCW_Direction);
|
||||
test_rrect_is_convex(reporter, &p);
|
||||
p.addRoundRect(r, &radii[0].fX);
|
||||
test_rrect_is_convex(reporter, &p);
|
||||
p.addRoundRect(r, &radii[0].fX, SkPath::kCCW_Direction);
|
||||
test_rrect_is_convex(reporter, &p);
|
||||
p.addRoundRect(r, radii[1].fX, radii[1].fY);
|
||||
test_rrect_is_convex(reporter, &p);
|
||||
p.addRoundRect(r, radii[1].fX, radii[1].fY, SkPath::kCCW_Direction);
|
||||
test_rrect_is_convex(reporter, &p);
|
||||
}
|
||||
|
||||
static void TestPath(skiatest::Reporter* reporter) {
|
||||
SkTSize<SkScalar>::Make(3,4);
|
||||
|
||||
@ -2673,6 +2701,7 @@ static void TestPath(skiatest::Reporter* reporter) {
|
||||
test_gen_id(reporter);
|
||||
test_path_close_issue1474(reporter);
|
||||
test_path_to_region(reporter);
|
||||
test_rrect(reporter);
|
||||
}
|
||||
|
||||
#include "TestClassDef.h"
|
||||
|
Loading…
Reference in New Issue
Block a user