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: 1936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkString onShortName() override { return SkString("addarc"); } 2019d8f9f17373bcf7d352b77e72a6a46568ee8a8breed 2136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkISize onISize() override { return SkISize::Make(1040, 1040); } 2219d8f9f17373bcf7d352b77e72a6a46568ee8a8breed 2336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onDraw(SkCanvas* canvas) 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 5436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool onAnimate(const SkAnimTimer& timer) 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: 7436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkString onShortName() override { return SkString("addarc_meas"); } 7561adb1b6491db3d3552d09a1c69ba5a37beb38d5reed 7636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkISize onISize() override { return SkISize::Make(2*R + 40, 2*R + 40); } 7761adb1b6491db3d3552d09a1c69ba5a37beb38d5reed 7836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onDraw(SkCanvas* canvas) 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: 12536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkString onShortName() override { return SkString("strokecircle"); } 1268ed666d230231c7280069236f265a61edb8a9a20reed 12736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkISize onISize() override { return SkISize::Make(520, 520); } 1288ed666d230231c7280069236f265a61edb8a9a20reed 12936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onDraw(SkCanvas* canvas) 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 15436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool onAnimate(const SkAnimTimer& timer) 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; ) 1659e779d495130009926fc5394a8971eec20494e5freed 1669e779d495130009926fc5394a8971eec20494e5freed////////////////////// 1679e779d495130009926fc5394a8971eec20494e5freed 1689e779d495130009926fc5394a8971eec20494e5freedstatic void html_canvas_arc(SkPath* path, SkScalar x, SkScalar y, SkScalar r, SkScalar start, 1699e779d495130009926fc5394a8971eec20494e5freed SkScalar end, bool ccw) { 1709e779d495130009926fc5394a8971eec20494e5freed SkRect bounds = { x - r, y - r, x + r, y + r }; 1719e779d495130009926fc5394a8971eec20494e5freed SkScalar sweep = ccw ? end - start : start - end; 1729e779d495130009926fc5394a8971eec20494e5freed path->arcTo(bounds, start, sweep, false); 1739e779d495130009926fc5394a8971eec20494e5freed} 1749e779d495130009926fc5394a8971eec20494e5freed 1759e779d495130009926fc5394a8971eec20494e5freed// Lifted from canvas-arc-circumference-fill-diffs.html 1769e779d495130009926fc5394a8971eec20494e5freedclass ManyArcsGM : public skiagm::GM { 1779e779d495130009926fc5394a8971eec20494e5freedpublic: 1789e779d495130009926fc5394a8971eec20494e5freed ManyArcsGM() {} 1799e779d495130009926fc5394a8971eec20494e5freed 1809e779d495130009926fc5394a8971eec20494e5freedprotected: 18136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkString onShortName() override { return SkString("manyarcs"); } 1829e779d495130009926fc5394a8971eec20494e5freed 18336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkISize onISize() override { return SkISize::Make(620, 330); } 1849e779d495130009926fc5394a8971eec20494e5freed 18536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onDraw(SkCanvas* canvas) override { 1869e779d495130009926fc5394a8971eec20494e5freed SkPaint paint; 1879e779d495130009926fc5394a8971eec20494e5freed paint.setAntiAlias(true); 1889e779d495130009926fc5394a8971eec20494e5freed paint.setStyle(SkPaint::kStroke_Style); 1899e779d495130009926fc5394a8971eec20494e5freed 1909e779d495130009926fc5394a8971eec20494e5freed canvas->translate(10, 10); 1919e779d495130009926fc5394a8971eec20494e5freed 1929e779d495130009926fc5394a8971eec20494e5freed // 20 angles. 1939e779d495130009926fc5394a8971eec20494e5freed SkScalar sweepAngles[] = { 1949e779d495130009926fc5394a8971eec20494e5freed -123.7f, -2.3f, -2, -1, -0.3f, -0.000001f, 0, 0.000001f, 0.3f, 0.7f, 1959e779d495130009926fc5394a8971eec20494e5freed 1, 1.3f, 1.5f, 1.7f, 1.99999f, 2, 2.00001f, 2.3f, 4.3f, 3934723942837.3f 1969e779d495130009926fc5394a8971eec20494e5freed }; 1979e779d495130009926fc5394a8971eec20494e5freed for (size_t i = 0; i < SK_ARRAY_COUNT(sweepAngles); ++i) { 1989e779d495130009926fc5394a8971eec20494e5freed sweepAngles[i] *= 180; 1999e779d495130009926fc5394a8971eec20494e5freed } 2009e779d495130009926fc5394a8971eec20494e5freed 2019e779d495130009926fc5394a8971eec20494e5freed SkScalar startAngles[] = { -1, -0.5f, 0, 0.5f }; 2029e779d495130009926fc5394a8971eec20494e5freed for (size_t i = 0; i < SK_ARRAY_COUNT(startAngles); ++i) { 2039e779d495130009926fc5394a8971eec20494e5freed startAngles[i] *= 180; 2049e779d495130009926fc5394a8971eec20494e5freed } 2059e779d495130009926fc5394a8971eec20494e5freed 2069e779d495130009926fc5394a8971eec20494e5freed bool anticlockwise = false; 2079e779d495130009926fc5394a8971eec20494e5freed SkScalar sign = 1; 2089e779d495130009926fc5394a8971eec20494e5freed for (size_t i = 0; i < SK_ARRAY_COUNT(startAngles) * 2; ++i) { 2099e779d495130009926fc5394a8971eec20494e5freed if (i == SK_ARRAY_COUNT(startAngles)) { 2109e779d495130009926fc5394a8971eec20494e5freed anticlockwise = true; 2119e779d495130009926fc5394a8971eec20494e5freed sign = -1; 2129e779d495130009926fc5394a8971eec20494e5freed } 2139e779d495130009926fc5394a8971eec20494e5freed SkScalar startAngle = startAngles[i % SK_ARRAY_COUNT(startAngles)] * sign; 2149e779d495130009926fc5394a8971eec20494e5freed canvas->save(); 2159e779d495130009926fc5394a8971eec20494e5freed for (size_t j = 0; j < SK_ARRAY_COUNT(sweepAngles); ++j) { 2169e779d495130009926fc5394a8971eec20494e5freed SkPath path; 2179e779d495130009926fc5394a8971eec20494e5freed path.moveTo(0, 2); 2189e779d495130009926fc5394a8971eec20494e5freed html_canvas_arc(&path, 18, 15, 10, startAngle, startAngle + (sweepAngles[j] * sign), 2199e779d495130009926fc5394a8971eec20494e5freed anticlockwise); 2209e779d495130009926fc5394a8971eec20494e5freed path.lineTo(0, 28); 2219e779d495130009926fc5394a8971eec20494e5freed canvas->drawPath(path, paint); 2229e779d495130009926fc5394a8971eec20494e5freed canvas->translate(30, 0); 2239e779d495130009926fc5394a8971eec20494e5freed } 2249e779d495130009926fc5394a8971eec20494e5freed canvas->restore(); 2259e779d495130009926fc5394a8971eec20494e5freed canvas->translate(0, 40); 2269e779d495130009926fc5394a8971eec20494e5freed } 2279e779d495130009926fc5394a8971eec20494e5freed } 2289e779d495130009926fc5394a8971eec20494e5freed 2299e779d495130009926fc5394a8971eec20494e5freedprivate: 2309e779d495130009926fc5394a8971eec20494e5freed typedef skiagm::GM INHERITED; 2319e779d495130009926fc5394a8971eec20494e5freed}; 2329e779d495130009926fc5394a8971eec20494e5freedDEF_GM( return new ManyArcsGM; ) 2339e779d495130009926fc5394a8971eec20494e5freed 234