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