[R] Lattice, ggplot, and pointsize

Deepayan Sarkar deepayan.sarkar at r-project.org
Wed Jun 5 16:07:04 CEST 2013

On Sun, May 26, 2013 at 12:47 AM, Milan Bouchet-Valat <nalimilan at club.fr> wrote:
> Le mardi 21 mai 2013 à 21:39 +0100, Prof Brian Ripley a écrit :
>> On 21/05/2013 21:24, Bert Gunter wrote:
>> > At the risk of misunderstanding... (inline)
>> >
>> > On Tue, May 21, 2013 at 12:17 PM, Milan Bouchet-Valat <nalimilan at club.fr> wrote:
>> >> Le mardi 21 mai 2013 à 08:17 -0700, Jeff Newmiller a écrit :
>> >>> That is like complaining that your hammer does not fit these
>> >>> newfangled Philips screws.
>> >>>
>> >>> These are different tools. Do not expect them to interoperate.
>> >> I understand that Lattice and ggplot2 do not use settings from par().
>> >> I'm fine with this, as these packages are different from base graphics
>> >> and have they own equivalent to tweak settings.
>> >>
>> >> What I do not understand is that one argument passed to output devices,
>> >> which are _not_ provided by package graphics, is ignored by these two
>> >> packages. Lattice and ggplot2 do not provide an alternative output
>> >> system,
>> >
>> > False, I believe, depending on what you mean by "output system". They
>> > both use grid graphics, not base graphics and with lattice, anyway,
>> Indeed.  The issue is a design difference between the base and grid
>> graphics subsystems.  See the 'R Internals' manual for more details.
> Thanks for the pointers. Indeed there is some interesting documentation
> there. I've also had a deeper look at the code, and I've traced
> pointsize (called ps) back to the R_GE_gcontext struct in
> src/include/R_ext/GraphicsEngine.h.
> If I understand correctly, base graphics draw text using GText() in
> src/library/graphics/src/graphics.c, which in turn calls GEText() in
> src/main/engine.c. GEText() does take into account the pointsize.
> On the other hand, grid graphics draw text using gridText() from
> src/library/grid/src/grid.c. This function uses gcontextFromgpar() to
> get its R_GE_gcontext object. gcontextFromgpar() (defined in gpar.c)
> computes the pointsize from the fontsize gpar setting and a general
> scaling of the output:
>     /*
>      * Scale by GSS_SCALE (a "zoom" factor)
>      */
>     gc->ps = gpFontSize(gp, i) * REAL(gridStateElement(dd, GSS_SCALE))[0];
> What is interesting is that when a new device gets initialized by grid
> (initGPar() atin gpar.c), the fontsize gpar settings is set to the
> device starting pointsize:
>     REAL(gpfs)[0] = dev->startps;
> And indeed this works with svg():
>> svg("test.svg", pointsize=5)
>> get.gpar("fontsize")
> $fontsize
> [1] 5
> ...but not with Lattice:
>> trellis.par.get("fontsize")
> $text
> [1] 12
> $points
> [1] 8
> So the problem does not appear to be a base vs. grid graphics issue, but
> rather something specific to Lattice and ggplot2. And indeed, when
> looking at Lattice's sources, canonical.theme() in settings.R does:
>              fontsize         = list(text = 12, points = 8),
> As simple as that! I didn't need to look so deep into the code... :-/
> ?trellis.par.set says:
>      The initial settings for each device defaults to values
>      appropriate for that device. In practice, this boils down to three
>      distinct settings, one for screen devices like ‘x11’ and
>      ‘windows’, one for black and white plots (mostly useful for
>      ‘postscript’) and one for color printers (color ‘postcript’,
>      ‘pdf’). [This may not be up-to-date, though...]
> So it does not appear completely absurd to try to adjust to the device
> settings where appropriate. Pointsize seems such a case to me.
> canonical.theme() could set the text font size to get.gpar("fontsize").
> Since the default value is 12 for most devices, this would not change
> anything by default. (ggplot2 could probably benefit from a similar
> change.)

If I remember correctly (it was a long time ago), I had nothing in
particular against the default text fontsize. The default symbol size
in grid was larger than I liked, and so fontsize$points was set to
something more reasonable, and fontsize$text just seemed natural to
add. It is only ever used in a single call to gpar() inside
print.trellis. So it seems perfectly reasonable to take the default of
fontsize$text from grid instead.

I don't like the idea of making the default
'get.gpar("fontsize")$fontsize' though, because that requires a device
to be active, which canonical.theme() doesn't by design. Instead I
have changed the default to NULL, and the fontsize is now set from (in
order of priority)

1. trellis.par.get("fontsize")$text  # NULL by default
2. trellis.par.get("grid.pars")$fontsize # NULL by default
3. get.gpars()$fontsize # approximately device pointsize by default

Hopefully this works for you. You can test using the r-forge version.


> I realize this is no longer a discussion relevant for R as a whole, but
> I am posting it here nevertheless in case somebody was interested. Maybe
> we should discuss this offlist with Deepayan.


More information about the R-help mailing list