From 4742ec972b50b873884597f58efd50dbd7333994 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 30 Apr 2019 15:25:08 +0200 Subject: [PATCH 01/10] allow numeric legend positioning in pyplot --- src/backends/gr.jl | 2 +- src/backends/pyplot.jl | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 69b278fd..2c8341f5 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -784,7 +784,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) tbx, tby = gr_inqtext(0, 0, string(lab)) legendw = max(legendw, tbx[3] - tbx[1]) end - + GR.setscale(1) GR.selntran(1) GR.restorestate() diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 3618412f..773b1932 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1251,6 +1251,12 @@ const _pyplot_legend_pos = KW( :topleft => "upper left" ) +py_legend_pos(pos::Symbol) = get(_pyplot_legend_pos, pos, "best") +py_legend_pos(pos) = "lower left" + +py_legend_bbox(pos::Symbol) = (0, 0, 1, 1) +py_legend_bbox(pos) = pos + function py_add_legend(plt::Plot, sp::Subplot, ax) leg = sp[:legend] clims = get_clims(sp) @@ -1288,7 +1294,8 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) if !isempty(handles) leg = ax."legend"(handles, labels, - loc = get(_pyplot_legend_pos, leg, "best"), + loc = py_legend_pos(leg), + bbox_to_anchor = py_legend_bbox(leg), scatterpoints = 1, fontsize = py_thickness_scale(plt, sp[:legendfontsize]), facecolor = py_color(sp[:background_color_legend]), From 03325533bf63ba74c4c83691e561b6a67c0bf9da Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 1 May 2019 12:08:35 +0200 Subject: [PATCH 02/10] outer legend positions for pyplot --- src/args.jl | 2 +- src/backends/pyplot.jl | 45 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/args.jl b/src/args.jl index 24676d01..f7ab6d06 100644 --- a/src/args.jl +++ b/src/args.jl @@ -1186,7 +1186,7 @@ function convertLegendValue(val::Symbol) :best elseif val in (:no, :none) :none - elseif val in (:right, :left, :top, :bottom, :inside, :best, :legend, :topright, :topleft, :bottomleft, :bottomright, :outertopright) + elseif val in (:right, :left, :top, :bottom, :inside, :best, :legend, :topright, :topleft, :bottomleft, :bottomright, :outertopright, :outertopleft, :outertop, :outerright, :outerleft, :outerbottomright, :outerbottomleft, :outerbottom) val else error("Invalid symbol for legend: $val") diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 773b1932..6a8a925d 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -311,6 +311,9 @@ function py_bbox_title(ax) bb end +# bounding box: legend +py_bbox_legend(ax) = py_bbox(ax."get_legend"()) + function py_thickness_scale(plt::Plot{PyPlotBackend}, ptsz) ptsz * plt[:thickness_scaling] end @@ -1188,7 +1191,7 @@ function _update_min_padding!(sp::Subplot{PyPlotBackend}) toppad = 0mm rightpad = 0mm bottompad = 0mm - for bb in (py_bbox_axis(ax, "x"), py_bbox_axis(ax, "y"), py_bbox_title(ax)) + for bb in (py_bbox_axis(ax, "x"), py_bbox_axis(ax, "y"), py_bbox_title(ax), py_bbox_legend(ax)) if ispositive(width(bb)) && ispositive(height(bb)) leftpad = max(leftpad, left(plotbb) - left(bb)) toppad = max(toppad, top(plotbb) - top(bb)) @@ -1251,11 +1254,43 @@ const _pyplot_legend_pos = KW( :topleft => "upper left" ) -py_legend_pos(pos::Symbol) = get(_pyplot_legend_pos, pos, "best") +const _pyplot_legend_pos_outer = KW( + :outerright => "center left", + :outerleft => "right", + :outertop => "lower center", + :outerbottom => "upper center", + :outerbottomleft => "lower right", + :outerbottomright => "lower left", + :outertopright => "upper left", + :outertopleft => "upper right" +) + +py_legend_pos(pos::Symbol) = get(_pyplot_legend_pos, pos, get(_pyplot_legend_pos_outer, pos, "best")) py_legend_pos(pos) = "lower left" -py_legend_bbox(pos::Symbol) = (0, 0, 1, 1) -py_legend_bbox(pos) = pos +function py_legend_bbox_outer(pos, ax) + pos_str = string(pos) + hor = if occursin("left", pos_str) + -0.15 + elseif occursin("right", pos_str) + 1.0 + else + 0.5 + end + ver = if pos == :outerbottom + -0.15 + elseif occursin("bottom", pos_str) + 0.0 + elseif occursin("top", pos_str) + 1.0 + else + 0.5 + end + return hor, ver, 0.0, 0.0 +end + +py_legend_bbox(pos::Symbol, ax) = pos in keys(_pyplot_legend_pos_outer) ? py_legend_bbox_outer(pos, ax) : (0.0, 0.0, 1.0, 1.0) +py_legend_bbox(pos, ax) = pos function py_add_legend(plt::Plot, sp::Subplot, ax) leg = sp[:legend] @@ -1295,7 +1330,7 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) leg = ax."legend"(handles, labels, loc = py_legend_pos(leg), - bbox_to_anchor = py_legend_bbox(leg), + bbox_to_anchor = py_legend_bbox(leg, ax), scatterpoints = 1, fontsize = py_thickness_scale(plt, sp[:legendfontsize]), facecolor = py_color(sp[:background_color_legend]), From 903cb404c3d712f3a470d38d28f62f0e538e629c Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 1 May 2019 12:12:51 +0200 Subject: [PATCH 03/10] shorter implementation --- src/backends/pyplot.jl | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 6a8a925d..100f15ee 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1268,29 +1268,19 @@ const _pyplot_legend_pos_outer = KW( py_legend_pos(pos::Symbol) = get(_pyplot_legend_pos, pos, get(_pyplot_legend_pos_outer, pos, "best")) py_legend_pos(pos) = "lower left" -function py_legend_bbox_outer(pos, ax) - pos_str = string(pos) - hor = if occursin("left", pos_str) - -0.15 - elseif occursin("right", pos_str) - 1.0 - else - 0.5 - end - ver = if pos == :outerbottom - -0.15 - elseif occursin("bottom", pos_str) - 0.0 - elseif occursin("top", pos_str) - 1.0 - else - 0.5 - end - return hor, ver, 0.0, 0.0 -end +const _pyplot_legend_bbox_outer = KW( + :outerright => (1.0, 0.5, 0.0, 0.0), + :outerleft => (-0.15, 0.5, 0.0, 0.0), + :outertop => (0.5, 1.0, 0.0, 0.0), + :outerbottom => (0.5, -0.15, 0.0, 0.0), + :outerbottomleft => (-0.15, 0.0, 0.0, 0.0), + :outerbottomright => (1.0, 0.0, 0.0, 0.0), + :outertopright => (1.0, 1.0, 0.0, 0.0), + :outertopleft => (-0.15, 1.0, 0.0, 0.0) +) -py_legend_bbox(pos::Symbol, ax) = pos in keys(_pyplot_legend_pos_outer) ? py_legend_bbox_outer(pos, ax) : (0.0, 0.0, 1.0, 1.0) -py_legend_bbox(pos, ax) = pos +py_legend_bbox(pos::Symbol) = get(_pyplot_legend_bbox_outer, pos, (0.0, 0.0, 1.0, 1.0)) +py_legend_bbox(pos) = pos function py_add_legend(plt::Plot, sp::Subplot, ax) leg = sp[:legend] @@ -1330,7 +1320,7 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) leg = ax."legend"(handles, labels, loc = py_legend_pos(leg), - bbox_to_anchor = py_legend_bbox(leg, ax), + bbox_to_anchor = py_legend_bbox(leg), scatterpoints = 1, fontsize = py_thickness_scale(plt, sp[:legendfontsize]), facecolor = py_color(sp[:background_color_legend]), From 0e3a9f0b8fa0c327ddd4e81b8430f7b5a150a64e Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 2 May 2019 11:18:17 +0200 Subject: [PATCH 04/10] outer legends for GR --- src/backends/gr.jl | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 2c8341f5..88995a3f 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -535,14 +535,26 @@ function gr_legend_pos(s::Symbol,w,h) xpos = viewport_plotarea[2] - 0.05 - w end elseif occursin("left", str) - xpos = viewport_plotarea[1] + 0.11 + if occursin("outer", str) + xpos = viewport_plotarea[1] - 0.11 - w + else + xpos = viewport_plotarea[1] + 0.11 + end else xpos = (viewport_plotarea[2]-viewport_plotarea[1])/2 - w/2 +.04 end if occursin("top", str) - ypos = viewport_plotarea[4] - 0.06 + if s == :outertop + ypos = viewport_plotarea[4] + h + 0.01 + else + ypos = viewport_plotarea[4] - 0.06 + end elseif occursin("bottom", str) - ypos = viewport_plotarea[3] + h + 0.06 + if s == :outerbottom + ypos = viewport_plotarea[3] - 0.11 + else + ypos = viewport_plotarea[3] + h + 0.06 + end else ypos = (viewport_plotarea[4]-viewport_plotarea[3])/2 + h/2 end @@ -790,8 +802,19 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) GR.restorestate() end - if occursin("outer", string(sp[:legend])) - viewport_plotarea[2] -= legendw + 0.1 + dy = _gr_point_mult[1] * sp[:legendfontsize] * 1.75 + legendh = dy * legendn + leg_str = string(sp[:legend]) + if occursin("outer", leg_str) + if occursin("right", leg_str) + viewport_plotarea[2] -= legendw + 0.1 + elseif occursin("left", leg_str) + viewport_plotarea[1] += legendw + 0.13 + elseif occursin("top", leg_str) + viewport_plotarea[4] -= legendh + 0.06 + elseif occursin("bottom", leg_str) + viewport_plotarea[3] += legendh + 0.09 + end end # fill in the plot area background From 21774dc36b3a1ba4c74750df4d999822a37b03b5 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 2 May 2019 11:27:16 +0200 Subject: [PATCH 05/10] consider rotation in gr_get_ticks_size --- src/backends/gr.jl | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 88995a3f..fde597c1 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -668,17 +668,29 @@ function gr_set_yticks_font(sp) return flip, mirror end -function gr_get_ticks_size(ticks, i) +text_box_width(w, h, rot) = abs(cosd(rot)) * w + abs(cosd(rot + 90)) * h +text_box_height(w, h, rot) = abs(sind(rot)) * w + abs(sind(rot + 90)) * h + +function gr_text_size(str, rot) GR.savestate() GR.selntran(0) - l = 0.0 - for (cv, dv) in zip(ticks...) - tb = gr_inqtext(0, 0, string(dv))[i] - tb_min, tb_max = extrema(tb) - l = max(l, tb_max - tb_min) - end + xs, ys = gr_inqtext(0, 0, string(str)) + l, r = extrema(xs) + b, t = extrema(ys) + w = text_box_width(r - l, t - b, rot) + h = text_box_height(r - l, t - b, rot) GR.restorestate() - return l + return w, h +end + +function gr_get_ticks_size(ticks, rot) + w, h = 0.0, 0.0 + for (cv, dv) in zip(ticks...) + wi, hi = gr_text_size(dv, rot) + w = max(w, wi) + h = max(h, hi) + end + return w, h end function _update_min_padding!(sp::Subplot{GRBackend}) @@ -701,7 +713,7 @@ function _update_min_padding!(sp::Subplot{GRBackend}) xticks, yticks = axis_drawing_info(sp)[1:2] if !(xticks in (nothing, false, :none)) flip, mirror = gr_set_xticks_font(sp) - l = gr_get_ticks_size(xticks, 2) + l = last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation])) if mirror toppad += 1mm + gr_plot_size[2] * l * px else @@ -710,7 +722,7 @@ function _update_min_padding!(sp::Subplot{GRBackend}) end if !(yticks in (nothing, false, :none)) flip, mirror = gr_set_yticks_font(sp) - l = gr_get_ticks_size(yticks, 1) + l = first(gr_get_ticks_size(yticks, sp[:yaxis][:rotation])) if mirror rightpad += 1mm + gr_plot_size[1] * l * px else From bf0bb68e28537a1bca90f81c119c66eda37f2eeb Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 2 May 2019 11:31:20 +0200 Subject: [PATCH 06/10] only add half of ticks text size to min padding --- src/backends/gr.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index fde597c1..bdbcfab2 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -715,18 +715,18 @@ function _update_min_padding!(sp::Subplot{GRBackend}) flip, mirror = gr_set_xticks_font(sp) l = last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation])) if mirror - toppad += 1mm + gr_plot_size[2] * l * px + toppad += 1mm + gr_plot_size[2] * l * px / 2 else - bottompad += 1mm + gr_plot_size[2] * l * px + bottompad += 1mm + gr_plot_size[2] * l * px / 2 end end if !(yticks in (nothing, false, :none)) flip, mirror = gr_set_yticks_font(sp) l = first(gr_get_ticks_size(yticks, sp[:yaxis][:rotation])) if mirror - rightpad += 1mm + gr_plot_size[1] * l * px + rightpad += 1mm + gr_plot_size[1] * l * px / 2 else - leftpad += 1mm + gr_plot_size[1] * l * px + leftpad += 1mm + gr_plot_size[1] * l * px / 2 end end # Add margin for x label From dcabb2c5790c9efb1a46fc31d9e183de49dee0a4 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 2 May 2019 23:04:35 +0200 Subject: [PATCH 07/10] ticks, guides, margins for gr --- src/backends/gr.jl | 123 +++++++++++++++++++++++++++++++-------------- 1 file changed, 86 insertions(+), 37 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index bdbcfab2..eb537223 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -522,21 +522,28 @@ end gr_view_xcenter() = 0.5 * (viewport_plotarea[1] + viewport_plotarea[2]) gr_view_ycenter() = 0.5 * (viewport_plotarea[3] + viewport_plotarea[4]) -function gr_legend_pos(s::Symbol,w,h) +function gr_legend_pos(sp::Subplot, w, h) + s = sp[:legend] + typeof(s) <: Symbol || return gr_legend_pos(s, w, h) str = string(s) if str == "best" str = "topright" end + if occursin("outer", str) + xaxis, yaxis = sp[:xaxis], sp[:yaxis] + xmirror = xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true) + ymirror = yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true) + end if occursin("right", str) if occursin("outer", str) # As per https://github.com/jheinen/GR.jl/blob/master/src/jlgr.jl#L525 - xpos = viewport_plotarea[2] + 0.11 + xpos = viewport_plotarea[2] + 0.11 + ymirror * gr_yaxis_width(sp) else xpos = viewport_plotarea[2] - 0.05 - w end elseif occursin("left", str) if occursin("outer", str) - xpos = viewport_plotarea[1] - 0.11 - w + xpos = viewport_plotarea[1] - 0.05 - w - !ymirror * gr_yaxis_width(sp) else xpos = viewport_plotarea[1] + 0.11 end @@ -545,13 +552,13 @@ function gr_legend_pos(s::Symbol,w,h) end if occursin("top", str) if s == :outertop - ypos = viewport_plotarea[4] + h + 0.01 + ypos = viewport_plotarea[4] + 0.02 + h + xmirror * gr_xaxis_height(sp) else ypos = viewport_plotarea[4] - 0.06 end elseif occursin("bottom", str) if s == :outerbottom - ypos = viewport_plotarea[3] - 0.11 + ypos = viewport_plotarea[3] - 0.05 - !xmirror * gr_xaxis_height(sp) else ypos = viewport_plotarea[3] + h + 0.06 end @@ -668,8 +675,17 @@ function gr_set_yticks_font(sp) return flip, mirror end -text_box_width(w, h, rot) = abs(cosd(rot)) * w + abs(cosd(rot + 90)) * h -text_box_height(w, h, rot) = abs(sind(rot)) * w + abs(sind(rot + 90)) * h +function gr_text_size(str) + GR.savestate() + GR.selntran(0) + xs, ys = gr_inqtext(0, 0, string(str)) + l, r = extrema(xs) + b, t = extrema(ys) + w = r - l + h = t - b + GR.restorestate() + return w, h +end function gr_text_size(str, rot) GR.savestate() @@ -683,6 +699,9 @@ function gr_text_size(str, rot) return w, h end +text_box_width(w, h, rot) = abs(cosd(rot)) * w + abs(cosd(rot + 90)) * h +text_box_height(w, h, rot) = abs(sind(rot)) * w + abs(sind(rot + 90)) * h + function gr_get_ticks_size(ticks, rot) w, h = 0.0, 0.0 for (cv, dv) in zip(ticks...) @@ -693,6 +712,30 @@ function gr_get_ticks_size(ticks, rot) return w, h end +function gr_xaxis_height(sp) + xaxis = sp[:xaxis] + xticks, yticks = axis_drawing_info(sp)[1:2] + gr_set_font(tickfont(xaxis)) + h = (xticks in (nothing, false, :none) ? 0 : last(gr_get_ticks_size(xticks, xaxis[:rotation]))) + if xaxis[:guide] != "" + gr_set_font(guidefont(xaxis)) + h += last(gr_text_size(xaxis[:guide])) + end + return h +end + +function gr_yaxis_width(sp) + yaxis = sp[:yaxis] + xticks, yticks = axis_drawing_info(sp)[1:2] + gr_set_font(tickfont(yaxis)) + w = (xticks in (nothing, false, :none) ? 0 : first(gr_get_ticks_size(yticks, yaxis[:rotation]))) + if yaxis[:guide] != "" + gr_set_font(guidefont(yaxis)) + w += last(gr_text_size(yaxis[:guide])) + end + return w +end + function _update_min_padding!(sp::Subplot{GRBackend}) dpi = sp.plt[:thickness_scaling] if !haskey(ENV, "GKSwstype") @@ -701,48 +744,59 @@ function _update_min_padding!(sp::Subplot{GRBackend}) end end # Add margin given by the user - leftpad = 4mm + sp[:left_margin] + leftpad = 2mm + sp[:left_margin] toppad = 2mm + sp[:top_margin] - rightpad = 4mm + sp[:right_margin] + rightpad = 2mm + sp[:right_margin] bottompad = 2mm + sp[:bottom_margin] # Add margin for title if sp[:title] != "" - toppad += 5mm + gr_set_font(titlefont(sp)) + l = last(last(gr_text_size(sp[:title]))) + h = 1mm + gr_plot_size[2] * l * px + toppad += h end # Add margin for x and y ticks xticks, yticks = axis_drawing_info(sp)[1:2] if !(xticks in (nothing, false, :none)) flip, mirror = gr_set_xticks_font(sp) - l = last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation])) + l = 0.01 + last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation])) + h = 1mm + gr_plot_size[2] * l * px if mirror - toppad += 1mm + gr_plot_size[2] * l * px / 2 + toppad += h else - bottompad += 1mm + gr_plot_size[2] * l * px / 2 + bottompad += h end end if !(yticks in (nothing, false, :none)) flip, mirror = gr_set_yticks_font(sp) - l = first(gr_get_ticks_size(yticks, sp[:yaxis][:rotation])) + l = 0.01 + first(gr_get_ticks_size(yticks, sp[:yaxis][:rotation])) + w = 1mm + gr_plot_size[1] * l * px if mirror - rightpad += 1mm + gr_plot_size[1] * l * px / 2 + rightpad += w else - leftpad += 1mm + gr_plot_size[1] * l * px / 2 + leftpad += w end end # Add margin for x label if sp[:xaxis][:guide] != "" + gr_set_font(guidefont(sp[:xaxis])) + l = last(gr_text_size(sp[:xaxis][:guide])) + h = 1mm + gr_plot_size[2] * l * px if sp[:xaxis][:guide_position] == :top || (sp[:xaxis][:guide_position] == :auto && sp[:xaxis][:mirror] == true) - toppad += 4mm + toppad += h else - bottompad += 4mm + bottompad += h end end # Add margin for y label if sp[:yaxis][:guide] != "" + gr_set_font(guidefont(sp[:yaxis])) + l = last(gr_text_size(sp[:yaxis][:guide])) + w = 1mm + gr_plot_size[2] * l * px if sp[:yaxis][:guide_position] == :right || (sp[:yaxis][:guide_position] == :auto && sp[:yaxis][:mirror] == true) - rightpad += 4mm + rightpad += w else - leftpad += 4mm + leftpad += w end end if sp[:colorbar_title] != "" @@ -819,13 +873,13 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) leg_str = string(sp[:legend]) if occursin("outer", leg_str) if occursin("right", leg_str) - viewport_plotarea[2] -= legendw + 0.1 + viewport_plotarea[2] -= legendw + 0.11 elseif occursin("left", leg_str) - viewport_plotarea[1] += legendw + 0.13 + viewport_plotarea[1] += legendw + 0.11 elseif occursin("top", leg_str) - viewport_plotarea[4] -= legendh + 0.06 + viewport_plotarea[4] -= legendh + 0.03 elseif occursin("bottom", leg_str) - viewport_plotarea[3] += legendh + 0.09 + viewport_plotarea[3] += legendh + 0.04 end end @@ -1096,34 +1150,29 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) gr_set_font(guidefont(xaxis)) GR.titles3d(xaxis[:guide], yaxis[:guide], zaxis[:guide]) else + xticks, yticks = axis_drawing_info(sp)[1:2] if xaxis[:guide] != "" + h = 0.01 + gr_xaxis_height(sp) gr_set_font(guidefont(xaxis)) if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true) GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP) - gr_text(gr_view_xcenter(), viewport_subplot[4], xaxis[:guide]) + gr_text(gr_view_xcenter(), viewport_plotarea[4] + h, xaxis[:guide]) else GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM) - gr_text(gr_view_xcenter(), viewport_subplot[3], xaxis[:guide]) + gr_text(gr_view_xcenter(), viewport_plotarea[3] - h, xaxis[:guide]) end end if yaxis[:guide] != "" + w = 0.02 + gr_yaxis_width(sp) gr_set_font(guidefont(yaxis)) GR.setcharup(-1, 0) if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true) GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM) - if viewport_plotarea[1] - viewport_subplot[1] > 0.1 - gr_text(viewport_plotarea[2] + 0.025, gr_view_ycenter(), yaxis[:guide]) - else - gr_text(viewport_subplot[2], gr_view_ycenter(), yaxis[:guide]) - end + gr_text(viewport_plotarea[2] + w, gr_view_ycenter(), yaxis[:guide]) else GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP) - if viewport_plotarea[1] - viewport_subplot[1] > 0.1 - gr_text(viewport_plotarea[1] - 0.075, gr_view_ycenter(), yaxis[:guide]) - else - gr_text(viewport_subplot[1], gr_view_ycenter(), yaxis[:guide]) - end + gr_text(viewport_plotarea[1] - w, gr_view_ycenter(), yaxis[:guide]) end end end @@ -1396,7 +1445,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if w > 0 dy = _gr_point_mult[1] * sp[:legendfontsize] * 1.75 h = dy*n - (xpos,ypos) = gr_legend_pos(sp[:legend],w,h) + xpos, ypos = gr_legend_pos(sp, w, h) GR.setfillintstyle(GR.INTSTYLE_SOLID) gr_set_fillcolor(sp[:background_color_legend]) GR.fillrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n) From c3990922611ab76c83a43ac9996589004b42f59a Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 4 May 2019 20:43:49 +0200 Subject: [PATCH 08/10] fix animations for pyplot --- src/backends/pyplot.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 100f15ee..f38914ab 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -273,6 +273,8 @@ function py_bbox(obj) BoundingBox(l*px, (ft-t)*px, (r-l)*px, (t-b)*px) end +py_bbox(::Nothing) = BoundingBox(0mm, 0mm) + # get the bounding box of the union of the objects function py_bbox(v::AVec) bbox_union = defaultbox From 0dba83daf605404c0da273a1ec20ed1489c6fa6a Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 5 May 2019 13:08:03 +0200 Subject: [PATCH 09/10] fix gr alphas --- src/backends/gr.jl | 82 ++++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index eb537223..e3a543e4 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -80,6 +80,8 @@ gr_set_markercolor(c) = GR.setmarkercolorind(gr_getcolorind(_cycle(c,1))) gr_set_textcolor(c) = GR.settextcolorind(gr_getcolorind(_cycle(c,1))) gr_set_transparency(α::Real) = GR.settransparency(clamp(α, 0, 1)) gr_set_transparency(::Nothing) = GR.settransparency(1) +gr_set_transparency(c, α) = gr_set_transparency(α) +gr_set_transparency(c::Colorant, ::Nothing) = GR.settransparency(alpha(c)) # -------------------------------------------------------------------------------------- @@ -167,7 +169,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot) #draw angular grid if xaxis[:grid] gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid]) - gr_set_transparency(xaxis[:gridalpha]) + gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha]) for i in 1:length(α) GR.polyline([sinf[i], 0], [cosf[i], 0]) end @@ -176,7 +178,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot) #draw radial grid if yaxis[:grid] gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid]) - gr_set_transparency(yaxis[:gridalpha]) + gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha]) for i in 1:length(rtick_values) r = (rtick_values[i] - rmin) / (rmax - rmin) if r <= 1.0 && r >= 0.0 @@ -296,15 +298,17 @@ function gr_draw_markers(series::Series, x, y, clims, msize = series[:markersize # draw a filled in shape, slightly bigger, to estimate a stroke if series[:markerstrokewidth] > 0 - cfunc(get_markerstrokecolor(series, i)) - gr_set_transparency(get_markerstrokealpha(series, i)) + c = get_markerstrokecolor(series, i) + cfunc(c) + gr_set_transparency(c, get_markerstrokealpha(series, i)) gr_draw_marker(x[i], y[i], msi + series[:markerstrokewidth], shape) end # draw the shape - don't draw filled area if marker shape is 1D if !(shape in (:hline, :vline, :+, :x)) - cfunc(get_markercolor(series, clims, i)) - gr_set_transparency(get_markeralpha(series, i)) + c = get_markercolor(series, clims, i) + cfunc(c) + gr_set_transparency(c, get_markeralpha(series, i)) gr_draw_marker(x[i], y[i], msi, shape) end end @@ -981,21 +985,21 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if xaxis[:grid] gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid]) - gr_set_transparency(xaxis[:gridalpha]) + gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha]) GR.grid3d(xtick, 0, 0, xmin, ymax, zmin, 2, 0, 0) end if yaxis[:grid] gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid]) - gr_set_transparency(yaxis[:gridalpha]) + gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha]) GR.grid3d(0, ytick, 0, xmin, ymax, zmin, 0, 2, 0) end if zaxis[:grid] gr_set_line(zaxis[:gridlinewidth], zaxis[:gridstyle], zaxis[:foreground_color_grid]) - gr_set_transparency(zaxis[:gridalpha]) + gr_set_transparency(zaxis[:foreground_color_grid], zaxis[:gridalpha]) GR.grid3d(0, 0, ztick, xmin, ymax, zmin, 0, 0, 2) end gr_set_line(1, :solid, xaxis[:foreground_color_axis]) - gr_set_transparency(1) + gr_set_transparency(xaxis[:foreground_color_axis]) GR.axes3d(xtick, 0, ztick, xmin, ymin, zmin, 2, 0, 2, -ticksize) GR.axes3d(0, ytick, 0, xmax, ymin, zmin, 0, 2, 0, ticksize) @@ -1018,24 +1022,24 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) # gr_set_linecolor(sp[:foreground_color_grid]) # GR.grid(xtick, ytick, 0, 0, majorx, majory) gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid]) - gr_set_transparency(xaxis[:gridalpha]) + gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha]) gr_polyline(coords(xgrid_segs)...) end if yaxis[:grid] gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid]) - gr_set_transparency(yaxis[:gridalpha]) + gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha]) gr_polyline(coords(ygrid_segs)...) end if xaxis[:minorgrid] # gr_set_linecolor(sp[:foreground_color_grid]) # GR.grid(xtick, ytick, 0, 0, majorx, majory) gr_set_line(xaxis[:minorgridlinewidth], xaxis[:minorgridstyle], xaxis[:foreground_color_minor_grid]) - gr_set_transparency(xaxis[:minorgridalpha]) + gr_set_transparency(xaxis[:foreground_color_minor_grid], xaxis[:minorgridalpha]) gr_polyline(coords(xminorgrid_segs)...) end if yaxis[:minorgrid] gr_set_line(yaxis[:minorgridlinewidth], yaxis[:minorgridstyle], yaxis[:foreground_color_minor_grid]) - gr_set_transparency(yaxis[:minorgridalpha]) + gr_set_transparency(yaxis[:foreground_color_minor_grid], yaxis[:minorgridalpha]) gr_polyline(coords(yminorgrid_segs)...) end gr_set_transparency(1.0) @@ -1057,7 +1061,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if xaxis[:showaxis] if sp[:framestyle] in (:zerolines, :grid) gr_set_line(1, :solid, xaxis[:foreground_color_grid]) - gr_set_transparency(xaxis[:tick_direction] == :out ? xaxis[:gridalpha] : 0) + gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:tick_direction] == :out ? xaxis[:gridalpha] : 0) else gr_set_line(1, :solid, xaxis[:foreground_color_axis]) end @@ -1067,7 +1071,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if yaxis[:showaxis] if sp[:framestyle] in (:zerolines, :grid) gr_set_line(1, :solid, yaxis[:foreground_color_grid]) - gr_set_transparency(yaxis[:tick_direction] == :out ? yaxis[:gridalpha] : 0) + gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:tick_direction] == :out ? yaxis[:gridalpha] : 0) else gr_set_line(1, :solid, yaxis[:foreground_color_axis]) end @@ -1119,10 +1123,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) intensity = sp[:framestyle] == :semi ? 0.5 : 1.0 if sp[:framestyle] in (:box, :semi) gr_set_line(intensity, :solid, xaxis[:foreground_color_border]) - gr_set_transparency(intensity) + gr_set_transparency(xaxis[:foreground_color_border], intensity) gr_polyline(coords(xborder_segs)...) gr_set_line(intensity, :solid, yaxis[:foreground_color_border]) - gr_set_transparency(intensity) + gr_set_transparency(yaxis[:foreground_color_border], intensity) gr_polyline(coords(yborder_segs)...) end end @@ -1231,10 +1235,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) GR.setfillintstyle(GR.INTSTYLE_SOLID) fr_from, fr_to = (is_2tuple(frng) ? frng : (y, frng)) for (i, rng) in enumerate(segments) - gr_set_fillcolor(get_fillcolor(series, clims, i)) + fc = get_fillcolor(series, clims, i) + gr_set_fillcolor(fc) fx = _cycle(x, vcat(rng, reverse(rng))) fy = vcat(_cycle(fr_from,rng), _cycle(fr_to,reverse(rng))) - gr_set_transparency(get_fillalpha(series, i)) + gr_set_transparency(fc, get_fillalpha(series, i)) GR.fillarea(fx, fy) end end @@ -1242,8 +1247,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) # draw the line(s) if st in (:path, :straightline) for (i, rng) in enumerate(segments) - gr_set_line(get_linewidth(series, i), get_linestyle(series, i), get_linecolor(series, clims, i)) #, series[:linealpha]) - gr_set_transparency(get_linealpha(series, i)) + lc = get_linecolor(series, clims, i) + gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc) #, series[:linealpha]) + gr_set_transparency(lc, get_linealpha(series, i)) arrowside = isa(series[:arrow], Arrow) ? series[:arrow].side : :none gr_polyline(x[rng], y[rng]; arrowside = arrowside) end @@ -1317,8 +1323,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) lz = series[:line_z] segments = iter_segments(series) for (i, rng) in enumerate(segments) - gr_set_line(get_linewidth(series, i), get_linestyle(series, i), get_linecolor(series, clims, i)) #, series[:linealpha]) - gr_set_transparency(get_linealpha(series, i)) + lc = get_linecolor(series, clims, i) + gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc) #, series[:linealpha]) + gr_set_transparency(lc, get_linealpha(series, i)) GR.polyline3d(x[rng], y[rng], z[rng]) end end @@ -1389,13 +1396,15 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) xseg, yseg = x[rng], y[rng] # draw the interior - gr_set_fill(get_fillcolor(series, clims, i)) - gr_set_transparency(get_fillalpha(series, i)) + fc = get_fillcolor(series, clims, i) + gr_set_fill(fc) + gr_set_transparency(fc, get_fillalpha(series, i)) GR.fillarea(xseg, yseg) # draw the shapes - gr_set_line(get_linewidth(series, i), get_linestyle(series, i), get_linecolor(series, clims, i)) - gr_set_transparency(get_linealpha(series, i)) + lc = get_linecolor(series, clims, i) + gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc) + gr_set_transparency(lc, get_linealpha(series, i)) GR.polyline(xseg, yseg) end end @@ -1455,30 +1464,33 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) if sp[:legendtitle] != nothing GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF) gr_set_textcolor(sp[:legendfontcolor]) - gr_set_transparency(1) + gr_set_transparency(sp[:legendfontcolor]) gr_text(xpos - 0.03 + 0.5*w, ypos, string(sp[:legendtitle])) ypos -= dy end for series in series_list(sp) should_add_to_legend(series) || continue st = series[:seriestype] - gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series, clims)) #, series[:linealpha]) + lc = get_linecolor(series, clims) + gr_set_line(get_linewidth(series), get_linestyle(series), lc) #, series[:linealpha]) if (st == :shape || series[:fillrange] != nothing) && series[:ribbon] == nothing - gr_set_fill(get_fillcolor(series, clims)) #, series[:fillalpha]) + fc = get_fillcolor(series, clims) + gr_set_fill(fc) #, series[:fillalpha]) l, r = xpos-0.07, xpos-0.01 b, t = ypos-0.4dy, ypos+0.4dy x = [l, r, r, l, l] y = [b, b, t, t, b] - gr_set_transparency(get_fillalpha(series)) + gr_set_transparency(fc, get_fillalpha(series)) gr_polyline(x, y, GR.fillarea) - gr_set_transparency(get_linealpha(series)) - gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series, clims)) + lc = get_linecolor(series, clims) + gr_set_transparency(lc, get_linealpha(series)) + gr_set_line(get_linewidth(series), get_linestyle(series), lc) st == :shape && gr_polyline(x, y) end if st in (:path, :straightline) - gr_set_transparency(get_linealpha(series)) + gr_set_transparency(lc, get_linealpha(series)) if series[:fillrange] == nothing || series[:ribbon] != nothing GR.polyline([xpos - 0.07, xpos - 0.01], [ypos, ypos]) else From 34cff752f10a082a6ce9f0504ab1ccf363ab543c Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sun, 5 May 2019 13:22:16 +0200 Subject: [PATCH 10/10] missing method for gr_set_transparency --- src/backends/gr.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index e3a543e4..8da4520e 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -81,7 +81,8 @@ gr_set_textcolor(c) = GR.settextcolorind(gr_getcolorind(_cycle(c,1))) gr_set_transparency(α::Real) = GR.settransparency(clamp(α, 0, 1)) gr_set_transparency(::Nothing) = GR.settransparency(1) gr_set_transparency(c, α) = gr_set_transparency(α) -gr_set_transparency(c::Colorant, ::Nothing) = GR.settransparency(alpha(c)) +gr_set_transparency(c::Colorant, ::Nothing) = gr_set_transparency(c) +gr_set_transparency(c::Colorant) = GR.settransparency(alpha(c)) # --------------------------------------------------------------------------------------