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