Skip to content

Commit

Permalink
tidysvg
Browse files Browse the repository at this point in the history
  • Loading branch information
cormullion committed Jun 26, 2023
1 parent 5d2f3ed commit 18d96c8
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 22 deletions.
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

### Added

- `circlering()`
- `polysuper()`
- `setfillrule()`
- `circlering()`, creates ring of circles inside a circle
- `polysuper()`, creates superellipse-basd polygons
- `setfillrule()`, access Cairo's fill rule parameter
- `getfillrule()`
- `tidysvg(fromfile, tofile)`, munge those SVG glyphs

### Changed

Expand Down
39 changes: 30 additions & 9 deletions src/drawings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -465,14 +465,12 @@ Read the SVG image in `fname` and write it to a file
Return the name of the modified file.
SVG images use named defs for text, which cause errors
problem when used in a notebook.
[See](https://github.com/jupyter/notebook/issues/333) for
example.
SVG images use 'named defs' for text, which cause errors
problem when used in browsers and notebooks.
See [this github issue](https://github.com/jupyter/notebook/issues/333) for
details.
A kludgy workround is to rename the elements...
As of Luxor 3.6 this is done elsewhere.
A kludgy workround is to rename the elements.
"""
function tidysvg(fname)
# I pinched this from Simon's RCall.jl
Expand All @@ -481,19 +479,42 @@ function tidysvg(fname)
if ext == ".svg"
outfile = "$(path * "-tidy" * ext)"
open(fname) do f
r = string(rand(100000:999999))
# random alpha strings
r = join(Char.(append!(rand(65:90, 6), rand(97:122, 6))))
d = read(f, String)
d = replace(d, "id=\"glyph" => "id=\"glyph" * r)
d = replace(d, "href=\"#glyph" => "href=\"#glyph" * r)
open(outfile, "w") do out
write(out, d)
end
@info "modified SVG file copied to $(outfile)"
@debug "modified SVG file copied to $(outfile)"
end
end
return outfile
end

"""
tidysvg(fromfile, tofile)
Read the SVG image in `fromfile` and write it to `tofile` with modified glyph names.
"""
function tidysvg(fromfile, tofile)
path, ext = splitext(fromfile)
if ext == ".svg"
open(fromfile) do f
r = join(Char.(append!(rand(65:90, 6), rand(97:122, 6))))
d = read(f, String)
d = replace(d, "id=\"glyph" => "id=\"glyph" * r)
d = replace(d, "href=\"#glyph" => "href=\"#glyph" * r)
open(tofile, "w") do out
write(out, d)
end
@debug "modified SVG file copied to $(tofile)"
end
end
return tofile
end

# in memory:

Base.showable(::MIME"image/svg+xml", d::Luxor.Drawing) = d.surfacetype == :svg
Expand Down
26 changes: 23 additions & 3 deletions src/hexagons.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
# algorithms from https://www.redblobgames.com/grids/hexagons/
# first adapted by GiovineItalia/Hexagons.jl
# then further tweaked for Julia v1 compatibility, Luxor use, etc.
"""
Hexagon
To create a hexagon, use one of the types:
- HexagonOffsetOddR q r origin w h
- HexagonOffsetEvenR q r origin w h
- HexagonAxial q r origin w h
- HexagonCubic q r s origin w h
Functions:
- hextile(hex::Hexagon) - calculate the six vertices
- hexcenter(hex::Hexagon) - center
- hexring(n::Int, hex::Hexagon) - array of hexagons surrounding hex
- hexspiral(hex::Hexagon, n) - arry of hexagons in spiral
- hexneighbors(hex::Hexagon) - array of neighbors of hexagon
"""
abstract type Hexagon end

"""
Expand Down Expand Up @@ -290,8 +308,9 @@ end
"""
hexagons_within(n::Int, hex::Hexagon)
Return all the hexagons within index distance `n` of `hex`. If `n` is 0, only the `hex` itself is returned.
If `n` is 1, `hex` and the six hexagons one index away are returned. If `n` is 2, 19 hexagons surrounding `hex` are returned.
Return all the hexagons within index distance `n` of `hex`. If `n` is 0, only
the `hex` itself is returned. If `n` is 1, `hex` and the six hexagons one index
away are returned. If `n` is 2, 19 hexagons surrounding `hex` are returned.
"""
function hexagons_within(n::Int, hex::Hexagon)
cubic_hex = convert(HexagonCubic, hex)
Expand Down Expand Up @@ -327,7 +346,8 @@ end
"""
hexring(n::Int, hex::Hexagon)
Return the ring of hexagons that surround `hex`. If `n` is 1, the hexagons immediately surrounding `hex` are returned.
Return the ring of hexagons that surround `hex`. If `n` is 1, the hexagons
immediately surrounding `hex` are returned.
"""
function hexring(n::Int, hex::Hexagon)
cubic_hex = convert(HexagonCubic, hex)
Expand Down
14 changes: 7 additions & 7 deletions src/text.jl
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ function label(txt::T where T <: AbstractString, alignment::Symbol=:N, pos::Poin
end

"""
label(txt::T where T <: AbstractString, rotation::Float64, pos::Point=O;
label(txt::T where T <: AbstractString, direction::Float64, pos::Point=O;
offset=5,
leader=false,
leaderoffsets=[0.0, 1.0])
Expand All @@ -526,27 +526,27 @@ Add a text label at a point, positioned relative to that point, for example,
label("text", pi) # positions text to the left of the origin
"""
function label(txt::T where T <: AbstractString, rotation::Real, pos::Point=O;
function label(txt::T where T <: AbstractString, direction::Real, pos::Point=O;
offset=5,
leader=false,
leaderoffsets=[0.0, 1.0])
if 0 < rotation <= pi/4
if 0 < direction <= pi/4
vertalign = :middle
horizalign = :left
elseif pi/4 < rotation <= 3pi/4
elseif pi/4 < direction <= 3pi/4
vertalign = :top
horizalign = :center
elseif 3pi/4 < rotation <= 5pi/4
elseif 3pi/4 < direction <= 5pi/4
vertalign = :middle
horizalign = :right
elseif 5pi/4 < rotation <= 7pi/4
elseif 5pi/4 < direction <= 7pi/4
vertalign = :bottom
horizalign = :center
else
vertalign = :middle
horizalign = :left
end
pt = pos + polar(offset, rotation)
pt = pos + polar(offset, direction)
if leader
line(between(pos, pt, leaderoffsets[1]), between(pos, pt, leaderoffsets[2]), :stroke)
end
Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ function run_all_tests()
include("place-svg.jl")
include("strokescale-test.jl")
include("dispatcher.jl")
include("tidy-svg.jl")
end
end

Expand Down
45 changes: 45 additions & 0 deletions test/tidy-svg.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Luxor, Test

f1 = "f1.svg"
@svg begin
text("hello")
text("world")
end 500 500 f1

f2 = "f2.svg"
@svg begin
text("hello")
text("world")
end 500 500 f2

tidysvg(f1, "f3.svg")
tidysvg(f2, "f4.svg")

lines_1 = open("f1.svg") do f
readlines(f)
end
lines_2 = open("f2.svg") do f
readlines(f)
end
lines_3 = open("f3.svg") do f
readlines(f)
end
lines_4 = open("f4.svg") do f
readlines(f)
end

# without running tidysvg(), symbols are the same
for i in eachindex(lines_1)
if occursin("<symbol", lines_1[i])
@test lines_1[i] == lines_2[i]
end
end

# with after running tidysvg(), symbols should be different
for i in eachindex(lines_3)
if occursin("<symbol", lines_3[i])
@test lines_3[i] != lines_4[i]
end
end

println("...finished tidysvg testing")

0 comments on commit 18d96c8

Please sign in to comment.