Skip to content

Commit 04ec6dd

Browse files
committed
refactor: collapse 11 parallel per-line band vectors in DocLayout::build into a Bands struct with push_placeholder
1 parent d4fc1ef commit 04ec6dd

1 file changed

Lines changed: 107 additions & 88 deletions

File tree

src/doc_layout.rs

Lines changed: 107 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,71 @@ const MEASURE_OVERSCAN_PX: f32 = 800.0;
967967
/// layout even when the cursor briefly outruns the scroll position).
968968
const MEASURE_OVERSCAN_LINES: usize = 30;
969969

970+
/// The 11 parallel per-line output vectors accumulated by `DocLayout::build`, kept in
971+
/// one struct so a placeholder row (hidden line or image-block anchor) is a single
972+
/// `push_placeholder` call instead of 11 hand-aligned pushes — the "add a field, forget
973+
/// a vector" hazard. Destructured into `DocLayout`'s fields at construction.
974+
struct Bands {
975+
heights: Vec<f32>,
976+
layouts: Vec<Rc<parley::Layout<Brush>>>,
977+
renders: Vec<Rc<LineRender>>,
978+
line_ranges: Vec<Range<usize>>,
979+
line_diffs: Vec<LineDiff>,
980+
ghosts: Vec<Vec<Ghost>>,
981+
ghost_height: Vec<f32>,
982+
quote_bars: Vec<Vec<f32>>,
983+
image_blocks: Vec<Option<ImageBlock>>,
984+
inline_draws: Vec<Vec<InlineImageDraw>>,
985+
table_lines: Vec<Option<(Rc<TableLayout>, RowKind)>>,
986+
empty_layout: Rc<parley::Layout<Brush>>,
987+
empty_render: Rc<LineRender>,
988+
}
989+
990+
impl Bands {
991+
fn new(
992+
n: usize,
993+
empty_layout: Rc<parley::Layout<Brush>>,
994+
empty_render: Rc<LineRender>,
995+
) -> Self {
996+
Bands {
997+
heights: Vec::with_capacity(n),
998+
layouts: Vec::with_capacity(n),
999+
renders: Vec::with_capacity(n),
1000+
line_ranges: Vec::with_capacity(n),
1001+
line_diffs: Vec::with_capacity(n),
1002+
ghosts: Vec::with_capacity(n),
1003+
ghost_height: Vec::with_capacity(n),
1004+
quote_bars: Vec::with_capacity(n),
1005+
image_blocks: Vec::with_capacity(n),
1006+
inline_draws: Vec::with_capacity(n),
1007+
table_lines: Vec::with_capacity(n),
1008+
empty_layout,
1009+
empty_render,
1010+
}
1011+
}
1012+
1013+
/// A non-materialized row: a hidden line (`height` 0, `image_block` None) or an
1014+
/// image-block anchor (its block height + `Some(block)`). Everything else empty.
1015+
fn push_placeholder(
1016+
&mut self,
1017+
height: f32,
1018+
range: Range<usize>,
1019+
image_block: Option<ImageBlock>,
1020+
) {
1021+
self.heights.push(height);
1022+
self.layouts.push(self.empty_layout.clone());
1023+
self.renders.push(self.empty_render.clone());
1024+
self.line_ranges.push(range);
1025+
self.line_diffs.push(LineDiff::default());
1026+
self.ghosts.push(Vec::new());
1027+
self.ghost_height.push(0.0);
1028+
self.quote_bars.push(Vec::new());
1029+
self.image_blocks.push(image_block);
1030+
self.inline_draws.push(Vec::new());
1031+
self.table_lines.push(None);
1032+
}
1033+
}
1034+
9701035
pub struct DocLayout {
9711036
layouts: Vec<Rc<parley::Layout<Brush>>>,
9721037
/// Per-line render results (shared with the RenderCache via `Rc`), parallel to
@@ -1171,16 +1236,7 @@ impl DocLayout {
11711236
// Scan mermaid fences once, not per line (a per-line info-string check allocates).
11721237
#[cfg(feature = "mermaid")]
11731238
let mermaid_blocks = snapshot.mermaid_blocks();
1174-
let mut layouts = Vec::with_capacity(n);
1175-
let mut renders = Vec::with_capacity(n);
1176-
let mut line_ranges = Vec::with_capacity(n);
1177-
let mut line_diffs = Vec::with_capacity(n);
1178-
let mut ghosts = Vec::with_capacity(n);
1179-
let mut ghost_height = Vec::with_capacity(n);
1180-
let mut quote_bars: Vec<Vec<f32>> = Vec::with_capacity(n);
1181-
let mut image_blocks: Vec<Option<ImageBlock>> = Vec::with_capacity(n);
1182-
let mut inline_draws: Vec<Vec<InlineImageDraw>> = Vec::with_capacity(n);
1183-
let mut table_lines: Vec<Option<(Rc<TableLayout>, RowKind)>> = Vec::with_capacity(n);
1239+
let mut bands = Bands::new(n, empty_layout.clone(), empty_render.clone());
11841240
let mut image_urls: Vec<String> = Vec::new();
11851241
#[cfg(feature = "mermaid")]
11861242
let mut mermaid_sources: Vec<(String, String)> = Vec::new();
@@ -1199,7 +1255,6 @@ impl DocLayout {
11991255
let content_w = max_advance;
12001256
let img_vpad = IMG_VPAD * scale;
12011257
// Each line's total height = its ghost block above + the real line.
1202-
let mut heights = Vec::with_capacity(n);
12031258
// Cursor component of a line's render key. Table rows share block-reveal state
12041259
// (all flip together when the cursor enters/leaves the block) — except the row
12051260
// the cursor actually sits on, which reveals its own markers. Three distinct
@@ -1231,17 +1286,7 @@ impl DocLayout {
12311286
fold_idx += 1;
12321287
}
12331288
if fold_idx < folds.len() && folds[fold_idx].start <= i {
1234-
heights.push(0.0);
1235-
layouts.push(empty_layout.clone());
1236-
renders.push(empty_render.clone());
1237-
line_ranges.push(snapshot.line_byte_range(i));
1238-
line_diffs.push(LineDiff::default());
1239-
ghosts.push(Vec::new());
1240-
ghost_height.push(0.0);
1241-
quote_bars.push(Vec::new());
1242-
image_blocks.push(None);
1243-
inline_draws.push(Vec::new());
1244-
table_lines.push(None);
1289+
bands.push_placeholder(0.0, snapshot.line_byte_range(i), None);
12451290
continue;
12461291
}
12471292
// Mermaid fence (diagram mode = caret outside the fence). Its non-anchor lines
@@ -1263,17 +1308,7 @@ impl DocLayout {
12631308
if let Some(m) = &mermaid
12641309
&& i != m.anchor_line
12651310
{
1266-
heights.push(0.0);
1267-
layouts.push(empty_layout.clone());
1268-
renders.push(empty_render.clone());
1269-
line_ranges.push(snapshot.line_byte_range(i));
1270-
line_diffs.push(LineDiff::default());
1271-
ghosts.push(Vec::new());
1272-
ghost_height.push(0.0);
1273-
quote_bars.push(Vec::new());
1274-
image_blocks.push(None);
1275-
inline_draws.push(Vec::new());
1276-
table_lines.push(None);
1311+
bands.push_placeholder(0.0, snapshot.line_byte_range(i), None);
12771312
continue;
12781313
}
12791314
// Display-math block ($$…$$): same as mermaid — rendered mode when the caret
@@ -1294,17 +1329,7 @@ impl DocLayout {
12941329
if let Some(m) = &math_block
12951330
&& i != m.anchor_line
12961331
{
1297-
heights.push(0.0);
1298-
layouts.push(empty_layout.clone());
1299-
renders.push(empty_render.clone());
1300-
line_ranges.push(snapshot.line_byte_range(i));
1301-
line_diffs.push(LineDiff::default());
1302-
ghosts.push(Vec::new());
1303-
ghost_height.push(0.0);
1304-
quote_bars.push(Vec::new());
1305-
image_blocks.push(None);
1306-
inline_draws.push(Vec::new());
1307-
table_lines.push(None);
1332+
bands.push_placeholder(0.0, snapshot.line_byte_range(i), None);
13081333
continue;
13091334
}
13101335
// Estimate the head (above the band) and the tail (once the band has covered
@@ -1327,17 +1352,17 @@ impl DocLayout {
13271352
// estimate it (deleted-line count × row height) so the scroll extent stays
13281353
// stable instead of jumping when the line scrolls into the materialized band.
13291354
let gh = estimate_ghost_height(diff, i, min_row);
1330-
heights.push(gh + h);
1331-
layouts.push(empty_layout.clone());
1332-
renders.push(empty_render.clone());
1333-
line_ranges.push(range);
1334-
line_diffs.push(LineDiff::default());
1335-
ghosts.push(Vec::new());
1336-
ghost_height.push(gh);
1337-
quote_bars.push(Vec::new());
1338-
image_blocks.push(None);
1339-
inline_draws.push(Vec::new());
1340-
table_lines.push(None);
1355+
bands.heights.push(gh + h);
1356+
bands.layouts.push(empty_layout.clone());
1357+
bands.renders.push(empty_render.clone());
1358+
bands.line_ranges.push(range);
1359+
bands.line_diffs.push(LineDiff::default());
1360+
bands.ghosts.push(Vec::new());
1361+
bands.ghost_height.push(gh);
1362+
bands.quote_bars.push(Vec::new());
1363+
bands.image_blocks.push(None);
1364+
bands.inline_draws.push(Vec::new());
1365+
bands.table_lines.push(None);
13411366
continue;
13421367
}
13431368
// Mermaid anchor (materialized): draw the diagram (or placeholder) in place of
@@ -1370,17 +1395,7 @@ impl DocLayout {
13701395
measured_count = i + 1;
13711396
}
13721397
}
1373-
heights.push(block_h);
1374-
layouts.push(empty_layout.clone());
1375-
renders.push(empty_render.clone());
1376-
quote_bars.push(Vec::new());
1377-
line_ranges.push(range);
1378-
line_diffs.push(LineDiff::default());
1379-
ghosts.push(Vec::new());
1380-
ghost_height.push(0.0);
1381-
image_blocks.push(Some(block));
1382-
inline_draws.push(Vec::new());
1383-
table_lines.push(None);
1398+
bands.push_placeholder(block_h, range, Some(block));
13841399
continue;
13851400
}
13861401
// Display-math anchor (materialized): render the math and draw it centered in
@@ -1419,17 +1434,7 @@ impl DocLayout {
14191434
measured_count = i + 1;
14201435
}
14211436
}
1422-
heights.push(block_h);
1423-
layouts.push(empty_layout.clone());
1424-
renders.push(empty_render.clone());
1425-
quote_bars.push(Vec::new());
1426-
line_ranges.push(range);
1427-
line_diffs.push(LineDiff::default());
1428-
ghosts.push(Vec::new());
1429-
ghost_height.push(0.0);
1430-
image_blocks.push(Some(block));
1431-
inline_draws.push(Vec::new());
1432-
table_lines.push(None);
1437+
bands.push_placeholder(block_h, range, Some(block));
14331438
continue;
14341439
}
14351440
// Ghost (deleted) lines rendered before this line, from the HEAD snapshot.
@@ -1688,17 +1693,17 @@ impl DocLayout {
16881693
measured_count = i + 1;
16891694
}
16901695
}
1691-
heights.push(total_h);
1692-
layouts.push(layout);
1693-
renders.push(lr);
1694-
quote_bars.push(bars);
1695-
line_ranges.push(range);
1696-
line_diffs.push(line_diff);
1697-
ghosts.push(line_ghosts);
1698-
ghost_height.push(gh);
1699-
image_blocks.push(image_block);
1700-
inline_draws.push(line_inline_draws);
1701-
table_lines.push(table_line);
1696+
bands.heights.push(total_h);
1697+
bands.layouts.push(layout);
1698+
bands.renders.push(lr);
1699+
bands.quote_bars.push(bars);
1700+
bands.line_ranges.push(range);
1701+
bands.line_diffs.push(line_diff);
1702+
bands.ghosts.push(line_ghosts);
1703+
bands.ghost_height.push(gh);
1704+
bands.image_blocks.push(image_block);
1705+
bands.inline_draws.push(line_inline_draws);
1706+
bands.table_lines.push(table_line);
17021707
}
17031708
cache.sweep();
17041709
render_cache.sweep();
@@ -1716,6 +1721,20 @@ impl DocLayout {
17161721
deleted_bg: peniko_color_alpha(theme.red, 0.15),
17171722
deleted_inline: peniko_color_alpha(theme.red, 0.40),
17181723
};
1724+
let Bands {
1725+
heights,
1726+
layouts,
1727+
renders,
1728+
line_ranges,
1729+
line_diffs,
1730+
ghosts,
1731+
ghost_height,
1732+
quote_bars,
1733+
image_blocks,
1734+
inline_draws,
1735+
table_lines,
1736+
..
1737+
} = bands;
17191738
Self {
17201739
layouts,
17211740
renders,

0 commit comments

Comments
 (0)