• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Google LLC.
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 "src/gpu/tessellate/Tessellation.h"
9 
10 #include "include/core/SkPath.h"
11 #include "src/core/SkGeometry.h"
12 #include "src/core/SkPathPriv.h"
13 #include "src/gpu/BufferWriter.h"
14 #include "src/gpu/tessellate/CullTest.h"
15 #include "src/gpu/tessellate/MiddleOutPolygonTriangulator.h"
16 #include "src/gpu/tessellate/WangsFormula.h"
17 
18 namespace skgpu {
19 
20 namespace {
21 
22 // Writes a new path, chopping as necessary so no verbs require more segments than
23 // kMaxTessellationSegmentsPerCurve. Curves completely outside the viewport are flattened into
24 // lines.
25 class PathChopper {
26 public:
PathChopper(const SkMatrix & matrix,const SkRect & viewport)27     PathChopper(const SkMatrix& matrix, const SkRect& viewport)
28             : fCullTest(viewport, matrix)
29             , fVectorXform(matrix) {
30         fPath.setIsVolatile(true);
31     }
32 
path() const33     SkPath path() const { return fPath; }
34 
moveTo(SkPoint p)35     void moveTo(SkPoint p) { fPath.moveTo(p); }
lineTo(SkPoint p1)36     void lineTo(SkPoint p1) { fPath.lineTo(p1); }
close()37     void close() { fPath.close(); }
38 
quadTo(const SkPoint p[3])39     void quadTo(const SkPoint p[3]) {
40         if (!fCullTest.areVisible3(p)) {
41             this->lineTo(p[2]);
42             return;
43         }
44         float n = wangs_formula::quadratic_pow4(kTessellationPrecision, p, fVectorXform);
45         if (n > pow4(kMaxTessellationSegmentsPerCurve)) {
46             SkPoint chops[5];
47             SkChopQuadAtHalf(p, chops);
48             this->quadTo(chops);
49             this->quadTo(chops + 2);
50             return;
51         }
52         fPath.quadTo(p[1], p[2]);
53     }
54 
conicTo(const SkPoint p[3],float w)55     void conicTo(const SkPoint p[3], float w) {
56         if (!fCullTest.areVisible3(p)) {
57             this->lineTo(p[2]);
58             return;
59         }
60         float n = wangs_formula::conic_pow2(kTessellationPrecision, p, w, fVectorXform);
61         if (n > pow2(kMaxTessellationSegmentsPerCurve)) {
62             SkConic chops[2];
63             if (!SkConic(p,w).chopAt(.5, chops)) {
64                 this->lineTo(p[2]);
65                 return;
66             }
67             this->conicTo(chops[0].fPts, chops[0].fW);
68             this->conicTo(chops[1].fPts, chops[1].fW);
69             return;
70         }
71         fPath.conicTo(p[1], p[2], w);
72     }
73 
cubicTo(const SkPoint p[4])74     void cubicTo(const SkPoint p[4]) {
75         if (!fCullTest.areVisible4(p)) {
76             this->lineTo(p[3]);
77             return;
78         }
79         float n = wangs_formula::cubic_pow4(kTessellationPrecision, p, fVectorXform);
80         if (n > pow4(kMaxTessellationSegmentsPerCurve)) {
81             SkPoint chops[7];
82             SkChopCubicAtHalf(p, chops);
83             this->cubicTo(chops);
84             this->cubicTo(chops + 3);
85             return;
86         }
87         fPath.cubicTo(p[1], p[2], p[3]);
88     }
89 
90 private:
91     const CullTest fCullTest;
92     const wangs_formula::VectorXform fVectorXform;
93     SkPath fPath;
94 };
95 
96 }  // namespace
97 
PreChopPathCurves(const SkPath & path,const SkMatrix & matrix,const SkRect & viewport)98 SkPath PreChopPathCurves(const SkPath& path, const SkMatrix& matrix, const SkRect& viewport) {
99     PathChopper chopper(matrix, viewport);
100     for (auto [verb, p, w] : SkPathPriv::Iterate(path)) {
101         switch (verb) {
102             case SkPathVerb::kMove:
103                 chopper.moveTo(p[0]);
104                 break;
105             case SkPathVerb::kLine:
106                 chopper.lineTo(p[1]);
107                 break;
108             case SkPathVerb::kQuad:
109                 chopper.quadTo(p);
110                 break;
111             case SkPathVerb::kConic:
112                 chopper.conicTo(p, *w);
113                 break;
114             case SkPathVerb::kCubic:
115                 chopper.cubicTo(p);
116                 break;
117             case SkPathVerb::kClose:
118                 chopper.close();
119                 break;
120         }
121     }
122     return chopper.path();
123 }
124 
125 }  // namespace skgpu
126