}
// A breakmark box must be translated into a finished node, so that we consume space without
// triggering yet another break. The finished node will consume all space up to the next pagebreak.
final long width = box.getContentAreaX2() - box.getContentAreaX1();
final RenderNode prevSilbling = box.getPrev();
if (prevSilbling == null)
{
// Node is first, so the parent's y is the next edge we take care of.
final long y = parent.getY();
final long y2 = Math.max(pageOffset, box.getY() + box.getHeight());
parent.replaceChild(box, new FinishedRenderNode(width, y2 - y, 0, 0, true));
}
else
{
final long y = prevSilbling.getY() + prevSilbling.getHeight();
final long y2 = Math.max(pageOffset, box.getY() + box.getHeight());
parent.replaceChild(box, new FinishedRenderNode(width, y2 - y, 0, 0, true));
}
}
if (box.isFinished() == false)
{
return true;
}
final RenderNode firstNode = box.getFirstChild();
if (firstNode == null)
{
// The cell is empty ..
return false;
}
final long nodeY = firstNode.getY();
if (nodeY > pageOffset)
{
// This box will be visible or will be processed in the future.
return false;
}
if (firstNode.isOpen())
{
return true;
}
if ((nodeY + firstNode.getHeight()) > pageOffset)
{
// this box will span to the next page and cannot be removed ...
return true;
}
// Next, search the last node that is fully invisible. We collapse all
// invisible node into one big box for efficiency reasons. They wont be
// visible anyway and thus the result will be the same as if they were
// still alive ..
RenderNode last = firstNode;
while (true)
{
final RenderNode next = last.getNext();
if (next == null)
{
break;
}
if (next.isOpen())
{
// as long as a box is open, it can grow and therefore it cannot be
// removed ..
break;
}
if ((next.getY() + next.getHeight()) > pageOffset)
{
// we cant handle that. This node will be visible. So the current last
// node is the one we can shrink ..
break;
}
last = next;
}
// todo: Aggressive removing by commenting out this if-block does seem to trigger a bug in the code below
if (last == firstNode)
{
if (last.getNodeType() == LayoutNodeTypes.TYPE_NODE_FINISHEDNODE)
{
// In this case, we can skip the replace-action below ..
return true;
}
}
final StaticBoxLayoutProperties sblp = box.getStaticBoxLayoutProperties();
final long insetsTop = sblp.getBorderTop() + box.getBoxDefinition().getPaddingTop();
// So lets get started. We remove all nodes between (and inclusive)
// node and last.
final long width = box.getContentAreaX2() - box.getContentAreaX1();
final long lastY2;
if (last.getNext() == null)
{
lastY2 = last.getY() + last.getHeight();
}
else
{
// in case the next box had been shifted
lastY2 = last.getNext().getY();
}
final long startOfBox = box.getY() + insetsTop;
final long height = lastY2 - startOfBox;
// make sure that the finished-box inherits the margins ..
final long marginsTop = firstNode.getEffectiveMarginTop();
final long marginsBottom = last.getEffectiveMarginBottom();
final boolean breakAfter = isBreakAfter(last);
final FinishedRenderNode replacement = new FinishedRenderNode(width, height, marginsTop, marginsBottom, breakAfter);
RenderNode removeNode = firstNode;
while (removeNode != last)
{
final RenderNode next = removeNode.getNext();
if (removeNode.isOpen())
{
throw new IllegalStateException("A node is still open. We should not have come that far.");
}
box.remove(removeNode);