roundrects.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. /*
  2. * Copyright 2013 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/SkMatrix.h"
  11. #include "include/core/SkPaint.h"
  12. #include "include/core/SkPoint.h"
  13. #include "include/core/SkRRect.h"
  14. #include "include/core/SkRect.h"
  15. #include "include/core/SkScalar.h"
  16. #include "include/core/SkShader.h"
  17. #include "include/core/SkSize.h"
  18. #include "include/core/SkString.h"
  19. #include "include/core/SkTileMode.h"
  20. #include "include/core/SkTypes.h"
  21. #include "include/effects/SkGradientShader.h"
  22. #include "include/private/SkTArray.h"
  23. #include "include/utils/SkRandom.h"
  24. #include "tools/ToolUtils.h"
  25. namespace skiagm {
  26. static SkColor gen_color(SkRandom* rand) {
  27. SkScalar hsv[3];
  28. hsv[0] = rand->nextRangeF(0.0f, 360.0f);
  29. hsv[1] = rand->nextRangeF(0.75f, 1.0f);
  30. hsv[2] = rand->nextRangeF(0.75f, 1.0f);
  31. return ToolUtils::color_to_565(SkHSVToColor(hsv));
  32. }
  33. class RoundRectGM : public GM {
  34. public:
  35. RoundRectGM() {
  36. this->setBGColor(0xFF000000);
  37. this->makePaints();
  38. this->makeMatrices();
  39. }
  40. protected:
  41. SkString onShortName() override {
  42. return SkString("roundrects");
  43. }
  44. SkISize onISize() override {
  45. return SkISize::Make(1200, 900);
  46. }
  47. void makePaints() {
  48. {
  49. // no AA
  50. SkPaint p;
  51. fPaints.push_back(p);
  52. }
  53. {
  54. // AA
  55. SkPaint p;
  56. p.setAntiAlias(true);
  57. fPaints.push_back(p);
  58. }
  59. {
  60. // AA with stroke style
  61. SkPaint p;
  62. p.setAntiAlias(true);
  63. p.setStyle(SkPaint::kStroke_Style);
  64. p.setStrokeWidth(SkIntToScalar(5));
  65. fPaints.push_back(p);
  66. }
  67. {
  68. // AA with stroke style, width = 0
  69. SkPaint p;
  70. p.setAntiAlias(true);
  71. p.setStyle(SkPaint::kStroke_Style);
  72. fPaints.push_back(p);
  73. }
  74. {
  75. // AA with stroke and fill style
  76. SkPaint p;
  77. p.setAntiAlias(true);
  78. p.setStyle(SkPaint::kStrokeAndFill_Style);
  79. p.setStrokeWidth(SkIntToScalar(3));
  80. fPaints.push_back(p);
  81. }
  82. }
  83. void makeMatrices() {
  84. {
  85. SkMatrix m;
  86. m.setIdentity();
  87. fMatrices.push_back(m);
  88. }
  89. {
  90. SkMatrix m;
  91. m.setScale(SkIntToScalar(3), SkIntToScalar(2));
  92. fMatrices.push_back(m);
  93. }
  94. {
  95. SkMatrix m;
  96. m.setScale(SkIntToScalar(2), SkIntToScalar(2));
  97. fMatrices.push_back(m);
  98. }
  99. {
  100. SkMatrix m;
  101. m.setScale(SkIntToScalar(1), SkIntToScalar(2));
  102. fMatrices.push_back(m);
  103. }
  104. {
  105. SkMatrix m;
  106. m.setScale(SkIntToScalar(4), SkIntToScalar(1));
  107. fMatrices.push_back(m);
  108. }
  109. {
  110. SkMatrix m;
  111. m.setRotate(SkIntToScalar(90));
  112. fMatrices.push_back(m);
  113. }
  114. {
  115. SkMatrix m;
  116. m.setSkew(SkIntToScalar(2), SkIntToScalar(3));
  117. fMatrices.push_back(m);
  118. }
  119. {
  120. SkMatrix m;
  121. m.setRotate(SkIntToScalar(60));
  122. fMatrices.push_back(m);
  123. }
  124. }
  125. void onDraw(SkCanvas* canvas) override {
  126. SkRandom rand(1);
  127. canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
  128. const SkRect rect = SkRect::MakeLTRB(-20, -30, 20, 30);
  129. SkRRect circleRect;
  130. circleRect.setRectXY(rect, 5, 5);
  131. const SkScalar kXStart = 60.0f;
  132. const SkScalar kYStart = 80.0f;
  133. const int kXStep = 150;
  134. const int kYStep = 160;
  135. int maxX = fMatrices.count();
  136. SkPaint rectPaint;
  137. rectPaint.setAntiAlias(true);
  138. rectPaint.setStyle(SkPaint::kStroke_Style);
  139. rectPaint.setStrokeWidth(SkIntToScalar(0));
  140. rectPaint.setColor(SK_ColorLTGRAY);
  141. int testCount = 0;
  142. for (int i = 0; i < fPaints.count(); ++i) {
  143. for (int j = 0; j < fMatrices.count(); ++j) {
  144. canvas->save();
  145. SkMatrix mat = fMatrices[j];
  146. // position the roundrect, and make it at off-integer coords.
  147. mat.postTranslate(kXStart + SK_Scalar1 * kXStep * (testCount % maxX) +
  148. SK_Scalar1 / 4,
  149. kYStart + SK_Scalar1 * kYStep * (testCount / maxX) +
  150. 3 * SK_Scalar1 / 4);
  151. canvas->concat(mat);
  152. SkColor color = gen_color(&rand);
  153. fPaints[i].setColor(color);
  154. canvas->drawRect(rect, rectPaint);
  155. canvas->drawRRect(circleRect, fPaints[i]);
  156. canvas->restore();
  157. ++testCount;
  158. }
  159. }
  160. // special cases
  161. // non-scaled tall and skinny roundrect
  162. for (int i = 0; i < fPaints.count(); ++i) {
  163. SkRect rect = SkRect::MakeLTRB(-20, -60, 20, 60);
  164. SkRRect ellipseRect;
  165. ellipseRect.setRectXY(rect, 5, 10);
  166. canvas->save();
  167. // position the roundrect, and make it at off-integer coords.
  168. canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.55f + SK_Scalar1 / 4,
  169. kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);
  170. SkColor color = gen_color(&rand);
  171. fPaints[i].setColor(color);
  172. canvas->drawRect(rect, rectPaint);
  173. canvas->drawRRect(ellipseRect, fPaints[i]);
  174. canvas->restore();
  175. }
  176. // non-scaled wide and short roundrect
  177. for (int i = 0; i < fPaints.count(); ++i) {
  178. SkRect rect = SkRect::MakeLTRB(-80, -30, 80, 30);
  179. SkRRect ellipseRect;
  180. ellipseRect.setRectXY(rect, 20, 5);
  181. canvas->save();
  182. // position the roundrect, and make it at off-integer coords.
  183. canvas->translate(kXStart + SK_Scalar1 * kXStep * 4 + SK_Scalar1 / 4,
  184. kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
  185. SK_ScalarHalf * kYStep);
  186. SkColor color = gen_color(&rand);
  187. fPaints[i].setColor(color);
  188. canvas->drawRect(rect, rectPaint);
  189. canvas->drawRRect(ellipseRect, fPaints[i]);
  190. canvas->restore();
  191. }
  192. // super skinny roundrect
  193. for (int i = 0; i < fPaints.count(); ++i) {
  194. SkRect rect = SkRect::MakeLTRB(0, -60, 1, 60);
  195. SkRRect circleRect;
  196. circleRect.setRectXY(rect, 5, 5);
  197. canvas->save();
  198. // position the roundrect, and make it at off-integer coords.
  199. canvas->translate(kXStart + SK_Scalar1 * kXStep * 3.25f + SK_Scalar1 / 4,
  200. kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);
  201. SkColor color = gen_color(&rand);
  202. fPaints[i].setColor(color);
  203. canvas->drawRRect(circleRect, fPaints[i]);
  204. canvas->restore();
  205. }
  206. // super short roundrect
  207. for (int i = 0; i < fPaints.count(); ++i) {
  208. SkRect rect = SkRect::MakeLTRB(-80, -1, 80, 0);
  209. SkRRect circleRect;
  210. circleRect.setRectXY(rect, 5, 5);
  211. canvas->save();
  212. // position the roundrect, and make it at off-integer coords.
  213. canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.5f + SK_Scalar1 / 4,
  214. kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
  215. SK_ScalarHalf * kYStep);
  216. SkColor color = gen_color(&rand);
  217. fPaints[i].setColor(color);
  218. canvas->drawRRect(circleRect, fPaints[i]);
  219. canvas->restore();
  220. }
  221. // radial gradient
  222. SkPoint center = SkPoint::Make(SkIntToScalar(0), SkIntToScalar(0));
  223. SkColor colors[] = { SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN };
  224. SkScalar pos[] = { 0, SK_ScalarHalf, SK_Scalar1 };
  225. auto shader = SkGradientShader::MakeRadial(center, 20, colors, pos, SK_ARRAY_COUNT(colors),
  226. SkTileMode::kClamp);
  227. for (int i = 0; i < fPaints.count(); ++i) {
  228. canvas->save();
  229. // position the path, and make it at off-integer coords.
  230. canvas->translate(kXStart + SK_Scalar1 * kXStep * 0 + SK_Scalar1 / 4,
  231. kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
  232. SK_ScalarHalf * kYStep);
  233. SkColor color = gen_color(&rand);
  234. fPaints[i].setColor(color);
  235. fPaints[i].setShader(shader);
  236. canvas->drawRect(rect, rectPaint);
  237. canvas->drawRRect(circleRect, fPaints[i]);
  238. fPaints[i].setShader(nullptr);
  239. canvas->restore();
  240. }
  241. // strokes and radii
  242. {
  243. SkScalar radii[][2] = {
  244. {10,10},
  245. {5,15},
  246. {5,15},
  247. {5,15}
  248. };
  249. SkScalar strokeWidths[] = {
  250. 20, 10, 20, 40
  251. };
  252. for (int i = 0; i < 4; ++i) {
  253. SkRRect circleRect;
  254. circleRect.setRectXY(rect, radii[i][0], radii[i][1]);
  255. canvas->save();
  256. // position the roundrect, and make it at off-integer coords.
  257. canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4,
  258. kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
  259. SK_ScalarHalf * kYStep);
  260. SkColor color = gen_color(&rand);
  261. SkPaint p;
  262. p.setAntiAlias(true);
  263. p.setStyle(SkPaint::kStroke_Style);
  264. p.setStrokeWidth(strokeWidths[i]);
  265. p.setColor(color);
  266. canvas->drawRRect(circleRect, p);
  267. canvas->restore();
  268. }
  269. }
  270. // test old entry point ( https://bug.skia.org/3786 )
  271. {
  272. canvas->save();
  273. canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4,
  274. kYStart + SK_Scalar1 * kYStep * 4 + SK_Scalar1 / 4 +
  275. SK_ScalarHalf * kYStep);
  276. const SkColor color = gen_color(&rand);
  277. SkPaint p;
  278. p.setColor(color);
  279. const SkRect oooRect = { 20, 30, -20, -30 }; // intentionally out of order
  280. canvas->drawRoundRect(oooRect, 10, 10, p);
  281. canvas->restore();
  282. }
  283. // rrect with stroke > radius/2
  284. {
  285. SkRect smallRect = { -30, -20, 30, 20 };
  286. SkRRect circleRect;
  287. circleRect.setRectXY(smallRect, 5, 5);
  288. canvas->save();
  289. // position the roundrect, and make it at off-integer coords.
  290. canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4,
  291. kYStart - SK_Scalar1 * kYStep + 73 * SK_Scalar1 / 4 +
  292. SK_ScalarHalf * kYStep);
  293. SkColor color = gen_color(&rand);
  294. SkPaint p;
  295. p.setAntiAlias(true);
  296. p.setStyle(SkPaint::kStroke_Style);
  297. p.setStrokeWidth(25);
  298. p.setColor(color);
  299. canvas->drawRRect(circleRect, p);
  300. canvas->restore();
  301. }
  302. }
  303. private:
  304. SkTArray<SkPaint> fPaints;
  305. SkTArray<SkMatrix> fMatrices;
  306. typedef GM INHERITED;
  307. };
  308. //////////////////////////////////////////////////////////////////////////////
  309. DEF_GM( return new RoundRectGM; )
  310. }