Repository navigation
Conversation
A plugin's service had no way to measure text: it runs in the engine, which linked no text shaping, and only a window's canvas could measure. Layout that must work while Zeron is hidden (agent tools) couldn't run. zeron.measure_text(text, opts) shapes with zgx-gpu's TextServices, the same shaper and font lookup a window's canvas uses, over the system's fonts and the app's own. zeron.load_font(path) adds a font file from the plugin's folder, so the service and a window that loads the same file with ui.load_font measure alike.
A missing file inside the plugin got the same "isn't in the plugin" message as a path outside it.
This was referenced Nov 12, 2026
zgx-gpu brought wgpu and winit into the engine, and on Linux its present code needs zgx's patched wgpu-hal, which the root workspace can't take (it would reach gpui's wgpu): the engine failed to build there. zgx-text (zeronsh/zgx#2094) is zgx's text shaping and measuring alone.
This was referenced Nov 12, 2026
A font the service downloaded (zeron.fetch with binary = true) had no
file in the plugin to name. { base64 = ... } loads it as a file loads,
64 MiB at most, as a window's ui.load_font.
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A plugin's service can't measure text. It runs in the engine, which has no
uiand no text shaping, and only a window's canvas hasc:measure_text. We're moving Zeron Design to a Luau plugin, and its layout has to run in the service, because agents call its tools while Zeron is hidden and plugin windows don't draw then.Now the service measures text the way its window's canvas does:
zeron.measure_text(text, { font, size, weight, italic, tabular, line_height, letter_spacing, width })returns a width and a height. The options are the canvas'sc:measure_textoptions.widthwraps the text, andline_heightandletter_spacingare in points, as onui.text.TextServicesand makes the same call a canvas makes (Scene::measure_text_with_font). The fonts are the system's plus the app's own (Geist, Geist Mono, Instrument Serif). A family it doesn't have falls back as it does in a window.zeron.load_font(path)adds a font file from the plugin's own folder and returns its family names.zeron.load_font { base64 = … }adds a font from its bytes (64 MiB at most), such as a Google Font fetched withzeron.fetch(url, { binary = true })(Plugins: zeron.fetch can return a font's or a picture's bytes whole, in base64 #1379). A window that loads the same file withui.load_font(A script loads a font file and names its family infontzgx#2074) gets the same faces, so both sides measure alike. Each service has its own fonts, so this needs no permission.zgxandzgx-text: zgx's text shaping and measuring without its renderer (Text shaping and measuring build without the renderer zgx#2094), so no wgpu or winit. Until #2094 merges, both are pinned to its commit on the author's fork (hoangvu12/zgxbaf248af). After it merges, the pin moves to zeronsh/zgx's commit, andapps/zgxshould move to the same rev so the service and its windows measure alike.Cost
Cargo.locklines. There's no wgpu, winit or present code. An earlier version of this PR linked zgx-gpu, and that failed on Linux, where zgx-gpu needs zgx's patched wgpu-hal.Testing
Four new tests in
plugins::service::vm::tests:a_service_measures_text_as_a_window_does: "9:41" in Geist 16 measures 29.58 by 23, the size Zeron's window gave on a canvas. Eight option sets (weights, italic, Instrument Serif, mono, the default font, a wrap width, line height and letter spacing) equal what a scene with a renderer's text services measures.a_family_it_lacks_falls_back_as_in_a_window: an unknown family measures as the window's fallback, and two unknown families measure the same. A badwidthis an error.a_service_measures_in_its_plugins_fonts: loading Geist Bold Italic, which isn't among the app's fonts, changes the width, and the new width matches a window with that font. A file that isn't a font, and a path outside the plugin, are refused.a_service_measures_in_a_font_from_its_bytes: Geist Bold Italic loaded from base64 measures as a window with that font. Bytes that aren't a font, text that isn't base64, and a table withoutbase64are refused.cargo test -p zeron-engine --lib plugins::service: 34 passed.cargo check -p zeron-engine --target x86_64-unknown-linux-gnupasses. I have no Linux machine, so the C dependencies' build scripts ran with a stand-in compiler that writes empty objects.cargo checkdoesn't link, so the Rust code is checked in full.cargo clippy -p zeron-engineshows nothing in the touched files.On Windows the engine's lib tests don't compile on
zeron/zgxas it is: an ignored test inchat_persistence.rsand a helper insource_control.rscalllibc::getrusage, which only exists on Unix. I made both Unix-only locally to run the tests and left that out of this PR.Open questions
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.