Skip to content

Conversation

@DaraJKong
Copy link

In a project I'm working on, I needed to draw text inside a Canvas widget. I initially created a FontContext and a LayoutContext inside the draw closure. I used masonry::core::render_text to render my text layout to the Vello Scene. While theoretically functionnal, my solution was extremely slow and wrong.

After realizing that both FontContext and LayoutContext are meant to be global resources created only once per application, I set out to tinker with the source code of the Canvas widget. What I came up with allowed me to do this:

canvas(|state: &mut AppState, ctx, scene, size| {
    let (fcx, lcx) = ctx.text_contexts();

    let mut text_layout_builder = lcx.ranged_builder(fcx, "Text", 1., true);
    text_layout_builder.push_default(StyleProperty::FontStack(FontStack::Single(
        FontFamily::Generic(GenericFamily::Serif),
    )));
    text_layout_builder.push_default(StyleProperty::FontSize(24.));

    let mut text_layout = text_layout_builder.build("Text");
    text_layout.break_all_lines(None);
    text_layout.align(None, TextAlign::Start, TextAlignOptions::default());

    masonry::core::render_text(
        scene,
        Affine::IDENTITY,
        &text_layout,
        &[css::WHITE.into()],
        true,
    );
})

I updated the FnOnce closure to accept a new ctx parameter. Then in Masonry, inside the Canvas::update_scene function, I got the ctx from the WidgetMut<'_, Canvas> and passed it as a mutable reference to the closure. In Xilem, I simply pass the ctx from the closure to the draw closure.

This PR includes the addition of a new screenshot test. The text_canvas test renders a 200x200 image with the text 'Canvas' stretched to fit inside.

Comment on lines +56 to +59
pub fn update_scene(
this: &mut WidgetMut<'_, Self>,
f: impl FnOnce(&mut MutateCtx<'_>, &mut Scene, Size),
) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using PaintCtx would make more sense?

MutateCtx can do a lot of things that this widget wouldn't need.

@DaraJKong
Copy link
Author

To clarify, I don't know if this is the correct way to do it as it's my first PR for this repo. But it works without issues for my use case on Linux.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants