pub struct Shape { /* private fields */ }Expand description
A shape value, not yet erased to a view.
circle and its neighbours hand back a ViewHandle, because a shape
conforms to View and that is all most callers want. Shape.fill(_:style:)
and .stroke(_:lineWidth:) are not view modifiers, though — they are
extension methods on Shape whose receiver is @in_guaranteed Self with
Self: Shape, and an AnyView satisfies neither. So reaching them needs
the value, its metadata and its Shape witness table kept together, which
is what this is.
The bytes are the shape’s own storage: empty for Circle, Rectangle and
Ellipse, which have no stored properties at all.
Implementations§
Source§impl Shape
impl Shape
Sourcepub fn circle() -> Self
pub fn circle() -> Self
Circle()
Examples found in repository?
196fn shapes() -> views::ViewHandle {
197 let swatch = |shape: views::Shape, c: Color| {
198 views::frame(&shape.fill(views::color_value_of(c)), 58.0, 44.0)
199 };
200 views::hstack_spacing(
201 &[
202 swatch(views::Shape::circle(), Color::new(0.95, 0.35, 0.30, 1.0)),
203 swatch(views::Shape::capsule(), Color::new(0.98, 0.70, 0.20, 1.0)),
204 swatch(views::Shape::rounded_rectangle(10.0, true), Color::new(0.30, 0.65, 1.0, 1.0)),
205 swatch(views::Shape::ellipse(), Color::new(0.35, 0.85, 0.55, 1.0)),
206 ],
207 10.0,
208 )
209}Sourcepub fn ellipse() -> Self
pub fn ellipse() -> Self
Ellipse()
Examples found in repository?
196fn shapes() -> views::ViewHandle {
197 let swatch = |shape: views::Shape, c: Color| {
198 views::frame(&shape.fill(views::color_value_of(c)), 58.0, 44.0)
199 };
200 views::hstack_spacing(
201 &[
202 swatch(views::Shape::circle(), Color::new(0.95, 0.35, 0.30, 1.0)),
203 swatch(views::Shape::capsule(), Color::new(0.98, 0.70, 0.20, 1.0)),
204 swatch(views::Shape::rounded_rectangle(10.0, true), Color::new(0.30, 0.65, 1.0, 1.0)),
205 swatch(views::Shape::ellipse(), Color::new(0.35, 0.85, 0.55, 1.0)),
206 ],
207 10.0,
208 )
209}Sourcepub fn capsule() -> Self
pub fn capsule() -> Self
Capsule() — one byte of RoundedCornerStyle.
Case 1, .continuous, which is what Capsule() with no argument
means. This said case 0 and called it .circular until a listing needed
a capsule’s corner style to match; nothing had compared one before, and
Self::rounded_rectangle next door had the numbering right all along.
Examples found in repository?
196fn shapes() -> views::ViewHandle {
197 let swatch = |shape: views::Shape, c: Color| {
198 views::frame(&shape.fill(views::color_value_of(c)), 58.0, 44.0)
199 };
200 views::hstack_spacing(
201 &[
202 swatch(views::Shape::circle(), Color::new(0.95, 0.35, 0.30, 1.0)),
203 swatch(views::Shape::capsule(), Color::new(0.98, 0.70, 0.20, 1.0)),
204 swatch(views::Shape::rounded_rectangle(10.0, true), Color::new(0.30, 0.65, 1.0, 1.0)),
205 swatch(views::Shape::ellipse(), Color::new(0.35, 0.85, 0.55, 1.0)),
206 ],
207 10.0,
208 )
209}Sourcepub fn rounded_rectangle(radius: f64, continuous: bool) -> Self
pub fn rounded_rectangle(radius: f64, continuous: bool) -> Self
RoundedRectangle(cornerRadius:style:) — a CGSize then the style.
style is RoundedCornerStyle: .circular is case 0 and
.continuous is case 1. The one-argument spelling in Swift source does
not mean circular — the declared default is .continuous, and the two
differ by about two hundred pixels around the corners of a 200x50 box.
Examples found in repository?
196fn shapes() -> views::ViewHandle {
197 let swatch = |shape: views::Shape, c: Color| {
198 views::frame(&shape.fill(views::color_value_of(c)), 58.0, 44.0)
199 };
200 views::hstack_spacing(
201 &[
202 swatch(views::Shape::circle(), Color::new(0.95, 0.35, 0.30, 1.0)),
203 swatch(views::Shape::capsule(), Color::new(0.98, 0.70, 0.20, 1.0)),
204 swatch(views::Shape::rounded_rectangle(10.0, true), Color::new(0.30, 0.65, 1.0, 1.0)),
205 swatch(views::Shape::ellipse(), Color::new(0.35, 0.85, 0.55, 1.0)),
206 ],
207 10.0,
208 )
209}
210
211fn controls() -> views::ViewHandle {
212 views::vstack_spacing(
213 &[
214 // Two toggles, both starting `false`: one bound to Rust-owned
215 // state, one a constant. If they ever disagree on screen, the
216 // binding's getter is at fault rather than the control.
217 views::toggle_bound("Bound to Rust state", switch_state()),
218 views::toggle("Constant false", false),
219 views::hstack_spacing(
220 &[
221 label_text(&format!("{:.2}", slider_state().get()), 14.0, None, 0.9),
222 views::slider_bound(slider_state(), 0.0, 1.0),
223 ],
224 10.0,
225 ),
226 views::stepper_bound(
227 &format!("Stepper: {:.0}", stepper_state().get()),
228 stepper_state(),
229 0.0,
230 10.0,
231 1.0,
232 ),
233 // Reads the stepper's Rust value. A `ProgressView` takes a plain
234 // number rather than a binding, so it can only ever show what it
235 // was built with — which is fine now that every write rebuilds the
236 // body from current state.
237 views::progress(stepper_state().get(), 10.0),
238 views::hstack_spacing(
239 &[
240 views::button_style(
241 &views::button("Bordered", on_tap),
242 views::ButtonStyle::Bordered,
243 ),
244 views::button_style(
245 &views::button("Glass", on_tap),
246 views::ButtonStyle::Glass,
247 ),
248 ],
249 12.0,
250 ),
251 views::textfield("A text field", ""),
252 ],
253 12.0,
254 )
255}
256
257fn symbols() -> views::ViewHandle {
258 let icon = |name: &str, c: Color| {
259 views::foreground_style_color(
260 &views::font_system(&views::system_image(name), 24.0, None, None),
261 c.r, c.g, c.b, c.a,
262 )
263 };
264 views::hstack_spacing(
265 &[
266 icon("star.fill", Color::new(1.0, 0.8, 0.2, 1.0)),
267 icon("heart.fill", Color::new(1.0, 0.35, 0.45, 1.0)),
268 icon("bolt.fill", Color::new(0.55, 0.8, 1.0, 1.0)),
269 icon("cloud.sun.fill", Color::new(0.8, 0.85, 1.0, 1.0)),
270 icon("checkmark.seal.fill", Color::new(0.4, 0.9, 0.6, 1.0)),
271 ],
272 16.0,
273 )
274}
275
276fn effects() -> views::ViewHandle {
277 let tile = |c: Color| views::frame(&views::color(c.r, c.g, c.b, c.a), 48.0, 40.0);
278 views::hstack_spacing(
279 &[
280 views::blur(&tile(Color::new(0.95, 0.4, 0.3, 1.0)), 4.0),
281 views::shadow(
282 &tile(Color::new(0.3, 0.7, 1.0, 1.0)),
283 Color::new(0.0, 0.0, 0.0, 0.8),
284 8.0,
285 0.0,
286 4.0,
287 ),
288 views::opacity(&tile(Color::new(0.5, 0.9, 0.5, 1.0)), 0.35),
289 views::corner_radius(&tile(Color::new(0.9, 0.7, 0.2, 1.0)), 12.0),
290 views::border(&tile(Color::new(0.0, 0.0, 0.0, 0.0)), 1.0, 1.0, 1.0, 2.0),
291 ],
292 10.0,
293 )
294}
295
296fn layout() -> views::ViewHandle {
297 let chip = |s: &str, c: Color| {
298 views::corner_radius(
299 &views::background(&views::padding(&label_text(s, 13.0, None, 1.0), 8.0), c.r, c.g, c.b, c.a),
300 8.0,
301 )
302 };
303 views::vstack_spacing(
304 &[
305 views::hstack_spacing(
306 &[
307 chip("HStack", Color::new(0.35, 0.35, 0.8, 0.8)),
308 views::spacer(),
309 chip("Spacer", Color::new(0.8, 0.35, 0.5, 0.8)),
310 ],
311 8.0,
312 ),
313 views::divider(),
314 views::zstack(&[
315 views::frame(
316 &views::Shape::rounded_rectangle(8.0, true)
317 .fill(views::color_value_of(Color::new(0.2, 0.5, 0.9, 0.55))),
318 120.0,
319 34.0,
320 ),
321 label_text("ZStack", 13.0, Some(views::Weight::Semibold), 1.0),
322 ]),
323 ],
324 10.0,
325 )
326}pub fn view(&self) -> ViewHandle
Sourcepub fn path() -> PathBuilder
pub fn path() -> PathBuilder
A Path, built by the four mutating methods below.
Path is 33 bytes — a reference plus a discriminator — so it is neither
one word nor a neat multiple of one, and every method takes it as
inout through x20 while the points travel in d0 onwards.
Sourcepub fn inset(&self, amount: f64) -> Self
pub fn inset(&self, amount: f64) -> Self
.inset(by:) — the shape drawn inside its own bounds.
inset(by:) is an InsettableShape requirement, so it is exported
once per conforming type rather than once on the protocol: there is a
Circle.inset, a Rectangle.inset and so on, and no
InsettableShape.inset at all. The result is some InsettableShape,
whose first conformance is InsettableShape — so the Shape witness
comes from the concrete metadata, as with stroke(lineWidth:).
Sourcepub fn offset(&self, x: f64, y: f64) -> Self
pub fn offset(&self, x: f64, y: f64) -> Self
.offset(x:y:) — an OffsetShape around this one.
A concrete wrapper, not an opaque return, so there is no substitution list to build: the result’s size comes from its own metadata and the call writes it through x8.
Sourcepub fn rotation(&self, degrees: f64) -> Self
pub fn rotation(&self, degrees: f64) -> Self
.rotation(_:anchor:) — a RotatedShape around this one.
Angle stores radians, and .center is UnitPoint(0.5, 0.5).
Sourcepub unsafe fn fill_style(
&self,
style: &[u8],
meta: *const c_void,
wt: *const c_void,
) -> ViewHandle
pub unsafe fn fill_style( &self, style: &[u8], meta: *const c_void, wt: *const c_void, ) -> ViewHandle
.fill(_:style:) with any ShapeStyle — its value, metadata and
witness table.
§Safety
style must hold an initialised value of the type meta describes, and
wt must be that type’s ShapeStyle conformance.
Sourcepub unsafe fn stroke_style(
&self,
style: &[u8],
meta: *const c_void,
wt: *const c_void,
line_width: f64,
) -> ViewHandle
pub unsafe fn stroke_style( &self, style: &[u8], meta: *const c_void, wt: *const c_void, line_width: f64, ) -> ViewHandle
.stroke(_:lineWidth:) with any ShapeStyle.
§Safety
style must hold an initialised value of the type meta describes, and
wt must be that type’s ShapeStyle conformance.
Sourcepub fn fill(&self, color: u64) -> ViewHandle
pub fn fill(&self, color: u64) -> ViewHandle
.fill(_:style:) with a Color.
Examples found in repository?
196fn shapes() -> views::ViewHandle {
197 let swatch = |shape: views::Shape, c: Color| {
198 views::frame(&shape.fill(views::color_value_of(c)), 58.0, 44.0)
199 };
200 views::hstack_spacing(
201 &[
202 swatch(views::Shape::circle(), Color::new(0.95, 0.35, 0.30, 1.0)),
203 swatch(views::Shape::capsule(), Color::new(0.98, 0.70, 0.20, 1.0)),
204 swatch(views::Shape::rounded_rectangle(10.0, true), Color::new(0.30, 0.65, 1.0, 1.0)),
205 swatch(views::Shape::ellipse(), Color::new(0.35, 0.85, 0.55, 1.0)),
206 ],
207 10.0,
208 )
209}
210
211fn controls() -> views::ViewHandle {
212 views::vstack_spacing(
213 &[
214 // Two toggles, both starting `false`: one bound to Rust-owned
215 // state, one a constant. If they ever disagree on screen, the
216 // binding's getter is at fault rather than the control.
217 views::toggle_bound("Bound to Rust state", switch_state()),
218 views::toggle("Constant false", false),
219 views::hstack_spacing(
220 &[
221 label_text(&format!("{:.2}", slider_state().get()), 14.0, None, 0.9),
222 views::slider_bound(slider_state(), 0.0, 1.0),
223 ],
224 10.0,
225 ),
226 views::stepper_bound(
227 &format!("Stepper: {:.0}", stepper_state().get()),
228 stepper_state(),
229 0.0,
230 10.0,
231 1.0,
232 ),
233 // Reads the stepper's Rust value. A `ProgressView` takes a plain
234 // number rather than a binding, so it can only ever show what it
235 // was built with — which is fine now that every write rebuilds the
236 // body from current state.
237 views::progress(stepper_state().get(), 10.0),
238 views::hstack_spacing(
239 &[
240 views::button_style(
241 &views::button("Bordered", on_tap),
242 views::ButtonStyle::Bordered,
243 ),
244 views::button_style(
245 &views::button("Glass", on_tap),
246 views::ButtonStyle::Glass,
247 ),
248 ],
249 12.0,
250 ),
251 views::textfield("A text field", ""),
252 ],
253 12.0,
254 )
255}
256
257fn symbols() -> views::ViewHandle {
258 let icon = |name: &str, c: Color| {
259 views::foreground_style_color(
260 &views::font_system(&views::system_image(name), 24.0, None, None),
261 c.r, c.g, c.b, c.a,
262 )
263 };
264 views::hstack_spacing(
265 &[
266 icon("star.fill", Color::new(1.0, 0.8, 0.2, 1.0)),
267 icon("heart.fill", Color::new(1.0, 0.35, 0.45, 1.0)),
268 icon("bolt.fill", Color::new(0.55, 0.8, 1.0, 1.0)),
269 icon("cloud.sun.fill", Color::new(0.8, 0.85, 1.0, 1.0)),
270 icon("checkmark.seal.fill", Color::new(0.4, 0.9, 0.6, 1.0)),
271 ],
272 16.0,
273 )
274}
275
276fn effects() -> views::ViewHandle {
277 let tile = |c: Color| views::frame(&views::color(c.r, c.g, c.b, c.a), 48.0, 40.0);
278 views::hstack_spacing(
279 &[
280 views::blur(&tile(Color::new(0.95, 0.4, 0.3, 1.0)), 4.0),
281 views::shadow(
282 &tile(Color::new(0.3, 0.7, 1.0, 1.0)),
283 Color::new(0.0, 0.0, 0.0, 0.8),
284 8.0,
285 0.0,
286 4.0,
287 ),
288 views::opacity(&tile(Color::new(0.5, 0.9, 0.5, 1.0)), 0.35),
289 views::corner_radius(&tile(Color::new(0.9, 0.7, 0.2, 1.0)), 12.0),
290 views::border(&tile(Color::new(0.0, 0.0, 0.0, 0.0)), 1.0, 1.0, 1.0, 2.0),
291 ],
292 10.0,
293 )
294}
295
296fn layout() -> views::ViewHandle {
297 let chip = |s: &str, c: Color| {
298 views::corner_radius(
299 &views::background(&views::padding(&label_text(s, 13.0, None, 1.0), 8.0), c.r, c.g, c.b, c.a),
300 8.0,
301 )
302 };
303 views::vstack_spacing(
304 &[
305 views::hstack_spacing(
306 &[
307 chip("HStack", Color::new(0.35, 0.35, 0.8, 0.8)),
308 views::spacer(),
309 chip("Spacer", Color::new(0.8, 0.35, 0.5, 0.8)),
310 ],
311 8.0,
312 ),
313 views::divider(),
314 views::zstack(&[
315 views::frame(
316 &views::Shape::rounded_rectangle(8.0, true)
317 .fill(views::color_value_of(Color::new(0.2, 0.5, 0.9, 0.55))),
318 120.0,
319 34.0,
320 ),
321 label_text("ZStack", 13.0, Some(views::Weight::Semibold), 1.0),
322 ]),
323 ],
324 10.0,
325 )
326}Sourcepub fn stroked(&self, line_width: f64) -> Self
pub fn stroked(&self, line_width: f64) -> Self
.stroke(lineWidth:), kept as a Shape rather than erased to a view.
What overlay(_:in:) wants: its in: argument is a Shape, and a
stroked shape still is one.
Sourcepub fn parts(&self) -> (Vec<u8>, *const c_void, *const c_void)
pub fn parts(&self) -> (Vec<u8>, *const c_void, *const c_void)
The value, metadata and Shape witness, for a call that takes a shape.
Sourcepub fn stroke_default(&self, line_width: f64) -> ViewHandle
pub fn stroke_default(&self, line_width: f64) -> ViewHandle
.stroke(lineWidth:) — no style, so it strokes with the foreground.
One generic parameter rather than two, so the substitution list is just
Self and its Shape witness, and the line width is the only formal
argument.
Sourcepub fn stroke(&self, color: u64, line_width: f64) -> ViewHandle
pub fn stroke(&self, color: u64, line_width: f64) -> ViewHandle
.stroke(_:lineWidth:) with a Color.
Source§impl Shape
impl Shape
Sourcepub fn trim(&self, from: f64, to: f64) -> Self
pub fn trim(&self, from: f64, to: f64) -> Self
.trim(from:to:) — keep a fraction of the shape’s path.
How a progress ring is drawn: a stroked circle trimmed to the fraction complete. Without it a “ring showing 70%” is a full circle.
.trim is @inlinable, so SwiftUI exports no function for it — but
_TrimmedShape<S> is just the shape and two CGFloats, its descriptor
is exported, and the field offsets come from the metadata rather than
being assumed.