degeneratesegments.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /*
  2. * Copyright 2011 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/SkFont.h"
  11. #include "include/core/SkPaint.h"
  12. #include "include/core/SkPath.h"
  13. #include "include/core/SkPoint.h"
  14. #include "include/core/SkRect.h"
  15. #include "include/core/SkScalar.h"
  16. #include "include/core/SkSize.h"
  17. #include "include/core/SkString.h"
  18. #include "include/core/SkTypeface.h"
  19. #include "include/core/SkTypes.h"
  20. #include "include/utils/SkRandom.h"
  21. #include "tools/ToolUtils.h"
  22. namespace skiagm {
  23. class DegenerateSegmentsGM : public GM {
  24. struct PathAndName {
  25. SkPath fPath;
  26. const char* fName1;
  27. const char* fName2;
  28. };
  29. SkString onShortName() override { return SkString("degeneratesegments"); }
  30. SkISize onISize() override { return {896, 930}; }
  31. typedef SkPoint (*AddSegmentFunc)(SkPath&, SkPoint&);
  32. // We need to use explicit commands here, instead of addPath, because we
  33. // do not want the moveTo that is added at the beginning of a path to
  34. // appear in the appended path.
  35. static SkPoint AddMove(SkPath& path, SkPoint& startPt) {
  36. SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
  37. path.moveTo(moveToPt);
  38. return moveToPt;
  39. }
  40. static SkPoint AddMoveClose(SkPath& path, SkPoint& startPt) {
  41. SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
  42. path.moveTo(moveToPt);
  43. path.close();
  44. return moveToPt;
  45. }
  46. static SkPoint AddDegenLine(SkPath& path, SkPoint& startPt) {
  47. path.lineTo(startPt);
  48. return startPt;
  49. }
  50. static SkPoint AddMoveDegenLine(SkPath& path, SkPoint& startPt) {
  51. SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
  52. path.moveTo(moveToPt);
  53. path.lineTo(moveToPt);
  54. return moveToPt;
  55. }
  56. static SkPoint AddMoveDegenLineClose(SkPath& path, SkPoint& startPt) {
  57. SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
  58. path.moveTo(moveToPt);
  59. path.lineTo(moveToPt);
  60. path.close();
  61. return moveToPt;
  62. }
  63. static SkPoint AddDegenQuad(SkPath& path, SkPoint& startPt) {
  64. path.quadTo(startPt, startPt);
  65. return startPt;
  66. }
  67. static SkPoint AddMoveDegenQuad(SkPath& path, SkPoint& startPt) {
  68. SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
  69. path.moveTo(moveToPt);
  70. path.quadTo(moveToPt, moveToPt);
  71. return moveToPt;
  72. }
  73. static SkPoint AddMoveDegenQuadClose(SkPath& path, SkPoint& startPt) {
  74. SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
  75. path.moveTo(moveToPt);
  76. path.quadTo(moveToPt, moveToPt);
  77. path.close();
  78. return moveToPt;
  79. }
  80. static SkPoint AddDegenCubic(SkPath& path, SkPoint& startPt) {
  81. path.cubicTo(startPt, startPt, startPt);
  82. return startPt;
  83. }
  84. static SkPoint AddMoveDegenCubic(SkPath& path, SkPoint& startPt) {
  85. SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
  86. path.moveTo(moveToPt);
  87. path.cubicTo(moveToPt, moveToPt, moveToPt);
  88. return moveToPt;
  89. }
  90. static SkPoint AddMoveDegenCubicClose(SkPath& path, SkPoint& startPt) {
  91. SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
  92. path.moveTo(moveToPt);
  93. path.cubicTo(moveToPt, moveToPt, moveToPt);
  94. path.close();
  95. return moveToPt;
  96. }
  97. static SkPoint AddClose(SkPath& path, SkPoint& startPt) {
  98. path.close();
  99. return startPt;
  100. }
  101. static SkPoint AddLine(SkPath& path, SkPoint& startPt) {
  102. SkPoint endPt = startPt + SkPoint::Make(40*SK_Scalar1, 0);
  103. path.lineTo(endPt);
  104. return endPt;
  105. }
  106. static SkPoint AddMoveLine(SkPath& path, SkPoint& startPt) {
  107. SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
  108. SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
  109. path.moveTo(moveToPt);
  110. path.lineTo(endPt);
  111. return endPt;
  112. }
  113. static SkPoint AddMoveLineClose(SkPath& path, SkPoint& startPt) {
  114. SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
  115. SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
  116. path.moveTo(moveToPt);
  117. path.lineTo(endPt);
  118. path.close();
  119. return endPt;
  120. }
  121. static SkPoint AddQuad(SkPath& path, SkPoint& startPt) {
  122. SkPoint midPt = startPt + SkPoint::Make(20*SK_Scalar1, 5*SK_Scalar1);
  123. SkPoint endPt = startPt + SkPoint::Make(40*SK_Scalar1, 0);
  124. path.quadTo(midPt, endPt);
  125. return endPt;
  126. }
  127. static SkPoint AddMoveQuad(SkPath& path, SkPoint& startPt) {
  128. SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
  129. SkPoint midPt = moveToPt + SkPoint::Make(20*SK_Scalar1, 5*SK_Scalar1);
  130. SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
  131. path.moveTo(moveToPt);
  132. path.quadTo(midPt, endPt);
  133. return endPt;
  134. }
  135. static SkPoint AddMoveQuadClose(SkPath& path, SkPoint& startPt) {
  136. SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
  137. SkPoint midPt = moveToPt + SkPoint::Make(20*SK_Scalar1, 5*SK_Scalar1);
  138. SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
  139. path.moveTo(moveToPt);
  140. path.quadTo(midPt, endPt);
  141. path.close();
  142. return endPt;
  143. }
  144. static SkPoint AddCubic(SkPath& path, SkPoint& startPt) {
  145. SkPoint t1Pt = startPt + SkPoint::Make(15*SK_Scalar1, 5*SK_Scalar1);
  146. SkPoint t2Pt = startPt + SkPoint::Make(25*SK_Scalar1, 5*SK_Scalar1);
  147. SkPoint endPt = startPt + SkPoint::Make(40*SK_Scalar1, 0);
  148. path.cubicTo(t1Pt, t2Pt, endPt);
  149. return endPt;
  150. }
  151. static SkPoint AddMoveCubic(SkPath& path, SkPoint& startPt) {
  152. SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
  153. SkPoint t1Pt = moveToPt + SkPoint::Make(15*SK_Scalar1, 5*SK_Scalar1);
  154. SkPoint t2Pt = moveToPt + SkPoint::Make(25*SK_Scalar1, 5*SK_Scalar1);
  155. SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
  156. path.moveTo(moveToPt);
  157. path.cubicTo(t1Pt, t2Pt, endPt);
  158. return endPt;
  159. }
  160. static SkPoint AddMoveCubicClose(SkPath& path, SkPoint& startPt) {
  161. SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
  162. SkPoint t1Pt = moveToPt + SkPoint::Make(15*SK_Scalar1, 5*SK_Scalar1);
  163. SkPoint t2Pt = moveToPt + SkPoint::Make(25*SK_Scalar1, 5*SK_Scalar1);
  164. SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
  165. path.moveTo(moveToPt);
  166. path.cubicTo(t1Pt, t2Pt, endPt);
  167. path.close();
  168. return endPt;
  169. }
  170. void drawPath(SkPath& path, SkCanvas* canvas, SkColor color,
  171. const SkRect& clip, SkPaint::Cap cap, SkPaint::Join join,
  172. SkPaint::Style style, SkPath::FillType fill,
  173. SkScalar strokeWidth) {
  174. path.setFillType(fill);
  175. SkPaint paint;
  176. paint.setStrokeCap(cap);
  177. paint.setStrokeWidth(strokeWidth);
  178. paint.setStrokeJoin(join);
  179. paint.setColor(color);
  180. paint.setStyle(style);
  181. canvas->save();
  182. canvas->clipRect(clip);
  183. canvas->drawPath(path, paint);
  184. canvas->restore();
  185. }
  186. void onDraw(SkCanvas* canvas) override {
  187. constexpr AddSegmentFunc gSegmentFunctions[] = {
  188. AddMove,
  189. AddMoveClose,
  190. AddDegenLine,
  191. AddMoveDegenLine,
  192. AddMoveDegenLineClose,
  193. AddDegenQuad,
  194. AddMoveDegenQuad,
  195. AddMoveDegenQuadClose,
  196. AddDegenCubic,
  197. AddMoveDegenCubic,
  198. AddMoveDegenCubicClose,
  199. AddClose,
  200. AddLine,
  201. AddMoveLine,
  202. AddMoveLineClose,
  203. AddQuad,
  204. AddMoveQuad,
  205. AddMoveQuadClose,
  206. AddCubic,
  207. AddMoveCubic,
  208. AddMoveCubicClose
  209. };
  210. const char* gSegmentNames[] = {
  211. "Move",
  212. "MoveClose",
  213. "DegenLine",
  214. "MoveDegenLine",
  215. "MoveDegenLineClose",
  216. "DegenQuad",
  217. "MoveDegenQuad",
  218. "MoveDegenQuadClose",
  219. "DegenCubic",
  220. "MoveDegenCubic",
  221. "MoveDegenCubicClose",
  222. "Close",
  223. "Line",
  224. "MoveLine",
  225. "MoveLineClose",
  226. "Quad",
  227. "MoveQuad",
  228. "MoveQuadClose",
  229. "Cubic",
  230. "MoveCubic",
  231. "MoveCubicClose"
  232. };
  233. struct FillAndName {
  234. SkPath::FillType fFill;
  235. const char* fName;
  236. };
  237. constexpr FillAndName gFills[] = {
  238. {SkPath::kWinding_FillType, "Winding"},
  239. {SkPath::kEvenOdd_FillType, "Even / Odd"},
  240. {SkPath::kInverseWinding_FillType, "Inverse Winding"},
  241. {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"}
  242. };
  243. struct StyleAndName {
  244. SkPaint::Style fStyle;
  245. const char* fName;
  246. };
  247. constexpr StyleAndName gStyles[] = {
  248. {SkPaint::kFill_Style, "Fill"},
  249. {SkPaint::kStroke_Style, "Stroke 10"},
  250. {SkPaint::kStrokeAndFill_Style, "Stroke 10 And Fill"}
  251. };
  252. struct CapAndName {
  253. SkPaint::Cap fCap;
  254. SkPaint::Join fJoin;
  255. const char* fName;
  256. };
  257. constexpr CapAndName gCaps[] = {
  258. {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
  259. {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
  260. {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
  261. };
  262. SkPaint titlePaint;
  263. titlePaint.setColor(SK_ColorBLACK);
  264. titlePaint.setAntiAlias(true);
  265. SkFont font(ToolUtils::create_portable_typeface(), 15);
  266. const char title[] = "Random Paths Drawn Into Rectangle Clips With "
  267. "Indicated Style, Fill and Linecaps, "
  268. "with Stroke width 6";
  269. canvas->drawString(title, 20, 20, font, titlePaint);
  270. SkRandom rand;
  271. SkRect rect = SkRect::MakeWH(220*SK_Scalar1, 50*SK_Scalar1);
  272. canvas->save();
  273. canvas->translate(2*SK_Scalar1, 30 * SK_Scalar1); // The title
  274. canvas->save();
  275. unsigned numSegments = SK_ARRAY_COUNT(gSegmentFunctions);
  276. unsigned numCaps = SK_ARRAY_COUNT(gCaps);
  277. unsigned numStyles = SK_ARRAY_COUNT(gStyles);
  278. unsigned numFills = SK_ARRAY_COUNT(gFills);
  279. for (size_t row = 0; row < 6; ++row) {
  280. if (0 < row) {
  281. canvas->translate(0, rect.height() + 100*SK_Scalar1);
  282. }
  283. canvas->save();
  284. for (size_t column = 0; column < 4; ++column) {
  285. if (0 < column) {
  286. canvas->translate(rect.width() + 4*SK_Scalar1, 0);
  287. }
  288. SkColor color = ToolUtils::color_to_565(0xff007000);
  289. StyleAndName style = gStyles[(rand.nextU() >> 16) % numStyles];
  290. CapAndName cap = gCaps[(rand.nextU() >> 16) % numCaps];
  291. FillAndName fill = gFills[(rand.nextU() >> 16) % numFills];
  292. SkPath path;
  293. unsigned s1 = (rand.nextU() >> 16) % numSegments;
  294. unsigned s2 = (rand.nextU() >> 16) % numSegments;
  295. unsigned s3 = (rand.nextU() >> 16) % numSegments;
  296. unsigned s4 = (rand.nextU() >> 16) % numSegments;
  297. unsigned s5 = (rand.nextU() >> 16) % numSegments;
  298. SkPoint pt = SkPoint::Make(10*SK_Scalar1, 0);
  299. pt = gSegmentFunctions[s1](path, pt);
  300. pt = gSegmentFunctions[s2](path, pt);
  301. pt = gSegmentFunctions[s3](path, pt);
  302. pt = gSegmentFunctions[s4](path, pt);
  303. pt = gSegmentFunctions[s5](path, pt);
  304. this->drawPath(path, canvas, color, rect,
  305. cap.fCap, cap.fJoin, style.fStyle,
  306. fill.fFill, SK_Scalar1*6);
  307. SkPaint rectPaint;
  308. rectPaint.setColor(SK_ColorBLACK);
  309. rectPaint.setStyle(SkPaint::kStroke_Style);
  310. rectPaint.setStrokeWidth(-1);
  311. rectPaint.setAntiAlias(true);
  312. canvas->drawRect(rect, rectPaint);
  313. SkPaint labelPaint;
  314. labelPaint.setColor(color);
  315. labelPaint.setAntiAlias(true);
  316. font.setSize(10);
  317. canvas->drawString(style.fName, 0, rect.height() + 12, font, labelPaint);
  318. canvas->drawString(fill.fName, 0, rect.height() + 24, font, labelPaint);
  319. canvas->drawString(cap.fName, 0, rect.height() + 36, font, labelPaint);
  320. canvas->drawString(gSegmentNames[s1], 0, rect.height() + 48, font, labelPaint);
  321. canvas->drawString(gSegmentNames[s2], 0, rect.height() + 60, font, labelPaint);
  322. canvas->drawString(gSegmentNames[s3], 0, rect.height() + 72, font, labelPaint);
  323. canvas->drawString(gSegmentNames[s4], 0, rect.height() + 84, font, labelPaint);
  324. canvas->drawString(gSegmentNames[s5], 0, rect.height() + 96, font, labelPaint);
  325. }
  326. canvas->restore();
  327. }
  328. canvas->restore();
  329. canvas->restore();
  330. }
  331. };
  332. //////////////////////////////////////////////////////////////////////////////
  333. DEF_GM( return new DegenerateSegmentsGM; )
  334. }