VerticalText.java

1
/*
2
 *
3
 * Copyright 2002 by Paulo Soares.
4
 *
5
 * The contents of this file are subject to the Mozilla Public License Version 1.1
6
 * (the "License"); you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at http://www.mozilla.org/MPL/
8
 *
9
 * Software distributed under the License is distributed on an "AS IS" basis,
10
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
 * for the specific language governing rights and limitations under the License.
12
 *
13
 * The Original Code is 'iText, a free JAVA-PDF library'.
14
 *
15
 * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
16
 * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
17
 * All Rights Reserved.
18
 * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
19
 * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
20
 *
21
 * Contributor(s): all the names of the contributors are added in the source code
22
 * where applicable.
23
 *
24
 * Alternatively, the contents of this file may be used under the terms of the
25
 * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
26
 * provisions of LGPL are applicable instead of those above.  If you wish to
27
 * allow use of your version of this file only under the terms of the LGPL
28
 * License and not to allow others to use your version of this file under
29
 * the MPL, indicate your decision by deleting the provisions above and
30
 * replace them with the notice and other provisions required by the LGPL.
31
 * If you do not delete the provisions above, a recipient may use your version
32
 * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
33
 *
34
 * This library is free software; you can redistribute it and/or modify it
35
 * under the terms of the MPL as stated above or under the terms of the GNU
36
 * Library General Public License as published by the Free Software Foundation;
37
 * either version 2 of the License, or any later version.
38
 *
39
 * This library is distributed in the hope that it will be useful, but WITHOUT
40
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
41
 * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
42
 * details.
43
 *
44
 * If you didn't download this code from the following link, you should check if
45
 * you aren't using an obsolete version:
46
 * http://www.lowagie.com/iText/
47
 */
48
package com.lowagie.text.pdf;
49
import java.awt.Color;
50
import java.util.ArrayList;
51
import java.util.Iterator;
52
import com.lowagie.text.error_messages.MessageLocalization;
53
54
import com.lowagie.text.Chunk;
55
import com.lowagie.text.Element;
56
import com.lowagie.text.Phrase;
57
58
/** Writes text vertically. Note that the naming is done according
59
 * to horizontal text although it refers to vertical text.
60
 * A line with the alignment Element.LEFT_ALIGN will actually
61
 * be top aligned.
62
 */
