Fix stroked arcs for mirror matrices.

Bug: b/142280381
Change-Id: I9933543377e6916bd262c6f2e936ed9f0976d039
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/259174
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2019-12-11 08:16:22 -05:00
parent 2ae348247a
commit 3517aa7b14
2 changed files with 87 additions and 4 deletions

View File

@ -263,3 +263,83 @@ DEF_SIMPLE_GM(crbug_888453, canvas, 480, 150) {
x += 2 * r + 4;
}
}
DEF_SIMPLE_GM(circular_arc_stroke_matrix, canvas, 820, 1090) {
static constexpr SkScalar kRadius = 40.f;
static constexpr SkScalar kStrokeWidth = 5.f;
static constexpr SkScalar kStart = 89.f;
static constexpr SkScalar kSweep = 180.f/SK_ScalarPI; // one radian
SkTArray<SkMatrix> matrices;
matrices.push_back().setRotate(kRadius, kRadius, 45.f);
matrices.push_back(SkMatrix::I());
matrices.push_back().setAll(-1, 0, 2*kRadius,
0, 1, 0,
0, 0, 1);
matrices.push_back().setAll( 1, 0, 0,
0, -1, 2*kRadius,
0, 0, 1);
matrices.push_back().setAll( 1, 0, 0,
0, -1, 2*kRadius,
0, 0, 1);
matrices.push_back().setAll( 0, -1, 2*kRadius,
-1, 0, 2*kRadius,
0, 0, 1);
matrices.push_back().setAll( 0, -1, 2*kRadius,
1, 0, 0,
0, 0, 1);
matrices.push_back().setAll( 0, 1, 0,
1, 0, 0,
0, 0, 1);
matrices.push_back().setAll( 0, 1, 0,
-1, 0, 2*kRadius,
0, 0, 1);
int baseMatrixCnt = matrices.count();
SkMatrix tinyCW;
tinyCW.setRotate(0.001f, kRadius, kRadius);
for (int i = 0; i < baseMatrixCnt; ++i) {
matrices.push_back().setConcat(matrices[i], tinyCW);
}
SkMatrix tinyCCW;
tinyCCW.setRotate(-0.001f, kRadius, kRadius);
for (int i = 0; i < baseMatrixCnt; ++i) {
matrices.push_back().setConcat(matrices[i], tinyCCW);
}
SkMatrix cw45;
cw45.setRotate(45.f, kRadius, kRadius);
for (int i = 0; i < baseMatrixCnt; ++i) {
matrices.push_back().setConcat(matrices[i], cw45);
}
int x = 0;
int y = 0;
static constexpr SkScalar kPad = 2*kStrokeWidth;
canvas->translate(kPad, kPad);
auto bounds = SkRect::MakeWH(2*kRadius, 2*kRadius);
for (auto cap : {SkPaint::kRound_Cap, SkPaint::kButt_Cap, SkPaint::kSquare_Cap}) {
for (const auto& m : matrices) {
SkPaint paint;
paint.setStrokeCap(cap);
paint.setAntiAlias(true);
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(kStrokeWidth);
canvas->save();
canvas->translate(x * (2*kRadius + kPad), y * (2*kRadius + kPad));
canvas->concat(m);
paint.setColor(SK_ColorRED);
paint.setAlpha(0x80);
canvas->drawArc(bounds, kStart, kSweep, false, paint);
paint.setColor(SK_ColorBLUE);
paint.setAlpha(0x80);
canvas->drawArc(bounds, kStart, kSweep - 360.f, false, paint);
canvas->restore();
++x;
if (x == baseMatrixCnt) {
x = 0;
++y;
}
}
}
}

View File

@ -1110,10 +1110,13 @@ public:
startPoint.normalize();
stopPoint.normalize();
// If the matrix included scale (on one axis) we need to swap our start and end points
if ((viewMatrix.getScaleX() < 0) != (viewMatrix.getScaleY() < 0)) {
using std::swap;
swap(startPoint, stopPoint);
// We know the matrix is a similarity here. Detect mirroring which will affect how we
// should orient the clip planes for arcs.
SkASSERT(viewMatrix.isSimilarity());
auto upperLeftDet = viewMatrix.getScaleX()*viewMatrix.getScaleY() -
viewMatrix.getSkewX() *viewMatrix.getSkewY();
if (upperLeftDet < 0) {
std::swap(startPoint, stopPoint);
}
fRoundCaps = style.strokeRec().getWidth() > 0 &&