Skip to content

Commit e3d4357

Browse files
chinmaygardednfield
authored andcommitted
Support non-uniform rounding radii.
1 parent cb54794 commit e3d4357

File tree

4 files changed

+110
-75
lines changed

4 files changed

+110
-75
lines changed

impeller/aiks/aiks_unittests.cc

+21
Original file line numberDiff line numberDiff line change
@@ -224,5 +224,26 @@ TEST_F(AiksTest,
224224
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
225225
}
226226

227+
TEST_F(AiksTest, CanRenderRoundedRectWithNonUniformRadii) {
228+
Canvas canvas;
229+
230+
Paint paint;
231+
paint.color = Color::Red();
232+
233+
PathBuilder::RoundingRadii radii;
234+
radii.top_left = {50, 25};
235+
radii.top_right = {25, 50};
236+
radii.bottom_right = {50, 25};
237+
radii.bottom_left = {25, 50};
238+
239+
auto path = PathBuilder{}
240+
.AddRoundedRect(Rect{100, 100, 500, 500}, radii)
241+
.CreatePath();
242+
243+
canvas.DrawPath(path, paint);
244+
245+
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
246+
}
247+
227248
} // namespace testing
228249
} // namespace impeller

impeller/geometry/path_builder.cc

+61-56
Original file line numberDiff line numberDiff line change
@@ -163,92 +163,97 @@ PathBuilder& PathBuilder::AddCircle(const Point& c, Scalar r) {
163163
}
164164

165165
PathBuilder& PathBuilder::AddRoundedRect(Rect rect, Scalar radius) {
166-
return radius == 0.0 ? AddRect(rect)
166+
return radius <= 0.0 ? AddRect(rect)
167167
: AddRoundedRect(rect, {radius, radius, radius, radius});
168168
}
169169

170170
PathBuilder& PathBuilder::AddRoundedRect(Rect rect, RoundingRadii radii) {
171-
current_ = rect.origin + Point{radii.topLeft, 0.0};
171+
if (radii.AreAllZero()) {
172+
return AddRect(rect);
173+
}
174+
175+
current_ = rect.origin + Point{radii.top_left.x, 0.0};
172176

173-
const Scalar magic_top_right = kArcApproximationMagic * radii.topRight;
174-
const Scalar magic_bottom_right = kArcApproximationMagic * radii.bottomRight;
175-
const Scalar magic_bottom_left = kArcApproximationMagic * radii.bottomLeft;
176-
const Scalar magic_top_left = kArcApproximationMagic * radii.topLeft;
177+
const auto magic_top_right = radii.top_right * kArcApproximationMagic;
178+
const auto magic_bottom_right = radii.bottom_right * kArcApproximationMagic;
179+
const auto magic_bottom_left = radii.bottom_left * kArcApproximationMagic;
180+
const auto magic_top_left = radii.top_left * kArcApproximationMagic;
177181

178182
//----------------------------------------------------------------------------
179-
/// Top line.
180-
///
183+
// Top line.
184+
//
181185
prototype_.AddLinearComponent(
182-
{rect.origin.x + radii.topLeft, rect.origin.y},
183-
{rect.origin.x + rect.size.width - radii.topRight, rect.origin.y});
186+
{rect.origin.x + radii.top_left.x, rect.origin.y},
187+
{rect.origin.x + rect.size.width - radii.top_right.x, rect.origin.y});
184188

185189
//----------------------------------------------------------------------------
186-
/// Top right arc.
187-
///
190+
// Top right arc.
191+
//
188192
prototype_.AddCubicComponent(
189-
{rect.origin.x + rect.size.width - radii.topRight, rect.origin.y},
190-
{rect.origin.x + rect.size.width - radii.topRight + magic_top_right,
193+
{rect.origin.x + rect.size.width - radii.top_right.x, rect.origin.y},
194+
{rect.origin.x + rect.size.width - radii.top_right.x + magic_top_right.x,
191195
rect.origin.y},
192196
{rect.origin.x + rect.size.width,
193-
rect.origin.y + radii.topRight - magic_top_right},
194-
{rect.origin.x + rect.size.width, rect.origin.y + radii.topRight});
197+
rect.origin.y + radii.top_right.y - magic_top_right.y},
198+
{rect.origin.x + rect.size.width, rect.origin.y + radii.top_right.y});
195199

196200
//----------------------------------------------------------------------------
197-
/// Right line.
198-
///
201+
// Right line.
202+
//
199203
prototype_.AddLinearComponent(
200-
{rect.origin.x + rect.size.width, rect.origin.y + radii.topRight},
204+
{rect.origin.x + rect.size.width, rect.origin.y + radii.top_right.y},
201205
{rect.origin.x + rect.size.width,
202-
rect.origin.y + rect.size.height - radii.bottomRight});
206+
rect.origin.y + rect.size.height - radii.bottom_right.y});
203207

