addarc.cpp revision f7834221ac5342a3446b9b299398ea3ff7976946
1/* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "gm.h" 9#include "SkAnimTimer.h" 10#include "SkCanvas.h" 11#include "SkPathMeasure.h" 12#include "SkRandom.h" 13 14class AddArcGM : public skiagm::GM { 15public: 16 AddArcGM() : fRotate(0) {} 17 18protected: 19 SkString onShortName() override { return SkString("addarc"); } 20 21 SkISize onISize() override { return SkISize::Make(1040, 1040); } 22 23 void onDraw(SkCanvas* canvas) override { 24 canvas->translate(20, 20); 25 26 SkRect r = SkRect::MakeWH(1000, 1000); 27 28 SkPaint paint; 29 paint.setAntiAlias(true); 30 paint.setStyle(SkPaint::kStroke_Style); 31 paint.setStrokeWidth(15); 32 33 const SkScalar inset = paint.getStrokeWidth() + 4; 34 const SkScalar sweepAngle = 345; 35 SkRandom rand; 36 37 SkScalar sign = 1; 38 while (r.width() > paint.getStrokeWidth() * 3) { 39 paint.setColor(rand.nextU() | (0xFF << 24)); 40 SkScalar startAngle = rand.nextUScalar1() * 360; 41 42 SkScalar speed = SkScalarSqrt(16 / r.width()) * 0.5f; 43 startAngle += fRotate * 360 * speed * sign; 44 45 SkPath path; 46 path.addArc(r, startAngle, sweepAngle); 47 canvas->drawPath(path, paint); 48 49 r.inset(inset, inset); 50 sign = -sign; 51 } 52 } 53 54 bool onAnimate(const SkAnimTimer& timer) override { 55 fRotate = timer.scaled(1, 360); 56 return true; 57 } 58 59private: 60 SkScalar fRotate; 61 typedef skiagm::GM INHERITED; 62}; 63DEF_GM( return new AddArcGM; ) 64 65/////////////////////////////////////////////////// 66 67#define R 400 68 69class AddArcMeasGM : public skiagm::GM { 70public: 71 AddArcMeasGM() {} 72 73protected: 74 SkString onShortName() override { return SkString("addarc_meas"); } 75 76 SkISize onISize() override { return SkISize::Make(2*R + 40, 2*R + 40); } 77 78 void onDraw(SkCanvas* canvas) override { 79 canvas->translate(R + 20, R + 20); 80 81 SkPaint paint; 82 paint.setAntiAlias(true); 83 paint.setStyle(SkPaint::kStroke_Style); 84 85 SkPaint measPaint; 86 measPaint.setAntiAlias(true); 87 measPaint.setColor(SK_ColorRED); 88 89 const SkRect oval = SkRect::MakeLTRB(-R, -R, R, R); 90 canvas->drawOval(oval, paint); 91 92 for (SkScalar deg = 0; deg < 360; deg += 10) { 93 const SkScalar rad = SkDegreesToRadians(deg); 94 SkScalar rx = SkScalarCos(rad) * R; 95 SkScalar ry = SkScalarSin(rad) * R; 96 97 canvas->drawLine(0, 0, rx, ry, paint); 98 99 SkPath path; 100 path.addArc(oval, 0, deg); 101 SkPathMeasure meas(path, false); 102 SkScalar arcLen = rad * R; 103 SkPoint pos; 104 if (meas.getPosTan(arcLen, &pos, NULL)) { 105 canvas->drawLine(0, 0, pos.x(), pos.y(), measPaint); 106 } 107 } 108 } 109 110private: 111 typedef skiagm::GM INHERITED; 112}; 113DEF_GM( return new AddArcMeasGM; ) 114 115/////////////////////////////////////////////////// 116 117// Emphasize drawing a stroked oval (containing conics) and then scaling the results up, 118// to ensure that we compute the stroke taking the CTM into account 119// 120class StrokeCircleGM : public skiagm::GM { 121public: 122 StrokeCircleGM() : fRotate(0) {} 123 124protected: 125 SkString onShortName() override { return SkString("strokecircle"); } 126 127 SkISize onISize() override { return SkISize::Make(520, 520); } 128 129 void onDraw(SkCanvas* canvas) override { 130 canvas->scale(20, 20); 131 canvas->translate(13, 13); 132 133 SkPaint paint; 134 paint.setAntiAlias(true); 135 paint.setStyle(SkPaint::kStroke_Style); 136 paint.setStrokeWidth(SK_Scalar1 / 2); 137 138 const SkScalar delta = paint.getStrokeWidth() * 3 / 2; 139 SkRect r = SkRect::MakeXYWH(-12, -12, 24, 24); 140 SkRandom rand; 141 142 SkScalar sign = 1; 143 while (r.width() > paint.getStrokeWidth() * 2) { 144 SkAutoCanvasRestore acr(canvas, true); 145 canvas->rotate(fRotate * sign); 146 147 paint.setColor(rand.nextU() | (0xFF << 24)); 148 canvas->drawOval(r, paint); 149 r.inset(delta, delta); 150 sign = -sign; 151 } 152 } 153 154 bool onAnimate(const SkAnimTimer& timer) override { 155 fRotate = timer.scaled(60, 360); 156 return true; 157 } 158 159private: 160 SkScalar fRotate; 161 162 typedef skiagm::GM INHERITED; 163}; 164DEF_GM( return new StrokeCircleGM; ) 165 166////////////////////// 167 168static void html_canvas_arc(SkPath* path, SkScalar x, SkScalar y, SkScalar r, SkScalar start, 169 SkScalar end, bool ccw) { 170 SkRect bounds = { x - r, y - r, x + r, y + r }; 171 SkScalar sweep = ccw ? end - start : start - end; 172 path->arcTo(bounds, start, sweep, false); 173} 174 175// Lifted from canvas-arc-circumference-fill-diffs.html 176class ManyArcsGM : public skiagm::GM { 177public: 178 ManyArcsGM() {} 179 180protected: 181 SkString onShortName() override { return SkString("manyarcs"); } 182 183 SkISize onISize() override { return SkISize::Make(620, 330); } 184 185 void onDraw(SkCanvas* canvas) override { 186 SkPaint paint; 187 paint.setAntiAlias(true); 188 paint.setStyle(SkPaint::kStroke_Style); 189 190 canvas->translate(10, 10); 191 192 // 20 angles. 193 SkScalar sweepAngles[] = { 194 -123.7f, -2.3f, -2, -1, -0.3f, -0.000001f, 0, 0.000001f, 0.3f, 0.7f, 195 1, 1.3f, 1.5f, 1.7f, 1.99999f, 2, 2.00001f, 2.3f, 4.3f, 3934723942837.3f 196 }; 197 for (size_t i = 0; i < SK_ARRAY_COUNT(sweepAngles); ++i) { 198 sweepAngles[i] *= 180; 199 } 200 201 SkScalar startAngles[] = { -1, -0.5f, 0, 0.5f }; 202 for (size_t i = 0; i < SK_ARRAY_COUNT(startAngles); ++i) { 203 startAngles[i] *= 180; 204 } 205 206 bool anticlockwise = false; 207 SkScalar sign = 1; 208 for (size_t i = 0; i < SK_ARRAY_COUNT(startAngles) * 2; ++i) { 209 if (i == SK_ARRAY_COUNT(startAngles)) { 210 anticlockwise = true; 211 sign = -1; 212 } 213 SkScalar startAngle = startAngles[i % SK_ARRAY_COUNT(startAngles)] * sign; 214 canvas->save(); 215 for (size_t j = 0; j < SK_ARRAY_COUNT(sweepAngles); ++j) { 216 SkPath path; 217 path.moveTo(0, 2); 218 html_canvas_arc(&path, 18, 15, 10, startAngle, startAngle + (sweepAngles[j] * sign), 219 anticlockwise); 220 path.lineTo(0, 28); 221 canvas->drawPath(path, paint); 222 canvas->translate(30, 0); 223 } 224 canvas->restore(); 225 canvas->translate(0, 40); 226 } 227 } 228 229private: 230 typedef skiagm::GM INHERITED; 231}; 232DEF_GM( return new ManyArcsGM; ) 233 234