KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lowagie > text > pdf > PdfLine


1 /*
2  * $Id: PdfLine.java 2742 2007-05-08 13:04:56Z blowagie $
3  * $Name$
4  *
5  * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
6  *
7  * The contents of this file are subject to the Mozilla Public License Version 1.1
8  * (the "License"); you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the License.
14  *
15  * The Original Code is 'iText, a free JAVA-PDF library'.
16  *
17  * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
18  * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
19  * All Rights Reserved.
20  * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
21  * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
22  *
23  * Contributor(s): all the names of the contributors are added in the source code
24  * where applicable.
25  *
26  * Alternatively, the contents of this file may be used under the terms of the
27  * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
28  * provisions of LGPL are applicable instead of those above. If you wish to
29  * allow use of your version of this file only under the terms of the LGPL
30  * License and not to allow others to use your version of this file under
31  * the MPL, indicate your decision by deleting the provisions above and
32  * replace them with the notice and other provisions required by the LGPL.
33  * If you do not delete the provisions above, a recipient may use your version
34  * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
35  *
36  * This library is free software; you can redistribute it and/or modify it
37  * under the terms of the MPL as stated above or under the terms of the GNU
38  * Library General Public License as published by the Free Software Foundation;
39  * either version 2 of the License, or any later version.
40  *
41  * This library is distributed in the hope that it will be useful, but WITHOUT
42  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
43  * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
44  * details.
45  *
46  * If you didn't download this code from the following link, you should check if
47  * you aren't using an obsolete version:
48  * http://www.lowagie.com/iText/
49  */

50
51 package com.lowagie.text.pdf;
52
53 import java.util.ArrayList JavaDoc;
54 import java.util.Iterator JavaDoc;
55
56 import com.lowagie.text.Chunk;
57 import com.lowagie.text.Element;
58 import com.lowagie.text.ListItem;
59
60 /**
61  * <CODE>PdfLine</CODE> defines an array with <CODE>PdfChunk</CODE>-objects
62  * that fit into 1 line.
63  */