63
public class VerticalText {
64
65
/** Signals that there are no more text available. */    
66
    public static final int NO_MORE_TEXT = 1;
67
    
68
/** Signals that there is no more column. */    
69
    public static final int NO_MORE_COLUMN = 2;
70
71
/** The chunks that form the text. */    
72
    protected ArrayList chunks = new ArrayList();
73
74
    /** The <CODE>PdfContent</CODE> where the text will be written to. */    
75
    protected PdfContentByte text;
76
    
77
    /** The column alignment. Default is left alignment. */
78
    protected int alignment = Element.ALIGN_LEFT;
79
80
    /** Marks the chunks to be eliminated when the line is written. */
81
    protected int currentChunkMarker = -1;
82
    
83
    /** The chunk created by the splitting. */
84
    protected PdfChunk currentStandbyChunk;
85
    
86
    /** The chunk created by the splitting. */
87
    protected String splittedChunkText;
88
89
    /** The leading
90
     */    
91
    protected float leading;
92
    
93
    /** The X coordinate.
94
     */    
95
    protected float startX;
96
    
97
    /** The Y coordinate.
98
     */    
99
    protected float startY;
100
    
101
    /** The maximum number of vertical lines.
102
     */    
103
    protected int maxLines;
104
    
105
    /** The height of the text.
106
     */    
107
    protected float height;
108
    
109
    /** Creates new VerticalText
110
     * @param text the place where the text will be written to. Can
111
     * be a template.
112
     */
113
    public VerticalText(PdfContentByte text) {
114
        this.text = text;
115
    }
116
    
117
    /**
118
     * Adds a <CODE>Phrase</CODE> to the current text array.
119
     * @param phrase the text
120
     */
121
    public void addText(Phrase phrase) {
122
        for (Object o : phrase.getChunks()) {
123
            chunks.add(new PdfChunk((Chunk) o, null));
124
        }
125
    }
126
    
127
    /**
128
     * Adds a <CODE>Chunk</CODE> to the current text array.
129
     * @param chunk the text
130
     */
131
    public void addText(Chunk chunk) {
132
        chunks.add(new PdfChunk(chunk, null));
133
    }
134
135
    /** Sets the layout.
136
     * @param startX the top right X line position
137
     * @param startY the top right Y line position
138
     * @param height the height of the lines
139
     * @param maxLines the maximum number of lines
140
     * @param leading the separation between the lines
141
     */    
142
    public void setVerticalLayout(float startX, float startY, float height, int maxLines, float leading) {
143
        this.startX = startX;
144
        this.startY = startY;
145
        this.height = height;
146
        this.maxLines = maxLines;
147 1 1. setVerticalLayout : removed call to com/lowagie/text/pdf/VerticalText::setLeading → NO_COVERAGE
        setLeading(leading);
148
    }
149
    
150
    /** Sets the separation between the vertical lines.
151
     * @param leading the vertical line separation
152
     */    
153
    public void setLeading(float leading) {
154
        this.leading = leading;
155
    }
156
157
    /** Gets the separation between the vertical lines.
158
     * @return the vertical line separation
159
     */    
160
    public float getLeading() {
161
        return leading;
162
    }
163
    
164
    /**
165
     * Creates a line from the chunk array.
166
     * @param width the width of the line
167
     * @return the line or null if no more chunks
168
     */
169
    protected PdfLine createLine(float width) {
170 1 1. createLine : negated conditional → NO_COVERAGE
        if (chunks.isEmpty())
171 1 1. createLine : mutated return of Object value for com/lowagie/text/pdf/VerticalText::createLine to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
            return null;
172
        splittedChunkText = null;
173
        currentStandbyChunk = null;
174
        PdfLine line = new PdfLine(0, width, alignment, 0);
175
        String total;
176 3 1. createLine : changed conditional boundary → NO_COVERAGE
2. createLine : Replaced integer addition with subtraction → NO_COVERAGE
3. createLine : negated conditional → NO_COVERAGE
        for (currentChunkMarker = 0; currentChunkMarker < chunks.size(); ++currentChunkMarker) {
177
            PdfChunk original = (PdfChunk)(chunks.get(currentChunkMarker));
178
            total = original.toString();
179
            currentStandbyChunk = line.add(original);
180 1 1. createLine : negated conditional → NO_COVERAGE
            if (currentStandbyChunk != null) {
181
                splittedChunkText = original.toString();
182 1 1. createLine : removed call to com/lowagie/text/pdf/PdfChunk::setValue → NO_COVERAGE
                original.setValue(total);
183 1 1. createLine : mutated return of Object value for com/lowagie/text/pdf/VerticalText::createLine to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
                return line;
184
            }
185
        }
186 1 1. createLine : mutated return of Object value for com/lowagie/text/pdf/VerticalText::createLine to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
        return line;
187
    }
188
    
189
    /**
190
     * Normalizes the list of chunks when the line is accepted.
191
     */
192
    protected void shortenChunkArray() {
193 2 1. shortenChunkArray : changed conditional boundary → NO_COVERAGE
2. shortenChunkArray : negated conditional → NO_COVERAGE
        if (currentChunkMarker < 0)
194
            return;
195 2 1. shortenChunkArray : changed conditional boundary → NO_COVERAGE
2. shortenChunkArray : negated conditional → NO_COVERAGE
        if (currentChunkMarker >= chunks.size()) {
196 1 1. shortenChunkArray : removed call to java/util/ArrayList::clear → NO_COVERAGE
            chunks.clear();
197
            return;
198
        }
199
        PdfChunk split = (PdfChunk)(chunks.get(currentChunkMarker));
200 1 1. shortenChunkArray : removed call to com/lowagie/text/pdf/PdfChunk::setValue → NO_COVERAGE
        split.setValue(splittedChunkText);
201
        chunks.set(currentChunkMarker, currentStandbyChunk);
202 2 1. shortenChunkArray : changed conditional boundary → NO_COVERAGE
2. shortenChunkArray : negated conditional → NO_COVERAGE
        if (currentChunkMarker > 0) {
203 1 1. shortenChunkArray : removed call to java/util/List::clear → NO_COVERAGE
            chunks.subList(0, currentChunkMarker).clear();
204
        }
205
    }
206
207
    /**
208
     * Outputs the lines to the document. It is equivalent to <CODE>go(false)</CODE>.
209
     * @return returns the result of the operation. It can be <CODE>NO_MORE_TEXT</CODE>
210
     * and/or <CODE>NO_MORE_COLUMN</CODE>
211
     */
212
    public int go() {
213 1 1. go : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE
        return go(false);
214
    }
215
    
216
    /**
217
     * Outputs the lines to the document. The output can be simulated.
218
     * @param simulate <CODE>true</CODE> to simulate the writing to the document
219
     * @return returns the result of the operation. It can be <CODE>NO_MORE_TEXT</CODE>
220
     * and/or <CODE>NO_MORE_COLUMN</CODE>
221
     */
222
    public int go(boolean simulate) {
223
        boolean dirty = false;
224
        PdfContentByte graphics = null;
225 1 1. go : negated conditional → NO_COVERAGE
        if (text != null) {
226
            graphics = text.getDuplicate();
227
        }
228 1 1. go : negated conditional → NO_COVERAGE
        else if (!simulate)
229
            throw new NullPointerException(MessageLocalization.getComposedMessage("verticaltext.go.with.simulate.eq.eq.false.and.text.eq.eq.null"));
230
        int status = 0;
231
        for (;;) {
232 2 1. go : changed conditional boundary → NO_COVERAGE
2. go : negated conditional → NO_COVERAGE
            if (maxLines <= 0) {
233
                status = NO_MORE_COLUMN;
234 1 1. go : negated conditional → NO_COVERAGE
                if (chunks.isEmpty())
235 1 1. go : Replaced bitwise OR with AND → NO_COVERAGE
                    status |= NO_MORE_TEXT;
236
                break;
237
            }
238 1 1. go : negated conditional → NO_COVERAGE
            if (chunks.isEmpty()) {
239
                status = NO_MORE_TEXT;
240
                break;
241
            }
242
            PdfLine line = createLine(height);
243 2 1. go : negated conditional → NO_COVERAGE
2. go : negated conditional → NO_COVERAGE
            if (!simulate && !dirty) {
244 1 1. go : removed call to com/lowagie/text/pdf/PdfContentByte::beginText → NO_COVERAGE
                text.beginText();
245
                dirty = true;
246
            }
247 1 1. go : removed call to com/lowagie/text/pdf/VerticalText::shortenChunkArray → NO_COVERAGE
            shortenChunkArray();
248 1 1. go : negated conditional → NO_COVERAGE
            if (!simulate) {
249 2 1. go : Replaced float subtraction with addition → NO_COVERAGE
2. go : removed call to com/lowagie/text/pdf/PdfContentByte::setTextMatrix → NO_COVERAGE
                text.setTextMatrix(startX, startY - line.indentLeft());
250 1 1. go : removed call to com/lowagie/text/pdf/VerticalText::writeLine → NO_COVERAGE
                writeLine(line, text, graphics);
251
            }
252 1 1. go : Replaced integer subtraction with addition → NO_COVERAGE
            --maxLines;
253 1 1. go : Replaced float subtraction with addition → NO_COVERAGE
            startX -= leading;
254
        }
255 1 1. go : negated conditional → NO_COVERAGE
        if (dirty) {
256 1 1. go : removed call to com/lowagie/text/pdf/PdfContentByte::endText → NO_COVERAGE
            text.endText();
257 1 1. go : removed call to com/lowagie/text/pdf/PdfContentByte::add → NO_COVERAGE
            text.add(graphics);
258
        }
259 1 1. go : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE
        return status;
260
    }
261
    
262
    void writeLine(PdfLine line, PdfContentByte text, PdfContentByte graphics) {
263
        PdfFont currentFont = null;
264
        PdfChunk chunk;
265 1 1. writeLine : negated conditional → NO_COVERAGE
        for (Iterator j = line.iterator(); j.hasNext(); ) {
266
            chunk = (PdfChunk) j.next();
267
            
268 1 1. writeLine : negated conditional → NO_COVERAGE
            if (chunk.font().compareTo(currentFont) != 0) {
269
                currentFont = chunk.font();
270 1 1. writeLine : removed call to com/lowagie/text/pdf/PdfContentByte::setFontAndSize → NO_COVERAGE
                text.setFontAndSize(currentFont.getFont(), currentFont.size());
271
            }
272
            Color color = chunk.color();
273 1 1. writeLine : negated conditional → NO_COVERAGE
            if (color != null)
274 1 1. writeLine : removed call to com/lowagie/text/pdf/PdfContentByte::setColorFill → NO_COVERAGE
                text.setColorFill(color);
275 1 1. writeLine : removed call to com/lowagie/text/pdf/PdfContentByte::showText → NO_COVERAGE
            text.showText(chunk.toString());
276 1 1. writeLine : negated conditional → NO_COVERAGE
            if (color != null)
277 1 1. writeLine : removed call to com/lowagie/text/pdf/PdfContentByte::resetRGBColorFill → NO_COVERAGE
                text.resetRGBColorFill();
278
        }
279
    }
280
    
281
    /** Sets the new text origin.
282
     * @param startX the X coordinate
283
     * @param startY the Y coordinate
284
     */    
285
    public void setOrigin(float startX, float startY) {
286
        this.startX = startX;
287
        this.startY = startY;
288
    }
289
    
290
    /** Gets the X coordinate where the next line will be written. This value will change
291
     * after each call to <code>go()</code>.
292
     * @return  the X coordinate
293
     */    
294
    public float getOriginX() {
295
        return startX;
296
    }
297
298
    /** Gets the Y coordinate where the next line will be written.
299
     * @return  the Y coordinate
300
     */    
301
    public float getOriginY() {
302
        return startY;
303
    }
304
    
305
    /** Gets the maximum number of available lines. This value will change
306
     * after each call to <code>go()</code>.
307
     * @return Value of property maxLines.
308
     */
309
    public int getMaxLines() {
310
        return maxLines;
311
    }
312
    
313
    /** Sets the maximum number of lines.
314
     * @param maxLines the maximum number of lines
315
     */
316
    public void setMaxLines(int maxLines) {
317
        this.maxLines = maxLines;
318
    }
319
    
320
    /** Gets the height of the line
321
     * @return the height
322
     */
323
    public float getHeight() {
324
        return height;
325
    }
326
    
327
    /** Sets the height of the line
328
     * @param height the new height
329
     */
330
    public void setHeight(float height) {
331
        this.height = height;
332
    }
333
    
334
    /**
335
     * Sets the alignment.
336
     * @param alignment the alignment
337
     */
338
    public void setAlignment(int alignment) {
339
        this.alignment = alignment;
340
    }
341
    
342
    /**
343
     * Gets the alignment.
344
     * @return the alignment
345
     */
346
    public int getAlignment() {
347
        return alignment;
348
    }
349
}

