KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > layout > LineArea


1 /*
2  * $Id: LineArea.java,v 1.53.2.19 2003/06/06 07:27:59 jeremias Exp $
3  * ============================================================================
4  * The Apache Software License, Version 1.1
5  * ============================================================================
6  *
7  * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without modifica-
10  * tion, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. The end-user documentation included with the redistribution, if any, must
20  * include the following acknowledgment: "This product includes software
21  * developed by the Apache Software Foundation (http://www.apache.org/)."
22  * Alternately, this acknowledgment may appear in the software itself, if
23  * and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. The names "FOP" and "Apache Software Foundation" must not be used to
26  * endorse or promote products derived from this software without prior
27  * written permission. For written permission, please contact
28  * apache@apache.org.
29  *
30  * 5. Products derived from this software may not be called "Apache", nor may
31  * "Apache" appear in their name, without prior written permission of the
32  * Apache Software Foundation.
33  *
34  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
35  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37  * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
39  * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
40  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44  * ============================================================================
45  *
46  * This software consists of voluntary contributions made by many individuals
47  * on behalf of the Apache Software Foundation and was originally created by
48  * James Tauber <jtauber@jtauber.com>. For more information on the Apache
49  * Software Foundation, please see <http://www.apache.org/>.
50  */

51 package org.apache.fop.layout;
52
53 // Java
54
import java.util.ArrayList JavaDoc;
55 import java.util.StringTokenizer JavaDoc;
56 import java.awt.Rectangle JavaDoc;
57
58 // FOP
59
import org.apache.fop.datatypes.IDReferences;
60 import org.apache.fop.fo.properties.Hyphenate;
61 import org.apache.fop.fo.properties.LeaderAlignment;
62 import org.apache.fop.fo.properties.LeaderPattern;
63 import org.apache.fop.fo.properties.TextAlign;
64 import org.apache.fop.fo.properties.VerticalAlign;
65 import org.apache.fop.fo.properties.WhiteSpaceCollapse;
66 import org.apache.fop.fo.properties.WrapOption;
67 import org.apache.fop.layout.hyphenation.Hyphenation;
68 import org.apache.fop.layout.hyphenation.Hyphenator;
69 import org.apache.fop.layout.inline.*;
70 import org.apache.fop.messaging.MessageHandler;
71 import org.apache.fop.render.Renderer;
72
73 public class LineArea extends Area {
74
75     protected int lineHeight;
76     protected int halfLeading;
77     protected int nominalFontSize;
78     protected int nominalGlyphHeight;
79
80     protected int allocationHeight;
81     protected int startIndent;
82     protected int endIndent;
83
84     private int placementOffset;
85     private int textAlign;
86
87     private FontState currentFontState; // not the nominal, which is
88
// in this.fontState
89
private float red, green, blue;
90     private int wrapOption;
91     private int whiteSpaceCollapse;
92     private int vAlign;
93
94     /* hyphenation */
95     private HyphenationProps hyphProps;
96
97     /*
98      * the width of text that has definitely made it into the line
99      * area
100      */

101     private int finalWidth = 0;
102
103     /* the position to shift a link rectangle in order to compensate
104      * for links embedded within a word
105      */

106     protected int embeddedLinkStart = 0;
107
108     /* the width of the current word so far */
109     // protected int wordWidth = 0;
110

111     /* values that prev (below) may take */
112     protected static final int NOTHING = 0;
113     protected static final int WHITESPACE = 1;
114     protected static final int TEXT = 2;
115     protected static final int MULTIBYTECHAR = 3;
116
117     /* the character type of the previous character */
118     private int prev = NOTHING;
119
120     /* width of spaces before current word */
121     private int spaceWidth = 0;
122
123     /*
124      * the inline areas that have not yet been added to the line
125      * because subsequent characters to come (in a different addText)
126      * may be part of the same word
127      */

128     private ArrayList JavaDoc pendingAreas = new ArrayList JavaDoc();
129
130     /* the width of the pendingAreas */
131     private int pendingWidth = 0;
132
133     /* text-decoration of the previous text */
134     protected boolean prevUlState = false;
135     protected boolean prevOlState = false;
136     protected boolean prevLTState = false;
137
138     // Whether the line has already be aligned text and expanded
139
// leaders.
140
private boolean aligned = false;
141     private boolean hasPageNumbers = false;
142
143     public class Leader {
144         int leaderPattern;
145         int leaderLengthMinimum;
146         int leaderLengthOptimum;
147         int leaderLengthMaximum;
148         int ruleStyle;
149         int ruleThickness;
150         int leaderPatternWidth;
151         int leaderAlignment;
152         FontState fontState;
153         float red;
154         float green;
155         float blue;
156         int placementOffset;
157         int position;
158
159         Leader(int leaderPattern, int leaderLengthMinimum,
160                int leaderLengthOptimum, int leaderLengthMaximum,
161                int ruleStyle, int ruleThickness,
162                int leaderPatternWidth, int leaderAlignment,
163                FontState fontState,
164                float red, float green, float blue,
165                int placementOffset,
166                int position) {
167             this.leaderPattern=leaderPattern;
168             this.leaderLengthMinimum=leaderLengthMinimum;
169             this.leaderLengthOptimum=leaderLengthOptimum;
170             this.leaderLengthMaximum=leaderLengthMaximum;
171             this.ruleStyle=ruleStyle;
172             this.ruleThickness=ruleThickness;
173             this.leaderPatternWidth=leaderPatternWidth;
174             this.leaderAlignment=leaderAlignment;
175             this.fontState=fontState;
176             this.red=red;
177             this.green=green;
178             this.blue=blue;
179             this.placementOffset=placementOffset;
180             this.position = position;
181         }
182         void expand() {
183             char dot = '.';
184             int dotWidth = fontState.getCharWidth(dot);
185             char space = ' ';
186             int spaceWidth = fontState.getCharWidth(space);
187             int idx=children.indexOf(this);
188             children.remove(this);
189             switch (leaderPattern) {
190             case LeaderPattern.SPACE:
191                 InlineSpace spaceArea = new InlineSpace(leaderLengthOptimum
192                                                         , false);
193                 children.add(idx,spaceArea);
194                 break;
195             case LeaderPattern.RULE:
196                 LeaderArea leaderArea = new LeaderArea(fontState, red, green,
197                                                        blue, "",
198                                                        leaderLengthOptimum,
199                                                        leaderPattern,
200                                                        ruleThickness,
201                                                        ruleStyle);
202                 leaderArea.setYOffset(placementOffset);
203                 children.add(idx,leaderArea);
204                 break;
205             case LeaderPattern.DOTS:
206                 // if the width of a dot is larger than leader-pattern-width
207
// ignore this property
208
if (this.leaderPatternWidth < dotWidth) {
209                     this.leaderPatternWidth = 0;
210                 }
211                 // if value of leader-pattern-width is 'use-font-metrics' (0)
212
if (this.leaderPatternWidth == 0) {
213                     if (dotWidth == 0) {
214                         MessageHandler.errorln("char " + dot
215                                                + " has width 0. Using width 100 instead.");
216                         dotWidth = 100;
217                     }
218                     // if leader-alignment is used, calculate space to
219
// insert before leader so that all dots will be
220
// parallel.
221
if (leaderAlignment == LeaderAlignment.REFERENCE_AREA) {
222                         int nextRepeatedLeaderPatternCycle
223                             = (int)Math.ceil((double)position/(double)dotWidth);
224                         int spaceBeforeLeader =
225                             dotWidth * nextRepeatedLeaderPatternCycle
226                             - position;
227                         // appending indent space leader-alignment setting
228
// InlineSpace to false, so it is not used in line
229
// justification
230
if (spaceBeforeLeader > 0) {
231                             children.add(idx, new InlineSpace(spaceBeforeLeader,
232                                                               false));
233                             idx++;
234                             // shorten leaderLength, otherwise - in
235
// case of leaderLength=remaining length -
236
// it will cut off the end of leaderlength
237
leaderLengthOptimum -= spaceBeforeLeader;
238                         }
239                     }
240                     int factor = (int)Math.floor(leaderLengthOptimum / dotWidth);
241                     char[] leaderChars = new char[factor];
242                     for (int i = 0; i < factor; i++) {
243                         leaderChars[i] = dot;
244                     }
245                     String JavaDoc leaderWord = new String JavaDoc(leaderChars);
246                     int leaderWordWidth = fontState.getWordWidth(leaderWord);
247                     WordArea leaderPatternArea =
248                         new WordArea(fontState, red, green, blue,
249                                      leaderWord,leaderWordWidth);
250                     leaderPatternArea.setYOffset(placementOffset);
251                     children.add(idx, leaderPatternArea);
252                     int spaceAfterLeader = leaderLengthOptimum
253                         - leaderWordWidth;
254                     if (spaceAfterLeader!=0) {
255                         children.add(idx+1, new InlineSpace(spaceAfterLeader,
256                                                             false));
257                     }
258                 } else {
259                     // if leader-alignment is used, calculate space to
260
// insert before leader so that all dots will be
261
// parallel.
262
if (leaderAlignment == LeaderAlignment.REFERENCE_AREA) {
263                         int nextRepeatedLeaderPatternCycle
264                             = (int)Math.ceil((double)position/(double)leaderPatternWidth);
265                         int spaceBeforeLeader =
266                             leaderPatternWidth * nextRepeatedLeaderPatternCycle
267                             - position;
268                         // appending indent space leader-alignment setting
269
// InlineSpace to false, so it is not used in line
270
// justification
271
if (spaceBeforeLeader > 0) {
272                             children.add(idx, new InlineSpace(spaceBeforeLeader,
273                                                               false));
274                             idx++;
275                             // shorten leaderLength, otherwise - in
276
// case of leaderLength=remaining length -
277
// it will cut off the end of leaderlength
278
leaderLengthOptimum -= spaceBeforeLeader;
279                         }
280                     }
281                     // calculate the space to insert between the dots
282
// and create a inline area with this width
283
int dotsFactor =
284                         (int)Math.floor(((double)leaderLengthOptimum)
285                                         / ((double)leaderPatternWidth));
286                     // add combination of dot + space to fill leader
287
// is there a way to do this in a more effective way?
288
for (int i = 0; i < dotsFactor; i++) {
289                         InlineSpace spaceBetweenDots =
290                             new InlineSpace(leaderPatternWidth - dotWidth,
291                                             false);
292                         WordArea leaderPatternArea =
293                             new WordArea(this.fontState,
294                                          this.red, this.green, this.blue,
295                                          new String JavaDoc("."), dotWidth);
296                         leaderPatternArea.setYOffset(placementOffset);
297                         children.add(idx,leaderPatternArea);
298                         idx++;
299                         children.add(idx,spaceBetweenDots);
300                         idx++;
301                     }
302                     // append at the end some space to fill up to leader length
303
children.add(idx,new InlineSpace(leaderLengthOptimum
304                                                      - dotsFactor
305                                                      * leaderPatternWidth));
306                     idx++;
307                 }
308                 break;
309                 // leader pattern use-content not implemented.
310
case LeaderPattern.USECONTENT:
311                 MessageHandler.errorln("leader-pattern=\"use-content\" not "
312                                        + "supported by this version of Fop");
313                 return;
314             }
315         }
316     }
317  
318     public LineArea(FontState fontState, int lineHeight, int halfLeading,
319                     int allocationWidth, int startIndent, int endIndent,
320                     LineArea prevLineArea) {
321         super(fontState);
322
323         this.currentFontState = fontState;
324         this.lineHeight = lineHeight;
325         this.nominalFontSize = fontState.getFontSize();
326         this.nominalGlyphHeight = fontState.getAscender()
327             - fontState.getDescender();
328
329         this.placementOffset = fontState.getAscender();
330         this.contentRectangleWidth = allocationWidth - startIndent
331             - endIndent;
332         this.fontState = fontState;
333
334         this.allocationHeight = this.nominalGlyphHeight;
335         this.halfLeading = this.lineHeight - this.allocationHeight;
336
337         this.startIndent = startIndent;
338         this.endIndent = endIndent;
339
340         if (prevLineArea != null) {
341             // There might be InlineSpaces at the beginning
342
// that should not be there - eat them
343
boolean eatMoreSpace = true;
344             pendingWidth = prevLineArea.pendingWidth;
345
346             for (int i = 0; i < prevLineArea.pendingAreas.size(); i++) {
347                 Object JavaDoc b = prevLineArea.pendingAreas.get(i);
348                 if (eatMoreSpace) {
349                     if (b instanceof InlineSpace) {
350                         InlineSpace is = (InlineSpace)b;
351                         if (is.isEatable()) {
352                             pendingWidth -= is.getSize();
353                         } else {
354                             eatMoreSpace = false;
355                             pendingAreas.add(b);
356                         }
357                     } else {
358                         eatMoreSpace = false;
359                         pendingAreas.add(b);
360                     }
361                 } else {
362                     pendingAreas.add(b);
363                 }
364             }
365             prevLineArea.pendingWidth=0;
366             prevLineArea.pendingAreas=null;
367         }
368     }
369
370     public void render(Renderer renderer) {
371         if (pendingWidth > 0) {
372             MessageHandler.error("Areas pending, text probably lost in line"
373                                  + getLineText());
374         }
375         if (hasPageNumbers) {
376             IDReferences idReferences = renderer.getIDReferences();
377             for (int i = 0; i < children.size(); i++) {
378                 Object JavaDoc o = children.get(i);
379                 if ( o instanceof PageNumberInlineArea) {
380                     PageNumberInlineArea pia = (PageNumberInlineArea)o;
381                     FontState piaFontState = pia.getFontState();
382                     finalWidth-=piaFontState.getWordWidth(pia.getText());
383                     pia.resolve(idReferences);
384                     finalWidth+=piaFontState.getWordWidth(pia.getText());
385                 }
386             }
387         }
388         if (!aligned) {
389             int padding = 0;
390             switch (textAlign) {
391             case TextAlign.START: // left
392
padding = this.getContentWidth() - finalWidth;
393                 endIndent += padding;
394                 for (int i = 0; i < children.size(); i++) {
395                     Object JavaDoc o = children.get(i);
396                     if (o instanceof LineArea.Leader) {
397                         LineArea.Leader leader = (LineArea.Leader)o;
398                         leader.expand();
399                     }
400                 }
401                 break;
402             case TextAlign.END: // right
403
padding = this.getContentWidth() - finalWidth;
404                 startIndent += padding;
405                 for (int i = 0; i < children.size(); i++) {
406                     Object JavaDoc o = children.get(i);
407                     if (o instanceof LineArea.Leader) {
408                         LineArea.Leader leader = (LineArea.Leader)o;
409                         leader.expand();
410                     }
411                 }
412                 break;
413             case TextAlign.CENTER: // center
414
padding = (this.getContentWidth() - finalWidth) / 2;
415                 startIndent += padding;
416                 endIndent += padding;
417                 for (int i = 0; i < children.size(); i++) {
418                     Object JavaDoc o = children.get(i);
419                     if (o instanceof LineArea.Leader) {
420                         LineArea.Leader leader = (LineArea.Leader)o;
421                         leader.expand();
422                     }
423                 }
424                 break;
425             case TextAlign.JUSTIFY: // justify
426
// first pass - count the spaces
427
int leaderCount = 0;
428                 int spaceCount = 0;
429                 for (int i = 0; i < children.size(); i++ ) {
430                     Object JavaDoc o = children.get(i);
431                     if (o instanceof InlineSpace) {
432                         InlineSpace space = (InlineSpace)o;
433                         if (space.getResizeable()) {
434                             spaceCount++;
435                         }
436                     } else if(o instanceof LineArea.Leader) {
437                         leaderCount++;
438                     }
439                 }
440                 padding = (this.getContentWidth() - finalWidth);
441                 if (padding!=0) {
442                     if (leaderCount>0) {
443                         int offset=0;
444                         for (int i = 0; i < children.size(); i++) {
445                             Object JavaDoc o = children.get(i);
446                             if (o instanceof LineArea.Leader) {
447                                 LineArea.Leader leader = (LineArea.Leader)o;
448                                 int leaderExpansionMaximum=
449                                     leader.leaderLengthMaximum - leader.leaderLengthOptimum;
450                                 int leaderExpansionMinimum=
451                                     leader.leaderLengthMinimum - leader.leaderLengthOptimum;
452                                 if (leaderExpansionMaximum < padding) {
453                                     leader.leaderLengthOptimum =
454                                         leader.leaderLengthMaximum;
455                                     leader.expand();
456                                     padding-=leaderExpansionMaximum;
457                                     offset+=leaderExpansionMaximum;
458                                 } else if (padding < leaderExpansionMinimum) {
459                                     leader.leaderLengthOptimum =
460                                         leader.leaderLengthMinimum;
461                                     leader.expand();
462                                     padding-=leaderExpansionMinimum;
463                                     offset+=leaderExpansionMinimum;
464                                 } else {
465                                     leader.leaderLengthOptimum += padding;
466                                     leader.expand();
467                                     padding=0;
468                                     offset+=padding;
469                                 }
470                             } else if (o instanceof InlineArea) {
471                                 ((InlineArea)o).setXOffset(((InlineArea)o).getXOffset() + offset);
472                             }
473                         }
474                     }
475                     if (padding != 0) {
476                         if (spaceCount > 0) {
477                             if (padding > 0) {
478                                 // The line is actually short of
479
// padding mod spaceCount
480
// millipoints. Should implement
481
// Bresenham-like algorithm for
482
// compensating, but it's not worth
483
// yet.
484
// If there are ref-area aligned leaders,
485
// they will be no longer aligned.
486
padding = padding/spaceCount;
487                                 spaceCount = 0;
488                                 // second pass - add additional space
489
for (int i = 0; i < children.size(); i++) {
490                                     Object JavaDoc o = children.get(i);
491                                     if (o instanceof InlineSpace) {
492                                         InlineSpace space = (InlineSpace)o;
493                                         if (space.getResizeable()) {
494                                             space.setSize(space.getSize() + padding);
495                                             spaceCount++;
496                                         }
497                                     } else if (o instanceof InlineArea) {
498                                         ((InlineArea)o).setXOffset(((InlineArea)o).getXOffset() + i * padding);
499                                     }
500                                 }
501                             } else {
502                                 MessageHandler.log("Area overflow in line "
503                                                    + getLineText());
504                             }
505                         } else {
506                             // no spaces
507
MessageHandler.log("No spaces to justify text in line "
508                                                + getLineText());
509                         }
510                     }
511                 }
512                 break;
513             default:
514                 MessageHandler.errorln("bad align: "+textAlign);
515             break;
516             }
517             aligned = true;
518         }
519         renderer.renderLineArea(this);
520     }
521
522     public int addPageNumberCitation(String JavaDoc refid, LinkSet ls) {
523
524         /*
525          * We should add code here to handle the case where the page
526          * number doesn't fit on the current line
527          */

528
529         // Space must be allocated for the page number, so currently we
530
// give it 3 spaces
531

532         int width = 3*currentFontState.getCharWidth(' ');
533
534
535         PageNumberInlineArea pia
536             = new PageNumberInlineArea(currentFontState,
537                                        this.red, this.green, this.blue,
538                                        refid, width);
539         
540         pia.setYOffset(placementOffset);
541         pendingAreas.add(pia);
542         pendingWidth += width;
543         prev = TEXT;
544         hasPageNumbers = true;
545
546         return -1;
547     }
548
549
550     /**
551      * adds text to line area
552      *
553      * @return int character position
554      */

555     public int addText(char data[], int start, int end, LinkSet ls,
556                        TextState textState) {
557         // this prevents an array index out of bounds
558
// which occurs when some text is laid out again.
559
if (start == -1)
560             return -1;
561         boolean overrun = false;
562
563         int wordStart = start;
564         int wordLength = 0;
565         int wordWidth = 0;
566         // With CID fonts, space isn't neccesary currentFontState.width(32)
567
int whitespaceWidth = currentFontState.getCharWidth(' ');
568
569         boolean isText = false;
570         boolean isMultiByteChar = false;
571
572         /* iterate over each character */
573         for (int i = start; i < end; i++) {
574             int charWidth;
575             /* get the character */
576             char c = data[i];
577             if (!(isSpace(c) || (c == '\n') || (c == '\r') || (c == '\t')
578                   || (c == '\u2028'))) {
579                 charWidth = currentFontState.getCharWidth(c);
580                 isText = true;
581                 isMultiByteChar = (c > 127);
582                 // Add support for zero-width spaces
583
if (charWidth <= 0 && c != '\u200B' && c != '\uFEFF')
584                     charWidth = whitespaceWidth;
585             } else {
586                 if ((c == '\n') || (c == '\r') || (c == '\t'))
587                     charWidth = whitespaceWidth;
588                 else
589                     charWidth = currentFontState.getCharWidth(c);
590
591                 isText = false;
592                 isMultiByteChar = false;
593
594                 if (prev == WHITESPACE) {
595
596                     // if current & previous are WHITESPACE
597

598                     if (this.whiteSpaceCollapse == WhiteSpaceCollapse.FALSE) {
599                         if (isSpace(c)) {
600                             spaceWidth += currentFontState.getCharWidth(c);
601                         } else if (c == '\n' || c == '\u2028') {
602                             // force line break
603
if (spaceWidth > 0) {
604                                 InlineSpace is = new InlineSpace(spaceWidth);
605                                 is.setUnderlined(textState.getUnderlined());
606                                 is.setOverlined(textState.getOverlined());
607                                 is.setLineThrough(textState.getLineThrough());
608                                 addChild(is);
609                                 finalWidth += spaceWidth;
610                                 spaceWidth = 0;
611                             }
612                             return i + 1;
613                         } else if (c == '\t') {
614                             spaceWidth += 8 * whitespaceWidth;
615                         }
616                     } else if (c == '\u2028') {
617                         // Line separator
618
// Breaks line even if WhiteSpaceCollapse = True
619
if (spaceWidth > 0) {
620                             InlineSpace is = new InlineSpace(spaceWidth);
621                             is.setUnderlined(textState.getUnderlined());
622                             is.setOverlined(textState.getOverlined());
623                             is.setLineThrough(textState.getLineThrough());
624                             addChild(is);
625                             finalWidth += spaceWidth;
626                             spaceWidth = 0;
627                         }
628                         return i + 1;
629                     }
630
631                 } else if (prev == TEXT || prev == MULTIBYTECHAR ) {
632
633                     // if current is WHITESPACE and previous TEXT
634
// the current word made it, so
635
// add the space before the current word (if there
636
// was some)
637

638                     if (spaceWidth > 0) {
639                         InlineSpace is = new InlineSpace(spaceWidth);
640                         if (prevUlState) {
641                             is.setUnderlined(textState.getUnderlined());
642                         }
643                         if (prevOlState) {
644                             is.setOverlined(textState.getOverlined());
645                         }
646                         if (prevLTState) {
647                             is.setLineThrough(textState.getLineThrough());
648                         }
649                         addChild(is);
650                         finalWidth += spaceWidth;
651                         spaceWidth = 0;
652                     }
653
654                     // add any pending areas
655

656                     for (int j = 0; j < pendingAreas.size(); j++ ) {
657                         Box box = (Box)pendingAreas.get(j);
658                         if (box instanceof InlineArea) {
659                             if (ls != null) {
660                                 Rectangle JavaDoc lr =
661                                     new Rectangle JavaDoc(finalWidth, 0,
662                                                   ((InlineArea)box).getCont