Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
dca7034
added S and C commands to draw_obj for path in svg, def_element moved…
ArbitRandomUser Jan 30, 2022
fc69613
implemented tex2svg julia function , get_latex_svg uses tex2svg now
ArbitRandomUser Jan 30, 2022
8ed5823
added options to tex2svg
ArbitRandomUser Jan 30, 2022
973e129
Revert "added options to tex2svg"
ArbitRandomUser Jan 30, 2022
acaa642
changed latexmk to latex, and run->success
ArbitRandomUser Jan 30, 2022
c842bdd
pass packages to tex2svg
ArbitRandomUser Jan 30, 2022
a1d4b48
added UUIDs as dep
ArbitRandomUser Jan 30, 2022
07bccd0
custom output_dir and uuid filenames for generated tex and other files
ArbitRandomUser Jan 30, 2022
d4829b5
testing svg scaling
ArbitRandomUser Jan 31, 2022
549185a
fixed scaling of fonts ... i thinks
ArbitRandomUser Feb 1, 2022
dffaaa1
fixed problem with reversed polys, i.e holes being clockwise instead …
ArbitRandomUser Feb 2, 2022
a9bd34d
svg2luxor can draw <path />'s in svg's with stroke attribute
ArbitRandomUser Feb 5, 2022
f681606
latex.jl now handles mathjax fonts,(only mathjax fonts need to be ins…
ArbitRandomUser Feb 5, 2022
013767c
Merge branch 'master' into latexbranch,
ArbitRandomUser Feb 5, 2022
80bd3d8
add optional packages parameter to latex
ArbitRandomUser Feb 6, 2022
e556e17
Revert "add optional packages parameter to latex"
ArbitRandomUser Feb 6, 2022
2049209
modify Javis.LaTeXusepackages to add and remove packages
ArbitRandomUser Feb 6, 2022
ddafdc9
default packages 'amssymb' and 'amsmath' added to LaTeXusepackages
ArbitRandomUser Feb 6, 2022
c596a58
change warning for log file
ArbitRandomUser Feb 6, 2022
dc77e66
removed
ArbitRandomUser Feb 6, 2022
e9dac9c
swicthable tex engine
ArbitRandomUser Feb 6, 2022
747c5da
removed Infiltrator from Javis.jl
ArbitRandomUser Feb 6, 2022
8b01efe
Merge branch 'latexbranch_switch_tex' into latexbranch
ArbitRandomUser Feb 6, 2022
f11145f
warn of missing attr only once
ArbitRandomUser Feb 6, 2022
e8f5845
12pt fixed instead of preview in latex
ArbitRandomUser Feb 8, 2022
80ffd6f
added changelog
ArbitRandomUser Feb 8, 2022
f3df493
ran formatter
ArbitRandomUser Feb 8, 2022
0b3848c
changed how tmp files and folders are made , moved dosctring
ArbitRandomUser Feb 11, 2022
499e08d
removed unecesary dosctring; remove commented code
ArbitRandomUser Feb 11, 2022
e2207e3
remove try statement; make if block
ArbitRandomUser Feb 11, 2022
9721314
ran formatter
ArbitRandomUser Feb 11, 2022
7d406c7
changed != to !== for nothing,changed pi to p_i, changed font scaling…
ArbitRandomUser Feb 14, 2022
706c96c
removed using UUID
ArbitRandomUser Feb 14, 2022
91a452b
added docstrings for check_stroke and setLaTeXprog, ran formatter
ArbitRandomUser Feb 14, 2022
949b536
cleanup=false for temp dirs and files in latex.jl; fixed bug where wa…
ArbitRandomUser Feb 15, 2022
7b6ec58
ran formatter
ArbitRandomUser Feb 15, 2022
aa85ff8
Merge branch 'master' into latexbranch
ArbitRandomUser Feb 16, 2022
cbfcdd8
updated changelog
ArbitRandomUser Feb 16, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
# Javis.jl - Changelog

##for PR
- change font scaling in svg2luxor from 1/2 to 425/1000
## Unreleased
- Shape.jl
- Now handles holes and polys both ways clockwise and counter-cw , this can happend if we are transforming that has an y-flip transform (typically like svg's that dvisvgm makes),
- latex.jl
- two module variables `LaTeXusepackages` and `LaTeXprog` to specify LaTeX behavior
- has optional support to use latex and dvisvgm to generate your latex
- function `tex2svg` added to convert Lstring to svg using dvisvgm
- svg2luxor.jl
- change font scaling in svg2luxor from 1/2 to 425/1000
- `draw_obj` for paths can now handle "stroke" attributes
- `draw_obj` can handle C and S svg path instructions.
- warnings for missing attributes are printed only once at their first occurance
- change default line width to 2.0 like luxor


## v0.8.0 (1st of February 2022)
- Allow Luxor v3.0
- moved notebooks to extra repository [JavisNB](https://github.com/JuliaAnimators/JavisNB.jl)
Expand Down
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Luxor = "ae8d54c2-7ccd-5906-9d76-62fc9837b5bc"
ProgressMeter = "92933f4c-e287-5a05-a399-4b506db050ca"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
VideoIO = "d6d074c3-1acf-5d4c-9a43-ef38773959a2"

[compat]
Expand Down
12 changes: 9 additions & 3 deletions src/Shape.jl
Original file line number Diff line number Diff line change
Expand Up @@ -182,27 +182,33 @@ function get_similarity(shapeA::Shape, shapeB::Shape)
end

function create_shapes(polys)
#@infiltrate
shapes = Vector{Shape}()

is_last_subpath = false
current_points = Point[]
current_subpaths = Vector{Vector{Point}}()
for poly in polys
if ispolyclockwise(poly) && !is_last_subpath
#firstpoly_orient = polys[1]
firstpoly_orient = ispolyclockwise(iterate(polys)[1])
for (i, poly) in enumerate(polys)
if (ispolyclockwise(poly) == firstpoly_orient) && !is_last_subpath
#@infiltrate
empty!(current_subpaths)
if !isempty(current_points)
shape = Shape(current_points, Vector{Vector{Point}}())
push!(shapes, shape)
end
current_points = poly
is_last_subpath = false
elseif ispolyclockwise(poly)
elseif (ispolyclockwise(poly) == firstpoly_orient)
#@infiltrate
shape = Shape(current_points, copy(current_subpaths))
push!(shapes, shape)
is_last_subpath = false
current_points = poly
empty!(current_subpaths)
else # is a hole
#@infiltrate
push!(current_subpaths, poly)
is_last_subpath = true
end
Expand Down
78 changes: 65 additions & 13 deletions src/latex.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
# cache such that creating svgs from LaTeX don't need to be created every time
# this is also used for test cases such that `tex2svg` doesn't need to be installed on Github Objects
include("latexsvgfile.jl")
LaTeXusepackages = ["amssymb", "amsmath"]
LaTeXprog = :tex2svg

""" set which backend to use
default is `:tex2svg`, set to
`setLaTeXprog(:dvisvgm)` to use pdflatex with dvisvgm
to generate latex
"""
function setLaTeXprog(s::Symbol)
global LaTeXprog
LaTeXprog = s
end

latex(text::LaTeXString) = latex(text, O)
latex(text::LaTeXString, pos::Point) = latex(text, pos, :stroke)
latex(text::LaTeXString, pos::Point, valign::Symbol, halign::Symbol) =
Expand Down Expand Up @@ -139,24 +152,63 @@ end

# \todo update LaTeXSVG cache to use output of strip_eq as the key. See https://github.com/JuliaAnimators/Javis.jl/pull/307#issuecomment-749616375
function get_latex_svg(text::LaTeXString)
# check if it's cached
#check if it's cached
""" for now the default is to use tex2svg, from mathjax
pass `Javis.setLaTeXprog(:dvisvgm)` to yse dvisvgm
"""

if haskey(LaTeXSVG, text)
svg = LaTeXSVG[text]
else
ts = replace(strip_eq(text), "\n" => " ")
command = if Sys.iswindows()
`cmd /C tex2svg $ts`
else
`tex2svg $ts`
end
try
svg = read(command, String)
catch e
@warn "Using LaTeX needs the program `tex2svg` which might not be installed"
@info "It can be installed using `npm install -g mathjax-node-cli`"
throw(e)
if Javis.LaTeXprog == :tex2svg
ts = replace(strip_eq(text), "\n" => " ")
command = if Sys.iswindows()
`cmd /C tex2svg $ts`
else
`tex2svg $ts`
end
try
svg = read(command, String)
catch e
@warn "Using LaTeX needs the program `tex2svg` which might not be installed"
@info "It can be installed using `npm install -g mathjax-node-cli`,or if you have a TeX distribution installed try setting `setLaTeXprog(:dvisvgm)`"
throw(e)
end
elseif Javis.LaTeXprog == :dvisvgm
println("using dvisvgm")
svg = tex2svg(text)
end
LaTeXSVG[text] = svg
end
return svg
end

Copy link
Copy Markdown
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
Copy Markdown
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 !

"""
generates svg from LaTeXString;
"""
function tex2svg(text::LaTeXString;)
output_dir = mktempdir(cleanup = false)
packagestring = "{" * join(LaTeXusepackages, ",") * "}"
pre = "\\documentclass[12pt]{standalone}
\\usepackage$packagestring

\\begin{document}
"
post = "\\end{document}
"
texfilepath, texio = mktemp(output_dir, cleanup = false)
write(texio, pre * "\n")
write(texio, text)
write(texio, "\n" * post)
flush(texio)
#sometimes latex returns 1,so we use `success` instead of `run`; but pdf is made so its okay
stat = success(
`latex --interaction=nonstopmode --output-dir=$output_dir --output-format=pdf $texfilepath`,
)
if stat == false
@warn "there maybe errors in processing latex, check $texfilepath.log for details"
end
retstring = read(`dvisvgm -n --bbox=preview --stdout --pdf $texfilepath.pdf`, String)
return retstring

end
102 changes: 92 additions & 10 deletions src/svg2luxor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,26 @@ function draw_obj(::Val{:path}, o, defs)
counter = 0

# split without loosing the command
stroke_width = check_stroke(o)
"""if stroke_width is nothing , we are parsing a poly, else we are parsing a stroke
we will go along the stroke path and make an offset poly of stroke-width around the poly, the we traverse a path on that poly """

"""This way svg-strokes with certain width are drawn in luxor"""
if stroke_width !== nothing
path_so_far = storepath()
newpath()
end


data_parts = split(data, r"(?=[A-Za-z])")
# needs to keep track of the current point `c_pt` and the last point `l_pt`
l_pt = O
c_pt = O
circle_pts = []
for pi in 1:length(data_parts)
p = data_parts[pi]
for p_i in 1:length(data_parts)
p = data_parts[p_i]
command, args = p[1], p[2:end]
args = replace(args, "-" => " -")
if command != 'T'
counter = 0
end
Expand Down Expand Up @@ -120,12 +132,40 @@ function draw_obj(::Val{:path}, o, defs)
new_pt = Point(c_pt.x, parse(Float64, args))
line(new_pt)
l_pt, c_pt = c_pt, new_pt
elseif command == 'C'
#println("processing command C with args ", args...)
control_pt1 = parse.(Float64, split(args))[1:2]
control_pt2 = parse.(Float64, split(args))[3:4]
endpt = parse.(Float64, split(args))[5:6]
curve(control_pt1..., control_pt2..., endpt...)
l_pt, c_pt = Point(control_pt2...), Point(endpt...)
elseif command == 'S'
control_pt1 = l_pt + 2 * (c_pt - l_pt)
control_pt2 = parse.(Float64, split(args))[1:2]
endpt = parse.(Float64, split(args))[3:4]
curve(control_pt1..., control_pt2..., endpt...)
l_pt, c_pt = Point(control_pt2...), Point(endpt...)
elseif command == 'Z'
closepath()
else
@warn "Couldn't parse the svg command: $command"
end
end

if stroke_width !== nothing
"""if stroke_width! is nothing , we had a stroke attr in the path
which also means there was no Z command and our path exists
"""
polyp = poly(pathtopoly()..., :none)
if length(polyp) == 2
insert!(polyp, 2, (polyp[1] + polyp[2]) / 2)
end
#@infiltrate
offsetp = offsetpoly(polyp, startoffset = stroke_width, endoffset = stroke_width)
drawpath(path_so_far, :path)
poly(offsetp, :path, close = true)
end

end


Expand Down Expand Up @@ -176,6 +216,20 @@ function set_attrs(o)
end
end

"""
checks for stroke attribute , if exists and a stroke-width exists returns
value of stroke-width, else returns nothing
(although we probably could directly check for stroke-width???)
"""
function check_stroke(o)
attrs = name.(attributes(o))
if "stroke" in attrs && "stroke-width" in attrs
return float_attribute(o, "stroke-width")
else
return nothing
end
end

"""
set_attr(::Val{:transform}, transform_strs)

Expand Down Expand Up @@ -227,7 +281,17 @@ set_transform(t, args...) = @warn "Can't transform $t"
set_attr(::Val{:href}, args...) = nothing
set_attr(::Val{:d}, args...) = nothing
set_attr(::Val{:id}, args...) = nothing
set_attr(t, args...) = @warn "No attr match for $t"
let shown_warning = []
"""warn user only once of missing attr"""
global function set_attr(t, args...)
if t in shown_warning
nothing
else
@warn "No attr match for $t"
push!(shown_warning, t)
end
end
end

"""
svgwh(svg)
Expand All @@ -238,10 +302,18 @@ function svgwh(svg)
fsize = get_current_setting().fontsize
xdoc = parse_string(svg)
xroot = root(xdoc)
# remove ex in the end
# remove ex in the end , or pt in the case of dvisvgm
ex_width = parse(Float64, attribute(xroot, "width")[1:(end - 2)])
ex_height = parse(Float64, attribute(xroot, "height")[1:(end - 2)])
return (fsize * (425 / 1000)) .* (ex_width, ex_height)


#width and height are different in tex2svg and dvisvgm
#tex2svg uses em while dvisvgm uses pt
if LaTeXprog == :tex2svg
return (fsize * (425 / 1000)) .* (ex_width, ex_height)
elseif LaTeXprog == :dvisvgm
return (fsize / 12) .* (ex_width, ex_height)
end
end

"""
Expand All @@ -254,11 +326,15 @@ function pathsvg(svg)
fsize = get_current_setting().fontsize
xdoc = parse_string(svg)
xroot = root(xdoc)
def_element = get_elements_by_tagname(xroot, "defs")[1]
# create a dict for all the definitions
defs = Dict{String,Any}()
for def in collect(child_elements(def_element))
defs[attribute(def, "id")] = def
all_def_tags = get_elements_by_tagname(xroot, "defs")
if length(all_def_tags) != 0
#create a dict for all the definitions
def_element = all_def_tags[1]
#todo: what if there are multiple def tags?
for def in collect(child_elements(def_element))
defs[attribute(def, "id")] = def
end
end
x, y, width, height = parse.(Float64, split(attribute(xroot, "viewBox")))
# remove ex in the end
Expand All @@ -270,7 +346,13 @@ function pathsvg(svg)
# such that we can scale half of a font size (size of a lower letter)
# with the corresponding height of the svg canvas
# and the ex_height given in it's description
scale((fsize * (425 / 1000)) / (height / ex_height))
if LaTeXprog == :tex2svg
scale((fsize * (425 / 1000)) / (height / ex_height))
elseif LaTeXprog == :dvisvgm
#12 here (and in svgwh) is from \dcoumentclass[12pt] in tex2svg function
scale((fsize / 12) / (height / ex_height))
end

translate(-x, -y)

for child in collect(child_elements(xroot))
Expand Down