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

Latexbranch #464

Open
wants to merge 38 commits into
base: main
Choose a base branch
from

Conversation

ArbitRandomUser
Copy link
Contributor

@ArbitRandomUser ArbitRandomUser commented Feb 8, 2022

PR Checklist

primarily this PR adds support for using dvisvgm which is distributed with TeXLive to render latex . This is an alternative to the existing mathjax solution. Mathjax still exists as the default setting for now.

All tests dont pass because the images are not exact 1-1 pixel replicas .. but they are close enough
edit1: Former are from dvisvgm and latter are from mathjax tex2svg

Linux: To get this working you will need latex (symlinked to pdftex binary) and dvisvgm in your path, pdftex, the latex symlink, and dvisvgm are made available by installing TeXLive (most distributions package TeXLive in their repos)

To try out an example program
https://gist.github.com/ArbitRandomUser/da8d439544945466c1df566df561d5f4

Windows & MacOS: somebody's gotta test this for me , i dont have access to either OS's at the moment.

act_dancing_circles_16_rot_trans
ref_dancing_circles_16_rot_trans

act_ologn
ref_ologn

(by default \begin{equation} adds numbering in latex)
act_matrix_transpose1
ref_matrix_transpose1

act_latex_8
ref_latex_8

If you are contributing to Javis.jl, please make sure you are able to check off each item on this list:

  • [✔️] Did I update CHANGELOG.md with whatever changes/features I added with this PR?
  • [ ✔️] Did I make sure to only change the part of the file where I introduced a new change/feature?
  • [ ✔️] Did I cover all corner cases to be close to 100% test coverage (if applicable)?
  • [ ✔️] Did I properly add Javis dependencies to the Project.toml + set an upper bound of the dependency (if applicable)?
  • Did I properly add test dependencies to the test directory (if applicable)?
  • Did I check relevant tutorials that may be affected by changes in this PR?
  • Did I clearly articulate why this PR was made the way it was and how it was made?

Link to relevant issue(s)
Closes #

How did you address these issues with this PR? What methods did you use?

@codecov-commenter
Copy link

codecov-commenter commented Feb 8, 2022

Codecov Report

Merging #464 (cbfcdd8) into master (0f24fcd) will decrease coverage by 2.96%.
The diff coverage is 29.54%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #464      +/-   ##
==========================================
- Coverage   96.47%   93.51%   -2.97%     
==========================================
  Files          35       35              
  Lines        1617     1680      +63     
