Skip to content

Commit

Permalink
Merge pull request #73 from davibarreira/feature/savepdf
Browse files Browse the repository at this point in the history
🐛 Adjusting the savefig to adjust the stroke in the case of pdf. Also, adding tests for savefig.
  • Loading branch information
davibarreira authored Feb 20, 2025
2 parents 50228ba + 7e36da0 commit 9ef7bab
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 8 deletions.
4 changes: 4 additions & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ new_viz = new_plt + T(470,0)plt + viz_frame + T(400,250)*viz_title
draw(new_viz)
```

Finally, we can save the diagram using `savefig(new_viz, filename="myviz.svg")`. You can change
the output type by simply changing the extension of the `filename`, for example,
`savefig(new_viz, filename="myviz.pdf")` saves the figures as a PDF.

Check the documentation for a more thorough exposition.

## Installation
Expand Down
23 changes: 19 additions & 4 deletions src/backends/savefigs.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"""
savesvg(plt::𝕋{Mark};filename::String, directory::String="./", height=400, pad=0)
savesvg(plt::𝕋{Mark};filename::String, directory::String="./", height::Union{Real,Nothing}=400, pad::Union{Real,Nothing}=0)
Saves the graphic as an svg figure. The function wraps the whole graphic into an
svg tag with a given view height equal to `height` + `pad`. The `pad` is just
some white space added around the figure. The use of padding is recommended
in order to guarantee that the image is fully displayed.
"""
function savesvg(
plt::Union{Mark,𝕋{Mark}}; filename::String, directory::String="./", height=300, pad=10
plt::Union{Prim, Mark,𝕋{Mark}}; filename::String, directory::String="./", height::Union{Real,Nothing}=300, pad::Union{Real,Nothing}=10
)
img = string(drawsvg(plt; height=height, pad=pad))
fname = filename
Expand All @@ -20,7 +20,7 @@ function savesvg(
end

"""
savefig(plt::𝕋{Mark}; filename::String, directory::String="./", height=400, pad=0)
savefig(plt::𝕋{Mark}; filename::String, directory::String="./", height::Union{Real,Nothing}=300, pad::Union{Real,Nothing}=10)
Saves the graphic as inferring the extension from the filename. The function wraps the whole graphic into an
svg tag with a given view height equal to `height` + `pad`. The `pad` is just
Expand All @@ -29,14 +29,29 @@ in order to guarantee that the image is fully displayed. For raster images
such as `.png`, the height is used to determine the number of pixels in the image.
"""
function savefig(
plt::Union{Mark,𝕋{Mark}}; filename::String, directory::String="./", height=300, pad=10
plt::Union{Prim, Mark,𝕋{Mark}}; filename::String, directory::String="./", height::Union{Real,Nothing}=300, pad::Union{Real,Nothing}=10
)
extension = filename[(end - 2):end]
if extension == "svg"
return savesvg(plt; filename=filename, directory=directory, height=height, pad=pad)
end

img = string(drawsvg(plt; height=height, pad=pad))
# Extract viewBox height from SVG string
viewbox_match = match(r"viewBox=\"[^\"]*\s+[^\"]*\s+[^\"]*\s+([^\"]*)", img)
if isnothing(viewbox_match)
# If no viewBox found, throw error since we can't determine proper scaling
error("Could not find viewBox in SVG - unable to determine proper scaling")
else
# Get the height if it exists, safely parsing the value
viewbox_height = let m = viewbox_match[1]
isnothing(m) ? error("Could not find viewBox in SVG - unable to determine proper scaling") : parse(Float64, m)
end
end

# Recompute the height to fix the stroke width
img = string(drawsvg(U(300/viewbox_height) * plt; height=height, pad=pad))

fname = filename
dirpath = directory
fpath = joinpath(dirpath, fname)
Expand Down
10 changes: 6 additions & 4 deletions src/backends/svgbackend.jl
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ tosvg(dmark::𝕋Mark; height=200, width=1000)
Converts a Diagram of Marks into an svg
"""
function tosvg(dmark::𝕋{<:Mark}; height=200, width=1000, kwargs...)
function tosvg(dmark::𝕋{<:Mark}; height::Real=200, width::Union{Real,Nothing}=1000, kwargs...)
return reducesvg(
map(p -> primtosvg(p), flatten(dmark));
height=height,
Expand All @@ -430,7 +430,7 @@ Takes a diagram `𝕋` and returns an SVG with
height 100 using the envelope of the diagram to compute
the width.
"""
function drawsvg(d::𝕋; height=300, pad=10, width=nothing, kwargs...)
function drawsvg(d::𝕋; height::Union{Real,Nothing}=300, pad::Union{Real,Nothing}=10, width::Union{Real,Nothing}=nothing, adjust_stroke::Bool=false, kwargs...)
bb = boundingbox(d)
if isnothing(bb) || bb [[0.0, 0.0], [0.0, 0.0]]
return tosvg(Prim[]; height=height, kwargs...)
Expand All @@ -451,6 +451,8 @@ function drawsvg(d::𝕋; height=300, pad=10, width=nothing, kwargs...)
height = isnothing(height) ? widthproportion * boxheight : height
width = isnothing(width) ? boxwidth * heightproportion : width
pad = pad / heightproportion

viewBox="$(bb[1][1]-pad/2) $(-bb[2][2]-pad/2) $(boxwidth+pad) $(boxheight+pad)",

return tosvg(
d;
Expand All @@ -462,7 +464,7 @@ function drawsvg(d::𝕋; height=300, pad=10, width=nothing, kwargs...)
)
end
function drawsvg(
p::Union{GeometricPrimitive,Prim,Vector{Prim},Mark}; height=300, pad=10, kwargs...
p::Union{GeometricPrimitive,Prim,Vector{Prim},Mark}; height::Union{Real,Nothing}=300, pad::Union{Real,Nothing}=10, width::Union{Real,Nothing}=nothing, adjust_stroke::Bool=false, kwargs...
)
return drawsvg(dmlift(p); height=height, pad=pad, kwargs...)
return drawsvg(dmlift(p); height=height, pad=pad, width=width, adjust_stroke=adjust_stroke, kwargs...)
end
32 changes: 32 additions & 0 deletions test/backends/test_savefigs.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Vizagrams

@testset "savefig" begin
d = U(1)S(:stroke=>:red,:strokeWidth=>10)Circle(r=1)

@testset "SVG output" begin
mktempdir() do dir
filename = joinpath(dir, "test.svg")
savefig(d, filename=filename)
@test isfile(filename)
content = read(filename, String)
@test occursin("vector-effect: non-scaling-stroke", content)
@test occursin("stroke: red", content)
end
end

@testset "PDF output" begin
mktempdir() do dir
filename = joinpath(dir, "test.pdf")
savefig(d, filename=filename)
@test isfile(filename)
end
end

@testset "PNG output" begin
mktempdir() do dir
filename = joinpath(dir, "test.png")
savefig(d, filename=filename)
@test isfile(filename)
end
end
end
3 changes: 3 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,7 @@ using SafeTestsets
include("./visual/plots.jl")
include("./visual/test_polar.jl")
end
@safetestset "Savefigs" begin
include("./backends/test_savefigs.jl")
end
end

0 comments on commit 9ef7bab

Please sign in to comment.