gpt4 book ai didi

How can I create fixed-width paragraphs with PDFbox?(如何使用PDFbox创建固定宽度的段落?)

转载 作者:bug小助手 更新时间:2023-10-24 17:55:12 29 4
gpt4 key购买 nike



I can insert simple text like this:

我可以像这样插入简单的文本:



document = new PDDocument();
page = new PDPage(PDPage.PAGE_SIZE_A4);
document.addPage(page);
PDPageContentStream content = new PDPageContentStream(document, page);
content.beginText();
content.moveTextPositionByAmount (10 , 10);
content.drawString ("test text");
content.endText();
content.close();


but how can I create a paragraph similar to HTML using the width attribute?

但是,如何使用Width属性创建类似于HTML的段落呢?



<p style="width:200px;">test text</p>

更多回答
优秀答案推荐


Warning: this answer applies to and old version of PDFBox and relies on features that has since been deprecated. See the comments below for more details.




According to this answer it's not possible to insert line breaks into some text and have PDF display it correctly (whether using PDFBox or something else), so I believe auto-wrapping some text to fit in some width may also be something it can't do automatically. (besides, there are many ways to wrap a text - whole words only, break them in smaller parts, etc)

根据这个答案,在一些文本中插入换行符并让PDF正确显示它是不可能的(无论是使用PDFBox还是其他工具),所以我认为自动换行一些文本以适应一定的宽度也可能是它不能自动完成的事情。(此外,还有很多方法可以换行--只换整个词,把它们拆分成小部分,等等)



This answer to another question (about centering a string) gives some pointers on how to do this yourself. Assuming you wrote a function possibleWrapPoints(String):int[] to list all points in the text a word wrap can happen (excluding "zero", including "text length"), one possible solution could be:

这个对另一个问题(关于字符串居中)的回答给出了一些关于如何自己做这件事的提示。假设您编写了一个函数possibleWrapPoints(字符串):int[]来列出可能发生换行的文本中的所有点(不包括“零”,包括“文本长度”),一种可能的解决方案是:



PDFont font = PDType1Font.HELVETICA_BOLD; // Or whatever font you want.
int fontSize = 16; // Or whatever font size you want.
int paragraphWidth = 200;
String text = "test text";

int start = 0;
int end = 0;
int height = 10;
for ( int i : possibleWrapPoints(text) ) {
float width = font.getStringWidth(text.substring(start,i)) / 1000 * fontSize;
if ( start < end && width > paragraphWidth ) {
// Draw partial text and increase height
content.moveTextPositionByAmount(10 , height);
content.drawString(text.substring(start,end));
height += font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * fontSize;
start = end;
}
end = i;
}
// Last piece of text
content.moveTextPositionByAmount(10 , height);
content.drawString(text.substring(start));


One example of possibleWrapPoints, that allow wrapping at any point that's not part of a word (reference), could be:

PossibleWrapPoints的一个例子是,它允许在单词(引用)之外的任何位置换行,例如:



int[] possibleWrapPoints(String text) {
String[] split = text.split("(?<=\\W)");
int[] ret = new int[split.length];
ret[0] = split[0].length();
for ( int i = 1 ; i < split.length ; i++ )
ret[i] = ret[i-1] + split[i].length();
return ret;
}


Update: some additional info:

更新:一些更多信息:




  • The PDF file format was designed to look the same in different situations, functionality like the one you requested makes sense in a PDF editor/creator, but not in the PDF file per se. For this reason, most "low level" tools tend to concentrate on dealing with the file format itself and leave away stuff like that.

    PDF文件格式被设计为在不同的情况下看起来是相同的,像您所请求的功能在PDF编辑器/创建器中是有意义的,但在PDF文件本身中不是这样的。出于这个原因,大多数“低级”工具倾向于专注于处理文件格式本身,而忽略了类似的东西。


  • Higher level tools OTOH usually have means to make this conversion. An example is Platypus (for Python, though), that do have easy ways of creating paragraphs, and relies on the lower level ReportLab functions to do the actual PDF rendering. I'm unaware of similar tools for PDFBox, but this post gives some hints on how to convert HTML content to PDF in a Java environment, using freely available tools. Haven't tried them myself, but I'm posting here since it might be useful (in case my hand-made attempt above is not enough).

    更高级的工具OTOH通常有进行这种转换的方法。一个例子是Platypus(不过,对于Python),它确实有创建段落的简单方法,并且依赖较低级别的ReportLab函数来执行实际的PDF呈现。我不知道PDFBox有类似的工具,但这篇文章给出了一些关于如何在Java环境中使用免费工具将HTML内容转换为PDF的提示。我自己还没有试过,但我在这里发帖,因为它可能会有用(以防我上面的手工尝试还不够)。




