Skip to content

Issues with recordPlot() and replayPlot() #349

@thomasp85

Description

@thomasp85

Hi

During our work on Positron and the graphics pane there we stumbled upon a peculiarity in tinyplot that may end up affecting how well it is supported in Positron. To give you a bit of background I'll briefly describe how plotting works in Positron:

When you open up the default device in Positron it will, under the hood open up a png() device. This device captures all the plotting that happens, but the rendering it does is not used for anything. Instead, the graphic commands that are sent to it are captured using recordPlot(). Once it is time to show something on the screen, or export a plot, the recorded plot is replayed (using replayPlot() on a graphics device that has been created with the correct dimensions etc. This is also how positron makes sure that plots continue to look good as the plot pane is resized etc.

This approach generally works well. Paul Murrell has done a lot of work to ensure the stability of recordPlot(). However, if the code that produces the plot makes any assumptions about the size/aspect ratio of the graphics device and hard codes this into the calls to graphics functions then the plot will look wrong if it is replayed on a device that doesn't match the dimensions of the device where it was recorded.

I found out that tinyplot does this, at least for the legend placement which means that the distance between the plot and the legend is aspect ratio dependent during replays. The lines responsible for this are

tinyplot/R/draw_legend.R

Lines 299 to 316 in b5240a2

soma = grconvertX(fklgnd$rect$w, to="lines") - grconvertX(0, to="lines")
# Add legend margins to the outer margin
soma = soma + sum(lmar)
## differing outer margin adjustments depending on side
if (outer_right) {
ooma[4] = soma
} else {
ooma[2] = soma
}
par(oma = ooma)
# determine legend inset
inset = grconvertX(lmar[1], from="lines", to="npc") - grconvertX(0, from = "lines", to = "npc")
if (isFALSE(outer_right)) {
# extra space needed for "left!" b/c of lhs inner margin
inset_bump = grconvertX(par("mar")[2], from = "lines", to = "npc") - grconvertX(0, from = "lines", to = "npc")
inset = inset + inset_bump
}

At least based on my understanding of the source code. There may be other places where this happens but the legend placement was by far what was most apparent.

I'm afraid that my poor understanding of the tinyplot codebase means that I can't provide a good fix for this. Perhaps wrapping it all in recordGraphics() will be enough.

I hope this report is useful

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions