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

Text Rendering Issues - Support resvg and/or Inkscape as alternative renderers #102

Open
joachimheintz opened this issue Aug 1, 2023 · 2 comments

Comments

@joachimheintz
Copy link
Contributor

there are some important features of svg text rendering which do not work in the internal jupyter notebook view, but do work when i export an svg file and then render the file with inkscape.

below are examples for some of these important differences. my question is: can text rendering in drawsvg be improved? or can the inkscape svg renderer be added as alternative? (cairosvg which is used by drawsvg states about itself: "Text and features related to fonts are poorly supported" --- which is true unfortunately.)

auto-wrapped text with 'inline-size' property (see W3C)

this is the code:

d = dw.Drawing(300,100,id_prefix='autowrapped')
# simple example for text wrapping
t = 'This text wraps at 200 pixels.'
x,y = 50,30
d.append(dw.Text(t,20,x,y,style='font-style: sans-serif; inline-size: 200px;'))
d.append(dw.Line(x,0,x,100,stroke='gray'))
d.append(dw.Line(x+200,0,x+200,100,stroke='gray'))
# export as svg
d.save_svg('auto-wrapped.svg')
# when exported as png result is wrong
d.save_png('auto-wrapped.png')
# but when the svg is rendered with inkscape it is correct
from os import system
system('inkscape -o auto-wrapped-inkscape.png auto-wrapped.svg')
d

this is the file which is rendered by drawsvg as png (with the same output as in the jupyter notebook):
auto-wrapped
this is the file which is rendered by inkscape:
auto-wrapped-inkscape

the 'shape-inside' property (see W3C)

d = dw.Drawing(300,300,id_prefix='shapeinside')
t = 'Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat.'
x,y = 50,30
d.append(dw.Raw('<defs><circle id="wrap" cx="150" cy="150" r="120"/></defs>'))
d.append(dw.Text(t,20,0,0,style="""font-style: sans-serif;
                text-align: center;
                shape-inside: url(#wrap);"""))
d.append(dw.Circle(150,150,120,stroke='gray',fill='none'))
d.save_svg('shape-inside.svg')
d.save_png('shape-inside.png')
from os import system
system('inkscape -o shape-inside-inkscape.png shape-inside.svg')
d

view in the notebook and in the exported png:
shape-inside
rendered by inkscape:
shape-inside-inkscape

white space

white space can be preserved with the white__space='pre' property (see W3C for all options).

d = dw.Drawing(300,100,id_prefix='whitespace')
d.append(dw.Text('white   space   not   preserved',14,30,30))
d.append(dw.Text('white   space   preserved',14,30,60,white_space='pre'))
d.save_svg('white-space.svg')
d.save_png('white-space.png')
from os import system
system('inkscape -o white-space-inkscape.png white-space.svg')
d

rendered in drawsvg:
white-space
rendered with command-line inkscape:
white-space-inkscape

result / question

cairosvg which is used by drawsvg is really missing important features of svg text.
is it possible to allow other rendering options?
for my case, inkscape is good because it can also render to pdf.
for other cases, resvg may also be an option.

my configuration: debian 11, Inkscape 1.2.2 (b0a8486541, 2022-12-01)

@cduck
Copy link
Owner

cduck commented Aug 4, 2023

Thanks so much for all these examples. I've actually never used these attributes before but they appear to be part of the SVG 2 specification that CairoSVG doesn't really support. Yes, I would definitely support the addition of alternate rendering backends, especially given the limitations of CairoSVG.

I think it would be useful to add an option to Drawing.rasterize and Drawing.save_png and possibly also have a global default backend similar to matplotlib. Here's some code I've previously written to call out to inkscape:


resvg looks like a great project. I'll need to try it out sometime. Have you had good results with it? If it works well, I might try packaging it into a Python wheel for easy use with drawsvg.

@cduck
Copy link
Owner

cduck commented Jan 11, 2024

Here are two relevant methods where new backends would be added: Raster.from_svg() and Raster.from_svg_to_file()

@cduck cduck changed the title text rendering issues - inkscape as optional renderer? Text Rendering Issues - Support resvg and/or Inkscape as alternative renderers Jan 11, 2024
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