123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722 |
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.List;
- import java.util.ListIterator;
-
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
-
- import org.apache.fop.traits.MinOptMax;
-
- /**
- * This class resolves spaces and conditional borders and paddings by replacing the
- * UnresolvedListElements descendants by the right combination of KnuthElements on an element
- * list.
- */
- public final class SpaceResolver {
-
- /** Logger instance */
- private static final Log LOG = LogFactory.getLog(SpaceResolver.class);
-
- private UnresolvedListElementWithLength[] firstPart;
- private BreakElement breakPoss;
- private UnresolvedListElementWithLength[] secondPart;
- private UnresolvedListElementWithLength[] noBreak;
-
- private MinOptMax[] firstPartLengths;
- private MinOptMax[] secondPartLengths;
- private MinOptMax[] noBreakLengths;
-
- private boolean isFirst;
- private boolean isLast;
-
- /**
- * Main constructor.
- * @param first Element list before a break (optional)
- * @param breakPoss Break possibility (optional)
- * @param second Element list after a break (or if no break possibility in vicinity)
- * @param isFirst Resolution at the beginning of a (full) element list
- * @param isLast Resolution at the end of a (full) element list
- */
- private SpaceResolver(List first, BreakElement breakPoss, List second,
- boolean isFirst, boolean isLast) {
- this.isFirst = isFirst;
- this.isLast = isLast;
- //Create combined no-break list
- int c = 0;
- if (first != null) {
- c += first.size();
- }
- if (second != null) {
- c += second.size();
- }
- noBreak = new UnresolvedListElementWithLength[c];
- noBreakLengths = new MinOptMax[c];
- int i = 0;
- ListIterator iter;
- if (first != null) {
- iter = first.listIterator();
- while (iter.hasNext()) {
- noBreak[i] = (UnresolvedListElementWithLength)iter.next();
- noBreakLengths[i] = noBreak[i].getLength();
- i++;
- }
- }
- if (second != null) {
- iter = second.listIterator();
- while (iter.hasNext()) {
- noBreak[i] = (UnresolvedListElementWithLength)iter.next();
- noBreakLengths[i] = noBreak[i].getLength();
- i++;
- }
- }
-
- //Add pending elements from higher level FOs
- if (breakPoss != null) {
- if (breakPoss.getPendingAfterMarks() != null) {
- if (LOG.isTraceEnabled()) {
- LOG.trace(" adding pending before break: "
- + breakPoss.getPendingAfterMarks());
- }
- first.addAll(0, breakPoss.getPendingAfterMarks());
- }
- if (breakPoss.getPendingBeforeMarks() != null) {
- if (LOG.isTraceEnabled()) {
- LOG.trace(" adding pending after break: "
- + breakPoss.getPendingBeforeMarks());
- }
- second.addAll(0, breakPoss.getPendingBeforeMarks());
- }
- }
- if (LOG.isTraceEnabled()) {
- LOG.trace("before: " + first);
- LOG.trace(" break: " + breakPoss);
- LOG.trace("after: " + second);
- LOG.trace("NO-BREAK: " + toString(noBreak, noBreakLengths));
- }
-
- if (first != null) {
- firstPart = new UnresolvedListElementWithLength[first.size()];
- firstPartLengths = new MinOptMax[firstPart.length];
- first.toArray(firstPart);
- for (i = 0; i < firstPart.length; i++) {
- firstPartLengths[i] = firstPart[i].getLength();
- }
- }
- this.breakPoss = breakPoss;
- if (second != null) {
- secondPart = new UnresolvedListElementWithLength[second.size()];
- secondPartLengths = new MinOptMax[secondPart.length];
- second.toArray(secondPart);
- for (i = 0; i < secondPart.length; i++) {
- secondPartLengths[i] = secondPart[i].getLength();
- }
- }
- resolve();
- }
-
- private String toString(Object[] arr1, Object[] arr2) {
- if (arr1.length != arr2.length) {
- throw new IllegalArgumentException("The length of both arrays must be equal");
- }
- StringBuffer sb = new StringBuffer("[");
- for (int i = 0; i < arr1.length; i++) {
- if (i > 0) {
- sb.append(", ");
- }
- sb.append(String.valueOf(arr1[i]));
- sb.append("/");
- sb.append(String.valueOf(arr2[i]));
- }
- sb.append("]");
- return sb.toString();
- }
-
- private void removeConditionalBorderAndPadding(
- UnresolvedListElement[] elems, MinOptMax[] lengths, boolean reverse) {
- for (int i = 0; i < elems.length; i++) {
- int effIndex;
- if (reverse) {
- effIndex = elems.length - 1 - i;
- } else {
- effIndex = i;
- }
- if (elems[effIndex] instanceof BorderOrPaddingElement) {
- BorderOrPaddingElement bop = (BorderOrPaddingElement)elems[effIndex];
- if (bop.isConditional() && !(bop.isFirst() || bop.isLast())) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Nulling conditional element: " + bop);
- }
- lengths[effIndex] = null;
- }
- }
- }
- if (LOG.isTraceEnabled() && elems.length > 0) {
- LOG.trace("-->Resulting list: " + toString(elems, lengths));
- }
- }
-
- private void performSpaceResolutionRule1(UnresolvedListElement[] elems, MinOptMax[] lengths,
- boolean reverse) {
- for (int i = 0; i < elems.length; i++) {
- int effIndex;
- if (reverse) {
- effIndex = elems.length - 1 - i;
- } else {
- effIndex = i;
- }
- if (lengths[effIndex] == null) {
- //Zeroed border or padding doesn't create a fence
- continue;
- } else if (elems[effIndex] instanceof BorderOrPaddingElement) {
- //Border or padding form fences!
- break;
- } else if (!elems[effIndex].isConditional()) {
- break;
- }
- if (LOG.isDebugEnabled()) {
- LOG.debug("Nulling conditional element using 4.3.1, rule 1: " + elems[effIndex]);
- }
- lengths[effIndex] = null;
- }
- if (LOG.isTraceEnabled() && elems.length > 0) {
- LOG.trace("-->Resulting list: " + toString(elems, lengths));
- }
- }
-
- private void performSpaceResolutionRules2to3(UnresolvedListElement[] elems,
- MinOptMax[] lengths, int start, int end) {
- if (LOG.isTraceEnabled()) {
- LOG.trace("rule 2-3: " + start + "-" + end);
- }
- SpaceElement space;
- int remaining;
-
- //Rule 2 (4.3.1, XSL 1.0)
- boolean hasForcing = false;
- remaining = 0;
- for (int i = start; i <= end; i++) {
- if (lengths[i] == null) {
- continue;
- }
- remaining++;
- space = (SpaceElement)elems[i];
- if (space.isForcing()) {
- hasForcing = true;
- break;
- }
- }
- if (remaining == 0) {
- return; //shortcut
- }
- if (hasForcing) {
- for (int i = start; i <= end; i++) {
- if (lengths[i] == null) {
- continue;
- }
- space = (SpaceElement)elems[i];
- if (!space.isForcing()) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Nulling non-forcing space-specifier using 4.3.1, rule 2: "
- + elems[i]);
- }
- lengths[i] = null;
- }
- }
- return; //If rule is triggered skip rule 3
- }
-
- //Rule 3 (4.3.1, XSL 1.0)
- //Determine highes precedence
- int highestPrecedence = Integer.MIN_VALUE;
- for (int i = start; i <= end; i++) {
- if (lengths[i] == null) {
- continue;
- }
- space = (SpaceElement)elems[i];
- highestPrecedence = Math.max(highestPrecedence, space.getPrecedence());
- }
- if (highestPrecedence != 0 && LOG.isDebugEnabled()) {
- LOG.debug("Highest precedence is " + highestPrecedence);
- }
- //Suppress space-specifiers with lower precedence
- remaining = 0;
- int greatestOptimum = Integer.MIN_VALUE;
- for (int i = start; i <= end; i++) {
- if (lengths[i] == null) {
- continue;
- }
- space = (SpaceElement)elems[i];
- if (space.getPrecedence() != highestPrecedence) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Nulling space-specifier with precedence "
- + space.getPrecedence() + " using 4.3.1, rule 3: "
- + elems[i]);
- }
- lengths[i] = null;
- } else {
- greatestOptimum = Math.max(greatestOptimum, space.getLength().getOpt());
- remaining++;
- }
- }
- if (LOG.isDebugEnabled()) {
- LOG.debug("Greatest optimum: " + greatestOptimum);
- }
- if (remaining <= 1) {
- return;
- }
- //Suppress space-specifiers with smaller optimum length
- remaining = 0;
- for (int i = start; i <= end; i++) {
- if (lengths[i] == null) {
- continue;
- }
- space = (SpaceElement)elems[i];
- if (space.getLength().getOpt() < greatestOptimum) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Nulling space-specifier with smaller optimum length "
- + "using 4.3.1, rule 3: "
- + elems[i]);
- }
- lengths[i] = null;
- } else {
- remaining++;
- }
- }
- if (remaining <= 1) {
- return;
- }
- //Construct resolved space-specifier from the remaining spaces
- int min = Integer.MIN_VALUE;
- int max = Integer.MAX_VALUE;
- for (int i = start; i <= end; i++) {
- if (lengths[i] == null) {
- continue;
- }
- space = (SpaceElement)elems[i];
- min = Math.max(min, space.getLength().getMin());
- max = Math.min(max, space.getLength().getMax());
- if (remaining > 1) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Nulling non-last space-specifier using 4.3.1, rule 3, second part: "
- + elems[i]);
- }
- lengths[i] = null;
- remaining--;
- } else {
- lengths[i] = MinOptMax.getInstance(min, lengths[i].getOpt(), max);
- }
- }
-
- if (LOG.isTraceEnabled() && elems.length > 0) {
- LOG.trace("Remaining spaces: " + remaining);
- LOG.trace("-->Resulting list: " + toString(elems, lengths));
- }
- }
-
- private void performSpaceResolutionRules2to3(UnresolvedListElement[] elems,
- MinOptMax[] lengths) {
- int start = 0;
- int i = start;
- while (i < elems.length) {
- if (elems[i] instanceof SpaceElement) {
- while (i < elems.length) {
- if (elems[i] == null || elems[i] instanceof SpaceElement) {
- i++;
- } else {
- break;
- }
- }
- performSpaceResolutionRules2to3(elems, lengths, start, i - 1);
- }
- i++;
- start = i;
- }
- }
-
- private boolean hasFirstPart() {
- return firstPart != null && firstPart.length > 0;
- }
-
- private boolean hasSecondPart() {
- return secondPart != null && secondPart.length > 0;
- }
-
- private void resolve() {
- if (breakPoss != null) {
- if (hasFirstPart()) {
- removeConditionalBorderAndPadding(firstPart, firstPartLengths, true);
- performSpaceResolutionRule1(firstPart, firstPartLengths, true);
- performSpaceResolutionRules2to3(firstPart, firstPartLengths);
- }
- if (hasSecondPart()) {
- removeConditionalBorderAndPadding(secondPart, secondPartLengths, false);
- performSpaceResolutionRule1(secondPart, secondPartLengths, false);
- performSpaceResolutionRules2to3(secondPart, secondPartLengths);
- }
- if (noBreak != null) {
- performSpaceResolutionRules2to3(noBreak, noBreakLengths);
- }
- } else {
- if (isFirst) {
- removeConditionalBorderAndPadding(secondPart, secondPartLengths, false);
- performSpaceResolutionRule1(secondPart, secondPartLengths, false);
- }
- if (isLast) {
- removeConditionalBorderAndPadding(firstPart, firstPartLengths, true);
- performSpaceResolutionRule1(firstPart, firstPartLengths, true);
- }
-
- if (hasFirstPart()) {
- //Now that we've handled isFirst/isLast conditions, we need to look at the
- //active part in its normal order so swap it back.
- LOG.trace("Swapping first and second parts.");
- UnresolvedListElementWithLength[] tempList;
- MinOptMax[] tempLengths;
- tempList = secondPart;
- tempLengths = secondPartLengths;
- secondPart = firstPart;
- secondPartLengths = firstPartLengths;
- firstPart = tempList;
- firstPartLengths = tempLengths;
- if (hasFirstPart()) {
- throw new IllegalStateException("Didn't expect more than one parts in a"
- + "no-break condition.");
- }
- }
- performSpaceResolutionRules2to3(secondPart, secondPartLengths);
- }
- }
-
- private MinOptMax sum(MinOptMax[] lengths) {
- MinOptMax sum = MinOptMax.ZERO;
- for (MinOptMax length : lengths) {
- if (length != null) {
- sum = sum.plus(length);
- }
- }
- return sum;
- }
-
- private void generate(ListIterator iter) {
- MinOptMax spaceBeforeBreak = sum(firstPartLengths);
- MinOptMax spaceAfterBreak = sum(secondPartLengths);
-
- boolean hasPrecedingNonBlock = false;
- if (breakPoss != null) {
- if (spaceBeforeBreak.isNonZero()) {
- iter.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, null, true));
- iter.add(new KnuthGlue(spaceBeforeBreak, null, true));
- if (breakPoss.isForcedBreak()) {
- //Otherwise, the preceding penalty and glue will be cut off
- iter.add(new KnuthBox(0, null, true));
- }
- }
- iter.add(new KnuthPenalty(breakPoss.getPenaltyWidth(), breakPoss.getPenaltyValue(),
- false, breakPoss.getBreakClass(),
- new SpaceHandlingBreakPosition(this, breakPoss), false));
- if (breakPoss.getPenaltyValue() <= -KnuthPenalty.INFINITE) {
- return; //return early. Not necessary (even wrong) to add additional elements
- }
-
- // No break
- // TODO: We can't use a MinOptMax for glue2,
- // because min <= opt <= max is not always true - why?
- MinOptMax noBreakLength = sum(noBreakLengths);
- MinOptMax spaceSum = spaceBeforeBreak.plus(spaceAfterBreak);
- int glue2width = noBreakLength.getOpt() - spaceSum.getOpt();
- int glue2stretch = noBreakLength.getStretch() - spaceSum.getStretch();
- int glue2shrink = noBreakLength.getShrink() - spaceSum.getShrink();
-
- if (glue2width != 0 || glue2stretch != 0 || glue2shrink != 0) {
- iter.add(new KnuthGlue(glue2width, glue2stretch, glue2shrink, null, true));
- }
- } else {
- if (spaceBeforeBreak.isNonZero()) {
- throw new IllegalStateException("spaceBeforeBreak should be 0 in this case");
- }
- }
- Position pos = null;
- if (breakPoss == null) {
- pos = new SpaceHandlingPosition(this);
- }
- if (spaceAfterBreak.isNonZero() || pos != null) {
- iter.add(new KnuthBox(0, pos, true));
- }
- if (spaceAfterBreak.isNonZero()) {
- iter.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, null, true));
- iter.add(new KnuthGlue(spaceAfterBreak, null, true));
- hasPrecedingNonBlock = true;
- }
- if (isLast && hasPrecedingNonBlock) {
- //Otherwise, the preceding penalty and glue will be cut off
- iter.add(new KnuthBox(0, null, true));
- }
- }
-
- /**
- * Position class for break possibilities. It is used to notify layout manager about the
- * effective spaces and conditional lengths.
- */
- public static class SpaceHandlingBreakPosition extends Position {
-
- private SpaceResolver resolver;
- private Position originalPosition;
-
- /**
- * Main constructor.
- * @param resolver the space resolver that provides the info about the actual situation
- * @param breakPoss the original break possibility that creates this Position
- */
- public SpaceHandlingBreakPosition(SpaceResolver resolver, BreakElement breakPoss) {
- super(null);
- this.resolver = resolver;
- this.originalPosition = breakPoss.getPosition();
- //Unpack since the SpaceHandlingBreakPosition is a non-wrapped Position, too
- while (this.originalPosition instanceof NonLeafPosition) {
- this.originalPosition = this.originalPosition.getPosition();
- }
- }
-
- /** @return the space resolver */
- public SpaceResolver getSpaceResolver() {
- return this.resolver;
- }
-
- /**
- * Notifies all affected layout managers about the current situation in the part to be
- * handled for area generation.
- * @param isBreakSituation true if this is a break situation.
- * @param side defines to notify about the situation whether before or after the break.
- * May be null if isBreakSituation is null.
- */
- public void notifyBreakSituation(boolean isBreakSituation, RelSide side) {
- if (isBreakSituation) {
- if (RelSide.BEFORE == side) {
- for (int i = 0; i < resolver.secondPart.length; i++) {
- resolver.secondPart[i].notifyLayoutManager(resolver.secondPartLengths[i]);
- }
- } else {
- for (int i = 0; i < resolver.firstPart.length; i++) {
- resolver.firstPart[i].notifyLayoutManager(resolver.firstPartLengths[i]);
- }
- }
- } else {
- for (int i = 0; i < resolver.noBreak.length; i++) {
- resolver.noBreak[i].notifyLayoutManager(resolver.noBreakLengths[i]);
- }
- }
- }
-
- /** {@inheritDoc} */
- public String toString() {
- StringBuffer sb = new StringBuffer();
- sb.append("SpaceHandlingBreakPosition(");
- sb.append(this.originalPosition);
- sb.append(")");
- return sb.toString();
- }
-
- /**
- * @return the original Position instance set at the BreakElement that this Position was
- * created for.
- */
- public Position getOriginalBreakPosition() {
- return this.originalPosition;
- }
-
- /** {@inheritDoc} */
- public Position getPosition() {
- return originalPosition;
- }
-
- }
-
- /**
- * Position class for no-break situations. It is used to notify layout manager about the
- * effective spaces and conditional lengths.
- */
- public static class SpaceHandlingPosition extends Position {
-
- private SpaceResolver resolver;
-
- /**
- * Main constructor.
- * @param resolver the space resolver that provides the info about the actual situation
- */
- public SpaceHandlingPosition(SpaceResolver resolver) {
- super(null);
- this.resolver = resolver;
- }
-
- /** @return the space resolver */
- public SpaceResolver getSpaceResolver() {
- return this.resolver;
- }
-
- /**
- * Notifies all affected layout managers about the current situation in the part to be
- * handled for area generation.
- */
- public void notifySpaceSituation() {
- if (resolver.breakPoss != null) {
- throw new IllegalStateException("Only applicable to no-break situations");
- }
- for (int i = 0; i < resolver.secondPart.length; i++) {
- resolver.secondPart[i].notifyLayoutManager(resolver.secondPartLengths[i]);
- }
- }
-
- /** {@inheritDoc} */
- public String toString() {
- return "SpaceHandlingPosition";
- }
- }
-
- /**
- * Resolves unresolved elements applying the space resolution rules defined in 4.3.1.
- * @param elems the element list
- */
- public static void resolveElementList(List elems) {
- if (LOG.isTraceEnabled()) {
- LOG.trace(elems);
- }
- boolean first = true;
- boolean last = false;
- boolean skipNextElement = false;
- List unresolvedFirst = new java.util.ArrayList();
- List unresolvedSecond = new java.util.ArrayList();
- List currentGroup;
- ListIterator iter = elems.listIterator();
- while (iter.hasNext()) {
- ListElement el = (ListElement)iter.next();
- if (el.isUnresolvedElement()) {
- if (LOG.isTraceEnabled()) {
- LOG.trace("unresolved found: " + el + " " + first + "/" + last);
- }
- BreakElement breakPoss = null;
- //Clear temp lists
- unresolvedFirst.clear();
- unresolvedSecond.clear();
- //Collect groups
- if (el instanceof BreakElement) {
- breakPoss = (BreakElement)el;
- currentGroup = unresolvedSecond;
- } else {
- currentGroup = unresolvedFirst;
- currentGroup.add(el);
- }
- iter.remove();
- last = true;
- skipNextElement = true;
- while (iter.hasNext()) {
- el = (ListElement)iter.next();
- if (el instanceof BreakElement && breakPoss != null) {
- skipNextElement = false;
- last = false;
- break;
- } else if (currentGroup == unresolvedFirst && (el instanceof BreakElement)) {
- breakPoss = (BreakElement)el;
- iter.remove();
- currentGroup = unresolvedSecond;
- } else if (el.isUnresolvedElement()) {
- currentGroup.add(el);
- iter.remove();
- } else {
- last = false;
- break;
- }
- }
- //last = !iter.hasNext();
- if (breakPoss == null && unresolvedSecond.isEmpty() && !last) {
- LOG.trace("Swap first and second parts in no-break condition,"
- + " second part is empty.");
- //The first list is reversed, so swap if this shouldn't happen
- List swapList = unresolvedSecond;
- unresolvedSecond = unresolvedFirst;
- unresolvedFirst = swapList;
- }
-
- LOG.debug("----start space resolution (first=" + first + ", last=" + last + ")...");
- SpaceResolver resolver = new SpaceResolver(
- unresolvedFirst, breakPoss, unresolvedSecond, first, last);
- if (!last) {
- iter.previous();
- }
- resolver.generate(iter);
- if (!last && skipNextElement) {
- iter.next();
- }
- LOG.debug("----end space resolution.");
- }
- first = false;
- }
- }
-
- /**
- * Inspects an effective element list and notifies all layout managers about the state of
- * the spaces and conditional lengths.
- * @param effectiveList the effective element list
- * @param startElementIndex index of the first element in the part to be processed
- * @param endElementIndex index of the last element in the part to be processed
- * @param prevBreak index of the the break possibility just before this part (used to
- * identify a break condition, lastBreak <= 0 represents a no-break condition)
- */
- public static void performConditionalsNotification(List effectiveList,
- int startElementIndex, int endElementIndex, int prevBreak) {
- KnuthElement el = null;
- if (prevBreak > 0) {
- el = (KnuthElement)effectiveList.get(prevBreak);
- }
- SpaceResolver.SpaceHandlingBreakPosition beforeBreak = null;
- SpaceResolver.SpaceHandlingBreakPosition afterBreak = null;
- if (el != null && el.isPenalty()) {
- Position pos = el.getPosition();
- if (pos instanceof SpaceResolver.SpaceHandlingBreakPosition) {
- beforeBreak = (SpaceResolver.SpaceHandlingBreakPosition)pos;
- beforeBreak.notifyBreakSituation(true, RelSide.BEFORE);
- }
- }
- el = endElementIndex > -1 ? (KnuthElement) effectiveList.get(endElementIndex) : null;
- if (el != null && el.isPenalty()) {
- Position pos = el.getPosition();
- if (pos instanceof SpaceResolver.SpaceHandlingBreakPosition) {
- afterBreak = (SpaceResolver.SpaceHandlingBreakPosition)pos;
- afterBreak.notifyBreakSituation(true, RelSide.AFTER);
- }
- }
- for (int i = startElementIndex; i <= endElementIndex; i++) {
- Position pos = ((KnuthElement)effectiveList.get(i)).getPosition();
- if (pos instanceof SpaceResolver.SpaceHandlingPosition) {
- ((SpaceResolver.SpaceHandlingPosition)pos).notifySpaceSituation();
- } else if (pos instanceof SpaceResolver.SpaceHandlingBreakPosition) {
- SpaceResolver.SpaceHandlingBreakPosition noBreak;
- noBreak = (SpaceResolver.SpaceHandlingBreakPosition)pos;
- if (noBreak != beforeBreak && noBreak != afterBreak) {
- noBreak.notifyBreakSituation(false, null);
- }
- }
- }
- }
-
-
- }
|