34
34
import org .apache .pdfbox .pdmodel .graphics .state .RenderingMode ;
35
35
import org .apache .pdfbox .pdmodel .interactive .action .PDActionJavaScript ;
36
36
import org .apache .pdfbox .pdmodel .interactive .viewerpreferences .PDViewerPreferences ;
37
+ import org .apache .pdfbox .text .PDFTextStripper ;
38
+ import org .apache .pdfbox .text .TextPosition ;
37
39
import org .apache .pdfbox .util .Matrix ;
38
40
39
41
import org .jsoup .Jsoup ;
@@ -65,6 +67,8 @@ public class PDFReportPDFBox extends GXReportPDFCommons{
65
67
private final float DEFAULT_PDFBOX_LEADING = 1.2f ;
66
68
67
69
private Set <String > supportedHTMLTags = new HashSet <>();
70
+ private PDPageContentStream currentPageContentStream ;
71
+ private final static String PAGES_PLACEHOLDER = "{{pages}}" ;
68
72
69
73
static {
70
74
log = org .apache .logging .log4j .LogManager .getLogger (PDFReportPDFBox .class );
@@ -811,7 +815,8 @@ else if (valign == PDFReportPDFBox.VerticalAlign.BOTTOM.value())
811
815
contentStream .close ();
812
816
}
813
817
814
- if (sTxt .trim ().equalsIgnoreCase ("{{Pages}}" )) {
818
+ // Handle {{Pages}}
819
+ if (sTxt .trim ().equalsIgnoreCase (PAGES_PLACEHOLDER )) {
815
820
if (!templateCreated ) {
816
821
templateFont = baseFont ;
817
822
templateFontSize = fontSize ;
@@ -820,7 +825,7 @@ else if (valign == PDFReportPDFBox.VerticalAlign.BOTTOM.value())
820
825
templateY = this .pageSize .getUpperRightY () - bottomAux - topMargin - bottomMargin ;
821
826
templateCreated = true ;
822
827
}
823
- sTxt = String . valueOf ( this . page ) ;
828
+ sTxt = PAGES_PLACEHOLDER ;
824
829
}
825
830
826
831
float textBlockWidth = rightAux - leftAux ;
@@ -1227,12 +1232,86 @@ else if (length == 15840 && width == 12240)
1227
1232
return new PDRectangle ((int )(width / PAGE_SCALE_X ) + leftMargin , (int )(length / PAGE_SCALE_Y ) + topMargin );
1228
1233
}
1229
1234
1235
+ private void replaceTemplatePages () throws IOException {
1236
+ int totalPages = document .getNumberOfPages ();
1237
+ for (int i = 0 ; i < totalPages ; i ++) {
1238
+ final PDPage page = document .getPage (i );
1239
+ final List <float []> replacements = new java .util .ArrayList <>();
1240
+ PDFTextStripper stripper = new PDFTextStripper () {
1241
+ @ Override
1242
+ protected void writeString (String text , List <TextPosition > textPositions ) throws IOException {
1243
+ String placeholder = PAGES_PLACEHOLDER ;
1244
+ int index = text .indexOf (placeholder );
1245
+ while (index != -1 && index + placeholder .length () <= textPositions .size ()) {
1246
+ float minX = Float .MAX_VALUE ;
1247
+ float maxX = 0 ;
1248
+ float minY = Float .MAX_VALUE ;
1249
+ float maxY = 0 ;
1250
+ for (int j = index ; j < index + placeholder .length (); j ++) {
1251
+ TextPosition tp = textPositions .get (j );
1252
+ float tpX = tp .getXDirAdj ();
1253
+ float tpY = tp .getYDirAdj ();
1254
+ float tpWidth = tp .getWidthDirAdj ();
1255
+ float tpHeight = tp .getHeightDir ();
1256
+ if (tpX < minX ) {
1257
+ minX = tpX ;
1258
+ }
1259
+ if (tpX + tpWidth > maxX ) {
1260
+ maxX = tpX + tpWidth ;
1261
+ }
1262
+ if (tpY < minY ) {
1263
+ minY = tpY ;
1264
+ }
1265
+ if (tpY + tpHeight > maxY ) {
1266
+ maxY = tpY + tpHeight ;
1267
+ }
1268
+ }
1269
+ float bboxWidth = maxX - minX ;
1270
+ float bboxHeight = maxY - minY ;
1271
+ float origBoxBottom = pageSize .getHeight () - maxY ;
1272
+ float originalCenterX = minX + bboxWidth / 2 ;
1273
+ float originalCenterY = origBoxBottom + bboxHeight / 2 ;
1274
+ float newCenterY = originalCenterY + (bboxHeight * 0.5f );
1275
+ float enlargedWidth = bboxWidth * 2.5f ;
1276
+ float enlargedHeight = bboxHeight * 2.5f ;
1277
+ float rectX = originalCenterX - (enlargedWidth / 2 );
1278
+ float rectY = newCenterY - (enlargedHeight / 2 );
1279
+ float baselineY = newCenterY ;
1280
+ replacements .add (new float [] { rectX , rectY , enlargedWidth , enlargedHeight , baselineY });
1281
+ index = text .indexOf (placeholder , index + placeholder .length ());
1282
+ }
1283
+ super .writeString (text , textPositions );
1284
+ }
1285
+ };
1286
+ stripper .setStartPage (i + 1 );
1287
+ stripper .setEndPage (i + 1 );
1288
+ stripper .getText (document );
1289
+ if (!replacements .isEmpty ()) {
1290
+ try (PDPageContentStream cs = new PDPageContentStream (
1291
+ document , page , PDPageContentStream .AppendMode .APPEND , true , true )) {
1292
+ for (float [] rep : replacements ) {
1293
+ cs .addRect (rep [0 ], rep [1 ], rep [2 ], rep [3 ]);
1294
+ cs .setNonStrokingColor (java .awt .Color .WHITE );
1295
+ cs .fill ();
1296
+ cs .beginText ();
1297
+ cs .setFont (templateFont , templateFontSize );
1298
+ cs .setNonStrokingColor (templateColorFill );
1299
+ cs .newLineAtOffset (rep [0 ], rep [4 ]);
1300
+ cs .showText (String .valueOf (totalPages ));
1301
+ cs .endText ();
1302
+ }
1303
+ }
1304
+ }
1305
+ }
1306
+ }
1307
+
1230
1308
public void GxEndDocument () {
1231
1309
try {
1232
1310
if (document .getNumberOfPages () == 0 ) {
1233
1311
document .addPage (new PDPage (this .pageSize ));
1234
1312
pages ++;
1235
1313
}
1314
+ replaceTemplatePages ();
1236
1315
int copies = 1 ;
1237
1316
try {
1238
1317
copies = Integer .parseInt (printerSettings .getProperty (form , Const .COPIES ));
@@ -1351,4 +1430,4 @@ public void GxStartPage() {
1351
1430
page = page + 1 ;
1352
1431
}
1353
1432
1354
- }
1433
+ }
0 commit comments