204208
//----------------------------------------------------------------------------
205-
/// Bottom right arc.
206-
///
209+
// Bottom right arc.
210+
//
207211
prototype_.AddCubicComponent(
208212
{rect.origin.x + rect.size.width,
209-
rect.origin.y + rect.size.height - radii.bottomRight},
213+
rect.origin.y + rect.size.height - radii.bottom_right.y},
210214
{rect.origin.x + rect.size.width, rect.origin.y + rect.size.height -
211-
radii.bottomRight +
212-
magic_bottom_right},
213-
{rect.origin.x + rect.size.width - radii.bottomRight + magic_bottom_right,
215+
radii.bottom_right.y +
216+
magic_bottom_right.y},
217+
{rect.origin.x + rect.size.width - radii.bottom_right.x +
218+
magic_bottom_right.x,
214219
rect.origin.y + rect.size.height},
215-
{rect.origin.x + rect.size.width - radii.bottomRight,
220+
{rect.origin.x + rect.size.width - radii.bottom_right.x,
216221
rect.origin.y + rect.size.height});
217222

218223
//----------------------------------------------------------------------------
219-
/// Bottom line.
220-
///
224+
// Bottom line.
225+
//
221226
prototype_.AddLinearComponent(
222-
{rect.origin.x + rect.size.width - radii.bottomRight,
227+
{rect.origin.x + rect.size.width - radii.bottom_right.x,
223228
rect.origin.y + rect.size.height},
224-
{rect.origin.x + radii.bottomLeft, rect.origin.y + rect.size.height});
229+
{rect.origin.x + radii.bottom_left.x, rect.origin.y + rect.size.height});
225230

226231
//----------------------------------------------------------------------------
227-
/// Bottom left arc.
228-
///
232+
// Bottom left arc.
233+
//
229234
prototype_.AddCubicComponent(
230-
{rect.origin.x + radii.bottomLeft, rect.origin.y + rect.size.height},
231-
{rect.origin.x + radii.bottomLeft - magic_bottom_left,
235+
{rect.origin.x + radii.bottom_left.x, rect.origin.y + rect.size.height},
236+
{rect.origin.x + radii.bottom_left.x - magic_bottom_left.x,
232237
rect.origin.y + rect.size.height},
233-
{rect.origin.x,
234-
rect.origin.y + rect.size.height - radii.bottomLeft + magic_bottom_left},
235-
{rect.origin.x, rect.origin.y + rect.size.height - radii.bottomLeft});
238+
{rect.origin.x, rect.origin.y + rect.size.height - radii.bottom_left.y +
239+
magic_bottom_left.y},
240+
{rect.origin.x, rect.origin.y + rect.size.height - radii.bottom_left.y});
236241

237242
//----------------------------------------------------------------------------
238-
/// Left line.
239-
///
243+
// Left line.
244+
//
240245
prototype_.AddLinearComponent(
241-
{rect.origin.x, rect.origin.y + rect.size.height - radii.bottomLeft},
242-
{rect.origin.x, rect.origin.y + radii.topLeft});
246+
{rect.origin.x, rect.origin.y + rect.size.height - radii.bottom_left.y},
247+
{rect.origin.x, rect.origin.y + radii.top_left.y});
243248

244249
//----------------------------------------------------------------------------
245-
/// Top left arc.
246-
///
250+
// Top left arc.
251+
//
247252
prototype_.AddCubicComponent(
248-
{rect.origin.x, rect.origin.y + radii.topLeft},
249-
{rect.origin.x, rect.origin.y + radii.topLeft - magic_top_left},
250-
{rect.origin.x + radii.topLeft - magic_top_left, rect.origin.y},
251-
{rect.origin.x + radii.topLeft, rect.origin.y});
253+
{rect.origin.x, rect.origin.y + radii.top_left.y},
254+
{rect.origin.x, rect.origin.y + radii.top_left.y - magic_top_left.y},
255+
{rect.origin.x + radii.top_left.x - magic_top_left.x, rect.origin.y},
256+
{rect.origin.x + radii.top_left.x, rect.origin.y});
252257