I have been working combining Lukas answer with mgibsonbr and arrived at this. More helpful to people looking for an out-of-the-box solution, I think.

我一直在努力结合卢卡斯的答案与mgibsonbr和到达这一点。我认为,这对那些寻求开箱即用的解决方案的人更有帮助。



private void write(Paragraph paragraph) throws IOException {
out.beginText();
out.appendRawCommands(paragraph.getFontHeight() + " TL\n");
out.setFont(paragraph.getFont(), paragraph.getFontSize());
out.moveTextPositionByAmount(paragraph.getX(), paragraph.getY());
out.setStrokingColor(paragraph.getColor());

List<String> lines = paragraph.getLines();
for (Iterator<String> i = lines.iterator(); i.hasNext(); ) {
out.drawString(i.next().trim());
if (i.hasNext()) {
out.appendRawCommands("T*\n");
}
}
out.endText();

}

public class Paragraph {

/** position X */
private float x;

/** position Y */
private float y;

/** width of this paragraph */
private int width = 500;

/** text to write */
private String text;

/** font to use */
private PDType1Font font = PDType1Font.HELVETICA;

/** font size to use */
private int fontSize = 10;

private int color = 0;

public Paragraph(float x, float y, String text) {
this.x = x;
this.y = y;
this.text = text;
}

/**
* Break the text in lines
* @return
*/
public List<String> getLines() throws IOException {
List<String> result = Lists.newArrayList();

String[] split = text.split("(?<=\\W)");
int[] possibleWrapPoints = new int[split.length];
possibleWrapPoints[0] = split[0].length();
for ( int i = 1 ; i < split.length ; i++ ) {
possibleWrapPoints[i] = possibleWrapPoints[i-1] + split[i].length();
}

int start = 0;
int end = 0;
for ( int i : possibleWrapPoints ) {
float width = font.getStringWidth(text.substring(start,i)) / 1000 * fontSize;
if ( start < end && width > this.width ) {
result.add(text.substring(start,end));
start = end;
}
end = i;
}
// Last piece of text
result.add(text.substring(start));
return result;
}

public float getFontHeight() {
return font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * fontSize;
}

public Paragraph withWidth(int width) {
this.width = width;
return this;
}

public Paragraph withFont(PDType1Font font, int fontSize) {
this.font = font;
this.fontSize = fontSize;
return this;
}

public Paragraph withColor(int color) {
this.color = color;
return this;
}

public int getColor() {
return color;
}

public float getX() {
return x;
}

public float getY() {
return y;
}

public int getWidth() {
return width;
}

public String getText() {
return text;
}

public PDType1Font getFont() {
return font;
}

public int getFontSize() {
return fontSize;
}

}


import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

public class PdfParagraph2 {

public enum Alignment {
LEFT, RIGHT, CENTER
}

public static void main(String[] args) throws IOException {
// Create a PDF document, add pages, and obtain content stream
// (You should have your PDFBox setup code here)
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);

// Create a content stream for the page
PDPageContentStream contentStream = new PDPageContentStream(document, page);
float startX = 1; // Left margin
float startY = 740; // Top margin
float lineSpacing = 12; // Line spacing
int maxWidth = 600; // Maximum line width
Alignment alignment = Alignment.RIGHT; // Set alignment

// Sample text for the paragraph
String text = "This is a sample paragraph." +
"Itmayspanmultiplelinesdependingonthewidthofthecontent. Paragraph 1: This is the first paragraph.af aFA FF AF AFAF Af af aF Af aF Af aF Af aF Af fafasfafas af f af af af af fffffffffffffs sgs ";

float[] nextPosition = addLine(contentStream, "Imli chor", startX, startY, lineSpacing, maxWidth, Alignment.LEFT);
addLine(contentStream, "Chor", nextPosition[0], nextPosition[1], lineSpacing, maxWidth, Alignment.LEFT);
contentStream.close();
document.save("D:\\pdf\\output1.pdf");
document.close();
// Continue adding more content or save the document
// (You should have the rest of your PDF generation code here)
}
public static float[] addLine(PDPageContentStream contentStream, String text, float startX, float startY, float lineSpacing, int maxWidth, Alignment alignment) throws IOException {
contentStream.setFont(PDType1Font.HELVETICA, 12);

String[] lines = text.split("\n");
float yOffset = startY;
float maxLineWidth = 0;
for (String line : lines) {
float xOffset;
float lineWidth = getStringWidth(PDType1Font.HELVETICA, 12, line);

// Calculate the X-coordinate based on the alignment
switch (alignment) {
case LEFT:
xOffset = startX;
break;
case CENTER:
xOffset = startX + (maxWidth - Math.min(maxWidth, lineWidth)) / 2;
break;
case RIGHT:
xOffset = startX + maxWidth - Math.min(maxWidth, lineWidth);
break;
default:
xOffset = startX; // Default to left alignment
}

String[] words = line.split(" ");
StringBuilder lineText = new StringBuilder();
float currentLineWidth = 0;

for (String word : words) {
float wordWidth = getStringWidth(PDType1Font.HELVETICA, 12, word);

if (currentLineWidth + wordWidth > maxWidth) {
// The word exceeds the remaining line width, start a new line
contentStream.beginText();
contentStream.newLineAtOffset(Math.max(xOffset, startX), yOffset);
contentStream.showText(lineText.toString());
contentStream.endText();

// Move to the next line
yOffset -= lineSpacing;
lineText.setLength(0); // Clear the lineText
currentLineWidth = 0;
}

if (lineText.length() > 0) {
lineText.append(" "); // Add space between words
currentLineWidth += getStringWidth(PDType1Font.HELVETICA, 12, " "); // Update line width
}

lineText.append(word);
currentLineWidth += wordWidth;
maxLineWidth = Math.max(currentLineWidth, maxLineWidth);
}

// Add the last line in the paragraph
contentStream.beginText();
contentStream.newLineAtOffset(Math.max(xOffset, startX), yOffset);
contentStream.showText(lineText.toString());
contentStream.endText();

// Move to the next line
//yOffset -= lineSpacing;
}

// Return the next X and Y positions
return new float[]{startX+maxLineWidth+getStringWidth(PDType1Font.HELVETICA, 12, " "), yOffset};
}

