Closed kiryph closed 1 year ago
Sorry, I can't help with Asymptote issues here. Please upload the corresponding DVI file demo-unitcircle_.dvi
.
How should I upload the dvi file? Is following fine:
÷À;����è TeX output 2023.04.27:1504���������������������������������������ÿÿÿÿïheader=l3backend-dvips.proh®´lR-®÷lR8ôï>dvisvgm:bbox f 57.659449bp 64.563436bp 60.159449bp 67.063436bpï®dvisvgm:raw{?nl}<g transform='matrix(0.996264 0 0 0.996264 57.6594 64.5634)'>{?nl}<path d='M 0 2.50937L 2.50937 2.50937L 2.50937 0L 0 0L 0 2.50937Z' fill='#ffffff'/>{?nl}</g>ò��Çdvisvgm:raw{?nl}<g transform='matrix(0.996264 0 0 0.996264 57.6594 64.5634)'>{?nl}<path d='M 2.25844 1.25469C 2.25844 0.700332 1.80904 0.250938 1.25469 0.250937C 0.700332 0.250937 0.250937 0.700332 0.250937 1.25469C 0.250937 1.80904 0.700332 2.25844 1.25469 2.25844C 1.80904 2.25844 2.25844 1.80904 2.25844 1.25469Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='0.501875'/>{?nl}</g>��ø���*À;����è�h®�;®��ù��Vßßßßßßß
ZIP file demo-unitcircle_.dvi.zip
Thanks for uploading the file. Unfortunately, I can't reproduce the error. The file converts correctly on my machines (Linux and Windows). Maybe someone needs to take a closer look at this on a Mac (which I don't have access to).
Currently, I am little bit lost:
based on recent issues on macOS
draw(box((0,0), (2,1)));
A diff between both intermediate tex files containing special commands:
\special{dvisvgm:raw{?nl}%
-<g transform='matrix(0.996264 0 0 0.996264 56.6594 65.5634)'>{?nl}%
-<path d='M 0 1.50562L 2.50937 1.50562L 2.50937 0L 0 0L 0 1.50562Z' fill='#ffffff'/>{?nl}%
+<g transform='matrix(0.996264 0 0 0.996264 57.6594 64.5634)'>{?nl}%
+<path d='M 0 2.50937L 2.50937 2.50937L 2.50937 0L 0 0L 0 2.50937Z' fill='#ffffff'/>{?nl}%
</g>}\catcode`\#=6%
\catcode`\#=11%
\special{dvisvgm:raw{?nl}%
-<g transform='matrix(0.996264 0 0 0.996264 56.6594 65.5634)'>{?nl}%
-<path d='M 0.250937 1.25469L 2.25844 1.25469L 2.25844 0.250937L 0.250937 0.250937L 0.250937 1.25469Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='0.501875'/>{?nl}%
+<g transform='matrix(0.996264 0 0 0.996264 57.6594 64.5634)'>{?nl}%
+<path d='M 2.25844 1.25469C 2.25844 0.700332, 1.80904 0.250938, 1.25469 0.250937C 0.700332 0.250937, 0.250937 0.700332, 0.250937 1.25469C 0.250937 1.80904, 0.700332 2.25844, 1.25469 2.25844C 1.80904 2.25844, 2.25844 1.80904, 2.25844 1.25469Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='0.501875'/>{?nl}%
shows that the most outstanding difference is the cubic Bézier curve.
The error XML error: error in path data: number expected (premature end of data)
comes from GraphicsPathParser.hpp
.
https://github.com/vectorgraphics/asymptote/issues/375
As you say, it seems to be that the generated dvi file is fine. So it might not be an issue on the side of asymptote but a platform-specific one.
Do you have an idea in which direction I could look? Is there anything platform-dependent regarding the GraphsPathParser.hpp
?
My current assumption is that I have to compile dvisvgm myself with debug symbols to see what is going on in GraphsPathParser
which I would really like to avoid.
I guess it's this issue. The behavior of operator >>
differs between libstdc++
and libc++
if applied to floating point numbers. libc++
seems to be the default on Mac.
While ligstdc++
just stops parsing a number as soon as an unexpected character occurs, libc++
immediately raises an error. So, when parsing the path commands M 0 2.50937L 2.50937 2.50937
on a Mac, it fails at the L
because it's not a valid digit of the y-coordinate. libstdc++
just stops and returns the proper value 2.50937.
I think I need to find some workaround for this. At the moment, there's probably nothing you can do about it.
Thanks for pointing out this difference between the two implementations of the STL regarding the operator >>
. This sounds like the reason, even though the rectangle example works.
What baffles me in particular is that this issue is 10 years old (https://github.com/llvm/llvm-project/issues/18156).
Writing correct parsers is IMHO always challenging, and something like SVG might be one of the even more complicated ones (xml+properties like paths). However, finding a license-compatible lightweight ready to use, actively maintained third-party library is also not a simple story.
Anyhow, I hope you find a workaround in the parser of dvisvgm and can fix it in one of the next releases of dvisvgm.
I did a little bit of further digging:
I took the test example from https://github.com/llvm/llvm-project/issues/18156 and added a few lines related to SVG path parsing:
The results are
❯ clang++ -o parse_double-libc++ demo-double-stream.cpp
❯ ./parse_double-libc++
local is C
'-4.9' converted to -4.9
'-4.9 X' converted to -4.9
'-4.9_' converted to -4.9
SVG Path parsing:
'2.50937L' converted to 2.50937
'0L' converted to 0
'2.50937Z' converted to 2.50937
Issue between libc++ (llvm) and libstdc++ (gcc):
'-4.9d' failed to convert to double
'-4.9X' failed to convert to double
SVG Path parsing:
'1.25469C' failed to convert to double
❯ g++-12 -o parse_double-libstdc++ demo-double-stream.cpp
❯ ./parse_double-libstdc++
local is C
'-4.9' converted to -4.9
'-4.9 X' converted to -4.9
'-4.9_' converted to -4.9
SVG Path parsing:
'2.50937L' converted to 2.50937
'0L' converted to 0
'2.50937Z' converted to 2.50937
Issue between libc++ (llvm) and libstdc++ (gcc):
'-4.9d' converted to -4.9
'-4.9X' converted to -4.9
SVG Path parsing:
'1.25469C' converted to 1.25469
This confirms that libc++ throws an error for 1.25469C
where libstdc++ does not.
Since this issue for libc++ is quite old and shows no sign of an upstream change, IMHO dvisvgm should take this into account.
As a first step it should be specifically mentioned that libc++ (LLVM) cannot be used for dvisvgm and suggest to use libstdc++ (GCC). However, libstdc++ is not by default available on macOS and makes installation on macOS more complicated. There might also be other reasons why someone would like to use libc++.
M
, L
, C
, ... or insert spaces before M
,L
,C
(https://www.w3.org/TR/SVG2/paths.html) and 2) read numbersAll of them sound like a major change in the code (new dependencies or a rewrite of the path parser).
I will try to compile dvisvgm myself using libstdc++ on macOS for now.
I will try to compile dvisvgm myself using libstdc++ on macOS for now.
I hardly know anything about how to compile either dvisvgm or Asymptote on macOS (though I'm on macOS), but if it's a litter bit easier to compile Asymptote on macOS using default settings, for a workaround it seems you can patch Asymptote to always insert a space before M
, L
, C
, and Z
.
Relevant lines in Asymptote https://github.com/vectorgraphics/asymptote/blob/494e8120ee967aa9c71ae26e2476b5632211b6e2/texfile.h#L419-L436
Or, does Asymptote allow executing user scripts after it writes to a tex file and before it runs latex command?
I hardly know anything about how to compile either dvisvgm or Asymptote on macOS (though I'm on macOS), but if it's a litter bit easier to compile Asymptote on macOS using default settings, for a workaround it seems you can patch Asymptote to always insert a space before M, L, C, and Z.
That's actually a suggestion I consider now. I am already struggling compiling dvisvgm since the kpathsea dependency is not easy to fulfil:
Thanks.
Or, does Asymptote allow executing user scripts after it writes to a tex file and before it runs latex command?
Not that I am aware of. I could add a workaround with the --keep
option of asy. After the dvisvgm command fails, I could run a script to insert the spaces and run dvisvgm once again. Not a fan and the whole story becomes a little bit of a nightmare.
I have now patched Asymptote and compiled it myself:
--- a/texfile.h
+++ b/texfile.h
@@ -417,22 +417,22 @@ public:
}
void moveto(pair z) {
- *out << "M";
+ *out << " M";
writeshifted(z);
}
void lineto(pair z) {
- *out << "L";
+ *out << " L";
writeshifted(z);
}
void curveto(pair zp, pair zm, pair z1) {
- *out << "C";
+ *out << " C";
writeshifted(zp); writeshifted(zm); writeshifted(z1);
}
void closepath() {
- *out << "Z";
+ *out << " Z";
}
❯ asy --version
Asymptote version 2.86-8 [(C) 2004 Andy Hammerlindl, John C. Bowman, Tom Prince]
ENABLED OPTIONS:
V3D 3D vector graphics output
WebGL 3D HTML rendering
OpenGL 3D OpenGL rendering
SSBO GLSL shader storage buffer objects
GSL GNU Scientific Library (special functions)
FFTW3 Fast Fourier transforms
XDR External Data Representation (portable binary file format for V3D)
CURL URL support
LSP Language Server Protocol
Readline Interactive history and editing
GC Boehm garbage collector
threads Render OpenGL in separate thread
DISABLED OPTIONS:
Eigen Eigenvalue library
Sigsegv Distinguish stack overflows from segmentation faults
Now I get a webgl output for draw(unitcircle);
However, I leave this issue open, since dvisvgm should handle all valid svg input correctly. Either dvisvgm should not compile with libc++ or find a workaround to deal with the difference between libc++ and libstdc++.
I've fixed the issue locally and will commit the patch after some more testing.
I am using Asymptote which in turns uses dvisvgm.
I get for following asymptote file
the error
Running asymptote verbose with keep intermediate files
shows that the error is printed by dvisvgm (see last lines):
My Environment:
Ghostscript 10.00.0 with libgs from https://www.tug.org/mactex/morepackages.html (watchout to customize the installation to include libgs)