Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkCornerPathEffect.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2006 The Android Open Source Project
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
9
11#include "include/core/SkPath.h"
21
22class SkMatrix;
23class SkStrokeRec;
24struct SkRect;
25
26static bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius,
27 SkPoint* step) {
29
30 *step = b - a;
31 if (dist <= radius * 2) {
33 return false;
34 } else {
35 *step *= radius / dist;
36 return true;
37 }
38}
39
41public:
42 explicit SkCornerPathEffectImpl(SkScalar radius) : fRadius(radius) {
43 SkASSERT(radius > 0);
44 }
45
46 bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*,
47 const SkMatrix&) const override {
48 if (fRadius <= 0) {
49 return false;
50 }
51
52 SkPath::Iter iter(src, false);
53 SkPath::Verb verb, prevVerb = SkPath::kDone_Verb;
54 SkPoint pts[4];
55
56 bool closed;
57 SkPoint moveTo, lastCorner;
58 SkVector firstStep, step;
59 bool prevIsValid = true;
60
61 // to avoid warnings
62 step.set(0, 0);
63 moveTo.set(0, 0);
64 firstStep.set(0, 0);
65 lastCorner.set(0, 0);
66
67 for (;;) {
68 switch (verb = iter.next(pts)) {
70 // close out the previous (open) contour
71 if (SkPath::kLine_Verb == prevVerb) {
72 dst->lineTo(lastCorner);
73 }
74 closed = iter.isClosedContour();
75 if (closed) {
76 moveTo = pts[0];
77 prevIsValid = false;
78 } else {
79 dst->moveTo(pts[0]);
80 prevIsValid = true;
81 }
82 break;
83 case SkPath::kLine_Verb: {
84 bool drawSegment = ComputeStep(pts[0], pts[1], fRadius, &step);
85 // prev corner
86 if (!prevIsValid) {
87 dst->moveTo(moveTo + step);
88 prevIsValid = true;
89 } else {
90 dst->quadTo(pts[0].fX, pts[0].fY, pts[0].fX + step.fX,
91 pts[0].fY + step.fY);
92 }
93 if (drawSegment) {
94 dst->lineTo(pts[1].fX - step.fX, pts[1].fY - step.fY);
95 }
96 lastCorner = pts[1];
97 prevIsValid = true;
98 break;
99 }
101 // TBD - just replicate the curve for now
102 if (!prevIsValid) {
103 dst->moveTo(pts[0]);
104 prevIsValid = true;
105 }
106 dst->quadTo(pts[1], pts[2]);
107 lastCorner = pts[2];
108 firstStep.set(0, 0);
109 break;
111 // TBD - just replicate the curve for now
112 if (!prevIsValid) {
113 dst->moveTo(pts[0]);
114 prevIsValid = true;
115 }
116 dst->conicTo(pts[1], pts[2], iter.conicWeight());
117 lastCorner = pts[2];
118 firstStep.set(0, 0);
119 break;
121 if (!prevIsValid) {
122 dst->moveTo(pts[0]);
123 prevIsValid = true;
124 }
125 // TBD - just replicate the curve for now
126 dst->cubicTo(pts[1], pts[2], pts[3]);
127 lastCorner = pts[3];
128 firstStep.set(0, 0);
129 break;
131 if (firstStep.fX || firstStep.fY) {
132 dst->quadTo(lastCorner.fX, lastCorner.fY,
133 lastCorner.fX + firstStep.fX,
134 lastCorner.fY + firstStep.fY);
135 }
136 dst->close();
137 prevIsValid = false;
138 break;
140 if (prevIsValid) {
141 dst->lineTo(lastCorner);
142 }
143 return true;
144 default:
145 SkDEBUGFAIL("default should not be reached");
146 return false;
147 }
148
149 if (SkPath::kMove_Verb == prevVerb) {
150 firstStep = step;
151 }
152 prevVerb = verb;
153 }
154 }
155
156 bool computeFastBounds(SkRect*) const override {
157 // Rounding sharp corners within a path produces a new path that is still contained within
158 // the original's bounds, so leave 'bounds' unmodified.
159 return true;
160 }
161
165
166 void flatten(SkWriteBuffer& buffer) const override {
167 buffer.writeScalar(fRadius);
168 }
169
170 Factory getFactory() const override { return CreateProc; }
171 const char* getTypeName() const override { return "SkCornerPathEffect"; }
172
173private:
174 const SkScalar fRadius;
175
176 using INHERITED = SkPathEffectBase;
177};
178
179//////////////////////////////////////////////////////////////////////////////////////////////////
180
182 return SkIsFinite(radius) && (radius > 0) ?
183 sk_sp<SkPathEffect>(new SkCornerPathEffectImpl(radius)) : nullptr;
184}
185
static int step(int x, SkScalar min, SkScalar max)
Definition BlurTest.cpp:215
#define SkDEBUGFAIL(message)
Definition SkAssert.h:118
#define SkASSERT(cond)
Definition SkAssert.h:116
static bool ComputeStep(const SkPoint &a, const SkPoint &b, SkScalar radius, SkPoint *step)
static bool SkIsFinite(T x, Pack... values)
#define SK_ScalarHalf
Definition SkScalar.h:19
SkCornerPathEffectImpl(SkScalar radius)
Factory getFactory() const override
const char * getTypeName() const override
bool computeFastBounds(SkRect *) const override
static sk_sp< SkFlattenable > CreateProc(SkReadBuffer &buffer)
bool onFilterPath(SkPath *dst, const SkPath &src, SkStrokeRec *, const SkRect *, const SkMatrix &) const override
void flatten(SkWriteBuffer &buffer) const override
static void RegisterFlattenables()
static sk_sp< SkPathEffect > Make(SkScalar radius)
sk_sp< SkFlattenable >(* Factory)(SkReadBuffer &)
static void Register(const char name[], Factory)
bool isClosedContour() const
Definition SkPath.cpp:1787
Verb next(SkPoint pts[4])
Definition SkPath.cpp:1837
SkScalar conicWeight() const
Definition SkPath.h:1527
@ kClose_Verb
Definition SkPath.h:1463
@ kMove_Verb
Definition SkPath.h:1458
@ kConic_Verb
Definition SkPath.h:1461
@ kDone_Verb
Definition SkPath.h:1464
@ kCubic_Verb
Definition SkPath.h:1462
@ kQuad_Verb
Definition SkPath.h:1460
@ kLine_Verb
Definition SkPath.h:1459
float SkScalar
Definition extension.cpp:12
static bool b
struct MyStruct a[10]
static const uint8_t buffer[]
float fX
x-axis value
void set(float x, float y)
static float Distance(const SkPoint &a, const SkPoint &b)
float fY
y-axis value