trickycubicstrokes.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /*
  2. * Copyright 2018 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/SkPath.h"
  13. #include "include/core/SkPoint.h"
  14. #include "include/core/SkRect.h"
  15. #include "include/core/SkSize.h"
  16. #include "include/core/SkString.h"
  17. #include "include/core/SkTypes.h"
  18. #include "src/core/SkGeometry.h"
  19. static constexpr float kStrokeWidth = 40;
  20. static constexpr int kCellSize = 200;
  21. static const SkPoint kCubics[][4] = {
  22. {{122, 737}, {348, 553}, {403, 761}, {400, 760}},
  23. {{244, 520}, {244, 518}, {1141, 634}, {394, 688}},
  24. {{550, 194}, {138, 130}, {1035, 246}, {288, 300}},
  25. {{226, 733}, {556, 779}, {-43, 471}, {348, 683}},
  26. {{268, 204}, {492, 304}, {352, 23}, {433, 412}},
  27. {{172, 480}, {396, 580}, {256, 299}, {338, 677}},
  28. {{731, 340}, {318, 252}, {1026, -64}, {367, 265}},
  29. {{475, 708}, {62, 620}, {770, 304}, {220, 659}},
  30. };
  31. static SkRect calc_tight_cubic_bounds(const SkPoint P[4], int depth=5) {
  32. if (0 == depth) {
  33. SkRect bounds;
  34. bounds.fLeft = SkTMin(SkTMin(P[0].x(), P[1].x()), SkTMin(P[2].x(), P[3].x()));
  35. bounds.fTop = SkTMin(SkTMin(P[0].y(), P[1].y()), SkTMin(P[2].y(), P[3].y()));
  36. bounds.fRight = SkTMax(SkTMax(P[0].x(), P[1].x()), SkTMax(P[2].x(), P[3].x()));
  37. bounds.fBottom = SkTMax(SkTMax(P[0].y(), P[1].y()), SkTMax(P[2].y(), P[3].y()));
  38. return bounds;
  39. }
  40. SkPoint chopped[7];
  41. SkChopCubicAt(P, chopped, .5f);
  42. SkRect bounds = calc_tight_cubic_bounds(chopped, depth - 1);
  43. bounds.join(calc_tight_cubic_bounds(chopped+3, depth - 1));
  44. return bounds;
  45. }
  46. // This is a compilation of cubics that have given strokers grief. Feel free to add more.
  47. class TrickyCubicStrokesGM : public skiagm::GM {
  48. public:
  49. TrickyCubicStrokesGM() {}
  50. protected:
  51. SkString onShortName() override {
  52. return SkString("trickycubicstrokes");
  53. }
  54. SkISize onISize() override {
  55. return SkISize::Make(3*kCellSize, 3*kCellSize);
  56. }
  57. void onOnceBeforeDraw() override {
  58. fStrokePaint.setAntiAlias(true);
  59. fStrokePaint.setStrokeWidth(kStrokeWidth);
  60. fStrokePaint.setColor(SK_ColorGREEN);
  61. fStrokePaint.setStyle(SkPaint::kStroke_Style);
  62. }
  63. void onDraw(SkCanvas* canvas) override {
  64. canvas->clear(SK_ColorBLACK);
  65. for (size_t i = 0; i < SK_ARRAY_COUNT(kCubics); ++i) {
  66. this->drawStroke(canvas, kCubics[i],
  67. SkRect::MakeXYWH((i%3) * kCellSize, (i/3) * kCellSize, kCellSize,
  68. kCellSize));
  69. }
  70. }
  71. void drawStroke(SkCanvas* canvas, const SkPoint P[4], const SkRect& location) {
  72. SkRect strokeBounds = calc_tight_cubic_bounds(P);
  73. strokeBounds.outset(kStrokeWidth, kStrokeWidth);
  74. SkMatrix matrix;
  75. matrix.setRectToRect(strokeBounds, location, SkMatrix::kCenter_ScaleToFit);
  76. SkPath path;
  77. path.moveTo(P[0]);
  78. path.cubicTo(P[1], P[2], P[3]);
  79. SkAutoCanvasRestore acr(canvas, true);
  80. canvas->concat(matrix);
  81. canvas->drawPath(path, fStrokePaint);
  82. }
  83. private:
  84. SkPaint fStrokePaint;
  85. typedef GM INHERITED;
  86. };
  87. DEF_GM( return new TrickyCubicStrokesGM; )