diff --git a/.github/workflows/Copier.yml_deactivate b/.github/workflows/Copier.yml_deactivate index f7919af..3ea94ee 100644 --- a/.github/workflows/Copier.yml_deactivate +++ b/.github/workflows/Copier.yml_deactivate @@ -2,7 +2,7 @@ name: Copier Update on: schedule: - - cron: 0 7 1/7 * * # Every 7 days at 7:00 UTC + - cron: 0 7 1/7 * * # Every 7 days at 7:00 UTC workflow_dispatch: jobs: @@ -24,7 +24,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v5 with: - cache: 'pip' + cache: "pip" python-version: "3.11" - name: Hack for setup-python cache # https://github.com/actions/setup-python/issues/807 run: rm requirements.txt diff --git a/src/fontOnCurve.jl b/src/fontOnCurve.jl index 67a5d30..b1c88f6 100644 --- a/src/fontOnCurve.jl +++ b/src/fontOnCurve.jl @@ -1,125 +1,155 @@ """ Code written mostly by Julius Krumbiegel with some modifications by Benedikt Ehinger """ - struct TextOnPath - text::String - path::Makie.BezierPath - end - - function Makie._get_glyphcollection_and_linesegments(top::TextOnPath, index, ts, f, fs, al, rot, jus, lh, col, scol, swi, www, offs) - gc = Makie.layout_text(top, ts, f, fs, al, rot, jus, lh, col, scol, swi) - gc, Point2f[], Float32[], RGBAf[], Int[] +struct TextOnPath + text::String + path::Makie.BezierPath +end + +function Makie._get_glyphcollection_and_linesegments( + top::TextOnPath, + index, + ts, + f, + fs, + al, + rot, + jus, + lh, + col, + scol, + swi, + www, + offs, +) + gc = Makie.layout_text(top, ts, f, fs, al, rot, jus, lh, col, scol, swi) + gc, Point2f[], Float32[], RGBAf[], Int[] +end + +""" +returns the attribute per character - if the length of the attribute does not equal to the length of the string, AND it equals to the number of points from the BezierPath - we will use the attribute per segment (until a MoveTo / NaN segment) + +Note: currently only works for LineTo and MoveTo - not Curve, as Curve interpolates 30points per curve! +""" +attribute_per_char_or_segment(string, attr, lengthPoints) = + Makie.attribute_per_char(string, attr) +function attribute_per_char_or_segment(string, attr::AbstractVector, lengthPoints) + + if (length(attr) !== length(string)) & (length(attr) == lengthPoints) + @assert all(isa.([MoveTo(1, 2), LineTo(1, 2)], Union{MoveTo,LineTo})) "Currently no support for BezierSegments other than MoveTo and LineTo" + return attr + else + return Makie.attribute_per_char(string, attr) + end - - """ - returns the attribute per character - if the length of the attribute does not equal to the length of the string, AND it equals to the number of points from the BezierPath - we will use the attribute per segment (until a MoveTo / NaN segment) - - Note: currently only works for LineTo and MoveTo - not Curve, as Curve interpolates 30points per curve! - """ - attribute_per_char_or_segment(string,attr,lengthPoints) = Makie.attribute_per_char(string,attr) - function attribute_per_char_or_segment(string,attr::AbstractVector,lengthPoints) - - if (length(attr) !== length(string) ) & (length(attr) == lengthPoints) - @assert all(isa.([MoveTo(1,2),LineTo(1,2)],Union{MoveTo,LineTo})) "Currently no support for BezierSegments other than MoveTo and LineTo" - return attr +end +function Makie.layout_text(top::TextOnPath, ts, f, fs, al, rot, jus, lh, col, scol, swi) + points = only(Makie.convert_arguments(PointBased(), top.path)) + + ft_font = Makie.to_font(f) + rscale = Makie.to_fontsize(ts) + + + colors = attribute_per_char_or_segment(top.text, col, length(points)) + strokecolors = attribute_per_char_or_segment(top.text, scol, length(points)) + strokewidths = attribute_per_char_or_segment(top.text, swi, length(points)) + fonts = attribute_per_char_or_segment(top.text, ft_font, length(points)) + fontsizes = attribute_per_char_or_segment(top.text, rscale, length(points)) + + gc = glyph_collection_on_path( + points, + top.text, + fonts, + fontsizes, + colors, + strokecolors, + strokewidths, + ) +end + +function glyph_collection_on_path( + points, + text, + fonts, + fontsizes, + colors, + strokecolors, + strokewidths, +) + glyphinfos = Makie.GlyphInfo[] + + seg = 1 + at_fraction::Float64 = 0.0 + + + get_attr(attr::Base.Generator, ix_char, seg) = collect(attr)[1] + get_attr(attr, ix_char, seg) = attr + + + function get_attr(attr::AbstractVector, ix_char, seg) + + if length(attr) == length(text) + return attr[ix_char] else - return Makie.attribute_per_char(string,attr) - + return attr[seg] end - end - function Makie.layout_text(top::TextOnPath, ts, f, fs, al, rot, jus, lh, col, scol, swi) - points = only(Makie.convert_arguments(PointBased(), top.path)) - - ft_font = Makie.to_font(f) - rscale = Makie.to_fontsize(ts) - - - colors = attribute_per_char_or_segment(top.text,col,length(points)) - strokecolors = attribute_per_char_or_segment(top.text,scol,length(points)) - strokewidths = attribute_per_char_or_segment(top.text,swi,length(points)) - fonts = attribute_per_char_or_segment(top.text, ft_font,length(points)) - fontsizes = attribute_per_char_or_segment(top.text, rscale,length(points)) - - gc = glyph_collection_on_path(points, top.text, fonts, fontsizes,colors,strokecolors,strokewidths) end - - function glyph_collection_on_path(points, text, fonts, fontsizes,colors,strokecolors,strokewidths) - glyphinfos = Makie.GlyphInfo[] - - seg = 1 - at_fraction::Float64 = 0.0 - - - get_attr(attr::Base.Generator,ix_char,seg) = collect(attr)[1] - get_attr(attr,ix_char,seg) = attr - - - function get_attr(attr::AbstractVector,ix_char,seg) - - if length(attr) == length(text) - return attr[ix_char] - else - return attr[seg] + for (ix_char, char) in enumerate(collect(text)) + + font = get_attr(fonts, ix_char, seg) + fontsize = get_attr(fontsizes, ix_char, seg) + strokecolor = get_attr(strokecolors, ix_char, seg) + strokewidth = get_attr(strokewidths, ix_char, seg) + color = get_attr(colors, ix_char, seg) + + v = points[seg+1] - points[seg] + p = points[seg] + v * at_fraction + + ext = Makie.GlyphExtent(font, char) + sz = Vec2f(fontsize, fontsize) + + hadvance = ext.hadvance * sz[1] + + # find next point + accumulated = 0.0 + while true + if isnan(points[seg+1]) | isnan(points[seg]) + seg += 1 + continue end - end - for (ix_char,char) in enumerate(collect(text)) - - font = get_attr(fonts,ix_char,seg) - fontsize = get_attr(fontsizes,ix_char,seg) - strokecolor = get_attr(strokecolors,ix_char,seg) - strokewidth = get_attr(strokewidths,ix_char,seg) - color = get_attr(colors,ix_char,seg) - - v = points[seg+1] - points[seg] - p = points[seg] + v * at_fraction - - ext = Makie.GlyphExtent(font, char) - sz = Vec2f(fontsize, fontsize) - - hadvance = ext.hadvance * sz[1] - - # find next point - accumulated = 0.0 - while true - if isnan(points[seg+1]) | isnan(points[seg]) + + seglength = Makie.norm(points[seg+1] - points[seg]) + remaining_this_seg = (1 - at_fraction) * seglength + to_go = hadvance - (accumulated + remaining_this_seg) + if to_go <= 0 + at_fraction = 1 - (-to_go / seglength) + break + else + accumulated += remaining_this_seg + at_fraction = 0.0 + if seg < length(points) - 1 seg += 1 - continue end - - seglength = Makie.norm(points[seg+1] - points[seg]) - remaining_this_seg = (1 - at_fraction) * seglength - to_go = hadvance - (accumulated + remaining_this_seg) - if to_go <= 0 - at_fraction = 1 - (-to_go / seglength) - break - else - accumulated += remaining_this_seg - at_fraction = 0.0 - if seg < length(points)-1 - seg += 1 - end - end - end - - gi = Makie.GlyphInfo( - Makie.FreeTypeAbstraction.glyph_index(font, char), - font, - p, - ext, - sz, - Makie.to_rotation(reverse(v) .* (-1, 1)), - color, - strokecolor, - strokewidth, - ) - push!(glyphinfos, gi) - if seg >= length(points)-1 - @warn "Could not fit all characters on path, you could reduce the fontsize" - break end end - #@show seg, size(glyphinfos) - return Makie.GlyphCollection(glyphinfos) + + gi = Makie.GlyphInfo( + Makie.FreeTypeAbstraction.glyph_index(font, char), + font, + p, + ext, + sz, + Makie.to_rotation(reverse(v) .* (-1, 1)), + color, + strokecolor, + strokewidth, + ) + push!(glyphinfos, gi) + if seg >= length(points) - 1 + @warn "Could not fit all characters on path, you could reduce the fontsize" + break + end end - - + #@show seg, size(glyphinfos) + return Makie.GlyphCollection(glyphinfos) +end diff --git a/src/importpdf.jl b/src/importpdf.jl index 9d29224..2c7144e 100644 --- a/src/importpdf.jl +++ b/src/importpdf.jl @@ -1,22 +1,22 @@ -function getPDFText(src; pages=nothing) +function getPDFText(src; pages = nothing) # handle that can be used for subsequence operations on the document. doc = pdDocOpen(src) - # Metadata extracted from the PDF document. - # This value is retained and returned as the return from the function. + # Metadata extracted from the PDF document. + # This value is retained and returned as the return from the function. docinfo = pdDocGetInfo(doc) io = IOBuffer() - # Returns number of pages in ithe document + # Returns number of pages in ithe document # if isnothing(pages) pages = 1:pdDocGetPageCount(doc) end - for i = pages + for i in pages @info "processing page $i" try - # handle to the specific page given the number index. + # handle to the specific page given the number index. page = pdDocGetPage(doc, i) # Extract text from the page and write it to the output file. @@ -26,7 +26,7 @@ function getPDFText(src; pages=nothing) end end - # Close the document handle. + # Close the document handle. # The doc handle should not be used after this call pdDocClose(doc) return io diff --git a/src/interpolateCurve.jl b/src/interpolateCurve.jl index c83ccce..fabf597 100644 --- a/src/interpolateCurve.jl +++ b/src/interpolateCurve.jl @@ -2,56 +2,48 @@ # returns interpolator - function interp_spline(z;order=2) - t = range(0,1,length=length(z)) - return interpolate(t,z,BSplineOrder(order),Natural()) - end - # returns k x more points, interpolated x/y -function interp_curve(k,x;kwargs...) - it = interp_spline(collect(x);kwargs...) - r = range(0,1,length=k*length(x)) - - r = range(0.5-1/(length(x)*2-2),0.5+1/(length(x)*2-2),length=k) - return it.(r) - -end -function rolling_interp(x;times=5,winsize=4,kwargs...) - if length(x) == 2 - return range(x[1],x[2],length=times) - end - #if length(x)==3 - #winsize =3 - #end - x = vcat(repeat(x[1:1],winsize÷2),x,repeat(x[end:end],winsize÷2)) - - - - return vcat( - rolling( - x-> interp_curve(times,x;kwargs...), - x, - winsize)..., - x[end]) - +function interp_spline(z; order = 2) + t = range(0, 1, length = length(z)) + return interpolate(t, z, BSplineOrder(order), Natural()) end -function rolling_inter2d(x,y;minDist = 1,kwargs...) - x = rolling_interp(x;kwargs...) - y = rolling_interp(y;kwargs...) - - - #ix = 1:length(x) - return equalize_distance(x,y;minDist=minDist) +# returns k x more points, interpolated x/y +function interp_curve(k, x; kwargs...) + it = interp_spline(collect(x); kwargs...) + r = range(0, 1, length = k * length(x)) + + r = range(0.5 - 1 / (length(x) * 2 - 2), 0.5 + 1 / (length(x) * 2 - 2), length = k) + return it.(r) + end +function rolling_interp(x; times = 5, winsize = 4, kwargs...) + if length(x) == 2 + return range(x[1], x[2], length = times) + end + #if length(x)==3 + #winsize =3 + #end + x = vcat(repeat(x[1:1], winsize ÷ 2), x, repeat(x[end:end], winsize ÷ 2)) + + + + return vcat(rolling(x -> interp_curve(times, x; kwargs...), x, winsize)..., x[end]) -function equalize_distance(x,y;minDist=1) - dist = rolling(dist2,x,y,2) - sumdist = cumsum(dist) - ix = vcat(0,findall(diff(floor.(sumdist./minDist)).>0),length(x)-1).+1 - return (;:x=>x[ix],:y=>y[ix]) end -function dist2(x,y) - return sqrt((x[1]-x[2])^2 + (y[1]-y[2])^2) - end - +function rolling_inter2d(x, y; minDist = 1, kwargs...) + x = rolling_interp(x; kwargs...) + y = rolling_interp(y; kwargs...) + + #ix = 1:length(x) + return equalize_distance(x, y; minDist = minDist) +end +function equalize_distance(x, y; minDist = 1) + dist = rolling(dist2, x, y, 2) + sumdist = cumsum(dist) + ix = vcat(0, findall(diff(floor.(sumdist ./ minDist)) .> 0), length(x) - 1) .+ 1 + return (; :x => x[ix], :y => y[ix]) +end +function dist2(x, y) + return sqrt((x[1] - x[2])^2 + (y[1] - y[2])^2) +end diff --git a/src/utils.jl b/src/utils.jl index 68e4d29..701dac1 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -3,8 +3,8 @@ function get_rotation(x, y) end -function newfigure(; size=(420, 594), size_factor=1, kwargs...) - f = Figure(; size=size .* size_factor, kwargs...) +function newfigure(; size = (420, 594), size_factor = 1, kwargs...) + f = Figure(; size = size .* size_factor, kwargs...) ax = f[1, 1] = Axis(f) hidespines!(ax) hidedecorations!(ax) @@ -13,17 +13,34 @@ end function add_title!(f, title, name, year) ##return (1, 1), 2 - ax = add_spacer!(f, 2, 1, 0.3; debug=false) - t1 = text!(ax, 0.5, 0.55, text=title, justification=:center, align=(:center, :center), font="Helvetica") - t2 = text!(ax, 0.85, 0.05, text=[name * "\n" * string(year)], position=[0, 0], justification=:right, color="#888", fontsize=7) + ax = add_spacer!(f, 2, 1, 0.3; debug = false) + t1 = text!( + ax, + 0.5, + 0.55, + text = title, + justification = :center, + align = (:center, :center), + font = "Helvetica", + ) + t2 = text!( + ax, + 0.85, + 0.05, + text = [name * "\n" * string(year)], + position = [0, 0], + justification = :right, + color = "#888", + fontsize = 7, + ) xlims!(ax, (0, 1.0)) ylims!(ax, (0, 1.0)) return (t1, t2, ax) end -function add_spacer!(f, row, col, aspect; debug=false) +function add_spacer!(f, row, col, aspect; debug = false) if debug - a = f[row, col] = Axis(f, backgroundcolor="red") + a = f[row, col] = Axis(f, backgroundcolor = "red") else a = f[row, col] = Axis(f) end diff --git a/test/speedtest.jl b/test/speedtest.jl index 332221a..3c1e5bc 100644 --- a/test/speedtest.jl +++ b/test/speedtest.jl @@ -3,31 +3,29 @@ using Observables using GLMakie -d = rand(50,100000); +d = rand(50, 100000); # n = 1 : 10 -function plt_lines(ax,d,n) +function plt_lines(ax, d, n) for ch = 1:50 - lines!(ax, @lift((d[ch,(($n-1)*10000+1):($n*19000)])), color="black") + lines!(ax, @lift((d[ch, (($n-1)*10000+1):($n*19000)])), color = "black") end end -function plt_series(ax,d,n) - series!(ax,lift(k->d[:,((k-1)*10000+1):(k*10000)],n),solid_color=:black) +function plt_series(ax, d, n) + series!(ax, lift(k -> d[:, ((k-1)*10000+1):(k*10000)], n), solid_color = :black) end n = Observable(1) testwhich = "series" f = Figure() -ax = f[1,1] = Axis(f) +ax = f[1, 1] = Axis(f) #@time plt_series(ax,d,n) # 0.009s / 0.5s -@time plt_lines(ax,d,n) +@time plt_lines(ax, d, n) @time display(f) # 0.013s / 0.13s @time @time begin - n[]=3 + n[] = 3 end - - diff --git a/test/test-basic-test.jl b/test/test-basic-test.jl index db30cfa..6780961 100644 --- a/test/test-basic-test.jl +++ b/test/test-basic-test.jl @@ -1,3 +1 @@ -@testset "ThesisArt.jl" begin - @test ThesisArt.hello_world() == "Hello, World!" -end +@testset "ThesisArt.jl" begin end