r-lib/svglite

Alpha masks treated as luminance masks by certain programs such as Inkscape and Eye of Gnome

trevorld opened this issue · 2 comments

  • I suspect these are probably bugs in the programs and not in {svglite} itself so feel free to close

  • Alpha masked shapes don't render for me in certain programs (such as the default program that open "svg" files on some Linux distributions). I observe that the masked grob isn't visible at all when viewed with:

    • inkscape
    • eog (Eye of Gnome)
  • Alpha masked shapes do render correctly in other programs:

    • google-chrome
    • firefox
  • Here is a simple example of a yellow rectangle with a blue border masked by a holed rectangle:

    library("grid")
    
    x <- c(0.1, 0.9, 0.9, 0.1, 0.1, 0.3, 0.7, 0.7, 0.3, 0.3)
    y <- c(0.1, 0.1, 0.9, 0.9, 0.1, 0.3, 0.3, 0.7, 0.7, 0.3)
    id.lengths <- c(5L, 5L)
    rule <- "evenodd"
    gp <- gpar(fill = "black", lwd = 0L)
    masker <- pathGrob(x, y, id.lengths = id.lengths, rule = "evenodd", gp = gp)
    
    masked <- rectGrob(height = unit(0.7, "npc"),
                       gp = gpar(fill = "yellow", lwd = 4, col = "blue"),
                       vp = viewport(mask = masker))
    svglite::svglite("mask_bug.svg")
    grid.draw(masked)
    dev.off()
    

    In inkscape and eog I just see an empty white page but in google-chrome and firefox I see the masked rectangle.

  • Loosely related issues:

I've opened an issue for inkscape: https://gitlab.com/inkscape/inbox/-/issues/6195

inkscape maintainer says that inkscape currently ignores mask-type:alpha and hence de facto treats the "alpha" mask instead as a "luminance" mask. Since my alpha mask was black it hence rendered invisible. In my use case where I was only using alpha values of 1 using a white filled alpha mask works with either mask case. In the general case for a more robust mask you'd use one whose luminance values match their alpha values:

library("grid")

x <- c(0.1, 0.9, 0.9, 0.1, 0.1, 0.3, 0.7, 0.7, 0.3, 0.3)
y <- c(0.1, 0.1, 0.9, 0.9, 0.1, 0.3, 0.3, 0.7, 0.7, 0.3)
id.lengths <- c(5L, 5L)
rule <- "evenodd"
gp <- gpar(fill = "white", lwd = 0L)
masker <- pathGrob(x, y, id.lengths = id.lengths, rule = "evenodd", gp = gp)

masked <- rectGrob(height = unit(0.7, "npc"),
                   gp = gpar(fill = "yellow", lwd = 4, col = "blue"),
                   vp = viewport(mask = masker))
svglite::svglite("mask_fixed.svg")
grid.draw(masked)
dev.off()

This also works in eog so it must have a similar bug/limitation.