Mutations

147

1.1
Location : setVerticalLayout
Killed by : none
removed call to com/lowagie/text/pdf/VerticalText::setLeading → NO_COVERAGE

170

1.1
Location : createLine
Killed by : none
negated conditional → NO_COVERAGE

171

1.1
Location : createLine
Killed by : none
mutated return of Object value for com/lowagie/text/pdf/VerticalText::createLine to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE

176

1.1
Location : createLine
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : createLine
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

3.3
Location : createLine
Killed by : none
negated conditional → NO_COVERAGE

180

1.1
Location : createLine
Killed by : none
negated conditional → NO_COVERAGE

182

1.1
Location : createLine
Killed by : none
removed call to com/lowagie/text/pdf/PdfChunk::setValue → NO_COVERAGE

183

1.1
Location : createLine
Killed by : none
mutated return of Object value for com/lowagie/text/pdf/VerticalText::createLine to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE

186

1.1
Location : createLine
Killed by : none
mutated return of Object value for com/lowagie/text/pdf/VerticalText::createLine to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE

193

1.1
Location : shortenChunkArray
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : shortenChunkArray
Killed by : none
negated conditional → NO_COVERAGE

195

1.1
Location : shortenChunkArray
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : shortenChunkArray
Killed by : none
negated conditional → NO_COVERAGE

