`Proxy` is the task queue as well as the way an application sends its own
events, so `ProxyQueue` is gone. `schedule_redraw` becomes
`request_redraw_if_needed`, which says what the comment beside it was
saying.
`assert_corners!` replaces the region helper, so `tests/common` goes with
it, and the scroll test now states both corners rather than one number.
`WakeTaskQueue` becomes `TaskQueue`, which carries the update itself.
Delivery and waking are then one act: the winit host sends it through the
`EventLoopProxy` as a `DefaultEvent::Update`, so there is no channel
beside the loop and nothing has to claim a redraw is needed in order to be
looked at. `Window::request_redraw` is gone from this path; `event`
applies the update and then asks the tree whether anything became dirty,
which is the same question `window_event` already ended with -- now
`schedule_redraw`, called from both.
The loop's message type is `DefaultEvent<State>`, so `Proxy` becomes a
wrapper that takes the application's own `Event` and requires it to be
`Send`, since it now crosses to the task thread by that route.
The harness supplies a channel-backed queue, which is what lets a test
hold updates until it asks for them.
Tests split by subject -- layout, pointer, scroll, tasks -- with the
region helper in `tests/common`.
`Tasks` held an `Arc<Window>` only to call `request_redraw` when a task
finished, which made the task queue -- and so `DefaultRsc` -- impossible
to build without a window. It now takes an `Arc<dyn WakeTaskQueue>`, and
`Window` implements it.
Waking moves from "the task ended" to "an update was sent", which is when
there is something for the host to apply: a task that keeps running after
sending one no longer holds its update until it finishes, and a task that
sends none no longer asks for a frame it does not need.
`iris::harness` is what that buys. `UiRenderState` already does layout,
hit testing and primitive building with no surface, so a test can build a
tree, run frames, move a pointer and read back where widgets landed.
`tests/harness.rs` does each of those; none of them could be written
before, since the only entry point to layout was a window.
It does not draw. A claim about pixels still needs a real surface.
Two majors, and the renderer is under everything else left to extract -- so it goes before the slices that would otherwise be written against wgpu 28 and then again against 30. `image` 0.25.6 -> 0.25.10 rides along. `winit` stays on 0.30.12, since 0.31 is only a prerelease and nothing here needs it; `parley` 0.11.1 is current.
What the API asked for, beyond the version:
- **An instance takes the display it will present on**, and GLES on Wayland needs it, so the window the surface is made from is handed over with it. That one matters for Android rather than for this machine.
- **`get_current_texture` returns a status rather than a `Result`**, which replaced an `unwrap` that would have panicked on a resize or an occluded window: reconfigure when the surface is outdated, lost or suboptimal, and skip the frame when there is nothing to draw into.
- **Presenting moved to the queue**, still after `pre_present_notify`.
- **Bind group and vertex buffer layouts are sparse**, so each slot states `Some(layout)`.
Verified the same way as #11: the tabs example with two runtime-added images, an image alone in a layer, and glyphs from a four-page atlas all render identically. `tests/draw_cost.rs` gives 33.6/167/587/2855 us per frame at 8/64/256/1024 layers, against 33.3/161/588/2903 on wgpu 28 -- no change.
---------
Co-authored-by: iris <2+iris@noreply.localhost>
Reviewed-on: iris/iris#13
Reviewed-by: iris <2+iris@noreply.localhost>
Co-authored-by: AIris <4+iris-ai@noreply.localhost>
Replaces the bindless `binding_array<texture_2d<f32>>` the renderer bound every texture through. That array needs `VK_EXT_descriptor_indexing`, which a real share of Android GPUs lack, so the old shape did not run there at all.
The two things being bound want opposite treatment, so they are now split:
- **Glyph atlas pages become layers of one `texture_2d_array`.** A glyph primitive carries a `layer` instead of a view/sampler index pair. A layer index is an ordinary sampling operand, so this needs nothing beyond plain Vulkan 1.0 / GLES. Growing the atlas recreates the array with headroom and `copy_texture_to_texture`s the old layers across, no readback.
- **A standalone image gets its own texture and its own bind group,** and draws in its own call. It no longer needs a per-instance entry in `PrimitiveData`: the bind group has already picked the texture.
`Primitives` keeps images in a list of their own as a result, with `PrimitiveChange::is_image` naming which list a renumbering belongs to -- the two have independent index spaces, so `(layer, inst_idx)` alone would collide between them.
Two notes on judgement calls, since this slice was rebuilt on top of `main` rather than transplanted:
- The source version renamed `GlyphEntry::is_colored` to `is_color` and added a second `IS_COLOR` flag constant beside the existing `GlyphEntry::IS_COLORED`. Both dropped: #10's naming and its `flags()` are kept, and UVs stay `Vec2` rather than going back to `[f32; 2]`.
- `ImageGpu` no longer holds the `Texture` behind its view, which removes an `#[allow(dead_code)]`. A `TextureView` keeps its own reference to the texture, checked by rendering rather than assumed -- see below.
### Verification
```
cargo fmt --all --check
cargo clippy --workspace --all-targets --locked -- -D warnings
cargo test --workspace --locked
```
All clean; the 4 text-edit tests pass. The only clippy output is the pre-existing future-incompatibility notice about `naga`/`wgpu`/`winit`.
Because this is a rendering change, it was also run for real rather than only compiled. The `tabs` example was rendered on this machine's GPU -- Venus onto an RX 7900 XT, confirmed from the loaded ICD (`libvulkan_virtio.so` on `/dev/dri/renderD128`) rather than assumed, since a failed Vulkan init here silently falls back to llvmpipe and would make the screenshots meaningless.
Screenshots before and after the change are **byte-identical** (same md5) in two scenes: the default tab, which exercises text (the atlas path) and rects, and the image tab with a standalone image pushed at startup, which exercises the per-image bind group. The image-tab scene needed a temporary local edit to the example to push the image without a click; that edit is not part of this branch. The same comparison, re-run after dropping the `Texture` field, is still byte-identical -- which is the check that the view alone keeps it alive.
---------
Co-authored-by: iris <2+iris@noreply.localhost>
Reviewed-on: iris/iris#11
Reviewed-by: iris <2+iris@noreply.localhost>
Co-authored-by: AIris <4+iris-ai@noreply.localhost>
Replace the cosmic-text path with Parley layout and Swash rasterization, backed by shared glyph-atlas pages. Shaping, editing, rasterization, and glyph rendering move together because they share the text buffer and rendered-glyph types; splitting them further would require a temporary renderer that is immediately removed.
This is reconstructed rather than replayed from the extraction history. It also fixes issues found during review:
- texture binding changes remain set when an atlas patch follows a new page
- pressing an empty field places a caret and accepts input
- selection motion delegates collapse behavior to Parley
- character deletion follows logical clusters rather than visual neighbors
- the unused root-level Swash dependency is omitted
Four public-behavior integration tests live in `tests/text_edit.rs`: empty-field input, multibyte IME preedit replacement, UTF-8-safe backspace, and selection replacement. The old twelve-test inline block and implementation-restating cases are omitted.
Every added source comment was manually reviewed. Comments that narrated implementation or history were removed; retained comments document cache/rasterization keys, GPU upload constraints, focus representation, bidi geometry, or IME semantics.
Known limitation: atlas pages currently grow without eviction. Each page is 4 MiB on CPU and GPU. An arbitrary cap would leave cached rendered-text UVs pointing at reused glyph slots, so bounding this safely needs a later generation/invalidation change.
This changes public text types and signatures. GPU glyph rendering is covered by compilation rather than a live-surface test.
Verified with:
- `cargo fmt --all --check`
- `cargo clippy --workspace --all-targets -- -D warnings`
- `cargo test --workspace` (four integration tests pass)
Cargo still reports inherited future-incompatibility notices for existing wgpu/winit dependencies; there are no current clippy warnings.
---------
Co-authored-by: iris <2+iris@noreply.localhost>
Reviewed-on: iris/iris#10
Reviewed-by: iris <2+iris@noreply.localhost>
Co-authored-by: AIris <4+iris-ai@noreply.localhost>