Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Fonts #3473

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Plots"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
author = ["Tom Breloff (@tbreloff)"]
version = "1.13.2"
version = "1.13.3"

[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
Expand Down
191 changes: 61 additions & 130 deletions src/args.jl
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ const _series_defaults = KW(
:contour_labels => false,
:subplot => :auto, # which subplot(s) does this series belong to?
:series_annotations => nothing, # a list of annotations which apply to the coordinates of this series
:series_annotationfont => nothing,
:primary => true, # when true, this "counts" as a series for color selection, etc. the main use is to allow
# one logical series to be broken up (path and markers, for example)
:hover => nothing, # text to display when hovering over the data points
Expand All @@ -331,17 +332,12 @@ const _series_defaults = KW(

const _plot_defaults = KW(
:plot_title => "",
:plot_titlefontsize => 16,
:plot_titlefont => (; pointsize=16),
:plot_title_location => :center, # also :left or :right
:plot_titlefontfamily => :match,
:plot_titlefonthalign => :hcenter,
:plot_titlefontvalign => :vcenter,
:plot_titlefontrotation => 0.0,
:plot_titlefontcolor => :match,
:background_color => colorant"white", # default for all backgrounds,
:background_color_outside => :match, # background outside grid,
:foreground_color => :auto, # default for all foregrounds, and title color,
:fontfamily => "sans-serif",
:font => (; pointsize=11),
:size => (600,400),
:pos => (0,0),
:window_title => "Plots.jl",
Expand All @@ -365,13 +361,8 @@ const _plot_defaults = KW(
const _subplot_defaults = KW(
:title => "",
:titlelocation => :center, # also :left or :right
:fontfamily_subplot => :match,
:titlefontfamily => :match,
:titlefontsize => 14,
:titlefonthalign => :hcenter,
:titlefontvalign => :vcenter,
:titlefontrotation => 0.0,
:titlefontcolor => :match,
:subplotfont => nothing,
:titlefont => (; pointsize=14),
:background_color_subplot => :match, # default for other bg colors... match takes plot default
:background_color_legend => :match, # background of legend
:background_color_inside => :match, # background inside grid
Expand All @@ -383,31 +374,16 @@ const _subplot_defaults = KW(
:legendtitle => nothing,
:colorbar => :legend,
:clims => :auto,
:colorbar_fontfamily => :match,
:colorbar_tickfont => (; pointsize=8),
:colorbar_ticks => :auto,
:colorbar_tickfontfamily => :match,
:colorbar_tickfontsize => 8,
:colorbar_tickfonthalign => :hcenter,
:colorbar_tickfontvalign => :vcenter,
:colorbar_tickfontrotation => 0.0,
:colorbar_tickfontcolor => :match,
:colorbar_scale => :identity,
:colorbar_formatter => :auto,
:colorbar_discrete_values => [],
:colorbar_continuous_values => zeros(0),
:legendfontfamily => :match,
:legendfontsize => 8,
:legendfonthalign => :hcenter,
:legendfontvalign => :vcenter,
:legendfontrotation => 0.0,
:legendfontcolor => :match,
:legendtitlefontfamily => :match,
:legendtitlefontsize => 11,
:legendtitlefonthalign => :hcenter,
:legendtitlefontvalign => :vcenter,
:legendtitlefontrotation => 0.0,
:legendtitlefontcolor => :match,
:legendfont => (; pointsize=8),
:legendtitlefont => (; pointsize=11),
:annotations => [], # annotation tuples... list of (x,y,annotation)
:annotationfont => (; pointsize=14),
:projection => :none, # can also be :polar or :3d
:aspect_ratio => :auto, # choose from :none or :equal
:margin => 1mm,
Expand All @@ -417,16 +393,11 @@ const _subplot_defaults = KW(
:bottom_margin => :match,
:subplot_index => -1,
:colorbar_title => "",
:colorbar_titlefontsize => 10,
:colorbar_titlefont => (; pointsize=10),
:colorbar_title_location => :center, # also :left or :right
:colorbar_titlefontfamily => :match,
:colorbar_titlefonthalign => :hcenter,
:colorbar_titlefontvalign => :vcenter,
:colorbar_titlefontrotation => 0.0,
:colorbar_titlefontcolor => :match,
:framestyle => :axes,
:camera => (30,30),
:extra_kwargs => Dict()
:extra_kwargs => Dict(),
)

const _axis_defaults = KW(
Expand All @@ -438,18 +409,8 @@ const _axis_defaults = KW(
:rotation => 0,
:flip => false,
:link => [],
:tickfontfamily => :match,
:tickfontsize => 8,
:tickfonthalign => :hcenter,
:tickfontvalign => :vcenter,
:tickfontrotation => 0.0,
:tickfontcolor => :match,
:guidefontfamily => :match,
:guidefontsize => 11,
:guidefonthalign => :hcenter,
:guidefontvalign => :vcenter,
:guidefontrotation => 0.0,
:guidefontcolor => :match,
:tickfont => (; pointsize=8),
:guidefont => (; pointsize=11),
:foreground_color_axis => :match, # axis border/tick colors,
:foreground_color_border => :match, # plot area border/spines,
:foreground_color_text => :match, # tick text color,
Expand Down Expand Up @@ -516,11 +477,13 @@ const _initial_defaults = deepcopy(_all_defaults)
const _initial_axis_defaults = deepcopy(_axis_defaults)

# to be able to reset font sizes to initial values
#=
const _initial_fontsizes = Dict(:titlefontsize => _subplot_defaults[:titlefontsize],
:legendfontsize => _subplot_defaults[:legendfontsize],
:legendtitlefontsize => _subplot_defaults[:legendtitlefontsize],
:tickfontsize => _axis_defaults[:tickfontsize],
:guidefontsize => _axis_defaults[:guidefontsize])
=#

const _internal_args =
[:plot_object, :series_plotindex, :markershape_to_add, :letter, :idxfilter]
Expand Down Expand Up @@ -652,7 +615,7 @@ add_aliases(:zguide, :zlabel, :zlab, :zl)
add_aliases(:zlims, :zlim, :zlimit, :zlimits)
add_aliases(:zticks, :ztick)
add_aliases(:zrotation, :zrot, :zr)
add_aliases(:guidefontsize, :labelfontsize)
add_aliases(:guidefont, :labelfont)
add_aliases(:fill_z, :fillz, :fz, :surfacecolor, :surfacecolour, :sc, :surfcolor, :surfcolour)
add_aliases(:legend, :leg, :key)
add_aliases(:legendtitle, :legend_title, :labeltitle, :label_title, :leg_title, :key_title)
Expand Down Expand Up @@ -967,39 +930,6 @@ function processMinorGridArg!(plotattributes::AKW, arg, letter)
end
end

function processFontArg!(plotattributes::AKW, fontname::Symbol, arg)
T = typeof(arg)
if T <: Font
plotattributes[Symbol(fontname, :family)] = arg.family
plotattributes[Symbol(fontname, :size)] = arg.pointsize
plotattributes[Symbol(fontname, :halign)] = arg.halign
plotattributes[Symbol(fontname, :valign)] = arg.valign
plotattributes[Symbol(fontname, :rotation)] = arg.rotation
plotattributes[Symbol(fontname, :color)] = arg.color
elseif arg == :center
plotattributes[Symbol(fontname, :halign)] = :hcenter
plotattributes[Symbol(fontname, :valign)] = :vcenter
elseif arg in (:hcenter, :left, :right)
plotattributes[Symbol(fontname, :halign)] = arg
elseif arg in (:vcenter, :top, :bottom)
plotattributes[Symbol(fontname, :valign)] = arg
elseif T <: Colorant
plotattributes[Symbol(fontname, :color)] = arg
elseif T <: Symbol || T <: AbstractString
try
plotattributes[Symbol(fontname, :color)] = parse(Colorant, string(arg))
catch
plotattributes[Symbol(fontname, :family)] = string(arg)
end
elseif typeof(arg) <: Integer
plotattributes[Symbol(fontname, :size)] = arg
elseif typeof(arg) <: Real
plotattributes[Symbol(fontname, :rotation)] = convert(Float64, arg)
else
@warn("Skipped font arg: $arg ($(typeof(arg)))")
end
end

_replace_markershape(shape::Symbol) = get(_markerAliases, shape, shape)
_replace_markershape(shapes::AVec) = map(_replace_markershape, shapes)
_replace_markershape(shape) = shape
Expand All @@ -1013,6 +943,27 @@ function _add_markershape(plotattributes::AKW)
end
end

"""
```julia
@fontdependency a b c
```
is equivalent to
```julia
fontattributes[:c] = font(
plotattributes[:a],
plotattributes[:b],
plotattributes[:c]
)
```
"""
macro fontdependency(dependencies...)
esc(
quote
fontattributes[$(QuoteNode(last(dependencies)))] = font(get.(Ref(plotattributes), $dependencies, nothing))
end
)
end

"Handle all preprocessing of args... break out colors/sizes/etc and replace aliases."
function RecipesPipeline.preprocess_attributes!(plotattributes::AKW)
replaceAliases!(plotattributes, _keyAliases)
Expand Down Expand Up @@ -1075,24 +1026,30 @@ function RecipesPipeline.preprocess_attributes!(plotattributes::AKW)
processMinorGridArg!(plotattributes, arg, letter)
end
end
# handle font args common to all axes
for fontname in (:tickfont, :guidefont)
args = RecipesPipeline.pop_kw!(plotattributes, fontname, ())
for arg in wraptuple(args)
for letter in (:x, :y, :z)
processFontArg!(plotattributes, Symbol(letter, fontname), arg)
end
end
end
# handle individual axes font args
for letter in (:x, :y, :z)
for fontname in (:tickfont, :guidefont)
args = RecipesPipeline.pop_kw!(plotattributes, Symbol(letter, fontname), ())
for arg in wraptuple(args)
processFontArg!(plotattributes, Symbol(letter, fontname), arg)
end
end
end

fontattributes = Dict{Symbol, Font}()


@fontdependency font
@fontdependency font plot_titlefont
@fontdependency font subplotfont
@fontdependency font subplotfont series_annotationfont
@fontdependency font subplotfont titlefont
@fontdependency font subplotfont legendfont
@fontdependency font subplotfont legendfont legendtitlefont
@fontdependency font subplotfont annotationfont
@fontdependency font subplotfont tickfont
@fontdependency font subplotfont guidefont
@fontdependency font subplotfont tickfont colorbar_tickfont
@fontdependency font subplotfont guidefont colorbar_titlefont
@fontdependency font subplotfont tickfont xtickfont
@fontdependency font suibplotfont guidefont xguidefont
@fontdependency font subplotfont tickfont ytickfont
@fontdependency font suibplotfont guidefont yguidefont
@fontdependency font subplotfont tickfont ztickfont
@fontdependency font suibplotfont guidefont zguidefont
merge!(plotattributes, fontattributes)

# handle axes args
for k in _axis_args
if haskey(plotattributes, k) && k !== :link
Expand All @@ -1106,14 +1063,6 @@ function RecipesPipeline.preprocess_attributes!(plotattributes::AKW)
end
end

# fonts
for fontname in (:titlefont, :legendfont, :legendtitlefont, :plot_titlefont, :colorbar_titlefont)
args = RecipesPipeline.pop_kw!(plotattributes, fontname, ())
for arg in wraptuple(args)
processFontArg!(plotattributes, fontname, arg)
end
end

# handle line args
for arg in wraptuple(RecipesPipeline.pop_kw!(plotattributes, :line, ()))
processLineArg(plotattributes, arg)
Expand Down Expand Up @@ -1344,21 +1293,6 @@ const _match_map = KW(
:top_margin => :margin,
:right_margin => :margin,
:bottom_margin => :margin,
:titlefontfamily => :fontfamily_subplot,
:titlefontcolor => :foreground_color_subplot,
:legendfontfamily => :fontfamily_subplot,
:legendfontcolor => :foreground_color_subplot,
:legendtitlefontfamily => :fontfamily_subplot,
:legendtitlefontcolor => :foreground_color_subplot,
:colorbar_fontfamily => :fontfamily_subplot,
:colorbar_titlefontfamily => :fontfamily_subplot,
:colorbar_titlefontcolor => :foreground_color_subplot,
:colorbar_tickfontfamily => :fontfamily_subplot,
:colorbar_tickfontcolor => :foreground_color_subplot,
:plot_titlefontfamily => :fontfamily,
:plot_titlefontcolor => :foreground_color,
:tickfontcolor => :foreground_color_text,
:guidefontcolor => :foreground_color_guide,
)

# these can match values from the parent container (axis --> subplot --> plot)
Expand All @@ -1371,9 +1305,6 @@ const _match_map2 = KW(
:foreground_color_minor_grid=> :foreground_color_subplot,
:foreground_color_guide => :foreground_color_subplot,
:foreground_color_text => :foreground_color_subplot,
:fontfamily_subplot => :fontfamily,
:tickfontfamily => :fontfamily_subplot,
:guidefontfamily => :fontfamily_subplot,
)

# properly retrieve from plt.attr, passing `:match` to the correct key
Expand Down
14 changes: 6 additions & 8 deletions src/backends/gr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -663,8 +663,6 @@ function gr_set_tickfont(sp, letter)
sp,
halign = halign,
valign = valign,
rotation = axis[:rotation],
color = axis[:tickfontcolor],
)
end

Expand Down Expand Up @@ -1010,7 +1008,7 @@ function gr_add_legend(sp, leg, viewport_plotarea)
should_add_to_legend(series) || continue
st = series[:seriestype]
lc = get_linecolor(series, clims)
gr_set_line(sp[:legendfontsize] / 8, get_linestyle(series), lc, sp)
gr_set_line(sp[:legendfont].pointsize / 8, get_linestyle(series), lc, sp)

if (st == :shape || series[:fillrange] !== nothing) && series[:ribbon] === nothing
fc = get_fillcolor(series, clims)
Expand Down Expand Up @@ -1046,16 +1044,16 @@ function gr_add_legend(sp, leg, viewport_plotarea)
ms = first(series[:markersize])
msw = first(series[:markerstrokewidth])
s, sw = if ms > 0
0.8 * sp[:legendfontsize], 0.8 * sp[:legendfontsize] * msw / ms
0.8 * sp[:legendfont].pointsize, 0.8 * sp[:legendfont].pointsize * msw / ms
else
0, 0.8 * sp[:legendfontsize] * msw / 8
0, 0.8 * sp[:legendfont].pointsize * msw / 8
end
gr_draw_markers(series, xpos - leg.width_factor * 2, ypos, clims, s, sw)
end

lab = series[:label]
GR.settextalign(GR.TEXT_HALIGN_LEFT, GR.TEXT_VALIGN_HALF)
gr_set_textcolor(plot_color(sp[:legendfontcolor]))
gr_set_textcolor(plot_color(sp[:legendfont].color))
gr_text(xpos, ypos, string(lab))
ypos -= leg.dy
end
Expand Down Expand Up @@ -1192,7 +1190,7 @@ function gr_get_legend_geometry(viewport_plotarea, sp)
x_legend_offset = (viewport_plotarea[2] - viewport_plotarea[1]) / 30
y_legend_offset = (viewport_plotarea[4] - viewport_plotarea[3]) / 30

dy = gr_point_mult(sp) * sp[:legendfontsize] * 1.75
dy = gr_point_mult(sp) * sp[:legendfont].pointsize * 1.75
legendh = dy * legendn

return (
Expand Down Expand Up @@ -1672,7 +1670,7 @@ function gr_add_series(sp, series)

if sp[:legend] == :inline && should_add_to_legend(series)
gr_set_font(legendfont(sp), sp)
gr_set_textcolor(plot_color(sp[:legendfontcolor]))
gr_set_textcolor(plot_color(sp[:legendfont].color))
if sp[:yaxis][:mirror]
(_,i) = sp[:xaxis][:flip] ? findmax(x) : findmin(x)
GR.settextalign(GR.TEXT_HALIGN_RIGHT, GR.TEXT_VALIGN_HALF)
Expand Down
Loading