public static float[] addParagraph(PDPageContentStream contentStream, String text, float startX, float startY, float lineSpacing, int maxWidth, Alignment alignment) throws IOException {
contentStream.setFont(PDType1Font.HELVETICA, 12);

String[] lines = text.split("\n");
float yOffset = startY;

for (String line : lines) {
float xOffset;
float lineWidth = getStringWidth(PDType1Font.HELVETICA, 12, line);

// Calculate the X-coordinate based on the alignment
switch (alignment) {
case LEFT:
xOffset = startX;
break;
case CENTER:
xOffset = startX + (maxWidth - Math.min(maxWidth, lineWidth)) / 2;
break;
case RIGHT:
xOffset = startX + maxWidth - Math.min(maxWidth, lineWidth);
break;
default:
xOffset = startX; // Default to left alignment
}

String[] words = line.split(" ");
StringBuilder lineText = new StringBuilder();
float currentLineWidth = 0;

for (String word : words) {
float wordWidth = getStringWidth(PDType1Font.HELVETICA, 12, word);

if (currentLineWidth + wordWidth > maxWidth) {
// The word exceeds the remaining line width, start a new line
contentStream.beginText();
contentStream.newLineAtOffset(Math.max(xOffset, startX), yOffset);
contentStream.showText(lineText.toString());
contentStream.endText();

// Move to the next line
yOffset -= lineSpacing;
lineText.setLength(0); // Clear the lineText
currentLineWidth = 0;
}

if (lineText.length() > 0) {
lineText.append(" "); // Add space between words
currentLineWidth += getStringWidth(PDType1Font.HELVETICA, 12, " "); // Update line width
}

lineText.append(word);
currentLineWidth += wordWidth;
}

// Add the last line in the paragraph
contentStream.beginText();
contentStream.newLineAtOffset(Math.max(xOffset, startX), yOffset);
contentStream.showText(lineText.toString());
contentStream.endText();

// Move to the next line
yOffset -= lineSpacing;
}

// Return the next X and Y positions
return new float[]{startX, yOffset};
}

private static float getStringWidth(PDType1Font font, float fontSize, String text) throws IOException {
return font.getStringWidth(text) * fontSize / 1000f;
}
}

更多回答

In PDF it is possible to make a line break. (see my answer)

在PDF中,可以换行。(见我的答案)

Just for reference: This answer uses the API that was current at that time and is now deprecated. Text can now be added by showText and line breaks added directly directly by newLine .

仅供参考:此答案使用的是当时最新的API,现在已弃用。现在可以通过showText添加文本,并通过换行符直接添加换行符。

This is a quite old post and a lot has changed with PDFBox. Also have a look at PDFBox-Layout which makes it way easier to handle all these concerns - wrapping texts, diff layouts etc.

这是一个相当古老的帖子,PDFBox已经发生了很大的变化。还可以看看PDFBox-Layout,它可以更容易地处理所有这些问题--换行文本、比较布局等。

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com