refactor(render): the atlas is a declared fixed-cell grid, and staging checks it
The text pipeline stages a glyph's rect *origin* per instance and carries the rect's *size* once per draw, so a backend whose glyphs have differing rect sizes -- a TrueType packing trimmed to ink, which is Task 8's shape -- would have drawn every glyph at whichever size it happened to be told, with nothing downstream able to tell. Make that constraint structural rather than documented: - TextBackend::cell_uv() declares the one cell size, and the contract (an atlas is a fixed-cell grid; a proportional face draws its glyphs *into* a uniform cell instead of trimming each rect to its ink, and why the pipeline needs it) is stated on the atlas accessors. - glyph_is_cell() is the check; add_text()/set_cell() declare the cell from the backend, and the staging path asserts it for every glyph in a debug build. A release build draws on with the cell it was told, as before. - Renderer::flush_text() takes u_glyph_uv from the backend, not from the batch, so the draw's one rect size can never come from whichever glyph was staged first.
This commit is contained in:
1 parent
e074f57ddf
commit
ffc060d6ca
11 files changed
+364
-43
No files matched your search
@@ -61,15 +61,25 @@ class LineBatch {
|
||||
/// buffer.hpp).
|
||||
///
|
||||
/// Every glyph a batch stages is read through one atlas rect of one size — its
|
||||
/// cell — so that size is recorded once (`glyph_cell_uv()`) and handed to the
|
||||
/// draw, rather than riding along with every instance.
|
||||
/// cell (see `TextBackend::cell_uv`) — so that size is declared once
|
||||
/// (`set_cell()`) and handed to the draw, rather than riding along with every
|
||||
/// instance. In a debug build every staged glyph is checked against it.
|
||||
class TextBatch {
|
||||
public:
|
||||
/// Starts a frame: empties the batch and the staged cell, keeps the capacity.
|
||||
/// Starts a frame: empties the batch and forgets the declared cell, keeps the
|
||||
/// capacity.
|
||||
void begin() noexcept;
|
||||
/// Same as `begin()`.
|
||||
void clear() noexcept;
|
||||
|
||||
/// Declares the atlas cell the glyphs staged from here on are drawn in -- the
|
||||
/// backend's `cell_uv()`. `add_text()` does this itself from the backend it is
|
||||
/// handed; a caller staging glyphs one at a time says it here, so the draw's
|
||||
/// single rect size comes from the backend rather than from whichever glyph was
|
||||
/// staged first. A debug build asserts that no second, different cell arrives
|
||||
/// in one batch.
|
||||
void set_cell(Vec2 cell_uv) noexcept;
|
||||
|
||||
/// Stages one glyph cell whose *pen* is `pen_px`: the cell's top-left corner is
|
||||
/// the pen moved by the glyph's bearing (see `Glyph`), scaled and measured
|
||||
/// along the run's own axes, so a glyph keeps its place inside a rotated run.
|
||||
@@ -101,9 +111,11 @@ class TextBatch {
|
||||
/// Interleaved `x,y,u,v,ax,ay`, six floats per staged glyph.
|
||||
const std::vector<f32>& data() const noexcept { return v_; }
|
||||
|
||||
/// The staged glyphs' cell in the atlas, normalised: `(u1 - u0, v1 - v0)` of
|
||||
/// the glyphs staged, which the draw passes as `u_glyph_uv` (see
|
||||
/// `TextProgram::set_glyph_uv`). `(0, 0)` while nothing is staged.
|
||||
/// The cell the staged glyphs are drawn in: what `set_cell()` declared, or --
|
||||
/// for a caller that stages raw glyphs without ever declaring one -- the rect
|
||||
/// size of the first glyph staged, since nothing else can be the authority
|
||||
/// there. The renderer declares the cell from the backend it draws with, so it
|
||||
/// never depends on that fallback. `(0, 0)` while nothing is staged.
|
||||
Vec2 glyph_cell_uv() const noexcept { return cell_uv_; }
|
||||
|
||||
private:
|
||||
@@ -113,6 +125,10 @@ class TextBatch {
|
||||
|
||||
std::vector<f32> v_;
|
||||
Vec2 cell_uv_{};
|
||||
/// False until a cell arrives -- from `set_cell()`, or from the first glyph
|
||||
/// staged by a caller that declared none. It keeps a zero-sized cell
|
||||
/// distinguishable from "nothing said yet".
|
||||
bool cell_declared_ = false;
|
||||
};
|
||||
|
||||
} // namespace plot::render
|
||||
Reference in new issue
Block a user