Spire.PDF is a professional PDF library applied to creating, writing, editing, handling and reading PDF files without any external dependencies. Get free and professional technical support for Spire.PDF for .NET, Java, Android, C++, Python.

Fri Oct 17, 2025 1:01 pm

i have this code
Code: Select all
if (value.length() < charLimitPerLine && fontSize > 5f) {

                                    replacer.replaceAllText(textFragment.getText(), (String) reportPDFFields.get(key));
                                } else {

                                    if (value.equals("■") || value.equals("□") || key.equals("addressStreet")) {
                                    //change font to arial and increase font size
                                    } else {
                                        _log.info("value: " + value);

                                        if (fontSize < 5f) fontSize = 7f;
                                        replacer.replaceText(textFragment.getText(), "");
                                        textFragment.getTextStates()[0].getFontFamily();

                                        PdfTextWidget textWidget = new PdfTextWidget(
                                                value,
                                                new PdfTrueTypeFont("C:\\Users\\ja.dinardo\\Desktop\\NotoSans\\NotoSans-Regular-2.ttf", fontSize),
                                                PdfBrushes.getBlack()
                                        );
                                        Rectangle2D bounds = textFragment.getBounds()[0].getBounds2D();
                                        float minHeight = fontSize + 1f;
                                        float actualHeight = Math.max((float) bounds.getHeight(), minHeight);
                                        PdfLayoutResult result = textWidget.draw(
                                                page,
                                                new Rectangle2D.Float(
                                                        (float) bounds.getX(),
                                                        (float) bounds.getY(),
                                                        (float) (bounds.getWidth()), // margine destro
                                                        (float) bounds.getHeight() // altezza automatica
                                                )
                                        );
                                    }
                                }


I want to know if I'm doing it correctly. in this snippet i replace a placeholder in the pdf with the corrispondent value.
When the font size is too small or the value is too long i draw a rectangle to increase font size or replace the text using two rows.
the 2 rows works correctly.

When i change font size and there are 2 placeholder one on top of the other it will draw just one.
Is there a better option to do this?
I'm usin spire.pdf 11.8.0 and java 1.8

Thanks.
Jacopo.

jadinard
 
Posts: 13
Joined: Wed Aug 13, 2025 2:25 pm

Fri Oct 17, 2025 1:55 pm

I may have found the problem, when i replace the Y between the 2 placeholders is too small
[optimizationReplaceAll][bounds.X] [115.39800262451172]_[bounds.Y] [478.2963562011719]_[bounds.MaxX] [146.70619201660156]_[bounds.MaxY] [480.30935621261597] [Sanitized]
[optimizationReplaceAll][value] [24][key] [_2001_hUsageRateValueMax]
[optimizationReplaceAll][bounds.X] [115.54000091552734]_[bounds.Y] [487.0833435058594]_[bounds.MaxX] [147.4178695678711]_[bounds.MaxY] [489.09634351730347] [Sanitized]

jadinard
 
Posts: 13
Joined: Wed Aug 13, 2025 2:25 pm

Mon Oct 20, 2025 3:13 am

Hello,

Sorry for the delayed response due to the weekend on our end.
Glad to hear you've identified the root cause of the issue. If the issue persists, please share your files and complete executable code with us for further investigation. You may upload the files as attachments or send them directly to my email: [email protected]. Thanks in advance.
Sincerely,
Talia
E-iceblue support team
User avatar

talia.liu
 
Posts: 331
Joined: Mon Apr 14, 2025 3:33 am

Mon Oct 20, 2025 8:04 am

talia.liu wrote:Hello,

Sorry for the delayed response due to the weekend on our end.
Glad to hear you've identified the root cause of the issue. If the issue persists, please share your files and complete executable code with us for further investigation. You may upload the files as attachments or send them directly to my email: [email protected]. Thanks in advance.


yes but i need some info

is this snippet correct to replace text while i want to increase the font size?

replacer.replaceText(textFragment.getText(), "");
PdfTextWidget textWidget = new PdfTextWidget(
value,
new PdfTrueTypeFont("C:\\Users\\ja.dinardo\\Desktop\\NotoSans\\NotoSans-Regular-2.ttf", fontSize),
PdfBrushes.getBlack()
);
Rectangle2D bounds = textFragment.getBounds()[0].getBounds2D();
float minHeight = Math.max((float) bounds.getHeight(), fontSize + 1);

PdfLayoutResult result = textWidget.draw(
page,
new Rectangle2D.Float(
(float) bounds.getX(),
(float) bounds.getY(),
(float) (bounds.getWidth()), // margine destro
(float) minHeight // altezza automatica
)
);


Is there some problem with thread when i am doing this while using replacer?
If the replace of two rectangle intersect do it stop replacing it?

jadinard
 
Posts: 13
Joined: Wed Aug 13, 2025 2:25 pm

Mon Oct 20, 2025 9:30 am

I may have found something strange.

