In contrast to page rendering, SVG conversion does not make sure whether any OCGs are valid at all. PyMuPDF Discussion item: https://github.com/pymupdf/PyMuPDF/discussions/3567 File link: https://github.com/user-attachments/files/15791552/dwe1_2.pdf How to reproduce: mutool draw -o test.svg dwe1_2.pdf Compare to: mutool draw -o test.png dwe1_2.pdf Note: The page refers to dozens of OCGs in its /Properties. But there exists no /OCProperties in the file - so all of the OCGs must be treated as non-existent, like it happens in rendering.
I have a fix in review: https://cgit.ghostscript.com/cgi-bin/cgit.cgi/user/robin/mupdf.git/commit/?h=so&id=8a01ae1ca85902adae87fde06e58af9de301a02e The issueis not the /OCProperties not existing, it's a bad interaction between layers and clips in the generated SVG file.
Tor isn't keen on my fix, because it can split layers into more groups that are strictly needed. We have therefore agreed to park my fix for a couple of weeks to see if he can find a formulation he likes better.
Created attachment 25767 [details] Minimized example.
Fixed with the following two commits: commit 65f283f2ac0445b15a106d565d999637aac9081a Author: Tor Andersson <tor.andersson@artifex.com> Date: Wed Jul 3 19:16:44 2024 +0200 Bug 707824: Emit properly nested clip and layer operations in PDF. If BMC/EMC and q/Q pairs (that apply clipping) don't nest properly, warn and close the EMC either immediately (if badly nested one way) or at the next Q (if badly nested the other way). Example 1: q BMC Q (close layer before this Q) EMC (ignore this EMC) Example 2: BMC q EMC (ignore this EMC) Q (close layer after this Q) Also change SVG output to emit Inkscape specific layer attributes. --- mc_depth tracks the level of BMC/EMC nesting in the content stream. nest_mark tracks the level of layer and clip calls that we've made to the fz_device. If the q/Q and BMC/EMC are badly nested, we ignore some EMCs and save them until we hit the next Q. The check in do_end_layer only ends the layer if the device and content stream are "in sync". If we're not in sync, we ignore the EMC. This can happen in two cases: either we saw a Q too early, or we saw an EMC too early. In the first case we have already popped the layer (so the EMC should be completely ignored). In the second case the layer started before the clip and we cannot end the layer just yet (so ignore the EMC until we see the Q and then pdf_grestore puts the world back into order). The loops around the pop_clip in pdf_grestore recover the syncing. The loop before closes any layers that need to be ended before the clip is popped (layer started with BMC inside the clip, but ends after the clip). The loop after closes any layers that had the EMC inside the clip but were started with BMC before the clip mask was pushed. commit 711e82dde434dfe8f36feca88c5c4b9d70ab87ce Author: Sebastian Rasmussen <sebras@gmail.com> Date: Wed Jul 17 01:08:27 2024 +0200 Check nesting depth before pushing clip mark. Without this the nesting depth might step outside the layer/clip stack.