|
| 1 | ++++ |
| 2 | +title = "Linebender in April 2025" |
| 3 | +authors = ["Daniel McNab", "Taj Pereira", "Tom Churchman"] |
| 4 | ++++ |
| 5 | + |
| 6 | +Linebender is an informal open-source organization working on various projects to advance the state of the art in GUI for [the Rust programming language](https://rust-lang.org). |
| 7 | + |
| 8 | +## RustWeek |
| 9 | + |
| 10 | +Many members of the Linebender community will be attending the [RustWeek 2025](https://rustweek.org/) conference, in Utrecht next month. |
| 11 | +At the time of writing, there are no longer tickets available, although there is a waitlist. |
| 12 | +Raph Levien will be giving a talk, titled [*Faster, easier 2D vector rendering*](https://rustweek.org/talks/raph/). |
| 13 | +This will be covering a lot of the sparse strips work discussed in [the Vello section](#vello). |
| 14 | + |
| 15 | +Matt Campbell will give a talk, titled [*AccessKit: reusable UI accessibility*](https://rustweek.org/talks/matt/). |
| 16 | + |
| 17 | +We will also be attending the [unconference](https://rustweek.org/unconf-intro/), as part of the "UI, App dev & Browser Summit" group. |
| 18 | +We're looking forward to working with other teams in the Rust UI ecosystem there. |
| 19 | + |
| 20 | +## Masonry |
| 21 | + |
| 22 | +Masonry is the widget system developed by Linebender. |
| 23 | +It provides a non-opinionated retained widget tree, designed as a base layer for high-level GUI frameworks. |
| 24 | + |
| 25 | +- [xilem#913][], [xilem#938][]: Ongoing work on properties, in preparation for adding more styling options. |
| 26 | +- [xilem#906][]: Improves Virtual Scrolling to support non-infinite use cases. |
| 27 | +- [xilem#922][]: Adds support for multiline text input, by alexjg. |
| 28 | +- [xilem#925][], [xilem#927][]: Update "line" scrolling to have a more correct speed, by Aaron Muir Hamilton and Alix Bott. |
| 29 | +- [xilem#929][]: Used trait upcasting to simplify how widgets use `Any`. |
| 30 | +- [xilem#937][]: Unifies test screenshots into a single folder, making it clearer which widget they relate to. |
| 31 | + |
| 32 | +<figure> |
| 33 | +<img style="height: auto" src="multiline_textbox.png" alt="To do list app, where the next item input says turn off the newline factory, with newlines before newline and factory. The final item also contains a newline." width="600" height="252"> |
| 34 | +<figcaption> |
| 35 | + |
| 36 | +Masonry now has support for multi-line text inputs. |
| 37 | + |
| 38 | +</figcaption> |
| 39 | +</figure> |
| 40 | + |
| 41 | +## Xilem |
| 42 | + |
| 43 | +Xilem is our flagship GUI project, inspired by SwiftUI, which uses Masonry for its widgets. |
| 44 | +It lets you build user interfaces declaratively by composing lightweight views together, and will diff them to provide minimal updates to a retained layer. |
| 45 | + |
| 46 | +- [xilem#920][]: Slightly improves the handling of messages, using trait upcasting. |
| 47 | +- [xilem#921][]: Supports Masonry's virtual scrolling in Xilem. |
| 48 | + |
| 49 | +## Vello |
| 50 | + |
| 51 | +Vello is our GPU vector renderer. |
| 52 | +It can draw large 2D scenes with high performance, using GPU compute shaders for most of the work. |
| 53 | + |
| 54 | +- [vello#886][], [vello#887][]: Update the SDL2 example to SDL3. |
| 55 | +- [vello#892][]: Improved how our snapshot tests are handled in preparation for Kompari integration. |
| 56 | + |
| 57 | +Progress on the sparse strips renderers has also been continuing at pace. |
| 58 | +The big standout this month is the significant leap in Vello CPU functionality: |
| 59 | + |
| 60 | +- [vello#923][]: Blending, compositing, and layers. |
| 61 | +- [vello#893][]: Linear, radial and sweep gradients. |
| 62 | +- [vello#878][]: Clipping. |
| 63 | +- [vello#919][]: Image rendering. |
| 64 | + |
| 65 | +<figure> |
| 66 | +<img style="height: auto" src="cowboy.png" alt="Cowboy emoji, with a rainbox gradient mixed on top." width="300" height="300"> |
| 67 | +<figcaption> |
| 68 | + |
| 69 | +An adapted version of Vello CPU's tests, showing support for blending, gradients and image rendering. |
| 70 | + |
| 71 | +</figcaption> |
| 72 | +</figure> |
| 73 | + |
| 74 | +The above PRs set the foundation for introducing these features into Vello Hybrid over the coming months. |
| 75 | +Another notable released feature is text outline rendering, which allows both renderers to draw text (emoji are not yet supported). |
| 76 | + |
| 77 | +- [vello#883][]: Text outline rendering for Vello CPU and Hybrid. |
| 78 | +- [vello#896][], [vello#897][]: Make the hinting robust, allowing clearer drawing in more cases. |
| 79 | + |
| 80 | +Our working roadmap can be found [here](https://docs.google.com/document/d/1ZquH-53j2OedTbgEKCJBKTh4WLE11UveM10mNdnVARY/edit?tab=t.0#heading=h.j3duh9pgdm94). |
| 81 | +This roadmap outlines our planned timeline for work on the renderers over the next year. |
| 82 | + |
| 83 | +## Parley |
| 84 | + |
| 85 | +Parley is a text layout library. |
| 86 | +It handles text layout, mostly at the level of line breaking and resolving glyph positions. |
| 87 | + |
| 88 | +- [parley#272][]: Added Kompari integration for testing into Parley. |
| 89 | +- [parley#315][]: Implemented properties based on CSS's `word-break` and `overflow-wrap`. |
| 90 | +- [parley#342][]: Fixes a bug in `align` where the offset wasn't being reset between calls. |
| 91 | + |
| 92 | +<figure> |
| 93 | +<img style="height: auto" src="break_all_second_half.png" alt="Text with a line break halfway through the word Antidisestablishmentarianism. The first characters after this break are underlined (indicating that those have the WordBreak property set)." width="626" height="408"> |
| 94 | +<figcaption> |
| 95 | + |
| 96 | +[parley#315][] added the `WordBreak` style property, which is set to `BreakAll` on 'anism' in this screenshot. |
| 97 | + |
| 98 | +</figcaption> |
| 99 | +</figure> |
| 100 | + |
| 101 | +## Kurbo |
| 102 | + |
| 103 | +[Kurbo][] provides data structures and algorithms for curves and vector paths. |
| 104 | + |
| 105 | +We released [Kurbo 0.11.2][], adding the [`Triangle`][kurbo-triangle] shape, providing more ergomic methods on various shapes, and improving performance. |
| 106 | +The following are some highlights of this release. |
| 107 | +See the [changelog][Kurbo 0.11.2] for a full overview. |
| 108 | + |
| 109 | +- [kurbo#350][]: Adds the [`Triangle`][kurbo-triangle] shape. |
| 110 | +- [kurbo#383][]: Adds an efficient numerical method for approximating ellipse perimeters, originally described by Kummer (1837) and rediscovered by Linderholm and Segal (1995). |
| 111 | +- [kurbo#418][]: Adds `BezPath::with_capacity` to allow more efficient allocation if the size of the bezier path is known beforehand. |
| 112 | +- [kurbo#379][]: Adds some common derives to `Stroke` and `StrokeOpts`. |
| 113 | +- [kurbo#384][]: Implements `Div<f64>` and `Mul<f64>` for `Insets`. |
| 114 | +- [kurbo#399][], [kurbo#409][]: Implement `Sum` for `Vec2`, add `Vec2::turn_90` and `Vec2::rotate_scale`. |
| 115 | +- [kurbo#412][], [kurbo#413][]: Add `Size::{min,max}` and `Size::INFINITY`. |
| 116 | +- [kurbo#429][]: Adds `Affine::scale_about` and `Affine::then_scale_about`. |
| 117 | +- [kurbo#390][], [kurbo#428][]: Improve performance by reducing the number of operations in `Triangle::circumscribed_circle` and improving inlining. |
| 118 | + |
| 119 | +Multiple improvements to Kurbo are on the roadmap, such as improved stroke expansion in [kurbo#427][]. |
| 120 | + |
| 121 | +## Color |
| 122 | + |
| 123 | +[Color][] provides functionality for representing, converting, parsing, serializing, and manipulating colors in a variety of color spaces. |
| 124 | +It closely follows the [CSS Color Module Level 4][] draft spec. |
| 125 | + |
| 126 | +We released [Color 0.3.0][], featuring the addition of manual chromatic adaptation and absolute color conversions, improved type conversion ergonomics, and more. |
| 127 | +This month saw the following changes, all included in the 0.3.0 release. |
| 128 | +See the [changelog][Color 0.3.0] for a full overview. |
| 129 | + |
| 130 | +- [color#156][], [color#164][], [color#165][]: Add specialized absolute color conversion methods for ProPhoto RGB, ACES2065-1 and ACEScg. |
| 131 | + While `ColorSpace` includes default implementations for absolute color conversions, having these specializations improves computational efficiency. |
| 132 | +- [color#166][]: Uses faster (and [almost-correct][color-alphacolor-to-rgba8]) rounding for conversion from double precision floating point to 8-bit integer RGBA formats. |
| 133 | + This works around slow x86 rounding behavior. |
| 134 | +- [color#155][]: Improves ergonomics by implementing `From<AlphaColor<_>> for DynamicColor` for all color spaces that have a `DynamicColor` counterpart. |
| 135 | +- [color#157][]: Removes the deprecated `From<Rgba8> for PremulColor<Srgb>` implementation. |
| 136 | +- [color#145][]: Fixes handling of powerless/missing components of the HWB color space, which is necessary for correct color interpolation when components are missing. |
| 137 | +- [color#158][], [color#159][]: Improve documentation for `DynamicColor::interpolate` and `gradient`, including usage examples. |
| 138 | +- [color#149][], [color#150][]: Improve constructing constant `Missing` flags and `Missing` documentation. |
| 139 | + |
| 140 | +## Android View |
| 141 | + |
| 142 | +[Android View](https://github.com/mwcampbell/android-view) is a platform integration for Rust code in Android apps. |
| 143 | +In April, Android View gained support for text input using the software keyboard, with accessibility support. |
| 144 | + |
| 145 | +<figure> |
| 146 | +<img style="height: auto" src="android_view_voice_input.png" alt="Android Screen, with text on the top half, and a keyboard visible with the word listening, followed by an ellipsis." width="252" height="257"> |
| 147 | +<figcaption> |
| 148 | + |
| 149 | +Android View now allows many input methods on Android. |
| 150 | +This screenshot shows voice to text working in an app using Linebender libraries. |
| 151 | +This image has been edited to remove blank areas. |
| 152 | + |
| 153 | +</figcaption> |
| 154 | +</figure> |
| 155 | + |
| 156 | +## Research and Future Directions |
| 157 | + |
| 158 | +Linebender has an origin story in being a very research oriented group, looking to break new ground. |
| 159 | +While we are focused on shipping code today, we still have an eye on the future and how to be prepared for the new opportunities and technologies that are coming. |
| 160 | + |
| 161 | +Towards the end of April, some members of Linebender started working on ecosystem standardisation of input events, based on the web input events specification. |
| 162 | +This work is happening in the [UI Events](https://github.com/endoli/ui-events) repository. |
| 163 | +This is not a Linebender project, but we're watching it with great interest. |
| 164 | + |
| 165 | +We've also started thinking about how to make a renderer abstraction, allowing APIs which can use any of Vello's backends. |
| 166 | +The largest difficulty there is related to resources such as images. |
| 167 | +For example Vello Hybrid's image type would be a `wgpu` Texture, whereas Vello CPU should just use a heap-allocated buffer. |
| 168 | +We have some existing prototypes, see [#vello > Rendering abstraction prototype](https://xi.zulipchat.com/#narrow/channel/197075-vello/topic/Rendering.20abstraction.20prototype/with/516197002) for example. |
| 169 | +This work is likely to now continue after RustWeek. |
| 170 | + |
| 171 | +## Get Involved |
| 172 | + |
| 173 | +We welcome collaboration on any of our crates. |
| 174 | +This can include improving the documentation, implementing new features, improving our test coverage, or using them within your own code. |
| 175 | + |
| 176 | +We host an hour long office hours meeting each week where we discuss what's going on in our projects. |
| 177 | +See [#office hours in Zulip](https://xi.zulipchat.com/#narrow/channel/359642-office-hours) for details. |
| 178 | +We've also started a separate office hours time dedicated to the renderer collaboration, details also available at that link. |
| 179 | + |
| 180 | +- Daniel and Olivier's "office hours" appointments can still be booked by anyone for open-ended discussion of the ecosystem. |
| 181 | + - [See Daniel's schedule here](https://calendar.google.com/calendar/u/0/appointments/schedules/AcZssZ32eQYJ9DtZ_wJaYNtT36YioETiloZDIdImFpBFRo5-XsqGzpikgkg47LPsiHhpiwiQ1orOwwW2). |
| 182 | + - [See Olivier's schedule here](https://calendar.google.com/calendar/u/0/appointments/schedules/AcZssZ2t767ZRETD_TkRI_VxK2ZTG0VrO9OZ4l7HvTxefhtJcg85iK0ZN7zWNnAEZtH0Dn7C1GKxrmYM). |
| 183 | + |
| 184 | +[Kurbo]: https://docs.rs/kurbo/ |
| 185 | +[kurbo-triangle]: https://docs.rs/kurbo/0.11.2/kurbo/struct.Triangle.html |
| 186 | + |
| 187 | +[Kurbo 0.11.2]: https://github.com/linebender/kurbo/releases/tag/v0.11.2 |
| 188 | + |
| 189 | +[Color]: https://docs.rs/color/ |
| 190 | +[CSS Color Module Level 4]: https://www.w3.org/TR/css-color-4/ |
| 191 | +[color-alphacolor-to-rgba8]: https://docs.rs/color/0.3.0/color/struct.AlphaColor.html#method.to_rgba8 |
| 192 | + |
| 193 | +[Color 0.3.0]: https://github.com/linebender/color/releases/tag/v0.3.0 |
| 194 | + |
| 195 | +[color#145]: https://github.com/linebender/color/pull/145 |
| 196 | +[color#149]: https://github.com/linebender/color/pull/149 |
| 197 | +[color#150]: https://github.com/linebender/color/pull/150 |
| 198 | +[color#155]: https://github.com/linebender/color/pull/155 |
| 199 | +[color#156]: https://github.com/linebender/color/pull/156 |
| 200 | +[color#157]: https://github.com/linebender/color/pull/157 |
| 201 | +[color#158]: https://github.com/linebender/color/pull/158 |
| 202 | +[color#159]: https://github.com/linebender/color/pull/159 |
| 203 | +[color#164]: https://github.com/linebender/color/pull/164 |
| 204 | +[color#165]: https://github.com/linebender/color/pull/165 |
| 205 | +[color#166]: https://github.com/linebender/color/pull/166 |
| 206 | +[kurbo#350]: https://github.com/linebender/kurbo/pull/350 |
| 207 | +[kurbo#379]: https://github.com/linebender/kurbo/pull/379 |
| 208 | +[kurbo#383]: https://github.com/linebender/kurbo/pull/383 |
| 209 | +[kurbo#384]: https://github.com/linebender/kurbo/pull/384 |
| 210 | +[kurbo#390]: https://github.com/linebender/kurbo/pull/390 |
| 211 | +[kurbo#399]: https://github.com/linebender/kurbo/pull/399 |
| 212 | +[kurbo#409]: https://github.com/linebender/kurbo/pull/409 |
| 213 | +[kurbo#412]: https://github.com/linebender/kurbo/pull/412 |
| 214 | +[kurbo#413]: https://github.com/linebender/kurbo/pull/413 |
| 215 | +[kurbo#418]: https://github.com/linebender/kurbo/pull/418 |
| 216 | +[kurbo#427]: https://github.com/linebender/kurbo/pull/427 |
| 217 | +[kurbo#428]: https://github.com/linebender/kurbo/pull/428 |
| 218 | +[kurbo#429]: https://github.com/linebender/kurbo/pull/429 |
| 219 | +[parley#272]: https://github.com/linebender/parley/pull/272 |
| 220 | +[parley#315]: https://github.com/linebender/parley/pull/315 |
| 221 | +[parley#342]: https://github.com/linebender/parley/pull/342 |
| 222 | +[vello#878]: https://github.com/linebender/vello/pull/878 |
| 223 | +[vello#883]: https://github.com/linebender/vello/pull/883 |
| 224 | +[vello#886]: https://github.com/linebender/vello/pull/886 |
| 225 | +[vello#887]: https://github.com/linebender/vello/pull/887 |
| 226 | +[vello#892]: https://github.com/linebender/vello/pull/892 |
| 227 | +[vello#893]: https://github.com/linebender/vello/pull/893 |
| 228 | +[vello#896]: https://github.com/linebender/vello/pull/896 |
| 229 | +[vello#897]: https://github.com/linebender/vello/pull/897 |
| 230 | +[vello#919]: https://github.com/linebender/vello/pull/919 |
| 231 | +[vello#923]: https://github.com/linebender/vello/pull/923 |
| 232 | +[xilem#906]: https://github.com/linebender/xilem/pull/906 |
| 233 | +[xilem#913]: https://github.com/linebender/xilem/pull/913 |
| 234 | +[xilem#920]: https://github.com/linebender/xilem/pull/920 |
| 235 | +[xilem#921]: https://github.com/linebender/xilem/pull/921 |
| 236 | +[xilem#922]: https://github.com/linebender/xilem/pull/922 |
| 237 | +[xilem#925]: https://github.com/linebender/xilem/pull/925 |
| 238 | +[xilem#927]: https://github.com/linebender/xilem/pull/927 |
| 239 | +[xilem#929]: https://github.com/linebender/xilem/pull/929 |
| 240 | +[xilem#937]: https://github.com/linebender/xilem/pull/937 |
| 241 | +[xilem#938]: https://github.com/linebender/xilem/pull/938 |
0 commit comments