Co-authored-by: t-bltg <tf.bltg@gmail.com> Co-authored-by: Simon Christ <SimonChrist@gmx.de>
608 lines
20 KiB
Julia
608 lines
20 KiB
Julia
# https://github.com/mbaz/Gaston.
|
|
|
|
# --------------------------------------------
|
|
# These functions are called by Plots
|
|
# --------------------------------------------
|
|
|
|
# Create the window/figure for this backend.
|
|
function _create_backend_figure(plt::Plot{GastonBackend})
|
|
state_handle = Gaston.nexthandle() # for now all the figures will be kept
|
|
plt.o = Gaston.newfigure(state_handle)
|
|
end
|
|
|
|
function _before_layout_calcs(plt::Plot{GastonBackend})
|
|
# Initialize all the subplots first
|
|
plt.o.subplots = Gaston.SubPlot[]
|
|
|
|
n1 = n2 = 0
|
|
if length(plt.inset_subplots) > 0
|
|
n1, sps = gaston_get_subplots(0, plt.inset_subplots, plt.layout)
|
|
gaston_init_subplots(plt, sps)
|
|
end
|
|
|
|
if length(plt.subplots) > 0
|
|
n2, sps = gaston_get_subplots(0, plt.subplots, plt.layout)
|
|
end
|
|
|
|
if (n = n1 + n2) != length(plt.subplots)
|
|
@error "Gaston: $n != $(length(plt.subplots))"
|
|
end
|
|
|
|
plt.o.layout = gaston_init_subplots(plt, sps)
|
|
|
|
# Then add the series (curves in gaston)
|
|
for series in plt.series_list
|
|
gaston_add_series(plt, series)
|
|
end
|
|
|
|
for sp in plt.subplots
|
|
sp === nothing && continue
|
|
for ann in sp[:annotations]
|
|
x, y, val = locate_annotation(sp, ann...)
|
|
sp.o.axesconf *= "\nset label '$(val.str)' at $x,$y $(gaston_font(val.font))"
|
|
end
|
|
end
|
|
nothing
|
|
end
|
|
|
|
function _update_min_padding!(sp::Subplot{GastonBackend})
|
|
sp.minpad = 0mm, 0mm, 0mm, 0mm
|
|
nothing
|
|
end
|
|
|
|
function _update_plot_object(plt::Plot{GastonBackend})
|
|
# respect the layout ratio
|
|
dat = gaston_multiplot_pos_size(plt.layout, (0, 0, 1, 1))
|
|
gaston_multiplot_pos_size!(dat)
|
|
nothing
|
|
end
|
|
|
|
for (mime, term) in (
|
|
"application/eps" => "epscairo",
|
|
"image/eps" => "epslatex",
|
|
"application/pdf" => "pdfcairo",
|
|
"application/postscript" => "postscript",
|
|
"image/png" => "png",
|
|
"image/svg+xml" => "svg",
|
|
"text/latex" => "tikz",
|
|
"application/x-tex" => "epslatex",
|
|
"text/plain" => "dumb",
|
|
)
|
|
@eval function _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{GastonBackend})
|
|
term = String($term)
|
|
tmpfile = "$(Gaston.tempname()).$term"
|
|
|
|
Gaston.save(
|
|
term = term,
|
|
output = tmpfile,
|
|
handle = plt.o.handle,
|
|
saveopts = gaston_saveopts(plt),
|
|
)
|
|
while !isfile(tmpfile)
|
|
end # avoid race condition with read in next line
|
|
write(io, read(tmpfile))
|
|
rm(tmpfile, force = true)
|
|
nothing
|
|
end
|
|
end
|
|
|
|
_display(plt::Plot{GastonBackend}) = display(plt.o)
|
|
|
|
# --------------------------------------------
|
|
# These functions are gaston specific
|
|
# --------------------------------------------
|
|
|
|
function gaston_saveopts(plt::Plot{GastonBackend})
|
|
saveopts = String["size $(join(plt.attr[:size], ","))"]
|
|
|
|
push!(
|
|
saveopts,
|
|
gaston_font(
|
|
plottitlefont(plt),
|
|
rot = false,
|
|
align = false,
|
|
color = false,
|
|
scale = 1,
|
|
),
|
|
)
|
|
|
|
push!(saveopts, "background $(gaston_color(plt.attr[:background_color]))")
|
|
|
|
# push!(saveopts, "title '$(plt.attr[:window_title])'")
|
|
|
|
# Scale all plot elements to match Plots.jl DPI standard
|
|
scaling = plt.attr[:dpi] / Plots.DPI
|
|
push!(saveopts, "fontscale $scaling lw $scaling dl $scaling ps $scaling")
|
|
|
|
return join(saveopts, " ")
|
|
end
|
|
|
|
function gaston_get_subplots(n, plt_subplots, layout)
|
|
nr, nc = size(layout)
|
|
sps = Array{Any}(nothing, nr, nc)
|
|
for r in 1:nr, c in 1:nc # NOTE: col major
|
|
l = layout[r, c]
|
|
if l isa GridLayout
|
|
n, sub = gaston_get_subplots(n, plt_subplots, l)
|
|
sps[r, c] = size(sub) == (1, 1) ? only(sub) : sub
|
|
else
|
|
sps[r, c] = get(l.attr, :blank, false) ? nothing : plt_subplots[n += 1]
|
|
end
|
|
end
|
|
return n, sps
|
|
end
|
|
|
|
function gaston_init_subplots(plt, sps)
|
|
sz = nr, nc = size(sps)
|
|
for c in 1:nc, r in 1:nr # NOTE: row major
|
|
sp = sps[r, c]
|
|
if sp isa Subplot || sp === nothing
|
|
gaston_init_subplot(plt, sp)
|
|
else
|
|
gaston_init_subplots(plt, sp)
|
|
sz = max.(sz, size(sp))
|
|
end
|
|
end
|
|
return sz
|
|
end
|
|
|
|
function gaston_init_subplot(
|
|
plt::Plot{GastonBackend},
|
|
sp::Union{Nothing,Subplot{GastonBackend}},
|
|
)
|
|
if sp === nothing
|
|
push!(plt.o.subplots, sp)
|
|
else
|
|
dims =
|
|
RecipesPipeline.is3d(sp) ||
|
|
sp.attr[:projection] == "3d" ||
|
|
needs_any_3d_axes(sp) ? 3 : 2
|
|
any_label = false
|
|
for series in series_list(sp)
|
|
if dims == 2 && series[:seriestype] ∈ (:heatmap, :contour)
|
|
dims = 3 # we need heatmap/contour to use splot, not plot
|
|
end
|
|
any_label |= should_add_to_legend(series)
|
|
end
|
|
sp.o = Gaston.Plot(
|
|
dims = dims,
|
|
curves = [],
|
|
axesconf = gaston_parse_axes_args(plt, sp, dims, any_label),
|
|
)
|
|
push!(plt.o.subplots, sp.o)
|
|
end
|
|
nothing
|
|
end
|
|
|
|
function gaston_multiplot_pos_size(layout, parent_xy_wh)
|
|
nr, nc = size(layout)
|
|
dat = Array{Any}(nothing, nr, nc)
|
|
for r in 1:nr, c in 1:nc
|
|
l = layout[r, c]
|
|
# width and height (pct) are multiplicative (parent)
|
|
w = layout.widths[c].value * parent_xy_wh[3]
|
|
h = layout.heights[r].value * parent_xy_wh[4]
|
|
if isa(l, EmptyLayout)
|
|
dat[r, c] = (c - 1) * w, (r - 1) * h, w, h, nothing
|
|
else
|
|
# previous position (origin)
|
|
prev_r = r > 1 ? dat[r - 1, c] : nothing
|
|
prev_c = c > 1 ? dat[r, c - 1] : nothing
|
|
prev_r isa Array && (prev_r = prev_r[end, end])
|
|
prev_c isa Array && (prev_c = prev_c[end, end])
|
|
x = prev_c !== nothing ? prev_c[1] + prev_c[3] : parent_xy_wh[1]
|
|
y = prev_r !== nothing ? prev_r[2] + prev_r[4] : parent_xy_wh[2]
|
|
if l isa GridLayout
|
|
sub = gaston_multiplot_pos_size(l, (x, y, w, h))
|
|
dat[r, c] = size(sub) == (1, 1) ? only(sub) : sub
|
|
else
|
|
dat[r, c] = x, y, w, h, l
|
|
end
|
|
end
|
|
end
|
|
return dat
|
|
end
|
|
|
|
function gaston_multiplot_pos_size!(dat)
|
|
nr, nc = size(dat)
|
|
for r in 1:nr, c in 1:nc
|
|
xy_wh_sp = dat[r, c]
|
|
if xy_wh_sp isa Array
|
|
gaston_multiplot_pos_size!(xy_wh_sp)
|
|
elseif xy_wh_sp isa Tuple
|
|
x, y, w, h, sp = xy_wh_sp
|
|
sp === nothing && continue
|
|
sp.o === nothing && continue
|
|
# gnuplot screen coordinates: bottom left at 0,0 and top right at 1,1
|
|
sp.o.axesconf = "set origin $x, $(1 - y - h)\nset size $w, $h\n" * sp.o.axesconf
|
|
end
|
|
end
|
|
nothing
|
|
end
|
|
|
|
function gaston_add_series(plt::Plot{GastonBackend}, series::Series)
|
|
sp = series[:subplot]
|
|
gsp = sp.o
|
|
x, y, z = series[:x], series[:y], series[:z]
|
|
st = series[:seriestype]
|
|
curves = []
|
|
if gsp.dims == 2 && z === nothing
|
|
for (n, seg) in enumerate(series_segments(series, st; check = true))
|
|
i, rng = seg.attr_index, seg.range
|
|
fr = _cycle(series[:fillrange], 1:length(x[rng]))
|
|
for sc in gaston_seriesconf!(sp, series, i, n == 1)
|
|
push!(curves, Gaston.Curve(x[rng], y[rng], nothing, fr, sc))
|
|
end
|
|
end
|
|
else
|
|
if z isa Surface
|
|
z = z.surf
|
|
if st == :image
|
|
z = reverse(Float32.(Gray.(z)), dims = 1) # flip y axis
|
|
nr, nc = size(z)
|
|
if (ly = length(y)) == 2 && ly != nr
|
|
y = collect(range(y[1], y[2], length = nr))
|
|
end
|
|
if (lx = length(x)) == 2 && lx != nc
|
|
x = collect(range(x[1], x[2], length = nc))
|
|
end
|
|
elseif st == :heatmap
|
|
length(x) == size(z, 2) + 1 && (x = @view x[1:(end - 1)])
|
|
length(y) == size(z, 1) + 1 && (y = @view y[1:(end - 1)])
|
|
end
|
|
end
|
|
if st == :mesh3d
|
|
x, y, z = mesh3d_triangles(x, y, z, series[:connections])
|
|
end
|
|
for sc in gaston_seriesconf!(sp, series, 1, true)
|
|
push!(curves, Gaston.Curve(x, y, z, nothing, sc))
|
|
end
|
|
end
|
|
|
|
for c in curves
|
|
append = length(gsp.curves) > 0
|
|
push!(gsp.curves, c)
|
|
Gaston.write_data(c, gsp.dims, gsp.datafile, append = append)
|
|
end
|
|
nothing
|
|
end
|
|
|
|
function gaston_seriesconf!(
|
|
sp::Subplot{GastonBackend},
|
|
series::Series,
|
|
i::Int,
|
|
add_to_legend::Bool,
|
|
)
|
|
#=
|
|
gnuplot abbreviations (see gnuplot/src/set.c)
|
|
---------------------------------------------
|
|
dl: dashlength
|
|
dt: dashtype
|
|
fc: fillcolor
|
|
fs: fillstyle
|
|
lc: linecolor
|
|
lp: linespoints
|
|
ls: linestyle
|
|
lt: linetype
|
|
lw: linewidth
|
|
pi: pointinterval
|
|
pn: pointnumber
|
|
ps: pointscale
|
|
pt: pointtype
|
|
tc: textcolor
|
|
w: with
|
|
=#
|
|
gsp = sp.o
|
|
st = series[:seriestype]
|
|
extra = []
|
|
add_to_legend &= should_add_to_legend(series)
|
|
curveconf = String[add_to_legend ? "title '$(series[:label])'" : "notitle"]
|
|
|
|
clims = get_clims(sp, series)
|
|
if st ∈ (:scatter, :scatter3d)
|
|
lc, dt, lw = gaston_lc_ls_lw(series, clims, i)
|
|
pt, ps, mc = gaston_mk_ms_mc(series, clims, i)
|
|
push!(curveconf, "w points pt $pt ps $ps lc $mc")
|
|
elseif st ∈ (:path, :straightline, :path3d)
|
|
fr = series[:fillrange]
|
|
fc = gaston_color(get_fillcolor(series, i), get_fillalpha(series, i))
|
|
lc, dt, lw = gaston_lc_ls_lw(series, clims, i)
|
|
if fr !== nothing # filled curves, but not filled curves with markers
|
|
push!(
|
|
curveconf,
|
|
"w filledcurves fc $fc fs solid border lc $lc lw $lw dt $dt,'' w lines lc $lc lw $lw dt $dt",
|
|
)
|
|
elseif series[:markershape] == :none # simplepath
|
|
push!(curveconf, "w lines lc $lc dt $dt lw $lw")
|
|
else
|
|
pt, ps, mc = gaston_mk_ms_mc(series, clims, i)
|
|
push!(curveconf, "w lp lc $mc dt $dt lw $lw pt $pt ps $ps")
|
|
end
|
|
elseif st == :shape
|
|
fc = gaston_color(get_fillcolor(series, i), get_fillalpha(series, i))
|
|
lc, _ = gaston_lc_ls_lw(series, clims, i)
|
|
push!(curveconf, "w filledcurves fc $fc fs solid border lc $lc")
|
|
elseif st ∈ (:steppre, :stepmid, :steppost)
|
|
step = if st == :steppre
|
|
"fsteps"
|
|
elseif st == :stepmid
|
|
"histeps"
|
|
elseif st == :steppost
|
|
"steps"
|
|
end
|
|
push!(curveconf, "w $step")
|
|
lc, dt, lw = gaston_lc_ls_lw(series, clims, i)
|
|
push!(extra, "w points lc $lc dt $dt lw $lw notitle")
|
|
elseif st == :image
|
|
palette = gaston_palette(series[:seriescolor])
|
|
gsp.axesconf *= "\nset palette model RGB defined $palette"
|
|
push!(curveconf, "w image pixels")
|
|
elseif st ∈ (:contour, :contour3d)
|
|
push!(curveconf, "w lines")
|
|
st == :contour && (gsp.axesconf *= "\nset view map\nunset surface") # 2D
|
|
levels = join(map(string, collect(contour_levels(series, clims))), ", ")
|
|
gsp.axesconf *= "\nset contour base\nset cntrparam levels discrete $levels"
|
|
elseif st ∈ (:surface, :heatmap)
|
|
push!(curveconf, "w pm3d")
|
|
palette = gaston_palette(series[:seriescolor])
|
|
gsp.axesconf *= "\nset palette model RGB defined $palette"
|
|
st == :heatmap && (gsp.axesconf *= "\nset view map")
|
|
elseif st ∈ (:wireframe, :mesh3d)
|
|
lc, dt, lw = gaston_lc_ls_lw(series, clims, i)
|
|
push!(curveconf, "w lines lc $lc dt $dt lw $lw")
|
|
elseif st == :quiver
|
|
push!(curveconf, "w vectors filled")
|
|
else
|
|
@warn "Gaston: $st is not implemented yet"
|
|
end
|
|
|
|
return [join(curveconf, " "), extra...]
|
|
end
|
|
|
|
function gaston_parse_axes_args(
|
|
plt::Plot{GastonBackend},
|
|
sp::Subplot{GastonBackend},
|
|
dims::Int,
|
|
any_label::Bool,
|
|
)
|
|
# axesconf = String["set margins 2, 2, 2, 2"] # left, right, bottom, top
|
|
axesconf = String[]
|
|
|
|
polar = ispolar(sp) && dims == 2 # cannot splot in polar coordinates
|
|
|
|
for letter in (:x, :y, :z)
|
|
(letter == :z && dims == 2) && continue
|
|
axis = sp.attr[get_attr_symbol(letter, :axis)]
|
|
# label names
|
|
push!(
|
|
axesconf,
|
|
"set $(letter)label '$(axis[:guide])' $(gaston_font(guidefont(axis)))",
|
|
)
|
|
mirror = axis[:mirror] ? "mirror" : "nomirror"
|
|
|
|
if axis[:scale] == :identity
|
|
logscale, base = "nologscale", ""
|
|
elseif axis[:scale] == :log10
|
|
logscale, base = "logscale", "10"
|
|
elseif axis[:scale] == :log2
|
|
logscale, base = "logscale", "2"
|
|
elseif axis[:scale] == :ln
|
|
logscale, base = "logscale", "e"
|
|
end
|
|
push!(axesconf, "set $logscale $letter $base")
|
|
|
|
# handle ticks
|
|
if polar
|
|
push!(axesconf, "set size square\nunset $(letter)tics")
|
|
else
|
|
push!(
|
|
axesconf,
|
|
"set $(letter)tics $(mirror) $(axis[:tick_direction]) $(gaston_font(tickfont(axis)))",
|
|
)
|
|
|
|
# major tick locations
|
|
if axis[:ticks] != :native
|
|
if axis[:flip]
|
|
hi, lo = axis_limits(sp, letter)
|
|
else
|
|
lo, hi = axis_limits(sp, letter)
|
|
end
|
|
push!(axesconf, "set $(letter)range [$lo:$hi]")
|
|
|
|
ticks = get_ticks(sp, axis)
|
|
gaston_set_ticks!(axesconf, ticks, letter, "", "")
|
|
|
|
if axis[:minorticks] != :native
|
|
minor_ticks = get_minor_ticks(sp, axis, ticks)
|
|
gaston_set_ticks!(axesconf, minor_ticks, letter, "m", "add")
|
|
end
|
|
end
|
|
end
|
|
|
|
if axis[:grid]
|
|
push!(axesconf, "set grid " * (polar ? "polar" : "$(letter)tics"))
|
|
axis[:minorgrid] &&
|
|
push!(axesconf, "set grid " * (polar ? "polar" : "m$(letter)tics"))
|
|
end
|
|
|
|
ratio = get_aspect_ratio(sp)
|
|
if ratio != :none
|
|
ratio == :equal && (ratio = -1)
|
|
push!(axesconf, "set size ratio $ratio")
|
|
end
|
|
end
|
|
gaston_set_legend!(axesconf, sp, any_label)
|
|
|
|
if hascolorbar(sp)
|
|
push!(axesconf, "set cbtics $(gaston_font(colorbartitlefont(sp)))")
|
|
end
|
|
|
|
if sp[:title] !== nothing
|
|
push!(axesconf, "set title '$(sp[:title])' $(gaston_font(titlefont(sp)))")
|
|
end
|
|
|
|
if polar
|
|
push!(axesconf, "unset border\nset polar\nset border polar")
|
|
tmin, tmax = axis_limits(sp, :x, false, false)
|
|
rmin, rmax = axis_limits(sp, :y, false, false)
|
|
rticks = get_ticks(sp, :y)
|
|
if (ttype = ticksType(rticks)) == :ticks
|
|
gaston_ticks = string.(rticks)
|
|
elseif ttype == :ticks_and_labels
|
|
gaston_ticks = String["'$l' $t" for (t, l) in zip(rticks...)]
|
|
end
|
|
push!(
|
|
axesconf,
|
|
"set rtics ( " *
|
|
join(gaston_ticks, ", ") *
|
|
" ) $(gaston_font(tickfont(sp.attr[:yaxis])))",
|
|
)
|
|
push!(axesconf, "set trange [$(min(0, tmin)):$(max(2π, tmax))]")
|
|
push!(axesconf, "set rrange [$rmin:$rmax]")
|
|
push!(
|
|
axesconf,
|
|
"set ttics 0,30 format \"%g\".GPVAL_DEGREE_SIGN $(gaston_font(tickfont(sp.attr[:xaxis])))",
|
|
)
|
|
push!(axesconf, "set mttics 3")
|
|
end
|
|
|
|
return join(axesconf, "\n")
|
|
end
|
|
|
|
function gaston_set_ticks!(axesconf, ticks, letter, maj_min, add)
|
|
ticks == :auto && return
|
|
if ticks ∈ (:none, nothing, false)
|
|
push!(axesconf, "unset $(maj_min)$(letter)tics")
|
|
return
|
|
end
|
|
|
|
gaston_ticks = String[]
|
|
if (ttype = ticksType(ticks)) == :ticks
|
|
tick_locs = @view ticks[:]
|
|
for i in eachindex(tick_locs)
|
|
tick = if maj_min == "m"
|
|
"'' $(tick_locs[i]) 1" # see gnuplot manual 'Mxtics'
|
|
else
|
|
"$(tick_locs[i])"
|
|
end
|
|
push!(gaston_ticks, tick)
|
|
end
|
|
elseif ttype == :ticks_and_labels
|
|
tick_locs = @view ticks[1][:]
|
|
tick_labels = @view ticks[2][:]
|
|
for i in eachindex(tick_locs)
|
|
lab = gaston_enclose_tick_string(tick_labels[i])
|
|
push!(gaston_ticks, "'$lab' $(tick_locs[i])")
|
|
end
|
|
else
|
|
gaston_ticks = nothing
|
|
@error "Gaston: invalid input for $(maj_min)$(letter)ticks: $ticks"
|
|
end
|
|
if gaston_ticks !== nothing
|
|
push!(axesconf, "set $(letter)tics $add (" * join(gaston_ticks, ", ") * ")")
|
|
end
|
|
nothing
|
|
end
|
|
|
|
function gaston_set_legend!(axesconf, sp, any_label)
|
|
leg = sp[:legend]
|
|
if sp[:legend] ∉ (:none, :inline) && any_label
|
|
leg == :best && (leg = :topright)
|
|
|
|
push!(
|
|
axesconf,
|
|
"set key " * (occursin("outer", string(leg)) ? "outside" : "inside"),
|
|
)
|
|
for position in ("top", "bottom", "left", "right")
|
|
occursin(position, string(leg)) && push!(axesconf, "set key $position")
|
|
end
|
|
push!(axesconf, "set key $(gaston_font(legendfont(sp), rot=false, align=false))")
|
|
if sp[:legendtitle] !== nothing
|
|
# NOTE: cannot use legendtitlefont(sp) as it will override legendfont
|
|
push!(axesconf, "set key title '$(sp[:legendtitle])'")
|
|
end
|
|
push!(axesconf, "set key box lw 1 opaque")
|
|
push!(axesconf, "set border back")
|
|
else
|
|
push!(axesconf, "set key off")
|
|
end
|
|
nothing
|
|
end
|
|
|
|
# --------------------------------------------
|
|
# Helpers
|
|
# --------------------------------------------
|
|
|
|
gaston_halign(k) = (left = :left, hcenter = :center, right = :right)[k]
|
|
gaston_valign(k) = (top = :top, vcenter = :center, bottom = :bottom)[k]
|
|
|
|
gaston_alpha(alpha) = alpha === nothing ? 0 : alpha
|
|
|
|
gaston_lc_ls_lw(series::Series, clims, i::Int) = (
|
|
gaston_color(get_linecolor(series, clims, i), get_linealpha(series, i)),
|
|
gaston_linestyle(get_linestyle(series, i)),
|
|
get_linewidth(series, i),
|
|
)
|
|
|
|
gaston_mk_ms_mc(series::Series, clims, i::Int) = (
|
|
gaston_marker(_cycle(series[:markershape], i), get_markeralpha(series, i)),
|
|
_cycle(series[:markersize], i) * 1.3 / 5,
|
|
gaston_color(get_markercolor(series, clims, i), get_markeralpha(series, i)),
|
|
)
|
|
|
|
function gaston_font(f; rot = true, align = true, color = true, scale = 1)
|
|
font = String["font '$(f.family),$(round(Int, scale * f.pointsize))'"]
|
|
align && push!(font, "$(gaston_halign(f.halign))")
|
|
rot && push!(font, "rotate by $(f.rotation)")
|
|
color && push!(font, "textcolor $(gaston_color(f.color))")
|
|
return join(font, " ")
|
|
end
|
|
|
|
function gaston_palette(gradient)
|
|
palette = String[]
|
|
n = -1
|
|
for rgba in gradient # FIXME: naive conversion, inefficient ?
|
|
push!(palette, "$(n += 1) $(rgba.r) $(rgba.g) $(rgba.b)")
|
|
end
|
|
return '(' * join(palette, ", ") * ')'
|
|
end
|
|
|
|
function gaston_marker(marker, alpha)
|
|
# NOTE: :rtriangle, :ltriangle, :hexagon, :heptagon, :octagon seems unsupported by gnuplot
|
|
filled = gaston_alpha(alpha) == 0
|
|
marker == :none && return -1
|
|
marker == :pixel && return 0
|
|
marker ∈ (:+, :cross) && return 1
|
|
marker ∈ (:x, :xcross) && return 2
|
|
marker == :star5 && return 3
|
|
marker == :rect && return filled ? 5 : 4
|
|
marker == :circle && return filled ? 7 : 6
|
|
marker == :utriangle && return filled ? 9 : 8
|
|
marker == :dtriangle && return filled ? 11 : 10
|
|
marker == :diamond && return filled ? 13 : 12
|
|
marker == :pentagon && return filled ? 15 : 14
|
|
|
|
@warn "Gaston: unsupported marker $marker"
|
|
return 1
|
|
end
|
|
|
|
function gaston_color(col, alpha = 0)
|
|
col = single_color(col) # in case of gradients
|
|
col = alphacolor(col, gaston_alpha(alpha)) # add a default alpha if non existent
|
|
return "rgb '#$(hex(col, :aarrggbb))'"
|
|
end
|
|
|
|
function gaston_linestyle(style)
|
|
style == :solid && return "1"
|
|
style == :dash && return "2"
|
|
style == :dot && return "3"
|
|
style == :dashdot && return "4"
|
|
style == :dashdotdot && return "5"
|
|
end
|
|
|
|
function gaston_enclose_tick_string(tick_string)
|
|
findfirst("^", tick_string) === nothing && return tick_string
|
|
base, power = split(tick_string, "^")
|
|
return "$base^{$power}"
|
|
end
|