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: #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: #10
Reviewed-by: iris <2+iris@noreply.localhost>
Co-authored-by: AIris <4+iris-ai@noreply.localhost>