Skip to main content

ColumnFlowLayout

Struct ColumnFlowLayout 

Source
pub struct ColumnFlowLayout;
Expand description

Flow text through an ordered set of rectangular columns, avoiding obstacles.

Implementations§

Source§

impl ColumnFlowLayout

Source

pub fn layout_into_columns( prepared: &PreparedTextWithSegments, columns: &[RectObstacle], rectangles: &[RectObstacle], circles: &[CircleObstacle], line_height: f64, min_slot_width: f64, ) -> Result<Vec<PositionedLine>, LayoutError>

Text that does not fit the supplied columns is left unmaterialized. Fully blocked rows advance vertically without consuming source text. Exactly one (the widest) available horizontal slot is used on each row.

Examples found in repository?
examples/editorial.rs (lines 61-68)
12fn main() -> Result<(), Box<dyn Error>> {
13    let engine = PretextLayout::new(Rc::new(DelegateTextMeasurerFactory::new(
14        |text: &str, _: &str| text.chars().count() as f64 * 8.0,
15    )));
16    let prepared = engine.prepare_with_segments(
17        "Prepare this paragraph once. Reflow it through columns as the exclusion \
18         shape moves. Width changes reuse the prepared measurements, and only \
19         the visible line ranges need their text materialized. This is useful \
20         for editorial pages, canvas labels and virtualized cards.",
21        "16px Monospace",
22        PrepareOptions::default(),
23    )?;
24    let columns = [
25        RectObstacle {
26            x: 0.0,
27            y: 0.0,
28            width: 240.0,
29            height: 220.0,
30        },
31        RectObstacle {
32            x: 264.0,
33            y: 0.0,
34            width: 240.0,
35            height: 220.0,
36        },
37    ];
38    let rectangles = [RectObstacle {
39        x: 0.0,
40        y: 0.0,
41        width: 80.0,
42        height: 40.0,
43    }];
44
45    println!("Illustrative monospace geometry (8 units per Unicode scalar)");
46    println!("Prepared segments: {}", prepared.segments().len());
47    for width in [120.0, 180.0, 240.0] {
48        let metrics = PreparedTextMetrics::collect_wrap_metrics(&prepared, width, 20.0);
49        println!(
50            "Width {width:>3.0}: {} lines, height {:.0}, widest {:.0}",
51            metrics.line_count, metrics.height, metrics.max_line_width,
52        );
53    }
54
55    for circle_y in [70.0, 150.0] {
56        let circles = [CircleObstacle {
57            x: 150.0,
58            y: circle_y,
59            radius: 45.0,
60        }];
61        let lines = ColumnFlowLayout::layout_into_columns(
62            &prepared,
63            &columns,
64            &rectangles,
65            &circles,
66            20.0,
67            48.0,
68        )?;
69        println!(
70            "\nCircle centered at (150, {circle_y:.0}); {} positioned lines:",
71            lines.len()
72        );
73        for line in lines {
74            println!(
75                "  x={:>3.0} y={:>3.0} w={:>3.0}  {}",
76                line.x, line.y, line.width, line.text
77            );
78        }
79    }
80
81    let inline = engine.prepare_rich_inline(&[
82        RichInlineItem::new("Assigned to ", "16px Monospace"),
83        RichInlineItem::new("@maya", "16px Monospace")
84            .with_break_mode(RichInlineBreakMode::Never)
85            .with_extra_width(16.0),
86        RichInlineItem::new(" for the next editorial review.", "16px Monospace"),
87    ])?;
88    println!("\nRich inline flow with an atomic badge:");
89    PretextLayout::walk_rich_inline_line_ranges(&inline, 160.0, |range| {
90        let line = PretextLayout::materialize_rich_inline_line_range(&inline, &range);
91        print!("  width={:>3.0}", line.width);
92        for fragment in line.fragments {
93            print!(
94                "  [item {} gap {:.0}: {}]",
95                fragment.item_index, fragment.gap_before, fragment.text
96            );
97        }
98        println!();
99    });
100    Ok(())
101}

Auto Trait Implementations§

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> ErasedDestructor for T
where T: 'static,

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.