Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problems rendering arcs in SVGs #358

Closed
nova-03 opened this issue Mar 8, 2022 · 5 comments
Closed

Problems rendering arcs in SVGs #358

nova-03 opened this issue Mar 8, 2022 · 5 comments

Comments

@nova-03
Copy link

nova-03 commented Mar 8, 2022

Adding SVG with content:

<svg xmlns="http://www.w3.org/2000/svg" width="88.9" height="166.96" viewBox="0 0 88.9 166.96">
  <g>
    <path d="M9.74,20h8V35.09A23.85,23.85,0,0,1,24,31.58a20.49,20.49,0,0,1,7.33-1.3A20.46,20.46,0,0,1,39.75,32a22.79,22.79,0,0,1,6.84,4.62,21.67,21.67,0,0,1,4.62,23.64A21.62,21.62,0,0,1,39.75,71.75a20.77,20.77,0,0,1-8.4,1.68A21.14,21.14,0,0,1,24,72.17a21.66,21.66,0,0,1-6.26-3.55v4.81h-8Zm8,31.93a12.9,12.9,0,0,0,1.07,5.27A13.71,13.71,0,0,0,26,64.35a13.36,13.36,0,0,0,5.31,1.07,13,13,0,0,0,5.27-1.07,13.79,13.79,0,0,0,7.18-7.18,13.07,13.07,0,0,0,1.07-5.27,13.29,13.29,0,0,0-1.07-5.31,13.62,13.62,0,0,0-2.9-4.32,13.78,13.78,0,0,0-4.28-2.9,13,13,0,0,0-5.27-1.07A13.36,13.36,0,0,0,26,39.37a13.51,13.51,0,0,0-7.21,7.22A13.12,13.12,0,0,0,17.76,51.9Z" transform="translate(-9.74 -17.22)" fill="#1d71b8"/>
    <path d="M60.45,30.28h8V54.19a10.62,10.62,0,0,0,.88,4.31,11.39,11.39,0,0,0,2.37,3.55,10.89,10.89,0,0,0,7.83,3.29,10.65,10.65,0,0,0,4.31-.88,10.77,10.77,0,0,0,3.51-2.41,11.39,11.39,0,0,0,2.37-3.55,10.62,10.62,0,0,0,.88-4.31V30.28h8V54.19a18.69,18.69,0,0,1-1.49,7.44,19.15,19.15,0,0,1-4.09,6.08A19.7,19.7,0,0,1,87,71.83a18.88,18.88,0,0,1-14.89,0A19.7,19.7,0,0,1,66,67.71a19.15,19.15,0,0,1-4.09-6.08,18.69,18.69,0,0,1-1.49-7.44Zm7.18-8.48a4.62,4.62,0,0,1,7.87-3.24,4.7,4.7,0,0,1,0,6.49,4.61,4.61,0,0,1-7.87-3.25Zm19.86-4.58a4.38,4.38,0,0,1,3.28,1.34,4.7,4.7,0,0,1,0,6.49,4.38,4.38,0,0,1-3.28,1.34,4.56,4.56,0,0,1-4.58-4.59,4.56,4.56,0,0,1,4.58-4.58Z" transform="translate(-9.74 -17.22)" fill="#1d71b8"/>
    <path d="M9.74,121.93h8v4.82A21.69,21.69,0,0,1,24,123.19a21.89,21.89,0,0,1,15.73.42,21.93,21.93,0,0,1,6.84,4.63,21.69,21.69,0,0,1,4.62,6.83,21,21,0,0,1,1.68,8.4,21.53,21.53,0,0,1-6.3,15.28,22.79,22.79,0,0,1-6.84,4.62,21.35,21.35,0,0,1-15.73.42,23.85,23.85,0,0,1-6.26-3.51v23.9h-8Zm21.61,35.14A13,13,0,0,0,36.62,156a13.59,13.59,0,0,0,7.18-7.22,13.29,13.29,0,0,0,1.07-5.31,13.07,13.07,0,0,0-1.07-5.27A13.7,13.7,0,0,0,36.62,131,13,13,0,0,0,31.35,130,13.36,13.36,0,0,0,26,131a13.61,13.61,0,0,0-7.21,7.18,12.9,12.9,0,0,0-1.07,5.27,13.12,13.12,0,0,0,1.07,5.31A13.51,13.51,0,0,0,26,156,13.36,13.36,0,0,0,31.35,157.07Z" transform="translate(-9.74 -17.22)" fill="#1d71b8"/>
  </g>
</svg>

results in "broken" arcs.

I am using Python 3.9.2 with the latest version of the master fpdf2 branch (2.5.1)

@nova-03 nova-03 added the bug label Mar 8, 2022
@Lucas-C Lucas-C added the svg label Mar 10, 2022
@Lucas-C
Copy link
Member

Lucas-C commented Mar 10, 2022

I had a look at this bug this morning, but I couldn' figure it out so far...
It seems to be caused by some erroneous arc-overlap logic.

Ping @torque if ever you have some time to look at this 😊

@Lucas-C
Copy link
Member

Lucas-C commented Mar 10, 2022

While I haven't found the fix yet, I have isolated a minimal SVG file reproducing this bug:

<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100" style="border: solid 1px">

  <path d="M 15, 40 v -5 h -5 Z m 10, 15 A 20, 20, 0, 0, 0, 35, 35 Z" fill="blue"/>

  <!-- Display some points to help debugging: -->
  <circle r="1" cx="15" cy="40" fill="green"/>   <!-- starting point -->
  <circle r="1" cx="15" cy="35" fill="green"/>   <!-- position after the vertical shift -->
  <circle r="1" cx="10" cy="35" fill="green"/>   <!-- position after the horizontal shift -->
  <circle r="1" cx="20" cy="50" fill="yellow"/>  <!-- the expected arc start -->
  <circle r="1" cx="25" cy="55" fill="purple"/>  <!-- the actual arc start when rendered in a web browser -->
  <circle r="1" cx="35" cy="35" fill="green"/>   <!-- end path position -->

</svg>

How it is rendered by a web browser can be compared to how fpdf2 renders it, using the following Python code:

#!/usr/bin/env python3
import fpdf

pdf = fpdf.FPDF()
pdf.add_page()
pdf.image("issue_358.svg")
pdf.rect(x=10, y=10, w=100, h=100)
pdf.output("issue_358.pdf")

What really amazes me, and makes this bug quite mysterious, is that the numeric values after the h & v operators can be changed, without the arc starting point moving, when rendered in a web browser!

@gmischler
Copy link
Collaborator

gmischler commented Mar 10, 2022

What really amazes me, and makes this bug quite mysterious, is that the numeric values after the h & v operators can be changed, without the arc starting point moving, when rendered in a web browser!

Scalable Vector Graphics (SVG) 2, 9.3.4. the "closepath" command says this:

Z or z - Close the current subpath by connecting it back to the current subpath's initial point. (my emphasis)

It is not stated very explicitly, but that seems to imply that the current position should be moved along as well.
In your example, after the "Z" the current position should again be (15, 40).
Instead, fpdf draws the "Z" line, but apparently ignores the associated move, and leaves the current position at the start of the line at (15-5, 40-5).
So after the "m 10, 15", the incorrect yellow dot is shifted from the purple dot by exactly that (-5, -5) distance.

Edit:
Now I see that you seem to have already fixed it along those lines.

@Lucas-C
Copy link
Member

Lucas-C commented Mar 11, 2022

Yes, this quote from https://www.w3.org/TR/SVG/paths.html#TermInitialPoint enlightened me:

The "moveto" commands (M or m) must establish a new initial point and a new current point. The effect is as if the "pen" were lifted and moved to a new location. A path data segment (if there is one) must begin with a "moveto" command. Subsequent "moveto" commands (i.e., when the "moveto" is not the first command) represent the start of a new subpath

I opened #362 to fix this

@nova-03
Copy link
Author

nova-03 commented Mar 11, 2022

Many thanks @Lucas-C and @gmischler for fixing this bug!
I've tested the fix with several "problematic" SVGs and it all works now like a charm!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants