📄 columntext.java
字号:
* @throws DocumentException on error
*/
public int go() throws DocumentException {
return go(false);
}
/**
* Outputs the lines to the document. The output can be simulated.
* @param simulate <CODE>true</CODE> to simulate the writting to the document
* @return returns the result of the operation. It can be <CODE>NO_MORE_TEXT</CODE>
* and/or <CODE>NO_MORE_COLUMN</CODE>
* @throws DocumentException on error
*/
public int go(boolean simulate) throws DocumentException {
if (composite)
return goComposite(simulate);
addWaitingPhrase();
if (bidiLine == null)
return NO_MORE_TEXT;
descender = 0;
linesWritten = 0;
boolean dirty = false;
float ratio = spaceCharRatio;
Object currentValues[] = new Object[2];
PdfFont currentFont = null;
Float lastBaseFactor = new Float(0);
currentValues[1] = lastBaseFactor;
PdfDocument pdf = null;
PdfContentByte graphics = null;
PdfContentByte text = null;
firstLineY = Float.NaN;
int localRunDirection = PdfWriter.RUN_DIRECTION_NO_BIDI;
if (runDirection != PdfWriter.RUN_DIRECTION_DEFAULT)
localRunDirection = runDirection;
if (canvas != null) {
graphics = canvas;
pdf = canvas.getPdfDocument();
text = canvas.getDuplicate();
}
else if (!simulate)
throw new NullPointerException("ColumnText.go with simulate==false and text==null.");
if (!simulate) {
if (ratio == GLOBAL_SPACE_CHAR_RATIO)
ratio = text.getPdfWriter().getSpaceCharRatio();
else if (ratio < 0.001f)
ratio = 0.001f;
}
float firstIndent = 0;
int status = 0;
if (rectangularMode) {
for (;;) {
firstIndent = (lastWasNewline ? indent : followingIndent);
if (rectangularWidth <= firstIndent + rightIndent) {
status = NO_MORE_COLUMN;
if (bidiLine.isEmpty())
status |= NO_MORE_TEXT;
break;
}
if (bidiLine.isEmpty()) {
status = NO_MORE_TEXT;
break;
}
PdfLine line = bidiLine.processLine(rectangularWidth - firstIndent - rightIndent, alignment, localRunDirection, arabicOptions);
if (line == null) {
status = NO_MORE_TEXT;
break;
}
float maxSize = line.getMaxSizeSimple();
if (isUseAscender() && Float.isNaN(firstLineY)) {
currentLeading = line.getAscender();
}
else {
currentLeading = fixedLeading + maxSize * multipliedLeading;
}
if (yLine > maxY || yLine - currentLeading < minY ) {
status = NO_MORE_COLUMN;
bidiLine.restore();
break;
}
yLine -= currentLeading;
if (!simulate && !dirty) {
text.beginText();
dirty = true;
}
if (Float.isNaN(firstLineY)) {
firstLineY = yLine;
}
updateFilledWidth(rectangularWidth - line.widthLeft());
if (!simulate) {
currentValues[0] = currentFont;
text.setTextMatrix(leftX + (line.isRTL() ? rightIndent : firstIndent) + line.indentLeft(), yLine);
pdf.writeLineToContent(line, text, graphics, currentValues, ratio);
currentFont = (PdfFont)currentValues[0];
}
lastWasNewline = line.isNewlineSplit();
yLine -= line.isNewlineSplit() ? extraParagraphSpace : 0;
++linesWritten;
descender = line.getDescender();
}
}
else {
currentLeading = fixedLeading;
for (;;) {
firstIndent = (lastWasNewline ? indent : followingIndent);
float yTemp = yLine;
float xx[] = findLimitsTwoLines();
if (xx == null) {
status = NO_MORE_COLUMN;
if (bidiLine.isEmpty())
status |= NO_MORE_TEXT;
yLine = yTemp;
break;
}
if (bidiLine.isEmpty()) {
status = NO_MORE_TEXT;
yLine = yTemp;
break;
}
float x1 = Math.max(xx[0], xx[2]);
float x2 = Math.min(xx[1], xx[3]);
if (x2 - x1 <= firstIndent + rightIndent)
continue;
if (!simulate && !dirty) {
text.beginText();
dirty = true;
}
PdfLine line = bidiLine.processLine(x2 - x1 - firstIndent - rightIndent, alignment, localRunDirection, arabicOptions);
if (line == null) {
status = NO_MORE_TEXT;
yLine = yTemp;
break;
}
if (!simulate) {
currentValues[0] = currentFont;
text.setTextMatrix(x1 + (line.isRTL() ? rightIndent : firstIndent) + line.indentLeft(), yLine);
pdf.writeLineToContent(line, text, graphics, currentValues, ratio);
currentFont = (PdfFont)currentValues[0];
}
lastWasNewline = line.isNewlineSplit();
yLine -= line.isNewlineSplit() ? extraParagraphSpace : 0;
++linesWritten;
descender = line.getDescender();
}
}
if (dirty) {
text.endText();
canvas.add(text);
}
return status;
}
/**
* Sets the extra space between paragraphs.
* @return the extra space between paragraphs
*/
public float getExtraParagraphSpace() {
return extraParagraphSpace;
}
/**
* Sets the extra space between paragraphs.
* @param extraParagraphSpace the extra space between paragraphs
*/
public void setExtraParagraphSpace(float extraParagraphSpace) {
this.extraParagraphSpace = extraParagraphSpace;
}
/**
* Clears the chunk array. A call to <CODE>go()</CODE> will always return
* NO_MORE_TEXT.
*/
public void clearChunks() {
if (bidiLine != null)
bidiLine.clearChunks();
}
/** Gets the space/character extra spacing ratio for
* fully justified text.
* @return the space/character extra spacing ratio
*/
public float getSpaceCharRatio() {
return spaceCharRatio;
}
/** Sets the ratio between the extra word spacing and the extra character spacing
* when the text is fully justified.
* Extra word spacing will grow <CODE>spaceCharRatio</CODE> times more than extra character spacing.
* If the ratio is <CODE>PdfWriter.NO_SPACE_CHAR_RATIO</CODE> then the extra character spacing
* will be zero.
* @param spaceCharRatio the ratio between the extra word spacing and the extra character spacing
*/
public void setSpaceCharRatio(float spaceCharRatio) {
this.spaceCharRatio = spaceCharRatio;
}
/** Sets the run direction.
* @param runDirection the run direction
*/
public void setRunDirection(int runDirection) {
if (runDirection < PdfWriter.RUN_DIRECTION_DEFAULT || runDirection > PdfWriter.RUN_DIRECTION_RTL)
throw new RuntimeException("Invalid run direction: " + runDirection);
this.runDirection = runDirection;
}
/** Gets the run direction.
* @return the run direction
*/
public int getRunDirection() {
return runDirection;
}
/** Gets the number of lines written.
* @return the number of lines written
*/
public int getLinesWritten() {
return this.linesWritten;
}
/** Gets the arabic shaping options.
* @return the arabic shaping options
*/
public int getArabicOptions() {
return this.arabicOptions;
}
/** Sets the arabic shaping options. The option can be AR_NOVOWEL,
* AR_COMPOSEDTASHKEEL and AR_LIG.
* @param arabicOptions the arabic shaping options
*/
public void setArabicOptions(int arabicOptions) {
this.arabicOptions = arabicOptions;
}
/** Gets the biggest descender value of the last line written.
* @return the biggest descender value of the last line written
*/
public float getDescender() {
return descender;
}
/** Gets the width that the line will occupy after writing.
* Only the width of the first line is returned.
* @param phrase the <CODE>Phrase</CODE> containing the line
* @param runDirection the run direction
* @param arabicOptions the options for the arabic shaping
* @return the width of the line
*/
public static float getWidth(Phrase phrase, int runDirection, int arabicOptions) {
ColumnText ct = new ColumnText(null);
ct.addText(phrase);
ct.addWaitingPhrase();
PdfLine line = ct.bidiLine.processLine(20000, Element.ALIGN_LEFT, runDirection, arabicOptions);
if (line == null)
return 0;
else
return 20000 - line.widthLeft();
}
/** Gets the width that the line will occupy after writing.
* Only the width of the first line is returned.
* @param phrase the <CODE>Phrase</CODE> containing the line
* @return the width of the line
*/
public static float getWidth(Phrase phrase) {
return getWidth(phrase, PdfWriter.RUN_DIRECTION_NO_BIDI, 0);
}
/** Shows a line of text. Only the first line is written.
* @param canvas where the text is to be written to
* @param alignment the alignment. It is not influenced by the run direction
* @param phrase the <CODE>Phrase</CODE> with the text
* @param x the x reference position
* @param y the y reference position
* @param rotation the rotation to be applied in degrees counterclockwise
* @param runDirection the run direction
* @param arabicOptions the options for the arabic shaping
*/
public static void showTextAligned(PdfContentByte canvas, int alignment, Phrase phrase, float x, float y, float rotation, int runDirection, int arabicOptions) {
if (alignment != Element.ALIGN_LEFT && alignment != Element.ALIGN_CENTER
&& alignment != Element.ALIGN_RIGHT)
alignment = Element.ALIGN_LEFT;
canvas.saveState();
ColumnText ct = new ColumnText(canvas);
if (rotation == 0) {
if (alignment == Element.ALIGN_LEFT)
ct.setSimpleColumn(phrase, x, y - 1, 20000 + x, y + 2, 2, alignment);
else if (alignment == Element.ALIGN_RIGHT)
ct.setSimpleColumn(phrase, x-20000, y-1, x, y+2, 2, alignment);
else
ct.setSimpleColumn(phrase, x-20000, y-1, x+20000, y+2, 2, alignment);
}
else {
double alpha = rotation * Math.PI / 180.0;
float cos = (float)Math.cos(alpha);
float sin = (float)Math.sin(alpha);
canvas.concatCTM(cos, sin, -sin, cos, x, y);
if (alignment == Element.ALIGN_LEFT)
ct.setSimpleColumn(phrase, 0, -1, 20000, 2, 2, alignment);
else if (alignment == Element.ALIGN_RIGHT)
ct.setSimpleColumn(phrase, -20000, -1, 0, 2, 2, alignment);
else
ct.setSimpleColumn(phrase, -20000, -1, 20000, 2, 2, alignment);
}
if (runDirection == PdfWriter.RUN_DIRECTION_RTL) {
if (alignment == Element.ALIGN_LEFT)
alignment = Element.ALIGN_RIGHT;
else if (alignment == Element.ALIGN_RIGHT)
alignment = Element.ALIGN_LEFT;
}
ct.setAlignment(alignment);
ct.setArabicOptions(arabicOptions);
ct.setRunDirection(runDirection);
try {
ct.go();
}
catch (DocumentException e) {
throw new ExceptionConverter(e);
}
canvas.restoreState();
}
/** Shows a line of text. Only the first line is written.
* @param canvas where the text is to be written to
* @param alignment the alignment
* @param phrase the <CODE>Phrase</CODE> with the text
* @param x the x reference position
* @param y the y reference position
* @param rotation the rotation to be applied in degrees counterclockwise
*/
public static void showTextAligned(PdfContentByte canvas, int alignment, Phrase phrase, float x, float y, float rotation) {
showTextAligned(canvas, alignment, phrase, x, y, rotation, PdfWriter.RUN_DIRECTION_NO_BIDI, 0);
}
protected int goComposite(boolean simulate) throws DocumentException {
if (!rectangularMode)
throw new DocumentException("Irregular columns are not supported in composite mode.");
linesWritten = 0;
descender = 0;
boolean firstPass = true;
main_loop:
while (true) {
if (compositeElements.isEmpty())
return NO_MORE_TEXT;
Element element = (Element)compositeElements.getFirst();
if (element.type() == Element.PARAGRAPH) {
Paragraph para = (Paragraph)element;
int status = 0;
for (int keep = 0; keep < 2; ++keep) {
float lastY = yLine;
boolean createHere = false;
if (compositeColumn == null) {
compositeColumn = new ColumnText(canvas);
compositeColumn.setUseAscender(firstPass ? useAscender : false);
compositeColumn.setAlignment(para.getAlignment());
compositeColumn.setIndent(para.getIndentationLeft() + para.getFirstLineIndent());
compositeColumn.setExtraParagraphSpace(para.getExtraParagraphSpace());
compositeColumn.setFollowingIndent(para.getIndentationLeft());
compositeColumn.setRightIndent(para.getIndentationRight());
compositeColumn.setLeading(para.getLeading(), para.getMultipliedLeading());
compositeColumn.setRunDirection(runDirection);
compositeColumn.setArabicOptions(arabicOptions);
compositeColumn.setSpaceCharRatio(spaceCharRatio);
compositeColumn.addText(para);
if (!firstPass) {
yLine -= para.spacingBefore();
}
createHere = true;
}
compositeColumn.leftX = leftX;
compositeColumn.rightX = rightX;
compositeColumn.yLine = yLine;
compositeColumn.rectangularWidth = rectangularWidth;
compositeColumn.rectangularMode = rectangularMode;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -