prawnpdf / prawn

Fast, Nimble PDF Writer for Ruby
https://prawnpdf.org
Other
4.66k stars 688 forks source link

Merge links on text with adjacent boxes #1157

Closed mrotteveel closed 2 years ago

mrotteveel commented 4 years ago

I'm a user of asciidoctor-pdf, which uses Prawn to generate its PDF. I have no knowledge of Prawn itself, so I hope I express myself correctly. Yesterday I reported https://github.com/asciidoctor/asciidoctor-pdf/issues/1688 to asciidoctor-pdf. I was asked to report the problem here.

The problem is that creating a link on text with multiple styles creates a link text on the individually styled blocks. This has the effect that instead of a single link, you actually have multiple links. In Adobe Acrobat, this has the effect that clicking on a link will only highlight part of the link, while in the PDF viewer of Firefox, hovering over the link will only highlight part of the link (see example at end).

Would it be possible for adjacent links to the same target to be merged into a single link?

As an example (in Firefox): emphasis-2-before emphasis-2-on emphasis-2-after

pointlessone commented 4 years ago

This wouldn't be easy to achieve. Links in PDF are represented by rectangles. To achieve what you suggest you'd need to make sure that style change doesn't change the line height which is not true in general case.

Consider the following example:

image

I highlighted different styles. As you can see, style change makes it hard to calculate a continuous rectangle because there's none. The easiest solution would be a bounding box but that is not trivial to calculate with the streaming approach Prawn took to document generation. Streaming means we don't know what will be the next style so we don't know if we need to expand current link rectangle.

This is not a solution and I'm afraid it's unlikely it will be implemented. We're open for contributions, as always.

Hope this sheds some light on the reasons behind links broken up into multilple segments.

gettalong commented 4 years ago

If someone wants to take a stab at this:

So to make this work one has to check whether two adjacent fragments haven links (fragment.link) and whether they have the same link. Then make sure that the first fragment doesn't draw the link overlay (e.g. by removing the link from the fragment) but remember its bounding box. Once the first fragment that has no link or a different one is found, draw the link overlay with the combined bounding box. The problem with this approach is, however, that the functionality for drawing links is residing in multiple classes...

mojavelinux commented 4 years ago

Excellent analysis.

I checked to see what the browser would do when generating the PDF (in this case Chrome) for the case Alexander cited. The result is...rather peculiar.

link-annotation-box

It seems to split the difference. I have no doubt it would be incredibly difficult to mimic the browser, but it could be a good reference for anyone attempting to tackle this challenge.

mrotteveel commented 4 years ago

@pointlessone @gettalong Thanks for your explanation.

petergoldstein commented 2 years ago

@pointlessone I think this can be either closed or promoted to a discussion. As you note, this is unlikely to ever be implemented