oldList.addLast(new KnuthBox(adjustedSpaceAfter,
new Position(lm), true));
bAddedBoxAfter = true;
}
MinOptMax totalLength = new MinOptMax(0);
MinOptMax totalUnits = new MinOptMax(0);
LinkedList newList = new LinkedList();
//log.debug(" Prima scansione");
// scan the list once to compute total min, opt and max length
ListIterator oldListIterator = oldList.listIterator();
while (oldListIterator.hasNext()) {
KnuthElement element = (KnuthElement) oldListIterator.next();
if (element.isBox()) {
totalLength.add(new MinOptMax(element.getW()));
//log.debug("box " + element.getW());
} else if (element.isGlue()) {
totalLength.min -= ((KnuthGlue) element).getZ();
totalLength.max += ((KnuthGlue) element).getY();
//leafValue = ((LeafPosition) element.getPosition()).getLeafPos();
//log.debug("glue " + element.getW() + " + "
// + ((KnuthGlue) element).getY() + " - " + ((KnuthGlue) element).getZ());
} else {
//log.debug((((KnuthPenalty)element).getP() == KnuthElement.INFINITE
// ? "PENALTY " : "penalty ") + element.getW());
}
}
// compute the total amount of "units"
totalUnits = new MinOptMax(neededUnits(totalLength.min),
neededUnits(totalLength.opt),
neededUnits(totalLength.max));
//log.debug(" totalLength= " + totalLength);
//log.debug(" unita'= " + totalUnits);
//log.debug(" Seconda scansione");
// scan the list once more, stopping at every breaking point
// in order to compute partial min, opt and max length
// and create the new elements
oldListIterator = oldList.listIterator();
boolean bPrevIsBox = false;
MinOptMax lengthBeforeBreak = new MinOptMax(0);
MinOptMax lengthAfterBreak = (MinOptMax) totalLength.clone();
MinOptMax unitsBeforeBreak;
MinOptMax unitsAfterBreak;
MinOptMax unsuppressibleUnits = new MinOptMax(0);
int firstIndex = 0;
int lastIndex = -1;
while (oldListIterator.hasNext()) {
KnuthElement element = (KnuthElement) oldListIterator.next();
lastIndex++;
if (element.isBox()) {
lengthBeforeBreak.add(new MinOptMax(element.getW()));
lengthAfterBreak.subtract(new MinOptMax(element.getW()));
bPrevIsBox = true;
} else if (element.isGlue()) {
lengthBeforeBreak.min -= ((KnuthGlue) element).getZ();
lengthAfterBreak.min += ((KnuthGlue) element).getZ();
lengthBeforeBreak.max += ((KnuthGlue) element).getY();
lengthAfterBreak.max -= ((KnuthGlue) element).getY();
bPrevIsBox = false;
} else {
lengthBeforeBreak.add(new MinOptMax(element.getW()));
bPrevIsBox = false;
}
// create the new elements
if (element.isPenalty() && ((KnuthPenalty) element).getP() < KnuthElement.INFINITE
|| element.isGlue() && bPrevIsBox
|| !oldListIterator.hasNext()) {
// suppress elements after the breaking point
int iStepsForward = 0;
while (oldListIterator.hasNext()) {
KnuthElement el = (KnuthElement) oldListIterator.next();
iStepsForward++;
if (el.isGlue()) {
// suppressed glue
lengthAfterBreak.min += ((KnuthGlue) el).getZ();
lengthAfterBreak.max -= ((KnuthGlue) el).getY();
} else if (el.isPenalty()) {
// suppressed penalty, do nothing
} else {
// box, end of suppressions
break;
}
}
// compute the partial amount of "units" before and after the break
unitsBeforeBreak = new MinOptMax(neededUnits(lengthBeforeBreak.min),
neededUnits(lengthBeforeBreak.opt),
neededUnits(lengthBeforeBreak.max));
unitsAfterBreak = new MinOptMax(neededUnits(lengthAfterBreak.min),
neededUnits(lengthAfterBreak.opt),
neededUnits(lengthAfterBreak.max));
// rewind the iterator and lengthAfterBreak
for (int i = 0; i < iStepsForward; i++) {
KnuthElement el = (KnuthElement) oldListIterator.previous();
if (el.isGlue()) {
lengthAfterBreak.min -= ((KnuthGlue) el).getZ();
lengthAfterBreak.max += ((KnuthGlue) el).getY();
}
}
// compute changes in length, stretch and shrink
int uLengthChange = unitsBeforeBreak.opt + unitsAfterBreak.opt - totalUnits.opt;
int uStretchChange = (unitsBeforeBreak.max + unitsAfterBreak.max - totalUnits.max)
- (unitsBeforeBreak.opt + unitsAfterBreak.opt - totalUnits.opt);
int uShrinkChange = (unitsBeforeBreak.opt + unitsAfterBreak.opt - totalUnits.opt)
- (unitsBeforeBreak.min + unitsAfterBreak.min - totalUnits.min);
// compute the number of normal, stretch and shrink unit
// that must be added to the new sequence
int uNewNormal = unitsBeforeBreak.opt - unsuppressibleUnits.opt;
int uNewStretch = (unitsBeforeBreak.max - unitsBeforeBreak.opt)
- (unsuppressibleUnits.max - unsuppressibleUnits.opt);
int uNewShrink = (unitsBeforeBreak.opt - unitsBeforeBreak.min)
- (unsuppressibleUnits.opt - unsuppressibleUnits.min);
//log.debug("("
// + unsuppressibleUnits.min + "-" + unsuppressibleUnits.opt + "-"
// + unsuppressibleUnits.max + ") "
// + " -> " + unitsBeforeBreak.min + "-" + unitsBeforeBreak.opt + "-"
// + unitsBeforeBreak.max
// + " + " + unitsAfterBreak.min + "-" + unitsAfterBreak.opt + "-"
// + unitsAfterBreak.max
// + (uLengthChange != 0 ? " [length " + uLengthChange + "] " : "")
// + (uStretchChange != 0 ? " [stretch " + uStretchChange + "] " : "")
// + (uShrinkChange != 0 ? " [shrink " + uShrinkChange + "]" : ""));
// create the MappingPosition which will be stored in the new elements
// correct firstIndex and lastIndex
int firstIndexCorrection = 0;
int lastIndexCorrection = 0;
if (bAddedBoxBefore) {
if (firstIndex != 0) {
firstIndexCorrection++;
}
lastIndexCorrection++;
}
if (bAddedBoxAfter && lastIndex == (oldList.size() - 1)) {
lastIndexCorrection++;
}
MappingPosition mappingPos = new MappingPosition(this,
firstIndex - firstIndexCorrection,
lastIndex - lastIndexCorrection);
// new box
newList.add(new KnuthBox((uNewNormal - uLengthChange) * bpUnit,
mappingPos,
false));
unsuppressibleUnits.add(new MinOptMax(uNewNormal - uLengthChange));
//log.debug(" box " + (uNewNormal - uLengthChange));
// new infinite penalty, glue and box, if necessary
if (uNewStretch - uStretchChange > 0
|| uNewShrink - uShrinkChange > 0) {
int iStretchUnits = (uNewStretch - uStretchChange > 0
? (uNewStretch - uStretchChange) : 0);
int iShrinkUnits = (uNewShrink - uShrinkChange > 0
? (uNewShrink - uShrinkChange) : 0);
newList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false,
mappingPos,
false));
newList.add(new KnuthGlue(0,
iStretchUnits * bpUnit,
iShrinkUnits * bpUnit,
LINE_NUMBER_ADJUSTMENT,
mappingPos,
false));
//log.debug(" PENALTY");
//log.debug(" glue 0 " + iStretchUnits + " " + iShrinkUnits);
unsuppressibleUnits.max += iStretchUnits;
unsuppressibleUnits.min -= iShrinkUnits;
if (!oldListIterator.hasNext()) {
newList.add(new KnuthBox(0,
mappingPos,
false));
//log.debug(" box 0");
}
}
// new breaking sequence
if (uStretchChange != 0
|| uShrinkChange != 0) {
// new infinite penalty, glue, penalty and glue
newList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false,
mappingPos,
false));
newList.add(new KnuthGlue(0,
uStretchChange * bpUnit,
uShrinkChange * bpUnit,
LINE_NUMBER_ADJUSTMENT,
mappingPos,
false));
newList.add(new KnuthPenalty(uLengthChange * bpUnit,
0, false, element.getPosition(), false));
newList.add(new KnuthGlue(0,
-uStretchChange * bpUnit,
-uShrinkChange * bpUnit,
LINE_NUMBER_ADJUSTMENT,
mappingPos,
false));
//log.debug(" PENALTY");
//log.debug(" glue 0 " + uStretchChange + " " + uShrinkChange);
//log.debug(" penalty " + uLengthChange + " * unit");
//log.debug(" glue 0 " + (- uStretchChange) + " "
// + (- uShrinkChange));
} else if (oldListIterator.hasNext()) {
// new penalty
newList.add(new KnuthPenalty(uLengthChange * bpUnit,
0, false,
mappingPos,
false));
//log.debug(" penalty " + uLengthChange + " * unit");
}
// update firstIndex
firstIndex = lastIndex + 1;
}
if (element.isPenalty()) {
lengthBeforeBreak.add(new MinOptMax(-element.getW()));
}
}
// remove elements at the beginning and at the end of oldList