Renderers: linear per-row measuring in ImGui; one tab width; Qt drawing fixes

ImGui measured every span, highlight and the cursor from column 0 of the
line (and rescanned the line for each column conversion), which is
quadratic in line length on minified files. Columns now come from one
table per line and pixel offsets from the nearest position already
measured. Output is pixel-identical to before (compared under Xvfb, with
syntax colouring, tabs, UTF-8 and search highlights).

kte::kTabWidth replaces the literal 8s, and Qt's 4: Qt expanded tabs to
4 columns while the command layer scrolled by 8, misplacing the cursor
and horizontal scroll on lines with tabs. MeasureChar and
DisplayColumns (TermWidth.h) are the command layer's column model, now
shared, and Qt draws by it instead of one column per byte, which
shifted everything after a multi-byte character.

Qt also:
- drew operators in the dark-mode background colour, so they vanished;
- computed the editor's column count three ways (different glyph,
  padding and status-row accounting) from painting, and positioned text
  with a rounded cell width, so the cursor drifted off the glyphs on long
  lines. One TextLayout now serves painting, resizing, font changes and
  wheel scrolling, with a fractional cell width; runs are drawn only
  where visible;
- drew each non-ASCII character at its cell, since a fallback-font glyph
  wider than a cell pushed the rest of the run out of place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB
This commit is contained in:
Claude
2026-09-24 12:19:59 -07:00
committed by Kyle Isom
parent 29d0ee8244
commit 323e2377fe
6 changed files with 227 additions and 223 deletions
+2 -2
View File
@@ -49,7 +49,7 @@ TerminalRenderer::Draw(Editor &ed)
std::size_t rowoffs = buf->Rowoffs();
std::size_t coloffs = buf->Coloffs();
const int tabw = 8;
const int tabw = static_cast<int>(kte::kTabWidth);
// Phase 3: prefetch visible viewport highlights (current terminal area)
if (buf->SyntaxEnabled() && buf->Highlighter() && buf->Highlighter()->HasHighlighter()) {
int fr = static_cast<int>(rowoffs);
@@ -147,7 +147,7 @@ TerminalRenderer::Draw(Editor &ed)
wch_len = static_cast<int>(res);
}
if (wch == L'\t') {
constexpr std::size_t tab_width = 8;
constexpr std::size_t tab_width = kte::kTabWidth;
const std::size_t next_tab = tab_width - (rc % tab_width);
rc += next_tab;
} else {