WeasyPrint icon indicating copy to clipboard operation
WeasyPrint copied to clipboard

Support for editable forms lacks support for radio buttons

Open zopyx opened this issue 2 years ago • 21 comments

See

https://print-css.rocks/lesson/lesson-forms https://print-css.rocks/lesson/lesson-forms/download/weasyprint.pdf

No offense but your implementation is only a partial implementation for editable forms (compared to other tools) since the support for radio buttons is missing (and the rendering is broken).

zopyx avatar Mar 07 '23 12:03 zopyx

@liZe - Is the constraint that only one option in a radio button group is selected that complicates including it in the editable (fillable) forms? Is there anywhere that talks more about what's missing?

I was looking at #1796, and you'd outline an approach to adding PDF forms when responding for adding support. Looking at add_inputs to see if I might get a handle on how the new support for textfield, textarea, & checkbox were added.

Is there any workaround? There's older response over here that points to a "tips & tricks" docs page that is to the previous host of the docs. I originally thought you might be able to render an underlying checkbox, but style it to appear as a radio button (and you'd lose the constraint for having only one selected).

Would looking at the pydyf approach to creating the PDF form tag help if I was brave enough to take a shot at a pull request?

Thanks for all the time you've put into this project & other Kozea projects

alenards avatar Jul 31 '23 23:07 alenards

Is the constraint that only one option in a radio button group is selected that complicates including it in the editable (fillable) forms?

The problem is to create these groups: we must find radio buttons that have the same name (shouldn’t be too hard) in the same form (that’s the hard part, because we don’t store this information). Rendering these inputs is the easy part (after spending some time reading the PDF specification, of course :smile:).

The clean solution would be to gather forms and their inputs, instead of just gathering a list of inputs, in gather_anchors. We basically need to:

  • replace inputs by forms, something like a dictionary with forms as keys and a list of inputs as values,
  • detect if box is a form, if it is store it in forms and keep the information that it’s the current form,
  • detect if box is an input, if it is store it in the current form,
  • change the document to store forms instead of inputs,
  • change the rendering code to receive forms instead of inputs, and to correctly draw radio buttons by finding radio button groups.

Gathering forms would also be useful to create PDF forms that send data to servers. But let’s keep that for another issue!

liZe avatar Aug 01 '23 07:08 liZe

Thank you for this detailed reply. I'll see if I can understand a bit better and maybe I'll have a follow-up question or two.

Rendering these inputs is the easy part (after spending some time reading the PDF specification, of course 😄).

I noticed in your profile the mention of being a "specification reader" 😉

alenards avatar Aug 01 '23 16:08 alenards

@liZe - when I was looking at another Python pdf library, I believe they stated the PDF 1.7 spec is the latest. Before I look closer, I wanted to make sure I'm in the right "neighborhood":

This is falls in the Acrobat SDK area, correct?

And this is the document to look at?

https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf


📝 the reason I asked if because the previous hyperlink used to refer to PDF 1.7 spec, https://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/pdf_reference_1-7.pdf, is now resolving to this page:

https://opensource.adobe.com/dc-acrobat-sdk-docs/

(cool that there is now an opensource.adobe.com subdomain ✨)

alenards avatar Aug 01 '23 17:08 alenards

when I was looking at another Python pdf library, I believe they stated the PDF 1.7 spec is the latest. Before I look closer, I wanted to make sure I'm in the right "neighborhood":

There’s actually PDF 2 (now available for free), but 1.7 is totally OK and easily available online, so you can use it.

This is falls in the Acrobat SDK area, correct?

You don’t have to use any of Adobe code, or to follow any of their API.

And this is the document to look at?

Yes. Section 12.7 is about forms, and section 12.7.4.2.4 is about radio buttons. You’ll see that’s it’s actually a subtype of buttons, really close to checkboxes (that are already implemented in WeasyPrint).

liZe avatar Aug 02 '23 06:08 liZe

Sorry @liZe - I worded this confusingly. I mainly wanted to confirm that I was reading that the right specification.

I did find the section on Field Types and Radio Buttons in PDF 1.7.

It seems like there is some valuable effort to get to the point where radio buttons could be rendered. So I'm going to try to address the first 4 bullets mentioned (regarding gather as form(s) that are keyed from form => input(s)) over here and I'll pull request them back to that forked repository in case anyone is curious to look at it:

  • https://github.com/alenards/WeasyPrint

