1 | /* | |
2 | * $Id: MultiColumnText.java 4065 2009-09-16 23:09:11Z psoares33 $ | |
3 | * | |
4 | * Copyright 2004 Steve Appling | |
5 | * | |
6 | * The contents of this file are subject to the Mozilla Public License Version 1.1 | |
7 | * (the "License"); you may not use this file except in compliance with the License. | |
8 | * You may obtain a copy of the License at http://www.mozilla.org/MPL/ | |
9 | * | |
10 | * Software distributed under the License is distributed on an "AS IS" basis, | |
11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
12 | * for the specific language governing rights and limitations under the License. | |
13 | * | |
14 | * The Original Code is 'iText, a free JAVA-PDF library'. | |
15 | * | |
16 | * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by | |
17 | * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie. | |
18 | * All Rights Reserved. | |
19 | * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer | |
20 | * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved. | |
21 | * | |
22 | * Contributor(s): all the names of the contributors are added in the source code | |
23 | * where applicable. | |
24 | * | |
25 | * Alternatively, the contents of this file may be used under the terms of the | |
26 | * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the | |
27 | * provisions of LGPL are applicable instead of those above. If you wish to | |
28 | * allow use of your version of this file only under the terms of the LGPL | |
29 | * License and not to allow others to use your version of this file under | |
30 | * the MPL, indicate your decision by deleting the provisions above and | |
31 | * replace them with the notice and other provisions required by the LGPL. | |
32 | * If you do not delete the provisions above, a recipient may use your version | |
33 | * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE. | |
34 | * | |
35 | * This library is free software; you can redistribute it and/or modify it | |
36 | * under the terms of the MPL as stated above or under the terms of the GNU | |
37 | * Library General Public License as published by the Free Software Foundation; | |
38 | * either version 2 of the License, or any later version. | |
39 | * | |
40 | * This library is distributed in the hope that it will be useful, but WITHOUT | |
41 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
42 | * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more | |
43 | * details. | |
44 | * | |
45 | * If you didn't download this code from the following link, you should check if | |
46 | * you aren't using an obsolete version: | |
47 | * http://www.lowagie.com/iText/ | |
48 | */ | |
49 | ||
50 | package com.lowagie.text.pdf; | |
51 | ||
52 | import java.util.ArrayList; | |
53 | import com.lowagie.text.error_messages.MessageLocalization; | |
54 | ||
55 | import com.lowagie.text.Chunk; | |
56 | import com.lowagie.text.DocumentException; | |
57 | import com.lowagie.text.Element; | |
58 | import com.lowagie.text.ElementListener; | |
59 | import com.lowagie.text.Phrase; | |
60 | import com.lowagie.text.Rectangle; | |
61 | ||
62 | /** | |
63 | * Formats content into one or more columns bounded by a | |
64 | * rectangle. The columns may be simple rectangles or | |
65 | * more complicated shapes. Add all of the columns before | |
66 | * adding content. Column continuation is supported. A MultiColumnText object may be added to | |
67 | * a document using <CODE>Document.add</CODE>. | |
68 | * @author Steve Appling | |
69 | */ | |
70 | public class MultiColumnText implements Element { | |
71 | ||
72 | /** special constant for automatic calculation of height */ | |
73 | public static final float AUTOMATIC = -1f; | |
74 | ||
75 | /** | |
76 | * total desiredHeight of columns. If <CODE>AUTOMATIC</CODE>, this means fill pages until done. | |
77 | * This may be larger than one page | |
78 | */ | |
79 | private float desiredHeight; | |
80 | ||
81 | /** | |
82 | * total height of element written out so far | |
83 | */ | |
84 | private float totalHeight; | |
85 | ||
86 | /** | |
87 | * true if all the text could not be written out due to height restriction | |
88 | */ | |
89 | private boolean overflow; | |
90 | ||
91 | /** | |
92 | * Top of the columns - y position on starting page. | |
93 | * If <CODE>AUTOMATIC</CODE>, it means current y position when added to document | |
94 | */ | |
95 | private float top; | |
96 | ||
97 | /** | |
98 | * ColumnText object used to do all the real work. This same object is used for all columns | |
99 | */ | |
100 | private ColumnText columnText; | |
101 | ||
102 | /** | |
103 | * Array of <CODE>ColumnDef</CODE> objects used to define the columns | |
104 | */ | |
105 | private ArrayList columnDefs; | |
106 | ||
107 | /** | |
108 | * true if all columns are simple (rectangular) | |
109 | */ | |
110 | private boolean simple = true; | |
111 | ||
112 | private int currentColumn = 0; | |
113 | | |
114 | private float nextY = AUTOMATIC; | |
115 | | |
116 | private boolean columnsRightToLeft = false; | |
117 | | |
118 | private PdfDocument document; | |
119 | /** | |
120 | * Default constructor. Sets height to <CODE>AUTOMATIC</CODE>. | |
121 | * Columns will repeat on each page as necessary to accommodate content length. | |
122 | */ | |
123 | public MultiColumnText() { | |
124 | this(AUTOMATIC); | |
125 | } | |
126 | ||
127 | /** | |
128 | * Construct a MultiColumnText container of the specified height. | |
129 | * If height is <CODE>AUTOMATIC</CODE>, fill complete pages until done. | |
130 | * If a specific height is used, it may span one or more pages. | |
131 | * | |
132 | * @param height | |
133 | */ | |
134 | public MultiColumnText(float height) { | |
135 | columnDefs = new ArrayList(); | |
136 | desiredHeight = height; | |
137 | top = AUTOMATIC; | |
138 | // canvas will be set later | |
139 | columnText = new ColumnText(null); | |
140 | totalHeight = 0f; | |
141 | } | |
142 | ||
143 | /** | |
144 | * Construct a MultiColumnText container of the specified height | |
145 | * starting at the specified Y position. | |
146 | * | |
147 | * @param height | |
148 | * @param top | |
149 | */ | |
150 | public MultiColumnText(float top, float height) { | |
151 | columnDefs = new ArrayList(); | |
152 | desiredHeight = height; | |
153 | this.top = top; | |
154 | nextY = top; | |
155 | // canvas will be set later | |
156 | columnText = new ColumnText(null); | |
157 | totalHeight = 0f; | |
158 | } | |
159 | | |
160 | /** | |
161 | * Indicates that all of the text did not fit in the | |
162 | * specified height. Note that isOverflow will return | |
163 | * false before the MultiColumnText object has been | |
164 | * added to the document. It will always be false if | |
165 | * the height is AUTOMATIC. | |
166 | * | |
167 | * @return true if there is still space left in the column | |
168 | */ | |
169 | public boolean isOverflow() { | |
170 | return overflow; | |
171 | } | |
172 | ||
173 | /** | |
174 | * Copy the parameters from the specified ColumnText to use | |
175 | * when rendering. Parameters like <CODE>setArabicOptions</CODE> | |
176 | * must be set in this way. | |
177 | * | |
178 | * @param sourceColumn | |
179 | */ | |
180 | public void useColumnParams(ColumnText sourceColumn) { | |
181 | // note that canvas will be overwritten later | |
182 | columnText.setSimpleVars(sourceColumn); | |
183 | } | |
184 | ||
185 | /** | |
186 | * Add a new column. The parameters are limits for each column | |
187 | * wall in the format of a sequence of points (x1,y1,x2,y2,...). | |
188 | * | |
189 | * @param left limits for left column | |
190 | * @param right limits for right column | |
191 | */ | |
192 | public void addColumn(float[] left, float[] right) { | |
193 | ColumnDef nextDef = new ColumnDef(left, right); | |
194 |
1
1. addColumn : negated conditional → NO_COVERAGE |
if (!nextDef.isSimple()) simple = false; |
195 | columnDefs.add(nextDef); | |
196 | } | |
197 | ||
198 | /** | |
199 | * Add a simple rectangular column with specified left | |
200 | * and right x position boundaries. | |
201 | * | |
202 | * @param left left boundary | |
203 | * @param right right boundary | |
204 | */ | |
205 | public void addSimpleColumn(float left, float right) { | |
206 | ColumnDef newCol = new ColumnDef(left, right); | |
207 | columnDefs.add(newCol); | |
208 | } | |
209 | ||
210 | /** | |
211 | * Add the specified number of evenly spaced rectangular columns. | |
212 | * Columns will be separated by the specified gutterWidth. | |
213 | * | |
214 | * @param left left boundary of first column | |
215 | * @param right right boundary of last column | |
216 | * @param gutterWidth width of gutter spacing between columns | |
217 | * @param numColumns number of columns to add | |
218 | */ | |
219 | public void addRegularColumns(float left, float right, float gutterWidth, int numColumns) { | |
220 | float currX = left; | |
221 |
1
1. addRegularColumns : Replaced float subtraction with addition → NO_COVERAGE |
float width = right - left; |
222 |
4
1. addRegularColumns : Replaced integer subtraction with addition → NO_COVERAGE 2. addRegularColumns : Replaced float multiplication with division → NO_COVERAGE 3. addRegularColumns : Replaced float subtraction with addition → NO_COVERAGE 4. addRegularColumns : Replaced float division with multiplication → NO_COVERAGE |
float colWidth = (width - (gutterWidth * (numColumns - 1))) / numColumns; |
223 |
3
1. addRegularColumns : changed conditional boundary → NO_COVERAGE 2. addRegularColumns : Changed increment from 1 to -1 → NO_COVERAGE 3. addRegularColumns : negated conditional → NO_COVERAGE |
for (int i = 0; i < numColumns; i++) { |
224 |
2
1. addRegularColumns : Replaced float addition with subtraction → NO_COVERAGE 2. addRegularColumns : removed call to com/lowagie/text/pdf/MultiColumnText::addSimpleColumn → NO_COVERAGE |
addSimpleColumn(currX, currX + colWidth); |
225 |
2
1. addRegularColumns : Replaced float addition with subtraction → NO_COVERAGE 2. addRegularColumns : Replaced float addition with subtraction → NO_COVERAGE |
currX += colWidth + gutterWidth; |
226 | } | |
227 | } | |
228 | ||
229 | /** | |
230 | * Adds a <CODE>Phrase</CODE> to the current text array. | |
231 | * Will not have any effect if addElement() was called before. | |
232 | * @param phrase the text | |
233 | * @since 2.1.5 | |
234 | */ | |
235 | public void addText(Phrase phrase) { | |
236 | columnText.addText(phrase); | |
237 | } | |
238 | | |
239 | /** | |
240 | * Adds a <CODE>Chunk</CODE> to the current text array. | |
241 | * Will not have any effect if addElement() was called before. | |
242 | * @param chunk the text | |
243 | * @since 2.1.5 | |
244 | */ | |
245 | public void addText(Chunk chunk) { | |
246 | columnText.addText(chunk); | |
247 | } | |
248 | | |
249 | /** | |
250 | * Add an element to be rendered in a column. | |
251 | * Note that you can only add a <CODE>Phrase</CODE> | |
252 | * or a <CODE>Chunk</CODE> if the columns are | |
253 | * not all simple. This is an underlying restriction in | |
254 | * {@link com.lowagie.text.pdf.ColumnText} | |
255 | * | |
256 | * @param element element to add | |
257 | * @throws DocumentException if element can't be added | |
258 | */ | |
259 | public void addElement(Element element) throws DocumentException { | |
260 |
1
1. addElement : negated conditional → NO_COVERAGE |
if (simple) { |
261 |
1
1. addElement : removed call to com/lowagie/text/pdf/ColumnText::addElement → NO_COVERAGE |
columnText.addElement(element); |
262 |
1
1. addElement : negated conditional → NO_COVERAGE |
} else if (element instanceof Phrase) { |
263 |
1
1. addElement : removed call to com/lowagie/text/pdf/ColumnText::addText → NO_COVERAGE |
columnText.addText((Phrase) element); |
264 |
1
1. addElement : negated conditional → NO_COVERAGE |
} else if (element instanceof Chunk) { |
265 |
1
1. addElement : removed call to com/lowagie/text/pdf/ColumnText::addText → NO_COVERAGE |
columnText.addText((Chunk) element); |
266 | } else { | |
267 | throw new DocumentException(MessageLocalization.getComposedMessage("can.t.add.1.to.multicolumntext.with.complex.columns", element.getClass())); | |
268 | } | |
269 | } | |
270 | ||
271 | ||
272 | /** | |
273 | * Write out the columns. After writing, use | |
274 | * {@link #isOverflow()} to see if all text was written. | |
275 | * @param canvas PdfContentByte to write with | |
276 | * @param document document to write to (only used to get page limit info) | |
277 | * @param documentY starting y position to begin writing at | |
278 | * @return the current height (y position) after writing the columns | |
279 | * @throws DocumentException on error | |
280 | */ | |
281 | public float write(PdfContentByte canvas, PdfDocument document, float documentY) throws DocumentException { | |
282 | this.document = document; | |
283 |
1
1. write : removed call to com/lowagie/text/pdf/ColumnText::setCanvas → NO_COVERAGE |
columnText.setCanvas(canvas); |
284 |
1
1. write : negated conditional → NO_COVERAGE |
if (columnDefs.isEmpty()) { |
285 | throw new DocumentException(MessageLocalization.getComposedMessage("multicolumntext.has.no.columns")); | |
286 | } | |
287 | overflow = false; | |
288 | float currentHeight = 0; | |
289 | boolean done = false; | |
290 | try { | |
291 |
1
1. write : negated conditional → NO_COVERAGE |
while (!done) { |
292 |
1
1. write : negated conditional → NO_COVERAGE |
if (top == AUTOMATIC) { |
293 | top = document.getVerticalPosition(true); // RS - 07/07/2005 - Get current doc writing position for top of columns on new page. | |
294 | } | |
295 |
1
1. write : negated conditional → NO_COVERAGE |
else if (nextY == AUTOMATIC) { |
296 | nextY = document.getVerticalPosition(true); // RS - 07/07/2005 - - Get current doc writing position for top of columns on new page. | |
297 | } | |
298 | ColumnDef currentDef = (ColumnDef) columnDefs.get(getCurrentColumn()); | |
299 |
1
1. write : removed call to com/lowagie/text/pdf/ColumnText::setYLine → NO_COVERAGE |
columnText.setYLine(top); |
300 | ||
301 | float[] left = currentDef.resolvePositions(Rectangle.LEFT); | |
302 | float[] right = currentDef.resolvePositions(Rectangle.RIGHT); | |
303 |
3
1. write : Replaced integer modulus with multiplication → NO_COVERAGE 2. write : negated conditional → NO_COVERAGE 3. write : negated conditional → NO_COVERAGE |
if (document.isMarginMirroring() && document.getPageNumber() % 2 == 0){ |
304 |
1
1. write : Replaced float subtraction with addition → NO_COVERAGE |
float delta = document.rightMargin() - document.left(); |
305 | left = left.clone(); | |
306 | right = right.clone(); | |
307 |
2
1. write : changed conditional boundary → NO_COVERAGE 2. write : negated conditional → NO_COVERAGE |
for (int i = 0; i < left.length; i += 2) { |
308 |
1
1. write : Replaced float subtraction with addition → NO_COVERAGE |
left[i] -= delta; |
309 | } | |
310 |
2
1. write : changed conditional boundary → NO_COVERAGE 2. write : negated conditional → NO_COVERAGE |
for (int i = 0; i < right.length; i += 2) { |
311 |
1
1. write : Replaced float subtraction with addition → NO_COVERAGE |
right[i] -= delta; |
312 | } | |
313 | } | |
314 | | |
315 | currentHeight = Math.max(currentHeight, getHeight(left, right)); | |
316 | ||
317 |
1
1. write : negated conditional → NO_COVERAGE |
if (currentDef.isSimple()) { |
318 |
1
1. write : removed call to com/lowagie/text/pdf/ColumnText::setSimpleColumn → NO_COVERAGE |
columnText.setSimpleColumn(left[2], left[3], right[0], right[1]); |
319 | } else { | |
320 |
1
1. write : removed call to com/lowagie/text/pdf/ColumnText::setColumns → NO_COVERAGE |
columnText.setColumns(left, right); |
321 | } | |
322 | ||
323 | int result = columnText.go(); | |
324 |
2
1. write : Replaced bitwise AND with OR → NO_COVERAGE 2. write : negated conditional → NO_COVERAGE |
if ((result & ColumnText.NO_MORE_TEXT) != 0) { |
325 | done = true; | |
326 | top = columnText.getYLine(); | |
327 |
1
1. write : negated conditional → NO_COVERAGE |
} else if (shiftCurrentColumn()) { |
328 | top = nextY; | |
329 | } else { // check if we are done because of height | |
330 |
1
1. write : Replaced float addition with subtraction → NO_COVERAGE |
totalHeight += currentHeight; |
331 |
3
1. write : changed conditional boundary → NO_COVERAGE 2. write : negated conditional → NO_COVERAGE 3. write : negated conditional → NO_COVERAGE |
if ((desiredHeight != AUTOMATIC) && (totalHeight >= desiredHeight)) { |
332 | overflow = true; | |
333 | break; | |
334 | } else { // need to start new page and reset the columns | |
335 | documentY = nextY; | |
336 |
1
1. write : removed call to com/lowagie/text/pdf/MultiColumnText::newPage → NO_COVERAGE |
newPage(); |
337 | currentHeight = 0; | |
338 | } | |
339 | } | |
340 | } | |
341 | } catch (DocumentException ex) { | |
342 |
1
1. write : removed call to com/lowagie/text/DocumentException::printStackTrace → NO_COVERAGE |
ex.printStackTrace(); |
343 | throw ex; | |
344 | } | |
345 |
2
1. write : negated conditional → NO_COVERAGE 2. write : negated conditional → NO_COVERAGE |
if (desiredHeight == AUTOMATIC && columnDefs.size() == 1) { |
346 |
1
1. write : Replaced float subtraction with addition → NO_COVERAGE |
currentHeight = documentY - columnText.getYLine(); |
347 | } | |
348 |
1
1. write : replaced return of float value with -(x + 1) for com/lowagie/text/pdf/MultiColumnText::write → NO_COVERAGE |
return currentHeight; |
349 | } | |
350 | ||
351 | private void newPage() throws DocumentException { | |
352 |
1
1. newPage : removed call to com/lowagie/text/pdf/MultiColumnText::resetCurrentColumn → NO_COVERAGE |
resetCurrentColumn(); |
353 |
1
1. newPage : negated conditional → NO_COVERAGE |
if (desiredHeight == AUTOMATIC) { |
354 | top = nextY = AUTOMATIC; | |
355 | } | |
356 | else { | |
357 | top = nextY; | |
358 | } | |
359 | totalHeight = 0; | |
360 |
1
1. newPage : negated conditional → NO_COVERAGE |
if (document != null) { |
361 | document.newPage(); | |
362 | } | |
363 | } | |
364 | | |
365 | /** | |
366 | * Figure out the height of a column from the border extents | |
367 | * | |
368 | * @param left left border | |
369 | * @param right right border | |
370 | * @return height | |
371 | */ | |
372 | private float getHeight(float[] left, float[] right) { | |
373 | float max = Float.MIN_VALUE; | |
374 | float min = Float.MAX_VALUE; | |
375 |
2
1. getHeight : changed conditional boundary → NO_COVERAGE 2. getHeight : negated conditional → NO_COVERAGE |
for (int i = 0; i < left.length; i += 2) { |
376 |
1
1. getHeight : Replaced integer addition with subtraction → NO_COVERAGE |
min = Math.min(min, left[i + 1]); |
377 |
1
1. getHeight : Replaced integer addition with subtraction → NO_COVERAGE |
max = Math.max(max, left[i + 1]); |
378 | } | |
379 |
2
1. getHeight : changed conditional boundary → NO_COVERAGE 2. getHeight : negated conditional → NO_COVERAGE |
for (int i = 0; i < right.length; i += 2) { |
380 |
1
1. getHeight : Replaced integer addition with subtraction → NO_COVERAGE |
min = Math.min(min, right[i + 1]); |
381 |
1
1. getHeight : Replaced integer addition with subtraction → NO_COVERAGE |
max = Math.max(max, right[i + 1]); |
382 | } | |
383 |
2
1. getHeight : Replaced float subtraction with addition → NO_COVERAGE 2. getHeight : replaced return of float value with -(x + 1) for com/lowagie/text/pdf/MultiColumnText::getHeight → NO_COVERAGE |
return max - min; |
384 | } | |
385 | ||
386 | ||
387 | /** | |
388 | * Processes the element by adding it to an | |
389 | * <CODE>ElementListener</CODE>. | |
390 | * | |
391 | * @param listener an <CODE>ElementListener</CODE> | |
392 | * @return <CODE>true</CODE> if the element was processed successfully | |
393 | */ | |
394 | public boolean process(ElementListener listener) { | |
395 | try { | |
396 |
1
1. process : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return listener.add(this); |
397 | } catch (DocumentException de) { | |
398 |
1
1. process : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
399 | } | |
400 | } | |
401 | ||
402 | /** | |
403 | * Gets the type of the text element. | |
404 | * | |
405 | * @return a type | |
406 | */ | |
407 | ||
408 | public int type() { | |
409 | return Element.MULTI_COLUMN_TEXT; | |
410 | } | |
411 | ||
412 | /** | |
413 | * Returns null - not used | |
414 | * | |
415 | * @return null | |
416 | */ | |
417 | ||
418 | public ArrayList getChunks() { | |
419 | return null; | |
420 | } | |
421 | | |
422 | /** | |
423 | * @see com.lowagie.text.Element#isContent() | |
424 | * @since iText 2.0.8 | |
425 | */ | |
426 | public boolean isContent() { | |
427 | return true; | |
428 | } | |
429 | ||
430 | /** | |
431 | * @see com.lowagie.text.Element#isNestable() | |
432 | * @since iText 2.0.8 | |
433 | */ | |
434 | public boolean isNestable() { | |
435 | return false; | |
436 | } | |
437 | ||
438 | /** | |
439 | * Calculates the appropriate y position for the bottom | |
440 | * of the columns on this page. | |
441 | * | |
442 | * @return the y position of the bottom of the columns | |
443 | */ | |
444 | private float getColumnBottom() { | |
445 |
1
1. getColumnBottom : negated conditional → NO_COVERAGE |
if (desiredHeight == AUTOMATIC) { |
446 |
1
1. getColumnBottom : replaced return of float value with -(x + 1) for com/lowagie/text/pdf/MultiColumnText::getColumnBottom → NO_COVERAGE |
return document.bottom(); |
447 | } else { | |
448 |
3
1. getColumnBottom : Replaced float subtraction with addition → NO_COVERAGE 2. getColumnBottom : Replaced float subtraction with addition → NO_COVERAGE 3. getColumnBottom : replaced return of float value with -(x + 1) for com/lowagie/text/pdf/MultiColumnText::getColumnBottom → NO_COVERAGE |
return Math.max(top - (desiredHeight - totalHeight), document.bottom()); |
449 | } | |
450 | } | |
451 | ||
452 | /** | |
453 | * Moves the text insertion point to the beginning of the next column, issuing a page break if | |
454 | * needed. | |
455 | * @throws DocumentException on error | |
456 | */ | |
457 | public void nextColumn() throws DocumentException { | |
458 |
2
1. nextColumn : Replaced integer addition with subtraction → NO_COVERAGE 2. nextColumn : Replaced integer modulus with multiplication → NO_COVERAGE |
currentColumn = (currentColumn + 1) % columnDefs.size(); |
459 | top = nextY; | |
460 |
1
1. nextColumn : negated conditional → NO_COVERAGE |
if (currentColumn == 0) { |
461 |
1
1. nextColumn : removed call to com/lowagie/text/pdf/MultiColumnText::newPage → NO_COVERAGE |
newPage(); |
462 | } | |
463 | } | |
464 | ||
465 | /** | |
466 | * Gets the current column. | |
467 | * @return the current column | |
468 | */ | |
469 | public int getCurrentColumn() { | |
470 |
1
1. getCurrentColumn : negated conditional → NO_COVERAGE |
if (columnsRightToLeft) { |
471 |
3
1. getCurrentColumn : Replaced integer subtraction with addition → NO_COVERAGE 2. getCurrentColumn : Replaced integer subtraction with addition → NO_COVERAGE 3. getCurrentColumn : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return (columnDefs.size() - currentColumn - 1); |
472 | } | |
473 |
1
1. getCurrentColumn : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return currentColumn; |
474 | } | |
475 | | |
476 | /** | |
477 | * Resets the current column. | |
478 | */ | |
479 | public void resetCurrentColumn() { | |
480 | currentColumn = 0; | |
481 | } | |
482 | | |
483 | /** | |
484 | * Shifts the current column. | |
485 | * @return true if the current column has changed | |
486 | */ | |
487 | public boolean shiftCurrentColumn() { | |
488 |
3
1. shiftCurrentColumn : changed conditional boundary → NO_COVERAGE 2. shiftCurrentColumn : Replaced integer addition with subtraction → NO_COVERAGE 3. shiftCurrentColumn : negated conditional → NO_COVERAGE |
if (currentColumn + 1 < columnDefs.size()) { |
489 |
1
1. shiftCurrentColumn : Replaced integer addition with subtraction → NO_COVERAGE |
currentColumn++; |
490 |
1
1. shiftCurrentColumn : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return true; |
491 | } | |
492 |
1
1. shiftCurrentColumn : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
493 | } | |
494 | | |
495 | /** | |
496 | * Sets the direction of the columns. | |
497 | * @param direction true = right2left; false = left2right | |
498 | */ | |
499 | public void setColumnsRightToLeft(boolean direction) { | |
500 | columnsRightToLeft = direction; | |
501 | } | |
502 | | |
503 | /** Sets the ratio between the extra word spacing and the extra character spacing | |
504 | * when the text is fully justified. | |
505 | * Extra word spacing will grow <CODE>spaceCharRatio</CODE> times more than extra character spacing. | |
506 | * If the ratio is <CODE>PdfWriter.NO_SPACE_CHAR_RATIO</CODE> then the extra character spacing | |
507 | * will be zero. | |
508 | * @param spaceCharRatio the ratio between the extra word spacing and the extra character spacing | |
509 | */ | |
510 | public void setSpaceCharRatio(float spaceCharRatio) { | |
511 | columnText.setSpaceCharRatio(spaceCharRatio); | |
512 | } | |
513 | ||
514 | /** Sets the run direction. | |
515 | * @param runDirection the run direction | |
516 | */ | |
517 | public void setRunDirection(int runDirection) { | |
518 | columnText.setRunDirection(runDirection); | |
519 | } | |
520 | | |
521 | /** Sets the arabic shaping options. The option can be AR_NOVOWEL, | |
522 | * AR_COMPOSEDTASHKEEL and AR_LIG. | |
523 | * @param arabicOptions the arabic shaping options | |
524 | */ | |
525 | public void setArabicOptions(int arabicOptions) { | |
526 | columnText.setArabicOptions(arabicOptions); | |
527 | } | |
528 | | |
529 | /** Sets the default alignment | |
530 | * @param alignment the default alignment | |
531 | */ | |
532 | public void setAlignment(int alignment) { | |
533 | columnText.setAlignment(alignment); | |
534 | } | |
535 | | |
536 | /** | |
537 | * Inner class used to define a column | |
538 | */ | |
539 | private class ColumnDef { | |
540 | private float[] left; | |
541 | private float[] right; | |
542 | ||
543 | ColumnDef(float[] newLeft, float[] newRight) { | |
544 | left = newLeft; | |
545 | right = newRight; | |
546 | } | |
547 | ||
548 | ColumnDef(float leftPosition, float rightPosition) { | |
549 | left = new float[4]; | |
550 | left[0] = leftPosition; // x1 | |
551 | left[1] = top; // y1 | |
552 | left[2] = leftPosition; // x2 | |
553 |
2
1. 2. |
if (desiredHeight == AUTOMATIC || top == AUTOMATIC) { |
554 | left[3] = AUTOMATIC; | |
555 | } else { | |
556 |
1
1. |
left[3] = top - desiredHeight; |
557 | } | |
558 | ||
559 | right = new float[4]; | |
560 | right[0] = rightPosition; // x1 | |
561 | right[1] = top; // y1 | |
562 | right[2] = rightPosition; // x2 | |
563 |
2
1. 2. |
if (desiredHeight == AUTOMATIC || top == AUTOMATIC) { |
564 | right[3] = AUTOMATIC; | |
565 | } else { | |
566 |
1
1. |
right[3] = top - desiredHeight; |
567 | } | |
568 | } | |
569 | ||
570 | /** | |
571 | * Resolves the positions for the specified side of the column | |
572 | * into real numbers once the top of the column is known. | |
573 | * | |
574 | * @param side either <CODE>Rectangle.LEFT</CODE> | |
575 | * or <CODE>Rectangle.RIGHT</CODE> | |
576 | * @return the array of floats for the side | |
577 | */ | |
578 | float[] resolvePositions(int side) { | |
579 |
1
1. resolvePositions : negated conditional → NO_COVERAGE |
if (side == Rectangle.LEFT) { |
580 |
1
1. resolvePositions : mutated return of Object value for com/lowagie/text/pdf/MultiColumnText$ColumnDef::resolvePositions to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return resolvePositions(left); |
581 | } else { | |
582 |
1
1. resolvePositions : mutated return of Object value for com/lowagie/text/pdf/MultiColumnText$ColumnDef::resolvePositions to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return resolvePositions(right); |
583 | } | |
584 | } | |
585 | ||
586 | private float[] resolvePositions(float[] positions) { | |
587 |
1
1. resolvePositions : negated conditional → NO_COVERAGE |
if (!isSimple()) { |
588 | positions[1] = top; | |
589 |
1
1. resolvePositions : mutated return of Object value for com/lowagie/text/pdf/MultiColumnText$ColumnDef::resolvePositions to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return positions; |
590 | } | |
591 |
1
1. resolvePositions : negated conditional → NO_COVERAGE |
if (top == AUTOMATIC) { |
592 | // this is bad - must be programmer error | |
593 | throw new RuntimeException("resolvePositions called with top=AUTOMATIC (-1). " + | |
594 | "Top position must be set befure lines can be resolved"); | |
595 | } | |
596 | positions[1] = top; | |
597 | positions[3] = getColumnBottom(); | |
598 |
1
1. resolvePositions : mutated return of Object value for com/lowagie/text/pdf/MultiColumnText$ColumnDef::resolvePositions to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return positions; |
599 | } | |
600 | ||
601 | /** | |
602 | * Checks if column definition is a simple rectangle | |
603 | * @return true if it is a simple column | |
604 | */ | |
605 | private boolean isSimple() { | |
606 |
5
1. isSimple : negated conditional → NO_COVERAGE 2. isSimple : negated conditional → NO_COVERAGE 3. isSimple : negated conditional → NO_COVERAGE 4. isSimple : negated conditional → NO_COVERAGE 5. isSimple : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return (left.length == 4 && right.length == 4) && (left[0] == left[2] && right[0] == right[2]); |
607 | } | |
608 | ||
609 | } | |
610 | } | |
Mutations | ||
194 |
1.1 |
|
221 |
1.1 |
|
222 |
1.1 2.2 3.3 4.4 |
|
223 |
1.1 2.2 3.3 |
|
224 |
1.1 2.2 |
|
225 |
1.1 2.2 |
|
260 |
1.1 |
|
261 |
1.1 |
|
262 |
1.1 |
|
263 |
1.1 |
|
264 |
1.1 |
|
265 |
1.1 |
|
283 |
1.1 |
|
284 |
1.1 |
|
291 |
1.1 |
|
292 |
1.1 |
|
295 |
1.1 |
|
299 |
1.1 |
|
303 |
1.1 2.2 3.3 |
|
304 |
1.1 |
|
307 |
1.1 2.2 |
|
308 |
1.1 |
|
310 |
1.1 2.2 |
|
311 |
1.1 |
|
317 |
1.1 |
|
318 |
1.1 |
|
320 |
1.1 |
|
324 |
1.1 2.2 |
|
327 |
1.1 |
|
330 |
1.1 |
|
331 |
1.1 2.2 3.3 |
|
336 |
1.1 |
|
342 |
1.1 |
|
345 |
1.1 2.2 |
|
346 |
1.1 |
|
348 |
1.1 |
|
352 |
1.1 |
|
353 |
1.1 |
|
360 |
1.1 |
|
375 |
1.1 2.2 |
|
376 |
1.1 |
|
377 |
1.1 |
|
379 |
1.1 2.2 |
|
380 |
1.1 |
|
381 |
1.1 |
|
383 |
1.1 2.2 |
|
396 |
1.1 |
|
398 |
1.1 |
|
445 |
1.1 |
|
446 |
1.1 |
|
448 |
1.1 2.2 3.3 |
|
458 |
1.1 2.2 |
|
460 |
1.1 |
|
461 |
1.1 |
|
470 |
1.1 |
|
471 |
1.1 2.2 3.3 |
|
473 |
1.1 |
|
488 |
1.1 2.2 3.3 |
|
489 |
1.1 |
|
490 |
1.1 |
|
492 |
1.1 |
|
553 |
1.1 2.2 |
|
556 |
1.1 |
|
563 |
1.1 2.2 |
|
566 |
1.1 |
|
579 |
1.1 |
|
580 |
1.1 |
|
582 |
1.1 |
|
587 |
1.1 |
|
589 |
1.1 |
|
591 |
1.1 |
|
598 |
1.1 |
|
606 |
1.1 2.2 3.3 4.4 5.5 |