addarc.cpp revision 8ed666d230231c7280069236f265a61edb8a9a20
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"
976113a9b7716748c70ea0ecf7aacbabe4cce5009reed#include "SkAnimTimer.h"
1019d8f9f17373bcf7d352b77e72a6a46568ee8a8breed#include "SkCanvas.h"
1161adb1b6491db3d3552d09a1c69ba5a37beb38d5reed#include "SkPathMeasure.h"
1219d8f9f17373bcf7d352b77e72a6a46568ee8a8breed#include "SkRandom.h"
1319d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
1419d8f9f17373bcf7d352b77e72a6a46568ee8a8breedclass AddArcGM : public skiagm::GM {
15d9adfe6a223955bc69c8c7661ab8e0a078afbc32reedpublic:
16d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed    AddArcGM() : fRotate(0) {}
17d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed
1819d8f9f17373bcf7d352b77e72a6a46568ee8a8breedprotected:
1919d8f9f17373bcf7d352b77e72a6a46568ee8a8breed    SkString onShortName() SK_OVERRIDE { return SkString("addarc"); }
2019d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
2119d8f9f17373bcf7d352b77e72a6a46568ee8a8breed    SkISize onISize() SK_OVERRIDE { return SkISize::Make(1040, 1040); }
2219d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
2319d8f9f17373bcf7d352b77e72a6a46568ee8a8breed    void onDraw(SkCanvas* canvas) SK_OVERRIDE {
2419d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        canvas->translate(20, 20);
2519d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
2619d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        SkRect r = SkRect::MakeWH(1000, 1000);
2719d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
2819d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        SkPaint paint;
2919d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        paint.setAntiAlias(true);
3019d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        paint.setStyle(SkPaint::kStroke_Style);
3119d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        paint.setStrokeWidth(15);
3219d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
3319d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        const SkScalar inset = paint.getStrokeWidth() + 4;
3419d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        const SkScalar sweepAngle = 345;
3519d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        SkRandom rand;
3619d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
37d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed        SkScalar sign = 1;
3819d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        while (r.width() > paint.getStrokeWidth() * 3) {
3919d8f9f17373bcf7d352b77e72a6a46568ee8a8breed            paint.setColor(rand.nextU() | (0xFF << 24));
4019d8f9f17373bcf7d352b77e72a6a46568ee8a8breed            SkScalar startAngle = rand.nextUScalar1() * 360;
4119d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
42d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed            SkScalar speed = SkScalarSqrt(16 / r.width()) * 0.5f;
43d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed            startAngle += fRotate * 360 * speed * sign;
44d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed
4519d8f9f17373bcf7d352b77e72a6a46568ee8a8breed            SkPath path;
4619d8f9f17373bcf7d352b77e72a6a46568ee8a8breed            path.addArc(r, startAngle, sweepAngle);
4719d8f9f17373bcf7d352b77e72a6a46568ee8a8breed            canvas->drawPath(path, paint);
4819d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
4919d8f9f17373bcf7d352b77e72a6a46568ee8a8breed            r.inset(inset, inset);
50d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed            sign = -sign;
5119d8f9f17373bcf7d352b77e72a6a46568ee8a8breed        }
5219d8f9f17373bcf7d352b77e72a6a46568ee8a8breed    }
5319d8f9f17373bcf7d352b77e72a6a46568ee8a8breed
5476113a9b7716748c70ea0ecf7aacbabe4cce5009reed    bool onAnimate(const SkAnimTimer& timer) SK_OVERRIDE {
5576113a9b7716748c70ea0ecf7aacbabe4cce5009reed        fRotate = timer.scaled(1, 360);
56d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed        return true;
57d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed    }
58d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed
5919d8f9f17373bcf7d352b77e72a6a46568ee8a8breedprivate:
60d9adfe6a223955bc69c8c7661ab8e0a078afbc32reed    SkScalar fRotate;
6119d8f9f17373bcf7d352b77e72a6a46568ee8a8breed    typedef skiagm::GM INHERITED;
6219d8f9f17373bcf7d352b77e72a6a46568ee8a8breed};
6319d8f9f17373bcf7d352b77e72a6a46568ee8a8breedDEF_GM( return new AddArcGM; )
6461adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
6561adb1b6491db3d3552d09a1c69ba5a37beb38d5reed///////////////////////////////////////////////////
6661adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
6761adb1b6491db3d3552d09a1c69ba5a37beb38d5reed#define R   400
6861adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
6961adb1b6491db3d3552d09a1c69ba5a37beb38d5reedclass AddArcMeasGM : public skiagm::GM {
7061adb1b6491db3d3552d09a1c69ba5a37beb38d5reedpublic:
7161adb1b6491db3d3552d09a1c69ba5a37beb38d5reed    AddArcMeasGM() {}
7261adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
7361adb1b6491db3d3552d09a1c69ba5a37beb38d5reedprotected:
7461adb1b6491db3d3552d09a1c69ba5a37beb38d5reed    SkString onShortName() SK_OVERRIDE { return SkString("addarc_meas"); }
7561adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
7661adb1b6491db3d3552d09a1c69ba5a37beb38d5reed    SkISize onISize() SK_OVERRIDE { return SkISize::Make(2*R + 40, 2*R + 40); }
7761adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
7861adb1b6491db3d3552d09a1c69ba5a37beb38d5reed    void onDraw(SkCanvas* canvas) SK_OVERRIDE {
7961adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        canvas->translate(R + 20, R + 20);
8061adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
8161adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        SkPaint paint;
8261adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        paint.setAntiAlias(true);
8361adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        paint.setStyle(SkPaint::kStroke_Style);
8461adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
8561adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        SkPaint measPaint;
8661adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        measPaint.setAntiAlias(true);
8761adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        measPaint.setColor(SK_ColorRED);
8861adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
8961adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        const SkRect oval = SkRect::MakeLTRB(-R, -R, R, R);
9061adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        canvas->drawOval(oval, paint);
9161adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
9261adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        for (SkScalar deg = 0; deg < 360; deg += 10) {
9361adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            const SkScalar rad = SkDegreesToRadians(deg);
9461adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            SkScalar rx = SkScalarCos(rad) * R;
9561adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            SkScalar ry = SkScalarSin(rad) * R;
9661adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
9761adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            canvas->drawLine(0, 0, rx, ry, paint);
9861adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
9961adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            SkPath path;
10061adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            path.addArc(oval, 0, deg);
10161adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            SkPathMeasure meas(path, false);
10261adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            SkScalar arcLen = rad * R;
10361adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            SkPoint pos;
10461adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            if (meas.getPosTan(arcLen, &pos, NULL)) {
10561adb1b6491db3d3552d09a1c69ba5a37beb38d5reed                canvas->drawLine(0, 0, pos.x(), pos.y(), measPaint);
10661adb1b6491db3d3552d09a1c69ba5a37beb38d5reed            }
10761adb1b6491db3d3552d09a1c69ba5a37beb38d5reed        }
10861adb1b6491db3d3552d09a1c69ba5a37beb38d5reed    }
10961adb1b6491db3d3552d09a1c69ba5a37beb38d5reed
11061adb1b6491db3d3552d09a1c69ba5a37beb38d5reedprivate:
11161adb1b6491db3d3552d09a1c69ba5a37beb38d5reed    typedef skiagm::GM INHERITED;
11261adb1b6491db3d3552d09a1c69ba5a37beb38d5reed};
11361adb1b6491db3d3552d09a1c69ba5a37beb38d5reedDEF_GM( return new AddArcMeasGM; )
1148ed666d230231c7280069236f265a61edb8a9a20reed
1158ed666d230231c7280069236f265a61edb8a9a20reed///////////////////////////////////////////////////
1168ed666d230231c7280069236f265a61edb8a9a20reed
1178ed666d230231c7280069236f265a61edb8a9a20reed// Emphasize drawing a stroked oval (containing conics) and then scaling the results up,
1188ed666d230231c7280069236f265a61edb8a9a20reed// to ensure that we compute the stroke taking the CTM into account
1198ed666d230231c7280069236f265a61edb8a9a20reed//
1208ed666d230231c7280069236f265a61edb8a9a20reedclass StrokeCircleGM : public skiagm::GM {
1218ed666d230231c7280069236f265a61edb8a9a20reedpublic:
1228ed666d230231c7280069236f265a61edb8a9a20reed    StrokeCircleGM() : fRotate(0) {}
1238ed666d230231c7280069236f265a61edb8a9a20reed
1248ed666d230231c7280069236f265a61edb8a9a20reedprotected:
1258ed666d230231c7280069236f265a61edb8a9a20reed    SkString onShortName() SK_OVERRIDE { return SkString("strokecircle"); }
1268ed666d230231c7280069236f265a61edb8a9a20reed
1278ed666d230231c7280069236f265a61edb8a9a20reed    SkISize onISize() SK_OVERRIDE { return SkISize::Make(520, 520); }
1288ed666d230231c7280069236f265a61edb8a9a20reed
1298ed666d230231c7280069236f265a61edb8a9a20reed    void onDraw(SkCanvas* canvas) SK_OVERRIDE {
1308ed666d230231c7280069236f265a61edb8a9a20reed        canvas->scale(20, 20);
1318ed666d230231c7280069236f265a61edb8a9a20reed        canvas->translate(13, 13);
1328ed666d230231c7280069236f265a61edb8a9a20reed
1338ed666d230231c7280069236f265a61edb8a9a20reed        SkPaint paint;
1348ed666d230231c7280069236f265a61edb8a9a20reed        paint.setAntiAlias(true);
1358ed666d230231c7280069236f265a61edb8a9a20reed        paint.setStyle(SkPaint::kStroke_Style);
1368ed666d230231c7280069236f265a61edb8a9a20reed        paint.setStrokeWidth(SK_Scalar1 / 2);
1378ed666d230231c7280069236f265a61edb8a9a20reed
1388ed666d230231c7280069236f265a61edb8a9a20reed        const SkScalar delta = paint.getStrokeWidth() * 3 / 2;
1398ed666d230231c7280069236f265a61edb8a9a20reed        SkRect r = SkRect::MakeXYWH(-12, -12, 24, 24);
1408ed666d230231c7280069236f265a61edb8a9a20reed        SkRandom rand;
1418ed666d230231c7280069236f265a61edb8a9a20reed
1428ed666d230231c7280069236f265a61edb8a9a20reed        SkScalar sign = 1;
1438ed666d230231c7280069236f265a61edb8a9a20reed        while (r.width() > paint.getStrokeWidth() * 2) {
1448ed666d230231c7280069236f265a61edb8a9a20reed            SkAutoCanvasRestore acr(canvas, true);
1458ed666d230231c7280069236f265a61edb8a9a20reed            canvas->rotate(fRotate * sign);
1468ed666d230231c7280069236f265a61edb8a9a20reed
1478ed666d230231c7280069236f265a61edb8a9a20reed            paint.setColor(rand.nextU() | (0xFF << 24));
1488ed666d230231c7280069236f265a61edb8a9a20reed            canvas->drawOval(r, paint);
1498ed666d230231c7280069236f265a61edb8a9a20reed            r.inset(delta, delta);
1508ed666d230231c7280069236f265a61edb8a9a20reed            sign = -sign;
1518ed666d230231c7280069236f265a61edb8a9a20reed        }
1528ed666d230231c7280069236f265a61edb8a9a20reed    }
1538ed666d230231c7280069236f265a61edb8a9a20reed
1548ed666d230231c7280069236f265a61edb8a9a20reed    bool onAnimate(const SkAnimTimer& timer) SK_OVERRIDE {
1558ed666d230231c7280069236f265a61edb8a9a20reed        fRotate = timer.scaled(60, 360);
1568ed666d230231c7280069236f265a61edb8a9a20reed        return true;
1578ed666d230231c7280069236f265a61edb8a9a20reed    }
1588ed666d230231c7280069236f265a61edb8a9a20reed
1598ed666d230231c7280069236f265a61edb8a9a20reedprivate:
1608ed666d230231c7280069236f265a61edb8a9a20reed    SkScalar fRotate;
1618ed666d230231c7280069236f265a61edb8a9a20reed
1628ed666d230231c7280069236f265a61edb8a9a20reed    typedef skiagm::GM INHERITED;
1638ed666d230231c7280069236f265a61edb8a9a20reed};
1648ed666d230231c7280069236f265a61edb8a9a20reedDEF_GM( return new StrokeCircleGM; )
165