mgieseki / dvisvgm

A fast DVI, EPS, and PDF to SVG converter
https://dvisvgm.de
GNU General Public License v3.0
295 stars 28 forks source link

PS/PDF clipping with overflow='hidden' renders incorrectly in Chromium/Chrome-based browsers #178

Closed agrahn closed 2 years ago

agrahn commented 2 years ago

The new method of clipping embedded PS and PDF files (commit c6f7709) does not render correctly in Chromium-based browsers. The reason is that they ignore the transform attribute in <svg> elements. In fact, transform is not a valid attribute of the <svg> element, according to https://www.w3.org/TR/SVG11/struct.html#SVGElement.

On the other hand, Firefox takes it into account: transform is listed as a Presentation Attribute in https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg.

Test file:

\special{papersize=210mm,297mm}

x\hbox to 52bp{%
  \vrule width 0pt height 52bp%
  \special{pdffile="example.pdf" llx=10 lly=10 urx=62 ury=62 clip}\hss}x

\bye

example.pdf

mgieseki commented 2 years ago

Shoot, I should have performed some more tests with different browsers. :-) Fortunately, it's easy to fix.

mgieseki commented 2 years ago

I hope you don't mind that I've applied my patch mentioned in #179 and don't merge your PR.

mgieseki commented 2 years ago

Sorry, I guess I need some sleep. The patch doesn't fix the issue. I'll repair it shortly.

mgieseki commented 2 years ago

@agrahn I played around with the two clipping variants overflow='hidden' and clipPath a bit more. In Firefox, your animation listed in #176 performs much faster with the clipPath method while it significantly slows down when using overflow='hidden'. Do you get different results?

agrahn commented 2 years ago

I double-checked. The clipPath version is much slower than the one with overflow="hidden" in Firefox-97. The former only reaches 7 FPS, while the latter meets the target frame rate of 30 FPS on my Dell inspiron laptop with Gentoo Linux. In Chromium, there is no difference.

The frame rate is printed to the JavaScript console (press Ctrl+Shift+i). I attach both versions. rainbowAnim-overflow.svg.zip rainbowAnim-clipPath.svg.zip

(For producing the overflow version, I used your commit 0e8d99fedc80d06eb86c030a539f1be5ef350112.)

Thank you for taking the time!

mgieseki commented 2 years ago

Thanks for the additional info. Unfortunately, commit https://github.com/mgieseki/dvisvgm/commit/0e8d99fedc80d06eb86c030a539f1be5ef350112 is buggy because it creates an empty svg element and puts everything into the group. Thus, no clipping is performed and results in fast animations. The latest commit https://github.com/mgieseki/dvisvgm/commit/7089529cc2143088d727065874887efc544f0926 fixes the issue but also slows down the animation -- at least on my Windows 10 laptop. I'll try it again on Fedora Linux tomorrow.

agrahn commented 2 years ago

You are right, the clipPath method indeed performs much better!

But only after I added option --optimize. Without this option, clip-path='url(#clip...)' attribute is added to every <path ...> object of the processed PS/PDF file, which is probably the reason for the slowing down. So maybe, after all, it would be better to revert to the pre-#176 version of dvisvgm. But could this optimising away of redundant clip-path attributes perhaps be generally applied?

agrahn commented 2 years ago

I tried an update of my PR ;-). Clipping is now achieved by placing the graphics content in a group with a clip-path. I was not sure how to get a unique clipPath ID. So I defined a global int (imgClipID), which may look a bit hacky, but it works :-).

rainbowAnim.svg.zip

mgieseki commented 2 years ago

I haven't tried your changes yet but it seems they restore the previous behavior without additional functionality. Is there a reason why you prefer creating the clip path stuff yourself? I'd just delegate everything to the PS interpreter which then triggers the creation of the clipPath elements. :-) But maybe I missed anything.

This is how the code section looked before adding the svg overflow="hidden" elements:

https://github.com/mgieseki/dvisvgm/blob/71f9228b0559ebb4b5147ef4bd5ddf00728f0b94/src/PsSpecialHandler.cpp#L425-L445

agrahn commented 2 years ago

Passing rectclip to the PS interpreter adds identical clip-path="url(...) " references to each and every path object in the imported PostScript file (322 occurrences in total). This is the (original) reason for slowing down of the animation. Here is an example with a single imported page from rainbow2.pdf (latex+dvisvgm.2.11.1 --zoom=-1 --font-format=woff2 --bbox=papersize):


\special{papersize=210mm,297mm}

\hbox to 283bp{%
  \vrule width 0pt height 283bp%
  \special{pdffile="rainbow2.pdf" page=1 llx=0 lly=0 urx=283 ury=283 clip}\hss}

\bye

rainbowSinglePage.svg.zip

mgieseki commented 2 years ago

Ouch, yes, I hadn't noticed that in all detail. In this case, your implementation works fine. In order to add the clip-path attributes only to the wrapper group and take further command-line parameters, like --relative into account, some additional things are required. Also, the counter should be reset for every DVI page, and empty groups created from strange EPS/PDF files should be ignored as well as their clipPath element. I modified and extended your idea a bit and pushed it to branch tmp. Hopefully, this time it works as expected. Feel free to have a look.

agrahn commented 2 years ago

Cool! Looks good, with groups properly placed.

mgieseki commented 2 years ago

Great, thanks for the feedback! In order to tidy up the SVG a bit more, I'm about to add an optimizer module that optionally removes the duplicate clipPath elements that differ only in their IDs.

mgieseki commented 2 years ago

I've published another release that hopefully fixes the clip path issues.