addedPositions = 0;
}
- if (addedPositions == lineLayouts.getLineNumber(activePossibility)) {
+ if (addedPositions == lineLayouts.getLineCount(activePossibility)) {
activePossibility ++;
addedPositions = 0;
/*LF*/ //System.out.println(" ");
// IPD remaining in line
MinOptMax availIPD = context.getStackLimit();
- LayoutContext inlineLC = new LayoutContext(context);
-
clearPrevIPD();
int iPrevLineEnd = vecInlineBreaks.size();
prevBP = null;
//PHASE 1: Create Knuth elements
-
if (knuthParagraphs == null) {
// it's the first time this method is called
knuthParagraphs = new ArrayList();
// here starts Knuth's algorithm
- KnuthElement thisElement = null;
- LinkedList returnedList = null;
- iLineWidth = context.getStackLimit().opt;
-
- // convert all the text in a sequence of paragraphs made
- // of KnuthBox, KnuthGlue and KnuthPenalty objects
- boolean bPrevWasKnuthBox = false;
- KnuthBox prevBox = null;
-
- Paragraph knuthPar = new Paragraph(this,
- bTextAlignment, bTextAlignmentLast,
- textIndent.getValue());
- knuthPar.startParagraph(availIPD.opt);
- while ((curLM = (InlineLevelLayoutManager) getChildLM()) != null) {
- if ((returnedList
- = curLM.getNextKnuthElements(inlineLC,
- effectiveAlignment))
- != null) {
- // look at the first element
- thisElement = (KnuthElement) returnedList.getFirst();
- if (thisElement.isBox() && !thisElement.isAuxiliary()
- && bPrevWasKnuthBox) {
- prevBox = (KnuthBox) knuthPar.removeLast();
- LinkedList oldList = new LinkedList();
- // if there are two consecutive KnuthBoxes the
- // first one does not represent a whole word,
- // so it must be given one more letter space
- if (!prevBox.isAuxiliary()) {
- // if letter spacing is constant,
- // only prevBox needs to be replaced;
- oldList.add(prevBox);
- } else {
- // prevBox is the last element
- // in the sub-sequence
- // <box> <aux penalty> <aux glue> <aux box>
- // the letter space is added to <aux glue>,
- // while the other elements are not changed
- oldList.add(prevBox);
- oldList.addFirst((KnuthGlue) knuthPar.removeLast());
- oldList.addFirst((KnuthPenalty) knuthPar.removeLast());
- }
- // adding a letter space could involve, according to the text
- // represented by oldList, replacing a glue element or adding
- // new elements
- knuthPar.addAll(((InlineLevelLayoutManager)
- prevBox.getLayoutManager())
- .addALetterSpaceTo(oldList));
- }
-
- // look at the last element
- KnuthElement lastElement = (KnuthElement) returnedList.getLast();
- boolean bForceLinefeed = false;
- if (lastElement.isBox()) {
- bPrevWasKnuthBox = true;
- } else {
- bPrevWasKnuthBox = false;
- if (lastElement.isPenalty()
- && ((KnuthPenalty) lastElement).getP()
- == -KnuthPenalty.INFINITE) {
- // a penalty item whose value is -inf
- // represents a preserved linefeed,
- // wich forces a line break
- bForceLinefeed = true;
- returnedList.removeLast();
- }
- }
-
- // add the new elements to the paragraph
- knuthPar.addAll(returnedList);
- if (bForceLinefeed) {
- if (knuthPar.size() == 0) {
- //only a forced linefeed on this line
- //-> compensate with a zero width box
- knuthPar.add(new KnuthInlineBox(0, 0, 0, 0,
- null, false));
- }
- knuthPar.endParagraph();
- knuthPar = new Paragraph(this,
- bTextAlignment, bTextAlignmentLast,
- textIndent.getValue());
- knuthPar.startParagraph(availIPD.opt);
- bPrevWasKnuthBox = false;
- }
- } else {
- // curLM returned null; this can happen
- // if it has nothing more to layout,
- // so just iterate once more to see
- // if there are other children
- }
- }
- knuthPar.endParagraph();
+ //TODO availIPD should not really be used here, so we can later support custom line
+ //widths for for each line (side-floats, differing available IPD after page break)
+ collectInlineKnuthElements(context, availIPD);
} else {
// this method has been called before
// all line breaks are already calculated
*/
}
+ /**
+ * Phase 1 of Knuth algorithm: Collect all inline Knuth elements before determining line breaks.
+ * @param context the LayoutContext
+ * @param availIPD available IPD for line (should be removed!)
+ */
+ private void collectInlineKnuthElements(LayoutContext context, MinOptMax availIPD) {
+ LayoutContext inlineLC = new LayoutContext(context);
+
+ InlineLevelLayoutManager curLM;
+ KnuthElement thisElement = null;
+ LinkedList returnedList = null;
+ iLineWidth = context.getStackLimit().opt;
+
+ // convert all the text in a sequence of paragraphs made
+ // of KnuthBox, KnuthGlue and KnuthPenalty objects
+ boolean bPrevWasKnuthBox = false;
+ KnuthBox prevBox = null;
+
+ Paragraph knuthPar = new Paragraph(this,
+ bTextAlignment, bTextAlignmentLast,
+ textIndent.getValue());
+ knuthPar.startParagraph(availIPD.opt);
+ while ((curLM = (InlineLevelLayoutManager) getChildLM()) != null) {
+ if ((returnedList
+ = curLM.getNextKnuthElements(inlineLC,
+ effectiveAlignment))
+ != null) {
+ // look at the first element
+ thisElement = (KnuthElement) returnedList.getFirst();
+ if (thisElement.isBox() && !thisElement.isAuxiliary()
+ && bPrevWasKnuthBox) {
+ prevBox = (KnuthBox) knuthPar.removeLast();
+ LinkedList oldList = new LinkedList();
+ // if there are two consecutive KnuthBoxes the
+ // first one does not represent a whole word,
+ // so it must be given one more letter space
+ if (!prevBox.isAuxiliary()) {
+ // if letter spacing is constant,
+ // only prevBox needs to be replaced;
+ oldList.add(prevBox);
+ } else {
+ // prevBox is the last element
+ // in the sub-sequence
+ // <box> <aux penalty> <aux glue> <aux box>
+ // the letter space is added to <aux glue>,
+ // while the other elements are not changed
+ oldList.add(prevBox);
+ oldList.addFirst((KnuthGlue) knuthPar.removeLast());
+ oldList.addFirst((KnuthPenalty) knuthPar.removeLast());
+ }
+ // adding a letter space could involve, according to the text
+ // represented by oldList, replacing a glue element or adding
+ // new elements
+ knuthPar.addAll(((InlineLevelLayoutManager)
+ prevBox.getLayoutManager())
+ .addALetterSpaceTo(oldList));
+ }
+
+ // look at the last element
+ KnuthElement lastElement = (KnuthElement) returnedList.getLast();
+ boolean bForceLinefeed = false;
+ if (lastElement.isBox()) {
+ bPrevWasKnuthBox = true;
+ } else {
+ bPrevWasKnuthBox = false;
+ if (lastElement.isPenalty()
+ && ((KnuthPenalty) lastElement).getP()
+ == -KnuthPenalty.INFINITE) {
+ // a penalty item whose value is -inf
+ // represents a preserved linefeed,
+ // wich forces a line break
+ bForceLinefeed = true;
+ returnedList.removeLast();
+ }
+ }
+
+ // add the new elements to the paragraph
+ knuthPar.addAll(returnedList);
+ if (bForceLinefeed) {
+ if (knuthPar.size() == 0) {
+ //only a forced linefeed on this line
+ //-> compensate with a zero width box
+ knuthPar.add(new KnuthInlineBox(0, 0, 0, 0,
+ null, false));
+ }
+ knuthPar.endParagraph();
+ knuthPar = new Paragraph(this,
+ bTextAlignment, bTextAlignmentLast,
+ textIndent.getValue());
+ knuthPar.startParagraph(availIPD.opt);
+ bPrevWasKnuthBox = false;
+ }
+ } else {
+ // curLM returned null; this can happen
+ // if it has nothing more to layout,
+ // so just iterate once more to see
+ // if there are other children
+ }
+ }
+ knuthPar.endParagraph();
+ }
+
/**
* Find a set of breaking points.
* This method is called only once by getNextBreakPoss, and it
}*/
+ /**
+ * Phase 2 of Knuth algorithm: find optimal break points.
+ * @param alignment alignmenr of the paragraph
+ * @return a list of Knuth elements representing broken lines
+ */
private LinkedList findOptimalLineBreakingPoints(int alignment) {
// find the optimal line breaking points for each paragraph
lineLayouts.restorePossibilities();
/* *** *** estensione *** *** */
+ //TODO This code snippet is disabled. Reenable?
if (false && alignment == EN_JUSTIFY && bTextAlignment == EN_JUSTIFY) {
/*LF*/ //System.out.println("LLM.getNextKnuthElements> soluzioni con piu' righe? " + lineLayouts.canUseMoreLines());
/*LF*/ //System.out.println(" soluzioni con meno righe? " + lineLayouts.canUseLessLines());
/* ALLINEAMENTO NON GIUSTIFICATO, elementi con Position effettive */
Position returnPosition = new LeafPosition(this, p);
for (int i = 0;
- i < lineLayouts.getChosenLineNumber();
+ i < lineLayouts.getChosenLineCount();
i++) {
if (!((BlockLevelLayoutManager) parentLM).mustKeepTogether()
&& i >= fobj.getOrphans()
- && i <= lineLayouts.getChosenLineNumber() - fobj.getWidows()
+ && i <= lineLayouts.getChosenLineCount() - fobj.getWidows()
&& returnList.size() > 0) {
// null penalty allowing a page break between lines
returnList.add(new KnuthPenalty(0, 0, false, returnPosition, false));
List breaker = new LinkedList();
/* commentare via per testare layout particolari */
- if (fobj.getOrphans() + fobj.getWidows() <= lineLayouts.getMinLineNumber()) {
- nInnerLines = lineLayouts.getMinLineNumber() - (fobj.getOrphans() + fobj.getWidows());
- nOptionalLines = lineLayouts.getMaxLineNumber() - lineLayouts.getOptLineNumber();
- nEliminableLines = lineLayouts.getOptLineNumber() - lineLayouts.getMinLineNumber();
- } else if (fobj.getOrphans() + fobj.getWidows() <= lineLayouts.getOptLineNumber()) {
- nOptionalLines = lineLayouts.getMaxLineNumber() - lineLayouts.getOptLineNumber();
- nEliminableLines = lineLayouts.getOptLineNumber() - (fobj.getOrphans() + fobj.getWidows());
- nConditionalEliminableLines = (fobj.getOrphans() + fobj.getWidows()) - lineLayouts.getMinLineNumber();
- } else if (fobj.getOrphans() + fobj.getWidows() <= lineLayouts.getMaxLineNumber()) {
- nOptionalLines = lineLayouts.getMaxLineNumber() - (fobj.getOrphans() + fobj.getWidows());
- nConditionalOptionalLines = (fobj.getOrphans() + fobj.getWidows()) - lineLayouts.getOptLineNumber();
- nConditionalEliminableLines = lineLayouts.getOptLineNumber() - lineLayouts.getMinLineNumber();
+ if (fobj.getOrphans() + fobj.getWidows() <= lineLayouts.getMinLineCount()) {
+ nInnerLines = lineLayouts.getMinLineCount() - (fobj.getOrphans() + fobj.getWidows());
+ nOptionalLines = lineLayouts.getMaxLineCount() - lineLayouts.getOptLineCount();
+ nEliminableLines = lineLayouts.getOptLineCount() - lineLayouts.getMinLineCount();
+ } else if (fobj.getOrphans() + fobj.getWidows() <= lineLayouts.getOptLineCount()) {
+ nOptionalLines = lineLayouts.getMaxLineCount() - lineLayouts.getOptLineCount();
+ nEliminableLines = lineLayouts.getOptLineCount() - (fobj.getOrphans() + fobj.getWidows());
+ nConditionalEliminableLines = (fobj.getOrphans() + fobj.getWidows()) - lineLayouts.getMinLineCount();
+ } else if (fobj.getOrphans() + fobj.getWidows() <= lineLayouts.getMaxLineCount()) {
+ nOptionalLines = lineLayouts.getMaxLineCount() - (fobj.getOrphans() + fobj.getWidows());
+ nConditionalOptionalLines = (fobj.getOrphans() + fobj.getWidows()) - lineLayouts.getOptLineCount();
+ nConditionalEliminableLines = lineLayouts.getOptLineCount() - lineLayouts.getMinLineCount();
nFirstLines -= nConditionalOptionalLines;
} else {
- nConditionalOptionalLines = lineLayouts.getMaxLineNumber() - lineLayouts.getOptLineNumber();
- nConditionalEliminableLines = lineLayouts.getOptLineNumber() - lineLayouts.getMinLineNumber();
- nFirstLines = lineLayouts.getOptLineNumber();
+ nConditionalOptionalLines = lineLayouts.getMaxLineCount() - lineLayouts.getOptLineCount();
+ nConditionalEliminableLines = lineLayouts.getOptLineCount() - lineLayouts.getMinLineCount();
+ nFirstLines = lineLayouts.getOptLineCount();
nLastLines = 0;
}
/* commentare via per testare layout particolari */
int lineNumberDifference = (int) Math.round((double) totalAdj / constantLineHeight + (adj > 0 ? - 0.4 : 0.4));
/*LF*/ //System.out.println(" LLM> variazione calcolata = " + ((double) totalAdj / constantLineHeight) + " variazione applicata = " + lineNumberDifference);
lineLayouts = (LineLayoutPossibilities)lineLayoutsList.get(pos.getLeafPos());
- lineNumberDifference = lineLayouts.applyLineNumberAdjustment(lineNumberDifference);
+ lineNumberDifference = lineLayouts.applyLineCountAdjustment(lineNumberDifference);
return lineNumberDifference * constantLineHeight;
}
lineLayouts = (LineLayoutPossibilities)lineLayoutsList.get(p);
/*LF*/ //System.out.println("demeriti definitivi: " + lineLayouts.getChosenDemerits());
for (int i = 0;
- i < lineLayouts.getChosenLineNumber();
+ i < lineLayouts.getChosenLineCount();
i ++) {
if (!((BlockLevelLayoutManager) parentLM).mustKeepTogether()
&& i >= fobj.getOrphans()
- && i <= lineLayouts.getChosenLineNumber() - fobj.getWidows()) {
+ && i <= lineLayouts.getChosenLineCount() - fobj.getWidows()) {
// null penalty allowing a page break between lines
returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false));
}
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
package org.apache.fop.layoutmgr;
-import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
public class LineLayoutPossibilities {
+ /** logger instance */
+ protected static Log log = LogFactory.getLog(LineLayoutPossibilities.class);
+
private class Possibility {
- private int lineNumber;
+ private int lineCount;
private double demerits;
- private ArrayList breakPositions;
+ private List breakPositions;
- private Possibility(int ln, double dem) {
- lineNumber = ln;
+ private Possibility(int lc, double dem) {
+ lineCount = lc;
demerits = dem;
- breakPositions = new ArrayList(ln);
+ breakPositions = new java.util.ArrayList(lc);
}
- private int getLineNumber() {
- return lineNumber;
+ private int getLineCount() {
+ return lineCount;
}
private double getDemerits() {
}
}
- private ArrayList possibilitiesList;
- private ArrayList savedPossibilities;
+ private List possibilitiesList;
+ private List savedPossibilities;
private int minimumIndex;
private int optimumIndex;
private int maximumIndex;
private int chosenIndex;
- private int savedOptLineNumber;
+ private int savedOptLineCount;
public LineLayoutPossibilities() {
- possibilitiesList = new ArrayList();
- savedPossibilities = new ArrayList();
+ possibilitiesList = new java.util.ArrayList();
+ savedPossibilities = new java.util.ArrayList();
optimumIndex = -1;
}
optimumIndex = possibilitiesList.size() - 1;
chosenIndex = optimumIndex;
}
- if (ln < ((Possibility)possibilitiesList.get(minimumIndex)).getLineNumber()) {
+ if (ln < ((Possibility)possibilitiesList.get(minimumIndex)).getLineCount()) {
minimumIndex = possibilitiesList.size() - 1;
}
- if (ln > ((Possibility)possibilitiesList.get(maximumIndex)).getLineNumber()) {
+ if (ln > ((Possibility)possibilitiesList.get(maximumIndex)).getLineCount()) {
maximumIndex = possibilitiesList.size() - 1;
}
}
/* save in a different array the computed Possibilities,
* so possibilitiesList is ready to store different Possibilities
*/
- public void savePossibilities(boolean bSaveOptLineNumber) {
- if (bSaveOptLineNumber) {
- savedOptLineNumber = getOptLineNumber();
+ public void savePossibilities(boolean bSaveOptLineCount) {
+ if (bSaveOptLineCount) {
+ savedOptLineCount = getOptLineCount();
} else {
- savedOptLineNumber = 0;
+ savedOptLineCount = 0;
}
savedPossibilities = possibilitiesList;
- possibilitiesList = new ArrayList();
+ possibilitiesList = new java.util.ArrayList();
}
/* replace the Possibilities stored in possibilitiesList with
int index = 0;
while (savedPossibilities.size() > 0) {
Possibility restoredPossibility = (Possibility) savedPossibilities.remove(0);
- if (restoredPossibility.getLineNumber() < getMinLineNumber()) {
+ if (restoredPossibility.getLineCount() < getMinLineCount()) {
// if the line number of restoredPossibility is less than the minimum one,
// add restoredPossibility at the beginning of the list
possibilitiesList.add(0, restoredPossibility);
optimumIndex ++;
maximumIndex ++;
chosenIndex ++;
- } else if (restoredPossibility.getLineNumber() > getMaxLineNumber()) {
+ } else if (restoredPossibility.getLineCount() > getMaxLineCount()) {
// if the line number of restoredPossibility is greater than the maximum one,
// add restoredPossibility at the end of the list
possibilitiesList.add(possibilitiesList.size(), restoredPossibility);
} else {
// find the index of the Possibility that will be replaced
while (index < maximumIndex
- && getLineNumber(index) < restoredPossibility.getLineNumber()) {
+ && getLineCount(index) < restoredPossibility.getLineCount()) {
index ++;
}
- if (getLineNumber(index) == restoredPossibility.getLineNumber()) {
+ if (getLineCount(index) == restoredPossibility.getLineCount()) {
possibilitiesList.set(index, restoredPossibility);
} else {
// this should not happen
-/*LF*/ System.out.println("ERRORE: LineLayoutPossibilities restorePossibilities(), min= " + getMinLineNumber() + " max= " + getMaxLineNumber() + " restored= " + restoredPossibility.getLineNumber());
+ log.error("LineLayoutPossibilities restorePossibilities(),"
+ + " min= " + getMinLineCount()
+ + " max= " + getMaxLineCount()
+ + " restored= " + restoredPossibility.getLineCount());
return;
}
}
// update optimumIndex and chosenIndex
- if (savedOptLineNumber == 0 && getDemerits(optimumIndex) > restoredPossibility.getDemerits()
- || savedOptLineNumber != 0 && restoredPossibility.getLineNumber() == savedOptLineNumber) {
+ if (savedOptLineCount == 0 && getDemerits(optimumIndex) > restoredPossibility.getDemerits()
+ || savedOptLineCount != 0 && restoredPossibility.getLineCount() == savedOptLineCount) {
optimumIndex = index;
chosenIndex = optimumIndex;
}
}
-/*LF*/ //System.out.println(">> minLineNumber = " + getMinLineNumber() + " optLineNumber = " + getOptLineNumber() + " maxLineNumber() = " + getMaxLineNumber());
+/*LF*/ //System.out.println(">> minLineCount = " + getMinLineCount() + " optLineCount = " + getOptLineCount() + " maxLineCount() = " + getMaxLineCount());
}
public void addBreakPosition(Position pos, int i) {
}
public boolean canUseMoreLines() {
- return (getOptLineNumber() < getMaxLineNumber());
+ return (getOptLineCount() < getMaxLineCount());
}
public boolean canUseLessLines() {
- return (getMinLineNumber() < getOptLineNumber());
+ return (getMinLineCount() < getOptLineCount());
}
- public int getMinLineNumber() {
- return getLineNumber(minimumIndex);
+ public int getMinLineCount() {
+ return getLineCount(minimumIndex);
}
- public int getOptLineNumber() {
- return getLineNumber(optimumIndex);
+ public int getOptLineCount() {
+ return getLineCount(optimumIndex);
}
- public int getMaxLineNumber() {
- return getLineNumber(maximumIndex);
+ public int getMaxLineCount() {
+ return getLineCount(maximumIndex);
}
- public int getChosenLineNumber() {
- return getLineNumber(chosenIndex);
+ public int getChosenLineCount() {
+ return getLineCount(chosenIndex);
}
- public int getLineNumber(int i) {
- return ((Possibility)possibilitiesList.get(i)).getLineNumber();
+ public int getLineCount(int i) {
+ return ((Possibility)possibilitiesList.get(i)).getLineCount();
}
public double getChosenDemerits() {
return ((Possibility)possibilitiesList.get(chosenIndex)).getBreakPosition(i);
}
- public int applyLineNumberAdjustment(int adj) {
- if (adj >= (getMinLineNumber() - getChosenLineNumber())
- && adj <= (getMaxLineNumber() - getChosenLineNumber())
- && getLineNumber(chosenIndex + adj) == getChosenLineNumber() + adj) {
+ public int applyLineCountAdjustment(int adj) {
+ if (adj >= (getMinLineCount() - getChosenLineCount())
+ && adj <= (getMaxLineCount() - getChosenLineCount())
+ && getLineCount(chosenIndex + adj) == getChosenLineCount() + adj) {
chosenIndex += adj;
- System.out.println("chosenLineNumber= " + (getChosenLineNumber() - adj) + " variazione= " + adj
- + " => chosenLineNumber= " + getLineNumber(chosenIndex));
+ log.debug("chosenLineCount= " + (getChosenLineCount() - adj) + " adjustment= " + adj
+ + " => chosenLineCount= " + getLineCount(chosenIndex));
return adj;
} else {
// this should not happen!
- System.out.println("Cannot apply the desired line number adjustment");
+ log.warn("Cannot apply the desired line count adjustment.");
return 0;
}
}
public void printAll() {
System.out.println("++++++++++");
- System.out.println(" " + possibilitiesList.size() + " possibilita':");
+ System.out.println(" " + possibilitiesList.size() + " possibility':");
for (int i = 0; i < possibilitiesList.size(); i ++) {
- System.out.println(" " + ((Possibility)possibilitiesList.get(i)).getLineNumber()
+ System.out.println(" " + ((Possibility)possibilitiesList.get(i)).getLineCount()
+ (i == optimumIndex ? " *" : "")
+ (i == minimumIndex ? " -" : "")
+ (i == maximumIndex ? " +" : ""));