64
65 public class PdfLine {
66     
67     // membervariables
68

69     /** The arraylist containing the chunks. */
70     protected ArrayList JavaDoc line;
71     
72     /** The left indentation of the line. */
73     protected float left;
74     
75     /** The width of the line. */
76     protected float width;
77     
78     /** The alignment of the line. */
79     protected int alignment;
80     
81     /** The heigth of the line. */
82     protected float height;
83     
84     /** The listsymbol (if necessary). */
85     protected Chunk listSymbol = null;
86     
87     /** The listsymbol (if necessary). */
88     protected float symbolIndent;
89     
90     /** <CODE>true</CODE> if the chunk splitting was caused by a newline. */
91     protected boolean newlineSplit = false;
92     
93     /** The original width. */
94     protected float originalWidth;
95     
96     protected boolean isRTL = false;
97     
98     // constructors
99

100     /**
101      * Constructs a new <CODE>PdfLine</CODE>-object.
102      *
103      * @param left the limit of the line at the left
104      * @param right the limit of the line at the right
105      * @param alignment the alignment of the line
106      * @param height the height of the line
107      */

108     
109     PdfLine(float left, float right, int alignment, float height) {
110         this.left = left;
111         this.width = right - left;
112         this.originalWidth = this.width;
113         this.alignment = alignment;
114         this.height = height;
115         this.line = new ArrayList JavaDoc();
116     }
117     
118     PdfLine(float left, float remainingWidth, int alignment, boolean newlineSplit, ArrayList JavaDoc line, boolean isRTL) {
119         this.left = left;
120         this.width = remainingWidth;
121         this.alignment = alignment;
122         this.line = line;
123         this.newlineSplit = newlineSplit;
124         this.isRTL = isRTL;
125     }
126     
127     // methods
128

129     /**
130      * Adds a <CODE>PdfChunk</CODE> to the <CODE>PdfLine</CODE>.
131      *
132      * @param chunk the <CODE>PdfChunk</CODE> to add
133      * @return <CODE>null</CODE> if the chunk could be added completely; if not
134      * a <CODE>PdfChunk</CODE> containing the part of the chunk that could
135      * not be added is returned
136      */

137     
138     PdfChunk add(PdfChunk chunk) {
139         // nothing happens if the chunk is null.
140
if (chunk == null || chunk.toString().equals("")) {
141             return null;
142         }
143         
144         // we split the chunk to be added
145
PdfChunk overflow = chunk.split(width);
146         newlineSplit = (chunk.isNewlineSplit() || overflow == null);
147         // if (chunk.isNewlineSplit() && alignment == Element.ALIGN_JUSTIFIED)
148
// alignment = Element.ALIGN_LEFT;
149

150         
151         // if the length of the chunk > 0 we add it to the line
152
if (chunk.length() > 0) {
153             if (overflow != null)
154                 chunk.trimLastSpace();
155             width -= chunk.width();
156             addToLine(chunk);
157         }
158         
159         // if the length == 0 and there were no other chunks added to the line yet,
160
// we risk to end up in an endless loop trying endlessly to add the same chunk
161
else if (line.size() < 1) {
162             chunk = overflow;
163             overflow = chunk.truncate(width);
164             width -= chunk.width();
165             if (chunk.length() > 0) {
166                 addToLine(chunk);
167                 return overflow;
168             }
169             // if the chunck couldn't even be truncated, we add everything, so be it
170
else {
171                 if (overflow != null)
172                     addToLine(overflow);
173                 return null;
174             }
175         }
176         else {
177             width += ((PdfChunk)(line.get(line.size() - 1))).trimLastSpace();
178         }
179         return overflow;
180     }
181     
182     private void addToLine(PdfChunk chunk) {
183         if (chunk.changeLeading && chunk.isImage()) {
184             float f = chunk.getImage().getScaledHeight() + chunk.getImageOffsetY();
185             if (f > height) height = f;
186         }
187         line.add(chunk);
188     }
189     
190     // methods to retrieve information
191

192     /**
193      * Returns the number of chunks in the line.
194      *
195      * @return a value
196      */

197     
198     public int size() {
199         return line.size();
200     }
201     
202     /**
203      * Returns an iterator of <CODE>PdfChunk</CODE>s.
204      *
205      * @return an <CODE>Iterator</CODE>
206      */

207     
208     public Iterator JavaDoc iterator() {
209         return line.iterator();
210     }
211     
212     /**
213      * Returns the height of the line.
214      *
215      * @return a value
216      */

217     
218     float height() {
219         return height;
220     }
221     
222     /**
223      * Returns the left indentation of the line taking the alignment of the line into account.
224      *
225      * @return a value
226      */

227     
228     float indentLeft() {
229         if (isRTL) {
230             switch (alignment) {
231                 case Element.ALIGN_LEFT:
232                     return left + width;
233                 case Element.ALIGN_CENTER:
234                     return left + (width / 2f);
235                 default:
236                     return left;
237             }
238         }
239         else {
240             switch (alignment) {
241                 case Element.ALIGN_RIGHT:
242                     return left + width;
243                 case Element.ALIGN_CENTER:
244                     return left + (width / 2f);
245                 default:
246                     return left;
247             }
248         }
249     }
250     
251     /**
252      * Checks if this line has to be justified.
253      *
254      * @return <CODE>true</CODE> if the alignment equals <VAR>ALIGN_JUSTIFIED</VAR> and there is some width left.
255      */

256     
257     public boolean hasToBeJustified() {
258         return ((alignment == Element.ALIGN_JUSTIFIED || alignment == Element.ALIGN_JUSTIFIED_ALL) && width != 0);
259     }
260     
261     /**
262      * Resets the alignment of this line.
263      * <P>
264      * The alignment of the last line of for instance a <CODE>Paragraph</CODE>
265      * that has to be justified, has to be reset to <VAR>ALIGN_LEFT</VAR>.
266      */

267     
268     public void resetAlignment() {
269         if (alignment == Element.ALIGN_JUSTIFIED) {
270             alignment = Element.ALIGN_LEFT;
271         }
272     }
273     
274     /** Adds extra indentation to the left (for Paragraph.setFirstLineIndent). */
275     void setExtraIndent(float extra) {
276         left += extra;
277         width -= extra;
278     }
279     
280     /**
281      * Returns the width that is left, after a maximum of characters is added to the line.
282      *
283      * @return a value
284      */

285     
286     float widthLeft() {
287         return width;
288     }
289     
290     /**
291      * Returns the number of space-characters in this line.
292      *
293      * @return a value
294      */

295     
296     int numberOfSpaces() {
297         String JavaDoc string = toString();
298         int length = string.length();
299         int numberOfSpaces = 0;
300         for (int i = 0; i < length; i++) {
301             if (string.charAt(i) == ' ') {
302                 numberOfSpaces++;
303             }
304         }
305         return numberOfSpaces;
306     }
307     
308     /**
309      * Sets the listsymbol of this line.
310      * <P>
311      * This is only necessary for the first line of a <CODE>ListItem</CODE>.
312      *
313      * @param listItem the list symbol
314      */

315     
316     public void setListItem(ListItem listItem) {
317         this.listSymbol = listItem.getListSymbol();
318         this.symbolIndent = listItem.getIndentationLeft();
319     }
320     
321     /**
322      * Returns the listsymbol of this line.
323      *
324      * @return a <CODE>PdfChunk</CODE> if the line has a listsymbol; <CODE>null</CODE> otherwise
325      */

326     
327     public Chunk listSymbol() {
328         return listSymbol;
329     }
330     
331     /**
332      * Return the indentation needed to show the listsymbol.
333      *
334      * @return a value
335      */

336     
337     public float listIndent() {
338         return symbolIndent;
339     }
340     
341     /**
342      * Get the string representation of what is in this line.
343      *
344      * @return a <CODE>String</CODE>
345      */

346     
347     public String JavaDoc toString() {
348         StringBuffer JavaDoc tmp = new StringBuffer JavaDoc();
349         for (Iterator JavaDoc i = line.iterator(); i.hasNext(); ) {
350             tmp.append(((PdfChunk) i.next()).toString());
351         }
352         return tmp.toString();
353     }
354     
355     /**
356      * Checks if a newline caused the line split.
357      * @return <CODE>true</CODE> if a newline caused the line split
358      */

359     public boolean isNewlineSplit() {
360         return newlineSplit && (alignment != Element.ALIGN_JUSTIFIED_ALL);
361     }
362     
363     /**
364      * Gets the index of the last <CODE>PdfChunk</CODE> with metric attributes
365      * @return the last <CODE>PdfChunk</CODE> with metric attributes
366      */

367     public int getLastStrokeChunk() {
368         int lastIdx = line.size() - 1;
369         for (; lastIdx >= 0; --lastIdx) {
370             PdfChunk chunk = (PdfChunk)line.get(lastIdx);
371             if (chunk.isStroked())
372                 break;
373         }
374         return lastIdx;
375     }
376     
377     /**
378      * Gets a <CODE>PdfChunk</CODE> by index.
379      * @param idx the index
380      * @return the <CODE>PdfChunk</CODE> or null if beyond the array
381      */

382     public PdfChunk getChunk(int idx) {
383         if (idx < 0 || idx >= line.size())
384             return null;
385         return (PdfChunk)line.get(idx);
386     }
387     
388     /**
389      * Gets the original width of the line.
390      * @return the original width of the line
391      */

392     public float getOriginalWidth() {
393         return originalWidth;
394     }
395     
396     /**
397      * Gets the maximum size of all the fonts used in this line
398      * including images.
399      * @return maximum size of all the fonts used in this line
400      */

401     float getMaxSizeSimple() {
402         float maxSize = 0;
403         for (int k = 0; k < line.size(); ++k) {
404             PdfChunk chunk = (PdfChunk)line.get(k);
405             if (!chunk.isImage()) {
406                 maxSize = Math.max(chunk.font().size(), maxSize);
407             }
408             else {
409                 maxSize = Math.max(chunk.getImage().getScaledHeight() + chunk.getImageOffsetY() , maxSize);
410             }
411         }
412         return maxSize;
413     }
414     
415     boolean isRTL() {
416         return isRTL;
417     }
418     
419     /**
420      * Gets a width corrected with a charSpacing and wordSpacing.
421      * @param charSpacing
422      * @param wordSpacing
423      * @return a corrected width
424      */

425     public float getWidthCorrected(float charSpacing, float wordSpacing) {
426         float total = 0;
427         for (int k = 0; k < line.size(); ++k) {
428             PdfChunk ck = (PdfChunk)line.get(k);
429             total += ck.getWidthCorrected(charSpacing, wordSpacing);
430         }
431         return total;
432     }
433     
434 /**
435  * Gets the maximum size of the ascender for all the fonts used
436  * in this line.
437  * @return maximum size of all the ascenders used in this line
438  */

439    public float getAscender() {
440        float ascender = 0;
441        for (int k = 0; k < line.size(); ++k) {
442            PdfChunk ck = (PdfChunk)line.get(k);
443            if (ck.isImage())
444                ascender = Math.max(ascender, ck.getImage().getScaledHeight() + ck.getImageOffsetY());
445            else {
446                PdfFont font = ck.font();
447                ascender = Math.max(ascender, font.getFont().getFontDescriptor(BaseFont.ASCENT, font.size()));
448            }
449        }
450        return ascender;
451    }
452
453 /**
454  * Gets the biggest descender for all the fonts used
455  * in this line. Note that this is a negative number.
456  * @return maximum size of all the ascenders used in this line
457  */

458     public float getDescender() {
459         float descender = 0;
460         for (int k = 0; k < line.size(); ++k) {
461             PdfChunk ck = (PdfChunk)line.get(k);
462             if (ck.isImage())
463                 descender = Math.min(descender, ck.getImageOffsetY());
464             else {
465                 PdfFont font = ck.font();
466                 descender = Math.min(descender, font.getFont().getFontDescriptor(BaseFont.DESCENT, font.size()));
467             }
468         }
469         return descender;
470     }
471 }
Popular Tags