==========================================
+ Hits         1560     1571      +11     
- Misses         57      109      +52     
Impacted Files Coverage Δ
src/latex.jl 60.49% <3.12%> (-22.27%) ⬇️
src/svg2luxor.jl 80.34% <40.38%> (-16.56%) ⬇️
src/Shape.jl 97.07% <100.00%> (+0.01%) ⬆️
src/Javis.jl 96.80% <0.00%> (-0.08%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0f24fcd...cbfcdd8. Read the comment docs.

Copy link
Member

@Wikunia Wikunia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for opening the PR. Looks really interesting. Regarding the font sizes. Do you know why yours are bigger than before?
I just had a look through the code so not a full review yet but maybe something of help. Will try a full review today or tomorrow.
I think you don't have a description of how to run it with the new way yet, right? Do you mind to write down a step by step instruction in the PR for people to just try it out including how to install it. We can later put that in the docs then.

src/latex.jl Outdated
end
LaTeXSVG[text] = svg
end
return svg
end

function tex2svg(text::LaTeXString; output_dir = "./.TeXfolder")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this output dir works for windows systems. I think there is a Julia function to create a temporary folder.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes mktemp and mktempdir , will be a neater way to do this ;
will change that .

src/latex.jl Outdated
generates svg from TeX;
default folder placed is ./.TeXfolder,
pdf's and aux files are deleted , tex and log files and other files remain
add LaTeX packages in `packages=[]`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the comment. Is there a reason why they don't get deleted?
Also what do you mean with packages =[] here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's no reason to keep the pdf's around after we're done converting to svg;
i just kept it around incase people want to inspect the log and tex files if they do run into errors

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

packages=[] was an earlier way i was passing the packages to be added in the usepackage line of the .tex file ; ive changed it in a later commit to a module level variable Javis.LaTeXusepackages which is a vector holding all the package names.
will remove the add Latex package in ... line

end
LaTeXSVG[text] = svg
end
return svg
end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure to have doctrings here and not inside the function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah ! Pythonic habits die hard ; will fix that !

src/svg2luxor.jl Outdated
defs = Dict{String,Any}()
for def in collect(child_elements(def_element))
defs[attribute(def, "id")] = def
try
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For each try catch I would like to know why it can fail and maybe there is an option to avoid the try catch then.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This try statement checks if we have any def tags , if they exist we add the defs to defs dictionary
if there are no def tags ( like in the case of dvisvgm which draws directly and doesnt predefine
paths to use) get_elements_by_tagname(xroot, "defs") will return an empty iterable and cause a bounds error .

Copy link
Contributor Author

@ArbitRandomUser ArbitRandomUser Feb 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah! i probably shouldn't have discarded all errors , should throw(e) if its not a BoundsError;
but a try free way would be better , the right way would be to check the lengths and proceed

all_def_tags = get_elements_by_tagname(xroot,"defs")
if length(all_def_tags) !=0
  defelements = all_def_tags[1]
  ...
  ...
end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes some kind of !isempty would be nicer than a try.

@ArbitRandomUser
Copy link
Contributor Author

ArbitRandomUser commented Feb 9, 2022

yes , i haven't documented how to use dvisvgm over the default , I'll add that.
(the only hint to use dvisvgm ive added is in the warning when it doesnt find tex2svg)

As for the font sizes , beats me !
ive edited the PR , the first images are from dvisvgm and the second images are from mathjax
mathjax images are slightly larger and also have a little more empty space around them than the ones dvisvgm makes;

as for the scaling factor i think iv'e got it right . At the risk of sounding like a bad worker who blames their tools
im gonna say that its a difference of how latex and mathjax differ in rendering the fonts ;
I dont know much about the intricacies of font rendering but , some things to be noted ..
when we specify a certain font height say 50 in Javis ; Neither latex nor mathjax svg's generate glyphs
which will span exactly between two lines that are 50 units apart

from latex-dvisvgm...
dvisvgm
from mathjax
tex2svg

@ArbitRandomUser
Copy link
Contributor Author

ArbitRandomUser commented Feb 9, 2022

digging a little more deeper into the fonts it seems to me the latex-dvisvgm way is alright
mathjax imo seems to be enlarging the fonts ; maybe someone with more knowledge of fonts rendering
can comment on this .
The earlier comment about font exactly occupying 50 units of height when fontsize is 50 is expected behaviour
So for example the O in Olog(n) will not have to be 50 points high when the fontsize is 50.

However the O has a relative size as defined by the font, one can get this info out of a program called fontforge
in OTF fonts the em size or the size of the "block" is 1000 units in fontforge ;
now lets look at how many units the O glyph spans top to bottom ...
fig
725 units (shown in green ).
So after drawing all of this with an fontsize of 50 in luxor , we should expect the O's height to be 0.725*50 = 36.25
Here i have added two dimensionings at apropriate locations from a point on y=0 to y=36.25 for one
and y=0 to y=50 for another

dvisvgm

We see the O is pretty close to 36.25 units, the dimensioning is a bit offset and it might be exactly 36.25 if shift the dimensioning down a little to exactly where the top of O starts , anyway its pretty close to 36.25 , whereas the mathjax font will definitely be way over 36.25 units. This is my reason to conclude that something is the matter with mathjax fonts and not latex and dvisvgm .

ill try to get in the changes from the other comments done by tomorrow or day-after , maybe it can be reviewed over the weekend ? or perhaps next week if you're not free this weekend

@ArbitRandomUser
Copy link
Contributor Author

ArbitRandomUser commented Feb 11, 2022

its not really mathjax's fault , it Javis scaling mathjax fonts the wrong way ,
look at the x glyph from mathjax font , its height is 425
fig
which means the scaling in line 273 at svg2luxor.h should be
scale((fsize * 425/1000) / (height / ex_height))
instead of
scale((fsize / 2) / (height / ex_height))

thats what ex means , atleast from my understanding from here
https://oreillymedia.github.io/Using_SVG/guide/units.html

@Wikunia
Copy link
Member

Wikunia commented Feb 11, 2022

Thanks for checking that out ☺️

Copy link
Member

@Wikunia Wikunia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know when you have an example for me to try it out. 😉
I've added some small comments for things I noticed

src/svg2luxor.jl Outdated
@@ -91,6 +102,7 @@ function draw_obj(::Val{:path}, o, defs)
for pi in 1:length(data_parts)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

avoid using pi

src/svg2luxor.jl Outdated
elseif command == 'Z'
closepath()
else
@warn "Couldn't parse the svg command: $command"
end
end

if stroke_width != nothing
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comparing with nothing should use triple equal sign or in this case !==.

src/svg2luxor.jl Outdated
defs = Dict{String,Any}()
for def in collect(child_elements(def_element))
defs[attribute(def, "id")] = def
try
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes some kind of !isempty would be nicer than a try.

@Wikunia
Copy link
Member

Wikunia commented Feb 12, 2022

Regarding the font size I'm super happy you figured it out way more than I did 😉

@ArbitRandomUser
Copy link
Contributor Author

@Wikunia , added an example gist in the PR :)

@Wikunia
Copy link
Member

Wikunia commented Feb 14, 2022

With the gist you mentioned I'm getting the following warning:

┌ Warning: there maybe errors in processing latex, check /tmp/jl_EZ9e2T/jl_gTEmBu.log for details
└ @ Javis ~/Julia/Javis/src/latex.jl:209

with this file: https://gist.github.com/Wikunia/75b74eb6806a9fac10b52fc676c0198c not sure whether this is expected.

@ArbitRandomUser
Copy link
Contributor Author

ArbitRandomUser commented Feb 15, 2022

Thats a small bug ; line 208 in latex.jl (in latexbranch) should be if !stat;
I'm leaving cleanup for the temp dirs and folders as false in a new commit.
else the warning to look at the log makes no sense, since the log gets deleted
after julia exits .

Also the tests fail now because ive changed scaling to 425/1000; lemme know if i
should set it back to 1/2.

@Wikunia Wikunia changed the base branch from master to main February 25, 2022 18:35
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

Successfully merging this pull request may close these issues.

None yet

3 participants