From 9f8747c112386f63a63e44a6374bdb42f08e6891 Mon Sep 17 00:00:00 2001 From: Vansh Negi Date: Sat, 4 Apr 2026 13:10:35 +0000 Subject: [PATCH 1/3] fix inner product symbol rendering in Tab cycling popup --- src/Graphics/Fonts/math_font.cpp | 117 ++++++++++++++++++++++++++----- 1 file changed, 98 insertions(+), 19 deletions(-) diff --git a/src/Graphics/Fonts/math_font.cpp b/src/Graphics/Fonts/math_font.cpp index c2a9303ac1..eea7b17e58 100644 --- a/src/Graphics/Fonts/math_font.cpp +++ b/src/Graphics/Fonts/math_font.cpp @@ -175,39 +175,118 @@ math_font_rep::supports (string c) { void math_font_rep::get_extents (string s, metric& ex) { - font fn; - search_font (s, fn); - fn->get_extents (s, ex); + // Fast path: single TeXmacs character + int i= 0; + tm_char_forwards (s, i); + if (i >= N (s)) { + font fn; + search_font (s, fn); + fn->get_extents (s, ex); + return; + } + // Multi-character string (e.g. ""): accumulate extents + // character by character so each symbol is looked up individually. + metric ey; + SI advance= 0; + bool first = true; + i = 0; + while (i < N (s)) { + int j= i; + tm_char_forwards (s, j); + get_extents (s (i, j), ey); + if (first) { + ex[0]= ey[0]; + first= false; + } + else { + ex->x2= advance + ey->x2; + ex->y1= min (ex->y1, ey->y1); + ex->y2= max (ex->y2, ey->y2); + ex->x3= min (ex->x3, advance + ey->x3); + ex->y3= min (ex->y3, ey->y3); + ex->x4= max (ex->x4, advance + ey->x4); + ex->y4= max (ex->y4, ey->y4); + } + advance+= ey->x2; + i= j; + } } void math_font_rep::get_xpositions (string s, SI* xpos) { if (s == "") return; - font fn; - string r= s; - search_font (r, fn); - if (r == s) fn->get_xpositions (s, xpos); - else if (N (r) != 1) font_rep::get_xpositions (s, xpos); - else { - int i, n= N (s); - for (i= 1; i < n; i++) - xpos[i]= 0; - fn->get_xpositions (r, xpos + n - 1); + // Fast path: single TeXmacs character + int i= 0; + tm_char_forwards (s, i); + if (i >= N (s)) { + font fn; + string r= s; + search_font (r, fn); + if (r == s) fn->get_xpositions (s, xpos); + else if (N (r) != 1) font_rep::get_xpositions (s, xpos); + else { + int k, n= N (s); + for (k= 1; k < n; k++) + xpos[k]= 0; + fn->get_xpositions (r, xpos + n - 1); + } + return; + } + // Multi-character string: compute positions character by character. + xpos[0] = 0; + SI advance= 0; + i = 0; + while (i < N (s)) { + int j= i; + tm_char_forwards (s, j); + metric ex; + get_extents (s (i, j), ex); + advance+= ex->x2; + xpos[j]= advance; + i = j; } } void math_font_rep::draw_fixed (renderer ren, string s, SI x, SI y) { - font fn; - search_font (s, fn); - fn->draw_fixed (ren, s, x, y); + // Fast path: single TeXmacs character + int i= 0; + tm_char_forwards (s, i); + if (i >= N (s)) { + font fn; + search_font (s, fn); + fn->draw_fixed (ren, s, x, y); + return; + } + // Multi-character string: draw each symbol at its own x-advance offset. + SI advance= 0; + i = 0; + while (i < N (s)) { + int j= i; + tm_char_forwards (s, j); + string c= s (i, j); + draw_fixed (ren, c, x + advance, y); + metric ex; + get_extents (c, ex); + advance+= ex->x2; + i= j; + } } void math_font_rep::draw_fixed (renderer ren, string s, SI x, SI y, SI xk) { - font fn; - search_font (s, fn); - fn->draw_fixed (ren, s, x, y, xk); + // Fast path: single TeXmacs character + int i= 0; + tm_char_forwards (s, i); + if (i >= N (s)) { + font fn; + search_font (s, fn); + fn->draw_fixed (ren, s, x, y, xk); + return; + } + // Multi-character string: delegate to base class which iterates char-by-char + // using get_xpositions (now consistent) and calls single-char draw_fixed. + font_rep::draw_fixed (ren, s, x, y, xk); } font From d4992fa6e96c570c20c835b6211d45eac46a75bf Mon Sep 17 00:00:00 2001 From: Vansh Negi Date: Sat, 4 Apr 2026 13:11:00 +0000 Subject: [PATCH 2/3] add developer document devel/201_104.md --- devel/201_104.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 devel/201_104.md diff --git a/devel/201_104.md b/devel/201_104.md new file mode 100644 index 0000000000..c5bccac2b8 --- /dev/null +++ b/devel/201_104.md @@ -0,0 +1,27 @@ +# [201_104] Fix inner product symbol not rendering in Tab cycling popup + +### What +Fixed `⟨⟩` (angle bracket pair) showing as a red broken symbol in the Tab cycling completion popup when typing `<` in math mode. + +### Why +The Tab cycling popup renders symbol labels using `math_font_rep`. Its `get_extents`, `get_xpositions`, and `draw_fixed` methods all passed the full string to `search_font`, which only handles single math symbols. For a bracket pair like `""` (two concatenated TeXmacs symbols), `search_font` fails — it is not a single dictionary entry and the character fallback rejects `<` — so it returns `error_font`, which draws in red. + +### How +Modified `src/Graphics/Fonts/math_font.cpp`. + +Added a single-char fast path (via `tm_char_forwards`) to `get_extents`, `get_xpositions`, and both `draw_fixed` overloads. Single characters use the original `search_font` lookup unchanged. Multi-character strings iterate character by character: + +- `get_extents`: accumulates per-symbol metrics, combining advance widths and taking the union of ink bounds. +- `get_xpositions`: fills the position array by accumulating advance widths per symbol. +- `draw_fixed(x, y)`: draws each symbol at its accumulated x-offset. +- `draw_fixed(x, y, xk)`: delegates to `font_rep::draw_fixed` (base class already iterates char-by-char). + +No Scheme-level changes needed — `lambda-to-symbol` in `math-edit.scm` already returns `(string-append lb rb)`. + +### How to test +1. Open Mogan Editor and create a new document. +2. Enter math mode (`$` or via Insert → Math). +3. Type `<` and press `Tab` to open the cycling popup. +4. **Verify**: The `⟨⟩` entry displays correctly (not in red). +5. Press `Tab` to cycle through variants and select `⟨⟩`. +6. **Verify**: The correct angle bracket pair is inserted in the document. From cdd30c668a6a0cbdc84fa0f217415afa8cc3a875 Mon Sep 17 00:00:00 2001 From: Vansh Negi Date: Sat, 4 Apr 2026 13:45:04 +0000 Subject: [PATCH 3/3] Trigger CI rerun