Skip to main content

Shape

Struct Shape 

Source
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

Source

pub fn circle() -> Self

Circle()

Examples found in repository?
examples/ios_app.rs (line 202)
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}
Source

pub fn rectangle() -> Self

Rectangle()

Source

pub fn ellipse() -> Self

Ellipse()

Examples found in repository?
examples/ios_app.rs (line 205)
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}
Source

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?
examples/ios_app.rs (line 203)
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}
Source

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?
examples/ios_app.rs (line 204)
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}
Source

pub fn view(&self) -> ViewHandle

Source

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.

Source

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:).

Source

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.

Source

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).

Source

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.

Source

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.

Source

pub fn fill(&self, color: u64) -> ViewHandle

.fill(_:style:) with a Color.

Examples found in repository?
examples/ios_app.rs (line 198)
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}
Source

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.

Source

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.

Source

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.

Source

pub fn stroke(&self, color: u64, line_width: f64) -> ViewHandle

.stroke(_:lineWidth:) with a Color.

Source§

impl Shape

Source

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.

Auto Trait Implementations§

§

impl !Send for Shape

§

impl !Sync for Shape

§

impl Freeze for Shape

§

impl RefUnwindSafe for Shape

§

impl Unpin for Shape

§

impl UnsafeUnpin for Shape

§

impl UnwindSafe for Shape

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.