}
- /** blockListIndex of the current BlockSequence in blockLists */
- private int blockListIndex = 0;
+ // used by doLayout and getNextBlockList*
+ private List<BlockSequence> blockLists;
- private List blockLists = null;
+ private boolean empty = true;
/** desired text alignment */
protected int alignment;
* @param alignment the desired text alignment
* @return the list of KnuthElements
*/
- protected abstract List getNextKnuthElements(LayoutContext context, int alignment);
+ protected abstract List<KnuthElement> getNextKnuthElements(LayoutContext context,
+ int alignment);
/**
* Get a sequence of KnuthElements representing the content
* change occurs between two LMs
* @return the list of KnuthElements
*/
- protected List getNextKnuthElements(LayoutContext context, int alignment,
+ protected List<KnuthElement> getNextKnuthElements(LayoutContext context, int alignment,
Position positionAtIPDChange, LayoutManager restartAtLM) {
throw new UnsupportedOperationException("TODO: implement acceptable fallback");
}
/** @return true if there's no content that could be handled. */
public boolean isEmpty() {
- return (this.blockLists.isEmpty());
+ return empty;
}
/**
childLC.setBPAlignment(alignment);
BlockSequence blockList;
- this.blockLists = new java.util.ArrayList();
+ blockLists = new java.util.ArrayList<BlockSequence>();
log.debug("PLM> flow BPD =" + flowBPD);
- //*** Phase 1: Get Knuth elements ***
int nextSequenceStartsOn = Constants.EN_ANY;
while (hasMoreContent()) {
blockLists.clear();
+ //*** Phase 1: Get Knuth elements ***
nextSequenceStartsOn = getNextBlockList(childLC, nextSequenceStartsOn);
+ empty = empty && blockLists.size() == 0;
- //*** Phase 2: Alignment and breaking ***
+ //*** Phases 2 and 3 ***
log.debug("PLM> blockLists.size() = " + blockLists.size());
- for (blockListIndex = 0; blockListIndex < blockLists.size(); blockListIndex++) {
- blockList = (BlockSequence) blockLists.get(blockListIndex);
+ for (int blockListIndex = 0; blockListIndex < blockLists.size(); blockListIndex++) {
+ blockList = blockLists.get(blockListIndex);
//debug code start
if (log.isDebugEnabled()) {
observeElementList(blockList);
//debug code end
+ //*** Phase 2: Alignment and breaking ***
log.debug("PLM> start of algorithm (" + this.getClass().getName()
+ "), flow BPD =" + flowBPD);
PageBreakingAlgorithm alg = new PageBreakingAlgorithm(getTopLevelLM(),
- getPageProvider(), createLayoutListener(),
- alignment, alignmentLast, footnoteSeparatorLength,
- isPartOverflowRecoveryActivated(), autoHeight, isSinglePartFavored());
+ getPageProvider(), createLayoutListener(),
+ alignment, alignmentLast, footnoteSeparatorLength,
+ isPartOverflowRecoveryActivated(), autoHeight, isSinglePartFavored());
BlockSequence effectiveList;
if (getCurrentDisplayAlign() == Constants.EN_X_FILL) {
int optimalPageCount = alg.findBreakingPoints(effectiveList, 1, true,
BreakingAlgorithm.ALL_BREAKS);
if (alg.getIPDdifference() != 0) {
- KnuthNode optimalBreak = alg.getBestNodeBeforeIPDChange();
- int positionIndex = optimalBreak.position;
- KnuthElement elementAtBreak = alg.getElement(positionIndex);
- Position positionAtBreak = elementAtBreak.getPosition();
- if (!(positionAtBreak instanceof SpaceResolver.SpaceHandlingBreakPosition)) {
- throw new UnsupportedOperationException(
- "Don't know how to restart at position" + positionAtBreak);
- }
- /* Retrieve the original position wrapped into this space position */
- positionAtBreak = positionAtBreak.getPosition();
- LayoutManager restartAtLM = null;
- List firstElements = Collections.EMPTY_LIST;
- if (containsNonRestartableLM(positionAtBreak)) {
- if (alg.getIPDdifference() > 0) {
- EventBroadcaster eventBroadcaster = getCurrentChildLM().getFObj()
- .getUserAgent().getEventBroadcaster();
- BlockLevelEventProducer eventProducer
- = BlockLevelEventProducer.Provider.get(eventBroadcaster);
- eventProducer.nonRestartableContentFlowingToNarrowerPage(this);
- }
- firstElements = new LinkedList();
- boolean boxFound = false;
- Iterator iter = effectiveList.listIterator(positionIndex + 1);
- Position position = null;
- while (iter.hasNext()
- && (position == null || containsNonRestartableLM(position))) {
- positionIndex++;
- KnuthElement element = (KnuthElement) iter.next();
- position = element.getPosition();
- if (element.isBox()) {
- boxFound = true;
- firstElements.add(element);
- } else if (boxFound) {
- firstElements.add(element);
- }
- }
- if (position instanceof SpaceResolver.SpaceHandlingBreakPosition) {
- /* Retrieve the original position wrapped into this space position */
- positionAtBreak = position.getPosition();
- } else {
- positionAtBreak = null;
- }
- }
- if (positionAtBreak != null && positionAtBreak.getIndex() == -1) {
- /*
- * This is an indication that we are between two blocks
- * (possibly surrounded by another block), not inside a
- * paragraph.
- */
- Position position;
- Iterator iter = effectiveList.listIterator(positionIndex + 1);
- do {
- KnuthElement nextElement = (KnuthElement) iter.next();
- position = nextElement.getPosition();
- } while (position == null
- || position instanceof SpaceResolver.SpaceHandlingPosition
- || position instanceof SpaceResolver.SpaceHandlingBreakPosition
- && position.getPosition().getIndex() == -1);
- LayoutManager surroundingLM = positionAtBreak.getLM();
- while (position.getLM() != surroundingLM) {
- position = position.getPosition();
- }
- restartAtLM = position.getPosition().getLM();
- }
- log.trace("IPD changes after page " + optimalPageCount + " at index "
- + optimalBreak.position);
addAreas(alg, optimalPageCount, blockList, effectiveList);
-
+ // *** redo Phase 1 ***
+ log.trace("IPD changes after page " + optimalPageCount);
blockLists.clear();
+ nextSequenceStartsOn = getNextBlockListChangedIPD(childLC, alg,
+ effectiveList);
blockListIndex = -1;
- nextSequenceStartsOn = getNextBlockList(childLC, Constants.EN_COLUMN,
- positionAtBreak, restartAtLM, firstElements);
} else {
log.debug("PLM> iOptPageCount= " + optimalPageCount
+ " pageBreaks.size()= " + alg.getPageBreaks().size());
-
//*** Phase 3: Add areas ***
doPhase3(alg, optimalPageCount, blockList, effectiveList);
}
}
}
+ // done
+ blockLists = null;
}
/**
BlockSequence originalList, BlockSequence effectiveList) {
LayoutContext childLC;
// add areas
- ListIterator effectiveListIterator = effectiveList.listIterator();
int startElementIndex = 0;
int endElementIndex = 0;
int lastBreak = -1;
// ignore KnuthGlue and KnuthPenalty objects
// at the beginning of the line
- effectiveListIterator = effectiveList
- .listIterator(startElementIndex);
+ ListIterator<KnuthElement> effectiveListIterator
+ = effectiveList.listIterator(startElementIndex);
while (effectiveListIterator.hasNext()
- && !((KnuthElement) effectiveListIterator.next())
- .isBox()) {
+ && !(effectiveListIterator.next()).isBox()) {
startElementIndex++;
}
&& p < (partCount - 1)) {
// count the boxes whose width is not 0
int boxCount = 0;
- effectiveListIterator = effectiveList
- .listIterator(startElementIndex);
+ effectiveListIterator = effectiveList.listIterator(startElementIndex);
while (effectiveListIterator.nextIndex() <= endElementIndex) {
- KnuthElement tempEl = (KnuthElement)effectiveListIterator.next();
+ KnuthElement tempEl = effectiveListIterator.next();
if (tempEl.isBox() && tempEl.getWidth() > 0) {
boxCount++;
}
* @param nextSequenceStartsOn indicates on what page the next sequence should start
* @return the page on which the next content should appear after a hard break
*/
- protected int getNextBlockList(LayoutContext childLC,
- int nextSequenceStartsOn) {
+ protected int getNextBlockList(LayoutContext childLC, int nextSequenceStartsOn) {
return getNextBlockList(childLC, nextSequenceStartsOn, null, null, null);
}
* break
*/
protected int getNextBlockList(LayoutContext childLC, int nextSequenceStartsOn,
- Position positionAtIPDChange, LayoutManager restartAtLM, List firstElements) {
+ Position positionAtIPDChange, LayoutManager restartAtLM,
+ List<KnuthElement> firstElements) {
updateLayoutContext(childLC);
//Make sure the span change signal is reset
childLC.signalSpanChange(Constants.NOT_SET);
BlockSequence blockList;
- List returnedList;
+ List<KnuthElement> returnedList;
if (firstElements == null) {
returnedList = getNextKnuthElements(childLC, alignment);
} else if (positionAtIPDChange == null) {
BlockSequence seq;
seq = blockList.endBlockSequence(breakPosition);
if (seq != null) {
- this.blockLists.add(seq);
+ blockLists.add(seq);
+ }
+ }
+ return nextSequenceStartsOn;
+ }
+
+ /**
+ * @param childLC LayoutContext to use
+ * @param alg the pagebreaking algorithm
+ * @param effectiveList the list of Knuth elements to be reused
+ * @return the page on which the next content should appear after a hard break
+ */
+ private int getNextBlockListChangedIPD(LayoutContext childLC, PageBreakingAlgorithm alg,
+ BlockSequence effectiveList) {
+ int nextSequenceStartsOn;
+ KnuthNode optimalBreak = alg.getBestNodeBeforeIPDChange();
+ int positionIndex = optimalBreak.position;
+ log.trace("IPD changes at index " + positionIndex);
+ KnuthElement elementAtBreak = alg.getElement(positionIndex);
+ Position positionAtBreak = elementAtBreak.getPosition();
+ if (!(positionAtBreak instanceof SpaceResolver.SpaceHandlingBreakPosition)) {
+ throw new UnsupportedOperationException(
+ "Don't know how to restart at position" + positionAtBreak);
+ }
+ /* Retrieve the original position wrapped into this space position */
+ positionAtBreak = positionAtBreak.getPosition();
+ LayoutManager restartAtLM = null;
+ List<KnuthElement> firstElements = Collections.EMPTY_LIST;
+ if (containsNonRestartableLM(positionAtBreak)) {
+ if (alg.getIPDdifference() > 0) {
+ EventBroadcaster eventBroadcaster = getCurrentChildLM().getFObj()
+ .getUserAgent().getEventBroadcaster();
+ BlockLevelEventProducer eventProducer
+ = BlockLevelEventProducer.Provider.get(eventBroadcaster);
+ eventProducer.nonRestartableContentFlowingToNarrowerPage(this);
+ }
+ firstElements = new LinkedList<KnuthElement>();
+ boolean boxFound = false;
+ Iterator<KnuthElement> iter = effectiveList.listIterator(positionIndex + 1);
+ Position position = null;
+ while (iter.hasNext()
+ && (position == null || containsNonRestartableLM(position))) {
+ positionIndex++;
+ KnuthElement element = iter.next();
+ position = element.getPosition();
+ if (element.isBox()) {
+ boxFound = true;
+ firstElements.add(element);
+ } else if (boxFound) {
+ firstElements.add(element);
+ }
+ }
+ if (position instanceof SpaceResolver.SpaceHandlingBreakPosition) {
+ /* Retrieve the original position wrapped into this space position */
+ positionAtBreak = position.getPosition();
+ } else {
+ positionAtBreak = null;
}
}
+ if (positionAtBreak != null && positionAtBreak.getIndex() == -1) {
+ /*
+ * This is an indication that we are between two blocks
+ * (possibly surrounded by another block), not inside a
+ * paragraph.
+ */
+ Position position;
+ Iterator<KnuthElement> iter = effectiveList.listIterator(positionIndex + 1);
+ do {
+ KnuthElement nextElement = iter.next();
+ position = nextElement.getPosition();
+ } while (position == null
+ || position instanceof SpaceResolver.SpaceHandlingPosition
+ || position instanceof SpaceResolver.SpaceHandlingBreakPosition
+ && position.getPosition().getIndex() == -1);
+ LayoutManager surroundingLM = positionAtBreak.getLM();
+ while (position.getLM() != surroundingLM) {
+ position = position.getPosition();
+ }
+ restartAtLM = position.getPosition().getLM();
+ }
+
+ nextSequenceStartsOn = getNextBlockList(childLC, Constants.EN_COLUMN,
+ positionAtBreak, restartAtLM, firstElements);
return nextSequenceStartsOn;
}
*/
private int optimizeLineLength(KnuthSequence effectiveList, int startElementIndex,
int endElementIndex) {
- ListIterator effectiveListIterator;
+ ListIterator<KnuthElement> effectiveListIterator;
// optimize line length
int boxCount = 0;
int accumulatedLineLength = 0;
int greatestMinimumLength = 0;
- effectiveListIterator = effectiveList
- .listIterator(startElementIndex);
+ effectiveListIterator = effectiveList.listIterator(startElementIndex);
while (effectiveListIterator.nextIndex() <= endElementIndex) {
- KnuthElement tempEl = (KnuthElement) effectiveListIterator
+ KnuthElement tempEl = effectiveListIterator
.next();
if (tempEl instanceof KnuthBlockBox) {
KnuthBlockBox blockBox = (KnuthBlockBox) tempEl;
log.debug("PLM> iOptPageNumber= " + iOptPageNumber);
//
- ListIterator sequenceIterator = blockList.listIterator();
- ListIterator breakIterator = alg.getPageBreaks().listIterator();
+ ListIterator<KnuthElement> sequenceIterator = blockList.listIterator();
+ ListIterator<PageBreakPosition> breakIterator = alg.getPageBreaks().listIterator();
KnuthElement thisElement = null;
PageBreakPosition thisBreak;
- int accumulatedS; // accumulated stretch or shrink
int adjustedDiff; // difference already adjusted
- int firstElementIndex;
while (breakIterator.hasNext()) {
- thisBreak = (PageBreakPosition) breakIterator.next();
+ thisBreak = breakIterator.next();
if (log.isDebugEnabled()) {
log.debug("| first page: break= "
+ thisBreak.getLeafPos() + " difference= "
+ thisBreak.difference + " ratio= "
+ thisBreak.bpdAdjust);
}
- accumulatedS = 0;
adjustedDiff = 0;
// glue and penalty items at the beginning of the page must
// while loop must be a box
KnuthElement firstElement;
while ( sequenceIterator.hasNext() ) {
- firstElement = (KnuthElement) sequenceIterator.next();
+ firstElement = sequenceIterator.next();
if ( !firstElement.isBox() ) {
log.debug("PLM> ignoring glue or penalty element "
+ "at the beginning of the sequence");
break;
}
}
- firstElementIndex = sequenceIterator.previousIndex();
sequenceIterator.previous();
// scan the sub-sequence representing a page,
// collecting information about potential adjustments
MinOptMax lineNumberMaxAdjustment = MinOptMax.ZERO;
MinOptMax spaceMaxAdjustment = MinOptMax.ZERO;
- double spaceAdjustmentRatio = 0.0;
- LinkedList blockSpacesList = new LinkedList();
- LinkedList unconfirmedList = new LinkedList();
- LinkedList adjustableLinesList = new LinkedList();
+ LinkedList<KnuthGlue> blockSpacesList = new LinkedList<KnuthGlue>();
+ LinkedList<KnuthGlue> unconfirmedList = new LinkedList<KnuthGlue>();
+ LinkedList<KnuthGlue> adjustableLinesList = new LinkedList<KnuthGlue>();
boolean bBoxSeen = false;
while (sequenceIterator.hasNext()
- && sequenceIterator.nextIndex() <= thisBreak
- .getLeafPos()) {
- thisElement = (KnuthElement) sequenceIterator.next();
+ && sequenceIterator.nextIndex() <= thisBreak.getLeafPos()) {
+ thisElement = sequenceIterator.next();
if (thisElement.isGlue()) {
// glue elements are used to represent adjustable
// lines
// and adjustable spaces between blocks
- Adjustment adjustment = ((KnuthGlue) thisElement).getAdjustmentClass();
+ KnuthGlue thisGlue = (KnuthGlue) thisElement;
+ Adjustment adjustment = thisGlue.getAdjustmentClass();
if (adjustment.equals(Adjustment.SPACE_BEFORE_ADJUSTMENT)
|| adjustment.equals(Adjustment.SPACE_AFTER_ADJUSTMENT)) {
// potential space adjustment
// glue items before the first box or after the
// last one
// must be ignored
- unconfirmedList.add(thisElement);
+ unconfirmedList.add(thisGlue);
} else if (adjustment.equals(Adjustment.LINE_NUMBER_ADJUSTMENT)) {
// potential line number adjustment
lineNumberMaxAdjustment
= lineNumberMaxAdjustment.plusMax(thisElement.getStretch());
lineNumberMaxAdjustment
= lineNumberMaxAdjustment.minusMin(thisElement.getShrink());
- adjustableLinesList.add(thisElement);
+ adjustableLinesList.add(thisGlue);
} else if (adjustment.equals(Adjustment.LINE_HEIGHT_ADJUSTMENT)) {
// potential line height adjustment
}
// the last box
// in this page; they must be added to
// blockSpaceList
- KnuthGlue blockSpace = (KnuthGlue) unconfirmedList
- .removeFirst();
+ KnuthGlue blockSpace = unconfirmedList.removeFirst();
spaceMaxAdjustment
= spaceMaxAdjustment.plusMax(blockSpace.getStretch());
spaceMaxAdjustment
|| (thisBreak.difference < 0 && thisBreak.difference >= spaceMaxAdjustment
.getMin())) {
// modify only the spaces between blocks
- spaceAdjustmentRatio = ((double) thisBreak.difference / (thisBreak.difference > 0
- ? spaceMaxAdjustment.getMax()
- : spaceMaxAdjustment.getMin()));
adjustedDiff += adjustBlockSpaces(
blockSpacesList,
thisBreak.difference,
return effectiveList;
}
- private int adjustBlockSpaces(LinkedList spaceList, int difference, int total) {
+ private int adjustBlockSpaces(LinkedList<KnuthGlue> spaceList, int difference, int total) {
if (log.isDebugEnabled()) {
log.debug("AdjustBlockSpaces: difference " + difference + " / " + total
+ " on " + spaceList.size() + " spaces in block");
}
- ListIterator spaceListIterator = spaceList.listIterator();
+ ListIterator<KnuthGlue> spaceListIterator = spaceList.listIterator();
int adjustedDiff = 0;
int partial = 0;
while (spaceListIterator.hasNext()) {
- KnuthGlue blockSpace = (KnuthGlue)spaceListIterator.next();
+ KnuthGlue blockSpace = spaceListIterator.next();
partial += (difference > 0 ? blockSpace.getStretch() : blockSpace.getShrink());
if (log.isDebugEnabled()) {
log.debug("available = " + partial + " / " + total);
return adjustedDiff;
}
- private int adjustLineNumbers(LinkedList lineList, int difference, int total) {
+ private int adjustLineNumbers(LinkedList<KnuthGlue> lineList, int difference, int total) {
if (log.isDebugEnabled()) {
log.debug("AdjustLineNumbers: difference "
+ difference
+ " elements");
}
- ListIterator lineListIterator = lineList.listIterator();
+ ListIterator<KnuthGlue> lineListIterator = lineList.listIterator();
int adjustedDiff = 0;
int partial = 0;
while (lineListIterator.hasNext()) {
- KnuthGlue line = (KnuthGlue)lineListIterator.next();
+ KnuthGlue line = lineListIterator.next();
partial += (difference > 0 ? line.getStretch() : line.getShrink());
int newAdjust = ((BlockLevelLayoutManager) line.getLayoutManager())
.negotiateBPDAdjustment