| /* |
| ******************************************************************************* |
| * Copyright (c) 2020 Contributors to the Eclipse Foundation |
| * |
| * See the NOTICE file(s) distributed with this work for additional |
| * information regarding copyright ownership. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| ******************************************************************************* |
| */ |
| package org.eclipse.openk.statementpublicaffairs.service; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.annotation.PostConstruct; |
| |
| import org.apache.pdfbox.cos.COSDictionary; |
| import org.apache.pdfbox.cos.COSName; |
| import org.apache.pdfbox.pdmodel.PDDocument; |
| import org.apache.pdfbox.pdmodel.PDDocumentInformation; |
| import org.apache.pdfbox.pdmodel.PDPage; |
| import org.apache.pdfbox.pdmodel.PDPageContentStream; |
| import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode; |
| import org.apache.pdfbox.pdmodel.font.PDFont; |
| import org.apache.pdfbox.pdmodel.font.PDType1Font; |
| import org.eclipse.openk.statementpublicaffairs.exceptions.BadRequestServiceException; |
| import org.eclipse.openk.statementpublicaffairs.exceptions.InternalErrorServiceException; |
| import org.eclipse.openk.statementpublicaffairs.model.AttachmentFile; |
| import org.eclipse.openk.statementpublicaffairs.model.CompanyContactBlockModel; |
| import org.eclipse.openk.statementpublicaffairs.model.FontModification; |
| import org.eclipse.openk.statementpublicaffairs.model.PageContext; |
| import org.eclipse.openk.statementpublicaffairs.model.TemplateClosingConfig; |
| import org.eclipse.openk.statementpublicaffairs.model.TemplateClosingConfigSignature; |
| import org.eclipse.openk.statementpublicaffairs.model.TemplateConfig; |
| import org.eclipse.openk.statementpublicaffairs.model.TemplateTextBlockConfig; |
| import org.eclipse.openk.statementpublicaffairs.model.TextState; |
| import org.eclipse.openk.statementpublicaffairs.model.TextToken; |
| import org.eclipse.openk.statementpublicaffairs.model.Textblock; |
| import org.eclipse.openk.statementpublicaffairs.service.compile.TextCompileUtil; |
| import org.eclipse.openk.statementpublicaffairs.service.compile.Token; |
| import org.eclipse.openk.statementpublicaffairs.viewmodel.TextConfiguration; |
| import org.springframework.beans.factory.annotation.Value; |
| import org.springframework.stereotype.Service; |
| import org.springframework.util.ResourceUtils; |
| |
| import com.fasterxml.jackson.databind.ObjectMapper; |
| |
| @Service |
| public class StatementCompileService { |
| |
| private static final String TEXT_NL = "\n"; |
| private static final String TEXT_BULLET = " • "; |
| private static final String TEXT_SPACE = " "; |
| |
| private boolean drawRects = false; |
| |
| public static final double DPI = 72.0; |
| public static final double CM_PER_INCH = 2.54; |
| |
| @Value("${statement.compile.dateFormatPattern:\"dd.MM.yyyy\"}") |
| private String dateFormatPattern; |
| |
| @Value("${statement.compile.statementFileName:\"Statement.pdf\"}") |
| private String statementFileName = "Statement.pdf"; |
| |
| @Value("${statement.compile.templatePdf}") |
| private String templatePdfPath; |
| |
| @Value("${statement.compile.templateJson}") |
| private String templateJsonPath; |
| |
| private Map<FontModification, PDFont> fonts; |
| |
| @PostConstruct |
| public void init() { |
| fonts = new HashMap<>(); |
| fonts.put(FontModification.Normal, PDType1Font.HELVETICA); |
| fonts.put(FontModification.Bold, PDType1Font.HELVETICA_BOLD); |
| fonts.put(FontModification.Italic, PDType1Font.HELVETICA_OBLIQUE); |
| } |
| |
| public AttachmentFile generatePDF(TextConfiguration textConfiguration, CompanyContactBlockModel contact, |
| List<Textblock> textArrangement) throws InternalErrorServiceException, BadRequestServiceException { |
| List<List<TextToken>> textBlockSets = TextCompileUtil.convertToTextTokens(textConfiguration, textArrangement); |
| return printPdf(textBlockSets, textConfiguration, contact); |
| } |
| |
| private PDDocument getTemplatePDF() throws InternalErrorServiceException { |
| try { |
| File templateFile = ResourceUtils.getFile(templatePdfPath); |
| InputStream templateStream = new FileInputStream(templateFile); |
| return PDDocument.load(templateStream); |
| } catch (IOException e) { |
| throw new InternalErrorServiceException("Could not load templatePdf from file " + templatePdfPath, e); |
| } |
| } |
| |
| private TemplateConfig getTemplateConfig() throws InternalErrorServiceException { |
| try { |
| File file = ResourceUtils.getFile(templateJsonPath); |
| ObjectMapper objectMapper = new ObjectMapper(); |
| return objectMapper.readValue(file, TemplateConfig.class); |
| } catch (IOException e) { |
| throw new InternalErrorServiceException("Could not load templateConfig from file " + templateJsonPath, e); |
| } |
| } |
| |
| private AttachmentFile printPdf(List<List<TextToken>> textblockSets, TextConfiguration textConfiguration, |
| CompanyContactBlockModel contact) throws InternalErrorServiceException, BadRequestServiceException { |
| AttachmentFile attachmentFile = new AttachmentFile(); |
| PDPage firstPageTemplate = null; |
| PDPage followupPageTemplate = null; |
| TemplateConfig templateConfig = getTemplateConfig(); |
| PDDocument sourcedoc = getTemplatePDF(); |
| firstPageTemplate = sourcedoc.getPage(0); |
| followupPageTemplate = sourcedoc.getPage(1); |
| |
| String welcomeText = String.join(TEXT_NL, templateConfig.getContentP1().getText()); |
| welcomeText = TextCompileUtil.fillPlaceholder(welcomeText, new HashMap<String, String>(), |
| textConfiguration.getReplacements(), textConfiguration.getConfiguration().getSelects()); |
| List<TextToken> welcomeTokens = TextCompileUtil.parseTextToToken(welcomeText); |
| textblockSets.add(0, welcomeTokens); |
| |
| PDDocument document = new PDDocument(); |
| PDDocumentInformation info = document.getDocumentInformation(); |
| info.setTitle("Statement-" + textConfiguration.getReplacements().get("id")); |
| |
| PDPage firstPage = clonePage(firstPageTemplate); |
| ByteArrayOutputStream out = new ByteArrayOutputStream(); |
| try { |
| drawAddressBox(document, firstPage, templateConfig, contact); |
| drawInfoBox(document, firstPage, templateConfig, textConfiguration.getReplacements()); |
| drawContent(document, firstPage, followupPageTemplate, templateConfig, textblockSets); |
| document.save(out); |
| } catch (IOException e) { |
| try { |
| document.close(); |
| } catch (IOException e1) { |
| // |
| } |
| throw new InternalErrorServiceException("Exception when drawing the statement pdf.", e); |
| } |
| byte[] data = out.toByteArray(); |
| InputStream is = new ByteArrayInputStream(data); |
| attachmentFile.setRessource(is); |
| attachmentFile.setName(statementFileName); |
| attachmentFile.setType("application/pdf"); |
| attachmentFile.setLength(out.size()); |
| return attachmentFile; |
| } |
| |
| protected float dpiOfCm(double cm) { |
| return (float) (cm / CM_PER_INCH * DPI); |
| } |
| |
| private float calcYPosFromTopCm(double cm, float dpiHeight) { |
| return dpiHeight - dpiOfCm(cm); |
| } |
| |
| private float calcSize(PDFont font, float fontSize, String text) throws IOException { |
| return fontSize * font.getStringWidth(text) / 1000; |
| |
| } |
| |
| private List<String> cutintopieces(PDFont font, float fontSize, String text, double width) throws IOException { |
| String[] token = text.split(TEXT_SPACE); |
| List<String> lines = new ArrayList<>(); |
| int tokenIndex = 0; |
| List<String> line = new ArrayList<>(); |
| for (tokenIndex = 0; tokenIndex < token.length; tokenIndex++) { |
| line.add(token[tokenIndex]); |
| if (calcSize(font, fontSize, String.join(TEXT_SPACE, line)) > width) { |
| String tmp = line.remove(line.size() - 1); |
| lines.add(String.join(TEXT_SPACE, line)); |
| line.clear(); |
| line.add(tmp); |
| } |
| |
| } |
| if (!line.isEmpty()) { |
| lines.add(String.join(TEXT_SPACE, line)); |
| } |
| return lines; |
| } |
| |
| private void drawRect(PageContext context, PDPageContentStream cont) throws IOException { |
| if (drawRects) { |
| cont.addRect(context.getPosX(), (float) (context.getPosY() + context.getLeading() - context.getHeight()), |
| context.getWidth(), context.getHeight()); |
| cont.setLineWidth(1); |
| cont.stroke(); |
| } |
| } |
| |
| private void drawContent(PDDocument document, PDPage firstPage, PDPage followupPageTemplate, |
| TemplateConfig templateConfig, List<List<TextToken>> textblockSets) throws IOException, BadRequestServiceException { |
| List<PDPage> pages = new ArrayList<>(); |
| boolean first = true; |
| |
| List<List<TextToken>> remainingTextSets = new ArrayList<>(textblockSets); |
| PDPage currentPage; |
| int contextLines; |
| PageContext context; |
| int pagescount = 0; |
| int maxPagesCount = textblockSets.size(); |
| |
| do { |
| TemplateTextBlockConfig cfg; |
| if (first) { |
| currentPage = firstPage; |
| cfg = templateConfig.getContentP1(); |
| first = false; |
| } else { |
| currentPage = clonePage(followupPageTemplate); |
| cfg = templateConfig.getContentP2(); |
| } |
| document.addPage(currentPage); |
| pages.add(currentPage); |
| |
| PDPageContentStream cont = new PDPageContentStream(document, currentPage, AppendMode.APPEND, false, true); |
| |
| context = new PageContext(); |
| context.setPageHeight(currentPage.getMediaBox().getHeight()); |
| context.setPosX(dpiOfCm(cfg.getX())); |
| context.setPosY(calcYPosFromTopCm(cfg.getY(), context.getPageHeight())); |
| context.setWidth(dpiOfCm(cfg.getWidth())); |
| context.setHeight(dpiOfCm(cfg.getHeight())); |
| context.setLeading(cfg.getFontSize() * 1.12); |
| context.setFontSize(templateConfig.getContentP1().getFontSize()); |
| |
| drawRect(context, cont); |
| |
| contextLines = drawContentPage(remainingTextSets, cont, context); |
| pagescount++; |
| if (pagescount > maxPagesCount) { |
| throw new BadRequestServiceException("Error, page could not be printed. Maybe a textblock is too large to fit on one page"); |
| } |
| |
| } while (!remainingTextSets.isEmpty()); |
| |
| TemplateClosingConfig closingConf = templateConfig.getClosing(); |
| double height = closingConf.getSalutation().size() * context.getLeading(); |
| height += dpiOfCm(closingConf.getSignatures().get(0).getYOffset()); |
| height += (closingConf.getSignatures().get(0).getLines().size() + 2) * context.getLeading(); |
| |
| float relYCursor = (float) (contextLines * context.getLeading()); |
| float posYCursor = context.getPosY() - relYCursor; |
| PageContext closingContext = new PageContext(); |
| if ((context.getHeight() - relYCursor) < height) { |
| currentPage = clonePage(followupPageTemplate); |
| TemplateTextBlockConfig cfg = templateConfig.getContentP2(); |
| document.addPage(currentPage); |
| pages.add(currentPage); |
| |
| closingContext.setPageHeight(currentPage.getMediaBox().getHeight()); |
| closingContext.setPosX(dpiOfCm(cfg.getX())); |
| closingContext.setPosY(calcYPosFromTopCm(cfg.getY(), closingContext.getPageHeight())); |
| closingContext.setWidth(dpiOfCm(cfg.getWidth())); |
| closingContext.setHeight((float) height); |
| closingContext.setLeading(cfg.getFontSize() * 1.12); |
| closingContext.setFontSize(templateConfig.getContentP1().getFontSize()); |
| } else { |
| closingContext.setPageHeight(context.getPageHeight()); |
| closingContext.setPosX(context.getPosX()); |
| closingContext.setPosY(posYCursor); |
| closingContext.setWidth(context.getWidth()); |
| closingContext.setHeight((float) height); |
| closingContext.setLeading(context.getLeading()); |
| closingContext.setFontSize(context.getFontSize()); |
| } |
| |
| PDPageContentStream cont = new PDPageContentStream(document, currentPage, AppendMode.APPEND, false, true); |
| |
| drawClosing(closingContext, cont, templateConfig.getClosing()); |
| |
| } |
| |
| private void drawClosing(PageContext context, PDPageContentStream cont, TemplateClosingConfig closingConfig) |
| throws IOException { |
| |
| drawRect(context, cont); |
| |
| cont.beginText(); |
| cont.setFont(fonts.get(FontModification.Normal), context.getFontSize()); |
| cont.setLeading(context.getLeading()); |
| cont.newLineAtOffset(context.getPosX(), context.getPosY()); |
| for (String line : closingConfig.getSalutation()) { |
| cont.showText(line); |
| cont.newLine(); |
| } |
| float posYCursor = (float) (context.getPosY() - closingConfig.getSalutation().size() * context.getLeading()); |
| cont.endText(); |
| |
| for (TemplateClosingConfigSignature signature : closingConfig.getSignatures()) { |
| |
| float posY = posYCursor - dpiOfCm(signature.getYOffset()); |
| float posX = context.getPosX() + dpiOfCm(signature.getXOffset()); |
| |
| cont.moveTo(posX, posY); |
| cont.lineTo(posX + dpiOfCm(signature.getWidth()), posY); |
| cont.setLineWidth(0.3f); |
| cont.stroke(); |
| |
| cont.beginText(); |
| cont.setFont(fonts.get(FontModification.Normal), context.getFontSize()); |
| cont.setLeading(context.getLeading()); |
| cont.newLineAtOffset(posX, posY); |
| cont.newLine(); |
| for (String signatureLine : signature.getLines()) { |
| cont.showText(signatureLine); |
| cont.newLine(); |
| } |
| cont.endText(); |
| } |
| cont.close(); |
| } |
| |
| private int drawContentPage(List<List<TextToken>> remainingTextSets, PDPageContentStream cont, PageContext context) |
| throws IOException { |
| cont.beginText(); |
| cont.setLeading(context.getLeading()); |
| cont.newLineAtOffset(context.getPosX(), context.getPosY()); |
| |
| DrawContentContext drawContext = new DrawContentContext(); |
| int resultLines = 0; |
| do { |
| |
| List<TextToken> set = new ArrayList<>(remainingTextSets.get(0)); |
| DrawContentContext resultContext = drawTokenList(drawContext, set, context.getWidth(), |
| context.getMaxLines(), context.getFontSize(), cont); |
| resultLines = resultContext.lines; |
| if (resultContext.fitOnPage && !resultContext.pagebreak) { |
| remainingTextSets.remove(0); |
| drawContext = resultContext; |
| } else { |
| if (resultContext.fitOnPage && resultContext.pagebreak) { |
| remainingTextSets.remove(0); |
| } |
| break; |
| } |
| } while (!remainingTextSets.isEmpty()); |
| cont.endText(); |
| cont.close(); |
| return resultLines; |
| } |
| |
| private DrawContentContext drawTokenList(DrawContentContext context, List<TextToken> set, double maxWidth, |
| int maxLines, float fontSize, PDPageContentStream cont) throws IOException { |
| DrawContentContext resContext = new DrawContentContext(); |
| |
| FontModification lastLineFontMode = FontModification.Normal; |
| |
| double currentTextWidth = context.currentTextWidth; |
| |
| // if specialtype |
| if (set.size() == 1 && set.get(0).getType() == Token.TK_PB) { |
| resContext.pagebreak = true; |
| resContext.fitOnPage = true; |
| return resContext; |
| } |
| List<List<TextToken>> lines = new ArrayList<>(); |
| List<TextToken> line = new ArrayList<>(); |
| if (currentTextWidth > 0) { |
| line.add(TextToken.newSpaceTextToken()); |
| line.add(TextToken.newSpaceTextToken()); |
| } |
| |
| int linecount = 0; |
| while (!set.isEmpty()) { |
| TextToken token = set.remove(0); |
| TextState newState = calculateLineWidth(lastLineFontMode, currentTextWidth, line, token, fontSize); |
| resContext.currentTextWidth = newState.getWidth(); |
| if (newState.isLineBreak()) { |
| linecount++; |
| line.add(token); |
| lines.add(line); |
| line = new ArrayList<>(); |
| resContext.currentTextWidth = 0; |
| currentTextWidth = 0; |
| lastLineFontMode = newState.getFontMode(); |
| |
| } else if (newState.getWidth() <= maxWidth) { |
| line.add(token); |
| } else { |
| linecount++; |
| line.add(TextToken.newLineTextToken()); |
| if (newState.isInBulletPoint()) { |
| line.add(TextToken.newBulletShiftTextToken()); |
| } |
| lines.add(line); |
| line = new ArrayList<>(); |
| line.add(token); |
| currentTextWidth = 0; |
| resContext.currentTextWidth = 0; |
| lastLineFontMode = newState.getFontMode(); |
| } |
| } |
| lines.add(line); |
| if (maxLines >= (context.lines + linecount)) { |
| drawTextSet(lines, cont, fontSize); |
| resContext.lines = context.lines + linecount; |
| resContext.fitOnPage = true; |
| } else { |
| resContext.pagebreak = true; |
| } |
| return resContext; |
| |
| } |
| |
| private class DrawContentContext { |
| private int lines; |
| private double currentTextWidth; |
| private boolean fitOnPage; |
| private boolean pagebreak; |
| } |
| |
| private FontModification updateFontMod(FontModification currentFontMod, Token token) { |
| FontModification newFontMod; |
| switch (token) { |
| case TK_BOLD: |
| if (currentFontMod == FontModification.Bold) { |
| newFontMod = FontModification.Normal; |
| } else { |
| newFontMod = FontModification.Bold; |
| } |
| break; |
| case TK_ITALIC: |
| if (currentFontMod == FontModification.Italic) { |
| newFontMod = FontModification.Normal; |
| } else { |
| newFontMod = FontModification.Italic; |
| } |
| break; |
| default: |
| newFontMod = FontModification.Normal; |
| } |
| return newFontMod; |
| } |
| |
| private void drawTextSet(List<List<TextToken>> lines, PDPageContentStream cont, float fontSize) throws IOException { |
| FontModification currentFontMod = FontModification.Normal; |
| boolean inBulletPoint = false; |
| for (List<TextToken> line : lines) { |
| boolean firstInLine = true; |
| for (TextToken lt : line) { |
| switch (lt.getType()) { |
| case TK_NL: |
| cont.newLine(); |
| inBulletPoint = false; |
| break; |
| case TK_BOLD: |
| case TK_ITALIC: |
| currentFontMod = updateFontMod(currentFontMod, lt.getType()); |
| break; |
| case TK_BULLET: |
| cont.setFont(fonts.get(currentFontMod), fontSize); |
| cont.showText(TEXT_BULLET); |
| inBulletPoint = true; |
| break; |
| case TK_SPACE: |
| if (!firstInLine) { |
| cont.setFont(fonts.get(currentFontMod), fontSize); |
| cont.showText(TEXT_SPACE); |
| } |
| break; |
| case TK_UNDERSCORE: |
| case STRING: |
| cont.setFont(fonts.get(currentFontMod), fontSize); |
| if (firstInLine && inBulletPoint) { |
| cont.showText(" "); |
| } |
| cont.showText(lt.getValue()); |
| break; |
| default: |
| break; |
| } |
| firstInLine = false; |
| } |
| } |
| } |
| |
| private TextState calculateLineWidth(FontModification initialFontMod, double currentTextWidth, List<TextToken> line, |
| TextToken token, float fontSize) throws IOException { |
| List<TextToken> tokens = new ArrayList<>(line); |
| tokens.add(token); |
| double width = currentTextWidth; |
| FontModification currentFontMod = initialFontMod; |
| TextState result = new TextState(); |
| for (TextToken lt : tokens) { |
| switch (lt.getType()) { |
| case TK_BOLD: |
| case TK_ITALIC: |
| currentFontMod = updateFontMod(currentFontMod, lt.getType()); |
| break; |
| case TK_SPACE: |
| width += calcSize(fonts.get(currentFontMod), fontSize, TEXT_SPACE); |
| break; |
| case TK_BULLET: |
| width += calcSize(fonts.get(currentFontMod), fontSize, TEXT_BULLET); |
| result.setInBulletPoint(true); |
| break; |
| case STRING: |
| width += calcSize(fonts.get(currentFontMod), fontSize, lt.getValue()); |
| break; |
| case TK_NL: |
| result.setLineBreak(true); |
| result.setInBulletPoint(false); |
| break; |
| default: |
| break; |
| } |
| } |
| result.setWidth(width); |
| result.setFontMode(currentFontMod); |
| return result; |
| } |
| |
| private void drawInfoBox(PDDocument document, PDPage firstPage, TemplateConfig templateConfig, Map<String, String> replacements) throws IOException { |
| PDPageContentStream cont = new PDPageContentStream(document, firstPage, AppendMode.APPEND, false, true); |
| float pageHeight = firstPage.getMediaBox().getHeight(); |
| |
| TemplateTextBlockConfig cfg = templateConfig.getInfo(); |
| float posX = dpiOfCm(cfg.getX()); |
| float posY = calcYPosFromTopCm(cfg.getY(), pageHeight); |
| float width = dpiOfCm(cfg.getWidth()); |
| float height = dpiOfCm(cfg.getHeight()); |
| |
| List<String> text = cfg.getText(); |
| |
| List<String> lines = new ArrayList<>(); |
| for (String textEntry : text) { |
| textEntry = TextCompileUtil.fillPlaceholder(textEntry, null, replacements, new HashMap<>()); |
| lines.addAll(cutintopieces(fonts.get(FontModification.Normal), cfg.getFontSize(), textEntry, width)); |
| } |
| |
| double leading = cfg.getFontSize() * 1.12; |
| |
| PageContext context = new PageContext(); |
| context.setPosX(posX); |
| context.setPosY(posY); |
| context.setLeading(leading); |
| context.setWidth(width); |
| context.setHeight(height); |
| |
| drawRect(context, cont); |
| |
| cont.beginText(); |
| cont.setFont(fonts.get(FontModification.Normal), cfg.getFontSize()); |
| cont.setLeading(leading); |
| cont.newLineAtOffset(posX, posY); |
| |
| for (String line : lines) { |
| cont.showText(line); |
| cont.newLine(); |
| } |
| cont.close(); |
| } |
| |
| private void drawAddressBox(PDDocument document, PDPage firstPage, TemplateConfig templateConfig, |
| CompanyContactBlockModel contact) throws IOException { |
| List<String> address = new ArrayList<>(); |
| address.add(contact.getCompany()); |
| List<String> nameEntries = new ArrayList<>(); |
| if (contact.getSalutation() != null) { |
| nameEntries.add(contact.getSalutation()); |
| } |
| if (contact.getTitle() != null) { |
| nameEntries.add(contact.getTitle()); |
| } |
| nameEntries.add(contact.getFirstName()); |
| nameEntries.add(contact.getLastName()); |
| address.add(String.join(TEXT_SPACE, nameEntries)); |
| address.add(contact.getStreet() + contact.getHouseNumber()); |
| address.add(contact.getPostCode() + TEXT_SPACE + contact.getCommunity()); |
| if (contact.getCommunitySuffix() != null) { |
| address.add(contact.getCommunitySuffix()); |
| } |
| |
| PDPageContentStream cont = new PDPageContentStream(document, firstPage, AppendMode.APPEND, false, true); |
| float pageHeight = firstPage.getMediaBox().getHeight(); |
| |
| TemplateTextBlockConfig addressCfg = templateConfig.getAddress(); |
| float posX = dpiOfCm(addressCfg.getX()); |
| float posY = calcYPosFromTopCm(addressCfg.getY(), pageHeight); |
| float width = dpiOfCm(addressCfg.getWidth()); |
| float height = dpiOfCm(addressCfg.getHeight()); |
| |
| List<String> lines = new ArrayList<>(); |
| for (String textEntry : address) { |
| lines.addAll(cutintopieces(fonts.get(FontModification.Normal), addressCfg.getFontSize(), textEntry, width)); |
| } |
| |
| double leading = addressCfg.getFontSize() * 1.12; |
| PageContext context = new PageContext(); |
| context.setPosX(posX); |
| context.setPosY(posY); |
| context.setLeading(leading); |
| context.setWidth(width); |
| context.setHeight(height); |
| drawRect(context, cont); |
| |
| cont.beginText(); |
| cont.setFont(fonts.get(FontModification.Normal), addressCfg.getFontSize()); |
| cont.setLeading(leading); |
| cont.newLineAtOffset(posX, posY); |
| |
| for (String line : lines) { |
| cont.showText(line); |
| cont.newLine(); |
| } |
| cont.endText(); |
| cont.close(); |
| } |
| |
| private PDPage clonePage(PDPage original) { |
| COSDictionary pageDict = original.getCOSObject(); |
| COSDictionary newPageDict = new COSDictionary(pageDict); |
| newPageDict.removeItem(COSName.ANNOTS); |
| return new PDPage(newPageDict); |
| } |
| |
| } |