196

1.1
Location : shortenChunkArray
Killed by : none
removed call to java/util/ArrayList::clear → NO_COVERAGE

200

1.1
Location : shortenChunkArray
Killed by : none
removed call to com/lowagie/text/pdf/PdfChunk::setValue → NO_COVERAGE

202

1.1
Location : shortenChunkArray
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : shortenChunkArray
Killed by : none
negated conditional → NO_COVERAGE

203

1.1
Location : shortenChunkArray
Killed by : none
removed call to java/util/List::clear → NO_COVERAGE

213

1.1
Location : go
Killed by : none
replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE

225

1.1
Location : go
Killed by : none
negated conditional → NO_COVERAGE

228

1.1
Location : go
Killed by : none
negated conditional → NO_COVERAGE

232

1.1
Location : go
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : go
Killed by : none
negated conditional → NO_COVERAGE

234

1.1
Location : go
Killed by : none
negated conditional → NO_COVERAGE

235

1.1
Location : go
Killed by : none
Replaced bitwise OR with AND → NO_COVERAGE

238

1.1
Location : go
Killed by : none
negated conditional → NO_COVERAGE

243

1.1
Location : go
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : go
Killed by : none
negated conditional → NO_COVERAGE

244

1.1
Location : go
Killed by : none
removed call to com/lowagie/text/pdf/PdfContentByte::beginText → NO_COVERAGE

