From 57d53707c1a2dea0e2c6d9e5d963cbbdd5083da0 Mon Sep 17 00:00:00 2001 From: DemchaAV Date: Sat, 11 Jul 2026 01:25:26 +0100 Subject: [PATCH] refactor(engine): dedup the atomic-block page-admission guard The identical "reject a block taller than a page, advance to a new page when it doesn't fit in the remaining height, mark the landing page touched" guard was copied verbatim into compileHorizontalRow, compileStackedLayer and compileAtomicLeaf. Fold the three copies into one private admitAtomicBlock so the atomic-pagination contract has a single source of truth. Byte-identical. --- .../document/layout/LayoutCompiler.java | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/demcha/compose/document/layout/LayoutCompiler.java b/src/main/java/com/demcha/compose/document/layout/LayoutCompiler.java index 40700f17..b8e3e864 100644 --- a/src/main/java/com/demcha/compose/document/layout/LayoutCompiler.java +++ b/src/main/java/com/demcha/compose/document/layout/LayoutCompiler.java @@ -389,14 +389,7 @@ private void compileHorizontalRow(PreparedNode prepared, MeasureResult naturalMeasure) { DocumentNode node = prepared.node(); double rowOuterHeight = naturalMeasure.height() + margin.vertical(); - double fullPageHeight = state.activeInnerHeight(); - if (rowOuterHeight > fullPageHeight + CAPACITY_TOLERANCE) { - throw atomicTooLarge(path, rowOuterHeight, fullPageHeight); - } - if (rowOuterHeight > state.remainingHeight() + EPS && state.usedHeight > EPS) { - state.newPage(); - } - state.touchPage(); + admitAtomicBlock(rowOuterHeight, path, state); int startPage = state.pageIndex; double placementX = regionX + margin.left(); @@ -588,14 +581,7 @@ private void compileStackedLayer(PreparedNode prepared, MeasureResult naturalMeasure) { DocumentNode node = prepared.node(); double stackOuterHeight = naturalMeasure.height() + margin.vertical(); - double fullPageHeight = state.activeInnerHeight(); - if (stackOuterHeight > fullPageHeight + CAPACITY_TOLERANCE) { - throw atomicTooLarge(path, stackOuterHeight, fullPageHeight); - } - if (stackOuterHeight > state.remainingHeight() + EPS && state.usedHeight > EPS) { - state.newPage(); - } - state.touchPage(); + admitAtomicBlock(stackOuterHeight, path, state); int startPage = state.pageIndex; double placementX = regionX + margin.left(); @@ -729,15 +715,7 @@ private void compileAtomicLeaf(PreparedNode prepared, Padding padding = toPadding(node.padding()); MeasureResult naturalMeasure = prepared.measureResult(); double outerHeight = naturalMeasure.height() + margin.vertical(); - double fullPageHeight = state.activeInnerHeight(); - - if (outerHeight > fullPageHeight + CAPACITY_TOLERANCE) { - throw atomicTooLarge(path, outerHeight, fullPageHeight); - } - if (outerHeight > state.remainingHeight() + EPS && state.usedHeight > EPS) { - state.newPage(); - } - state.touchPage(); + admitAtomicBlock(outerHeight, path, state); double placementX = regionX + margin.left(); double placementY = state.pageTop() - state.usedHeight - margin.top() - naturalMeasure.height(); @@ -1334,6 +1312,28 @@ private String semanticName(DocumentNode node) { return node.name().trim(); } + /** + * Admits a non-splitting block — a horizontal row band, a layer stack, or an + * atomic leaf — onto the page: rejects a block taller than a full page, moves + * to a fresh page when it does not fit in the remaining height, and marks the + * landing page touched. + * + * @param outerHeight the block's outer (margin-box) height + * @param path the block's layout path, for the too-large error message + * @param state the compiler cursor (mutated: may advance to a new page) + * @throws AtomicNodeTooLargeException if the block cannot fit on a full page + */ + private void admitAtomicBlock(double outerHeight, String path, CompilerState state) { + double fullPageHeight = state.activeInnerHeight(); + if (outerHeight > fullPageHeight + CAPACITY_TOLERANCE) { + throw atomicTooLarge(path, outerHeight, fullPageHeight); + } + if (outerHeight > state.remainingHeight() + EPS && state.usedHeight > EPS) { + state.newPage(); + } + state.touchPage(); + } + private AtomicNodeTooLargeException atomicTooLarge(String path, double outerHeight, double pageHeight) { return new AtomicNodeTooLargeException( "Node '" + path + "' requires outer height " + outerHeight