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

Including more than a single raw svg doesn't work #19

Closed
marekyggdrasil opened this issue Jun 17, 2020 · 2 comments
Closed

Including more than a single raw svg doesn't work #19

marekyggdrasil opened this issue Jun 17, 2020 · 2 comments

Comments

@marekyggdrasil
Copy link
Contributor

marekyggdrasil commented Jun 17, 2020

Hi all,

I discovered a following problem which can be reproduced as follows.

import drawSvg as draw
d = draw.Drawing(100, 100, origin='center')
# load external SVGs
raw_latex_1 = ''
raw_latex_2 = ''
with open('latex_1.svg', 'r') as file:
    raw_svg = file.read()
    raw_latex_1 = raw_svg.replace('<?xml version=\'1.0\'?>', '')
with open('latex_2.svg', 'r') as file:
    raw_svg = file.read()
    raw_latex_2 = raw_svg.replace('<?xml version=\'1.0\'?>', '')
# display one on top of another
raw_rendered_svg_1 = draw.Raw(raw_latex_1)
raw_rendered_svg_2 = draw.Raw(raw_latex_2)
d.append(raw_rendered_svg_1)
d.append(raw_rendered_svg_2)
# create a file that can be included in this issue
d.setPixelScale(4)
d.savePng('case1.png')

it is rather hard to say but output seems ok

case1

now let us translate second SVG so that they are not on top of each other

import drawSvg as draw
d = draw.Drawing(100, 100, origin='center')
# load external SVGs
raw_latex_1 = ''
raw_latex_2 = ''
with open('latex_1.svg', 'r') as file:
    raw_svg = file.read()
    raw_latex_1 = raw_svg.replace('<?xml version=\'1.0\'?>', '')
with open('latex_2.svg', 'r') as file:
    raw_svg = file.read()
    raw_latex_2 = raw_svg.replace('<?xml version=\'1.0\'?>', '')
# display one on top of another
raw_rendered_svg_1 = draw.Raw(raw_latex_1)
raw_rendered_svg_2 = draw.Raw(raw_latex_2, transform="translate(10,20)")
d.append(raw_rendered_svg_1)
d.append(raw_rendered_svg_2)
# create a file that can be included in this issue
d.setPixelScale(4)
d.savePng('case2.png')

the second SVG gets messed up!

case2

let's see what happens when we still perform the translation but lets do not include first SVG

import drawSvg as draw
d = draw.Drawing(100, 100, origin='center')
# load external SVGs
raw_latex_1 = ''
raw_latex_2 = ''
with open('latex_1.svg', 'r') as file:
    raw_svg = file.read()
    raw_latex_1 = raw_svg.replace('<?xml version=\'1.0\'?>', '')
with open('latex_2.svg', 'r') as file:
    raw_svg = file.read()
    raw_latex_2 = raw_svg.replace('<?xml version=\'1.0\'?>', '')
# display one on top of another
raw_rendered_svg_1 = draw.Raw(raw_latex_1)
raw_rendered_svg_2 = draw.Raw(raw_latex_2, transform="translate(10,20)")
# d.append(raw_rendered_svg_1)
d.append(raw_rendered_svg_2)
# create a file that can be included in this issue
d.setPixelScale(4)
d.savePng('case3.png')

now the second SVG is perfectly fine even after performing the translation

case3

I noticed the larger the translation the more messed up figure gets but it only occurs if multiple raw SVGs are added and the first one appended to the Drawing is always perfectly fine.

Here are the included SVGs (I purposely changed the extension from to .txt because otherwise GitHub won't let me include them, .svg is not a supported attachment extension).

latex_1.txt
latex_2.txt

Those svg files are generated using https://github.com/tuxu/latex2svg

@cduck
Copy link
Owner

cduck commented Jun 17, 2020

Thanks for the detailed report. This is a slightly incorrect use of drawSvg.Raw, not an issue with drawSvg.

After looking closely, it seems your issue also occurs in your first example (use draw.Raw(raw_latex_1, opacity=0.1) to see it). The issue is having multiple embedded SVGs in your drawing, not using the translation attribute.

It is not straightforward to embed one SVG in another. You need to remove the <svg> tags and separate the elements between <defs> from the other elements. Another issue with embedding multiple SVGs is conflicting element IDs. If elements from different SVGs have the same ID, one of the elements may be used in place of the other. This code (https://github.com/cduck/latextools/blob/master/latextools/convert.py#L188) shows how to separate the defs and ensures the IDs are unique but you would need to parse the XML instead of using regexs to generalize this for an SVG not generated from LaTeX.

Can I point you to latextools? It has different dependencies than latex2svg but I've integrated it with drawSvg (using drawSvg's toDrawables interface). See this latextools example.

@cduck cduck closed this as completed Jun 17, 2020
@marekyggdrasil
Copy link
Contributor Author

Thanks a lot @cduck for the explanation and for providing the solution, I'm really glad to have it worked out but it is also good to know why it was messing up.

Just for the sake of future readers of this issue, here is the working source-code based on latextools library.

import latextools
import drawSvg as draw  # pip3 install drawSvg

# Render latex
latex_eq_1 = latextools.render_snippet(
    r'$\sqrt{X}$',
    commands=[latextools.cmd.all_math])
svg_eq_1 = latex_eq_1.as_svg()

latex_eq_2 = latextools.render_snippet(
    r'$\sqrt{X^\dag}$',
    commands=[latextools.cmd.all_math])
svg_eq_2 = latex_eq_2.as_svg()

# Use the rendered latex in a vector drawing
d = draw.Drawing(100, 100, origin='center', displayInline=False)
d.draw(svg_eq_1, x=-10, y=10, center=True, scale=2.5)
d.draw(svg_eq_2, x=10, y=-30, center=True, scale=2.5)

d.setPixelScale(4)

d.saveSvg('latextest.svg')
d.savePng('latextest.png')

Output

latextest

@cduck cduck changed the title including more than single raw svg breaks if translation is present Including more than a single raw svg doesn't work Jun 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants