Skip to content

Commit 5928d10

Browse files
iroquetaBeta Bot
authored andcommitted
Cherry pick branch 'genexuslabs:fix/pages-pdfbox' into beta
1 parent 58ac92b commit 5928d10

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
@@ -32,8 +32,6 @@
3232
import org.apache.pdfbox.pdmodel.graphics.state.RenderingMode;
3333
import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript;
3434
import org.apache.pdfbox.pdmodel.interactive.viewerpreferences.PDViewerPreferences;
35-
import org.apache.pdfbox.text.PDFTextStripper;
36-
import org.apache.pdfbox.text.TextPosition;
3735
import org.apache.pdfbox.util.Matrix;
3836

3937
import org.jsoup.Jsoup;
@@ -53,9 +51,6 @@ public class PDFReportPDFBox extends GXReportPDFCommons{
5351
private String barcodeType = null;
5452
private PDDocument document;
5553
private PDDocumentCatalog writer;
56-
private PDFont templateFont;
57-
private float templateX;
58-
private float templateY;
5954
public boolean lineCapProjectingSquare = true;
6055
public boolean barcode128AsImage = true;
6156
ConcurrentHashMap<String, PDImageXObject> documentImages;
@@ -65,6 +60,7 @@ public class PDFReportPDFBox extends GXReportPDFCommons{
6560
private Set<String> supportedHTMLTags = new HashSet<>();
6661
private PDPageContentStream currentPageContentStream;
6762
private final static String PAGES_PLACEHOLDER = "{{pages}}";
63+
private final List<PageCountPlaceholder> pageCountPlaceholders = new ArrayList<>();
6864

6965
static {
7066
log = org.apache.logging.log4j.LogManager.getLogger(PDFReportPDFBox.class);
@@ -668,6 +664,31 @@ public void GxDrawText(String sTxt, int left, int top, int right, int bottom, in
668664
int alignment = align & 3;
669665
boolean autoResize = ((align & 256) == 256);
670666

667+
if (sTxt.trim().equalsIgnoreCase(PAGES_PLACEHOLDER)) {
668+
float width = baseFont.getStringWidth("999") / 1000 * fontSize;
669+
670+
float x;
671+
switch (align) {
672+
case 1:
673+
x = ((leftAux + rightAux) / 2) + leftMargin - width / 2;
674+
break;
675+
case 2:
676+
x = rightAux + leftMargin - width;
677+
break;
678+
default:
679+
x = leftAux + leftMargin;
680+
break;
681+
}
682+
683+
float y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin - fontSize*0.2f ;
684+
685+
int pageIndex = document.getNumberOfPages() - 1;
686+
pageCountPlaceholders.add(new PageCountPlaceholder(pageIndex, x, y, baseFont, fontSize, foreColor));
687+
688+
return;
689+
}
690+
691+
671692
// Handle HTML format
672693
if (htmlformat == 1) {
673694
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");
@@ -878,19 +899,6 @@ else if (barcodeType != null) {
878899
contentStream.fill();
879900
}
880901

881-
// Handle {{Pages}}
882-
if (sTxt.trim().equalsIgnoreCase(PAGES_PLACEHOLDER)) {
883-
if (!templateCreated) {
884-
templateFont = baseFont;
885-
templateFontSize = fontSize;
886-
templateColorFill = foreColor;
887-
templateX = leftAux + leftMargin;
888-
templateY = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin;
889-
templateCreated = true;
890-
}
891-
sTxt = PAGES_PLACEHOLDER;
892-
}
893-
894902
float textBlockWidth = rightAux - leftAux;
895903
float txtWidth = baseFont.getStringWidth(sTxt) / 1000 * fontSize;
896904
boolean justified = (alignment == 3) && textBlockWidth < txtWidth;
@@ -1292,75 +1300,22 @@ else if (length == 15840 && width == 12240)
12921300
return new PDRectangle((int)(width / PAGE_SCALE_X) + leftMargin, (int)(length / PAGE_SCALE_Y) + topMargin);
12931301
}
12941302

1295-
private void replaceTemplatePages() throws IOException {
1303+
private void writePageCountPlaceholders() {
12961304
int totalPages = document.getNumberOfPages();
1297-
for (int i = 0; i < totalPages; i++) {
1298-
final PDPage page = document.getPage(i);
1299-
final List<float[]> replacements = new java.util.ArrayList<>();
1300-
PDFTextStripper stripper = new PDFTextStripper() {
1301-
@Override
1302-
protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
1303-
String placeholder = PAGES_PLACEHOLDER;
1304-
int index = text.indexOf(placeholder);
1305-
while (index != -1 && index + placeholder.length() <= textPositions.size()) {
1306-
float minX = Float.MAX_VALUE;
1307-
float maxX = 0;
1308-
float minY = Float.MAX_VALUE;
1309-
float maxY = 0;
1310-
for (int j = index; j < index + placeholder.length(); j++) {
1311-
TextPosition tp = textPositions.get(j);
1312-
float tpX = tp.getXDirAdj();
1313-
float tpY = tp.getYDirAdj();
1314-
float tpWidth = tp.getWidthDirAdj();
1315-
float tpHeight = tp.getHeightDir();
1316-
if (tpX < minX) {
1317-
minX = tpX;
1318-
}
1319-
if (tpX + tpWidth > maxX) {
1320-
maxX = tpX + tpWidth;
1321-
}
1322-
if (tpY < minY) {
1323-
minY = tpY;
1324-
}
1325-
if (tpY + tpHeight > maxY) {
1326-
maxY = tpY + tpHeight;
1327-
}
1328-
}
1329-
float bboxWidth = maxX - minX;
1330-
float bboxHeight = maxY - minY;
1331-
float origBoxBottom = pageSize.getHeight() - maxY;
1332-
float originalCenterX = minX + bboxWidth / 2;
1333-
float originalCenterY = origBoxBottom + bboxHeight / 2;
1334-
float newCenterY = originalCenterY + (bboxHeight * 0.5f);
1335-
float enlargedWidth = bboxWidth * 2.5f;
1336-
float enlargedHeight = bboxHeight * 2.5f;
1337-
float rectX = originalCenterX - (enlargedWidth / 2);
1338-
float rectY = newCenterY - (enlargedHeight / 2);
1339-
float baselineY = newCenterY;
1340-
replacements.add(new float[] { rectX, rectY, enlargedWidth, enlargedHeight, baselineY });
1341-
index = text.indexOf(placeholder, index + placeholder.length());
1342-
}
1343-
super.writeString(text, textPositions);
1344-
}
1345-
};
1346-
stripper.setStartPage(i + 1);
1347-
stripper.setEndPage(i + 1);
1348-
stripper.getText(document);
1349-
if (!replacements.isEmpty()) {
1350-
try (PDPageContentStream cs = new PDPageContentStream(
1351-
document, page, PDPageContentStream.AppendMode.APPEND, true, true)) {
1352-
for (float[] rep : replacements) {
1353-
cs.addRect(rep[0], rep[1], rep[2], rep[3]);
1354-
cs.setNonStrokingColor(java.awt.Color.WHITE);
1355-
cs.fill();
1356-
cs.beginText();
1357-
cs.setFont(templateFont, templateFontSize);
1358-
cs.setNonStrokingColor(templateColorFill);
1359-
cs.newLineAtOffset(rep[0], rep[4]);
1360-
cs.showText(String.valueOf(totalPages));
1361-
cs.endText();
1362-
}
1363-
}
1305+
1306+
for (PageCountPlaceholder p : pageCountPlaceholders) {
1307+
PDPage page = document.getPage(p.pageIndex);
1308+
try (PDPageContentStream cs = new PDPageContentStream(
1309+
document, page, PDPageContentStream.AppendMode.APPEND, true)) {
1310+
1311+
cs.beginText();
1312+
cs.setFont(p.font, p.fontSize);
1313+
cs.setNonStrokingColor(p.color);
1314+
cs.newLineAtOffset(p.x, p.y);
1315+
cs.showText(String.valueOf(totalPages));
1316+
cs.endText();
1317+
} catch (IOException e) {
1318+
log.error("Failed to write page count placeholder", e);
13641319
}
13651320
}
13661321
}
@@ -1372,7 +1327,7 @@ public void GxEndDocument() {
13721327
pages++;
13731328
}
13741329
GxEndPage();
1375-
replaceTemplatePages();
1330+
writePageCountPlaceholders();
13761331
int copies = 1;
13771332
try {
13781333
copies = Integer.parseInt(printerSettings.getProperty(form, Const.COPIES));
@@ -1509,4 +1464,22 @@ public void GxEndPage() {
15091464
}
15101465
}
15111466

1467+
private static class PageCountPlaceholder {
1468+
final int pageIndex;
1469+
final float x;
1470+
final float y;
1471+
final PDFont font;
1472+
final float fontSize;
1473+
final Color color;
1474+
1475+
PageCountPlaceholder(int pageIndex, float x, float y, PDFont font, float fontSize, Color color) {
1476+
this.pageIndex = pageIndex;
1477+
this.x = x;
1478+
this.y = y;
1479+
this.font = font;
1480+
this.fontSize = fontSize;
1481+
this.color = color;
1482+
}
1483+
}
1484+
15121485
}

0 commit comments

Comments
 (0)