Skip to content

Commit d9cd101

Browse files
authored
{{pages}} do not print in PDFBox (#1076)
The template {{pages}} does not print in PDFBox Issue: 207056
1 parent da21f06 commit d9cd101

1 file changed

Lines changed: 60 additions & 87 deletions

File tree

java/src/main/java/com/genexus/reports/PDFReportPDFBox.java

Lines changed: 60 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@
3030
import org.apache.pdfbox.pdmodel.graphics.state.RenderingMode;
3131
import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript;
3232
import org.apache.pdfbox.pdmodel.interactive.viewerpreferences.PDViewerPreferences;
33-
import org.apache.pdfbox.text.PDFTextStripper;
34-
import org.apache.pdfbox.text.TextPosition;
3533
import org.apache.pdfbox.util.Matrix;
3634

3735
import org.jsoup.Jsoup;
@@ -51,9 +49,6 @@ public class PDFReportPDFBox extends GXReportPDFCommons{
5149
private String barcodeType = null;
5250
private PDDocument document;
5351
private PDDocumentCatalog writer;
54-
private PDFont templateFont;
55-
private float templateX;
56-
private float templateY;
5752
public boolean lineCapProjectingSquare = true;
5853
public boolean barcode128AsImage = true;
5954
ConcurrentHashMap<String, PDImageXObject> documentImages;
@@ -63,6 +58,7 @@ public class PDFReportPDFBox extends GXReportPDFCommons{
6358
private Set<String> supportedHTMLTags = new HashSet<>();
6459
private PDPageContentStream currentPageContentStream;
6560
private final static String PAGES_PLACEHOLDER = "{{pages}}";
61+
private final List<PageCountPlaceholder> pageCountPlaceholders = new ArrayList<>();
6662

6763
static {
6864
log = org.apache.logging.log4j.LogManager.getLogger(PDFReportPDFBox.class);
@@ -647,6 +643,31 @@ public void GxDrawText(String sTxt, int left, int top, int right, int bottom, in
647643
int alignment = align & 3;
648644
boolean autoResize = ((align & 256) == 256);
649645

646+
if (sTxt.trim().equalsIgnoreCase(PAGES_PLACEHOLDER)) {
647+
float width = baseFont.getStringWidth("999") / 1000 * fontSize;
648+
649+
float x;
650+
switch (align) {
651+
case 1:
652+
x = ((leftAux + rightAux) / 2) + leftMargin - width / 2;
653+
break;
654+
case 2:
655+
x = rightAux + leftMargin - width;
656+
break;
657+
default:
658+
x = leftAux + leftMargin;
659+
break;
660+
}
661+
662+
float y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin - fontSize*0.2f ;
663+
664+
int pageIndex = document.getNumberOfPages() - 1;
665+
pageCountPlaceholders.add(new PageCountPlaceholder(pageIndex, x, y, baseFont, fontSize, foreColor));
666+
667+
return;
668+
}
669+
670+
650671
// Handle HTML format
651672
if (htmlformat == 1) {
652673
log.debug("WARNING: HTML rendering is not natively supported by PDFBOX 2.0.27. Handcrafted support is provided but it is not intended to cover all possible use cases");
@@ -857,19 +878,6 @@ else if (barcodeType != null) {
857878
contentStream.fill();
858879
}
859880

860-
// Handle {{Pages}}
861-
if (sTxt.trim().equalsIgnoreCase(PAGES_PLACEHOLDER)) {
862-
if (!templateCreated) {
863-
templateFont = baseFont;
864-
templateFontSize = fontSize;
865-
templateColorFill = foreColor;
866-
templateX = leftAux + leftMargin;
867-
templateY = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin;
868-
templateCreated = true;
869-
}
870-
sTxt = PAGES_PLACEHOLDER;
871-
}
872-
873881
float textBlockWidth = rightAux - leftAux;
874882
float txtWidth = baseFont.getStringWidth(sTxt) / 1000 * fontSize;
875883
boolean justified = (alignment == 3) && textBlockWidth < txtWidth;
@@ -1271,75 +1279,22 @@ else if (length == 15840 && width == 12240)
12711279
return new PDRectangle((int)(width / PAGE_SCALE_X) + leftMargin, (int)(length / PAGE_SCALE_Y) + topMargin);
12721280
}
12731281

1274-
private void replaceTemplatePages() throws IOException {
1282+
private void writePageCountPlaceholders() {
12751283
int totalPages = document.getNumberOfPages();
1276-
for (int i = 0; i < totalPages; i++) {
1277-
final PDPage page = document.getPage(i);
1278-
final List<float[]> replacements = new java.util.ArrayList<>();
1279-
PDFTextStripper stripper = new PDFTextStripper() {
1280-
@Override
1281-
protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
1282-
String placeholder = PAGES_PLACEHOLDER;
1283-
int index = text.indexOf(placeholder);
1284-
while (index != -1 && index + placeholder.length() <= textPositions.size()) {
1285-
float minX = Float.MAX_VALUE;
1286-
float maxX = 0;
1287-
float minY = Float.MAX_VALUE;
1288-
float maxY = 0;
1289-
for (int j = index; j < index + placeholder.length(); j++) {
1290-
TextPosition tp = textPositions.get(j);
1291-
float tpX = tp.getXDirAdj();
1292-
float tpY = tp.getYDirAdj();
1293-
float tpWidth = tp.getWidthDirAdj();
1294-
float tpHeight = tp.getHeightDir();
1295-
if (tpX < minX) {
1296-
minX = tpX;
1297-
}
1298-
if (tpX + tpWidth > maxX) {
1299-
maxX = tpX + tpWidth;
1300-
}
1301-
if (tpY < minY) {
1302-
minY = tpY;
1303-
}
1304-
if (tpY + tpHeight > maxY) {
1305-
maxY = tpY + tpHeight;
1306-
}
1307-
}
1308-
float bboxWidth = maxX - minX;
1309-
float bboxHeight = maxY - minY;
1310-
float origBoxBottom = pageSize.getHeight() - maxY;
1311-
float originalCenterX = minX + bboxWidth / 2;
1312-
float originalCenterY = origBoxBottom + bboxHeight / 2;
1313-
float newCenterY = originalCenterY + (bboxHeight * 0.5f);
1314-
float enlargedWidth = bboxWidth * 2.5f;
1315-
float enlargedHeight = bboxHeight * 2.5f;
1316-
float rectX = originalCenterX - (enlargedWidth / 2);
1317-
float rectY = newCenterY - (enlargedHeight / 2);
1318-
float baselineY = newCenterY;
1319-
replacements.add(new float[] { rectX, rectY, enlargedWidth, enlargedHeight, baselineY });
1320-
index = text.indexOf(placeholder, index + placeholder.length());
1321-
}
1322-
super.writeString(text, textPositions);
1323-
}
1324-
};
1325-
stripper.setStartPage(i + 1);
1326-
stripper.setEndPage(i + 1);
1327-
stripper.getText(document);
1328-
if (!replacements.isEmpty()) {
1329-
try (PDPageContentStream cs = new PDPageContentStream(
1330-
document, page, PDPageContentStream.AppendMode.APPEND, true, true)) {
1331-
for (float[] rep : replacements) {
1332-
cs.addRect(rep[0], rep[1], rep[2], rep[3]);
1333-
cs.setNonStrokingColor(java.awt.Color.WHITE);
1334-
cs.fill();
1335-
cs.beginText();
1336-
cs.setFont(templateFont, templateFontSize);
1337-
cs.setNonStrokingColor(templateColorFill);
1338-
cs.newLineAtOffset(rep[0], rep[4]);
1339-
cs.showText(String.valueOf(totalPages));
1340-
cs.endText();
1341-
}
1342-
}
1284+
1285+
for (PageCountPlaceholder p : pageCountPlaceholders) {
1286+
PDPage page = document.getPage(p.pageIndex);
1287+
try (PDPageContentStream cs = new PDPageContentStream(
1288+
document, page, PDPageContentStream.AppendMode.APPEND, true)) {
1289+
1290+
cs.beginText();
1291+
cs.setFont(p.font, p.fontSize);
1292+
cs.setNonStrokingColor(p.color);
1293+
cs.newLineAtOffset(p.x, p.y);
1294+
cs.showText(String.valueOf(totalPages));
1295+
cs.endText();
1296+
} catch (IOException e) {
1297+
log.error("Failed to write page count placeholder", e);
13431298
}
13441299
}
13451300
}
@@ -1351,7 +1306,7 @@ public void GxEndDocument() {
13511306
pages++;
13521307
}
13531308
GxEndPage();
1354-
replaceTemplatePages();
1309+
writePageCountPlaceholders();
13551310
int copies = 1;
13561311
try {
13571312
copies = Integer.parseInt(printerSettings.getProperty(form, Const.COPIES));
@@ -1488,4 +1443,22 @@ public void GxEndPage() {
14881443
}
14891444
}
14901445

1446+
private static class PageCountPlaceholder {
1447+
final int pageIndex;
1448+
final float x;
1449+
final float y;
1450+
final PDFont font;
1451+
final float fontSize;
1452+
final Color color;
1453+
1454+
PageCountPlaceholder(int pageIndex, float x, float y, PDFont font, float fontSize, Color color) {
1455+
this.pageIndex = pageIndex;
1456+
this.x = x;
1457+
this.y = y;
1458+
this.font = font;
1459+
this.fontSize = fontSize;
1460+
this.color = color;
1461+
}
1462+
}
1463+
14911464
}

0 commit comments

Comments
 (0)