circulararcs.cpp revision dbfd7ab10883f173f5c1b653a233e18dc6142002
1/* 2 * Copyright 2016 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 <functional> 9#include "SkCanvas.h" 10#include "SkDashPathEffect.h" 11#include "gm.h" 12 13constexpr SkScalar kStarts[] = {0.f, 10.f, 30.f, 45.f, 90.f, 165.f, 180.f, 270.f}; 14constexpr SkScalar kSweeps[] = {1.f, 45.f, 90.f, 130.f, 180.f, 184.f, 300.f, 355.f}; 15constexpr SkScalar kDiameter = 40.f; 16constexpr SkRect kRect = {0.f, 0.f, kDiameter, kDiameter}; 17constexpr int kW = 1000; 18constexpr int kH = 1000; 19constexpr SkScalar kPad = 20.f; 20 21void draw_arcs(SkCanvas* canvas, std::function<void(SkPaint*)> configureStyle) { 22 // Draws grid of arcs with different start/sweep angles in red and their complement arcs in 23 // blue. 24 auto drawGrid = [canvas, &configureStyle] (SkScalar x, SkScalar y, bool useCenter, bool aa) { 25 SkPaint p0; 26 p0.setColor(SK_ColorRED); 27 p0.setAntiAlias(aa); 28 // Set a reasonable stroke width that configureStyle can override. 29 p0.setStrokeWidth(15.f); 30 SkPaint p1 = p0; 31 p1.setColor(SK_ColorBLUE); 32 // Use alpha so we see magenta on overlap between arc and its complement. 33 p0.setAlpha(100); 34 p1.setAlpha(100); 35 configureStyle(&p0); 36 configureStyle(&p1); 37 38 canvas->save(); 39 canvas->translate(kPad + x, kPad + y); 40 for (auto start : kStarts) { 41 canvas->save(); 42 for (auto sweep : kSweeps) { 43 canvas->drawArc(kRect, start, sweep, useCenter, p0); 44 canvas->drawArc(kRect, start, -(360.f - sweep), useCenter, p1); 45 canvas->translate(kRect.width() + kPad, 0.f); 46 } 47 canvas->restore(); 48 canvas->translate(0, kRect.height() + kPad); 49 } 50 canvas->restore(); 51 }; 52 // Draw a grids for combo of enabling/disabling aa and using center. 53 constexpr SkScalar kGridW = kW / 2.f; 54 constexpr SkScalar kGridH = kH / 2.f; 55 drawGrid(0.f , 0.f , false, false); 56 drawGrid(kGridW, 0.f , true , false); 57 drawGrid(0.f , kGridH, false, true ); 58 drawGrid(kGridW, kGridH, true , true ); 59 // Draw separators between the grids. 60 SkPaint linePaint; 61 linePaint.setAntiAlias(true); 62 linePaint.setColor(SK_ColorBLACK); 63 canvas->drawLine(kGridW, 0.f , kGridW, SkIntToScalar(kH), linePaint); 64 canvas->drawLine(0.f , kGridH, SkIntToScalar(kW), kGridH, linePaint); 65} 66 67#define DEF_ARC_GM(name) DEF_SIMPLE_GM(circular_arcs_##name, canvas, kW, kH) 68 69DEF_ARC_GM(fill) { 70 auto setFill = [] (SkPaint*p) { p->setStyle(SkPaint::kFill_Style); }; 71 draw_arcs(canvas, setFill); 72} 73 74DEF_ARC_GM(hairline) { 75 auto setHairline = [] (SkPaint* p) { 76 p->setStyle(SkPaint::kStroke_Style); 77 p->setStrokeWidth(0.f); 78 }; 79 draw_arcs(canvas, setHairline); 80} 81 82DEF_ARC_GM(stroke_butt) { 83 auto setStroke = [](SkPaint* p) { 84 p->setStyle(SkPaint::kStroke_Style); 85 p->setStrokeCap(SkPaint::kButt_Cap); 86 }; 87 draw_arcs(canvas, setStroke); 88} 89 90DEF_ARC_GM(stroke_square) { 91 auto setStroke = [] (SkPaint* p) { 92 p->setStyle(SkPaint::kStroke_Style); 93 p->setStrokeCap(SkPaint::kSquare_Cap); 94 }; 95 draw_arcs(canvas, setStroke); 96} 97 98DEF_ARC_GM(stroke_round) { 99 auto setStroke = [] (SkPaint* p) { 100 p->setStyle(SkPaint::kStroke_Style); 101 p->setStrokeCap(SkPaint::kRound_Cap); 102 }; 103 draw_arcs(canvas, setStroke); 104} 105 106DEF_ARC_GM(stroke_and_fill_butt) { 107 auto setStroke = [] (SkPaint* p) { 108 p->setStyle(SkPaint::kStrokeAndFill_Style); 109 p->setStrokeCap(SkPaint::kButt_Cap); 110 }; 111 draw_arcs(canvas, setStroke); 112} 113 114DEF_ARC_GM(stroke_and_fill_square) { 115 auto setStroke = [] (SkPaint* p) { 116 p->setStyle(SkPaint::kStrokeAndFill_Style); 117 p->setStrokeCap(SkPaint::kSquare_Cap); 118 }; 119 draw_arcs(canvas, setStroke); 120} 121 122DEF_ARC_GM(stroke_and_fill_round) { 123 auto setStroke = [] (SkPaint* p) { 124 p->setStyle(SkPaint::kStrokeAndFill_Style); 125 p->setStrokeCap(SkPaint::kRound_Cap); 126 }; 127 draw_arcs(canvas, setStroke); 128} 129 130DEF_SIMPLE_GM(circular_arcs_weird, canvas, 1000, 400) { 131 constexpr SkScalar kS = 50; 132 struct Arc { 133 SkRect fOval; 134 SkScalar fStart; 135 SkScalar fSweep; 136 }; 137 const Arc noDrawArcs[] = { 138 // no sweep 139 {SkRect::MakeWH(kS, kS), 0, 0}, 140 // empty rect in x 141 {SkRect::MakeWH(-kS, kS), 0, 90}, 142 // empty rect in y 143 {SkRect::MakeWH(kS, -kS), 0, 90}, 144 // empty rect in x and y 145 {SkRect::MakeWH( 0, 0), 0, 90}, 146 }; 147 const Arc arcs[] = { 148 // large start 149 {SkRect::MakeWH(kS, kS), 810.f, 90.f}, 150 // large negative start 151 {SkRect::MakeWH(kS, kS), -810.f, 90.f}, 152 // exactly 360 sweep 153 {SkRect::MakeWH(kS, kS), 0.f, 360.f}, 154 // exactly -360 sweep 155 {SkRect::MakeWH(kS, kS), 0.f, -360.f}, 156 // exactly 540 sweep 157 {SkRect::MakeWH(kS, kS), 0.f, 540.f}, 158 // exactly -540 sweep 159 {SkRect::MakeWH(kS, kS), 0.f, -540.f}, 160 // generic large sweep and large start 161 {SkRect::MakeWH(kS, kS), 1125.f, 990.f}, 162 }; 163 SkTArray<SkPaint> paints; 164 // fill 165 paints.push_back(); 166 // stroke 167 paints.push_back().setStyle(SkPaint::kStroke_Style); 168 paints.back().setStrokeWidth(kS / 6.f); 169 // hairline 170 paints.push_back().setStyle(SkPaint::kStroke_Style); 171 paints.back().setStrokeWidth(0.f); 172 // stroke and fill 173 paints.push_back().setStyle(SkPaint::kStrokeAndFill_Style); 174 paints.back().setStrokeWidth(kS / 6.f); 175 // dash effect 176 paints.push_back().setStyle(SkPaint::kStroke_Style); 177 paints.back().setStrokeWidth(kS / 6.f); 178 constexpr SkScalar kDashIntervals[] = {kS / 15, 2 * kS / 15}; 179 paints.back().setPathEffect(SkDashPathEffect::Make(kDashIntervals, 2, 0.f)); 180 181 canvas->translate(kPad, kPad); 182 // This loop should draw nothing. 183 for (auto arc : noDrawArcs) { 184 for (auto paint : paints) { 185 paint.setAntiAlias(true); 186 canvas->drawArc(arc.fOval, arc.fStart, arc.fSweep, false, paint); 187 canvas->drawArc(arc.fOval, arc.fStart, arc.fSweep, true, paint); 188 } 189 } 190 191 SkPaint linePaint; 192 linePaint.setAntiAlias(true); 193 linePaint.setColor(SK_ColorRED); 194 SkScalar midX = SK_ARRAY_COUNT(arcs) * (kS + kPad) - kPad/2.f; 195 SkScalar height = paints.count() * (kS + kPad); 196 canvas->drawLine(midX, -kPad, midX, height, linePaint); 197 198 for (auto paint : paints) { 199 paint.setAntiAlias(true); 200 canvas->save(); 201 for (auto arc : arcs) { 202 canvas->drawArc(arc.fOval, arc.fStart, arc.fSweep, false, paint); 203 canvas->translate(kS + kPad, 0.f); 204 } 205 for (auto arc : arcs) { 206 canvas->drawArc(arc.fOval, arc.fStart, arc.fSweep, true, paint); 207 canvas->translate(kS + kPad, 0.f); 208 } 209 canvas->restore(); 210 canvas->translate(0, kS + kPad); 211 } 212} 213 214DEF_SIMPLE_GM(onebadarc, canvas, 100, 100) { 215 SkPath path; 216 path.moveTo(SkBits2Float(0x41a00000), SkBits2Float(0x41a00000)); // 20, 20 217 path.lineTo(SkBits2Float(0x4208918c), SkBits2Float(0x4208918c)); // 34.1421f, 34.1421f 218 path.conicTo(SkBits2Float(0x41a00000), SkBits2Float(0x42412318), // 20, 48.2843f 219 SkBits2Float(0x40bb73a0), SkBits2Float(0x4208918c), // 5.85786f, 34.1421f 220 SkBits2Float(0x3f3504f3)); // 0.707107f 221 path.quadTo(SkBits2Float(0x40bb73a0), SkBits2Float(0x4208918c), // 5.85786f, 34.1421f 222 SkBits2Float(0x40bb73a2), SkBits2Float(0x4208918c)); // 5.85787f, 34.1421f 223 path.lineTo(SkBits2Float(0x41a00000), SkBits2Float(0x41a00000)); // 20, 20 224 path.close(); 225 SkPaint p0; 226 p0.setColor(SK_ColorRED); 227 p0.setStrokeWidth(15.f); 228 p0.setStyle(SkPaint::kStroke_Style); 229 p0.setAlpha(100); 230 canvas->translate(20, 0); 231 canvas->drawPath(path, p0); 232 233 SkRect kRect = { 60, 0, 100, 40}; 234 canvas->drawArc(kRect, 45, 90, true, p0); 235} 236