119d8f9f17373bcf7d352b77e72a6a46568ee8a8breed/*
219d8f9f17373bcf7d352b77e72a6a46568ee8a8breed * Copyright 2015 Google Inc.
319d8f9f17373bcf7d352b77e72a6a46568ee8a8breed *
419d8f9f17373bcf7d352b77e72a6a46568ee8a8breed * Use of this source code is governed by a BSD-style license that can be
519d8f9f17373bcf7d352b77e72a6a46568ee8a8breed * found in the LICENSE file.
619d8f9f17373bcf7d352b77e72a6a46568ee8a8breed */
719d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
819d8f9f17373bcf7d352b77e72a6a46568ee8a8breed#include "gm.h"
933d2055e594177b27360f84e0631b26d74a55a9bMike Klein#include "sk_tool_utils.h"
1076113a9b7716748c70ea0ecf7aacbabe4cce5009reed#include "SkAnimTimer.h"
1119d8f9f17373bcf7d352b77e72a6a46568ee8a8breed#include "SkCanvas.h"
1261adb1b6491db3d3552d09a1c69ba5a37beb38d5reed#include "SkPathMeasure.h"
1319d8f9f17373bcf7d352b77e72a6a46568ee8a8breed#include "SkRandom.h"
1419d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
1519d8f9f17373bcf7d352b77e72a6a46568ee8a8breedclass AddArcGM : public skiagm::GM {
16d9adfe6a223955bc69c8c7661ab8e0a078afbc32reedpublic:
17d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed    AddArcGM() : fRotate(0) {}
18d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed
1919d8f9f17373bcf7d352b77e72a6a46568ee8a8breedprotected:
2036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkString onShortName() override { return SkString("addarc"); }
2119d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
2236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkISize onISize() override { return SkISize::Make(1040, 1040); }
2319d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
2436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onDraw(SkCanvas* canvas) override {
2519d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        canvas->translate(20, 20);
2619d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
2719d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        SkRect r = SkRect::MakeWH(1000, 1000);
2819d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
2919d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        SkPaint paint;
3019d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        paint.setAntiAlias(true);
3119d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        paint.setStyle(SkPaint::kStroke_Style);
3219d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        paint.setStrokeWidth(15);
3319d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
3419d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        const SkScalar inset = paint.getStrokeWidth() + 4;
3519d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        const SkScalar sweepAngle = 345;
3619d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        SkRandom rand;
3719d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
38d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed        SkScalar sign = 1;
3919d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        while (r.width() > paint.getStrokeWidth() * 3) {
40125960152dfd7f2aba4c2239131bdf75d9ac2705caryclark            paint.setColor(sk_tool_utils::color_to_565(rand.nextU() | (0xFF << 24)));
4119d8f9f17373bcf7d352b77e72a6a46568ee8a8breed            SkScalar startAngle = rand.nextUScalar1() * 360;
4219d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
43d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed            SkScalar speed = SkScalarSqrt(16 / r.width()) * 0.5f;
44d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed            startAngle += fRotate * 360 * speed * sign;
45d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed
4619d8f9f17373bcf7d352b77e72a6a46568ee8a8breed            SkPath path;
4719d8f9f17373bcf7d352b77e72a6a46568ee8a8breed            path.addArc(r, startAngle, sweepAngle);
4819d8f9f17373bcf7d352b77e72a6a46568ee8a8breed            canvas->drawPath(path, paint);
4919d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
5019d8f9f17373bcf7d352b77e72a6a46568ee8a8breed            r.inset(inset, inset);
51d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed            sign = -sign;
5219d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        }
5319d8f9f17373bcf7d352b77e72a6a46568ee8a8breed    }
5419d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
5536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool onAnimate(const SkAnimTimer& timer) override {
5676113a9b7716748c70ea0ecf7aacbabe4cce5009reed        fRotate = timer.scaled(1, 360);
57d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed        return true;
58d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed    }
59d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed
6019d8f9f17373bcf7d352b77e72a6a46568ee8a8breedprivate:
61d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed    SkScalar fRotate;
6219d8f9f17373bcf7d352b77e72a6a46568ee8a8breed    typedef skiagm::GM INHERITED;
6319d8f9f17373bcf7d352b77e72a6a46568ee8a8breed};
6419d8f9f17373bcf7d352b77e72a6a46568ee8a8breedDEF_GM( return new AddArcGM; )
6561adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
6661adb1b6491db3d3552d09a1c69ba5a37beb38d5reed///////////////////////////////////////////////////
6761adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
6861adb1b6491db3d3552d09a1c69ba5a37beb38d5reed#define R   400
6961adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
7061adb1b6491db3d3552d09a1c69ba5a37beb38d5reedclass AddArcMeasGM : public skiagm::GM {
7161adb1b6491db3d3552d09a1c69ba5a37beb38d5reedpublic:
7261adb1b6491db3d3552d09a1c69ba5a37beb38d5reed    AddArcMeasGM() {}
7361adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
7461adb1b6491db3d3552d09a1c69ba5a37beb38d5reedprotected:
7536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkString onShortName() override { return SkString("addarc_meas"); }
7661adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
7736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkISize onISize() override { return SkISize::Make(2*R + 40, 2*R + 40); }
7861adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
7936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onDraw(SkCanvas* canvas) override {
8061adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        canvas->translate(R + 20, R + 20);
8161adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
8261adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        SkPaint paint;
8361adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        paint.setAntiAlias(true);
8461adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        paint.setStyle(SkPaint::kStroke_Style);
8561adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
8661adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        SkPaint measPaint;
8761adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        measPaint.setAntiAlias(true);
8861adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        measPaint.setColor(SK_ColorRED);
8961adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
9061adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        const SkRect oval = SkRect::MakeLTRB(-R, -R, R, R);
9161adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        canvas->drawOval(oval, paint);
9261adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
9361adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        for (SkScalar deg = 0; deg < 360; deg += 10) {
9461adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            const SkScalar rad = SkDegreesToRadians(deg);
9561adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            SkScalar rx = SkScalarCos(rad) * R;
9661adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            SkScalar ry = SkScalarSin(rad) * R;
9761adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
9861adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            canvas->drawLine(0, 0, rx, ry, paint);
9961adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
10061adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            SkPath path;
10161adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            path.addArc(oval, 0, deg);
10261adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            SkPathMeasure meas(path, false);
10361adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            SkScalar arcLen = rad * R;
10461adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            SkPoint pos;
10596fcdcc219d2a0d3579719b84b28bede76efba64halcanary            if (meas.getPosTan(arcLen, &pos, nullptr)) {
10661adb1b6491db3d3552d09a1c69ba5a37beb38d5reed                canvas->drawLine(0, 0, pos.x(), pos.y(), measPaint);
10761adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            }
10861adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        }
10961adb1b6491db3d3552d09a1c69ba5a37beb38d5reed    }
11061adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
11161adb1b6491db3d3552d09a1c69ba5a37beb38d5reedprivate:
11261adb1b6491db3d3552d09a1c69ba5a37beb38d5reed    typedef skiagm::GM INHERITED;
11361adb1b6491db3d3552d09a1c69ba5a37beb38d5reed};
11461adb1b6491db3d3552d09a1c69ba5a37beb38d5reedDEF_GM( return new AddArcMeasGM; )
1158ed666d230231c7280069236f265a61edb8a9a20reed
1168ed666d230231c7280069236f265a61edb8a9a20reed///////////////////////////////////////////////////
1178ed666d230231c7280069236f265a61edb8a9a20reed
1188ed666d230231c7280069236f265a61edb8a9a20reed// Emphasize drawing a stroked oval (containing conics) and then scaling the results up,
1198ed666d230231c7280069236f265a61edb8a9a20reed// to ensure that we compute the stroke taking the CTM into account
1208ed666d230231c7280069236f265a61edb8a9a20reed//
1218ed666d230231c7280069236f265a61edb8a9a20reedclass StrokeCircleGM : public skiagm::GM {
1228ed666d230231c7280069236f265a61edb8a9a20reedpublic:
1238ed666d230231c7280069236f265a61edb8a9a20reed    StrokeCircleGM() : fRotate(0) {}
1249d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
1258ed666d230231c7280069236f265a61edb8a9a20reedprotected:
12636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkString onShortName() override { return SkString("strokecircle"); }
1279d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
12836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkISize onISize() override { return SkISize::Make(520, 520); }
1299d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
13036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onDraw(SkCanvas* canvas) override {
1318ed666d230231c7280069236f265a61edb8a9a20reed        canvas->scale(20, 20);
1328ed666d230231c7280069236f265a61edb8a9a20reed        canvas->translate(13, 13);
1338ed666d230231c7280069236f265a61edb8a9a20reed
1348ed666d230231c7280069236f265a61edb8a9a20reed        SkPaint paint;
1358ed666d230231c7280069236f265a61edb8a9a20reed        paint.setAntiAlias(true);
1368ed666d230231c7280069236f265a61edb8a9a20reed        paint.setStyle(SkPaint::kStroke_Style);
1378ed666d230231c7280069236f265a61edb8a9a20reed        paint.setStrokeWidth(SK_Scalar1 / 2);
1388ed666d230231c7280069236f265a61edb8a9a20reed
1398ed666d230231c7280069236f265a61edb8a9a20reed        const SkScalar delta = paint.getStrokeWidth() * 3 / 2;
1408ed666d230231c7280069236f265a61edb8a9a20reed        SkRect r = SkRect::MakeXYWH(-12, -12, 24, 24);
1418ed666d230231c7280069236f265a61edb8a9a20reed        SkRandom rand;
1428ed666d230231c7280069236f265a61edb8a9a20reed
1438ed666d230231c7280069236f265a61edb8a9a20reed        SkScalar sign = 1;
1448ed666d230231c7280069236f265a61edb8a9a20reed        while (r.width() > paint.getStrokeWidth() * 2) {
1458ed666d230231c7280069236f265a61edb8a9a20reed            SkAutoCanvasRestore acr(canvas, true);
1468ed666d230231c7280069236f265a61edb8a9a20reed            canvas->rotate(fRotate * sign);
1478ed666d230231c7280069236f265a61edb8a9a20reed
148125960152dfd7f2aba4c2239131bdf75d9ac2705caryclark            paint.setColor(sk_tool_utils::color_to_565(rand.nextU() | (0xFF << 24)));
1498ed666d230231c7280069236f265a61edb8a9a20reed            canvas->drawOval(r, paint);
1508ed666d230231c7280069236f265a61edb8a9a20reed            r.inset(delta, delta);
1518ed666d230231c7280069236f265a61edb8a9a20reed            sign = -sign;
1528ed666d230231c7280069236f265a61edb8a9a20reed        }
1538ed666d230231c7280069236f265a61edb8a9a20reed    }
1548ed666d230231c7280069236f265a61edb8a9a20reed
15536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool onAnimate(const SkAnimTimer& timer) override {
1568ed666d230231c7280069236f265a61edb8a9a20reed        fRotate = timer.scaled(60, 360);
1578ed666d230231c7280069236f265a61edb8a9a20reed        return true;
1588ed666d230231c7280069236f265a61edb8a9a20reed    }
1598ed666d230231c7280069236f265a61edb8a9a20reed
1608ed666d230231c7280069236f265a61edb8a9a20reedprivate:
1618ed666d230231c7280069236f265a61edb8a9a20reed    SkScalar fRotate;
1628ed666d230231c7280069236f265a61edb8a9a20reed
1638ed666d230231c7280069236f265a61edb8a9a20reed    typedef skiagm::GM INHERITED;
1648ed666d230231c7280069236f265a61edb8a9a20reed};
1658ed666d230231c7280069236f265a61edb8a9a20reedDEF_GM( return new StrokeCircleGM; )
1669e779d495130009926fc5394a8971eec20494e5freed
1679e779d495130009926fc5394a8971eec20494e5freed//////////////////////
1689e779d495130009926fc5394a8971eec20494e5freed
169e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian// Fill circles and rotate them to test our Analytic Anti-Aliasing.
170e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian// This test is based on StrokeCircleGM.
171e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqianclass FillCircleGM : public skiagm::GM {
172e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqianpublic:
173e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    FillCircleGM() : fRotate(0) {}
174e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
175e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqianprotected:
176e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    SkString onShortName() override { return SkString("fillcircle"); }
177e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
178e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    SkISize onISize() override { return SkISize::Make(520, 520); }
179e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
180e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    void onDraw(SkCanvas* canvas) override {
181e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        canvas->scale(20, 20);
182e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        canvas->translate(13, 13);
183e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
184e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        SkPaint paint;
185e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        paint.setAntiAlias(true);
186e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        paint.setStyle(SkPaint::kStroke_Style);
187e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        paint.setStrokeWidth(SK_Scalar1 / 2);
188e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
189e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        const SkScalar strokeWidth = paint.getStrokeWidth();
190e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        const SkScalar delta = strokeWidth * 3 / 2;
191e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        SkRect r = SkRect::MakeXYWH(-12, -12, 24, 24);
192e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        SkRandom rand;
193e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
194e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        // Reset style to fill. We only need stroke stype for producing delta and strokeWidth
195e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        paint.setStyle(SkPaint::kFill_Style);
196e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
197e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        SkScalar sign = 1;
198e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        while (r.width() > strokeWidth * 2) {
199e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian            SkAutoCanvasRestore acr(canvas, true);
200e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian            canvas->rotate(fRotate * sign);
201e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian            paint.setColor(sk_tool_utils::color_to_565(rand.nextU() | (0xFF << 24)));
202e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian            canvas->drawOval(r, paint);
203e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian            r.inset(delta, delta);
204e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian            sign = -sign;
205e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        }
206e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    }
207e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
208e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    bool onAnimate(const SkAnimTimer& timer) override {
209e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        fRotate = timer.scaled(60, 360);
210e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        return true;
211e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    }
212e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
213e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqianprivate:
214e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    SkScalar fRotate;
215e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
216e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    typedef skiagm::GM INHERITED;
217e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian};
218e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqianDEF_GM( return new FillCircleGM; )
219e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
220e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian//////////////////////
221e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
2229e779d495130009926fc5394a8971eec20494e5freedstatic void html_canvas_arc(SkPath* path, SkScalar x, SkScalar y, SkScalar r, SkScalar start,
2236069ddabd8385ff838236dc25d7354e71649c9f3xidachen                            SkScalar end, bool ccw, bool callArcTo) {
2249e779d495130009926fc5394a8971eec20494e5freed    SkRect bounds = { x - r, y - r, x + r, y + r };
2259e779d495130009926fc5394a8971eec20494e5freed    SkScalar sweep = ccw ? end - start : start - end;
2266069ddabd8385ff838236dc25d7354e71649c9f3xidachen    if (callArcTo)
2276069ddabd8385ff838236dc25d7354e71649c9f3xidachen        path->arcTo(bounds, start, sweep, false);
2286069ddabd8385ff838236dc25d7354e71649c9f3xidachen    else
2296069ddabd8385ff838236dc25d7354e71649c9f3xidachen        path->addArc(bounds, start, sweep);
2309e779d495130009926fc5394a8971eec20494e5freed}
2319e779d495130009926fc5394a8971eec20494e5freed
2329e779d495130009926fc5394a8971eec20494e5freed// Lifted from canvas-arc-circumference-fill-diffs.html
2339e779d495130009926fc5394a8971eec20494e5freedclass ManyArcsGM : public skiagm::GM {
2349e779d495130009926fc5394a8971eec20494e5freedpublic:
2359e779d495130009926fc5394a8971eec20494e5freed    ManyArcsGM() {}
2369d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2379e779d495130009926fc5394a8971eec20494e5freedprotected:
23836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkString onShortName() override { return SkString("manyarcs"); }
2399d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
24036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkISize onISize() override { return SkISize::Make(620, 330); }
2419d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
24236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onDraw(SkCanvas* canvas) override {
2439e779d495130009926fc5394a8971eec20494e5freed        SkPaint paint;
2449e779d495130009926fc5394a8971eec20494e5freed        paint.setAntiAlias(true);
2459e779d495130009926fc5394a8971eec20494e5freed        paint.setStyle(SkPaint::kStroke_Style);
2469e779d495130009926fc5394a8971eec20494e5freed
2479e779d495130009926fc5394a8971eec20494e5freed        canvas->translate(10, 10);
2489e779d495130009926fc5394a8971eec20494e5freed
2499e779d495130009926fc5394a8971eec20494e5freed        // 20 angles.
2509e779d495130009926fc5394a8971eec20494e5freed        SkScalar sweepAngles[] = {
2519e779d495130009926fc5394a8971eec20494e5freed                           -123.7f, -2.3f, -2, -1, -0.3f, -0.000001f, 0, 0.000001f, 0.3f, 0.7f,
2529e779d495130009926fc5394a8971eec20494e5freed                           1, 1.3f, 1.5f, 1.7f, 1.99999f, 2, 2.00001f, 2.3f, 4.3f, 3934723942837.3f
2539e779d495130009926fc5394a8971eec20494e5freed        };
2549e779d495130009926fc5394a8971eec20494e5freed        for (size_t i = 0; i < SK_ARRAY_COUNT(sweepAngles); ++i) {
2559e779d495130009926fc5394a8971eec20494e5freed            sweepAngles[i] *= 180;
2569e779d495130009926fc5394a8971eec20494e5freed        }
2579d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2589e779d495130009926fc5394a8971eec20494e5freed        SkScalar startAngles[] = { -1, -0.5f, 0, 0.5f };
2599e779d495130009926fc5394a8971eec20494e5freed        for (size_t i = 0; i < SK_ARRAY_COUNT(startAngles); ++i) {
2609e779d495130009926fc5394a8971eec20494e5freed            startAngles[i] *= 180;
2619e779d495130009926fc5394a8971eec20494e5freed        }
2629d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2639e779d495130009926fc5394a8971eec20494e5freed        bool anticlockwise = false;
2649e779d495130009926fc5394a8971eec20494e5freed        SkScalar sign = 1;
2659e779d495130009926fc5394a8971eec20494e5freed        for (size_t i = 0; i < SK_ARRAY_COUNT(startAngles) * 2; ++i) {
2669e779d495130009926fc5394a8971eec20494e5freed            if (i == SK_ARRAY_COUNT(startAngles)) {
2679e779d495130009926fc5394a8971eec20494e5freed                anticlockwise = true;
2689e779d495130009926fc5394a8971eec20494e5freed                sign = -1;
2699e779d495130009926fc5394a8971eec20494e5freed            }
2709e779d495130009926fc5394a8971eec20494e5freed            SkScalar startAngle = startAngles[i % SK_ARRAY_COUNT(startAngles)] * sign;
2719e779d495130009926fc5394a8971eec20494e5freed            canvas->save();
2729e779d495130009926fc5394a8971eec20494e5freed            for (size_t j = 0; j < SK_ARRAY_COUNT(sweepAngles); ++j) {
2739e779d495130009926fc5394a8971eec20494e5freed                SkPath path;
2749e779d495130009926fc5394a8971eec20494e5freed                path.moveTo(0, 2);
2759e779d495130009926fc5394a8971eec20494e5freed                html_canvas_arc(&path, 18, 15, 10, startAngle, startAngle + (sweepAngles[j] * sign),
2766069ddabd8385ff838236dc25d7354e71649c9f3xidachen                                anticlockwise, true);
2779e779d495130009926fc5394a8971eec20494e5freed                path.lineTo(0, 28);
2789e779d495130009926fc5394a8971eec20494e5freed                canvas->drawPath(path, paint);
2799e779d495130009926fc5394a8971eec20494e5freed                canvas->translate(30, 0);
2809e779d495130009926fc5394a8971eec20494e5freed            }
2819e779d495130009926fc5394a8971eec20494e5freed            canvas->restore();
2829e779d495130009926fc5394a8971eec20494e5freed            canvas->translate(0, 40);
2839e779d495130009926fc5394a8971eec20494e5freed        }
2849e779d495130009926fc5394a8971eec20494e5freed    }
2859d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2869e779d495130009926fc5394a8971eec20494e5freedprivate:
2879e779d495130009926fc5394a8971eec20494e5freed    typedef skiagm::GM INHERITED;
2889e779d495130009926fc5394a8971eec20494e5freed};
2899e779d495130009926fc5394a8971eec20494e5freedDEF_GM( return new ManyArcsGM; )
2906069ddabd8385ff838236dc25d7354e71649c9f3xidachen
2916069ddabd8385ff838236dc25d7354e71649c9f3xidachen// Lifted from https://bugs.chromium.org/p/chromium/issues/detail?id=640031
2926069ddabd8385ff838236dc25d7354e71649c9f3xidachenclass TinyAngleBigRadiusArcsGM : public skiagm::GM {
2936069ddabd8385ff838236dc25d7354e71649c9f3xidachenpublic:
2946069ddabd8385ff838236dc25d7354e71649c9f3xidachen    TinyAngleBigRadiusArcsGM() {}
2956069ddabd8385ff838236dc25d7354e71649c9f3xidachen
2966069ddabd8385ff838236dc25d7354e71649c9f3xidachenprotected:
2976069ddabd8385ff838236dc25d7354e71649c9f3xidachen    SkString onShortName() override { return SkString("tinyanglearcs"); }
2986069ddabd8385ff838236dc25d7354e71649c9f3xidachen
2996069ddabd8385ff838236dc25d7354e71649c9f3xidachen    SkISize onISize() override { return SkISize::Make(620, 330); }
3006069ddabd8385ff838236dc25d7354e71649c9f3xidachen
3016069ddabd8385ff838236dc25d7354e71649c9f3xidachen    void onDraw(SkCanvas* canvas) override {
3026069ddabd8385ff838236dc25d7354e71649c9f3xidachen        SkPaint paint;
3036069ddabd8385ff838236dc25d7354e71649c9f3xidachen        paint.setAntiAlias(true);
3046069ddabd8385ff838236dc25d7354e71649c9f3xidachen        paint.setStyle(SkPaint::kStroke_Style);
3056069ddabd8385ff838236dc25d7354e71649c9f3xidachen
3066069ddabd8385ff838236dc25d7354e71649c9f3xidachen        canvas->translate(50, 50);
3076069ddabd8385ff838236dc25d7354e71649c9f3xidachen
30895e34a3d847684692184daea4a887f7825d65e51xidachen        SkScalar outerRadius = 100000.0f;
30995e34a3d847684692184daea4a887f7825d65e51xidachen        SkScalar innerRadius = outerRadius - 20.0f;
31095e34a3d847684692184daea4a887f7825d65e51xidachen        SkScalar centerX = 50;
31195e34a3d847684692184daea4a887f7825d65e51xidachen        SkScalar centerY = outerRadius;
31295e34a3d847684692184daea4a887f7825d65e51xidachen        SkScalar startAngles[] = { 1.5f * SK_ScalarPI , 1.501f * SK_ScalarPI  };
31395e34a3d847684692184daea4a887f7825d65e51xidachen        SkScalar sweepAngle = 10.0f / outerRadius;
31495e34a3d847684692184daea4a887f7825d65e51xidachen
31595e34a3d847684692184daea4a887f7825d65e51xidachen        for (size_t i = 0; i < SK_ARRAY_COUNT(startAngles); ++i) {
31695e34a3d847684692184daea4a887f7825d65e51xidachen            SkPath path;
31795e34a3d847684692184daea4a887f7825d65e51xidachen            SkScalar endAngle = startAngles[i] + sweepAngle;
31895e34a3d847684692184daea4a887f7825d65e51xidachen            path.moveTo(centerX + innerRadius * sk_float_cos(startAngles[i]),
31995e34a3d847684692184daea4a887f7825d65e51xidachen                        centerY + innerRadius * sk_float_sin(startAngles[i]));
32095e34a3d847684692184daea4a887f7825d65e51xidachen            path.lineTo(centerX + outerRadius * sk_float_cos(startAngles[i]),
32195e34a3d847684692184daea4a887f7825d65e51xidachen                        centerY + outerRadius * sk_float_sin(startAngles[i]));
32295e34a3d847684692184daea4a887f7825d65e51xidachen            // A combination of tiny sweepAngle + large radius, we should draw a line.
32395e34a3d847684692184daea4a887f7825d65e51xidachen            html_canvas_arc(&path, centerX, outerRadius, outerRadius,
32495e34a3d847684692184daea4a887f7825d65e51xidachen                            startAngles[i] * 180 / SK_ScalarPI, endAngle * 180 / SK_ScalarPI,
32595e34a3d847684692184daea4a887f7825d65e51xidachen                            true, true);
32695e34a3d847684692184daea4a887f7825d65e51xidachen            path.lineTo(centerX + innerRadius * sk_float_cos(endAngle),
32795e34a3d847684692184daea4a887f7825d65e51xidachen                        centerY + innerRadius * sk_float_sin(endAngle));
32895e34a3d847684692184daea4a887f7825d65e51xidachen            html_canvas_arc(&path, centerX, outerRadius, innerRadius,
32995e34a3d847684692184daea4a887f7825d65e51xidachen                            endAngle * 180 / SK_ScalarPI, startAngles[i] * 180 / SK_ScalarPI,
33095e34a3d847684692184daea4a887f7825d65e51xidachen                            true, false);
33195e34a3d847684692184daea4a887f7825d65e51xidachen            canvas->drawPath(path, paint);
33295e34a3d847684692184daea4a887f7825d65e51xidachen            canvas->translate(20, 0);
33395e34a3d847684692184daea4a887f7825d65e51xidachen        }
3346069ddabd8385ff838236dc25d7354e71649c9f3xidachen    }
3356069ddabd8385ff838236dc25d7354e71649c9f3xidachen
3366069ddabd8385ff838236dc25d7354e71649c9f3xidachenprivate:
3376069ddabd8385ff838236dc25d7354e71649c9f3xidachen    typedef skiagm::GM INHERITED;
3386069ddabd8385ff838236dc25d7354e71649c9f3xidachen};
3396069ddabd8385ff838236dc25d7354e71649c9f3xidachenDEF_GM( return new TinyAngleBigRadiusArcsGM; )
340