📄 columntext.java
字号:
/*
* $Id: ColumnText.java,v 1.12 2001/12/10 13:53:21 blowagie Exp $
* $Name: $
*
* Copyright 2001 by Paulo Soares
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published
* by the Free Software Foundation; either version 2 of the License, or any
* later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
* details.
*
* You should have received a copy of the GNU Library General Public License along
* with this library; if not, write to the Free Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA.
*
* If you didn't download this code from the following link, you should check if
* you aren't using an obsolete version:
* http://www.lowagie.com/iText/
*
* ir-arch Bruno Lowagie,
* Adolf Baeyensstraat 121
* 9040 Sint-Amandsberg
* BELGIUM
* tel. +32 (0)9 228.10.97
* bruno@lowagie.com
*
*/
package com.lowagie.text.pdf;
import java.util.ArrayList;
import java.util.Iterator;
import com.lowagie.text.Phrase;
import com.lowagie.text.Chunk;
import com.lowagie.text.Element;
import com.lowagie.text.DocumentException;
/**
* Formats text in a columnwise form. The text is bound
* on the left and on the right by a sequence of lines. This allows the column
* to have any shape, not only rectangular.
* <P>
* Several parameters can be set like the first paragraph line indent and
* extra space between paragraphs.
* <P>
* A call to the method <CODE>go</CODE> will return one of the following
* situations: the column ended or the text ended.
* <P>
* I the column ended, a new column definition can be loaded with the method
* <CODE>setColumns</CODE> and the method <CODE>go</CODE> can be called again.
* <P>
* If the text ended, more text can be loaded with <CODE>addText</CODE>
* and the method <CODE>go</CODE> can be called again.<BR>
* The only limitation is that one or more complete paragraphs must be loaded
* each time.
* @author Paulo Soares (psoares@ip.pt)
*/
public class ColumnText {
/** Signals that there are no more text available. */
public static final int NO_MORE_TEXT = 1;
/** Signals that there is no more column. */
public static final int NO_MORE_COLUMN = 2;
/** The column is valid. */
protected static final int LINE_STATUS_OK = 0;
/** The line is out outhe column limits. */
protected static final int LINE_STATUS_OFFLIMITS = 1;
/** The line cannot fit this column position. */
protected static final int LINE_STATUS_NOLINE = 2;
/** Upper bound of the column. */
protected float maxY;
/** Lower bound of the column. */
protected float minY;
/** The column alignment. Default is left alignment. */
protected int alignment = Element.ALIGN_LEFT;
/** The left column bound. */
protected ArrayList leftWall;
/** The right column bound. */
protected ArrayList rightWall;
/** The chunks that form the text. */
protected ArrayList chunks = new ArrayList();
/** The current y line location. Text will be written at this line minus the leading. */
protected float yLine;
/** The leading for the current line. */
protected float currentLeading = 16;
/** The fixed text leading. */
protected float fixedLeading = 16;
/** The text leading that is multiplied by the biggest font size in the line. */
protected float multipliedLeading = 0;
/** The <CODE>PdfContent</CODE> where the text will be written to. */
protected PdfContentByte text;
/** The line status when trying to fit a line to a column. */
protected int lineStatus;
/** The first paragraph line indent. */
protected float indent = 0;
/** The extra space between paragraphs. */
protected float extraParagraphSpace = 0;
/** Marks the chunks to be eliminated when the line is written. */
protected int currentChunkMarker = -1;
/** The chunk created by the splitting. */
protected PdfChunk currentStandbyChunk;
/** The chunk created by the splitting. */
protected String splittedChunkText;
/** The width of the line when the column is defined as a simple rectangle. */
protected float rectangularWidth = -1;
/**
* Creates a <CODE>ColumnText</CODE>.
* @param text the place where the text will be written to. Can
* be a template.
*/
public ColumnText(PdfContentByte text)
{
this.text = text;
}
/**
* Adds a <CODE>Phrase</CODE> to the current text array.
* @param phrase the text
*/
public void addText(Phrase phrase)
{
for (Iterator j = phrase.getChunks().iterator(); j.hasNext();)
{
chunks.add(new PdfChunk((Chunk)j.next(), null));
}
}
/**
* Adds a <CODE>Chunk</CODE> to the current text array.
* @param chunk the text
*/
public void addText(Chunk chunk)
{
chunks.add(new PdfChunk(chunk, null));
}
/**
* Converts a sequence of lines representing one of the column bounds into
* an internal format.
* <p>
* Each array element will contain a <CODE>float[4]</CODE> representing
* the line x = ax + b.
* @param cLine the column array
* @return the converted array
*/
protected ArrayList convertColumn(float cLine[])
{
if (cLine.length < 4)
throw new RuntimeException("No valid column line found.");
ArrayList cc = new ArrayList();
for (int k = 0; k < cLine.length - 2; k += 2) {
float x1 = cLine[k];
float y1 = cLine[k + 1];
float x2 = cLine[k + 2];
float y2 = cLine[k + 3];
if (y1 == y2)
continue;
// x = ay + b
float a = (x1 - x2) / (y1 - y2);
float b = x1 - a * y1;
float r[] = new float[4];
r[0] = Math.min(y1, y2);
r[1] = Math.max(y1, y2);
r[2] = a;
r[3] = b;
cc.add(r);
maxY = Math.max(maxY, r[1]);
minY = Math.min(minY, r[0]);
}
if (cc.size() == 0)
throw new RuntimeException("No valid column line found.");
return cc;
}
/**
* Finds the intersection between the <CODE>yLine</CODE> and the column. It will
* set the <CODE>lineStatus</CODE> apropriatly.
* @param wall the column to intersect
* @return the x coordinate of the intersection
*/
protected float findLimitsPoint(ArrayList wall)
{
lineStatus = LINE_STATUS_OK;
if (yLine < minY || yLine > maxY) {
lineStatus = LINE_STATUS_OFFLIMITS;
return 0;
}
for (int k = 0; k < wall.size(); ++k) {
float r[] = (float[])wall.get(k);
if (yLine < r[0] || yLine > r[1])
continue;
return r[2] * yLine + r[3];
}
lineStatus = LINE_STATUS_NOLINE;
return 0;
}
/**
* Finds the intersection between the <CODE>yLine</CODE> and the two
* column bounds. It will set the <CODE>lineStatus</CODE> apropriatly.
* @return a <CODE>float[2]</CODE>with the x coordinates of the intersection
*/
protected float[] findLimitsOneLine()
{
for (;;) {
float x1 = findLimitsPoint(leftWall);
if (lineStatus == LINE_STATUS_OFFLIMITS || lineStatus == LINE_STATUS_NOLINE)
return null;
float x2 = findLimitsPoint(rightWall);
if (lineStatus == LINE_STATUS_NOLINE)
return null;
return new float[]{x1, x2};
}
}
/**
* Finds the intersection between the <CODE>yLine</CODE>,
* the <CODE>yLine-leading</CODE>and the two
* column bounds. It will set the <CODE>lineStatus</CODE> apropriatly.
* @return a <CODE>float[4]</CODE>with the x coordinates of the intersection
*/
protected float[] findLimitsTwoLines()
{
for (;;) {
float x1[] = findLimitsOneLine();
if (lineStatus == LINE_STATUS_OFFLIMITS)
return null;
yLine -= currentLeading;
if (lineStatus == LINE_STATUS_NOLINE) {
continue;
}
float x2[] = findLimitsOneLine();
if (lineStatus == LINE_STATUS_OFFLIMITS)
return null;
if (lineStatus == LINE_STATUS_NOLINE) {
yLine -= currentLeading;
continue;
}
if (x1[0] >= x2[1] || x2[0] >= x1[1])
continue;
return new float[]{x1[0], x1[1], x2[0], x2[1]};
}
}
/**
* Sets the columns bounds. Each column bound is described by a
* <CODE>float[]</CODE> with the line points [x1,y1,x2,y2,...].
* The array must have at least 4 elements.
* @param leftLine the left column bound
* @param rightLine the right column bound
*/
public void setColumns(float leftLine[], float rightLine[])
{
rightWall = convertColumn(rightLine);
leftWall = convertColumn(leftLine);
rectangularWidth = -1;
}
/**
* Simplified method for rectangular columns.
* @param phrase a <CODE>Phrase</CODE>
* @param llx the lower left x corner
* @param lly the lower left y corner
* @param urx the upper right x corner
* @param ury the upper right y corner
* @param leading the leading
* @param alignment the column alignment
*/
public void setSimpleColumn(Phrase phrase, float llx, float lly, float urx, float ury, float leading, int alignment)
{
addText(phrase);
setSimpleColumn(llx, lly, urx, ury, leading, alignment);
}
/**
* Simplified method for rectangular columns.
* @param llx the lower left x corner
* @param lly the lower left y corner
* @param urx the upper right x corner
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -