All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.janeluo.easypdf.PDFDoc Maven / Gradle / Ivy

The newest version!
/* Copyright (c) 2021 janeluo
 * easy-pdf is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package com.janeluo.easypdf;

import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.*;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.element.*;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.UnitValue;
import com.itextpdf.layout.property.VerticalAlignment;
import com.itextpdf.layout.splitting.ISplitCharacters;
import com.janeluo.easypdf.draw.CustomLineSeparator;
import lombok.extern.slf4j.Slf4j;
import org.xml.sax.Attributes;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * PDF 操作类
 * 

* 这个类封装 PDF 文档相关的操作,通过 iText 实现。 * 如果需要水印、印章等特殊效果,请参考 PDFProcess 类。 */ @Slf4j public class PDFDoc extends TextDoc { protected InputStream templateInputStream; protected Map fontFamilyMap; private final Map blockTypes = new HashMap() {{ put("title", BlockType.BLOCK_TITLE); put("chapter", BlockType.BLOCK_CHAPTER); put("section", BlockType.BLOCK_SECTION); put("para", BlockType.BLOCK_PARA); }}; private final List pdfBlockDefaults; private PdfDocument pdfDocument; private Document document; private final Map images; private final ISplitCharacters splitCharacters = (glyphLine, i) -> true; public PDFDoc(InputStream templateInputStream, OutputStream outputStream, Map fontFamilyMap) { super(outputStream); this.templateInputStream = templateInputStream; this.fontFamilyMap = fontFamilyMap; this.fontFamilyMap.put("heiti", "font/SIMHEI.TTF"); this.fontFamilyMap.put("hei", "font/SIMHEI.TTF"); this.fontFamilyMap.put("songti", "font/SIMSUN.TTC,0"); this.fontFamilyMap.put("song", "font/SIMSUN.TTC,0"); pdfBlockDefaults = new ArrayList<>(); images = new HashMap<>(); for (Map.Entry entry : this.fontFamilyMap.entrySet()) { pdfBlockDefaults.add(new PDFBlockDefault(BlockType.BLOCK_TITLE, entry.getKey(), 18, FontStyle.BOLD, TextAlignment.CENTER, 0.0f, 0.0f, 16.0f) ); pdfBlockDefaults.add(new PDFBlockDefault(BlockType.BLOCK_CHAPTER, entry.getKey(), 16, FontStyle.BOLD, TextAlignment.LEFT, 0.0f, 14.0f, 0.0f) ); pdfBlockDefaults.add(new PDFBlockDefault(BlockType.BLOCK_SECTION, entry.getKey(), 14, FontStyle.BOLD, TextAlignment.LEFT, 0.0f, 12.0f, 0.0f) ); pdfBlockDefaults.add(new PDFBlockDefault(BlockType.BLOCK_PARA, entry.getKey(), 12, FontStyle.NONE, TextAlignment.LEFT, 22.0f, 6.0f, 0.0f) ); // 默认的块属性,应用程序可以通过 setBlockDefault() 来修改这些属性 } } private void addMetaInfo() { PdfDocumentInfo info = pdfDocument.getDocumentInfo(); // info.setTitle("TextPdf 合同"); // info.setSubject("本合同带有防伪标识,请登录系统核查"); // info.setAuthor("Lucky Byte, Inc.(诺百)"); // info.setKeywords("TextPdf, PDF, Lucky Byte Inc., 诺百"); // info.setCreator("TextPdf 版本 " + Version.VERSION + // " - http://git.oschina.net/lucky-byte/textpdf"); } @Override public boolean open() { try { final PdfWriter writer = new PdfWriter(outputStream); // 有模板 if (this.templateInputStream != null) { PdfDocument srcDoc = new PdfDocument(new PdfReader(this.templateInputStream)); // Event handler copies content of the source pdf file on every page // of the result pdf file final PdfPage firstPage = srcDoc.getFirstPage(); PageSize pageSize = new PageSize(firstPage.getPageSize().getWidth(), firstPage.getPageSize().getHeight()); pdfDocument = new PdfDocument(writer); pdfDocument.setDefaultPageSize(pageSize); final PdfFormXObject background = firstPage.copyAsFormXObject(pdfDocument); pdfDocument.addEventHandler(PdfDocumentEvent.END_PAGE, new PaginationEventHandler(background)); } else { pdfDocument = new PdfDocument(writer); } this.document = new Document(pdfDocument); document.setMargins(pageMarginTop, pageMarginRight, pageMarginBottom, pageMarginLeft); // writer.setFullCompression(); // 需求 PDF 1.5 writer.setCompressionLevel(9); addMetaInfo(); return true; } catch (Exception e) { e.printStackTrace(); return false; } } protected class PaginationEventHandler implements IEventHandler { protected PdfFormXObject background; public PaginationEventHandler(PdfFormXObject background) { this.background = background; } @Override public void handleEvent(Event event) { PdfDocument pdfDoc = ((PdfDocumentEvent) event).getDocument(); PdfPage currentPage = ((PdfDocumentEvent) event).getPage(); // Add the background final PdfCanvas pdfCanvas = new PdfCanvas(currentPage.newContentStreamBefore(), currentPage.getResources(), pdfDoc); pdfCanvas .addXObjectAt(background, 0, 0); } } @Override public void close() { pdfDocument.close(); } @Override public boolean isOpen() { if (pdfDocument == null) { return false; } return !pdfDocument.isClosed(); } @Override public void setPageSize(PageSize pageSize) { super.setPageSize(pageSize); if (isOpen()) { pdfDocument.addNewPage(pageSize); } } @Override public void setPageMargin(int left, int right, int top, int bottom) { super.setPageMargin(left, right, top, bottom); if (isOpen()) { document.setMargins(pageMarginTop, pageMarginRight, pageMarginBottom, pageMarginLeft); } } /** * 设置块默认属性 * 这个函数一次性设置所有的块默认属性,如果需要单独设置某一个属性, * 请使用下面的 setBlockDefaultXXX() 函数。 * * @param blockType 块类型 * @param fontFamily 字体家族 * @param fontSize 字体大小 * @param fontStyle 字体风格 * @param alignment 对齐方式 * @param indent 首行缩进距离 */ public void setBlockDefault(BlockType blockType, String fontFamily, int fontSize, FontStyle fontStyle, TextAlignment alignment, float indent, float lineSpaceBefore, float lineSpaceAfter) { for (PDFBlockDefault block : pdfBlockDefaults) { if (block.blockType == blockType) { block.fontFamily = fontFamily; block.fontSize = fontSize; block.fontStyle = fontStyle; block.alignment = alignment; block.indent = indent; block.lineSpaceBefore = lineSpaceBefore; block.lineSpaceAfter = lineSpaceAfter; break; } } } /** * 设置块的默认字体家族 * * @param blockType 类型 * @param fontFamily 字体 */ public void setBlockDefaultFontFamily(BlockType blockType, String fontFamily) { for (PDFBlockDefault block : pdfBlockDefaults) { if (block.blockType == blockType) { block.fontFamily = fontFamily; break; } } } /** * 设置块的默认字体大小 * * @param blockType 类型 * @param fontSize 字体大小 */ public void setBlockDefaultFontSize(BlockType blockType, int fontSize) { for (PDFBlockDefault block : pdfBlockDefaults) { if (block.blockType == blockType) { block.fontSize = fontSize; break; } } } /** * 设置块的默认字体风格 * * @param blockType 类型 * @param fontStyle 字体样式 */ public void setBlockDefaultFontStyle(BlockType blockType, FontStyle fontStyle) { for (PDFBlockDefault block : pdfBlockDefaults) { if (block.blockType == blockType) { block.fontStyle = fontStyle; break; } } } /** * 设置块的默认对齐方式 * * @param blockType 类型 * @param alignment 对齐方式 */ public void setBlockDefaultAlignment(BlockType blockType, TextAlignment alignment) { for (PDFBlockDefault block : pdfBlockDefaults) { if (block.blockType == blockType) { block.alignment = alignment; break; } } } /** * 设置块的默认首行缩进距离 * * @param blockType 类型 * @param indent 首航缩进大小 */ public void setBlockDefaultIndent(BlockType blockType, float indent) { for (PDFBlockDefault block : pdfBlockDefaults) { if (block.blockType == blockType) { block.indent = indent; break; } } } /** * 设置段前空间 * * @param blockType 类型 * @param lineSpaceBefore 行上面空行大小 */ public void setBlockDefaultLineSpaceBefore(BlockType blockType, float lineSpaceBefore) { for (PDFBlockDefault block : pdfBlockDefaults) { if (block.blockType == blockType) { block.lineSpaceBefore = lineSpaceBefore; break; } } } /** * 设置段后空间 * * @param blockType 类型 * @param lineSpaceAfter 下面空行大小 */ public void setBlockDefaultLineSpaceAfter(BlockType blockType, float lineSpaceAfter) { for (PDFBlockDefault block : pdfBlockDefaults) { if (block.blockType == blockType) { block.lineSpaceAfter = lineSpaceAfter; break; } } } /** * 根据 TextChunk 中字体相关的属性来设置 Chunk 的字体,字体包括: * 家族(黑体或宋体)、大小、修饰(粗体、斜体、下划线等等)。 * * @param textChunk TextChunk 对象,保存了字体的属性 * @param chunk PDF Chunk 对象 * @param blockDefault * @throws IOException */ private void setChunkFont(TextChunk textChunk, Text chunk, PDFBlockDefault blockDefault) throws IOException { Map attrs = textChunk.getAttrs(); String fontFamily = blockDefault.fontFamily; int fontSize = blockDefault.fontSize; FontStyle fontStyle = blockDefault.fontStyle; PdfFont pdfFont = null; String value = attrs.get("font-family"); if (value != null) { fontFamily = value; } value = attrs.get("font-size"); if (value != null) { try { fontSize = Integer.parseInt(value); } catch (Exception ex) { System.err.println("Font size '" + value + "' invalid."); } } value = attrs.get("font-style"); if (value != null) { String[] styles = value.split(","); for (String style : styles) { String label = style.trim(); if ("bold".equalsIgnoreCase(label)) { chunk.setBold(); } else if ("italic".equalsIgnoreCase(label)) { chunk.setItalic(); } else if ("underline".equalsIgnoreCase(label)) { chunk.setUnderline(); } } } else { switch (fontStyle) { case BOLD: chunk.setBold(); break; case ITALIC: chunk.setItalic(); break; case UNDERLINE: chunk.setUnderline(); break; case NONE: default: break; } } String fontProgram = fontFamilyMap.get(fontFamily); pdfFont = PdfFontFactory.createFont(fontProgram, PdfEncodings.IDENTITY_H, PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED); chunk.setFontSize(fontSize); chunk.setFont(pdfFont); } /** * 根据 TextChunk 的属性生成 PDF Text 对象 * * @param text_chunk TextChunk 对象 * @param blockDefault 块默认类型 * @return PDF Text */ private Text formatChunk(TextChunk text_chunk, PDFBlockDefault blockDefault) { Text chunk = new Text(""); Map attrs = text_chunk.getAttrs(); String value = attrs.get("super"); if ("true".equalsIgnoreCase(value)) { chunk.setTextRise(6.0f); if (!attrs.containsKey("font-size")) { attrs.put("font-size", "8"); } } value = attrs.get("sub"); if ("true".equalsIgnoreCase(value)) { chunk.setTextRise(-3.0f); if (!attrs.containsKey("font-size")) { attrs.put("font-size", "8"); } } String contents = text_chunk.getContents(); value = text_chunk.getAttrs().get("minlen"); if (value != null && value.length() > 0) { if (contents.length() == 0) { chunk.setUnderline(1.0f, -4.0f); } try { int minlen = Integer.parseInt(value); int currlen = 0; for (int i = 0; i < contents.length(); i++) { char ch = contents.charAt(i); if (ch < 127) { currlen += 1; } else { currlen += 2; } } if (currlen < minlen) { StringBuilder builder = new StringBuilder(contents); for (; currlen < minlen; currlen++) { builder.append(' '); } contents = builder.toString(); } } catch (Exception ex) { ex.printStackTrace(); System.err.println("minlen need a integer value."); } } chunk.setText(contents); try { setChunkFont(text_chunk, chunk, blockDefault); } catch (IOException ignored) { } return chunk; } private void formatParagraph(Paragraph para, List chunkList) { // 用第一个节点来设置块的段落属性 TextChunk textChunk = chunkList.get(0); if (textChunk != null) { Map attrs = textChunk.getAttrs(); // 设置段落对齐方式 String value = attrs.get("align"); if (value != null) { if ("left".equalsIgnoreCase(value)) { para.setTextAlignment(TextAlignment.LEFT); } else if ("center".equalsIgnoreCase(value)) { para.setTextAlignment(TextAlignment.CENTER); } else if ("right".equalsIgnoreCase(value)) { para.setTextAlignment(TextAlignment.RIGHT); } else { System.err.println("Block alignment type '" + value + "' unknown."); } } // 设置段落缩进 value = attrs.get("indent"); if (value != null) { try { float indent = Float.parseFloat(value); para.setFirstLineIndent(indent); } catch (Exception ex) { System.err.println( "Indent attribute must has a float value"); } } // 设置段落前空间 value = attrs.get("space-before"); if (value != null) { try { float space = Float.parseFloat(value); para.setMarginTop(space); } catch (Exception ex) { System.err.println( "space-before attribute must has a float value"); } } // 设置段落后空间 value = attrs.get("space-after"); if (value != null) { try { float space = Float.parseFloat(value); para.setMarginBottom(space); } catch (Exception ex) { if (log.isErrorEnabled()) { log.error("space-after attribute must has a float value", ex); } else { System.err.println( "space-after attribute must has a float value"); } } } final String height = attrs.get("height"); if (height != null && !"".equals(height)) { para.setHeight(Float.parseFloat(height)); } // 外补丁 final String margin = attrs.get("margin"); if (margin != null) { final String[] split = margin.split(" "); try { if (split.length == 1) { para.setMargin(Float.parseFloat(margin)); } else if (split.length == 2) { float top = Float.parseFloat(split[0]), bottom = Float.parseFloat(split[0]); float left = Float.parseFloat(split[1]), right = Float.parseFloat(split[1]); para.setMargins(top, right, bottom, left); } if (split.length == 4) { float top = Float.parseFloat(split[0]); float right = Float.parseFloat(split[1]); float bottom = Float.parseFloat(split[2]); float left = Float.parseFloat(split[3]); para.setMargins(top, right, bottom, left); } } catch (Exception ex) { if (log.isErrorEnabled()) { log.error("margin attribute must has a float value", ex); } else { System.err.println( "margin attribute must has a float value"); } } } // 相对定位, 格式左上右下 final String relativePosition = attrs.get("relative-position"); if (relativePosition != null && !"".equals(relativePosition)) { final String[] split = relativePosition.split(" "); if (split.length == 4) { try { float left = Float.parseFloat(split[0]); float top = Float.parseFloat(split[1]); float right = Float.parseFloat(split[2]); float bottom = Float.parseFloat(split[3]); para.setRelativePosition(left, top, right, bottom); } catch (Exception ex) { if (log.isErrorEnabled()) { log.error("relative-position attribute must has a float value", ex); } else { System.err.println( "relative-position attribute must has a float value"); } } } else { if (log.isErrorEnabled()) { log.error("relative-position attribute must like 'relative-position:\"left top right bottom\"'"); } else { System.err.println( "relative-position attribute must like 'relative-position:\"left top right bottom\"'"); } } } String fixedPosition = attrs.get("fixed-position"); if (fixedPosition != null && !"".equals(fixedPosition)) { final String[] split = fixedPosition.split(" "); if (split.length == 2) { try { float left = Float.parseFloat(split[0]); float bottom = Float.parseFloat(split[1]); para.setFixedPosition(left, bottom, UnitValue.createPercentValue(100)); } catch (Exception ex) { if (log.isErrorEnabled()) { log.error("fixed-position attribute must has a float value", ex); } else { System.err.println( "fixed-position attribute must has a float value"); } } } else { if (log.isErrorEnabled()) { log.error("fixed-position attribute must like 'fixed-position:\"left bottom\"'"); } else { System.err.println( "fixed-position attribute must like 'fixed-position:\"left bottom\"'"); } } } // 行间距 final String lineHeight = attrs.get("line-height"); if (null != lineHeight && !"".equals(lineHeight)) { try { para.setMultipliedLeading(Float.parseFloat(lineHeight)); } catch (NumberFormatException ex) { if (log.isErrorEnabled()) { log.error("line-height attribute must has a float value", ex); } else { System.err.println( "line-height attribute must has a float value"); } } } } } /** * 添加一段文字到 PDF 文档 * * @param blockType 块类型 * @param chunkList chunks 列表 * @param pdfBlockDefault */ private void addParagraph(BlockType blockType, List chunkList, PDFBlockDefault pdfBlockDefault) { Paragraph para = new Paragraph(); for (TextChunk textChunk : chunkList) { Text chunk = formatChunk(textChunk, pdfBlockDefault); chunk.setSplitCharacters(splitCharacters); para.add(chunk); } para.setMarginTop(pdfBlockDefault.lineSpaceBefore); para.setMarginBottom(pdfBlockDefault.lineSpaceAfter); para.setTextAlignment(pdfBlockDefault.alignment); para.setFirstLineIndent(pdfBlockDefault.indent); formatParagraph(para, chunkList); document.add(para); } /** * 添加一块内容到 PDF 文档,块可以为 Title、Section、等等, * 参考类前面的数组定义 * * @param blockName 块类型名,例如 title, section 等等 * @param chunkList 本块的内容,一个块包含多个 chunk,它们通过列表保存 */ @Override public void writeBlock(String blockName, List chunkList) { if (blockName == null || chunkList == null || chunkList.size() == 0) { return; } if (pdfDocument == null || pdfDocument.isClosed()) { System.err.println("Document unopen yet, please open it first."); return; } // 将块名称映射到内部的整数表示 final String lowerBlockName = blockName.toLowerCase(); if (!blockTypes.containsKey(lowerBlockName)) { System.err.println("Block type '" + blockName + "' unknown!"); return; } BlockType blockType = blockTypes.get(lowerBlockName); for (PDFBlockDefault pdfBlockDefault : pdfBlockDefaults) { if (pdfBlockDefault.blockType == blockType) { addParagraph(blockType, chunkList, pdfBlockDefault); break; } } } /** * 换页 */ @Override public void newPage() { if (pdfDocument == null || pdfDocument.isClosed()) { System.err.println("Document unopen yet, please open it first."); return; } pdfDocument.addNewPage(); } @Override public void addHrule(Attributes attrs) { try { int width = 1; int percent = 100; String value = attrs.getValue("width"); if (value != null) { try { width = Integer.parseInt(value); } catch (Exception ignored) { } } value = attrs.getValue("percent"); if (value != null) { try { percent = Integer.parseInt(value); } catch (Exception ignored) { } } document.add(new AreaBreak()); document.add(new LineSeparator(new CustomLineSeparator(width, percent))); } catch (Exception ex) { ex.printStackTrace(); } } /** * 添加一个图片 * * @param attrs 属性 */ @Override public void addImage(Attributes attrs) { try { String src = attrs.getValue("src"); if (src == null) { System.err.println("img missing src attribute."); return; } Image img = images.get(src); if (img == null) { img = new Image(ImageDataFactory.create(src)); images.put(src, img); } document.add(img); } catch (Exception e) { e.printStackTrace(); } } private Table createTable(Map attrs) { float width = 100; float[] columns = null; Table table; String value = attrs.get("columns"); if (value != null) { try { String[] array = value.split(","); columns = new float[array.length]; for (int i = 0; i < array.length; i++) { columns[i] = Integer.parseInt(array[i]); } } catch (Exception ex) { System.err.println("column must has a integer value"); } } if (columns == null) { table = new Table(UnitValue.createPercentArray(1)); } else { table = new Table(UnitValue.createPercentArray(columns)); } value = attrs.get("width"); if (value != null) { try { width = Float.parseFloat(value); } catch (Exception ex) { System.err.println("width must has a float value"); } } table.setWidth(UnitValue.createPercentValue(width)); table.setFixedLayout(); // 外补丁 final String margin = attrs.get("margin"); if (margin != null) { final String[] split = margin.split(" "); try { if (split.length == 1) { table.setMargin(Float.parseFloat(margin)); } else if (split.length == 2) { float top = Float.parseFloat(split[0]), bottom = Float.parseFloat(split[0]); float left = Float.parseFloat(split[1]), right = Float.parseFloat(split[1]); table.setMargins(top, right, bottom, left); } if (split.length == 4) { float top = Float.parseFloat(split[0]); float right = Float.parseFloat(split[1]); float bottom = Float.parseFloat(split[2]); float left = Float.parseFloat(split[3]); table.setMargins(top, right, bottom, left); } } catch (Exception ex) { if (log.isErrorEnabled()) { log.error("margin attribute must has a float value", ex); } else { System.err.println( "margin attribute must has a float value"); } } } return table; } private Cell createTableCell(TextChunk textChunk, PDFBlockDefault blockDefault) { Map attrs = textChunk.getAttrs(); Text chunk = formatChunk(textChunk, blockDefault); Paragraph phrase = new Paragraph(); // 行间距 final String lineHeight = attrs.get("line-height"); if (null != lineHeight && !"".equals(lineHeight)) { try { phrase.setMultipliedLeading(Float.parseFloat(lineHeight)); } catch (NumberFormatException ex) { if (log.isErrorEnabled()) { log.error("line-height attribute must has a float value", ex); } else { System.err.println( "line-height attribute must has a float value"); } } } phrase.add(chunk); String value = attrs.get("colspan"); int colspan = 1; if (value != null) { try { colspan = Integer.parseInt(value); } catch (Exception ex) { System.err.println("colspan must has a integer value"); } } Cell cell = new Cell(1, colspan); cell.add(phrase); cell.setVerticalAlignment(VerticalAlignment.MIDDLE); value = attrs.get("align"); if (value != null) { if ("left".equalsIgnoreCase(value)) { cell.setTextAlignment(TextAlignment.LEFT); } else if ("center".equalsIgnoreCase(value)) { cell.setTextAlignment(TextAlignment.CENTER); } else if ("right".equalsIgnoreCase(value)) { cell.setTextAlignment(TextAlignment.RIGHT); } } // 内补丁 final String padding = attrs.get("padding"); if (padding != null) { final String[] split = padding.split(" "); try { if (split.length == 1) { cell.setPadding(Float.parseFloat(padding)); } else if (split.length == 2) { float top = Float.parseFloat(split[0]), bottom = Float.parseFloat(split[0]); float left = Float.parseFloat(split[1]), right = Float.parseFloat(split[1]); cell.setPaddings(top, right, bottom, left); } if (split.length == 4) { float top = Float.parseFloat(split[0]); float right = Float.parseFloat(split[1]); float bottom = Float.parseFloat(split[2]); float left = Float.parseFloat(split[3]); cell.setPaddings(top, right, bottom, left); } } catch (Exception ex) { if (log.isErrorEnabled()) { log.error("padding attribute must has a float value", ex); } else { System.err.println( "padding attribute must has a float value"); } } } final String backgroundColor = attrs.get("background-color"); if (backgroundColor != null) { final String[] colors = backgroundColor.split(" "); if (colors.length == 3) { try { final int r = Integer.parseInt(colors[0]); final int g = Integer.parseInt(colors[1]); final int b = Integer.parseInt(colors[2]); cell.setBackgroundColor(new DeviceRgb(r, g, b)); } catch (Exception ex) { log.error("background-color item must has a float value", ex); } } } final String border = attrs.getOrDefault("border", ""); if (!"".equals(border)) { if ("no-border".equals(border)) { cell.setBorder(Border.NO_BORDER); } } return cell; } @Override public void writeTable(TextTable table) { if (!isOpen() || table == null) { return; } PDFBlockDefault blockDefault = null; for (PDFBlockDefault def : this.pdfBlockDefaults) { if (def.blockType == BlockType.BLOCK_PARA) { blockDefault = def; break; } } Table pdfTable = createTable(table.getAttrs()); for (TextChunk textChunk : table.getCells()) { pdfTable.addCell(createTableCell(textChunk, blockDefault)); } document.add(pdfTable); } } /** * 一个类用于保存块默认属性 */ class PDFBlockDefault { protected BlockType blockType; protected String fontFamily; protected int fontSize; protected FontStyle fontStyle; protected TextAlignment alignment; protected float indent; protected float lineSpaceBefore; protected float lineSpaceAfter; public PDFBlockDefault(BlockType blockType, String family, int size, FontStyle style, TextAlignment alignment, float indent, float lineSpaceBefore, float lineSpaceAfter) { this.blockType = blockType; this.fontFamily = family; this.fontSize = size; this.fontStyle = style; this.alignment = alignment; this.indent = indent; this.lineSpaceBefore = lineSpaceBefore; this.lineSpaceAfter = lineSpaceAfter; } } /** * 块类型 */ enum BlockType { /** * 标题 */ BLOCK_TITLE(1), /** * */ BLOCK_CHAPTER(2), /** * */ BLOCK_SECTION(3), /** * */ BLOCK_PARA(3), ; BlockType(int type) { this.type = type; } private final int type; public int getType() { return type; } } enum FontStyle { /** * 空 */ NONE(0), /** * 加粗 */ BOLD(1), /** * 下划线 */ UNDERLINE(2), ITALIC(4), ; FontStyle(int type) { this.type = type; } private final int type; public int getType() { return type; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy