diff --git a/CHANGELOG.md b/CHANGELOG.md index bb9e6e82..b8662ffa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/drawings.jl b/src/drawings.jl index cf249b28..919bbe65 100644 --- a/src/drawings.jl +++ b/src/drawings.jl @@ -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 @@ -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 diff --git a/src/hexagons.jl b/src/hexagons.jl index 8d699b94..4a2b88dc 100644 --- a/src/hexagons.jl +++ b/src/hexagons.jl @@ -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 """ @@ -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) @@ -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) diff --git a/src/text.jl b/src/text.jl index 9b9eb317..5e5f854f 100644 --- a/src/text.jl +++ b/src/text.jl @@ -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]) @@ -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 diff --git a/test/runtests.jl b/test/runtests.jl index 6e37c7ba..78533771 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -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 diff --git a/test/tidy-svg.jl b/test/tidy-svg.jl new file mode 100644 index 00000000..cacce17f --- /dev/null +++ b/test/tidy-svg.jl @@ -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("