gettalong / hexapdf

Versatile PDF creation and manipulation for Ruby
https://hexapdf.gettalong.org
Other
1.24k stars 70 forks source link

Odd behaviour with value layout of AcroForm TextField #163

Closed xenyal closed 2 years ago

xenyal commented 2 years ago

I'm noticing an odd issue when using HexaPDF to set a value on a TextField. If I were to open an example PDF using Mac OS preview, or Adobe Acrobat, I'm able to set a value on a given TextField with the layout of the text looking like the below screenshot (of which the blue background is the TextField area): image

However, when I set the value on the TextField dynamically using HexaPDF, the layout of the text proceeds to be offset to the point where part of the text gets chopped off like so: image

Might there be a way for me to reset the placement of the TextField value relative to the bounding box of the field widget? It appears in both cases that the text is going out of bounds to a degree, but only the second case leads to partially obscured text. I've tried overwriting the :DA on the field and on the widget level, but it didn't seem to affect the issue. What's strange is also that the Rect of the field widget doesn't seem to accurately portray the dimensions of the textbox, as the height should be drastically smaller than the width:

 :Rect=>#<HexaPDF::Rectangle [0, 0] value=[477.24, 464.04, 582.96, 474]>

Any pointers would be greatly appreciated!

gettalong commented 2 years ago

The location of the text is determined by various factors, e.g. the annotation rectangle, font size, font properties and it also tries to mimic the way Adobe Acrobat does it as good as possible. So I would need to have the PDF document in question to have an in-depth look at it why the placement is different.

As for the rectangle and its height: The PDF rectangle data structure is defined by four numbers which describe two diagonally opposite corners of the rectangle (this is in contrast to how a rectangle is drawn inside a content stream, e.g. with the lower left corner and width/height).

xenyal commented 2 years ago

Thanks for the response @gettalong! Here's an example of a PDF that contains the problematic TextFields I was talking about: blank.pdf

I've previously worked with PDFBox using jruby to handle resetting of the text field properties such as :FF, FLAG_COMB | FLAG_MULTILINE, false in which case certain behaviours of the text field gets reset 🤔 might I be able to do the same in HexaPDF? I do feel the specific issue I'm encountering with the above PDF is a separate issue though.

gettalong commented 2 years ago

Thanks for the PDF!

Some observations:

As for the other question: Yes, there are the #flag, #unflag, and #flagged? methods for setting those flags. So running field.unflag(:multiline) will unset the multiline flag. Same with :comb

xenyal commented 2 years ago

Awesome, thanks so much for the tips! Might there be any examples for how to construct or set annotation rectangles for a multiline text field? I figure that'd also require some level of calculation with respect to line spacing and the number of lines that can fit into the text field in that case.

As an aside, might you have a preference for where I ask questions about HexaPDF? I wasn't sure whether it's more appropriate to open a GitHub issue vs. asking a question on Stack Overflow.

gettalong commented 2 years ago

Hmm... setting the rectangle is as easy as widget[:Rect] = [llx, lly, urx, ury]. However, calculating the required height w.r.t. the number of lines is a bit trickier because it depends on the application/library generating the appearance. The default appearance generator shipped with HexaPDF uses the HexaPDF::Layout::TextLayouter class to do the actual layouting, using proportional line spacing with a factor of 1.25. Together with the font size this will allow you to calculate the needed height for a given number of lines (use one more line than needed to allow for error, padding, margins, ...).

You can ask on either one of them but on Github I will get a notification so you will get an answer quicker (don't know if something like this is possible on Stack Overflow...).

gettalong commented 2 years ago

@xenyal I just activated Github Discussions, so that is probably the best place from now on to ask questions :smile:

xenyal commented 2 years ago

Much appreciated @gettalong !