alenards avatar Aug 02 '23 15:08 alenards

@zopyx - a note about the sample provided here, the weasyprint.pdf is no longer available at the provided link:

Screenshot 2023-08-02 at 9 37 56 AM

alenards avatar Aug 02 '23 16:08 alenards

@liZe - given what you know the source code, focusing these 2 bullets:

  • detect if box is a form, if it is store it in forms and keep the information that it’s the current form,
  • detect if box is an input, if it is store it in the current form

Do you have any thoughts about how you'd handle encountering a box where box.is_input() is True, but there is not a current form?

alenards avatar Aug 03 '23 18:08 alenards

Do you have any thoughts about how you'd handle encountering a box where box.is_input() is True, but there is not a current form?

If it’s not in a form, then it’s global and will be put with other global inputs.

If we store forms with this structure:

{<form1>: [<input11>, <input12>], <form2>: [<input21>, <input22>]}

then we can use None as a key to store inputs not in a form.

liZe avatar Aug 05 '23 09:08 liZe

That makes sense. I wasn't sure of the implications. Thanks @liZe 🙇

I have a PR nearing draft for "gathering forms" so that they're tracked. It does not address anything with the radio button groups yet. I thought if I sliced it a bit thinner it might help me tune up my Python (I haven't written Python in 3-5 years).

alenards avatar Aug 07 '23 15:08 alenards

I might be getting ahead of myself. But do see the "gathering" of inputs within their containing form (and/or global form) as causing any problems with the order they appear within a page of a document?

I can try to look closer at the pytests maybe for an answer there.

alenards avatar Aug 07 '23 16:08 alenards

But do see the "gathering" of inputs within their containing form (and/or global form) as causing any problems with the order they appear within a page of a document?

I’m not sure to understand your problem, but I don’t see why the order could be a problem.

liZe avatar Aug 09 '23 16:08 liZe

I'll see if I can get a little example together.

But if we're putting the inputs into a forms dictionary, we lose the source order when process the dictionary by its' keys.

alenards avatar Aug 09 '23 18:08 alenards

I’m not sure that it’s a problem:

  1. Why should we care about the order?
  2. Dictionaries keep order in Python.

I'll see if I can get a little example together.

That would help!

liZe avatar Aug 09 '23 18:08 liZe

I forgot that Python will get your the order that keys were "put" into the dictionary!

I expected that when we did a for key in forms: # blah, we'd get the inputs in whatever order the hash function for the dictionary had encoded them.

😮‍💨 🤦 Sorry for the confusion.

alenards avatar Aug 09 '23 19:08 alenards

👋 excited to see the conversation here and possible solution!

It looks like this thread may have gone a bit stale - @alenards I'm curious if you're still looking into this, otherwise I may take a look as it'd be really nice to have for a project I'm working on.

okkays avatar Apr 19 '24 17:04 okkays

Hi @okkays / Kevin,

I haven't been able to spend enough time here. I agree that it is a nice project, and I know that it would be highly valuable. I had my super draft work in branches on the fork I made: https://github.com/alenards/WeasyPrint/branches

I haven't touched it for 9 months, but I was using the feedback from here to "gathering together" the form inputs, and then trying to get all the radio button inputs in their group:

https://github.com/alenards/WeasyPrint/commits/issue-1831-forms-gathering/

I thought I'd get them "tracked", but I didn't know enough about the encode in the rendering (and trying to wrap my head around the spec, how "children" - aka kids - needed to be written out).

I'm on a US timezone, seems from your profile you are too. I've been up to "pair & ponder" on this. I just know I can't try to tackle it as a primary contributor right now 😢

alenards avatar Apr 19 '24 17:04 alenards

Thanks for the quick response and sharing your work so far! I'll take a look through what you have and spend a bit of time in the code to try and size this up 😄

okkays avatar Apr 19 '24 18:04 okkays

What I have committed is very much "sketches"; I don't think it would make it through any level of code review. And, it might help. I think the instructions for getting test suites running locally are up-to-date now 🤞 (or hope they are).

alenards avatar Apr 19 '24 20:04 alenards

#2143 is up for this following the outline from https://github.com/Kozea/WeasyPrint/issues/1831#issuecomment-1659757718 😄

okkays avatar May 01 '24 20:05 okkays

WHOA!

alenards avatar May 01 '24 20:05 alenards