KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > layoutmgr > SpaceResolver


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 /* $Id: SpaceResolver.java 426576 2006-07-28 15:44:37Z jeremias $ */
19
20 package org.apache.fop.layoutmgr;
21
22 import java.util.LinkedList JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.ListIterator JavaDoc;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.fop.traits.MinOptMax;
29
30 /**
31  * This class resolves spaces and conditional borders and paddings by replacing the
32  * UnresolvedListElements descendants by the right combination of KnuthElements on an element
33  * list.
34  */

35 public class SpaceResolver {
36
37     /** Logger instance */
38     protected static Log log = LogFactory.getLog(SpaceResolver.class);
39     
40     private UnresolvedListElementWithLength[] firstPart;
41     private BreakElement breakPoss;
42     private UnresolvedListElementWithLength[] secondPart;
43     private UnresolvedListElementWithLength[] noBreak;
44     
45     private MinOptMax[] firstPartLengths;
46     private MinOptMax[] secondPartLengths;
47     private MinOptMax[] noBreakLengths;
48     
49     private boolean isFirst;
50     private boolean isLast;
51     
52     /**
53      * Main constructor.
54      * @param first Element list before a break (optional)
55      * @param breakPoss Break possibility (optional)
56      * @param second Element list after a break (or if no break possibility in vicinity)
57      * @param isFirst Resolution at the beginning of a (full) element list
58      * @param isLast Resolution at the end of a (full) element list
59      */

60     public SpaceResolver(List JavaDoc first, BreakElement breakPoss, List JavaDoc second,
61             boolean isFirst, boolean isLast) {
62         this.isFirst = isFirst;
63         this.isLast = isLast;
64         //Create combined no-break list
65
int c = 0;
66         if (first != null) {
67             c += first.size();
68         }
69         if (second != null) {
70             c += second.size();
71         }
72         noBreak = new UnresolvedListElementWithLength[c];
73         noBreakLengths = new MinOptMax[c];
74         int i = 0;
75         ListIterator JavaDoc iter;
76         if (first != null) {
77             iter = first.listIterator();
78             while (iter.hasNext()) {
79                 noBreak[i] = (UnresolvedListElementWithLength)iter.next();
80                 noBreakLengths[i] = noBreak[i].getLength();
81                 i++;
82             }
83         }
84         if (second != null) {
85             iter = second.listIterator();
86             while (iter.hasNext()) {
87                 noBreak[i] = (UnresolvedListElementWithLength)iter.next();
88                 noBreakLengths[i] = noBreak[i].getLength();
89                 i++;
90             }
91         }
92
93         //Add pending elements from higher level FOs
94
if (breakPoss != null) {
95             if (breakPoss.getPendingAfterMarks() != null) {
96                 if (log.isTraceEnabled()) {
97                     log.trace(" adding pending before break: "
98                             + breakPoss.getPendingAfterMarks());
99                 }
100                 first.addAll(0, breakPoss.getPendingAfterMarks());
101             }
102             if (breakPoss.getPendingBeforeMarks() != null) {
103                 if (log.isTraceEnabled()) {
104                     log.trace(" adding pending after break: "
105                             + breakPoss.getPendingBeforeMarks());
106                 }
107                 second.addAll(0, breakPoss.getPendingBeforeMarks());
108             }
109         }
110         if (log.isTraceEnabled()) {
111             log.trace("before: " + first);
112             log.trace(" break: " + breakPoss);
113             log.trace("after: " + second);
114             log.trace("NO-BREAK: " + toString(noBreak, noBreakLengths));
115         }
116
117         if (first != null) {
118             firstPart = new UnresolvedListElementWithLength[first.size()];
119             firstPartLengths = new MinOptMax[firstPart.length];
120             first.toArray(firstPart);
121             for (i = 0; i < firstPart.length; i++) {
122                 firstPartLengths[i] = firstPart[i].getLength();
123             }
124         }
125         this.breakPoss = breakPoss;
126         if (second != null) {
127             secondPart = new UnresolvedListElementWithLength[second.size()];
128             secondPartLengths = new MinOptMax[secondPart.length];
129             second.toArray(secondPart);
130             for (i = 0; i < secondPart.length; i++) {
131                 secondPartLengths[i] = secondPart[i].getLength();
132             }
133         }
134         resolve();
135     }
136     
137     private String JavaDoc toString(Object JavaDoc[] arr1, Object JavaDoc[] arr2) {
138         if (arr1.length != arr2.length) {
139             new IllegalArgumentException JavaDoc("The length of both arrays must be equal");
140         }
141         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("[");
142         for (int i = 0; i < arr1.length; i++) {
143             if (i > 0) {
144                 sb.append(", ");
145             }
146             sb.append(String.valueOf(arr1[i]));
147             sb.append("/");
148             sb.append(String.valueOf(arr2[i]));
149         }
150         sb.append("]");
151         return sb.toString();
152     }
153     
154     private void removeConditionalBorderAndPadding(
155                 UnresolvedListElement[] elems, MinOptMax[] lengths, boolean reverse) {
156         for (int i = 0; i < elems.length; i++) {
157             int effIndex;
158             if (reverse) {
159                 effIndex = elems.length - 1 - i;
160             } else {
161                 effIndex = i;
162             }
163             if (elems[effIndex] instanceof BorderOrPaddingElement) {
164                 BorderOrPaddingElement bop = (BorderOrPaddingElement)elems[effIndex];
165                 if (bop.isConditional() && !(bop.isFirst() || bop.isLast())) {
166                     if (log.isDebugEnabled()) {
167                         log.debug("Nulling conditional element: " + bop);
168                     }
169                     lengths[effIndex] = null;
170                 }
171             }
172         }
173         if (log.isTraceEnabled() && elems.length > 0) {
174             log.trace("-->Resulting list: " + toString(elems, lengths));
175         }
176     }
177     
178     private void performSpaceResolutionRule1(UnresolvedListElement[] elems, MinOptMax[] lengths,
179                     boolean reverse) {
180         for (int i = 0; i < elems.length; i++) {
181             int effIndex;
182             if (reverse) {
183                 effIndex = elems.length - 1 - i;
184             } else {
185                 effIndex = i;
186             }
187             if (lengths[effIndex] == null) {
188                 //Zeroed border or padding doesn't create a fence
189
continue;
190             } else if (elems[effIndex] instanceof BorderOrPaddingElement) {
191                 //Border or padding form fences!
192
break;
193             } else if (!elems[effIndex].isConditional()) {
194                 break;
195             }
196             if (log.isDebugEnabled()) {
197                 log.debug("Nulling conditional element using 4.3.1, rule 1: " + elems[effIndex]);
198             }
199             lengths[effIndex] = null;
200         }
201         if (log.isTraceEnabled() && elems.length > 0) {
202             log.trace("-->Resulting list: " + toString(elems, lengths));
203         }
204     }
205
206     private void performSpaceResolutionRules2to3(UnresolvedListElement[] elems,
207             MinOptMax[] lengths, int start, int end) {
208         if (log.isTraceEnabled()) {
209             log.trace("rule 2-3: " + start + "-" + end);
210         }
211         SpaceElement space;
212         int remaining;
213         
214         //Rule 2 (4.3.1, XSL 1.0)
215
boolean hasForcing = false;
216         remaining = 0;
217         for (int i = start; i <= end; i++) {
218             if (lengths[i] == null) {
219                 continue;
220             }
221             remaining++;
222             space = (SpaceElement)elems[i];
223             if (space.isForcing()) {
224                 hasForcing = true;
225                 break;
226             }
227         }
228         if (remaining == 0) {
229             return; //shortcut
230
}
231         if (hasForcing) {
232             for (int i = start; i <= end; i++) {
233                 if (lengths[i] == null) {
234                     continue;
235                 }
236                 space = (SpaceElement)elems[i];
237                 if (!space.isForcing()) {
238                     if (log.isDebugEnabled()) {
239                         log.debug("Nulling non-forcing space-specifier using 4.3.1, rule 2: "
240                                 + elems[i]);
241                     }
242                     lengths[i] = null;
243                 }
244             }
245             return; //If rule is triggered skip rule 3
246
}
247         
248         //Rule 3 (4.3.1, XSL 1.0)
249
//Determine highes precedence
250
int highestPrecedence = Integer.MIN_VALUE;
251         for (int i = start; i <= end; i++) {
252             if (lengths[i] == null) {
253                 continue;
254             }
255             space = (SpaceElement)elems[i];
256             highestPrecedence = Math.max(highestPrecedence, space.getPrecedence());
257         }
258         if (highestPrecedence != 0 && log.isDebugEnabled()) {
259             log.debug("Highest precedence is " + highestPrecedence);
260         }
261         //Suppress space-specifiers with lower precedence
262
remaining = 0;
263         int greatestOptimum = Integer.MIN_VALUE;
264         for (int i = start; i <= end; i++) {
265             if (lengths[i] == null) {
266                 continue;
267             }
268             space = (SpaceElement)elems[i];
269             if (space.getPrecedence() != highestPrecedence) {
270                 if (log.isDebugEnabled()) {
271                     log.debug("Nulling space-specifier with precedence "
272                             + space.getPrecedence() + " using 4.3.1, rule 3: "
273                             + elems[i]);
274                 }
275                 lengths[i] = null;
276             } else {
277                 greatestOptimum = Math.max(greatestOptimum, space.getLength().opt);
278                 remaining++;
279             }
280         }
281         if (log.isDebugEnabled()) {
282             log.debug("Greatest optimum: " + greatestOptimum);
283         }
284         if (remaining <= 1) {
285             return;
286         }
287         //Suppress space-specifiers with smaller optimum length
288
remaining = 0;
289         for (int i = start; i <= end; i++) {
290             if (lengths[i] == null) {
291                 continue;
292             }
293             space = (SpaceElement)elems[i];
294             if (space.getLength().opt < greatestOptimum) {
295                 if (log.isDebugEnabled()) {
296                     log.debug("Nulling space-specifier with smaller optimum length "
297                             + "using 4.3.1, rule 3: "
298                             + elems[i]);
299                 }
300                 lengths[i] = null;
301             } else {
302                 remaining++;
303             }
304         }
305         if (remaining <= 1) {
306             return;
307         }
308         //Construct resolved space-specifier from the remaining spaces
309
int min = Integer.MIN_VALUE;
310         int max = Integer.MAX_VALUE;
311         for (int i = start; i <= end; i++) {
312             if (lengths[i] == null) {
313                 continue;
314             }
315             space = (SpaceElement)elems[i];
316             min = Math.max(min, space.getLength().min);
317             max = Math.min(max, space.getLength().max);
318             if (remaining > 1) {
319                 if (log.isDebugEnabled()) {
320                     log.debug("Nulling non-last space-specifier using 4.3.1, rule 3, second part: "
321                             + elems[i]);
322                 }
323                 lengths[i] = null;
324                 remaining--;
325             } else {
326                 lengths[i].min = min;
327                 lengths[i].max = max;
328             }
329         }
330
331         if (log.isTraceEnabled() && elems.length > 0) {
332             log.trace("Remaining spaces: " + remaining);
333             log.trace("-->Resulting list: " + toString(elems, lengths));
334         }
335     }
336     
337     private void performSpaceResolutionRules2to3(UnresolvedListElement[] elems,
338             MinOptMax[] lengths) {
339         int start = 0;
340         int i = start;
341         while (i < elems.length) {
342             if (elems[i] instanceof SpaceElement) {
343                 while (i < elems.length) {
344                     if (elems[i] == null || elems[i] instanceof SpaceElement) {
345                         i++;
346                     } else {
347                         break;
348                     }
349                 }
350                 performSpaceResolutionRules2to3(elems, lengths, start, i - 1);
351             }
352             i++;
353             start = i;
354         }
355     }
356     
357     private boolean hasFirstPart() {
358         return firstPart != null && firstPart.length > 0;
359     }
360     
361     private boolean hasSecondPart() {
362         return secondPart != null && secondPart.length > 0;
363     }
364     
365     private void resolve() {
366         if (breakPoss != null) {
367             if (hasFirstPart()) {
368                 removeConditionalBorderAndPadding(firstPart, firstPartLengths, true);
369                 performSpaceResolutionRule1(firstPart, firstPartLengths, true);
370                 performSpaceResolutionRules2to3(firstPart, firstPartLengths);
371             }
372             if (hasSecondPart()) {
373                 removeConditionalBorderAndPadding(secondPart, secondPartLengths, false);
374                 performSpaceResolutionRule1(secondPart, secondPartLengths, false);
375                 performSpaceResolutionRules2to3(secondPart, secondPartLengths);
376             }
377             if (noBreak != null) {
378                 performSpaceResolutionRules2to3(noBreak, noBreakLengths);
379             }
380         } else {
381             if (isFirst) {
382                 removeConditionalBorderAndPadding(secondPart, secondPartLengths, false);
383                 performSpaceResolutionRule1(secondPart, secondPartLengths, false);
384             }
385             if (isLast) {
386                 removeConditionalBorderAndPadding(firstPart, firstPartLengths, true);
387                 performSpaceResolutionRule1(firstPart, firstPartLengths, true);
388             }
389             
390             if (hasFirstPart()) {
391                 //Now that we've handled isFirst/isLast conditions, we need to look at the
392
//active part in its normal order so swap it back.
393
log.trace("Swapping first and second parts.");
394                 UnresolvedListElementWithLength[] tempList;
395                 MinOptMax[] tempLengths;
396                 tempList = secondPart;
397                 tempLengths = secondPartLengths;
398                 secondPart = firstPart;
399                 secondPartLengths = firstPartLengths;
400                 firstPart = tempList;
401                 firstPartLengths = tempLengths;
402                 if (hasFirstPart()) {
403                     throw new IllegalStateException JavaDoc("Didn't expect more than one parts in a"
404                             + "no-break condition.");
405                 }
406             }
407             performSpaceResolutionRules2to3(secondPart, secondPartLengths);
408         }
409     }
410     
411     private MinOptMax sum(MinOptMax[] lengths) {
412         MinOptMax sum = new MinOptMax();
413         for (int i = 0; i < lengths.length; i++) {
414             if (lengths[i] != null) {
415                 sum.add(lengths[i]);
416             }
417         }
418         return sum;
419     }
420     
421     private void generate(ListIterator JavaDoc iter) {
422         MinOptMax noBreakLength = new MinOptMax();
423         MinOptMax glue1; //space before break possibility if break occurs
424
//MinOptMax glue2; //difference between glue 1 and 3 when no break occurs
425
MinOptMax glue3; //space after break possibility if break occurs
426
glue1 = sum(firstPartLengths);
427         glue3 = sum(secondPartLengths);
428         noBreakLength = sum(noBreakLengths);
429         
430         //This doesn't produce the right glue2
431
//glue2 = new MinOptMax(noBreakLength);
432
//glue2.subtract(glue1);
433
//glue2.subtract(glue3);
434

435         int glue2w = noBreakLength.opt - glue1.opt - glue3.opt;
436         int glue2stretch = (noBreakLength.max - noBreakLength.opt);
437         int glue2shrink = (noBreakLength.opt - noBreakLength.min);
438         glue2stretch -= glue1.max - glue1.opt;
439         glue2stretch -= glue3.max - glue3.opt;
440         glue2shrink -= glue1.opt - glue1.min;
441         glue2shrink -= glue3.opt - glue3.min;
442         
443         boolean hasPrecedingNonBlock = false;
444         boolean forcedBreak = false;
445         if (log.isDebugEnabled()) {
446             log.debug("noBreakLength=" + noBreakLength
447                     + ", glue1=" + glue1
448                     + ", glue2=" + glue2w + "+" + glue2stretch + "-" + glue2shrink
449                     + ", glue3=" + glue3);
450         }
451         if (breakPoss != null) {
452             if (glue1.isNonZero()) {
453                 iter.add(new KnuthPenalty(0, KnuthPenalty.INFINITE,
454                         false, (Position)null, true));
455                 iter.add(new KnuthGlue(glue1.opt, glue1.max - glue1.opt, glue1.opt - glue1.min,
456                         (Position)null, true));
457             }
458             iter.add(new KnuthPenalty(breakPoss.getPenaltyWidth(), breakPoss.getPenaltyValue(),
459                     false, breakPoss.getBreakClass(),
460                     new SpaceHandlingBreakPosition(this, breakPoss), false));
461             if (breakPoss.getPenaltyValue() <= -KnuthPenalty.INFINITE) {
462                 return; //return early. Not necessary (even wrong) to add additional elements
463
}
464             if (glue2w != 0 || glue2stretch != 0 || glue2shrink != 0) {
465                 iter.add(new KnuthGlue(glue2w, glue2stretch, glue2shrink,
466                         (Position)null, true));
467             }
468         } else {
469             if (glue1.isNonZero()) {
470                 throw new IllegalStateException JavaDoc("glue1 should be 0 in this case");
471             }
472         }
473         Position pos = null;
474         if (breakPoss == null) {
475             pos = new SpaceHandlingPosition(this);
476         }
477         if (glue3.isNonZero() || pos != null) {
478             iter.add(new KnuthBox(0, pos, true));
479         }
480         if (glue3.isNonZero()) {
481             iter.add(new KnuthPenalty(0, KnuthPenalty.INFINITE,
482                     false, (Position)null, true));
483             iter.add(new KnuthGlue(glue3.opt, glue3.max - glue3.opt, glue3.opt - glue3.min,
484                     (Position)null, true));
485             hasPrecedingNonBlock = true;
486         }
487         if (isLast && hasPrecedingNonBlock) {
488             //Otherwise, the preceding penalty and glue will be cut off
489
iter.add(new KnuthBox(0, (Position)null, true));
490         }
491     }
492     
493     /**
494      * Position class for break possibilities. It is used to notify layout manager about the
495      * effective spaces and conditional lengths.
496      */

497     public class SpaceHandlingBreakPosition extends Position {
498
499         private SpaceResolver resolver;
500         private Position originalPosition;
501         
502         /**
503          * Main constructor.
504          * @param resolver the space resolver that provides the info about the actual situation
505          * @param breakPoss the original break possibility that creates this Position
506          */

507         public SpaceHandlingBreakPosition(SpaceResolver resolver, BreakElement breakPoss) {
508             super(null);
509             this.resolver = resolver;
510             this.originalPosition = breakPoss.getPosition();
511             //Unpack since the SpaceHandlingBreakPosition is a non-wrapped Position, too
512
while (this.originalPosition instanceof NonLeafPosition) {
513                 this.originalPosition = this.originalPosition.getPosition();
514             }
515         }
516         
517         /** @return the space resolver */
518         public SpaceResolver getSpaceResolver() {
519             return this.resolver;
520         }
521         
522         /**
523          * Notifies all affected layout managers about the current situation in the part to be
524          * handled for area generation.
525          * @param isBreakSituation true if this is a break situation.
526          * @param side defines to notify about the situation whether before or after the break.
527          * May be null if isBreakSituation is null.
528          */

529         public void notifyBreakSituation(boolean isBreakSituation, RelSide side) {
530             if (isBreakSituation) {
531                 if (RelSide.BEFORE == side) {
532                     for (int i = 0; i < resolver.secondPart.length; i++) {
533                         resolver.secondPart[i].notifyLayoutManager(resolver.secondPartLengths[i]);
534                     }
535                 } else {
536                     for (int i = 0; i < resolver.firstPart.length; i++) {
537                         resolver.firstPart[i].notifyLayoutManager(resolver.firstPartLengths[i]);
538                     }
539                 }
540             } else {
541                 for (int i = 0; i < resolver.noBreak.length; i++) {
542                     resolver.noBreak[i].notifyLayoutManager(resolver.noBreakLengths[i]);
543                 }
544             }
545         }
546         
547         /** @see java.lang.Object#toString() */
548         public String JavaDoc toString() {
549             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
550             sb.append("SpaceHandlingBreakPosition(");
551             sb.append(this.originalPosition);
552             sb.append(")");
553             return sb.toString();
554         }
555
556         /**
557          * @return the original Position instance set at the BreakElement that this Position was
558          * created for.
559          */

560         public Position getOriginalBreakPosition() {
561             return this.originalPosition;
562         }
563     }
564     
565     /**
566      * Position class for no-break situations. It is used to notify layout manager about the
567      * effective spaces and conditional lengths.
568      */

569     public class SpaceHandlingPosition extends Position {
570
571         private SpaceResolver resolver;
572         
573         /**
574          * Main constructor.
575          * @param resolver the space resolver that provides the info about the actual situation
576          */

577         public SpaceHandlingPosition(SpaceResolver resolver) {
578             super(null);
579             this.resolver = resolver;
580         }
581         
582         /** @return the space resolver */
583         public SpaceResolver getSpaceResolver() {
584             return this.resolver;
585         }
586         
587         /**
588          * Notifies all affected layout managers about the current situation in the part to be
589          * handled for area generation.
590          */

591         public void notifySpaceSituation() {
592             if (resolver.breakPoss != null) {
593                 throw new IllegalStateException JavaDoc("Only applicable to no-break situations");
594             }
595             for (int i = 0; i < resolver.secondPart.length; i++) {
596                 resolver.secondPart[i].notifyLayoutManager(resolver.secondPartLengths[i]);
597             }
598         }
599         
600         /** @see java.lang.Object#toString() */
601         public String JavaDoc toString() {
602             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
603             sb.append("SpaceHandlingPosition");
604             return sb.toString();
605         }
606     }
607     
608     /**
609      * Resolves unresolved elements applying the space resolution rules defined in 4.3.1.
610      * @param elems the element list
611      */

612     public static void resolveElementList(LinkedList JavaDoc elems) {
613         if (log.isTraceEnabled()) {
614             log.trace(elems);
615         }
616         boolean first = true;
617         boolean last = false;
618         boolean skipNextElement = false;
619         List JavaDoc unresolvedFirst = new java.util.ArrayList JavaDoc();
620         List JavaDoc unresolvedSecond = new java.util.ArrayList JavaDoc();
621         List JavaDoc currentGroup;
622         ListIterator JavaDoc iter = elems.listIterator();
623         while (iter.hasNext()) {
624             ListElement el = (ListElement)iter.next();
625             if (el.isUnresolvedElement()) {
626                 if (log.isTraceEnabled()) {
627                     log.trace("unresolved found: " + el + " " + first + "/" + last);
628                 }
629                 BreakElement breakPoss = null;
630                 //Clear temp lists
631
unresolvedFirst.clear();
632                 unresolvedSecond.clear();
633                 //Collect groups
634
if (el instanceof BreakElement) {
635                     breakPoss = (BreakElement)el;
636                     currentGroup = unresolvedSecond;
637                 } else {
638                     currentGroup = unresolvedFirst;
639                     currentGroup.add(el);
640                 }
641                 iter.remove();
642                 last = true;
643                 skipNextElement = true;
644                 while (iter.hasNext()) {
645                     el = (ListElement)iter.next();
646                     if (el instanceof BreakElement && breakPoss != null) {
647                         skipNextElement = false;
648                         last = false;
649                         break;
650                     } else if (currentGroup == unresolvedFirst && (el instanceof BreakElement)) {
651                         breakPoss = (BreakElement)el;
652                         iter.remove();
653                         currentGroup = unresolvedSecond;
654                     } else if (el.isUnresolvedElement()) {
655                         currentGroup.add(el);
656                         iter.remove();
657                     } else {
658                         last = false;
659                         break;
660                     }
661                 }
662                 //last = !iter.hasNext();
663
if (breakPoss == null && unresolvedSecond.size() == 0 && !last) {
664                     log.trace("Swap first and second parts in no-break condition,"
665                             + " second part is empty.");
666                     //The first list is reversed, so swap if this shouldn't happen
667
List JavaDoc swapList = unresolvedSecond;
668                     unresolvedSecond = unresolvedFirst;
669                     unresolvedFirst = swapList;
670                 }
671                 
672                 log.debug("----start space resolution (first=" + first + ", last=" + last + ")...");
673                 SpaceResolver resolver = new SpaceResolver(
674                         unresolvedFirst, breakPoss, unresolvedSecond, first, last);
675                 if (!last) {
676                     iter.previous();
677                 }
678                 resolver.generate(iter);
679                 if (!last && skipNextElement) {
680                     iter.next();
681                 }
682                 log.debug("----end space resolution.");
683             }
684             first = false;
685         }
686     }
687     
688     /**
689      * Inspects an effective element list and notifies all layout managers about the state of
690      * the spaces and conditional lengths.
691      * @param effectiveList the effective element list
692      * @param startElementIndex index of the first element in the part to be processed
693      * @param endElementIndex index of the last element in the part to be processed
694      * @param prevBreak index of the the break possibility just before this part (used to
695      * identify a break condition, lastBreak <= 0 represents a no-break condition)
696      */

697     public static void performConditionalsNotification(List JavaDoc effectiveList,
698             int startElementIndex, int endElementIndex, int prevBreak) {
699         KnuthElement el = null;
700         if (prevBreak > 0) {
701             el = (KnuthElement)effectiveList.get(prevBreak);
702         }
703         SpaceResolver.SpaceHandlingBreakPosition beforeBreak = null;
704         SpaceResolver.SpaceHandlingBreakPosition afterBreak = null;
705         if (el != null && el.isPenalty()) {
706             Position pos = el.getPosition();
707             if (pos instanceof SpaceResolver.SpaceHandlingBreakPosition) {
708                 beforeBreak = (SpaceResolver.SpaceHandlingBreakPosition)pos;
709                 beforeBreak.notifyBreakSituation(true, RelSide.BEFORE);
710             }
711         }
712         el = (KnuthElement)effectiveList.get(endElementIndex);
713         if (el != null && el.isPenalty()) {
714             Position pos = el.getPosition();
715             if (pos instanceof SpaceResolver.SpaceHandlingBreakPosition) {
716                 afterBreak = (SpaceResolver.SpaceHandlingBreakPosition)pos;
717                 afterBreak.notifyBreakSituation(true, RelSide.AFTER);
718             }
719         }
720         for (int i = startElementIndex; i <= endElementIndex; i++) {
721             Position pos = ((KnuthElement)effectiveList.get(i)).getPosition();
722             if (pos instanceof SpaceResolver.SpaceHandlingPosition) {
723                 ((SpaceResolver.SpaceHandlingPosition)pos).notifySpaceSituation();
724             } else if (pos instanceof SpaceResolver.SpaceHandlingBreakPosition) {
725                 SpaceResolver.SpaceHandlingBreakPosition noBreak;
726                 noBreak = (SpaceResolver.SpaceHandlingBreakPosition)pos;
727                 if (noBreak != beforeBreak && noBreak != afterBreak) {
728                     noBreak.notifyBreakSituation(false, null);
729                 }
730             }
731         }
732     }
733     
734     
735
736 }
737
Popular Tags