247

1.1
Location : go
Killed by : none
removed call to com/lowagie/text/pdf/VerticalText::shortenChunkArray → NO_COVERAGE

248

1.1
Location : go
Killed by : none
negated conditional → NO_COVERAGE

249

1.1
Location : go
Killed by : none
Replaced float subtraction with addition → NO_COVERAGE

2.2
Location : go
Killed by : none
removed call to com/lowagie/text/pdf/PdfContentByte::setTextMatrix → NO_COVERAGE

250

1.1
Location : go
Killed by : none
removed call to com/lowagie/text/pdf/VerticalText::writeLine → NO_COVERAGE

252

1.1
Location : go
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

253

1.1
Location : go
Killed by : none
Replaced float subtraction with addition → NO_COVERAGE

255

1.1
Location : go
Killed by : none
negated conditional → NO_COVERAGE

256

1.1
Location : go
Killed by : none
removed call to com/lowagie/text/pdf/PdfContentByte::endText → NO_COVERAGE

257

1.1
Location : go
Killed by : none
removed call to com/lowagie/text/pdf/PdfContentByte::add → NO_COVERAGE

259

1.1
Location : go
Killed by : none
replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE

265

1.1
Location : writeLine
Killed by : none
negated conditional → NO_COVERAGE

268

1.1
Location : writeLine
Killed by : none
negated conditional → NO_COVERAGE

270

1.1
Location : writeLine
Killed by : none
removed call to com/lowagie/text/pdf/PdfContentByte::setFontAndSize → NO_COVERAGE

273

1.1
Location : writeLine
Killed by : none
negated conditional → NO_COVERAGE

274

1.1
Location : writeLine
Killed by : none
removed call to com/lowagie/text/pdf/PdfContentByte::setColorFill → NO_COVERAGE

275

1.1
Location : writeLine
Killed by : none
removed call to com/lowagie/text/pdf/PdfContentByte::showText → NO_COVERAGE

276

1.1
Location : writeLine
Killed by : none
negated conditional → NO_COVERAGE

277

1.1
Location : writeLine
Killed by : none
removed call to com/lowagie/text/pdf/PdfContentByte::resetRGBColorFill → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.4.2