Updating Graphics Devices for R 4.2.0

A number of new graphics features have been added to the R graphics engine in the development version of R (to become version 4.2.0):
groups, compositing operators, affine transformations, stroking and filling paths, and luminance masks. This has consequences for R packages that provide graphics devices, like the ‘ragg’ package.

For users of R packages that provide graphics devices, those packages will need to be reinstalled when updating to R 4.2.0.

For the maintainers of R packages that provide graphics devices, this document describes the changes that are necessary to update a graphics device package in preparation for R 4.2.0.

All an R user should need to know is to reinstall graphics device packages; the rest of this document is more technical and aimed at R developers who maintain graphics device packages.

Option 1

The first option is easy: do nothing.

With the addition of the deviceVersion for graphics devices, the graphics engine is able to detect that a graphics device has not been updated and it will not ask a device to do things that it does not support.

The only problem that should occur is if the graphics device package is not reinstalled, and the package uses R_GE_checkVersionOrDie(), then the package will fail with a “version mismatch” error. The solution in that case will be to reinstall the graphics device.

Option 2

The second option is also relatively easy: do almost nothing.

This option involves updating the graphics device package to set the deviceVersion to 15 (R_GE_group), but without providing support for any of the new features.

The new graphics engine version requires that the graphics device provides the following new device callbacks:

  • defineGroup()
  • useGroup()
  • releaseGroup()
  • stroke()
  • fill()
  • fillStroke()
  • capabilities()

In each case, it is possible to provide a stub that does nothing. The graphics engine will call the device, but there will just be no output produced.

The postscript() graphics device provides a template for this approach. A graphics device package can model its device callbacks on functions like PS_defineGroup() in devPS.c.

A more ambitious variant of this option is to provide support for just a subset of the new features; that is also a less ambitious variant of the next option …

Option 3

This option is a lot harder: add support for the new features.

For some graphics devices, this will not be an option because the language or library underlying the graphics device does not support the new features. The xfig() device is an example.

Where it is possible to add support, the purpose of each of the new device callbacks is (briefly):

  • defineGroup(source, op, destination) should run the R function destination, set the compositing operator op, then run the R function source, recording all drawing that occurs as a result off-screen, and return a reference to the recorded drawing.
  • useGroup(ref, trans) should apply the transformation matrix trans and render the recorded drawing referenced by ref.
  • releaseGroup(ref) can release resources associated with the recorded drawing referenced by ref.
  • stroke(path) should run the R function path, recording all drawing as a path, then stroke the path.
  • fill(path, rule) should run the R function path, recording all drawing as a path, then fill the path using the fill rule.
  • fillStroke(path, rule) should run the R function path, recording all drawing as a path, then fill and stroke the path using the fill rule.
  • capabilities(capabilities) should modify components of the list capabilities to indicate the level of support provided by the device.

The pdf() device and the devices based on the Cairo graphics library, e.g., png(type="cairo") and svg(), provide exemplars of devices that have implemented support for the new features. See, for example, PDF_defineGroup() in devPS.c and Cairo_DefineGroup() in cairoFns.c.

The “Graphics Devices” Section of the “R Internals” Manual also contains some more detailed information, particularly about the capabilities() device callback.

Further discussion and more detail about the new features and how they have been implemented can be found in a series of technical reports: one on groups, one on paths, and one on masks.