if i do this
Code: Select all
replacer.replaceText(textFragment.getText(), "");
                                    PdfTextWidget textWidget = new PdfTextWidget(
                                            value,
                                            new PdfTrueTypeFont("C:\\Users\\ja.dinardo\\Desktop\\NotoSans\\NotoSans-Regular-2.ttf", fontSize),
                                            PdfBrushes.getBlack()
                                    );
                                    Rectangle2D bounds = textFragment.getBounds()[0].getBounds2D();
                                    float minHeight = Math.max((float) bounds.getHeight(), fontSize + 1);

                                    PdfLayoutResult result = textWidget.draw(
                                            page,
                                            new Rectangle2D.Float(
                                                    (float) bounds.getX(),
                                                    (float) bounds.getY(),
                                                    (float) (bounds.getWidth()), // margine destro
                                                    (float) minHeight // altezza automatica
                                            )
                                    );


On a foreach text fragment, it works only the first time.

Does it break something? the canvas maybe?

jadinard
 
Posts: 13
Joined: Wed Aug 13, 2025 2:25 pm

Mon Oct 20, 2025 9:50 am

Hello,

Thank you for your feedback.
Based on the information you provided, please refer to the following code for implementing text and font size replacement:

Code: Select all
PdfDocument doc = new PdfDocument();
        doc.loadFromFile("sample.pdf");
        StringBuilder builder = new StringBuilder();
        for (Object pageBase : doc.getPages()) {
            PdfPageBase pagebase = (PdfPageBase) pageBase;
            PdfTextFinder find = new PdfTextFinder(pagebase);
            find.getOptions().setTextFindParameter(EnumSet.of(TextFindParameter.WholeWord));
            String text="PDF";
            List<PdfTextFragment> collection =find.find(text);
            for (PdfTextFragment  fragment : collection) {

                Point2D[] locations = fragment.getPositions();
                Dimension2D[] size = fragment.getSizes();
                for (int i = 0; i < locations.length; i++) {
                    float x = (float) locations[i].getX();
                    float y = (float) locations[i].getY();
                    float h = (float) size[i].getHeight();
                    float w = (float) size[i].getWidth();
                    System.out.println(text:"+text +"  X: " + x + " Y: " + y +"   height: " +h+"  width: "+w);

                    float width = h;
                    float height = w;
                    PdfPen pen = new PdfPen(new PdfRGBColor(Color.white), 0f);
                    PdfBrush brush=  PdfBrushes.getWhite();

                    pagebase.getCanvas().drawRectangle(pen, brush,x, y,height , width);


                    PdfTextWidget textWidget = new PdfTextWidget(
                        "test",
                        new PdfTrueTypeFont("C:\\Windows\\Fonts\\Open-Sans.ttf", 12f),
                        PdfBrushes.getBlack()
                );
                Rectangle2D bounds = fragment.getBounds()[0].getBounds2D();
                float minHeight = Math.max((float) bounds.getHeight(), 13f);

                PdfLayoutResult result = textWidget.draw(
                        pagebase,
                        new Rectangle2D.Float(
                                (float) bounds.getX(),
                                (float) bounds.getY(),
                                (float) (bounds.getWidth()), // margine destro
                                (float) minHeight // altezza automatica
                        ));
            }
            doc.saveToFile("testreplace.pdf");
    }

In my local testing environment, I did not encounter any issues under multi-threading conditions, nor did I experience the problem of replacement stopping due to rectangle intersection. Could you please test again in your environment using the code above? If you encounter any issues, please send us your test file, and we will conduct further investigation. We look forward to receiving your feedback.
Sincerely,
Talia
E-iceblue support team
User avatar

talia.liu
 
Posts: 331
Joined: Mon Apr 14, 2025 3:33 am

Mon Oct 20, 2025 12:51 pm

Hi i did some test

private void optimizationReplaceAllSinglePage(PdfPageBase page, Map<String, Object> reportPDFFields, List<PdfTextFragment> textFragmentCollection) {

// Create text find options for searching
PdfTextFindOptions findOptions = new PdfTextFindOptions();

// Set search parameters
findOptions.setTextFindParameter(EnumSet.of(TextFindParameter.Regex));

String regex = "\\${2,}\\w+\\${2,}";


// PdfTextReplacer replacer = new PdfTextReplacer(page);
PdfTextReplaceOptions options = new PdfTextReplaceOptions();
options.setReplaceType(EnumSet.of(ReplaceActionType.Regex));
List<TextToDraw> textsToDraw = new ArrayList<>();
for (PdfTextFragment textFragment : textFragmentCollection) {
try {
String text = textFragment.getText();
String key = text.replaceAll("\\$", StringPool.BLANK);
if (reportPDFFields.containsKey(key)) {
// float fontSize = textFragment.getTextState().getFontSize();
// if (fontSize < 5f) fontSize = 7f;
if (reportPDFFields.get(key) instanceof String) {
float fontSize;
try {
fontSize = textFragment.getTextStates()[0].getFontSize();
} catch (Exception e) {
fontSize = 7f;
}
String value = (String) reportPDFFields.get(key);
try {
value = value.replaceAll("\\r?\\n", " ");
int charLimitPerLine = textFragment.getText().length();

if (value.length() < charLimitPerLine) {
if (fontSize > 5) {
// replacer.replaceAllText(textFragment.getText(), (String) reportPDFFields.get(key));
} else {
if (_log.isInfoEnabled()) {
_log.info("[optimizationReplaceAll]"
+ "[value]" + " [" + value + "]"
+ "[X]" + " [" + textFragment.getBounds()[0].getX() + "]"
+ "[y]" + " [" + textFragment.getBounds()[0].getY() + "]"
);

}
if (value.equals("■") || value.equals("□")) {
continue;
}
Rectangle2D bounds = textFragment.getBounds()[0].getBounds2D();
fontSize = 7f;
// replacer.replaceText(textFragment.getText(), " "); // Spazio non vuoto
page.getCanvas().drawRectangle(
PdfBrushes.getWhite(),
new Rectangle2D.Float(
(float) bounds.getX() - 1,
(float) bounds.getY() - 1,
(float) bounds.getWidth() + 2,
(float) bounds.getHeight() + 2
)
);
PdfTrueTypeFont font = new PdfTrueTypeFont(new Font("Arial", Font.PLAIN, 8), true);
PdfStringFormat format = new PdfStringFormat(PdfTextAlignment.Left);

page.getCanvas().drawString(
value,
font,
PdfBrushes.getBlack(),
(float) bounds.getX(),
(float) bounds.getY(),
format
);
// NO save/restore, solo transparency
page.getCanvas().setTransparency(1);
// replacer.replaceText(textFragment.getText(), "");
// PdfTextWidget textWidget = new PdfTextWidget(
// value,
// new PdfTrueTypeFont("C:\\Users\\ja.dinardo\\Desktop\\NotoSans\\NotoSans-Regular-2.ttf", fontSize),
// PdfBrushes.getBlack()
// );
// Rectangle2D bounds = textFragment.getBounds()[0].getBounds2D();
// float minHeight = Math.max((float) bounds.getHeight(), fontSize + 1);
//
// PdfLayoutResult result = textWidget.draw(
// page,
// new Rectangle2D.Float(
// (float) bounds.getX(),
// (float) bounds.getY(),
// (float) (bounds.getWidth()), // margine destro
// (float) minHeight // altezza automatica
// )
// );
// page.getCanvas().restore();
}
} else {

// replacer.replaceText(textFragment.getText(), "");
// PdfTextWidget textWidget = new PdfTextWidget(
// value,
// new PdfTrueTypeFont("C:\\Users\\ja.dinardo\\Desktop\\NotoSans\\NotoSans-Regular-2.ttf", fontSize),
// PdfBrushes.getBlack()
// );
// Rectangle2D bounds = textFragment.getBounds()[0].getBounds2D();
// float minHeight = Math.max((float) bounds.getHeight(), fontSize + 1);
//
// PdfLayoutResult result = textWidget.draw(
// page,
// new Rectangle2D.Float(
// (float) bounds.getX(),
// (float) bounds.getY(),
// (float) (bounds.getWidth()), // margine destro
// (float) minHeight // altezza automatica
// )
// );

}
} catch (Exception e) {
_log.error("Could not replace text", e);
}
} else {
if (_log.isDebugEnabled()) {
_log.debug("[asposePDFExporterImpl] optimizationReplaceAll error replacing: key = " + key + "text = " + text);
}
// replacer.replaceText(textFragment.getText(), StringPool.DASH);
}
} else {
// replacer.replaceText(textFragment.getText(), StringPool.DASH);
}
} catch (Exception e1) {
_log.error("[asposePDFExporterImpl] optimizationReplaceAll " + e1.getMessage(), e1);
}
}
}


To make the draw string function work on all strings, I had to comment out the replacer, so if they are operating together, only the replacer works, and then the first drawing works and the rest do not.
I can do some workaround but can you let me know if like the replacer block the canvas?

jadinard
 
Posts: 13
Joined: Wed Aug 13, 2025 2:25 pm

Tue Oct 21, 2025 6:00 am

Hello,

Thank you for your feedback.
Could you please describe the specific symptoms of the issue where only the first drawing operation works? I have tested using the function you provided with a simulated simple document, but was unable to reproduce the issue. Could you please provide us with your complete running code, test input files, result files, or screenshots of the issue? This will help us identify the specific cause of the problem. You may upload the files as attachments or send them directly to my email: [email protected]. Thanks in advance.
Sincerely,
Talia
E-iceblue support team
User avatar

talia.liu
 
Posts: 331
Joined: Mon Apr 14, 2025 3:33 am

Return to Spire.PDF