in fop-core/src/main/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java [262:425]
public List getNextKnuthElements(
LayoutContext context, int alignment) {
LayoutManager curLM;
// the list returned by child LM
List<KnuthSequence> returnedList;
// the list which will be returned to the parent LM
List<KnuthSequence> returnList = new LinkedList<KnuthSequence>();
KnuthSequence lastSequence = null;
if (fobj instanceof Title) {
alignmentContext = new AlignmentContext(font,
lineHeight.getOptimum(this).getLength().getValue(this),
context.getWritingMode());
} else {
alignmentContext = new AlignmentContext(font
, lineHeight.getOptimum(this).getLength().getValue(this)
, alignmentAdjust
, alignmentBaseline
, baselineShift
, dominantBaseline
, context.getAlignmentContext());
}
childLC = LayoutContext.copyOf(context);
childLC.setAlignmentContext(alignmentContext);
if (context.startsNewArea()) {
// First call to this LM in new parent "area", but this may
// not be the first area created by this inline
if (getSpaceStart() != null) {
context.getLeadingSpace().addSpace(new SpaceVal(getSpaceStart(), this));
}
}
StringBuffer trace = new StringBuffer("InlineLM:");
// We'll add the border to the first inline sequence created.
// This flag makes sure we do it only once.
boolean borderAdded = false;
if (borderProps != null) {
childLC.setLineStartBorderAndPaddingWidth(context.getLineStartBorderAndPaddingWidth()
+ borderProps.getPaddingStart(true, this)
+ borderProps.getBorderStartWidth(true)
);
childLC.setLineEndBorderAndPaddingWidth(context.getLineEndBorderAndPaddingWidth()
+ borderProps.getPaddingEnd(true, this)
+ borderProps.getBorderEndWidth(true)
);
}
while ((curLM = getChildLM()) != null) {
if (!(curLM instanceof InlineLevelLayoutManager)) {
// A block LM
// Leave room for start/end border and padding
if (borderProps != null) {
childLC.setRefIPD(childLC.getRefIPD()
- borderProps.getPaddingStart(lastChildLM != null, this)
- borderProps.getBorderStartWidth(lastChildLM != null)
- borderProps.getPaddingEnd(hasNextChildLM(), this)
- borderProps.getBorderEndWidth(hasNextChildLM()));
}
}
// get KnuthElements from curLM
returnedList = curLM.getNextKnuthElements(childLC, alignment);
if (returnList.isEmpty() && childLC.isKeepWithPreviousPending()) {
childLC.clearKeepWithPreviousPending();
}
if (returnedList == null
|| returnedList.isEmpty()) {
// curLM returned null or an empty list, because it finished;
// just iterate once more to see if there is another child
continue;
}
if (curLM instanceof InlineLevelLayoutManager) {
context.clearKeepWithNextPending();
// "wrap" the Position stored in each element of returnedList
for (KnuthSequence sequence : returnedList) {
sequence.wrapPositions(this);
}
int insertionStartIndex = 0;
if (lastSequence != null
&& lastSequence.appendSequenceOrClose(returnedList.get(0))) {
insertionStartIndex = 1;
}
// add border and padding to the first complete sequence of this LM
if (!borderAdded && !returnedList.isEmpty()) {
addKnuthElementsForBorderPaddingStart(returnedList.get(0));
borderAdded = true;
}
for (Iterator<KnuthSequence> iter = returnedList.listIterator(insertionStartIndex);
iter.hasNext();) {
returnList.add(iter.next());
}
} else { // A block LM
BlockKnuthSequence sequence = new BlockKnuthSequence(returnedList);
sequence.wrapPositions(this);
boolean appended = false;
if (lastSequence != null) {
if (lastSequence.canAppendSequence(sequence)) {
BreakElement bk = new BreakElement(new Position(this), 0, context);
boolean keepTogether = (mustKeepTogether()
|| context.isKeepWithNextPending()
|| childLC.isKeepWithPreviousPending());
appended = lastSequence.appendSequenceOrClose(sequence, keepTogether, bk);
} else {
lastSequence.endSequence();
}
}
if (!appended) {
// add border and padding to the first complete sequence of this LM
if (!borderAdded) {
addKnuthElementsForBorderPaddingStart(sequence);
borderAdded = true;
}
returnList.add(sequence);
}
// propagate and clear
context.updateKeepWithNextPending(childLC.getKeepWithNextPending());
childLC.clearKeepsPending();
}
lastSequence = ListUtil.getLast(returnList);
lastChildLM = curLM;
// the context used to create this childLC above was applied a LayoutContext.SUPPRESS_BREAK_BEFORE
// in the getNextChildElements() method of the parent BlockLayoutManger; as a consequence all
// line breaks in blocks nested inside the inline associated with this ILM are being supressed;
// here we revert that supression; we do not need to do that for the first element since that
// is handled by the getBreakBefore() method of the wrapping BlockStackingLayoutManager.
// Note: this fix seems to work but is far from being the ideal way to do this
childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE, false);
}
if (lastSequence != null) {
addKnuthElementsForBorderPaddingEnd(lastSequence);
}
setFinished(true);
log.trace(trace);
if (returnList.isEmpty()) {
/*
* if the FO itself is empty, but has an id specified
* or associated fo:markers, then we still need a dummy
* sequence to register its position in the area tree
*/
if (fobj.hasId() || fobj.hasMarkers()) {
InlineKnuthSequence emptySeq = new InlineKnuthSequence();
emptySeq.add(new KnuthInlineBox(
0,
alignmentContext,
notifyPos(getAuxiliaryPosition()),
true));
returnList.add(emptySeq);
}
}
return returnList.isEmpty() ? null : returnList;
}