253258
return *this;
254259
}
@@ -260,35 +265,35 @@ PathBuilder& PathBuilder::AddOval(const Rect& container) {
260265
const Point m = {kArcApproximationMagic * r.x, kArcApproximationMagic * r.y};
261266

262267
//----------------------------------------------------------------------------
263-
/// Top right arc.
264-
///
268+
// Top right arc.
269+
//
265270
prototype_.AddCubicComponent({c.x, c.y - r.y}, // p1
266271
{c.x + m.x, c.y - r.y}, // cp1
267272
{c.x + r.x, c.y - m.y}, // cp2
268273
{c.x + r.x, c.y} // p2
269274
);
270275

271276
//----------------------------------------------------------------------------
272-
/// Bottom right arc.
273-
///
277+
// Bottom right arc.
278+
//
274279
prototype_.AddCubicComponent({c.x + r.x, c.y}, // p1
275280
{c.x + r.x, c.y + m.y}, // cp1
276281
{c.x + m.x, c.y + r.y}, // cp2
277282
{c.x, c.y + r.y} // p2
278283
);
279284

280285
//----------------------------------------------------------------------------
281-
/// Bottom left arc.
282-
///
286+
// Bottom left arc.
287+
//
283288
prototype_.AddCubicComponent({c.x, c.y + r.y}, // p1
284289
{c.x - m.x, c.y + r.y}, // cp1
285290
{c.x - r.x, c.y + m.y}, // cp2
286291
{c.x - r.x, c.y} // p2
287292
);
288293

289294
//----------------------------------------------------------------------------
290-
/// Top left arc.
291-
///
295+
// Top left arc.
296+
//
292297
prototype_.AddCubicComponent({c.x - r.x, c.y}, // p1
293298
{c.x - r.x, c.y - m.y}, // cp1
294299
{c.x - m.x, c.y - r.y}, // cp2

impeller/geometry/path_builder.h

+24-17
Original file line numberDiff line numberDiff line change
@@ -48,34 +48,41 @@ class PathBuilder {
4848

4949
PathBuilder& AddRect(Rect rect);
5050

51-
PathBuilder& AddRoundedRect(Rect rect, Scalar radius);
52-
5351
PathBuilder& AddCircle(const Point& center, Scalar radius);
5452

5553
PathBuilder& AddOval(const Rect& rect);
5654

5755
PathBuilder& AddLine(const Point& p1, const Point& p2);
5856

5957
struct RoundingRadii {
60-
Scalar topLeft = 0.0;
61-
Scalar bottomLeft = 0.0;
62-
Scalar topRight = 0.0;
63-
Scalar bottomRight = 0.0;
64-
65-
RoundingRadii() {}
66-
67-
RoundingRadii(Scalar pTopLeft,
68-
Scalar pBottomLeft,
69-
Scalar pTopRight,
70-
Scalar pBottomRight)
71-
: topLeft(pTopLeft),
72-
bottomLeft(pBottomLeft),
73-
topRight(pTopRight),
74-
bottomRight(pBottomRight) {}
58+
Point top_left;
59+
Point bottom_left;
60+
Point top_right;
61+
Point bottom_right;
62+
63+
RoundingRadii() = default;
64+
65+
RoundingRadii(Scalar p_top_left,
66+
Scalar p_bottom_left,
67+
Scalar p_top_right,
68+
Scalar p_bottom_right)
69+
: top_left(p_top_left, p_top_left),
70+
bottom_left(p_bottom_left, p_bottom_left),
71+
top_right(p_top_right, p_top_right),
72+
bottom_right(p_bottom_right, p_bottom_right) {}
73+
74+
bool AreAllZero() const {
75+
return top_left.IsZero() && //
76+
bottom_left.IsZero() && //
77+
top_right.IsZero() && //
78+
bottom_right.IsZero();
79+
}
7580
};
7681

7782
PathBuilder& AddRoundedRect(Rect rect, RoundingRadii radii);
7883

84+
PathBuilder& AddRoundedRect(Rect rect, Scalar radius);
85+
7986
private:
8087
Point subpath_start_;
8188
Point current_;

impeller/geometry/point.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ struct TPoint {
5757
return {x - s.width, y - s.height};
5858
}
5959

60-
constexpr TPoint operator*(Type scale) const {
60+
constexpr TPoint operator*(Scalar scale) const {
6161
return {x * scale, y * scale};
6262
}
6363

@@ -69,7 +69,7 @@ struct TPoint {
6969
return {x * s.width, y * s.height};
7070
}
7171

72-
constexpr TPoint operator/(Type d) const { return {x / d, y / d}; }
72+
constexpr TPoint operator/(Scalar d) const { return {x / d, y / d}; }
7373

7474
constexpr TPoint operator/(const TPoint& p) const {
7575
return {x / p.x, y / p.y};
@@ -108,6 +108,8 @@ struct TPoint {
108108
}
109109
return {x / length, y / length};
110110
}
111+
112+
constexpr bool IsZero() const { return x == 0 && y == 0; }
111113
};
112114

113115
using Point = TPoint<Scalar>;

0 commit comments

Comments
 (0)