在使用 itext 创建具有圆角的 table 时,PDF 的大小意外增加
On creating a table having rounded corner with itext, the size of PDF is increasing unexpectedly
我正在同一个 PDF 上创建多个 table。我需要 table 的圆角,单元格的边框颜色和 table 的边框颜色应该不同。我为此创建了 table 渲染器,在使用渲染器创建 table 时,PDF 大小随机增加。如果我们不使用圆角,则 PDF 大小为“61KB”;如果我使用渲染器制作圆角,则 PDF 大小为“500KB”。请建议如何修复
import java.io.FileNotFoundException;
import com.itextpdf.kernel.colors.Color;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.borders.SolidBorder;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.element.Text;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.VerticalAlignment;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.layout.renderer.IRenderer;
import com.itextpdf.layout.renderer.TableRenderer;
public class testDate {
public static void main(String[] args) throws FileNotFoundException {
String dest = "D://PDF_SIZE.pdf";
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdf = new PdfDocument(writer);
pdf.addNewPage();
Document doc = new Document(pdf);
for (int i =0 ; i< 1130 ; i++){
Table table = new Table(new float[]{100f,100f});
table.setWidth(506.25f);
table.setProperty(com.itextpdf.layout.property.Property.TABLE_LAYOUT, "fixed");
com.itextpdf.layout.element.Cell cell = new com.itextpdf.layout.element.Cell(1,1);
cell.setWidth(15.165f);
Text t =new Text("A").setFontSize(11f);
Paragraph p = new Paragraph();
p.setFixedLeading(0.0f).setMultipliedLeading(0.86f);
cell.add(p.add(t));
cell.setPadding(3f);
cell.setMinHeight(10f);
cell.setVerticalAlignment(VerticalAlignment.TOP);
cell.setTextAlignment(TextAlignment.LEFT);
cell.setKeepTogether(true);
cell.setBorder(new SolidBorder(new DeviceRgb(255,0,0),0.5f));
cell.setBackgroundColor(new DeviceRgb(255,255,255));
table.addCell(cell);
com.itextpdf.layout.element.Cell cell2 = new com.itextpdf.layout.element.Cell(1,1);
cell2.setWidth(490.33502f);
Text t2 =new Text("Row Number - " + i).setFontSize(11f);
Paragraph p2 = new Paragraph();
p2.setFixedLeading(0.0f).setMultipliedLeading(0.86f);
cell2.add(p2.add(t2));
cell2.setPadding(3f);
cell2.setMinHeight(10f);
cell2.setVerticalAlignment(VerticalAlignment.TOP);
cell2.setTextAlignment(TextAlignment.LEFT);
cell.setKeepTogether(true);
cell2.setBorder(new SolidBorder(new DeviceRgb(255,0,0),0.5f));
cell2.setBackgroundColor(new DeviceRgb(255,255,255));
table.addCell(cell2);
table.setNextRenderer(new TableBorderRenderer (table));
doc.add(table);
}
doc.close();
System.out.println("table Added.");
}
public static class TableBorderRenderer extends TableRenderer {
public TableBorderRenderer(Table modelElement) {
super(modelElement);
}
@Override
public IRenderer getNextRenderer() {
return new TableBorderRenderer((Table) modelElement);
}
@Override
protected void drawBorders(DrawContext drawContext) {
Rectangle rect = getOccupiedAreaBBox();
PdfPage currentPage = drawContext.getDocument().getPage(getOccupiedArea().getPageNumber());
PdfCanvas aboveCanvas = new PdfCanvas(currentPage.newContentStreamAfter(), currentPage.getResources(), drawContext.getDocument());
float lineWidth = 0.5f;
rect.applyMargins(lineWidth / 2, lineWidth / 2, lineWidth / 2, lineWidth / 2, false);
Color strokeColor;
strokeColor = new DeviceRgb(255,255,0);
aboveCanvas.saveState().setLineWidth(0.5f).setStrokeColor(new DeviceRgb(255,255,255)).rectangle(rect).stroke().restoreState();
aboveCanvas.saveState().setLineWidth(0.5f).setStrokeColor(strokeColor).roundRectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight(), 5).stroke().restoreState();
super.drawBorders(drawContext);
}
@Override
public void drawChildren(DrawContext drawContext) {
Rectangle rect = getOccupiedAreaBBox();
float lineWidth = 0.5f;
rect.applyMargins(lineWidth, lineWidth, lineWidth, lineWidth, false);
PdfCanvas canvas = drawContext.getCanvas();
canvas.saveState();
canvas.roundRectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight(), 4.5f);
canvas.clip().endPath();
super.drawChildren(drawContext);
canvas.restoreState();
}
}
}
由于您在循环内部而不是外部创建了一个 table,因此您创建了 1130 个 table 而不是 1 个。这是最大的问题,它阻止您利用 SO 的想法回答你在评论中提到的。
如果像我在以下代码片段中所做的那样将 table 创建置于循环之外,则生成的 PDF 的大小将从 521 Kb 减小到 51 Kb。如果您禁用为此类代码设置自定义 table 渲染器,则生成的 PDF 大小将为 45 Kb。
Table table = new Table(new float[] {100f, 100f});
table.setWidth(506.25f);
table.setFixedLayout();
for (int i =0 ; i < 1130 ; i++) {
// each iteration of this loop represents adding of a single row
// some code
}
doc.add(table);
这是生成的 PDF 现在的样子:
正如您在问题中所问,它具有黄色圆形 table 边框、单元格背景(您在代码中将其设置为白色)和红色单元格边框。
我正在同一个 PDF 上创建多个 table。我需要 table 的圆角,单元格的边框颜色和 table 的边框颜色应该不同。我为此创建了 table 渲染器,在使用渲染器创建 table 时,PDF 大小随机增加。如果我们不使用圆角,则 PDF 大小为“61KB”;如果我使用渲染器制作圆角,则 PDF 大小为“500KB”。请建议如何修复
import java.io.FileNotFoundException;
import com.itextpdf.kernel.colors.Color;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.borders.SolidBorder;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.element.Text;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.VerticalAlignment;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.layout.renderer.IRenderer;
import com.itextpdf.layout.renderer.TableRenderer;
public class testDate {
public static void main(String[] args) throws FileNotFoundException {
String dest = "D://PDF_SIZE.pdf";
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdf = new PdfDocument(writer);
pdf.addNewPage();
Document doc = new Document(pdf);
for (int i =0 ; i< 1130 ; i++){
Table table = new Table(new float[]{100f,100f});
table.setWidth(506.25f);
table.setProperty(com.itextpdf.layout.property.Property.TABLE_LAYOUT, "fixed");
com.itextpdf.layout.element.Cell cell = new com.itextpdf.layout.element.Cell(1,1);
cell.setWidth(15.165f);
Text t =new Text("A").setFontSize(11f);
Paragraph p = new Paragraph();
p.setFixedLeading(0.0f).setMultipliedLeading(0.86f);
cell.add(p.add(t));
cell.setPadding(3f);
cell.setMinHeight(10f);
cell.setVerticalAlignment(VerticalAlignment.TOP);
cell.setTextAlignment(TextAlignment.LEFT);
cell.setKeepTogether(true);
cell.setBorder(new SolidBorder(new DeviceRgb(255,0,0),0.5f));
cell.setBackgroundColor(new DeviceRgb(255,255,255));
table.addCell(cell);
com.itextpdf.layout.element.Cell cell2 = new com.itextpdf.layout.element.Cell(1,1);
cell2.setWidth(490.33502f);
Text t2 =new Text("Row Number - " + i).setFontSize(11f);
Paragraph p2 = new Paragraph();
p2.setFixedLeading(0.0f).setMultipliedLeading(0.86f);
cell2.add(p2.add(t2));
cell2.setPadding(3f);
cell2.setMinHeight(10f);
cell2.setVerticalAlignment(VerticalAlignment.TOP);
cell2.setTextAlignment(TextAlignment.LEFT);
cell.setKeepTogether(true);
cell2.setBorder(new SolidBorder(new DeviceRgb(255,0,0),0.5f));
cell2.setBackgroundColor(new DeviceRgb(255,255,255));
table.addCell(cell2);
table.setNextRenderer(new TableBorderRenderer (table));
doc.add(table);
}
doc.close();
System.out.println("table Added.");
}
public static class TableBorderRenderer extends TableRenderer {
public TableBorderRenderer(Table modelElement) {
super(modelElement);
}
@Override
public IRenderer getNextRenderer() {
return new TableBorderRenderer((Table) modelElement);
}
@Override
protected void drawBorders(DrawContext drawContext) {
Rectangle rect = getOccupiedAreaBBox();
PdfPage currentPage = drawContext.getDocument().getPage(getOccupiedArea().getPageNumber());
PdfCanvas aboveCanvas = new PdfCanvas(currentPage.newContentStreamAfter(), currentPage.getResources(), drawContext.getDocument());
float lineWidth = 0.5f;
rect.applyMargins(lineWidth / 2, lineWidth / 2, lineWidth / 2, lineWidth / 2, false);
Color strokeColor;
strokeColor = new DeviceRgb(255,255,0);
aboveCanvas.saveState().setLineWidth(0.5f).setStrokeColor(new DeviceRgb(255,255,255)).rectangle(rect).stroke().restoreState();
aboveCanvas.saveState().setLineWidth(0.5f).setStrokeColor(strokeColor).roundRectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight(), 5).stroke().restoreState();
super.drawBorders(drawContext);
}
@Override
public void drawChildren(DrawContext drawContext) {
Rectangle rect = getOccupiedAreaBBox();
float lineWidth = 0.5f;
rect.applyMargins(lineWidth, lineWidth, lineWidth, lineWidth, false);
PdfCanvas canvas = drawContext.getCanvas();
canvas.saveState();
canvas.roundRectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight(), 4.5f);
canvas.clip().endPath();
super.drawChildren(drawContext);
canvas.restoreState();
}
}
}
由于您在循环内部而不是外部创建了一个 table,因此您创建了 1130 个 table 而不是 1 个。这是最大的问题,它阻止您利用 SO 的想法回答你在评论中提到的。
如果像我在以下代码片段中所做的那样将 table 创建置于循环之外,则生成的 PDF 的大小将从 521 Kb 减小到 51 Kb。如果您禁用为此类代码设置自定义 table 渲染器,则生成的 PDF 大小将为 45 Kb。
Table table = new Table(new float[] {100f, 100f});
table.setWidth(506.25f);
table.setFixedLayout();
for (int i =0 ; i < 1130 ; i++) {
// each iteration of this loop represents adding of a single row
// some code
}
doc.add(table);
这是生成的 PDF 现在的样子:
正如您在问题中所问,它具有黄色圆形 table 边框、单元格背景(您在代码中将其设置为白色)和红色单元格边框。