circulararcs.cpp 9.1 KB

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