| |
| library(grid) |
| |
| HersheyLabel <- function(x, y=unit(.5, "npc")) { |
| lines <- strsplit(x, "\n")[[1]] |
| if (!is.unit(y)) |
| y <- unit(y, "npc") |
| n <- length(lines) |
| if (n > 1) { |
| y <- y + unit(rev(seq(n)) - mean(seq(n)), "lines") |
| } |
| grid.text(lines, y=y, gp=gpar(fontfamily="HersheySans")) |
| } |
| |
| ################################################################################ |
| |
| ## Simple mask |
| mask <- circleGrob(r=.3, gp=gpar(fill="black")) |
| grid.newpage() |
| pushViewport(viewport(mask=mask)) |
| grid.rect(width=.5, gp=gpar(fill="black")) |
| popViewport() |
| HersheyLabel("solid black rectangle with circle mask", y=.1) |
| |
| ## VERY thin mask |
| mask <- circleGrob(r=.3, gp=gpar(fill=NA)) |
| grid.newpage() |
| pushViewport(viewport(mask=mask)) |
| grid.rect(width=.5, gp=gpar(fill="black")) |
| popViewport() |
| HersheyLabel("solid black rectangle with circle BORDER mask", y=.1) |
| |
| ## Multiple grobs mask |
| mask <- circleGrob(x=1:3/4, y=1:3/4, r=.1, gp=gpar(fill="black")) |
| grid.newpage() |
| pushViewport(viewport(mask=mask)) |
| grid.rect(width=.5, gp=gpar(fill="black")) |
| popViewport() |
| HersheyLabel("solid black rectangle with three-circle mask", y=.1) |
| |
| ## Mask with gradient on single grob |
| mask <- circleGrob(gp=gpar(col=NA, |
| fill=radialGradient(c("black", "transparent")))) |
| grid.newpage() |
| pushViewport(viewport(mask=mask)) |
| grid.rect(width=.5, gp=gpar(fill="black")) |
| popViewport() |
| HersheyLabel("solid black rectangle with radial gradient mask", y=.1) |
| |
| ## Mask with gradient on multiple grobs |
| grid.newpage() |
| pushViewport(viewport(mask=mask)) |
| grid.rect(x=1:2/3, width=.2, gp=gpar(fill="black")) |
| popViewport() |
| HersheyLabel("two solid black rectangles with radial gradient mask", y=.1) |
| |
| ## Mask with clipping path |
| mask <- gTree(children=gList(rectGrob(gp=gpar(fill="black"))), |
| vp=viewport(clip=circleGrob(r=.4))) |
| grid.newpage() |
| pushViewport(viewport(mask=mask)) |
| grid.rect(width=.5, gp=gpar(fill="grey")) |
| popViewport() |
| HersheyLabel("rect is half width and filled grey |
| mask is full rect with circle clipping path |
| result is half width rect with rounded top and bottom", y=.1) |
| |
| ## Mask with a mask |
| mask <- gTree(children=gList(rectGrob(gp=gpar(fill="black"))), |
| vp=viewport(mask=circleGrob(r=.4, gp=gpar(fill="black")))) |
| grid.newpage() |
| pushViewport(viewport(mask=mask)) |
| grid.rect(width=.5, gp=gpar(fill="grey")) |
| popViewport() |
| HersheyLabel("rect is half width and filled grey |
| mask is full rect with circle mask |
| result is half width rect with rounded top and bottom", y=.1) |
| |
| ## A mask from two grobs, with ONE grob making use of a clipping path |
| grid.newpage() |
| mask <- gTree(children=gList(rectGrob(x=.25, width=.3, height=.8, |
| gp=gpar(fill="black"), |
| vp=viewport(clip=circleGrob(r=.4))), |
| rectGrob(x=.75, width=.3, height=.8, |
| gp=gpar(fill="black")))) |
| pushViewport(viewport(mask=mask)) |
| grid.rect(gp=gpar(fill="grey")) |
| popViewport() |
| HersheyLabel("mask is two grobs, ONE with its own (circle) clip path |
| push mask |
| rect |
| result is one slice of circle and one rectangle") |
| |
| ## A mask that is equivalent to ... |
| ## A clipping path that itself makes use of a clipping path !? |
| grid.newpage() |
| mask <- rectGrob(gp=gpar(fill="black"), |
| vp=viewport(width=.5, height=.5, clip=circleGrob())) |
| pushViewport(viewport(mask=mask)) |
| grid.rect(gp=gpar(fill="grey")) |
| HersheyLabel("mask includes clip path |
| (clip path is circle) |
| push mask |
| rect |
| small grey circle") |
| |
| ## A mask that is equivalent to ... |
| ## A clipping path that itself makes use of a rectangular clipping !? |
| grid.newpage() |
| mask <- circleGrob(r=.6, |
| gp=gpar(fill="black"), |
| vp=viewport(width=.5, height=.5, clip=TRUE)) |
| pushViewport(viewport(mask=mask)) |
| grid.rect(gp=gpar(fill="grey")) |
| HersheyLabel("mask includes clip rect |
| (mask is squared circle) |
| push mask |
| rect |
| grey squared circle") |
| |
| ## Inheriting masks (between viewports) |
| grid.newpage() |
| pushViewport(viewport(mask=circleGrob(gp=gpar(fill="black")))) |
| pushViewport(viewport()) |
| grid.rect(gp=gpar(fill="grey")) |
| HersheyLabel("push mask |
| push again (inherit mask) |
| rect |
| grey circle") |
| |
| ## Restoring masks (between viewports) |
| grid.newpage() |
| pushViewport(viewport(mask=circleGrob(gp=gpar(fill="black")))) |
| pushViewport(viewport()) |
| pushViewport(viewport()) |
| upViewport() |
| grid.rect(gp=gpar(fill="grey")) |
| HersheyLabel("push mask |
| push again (inherit mask) |
| push again (inherit mask) |
| up (restore inherited mask) |
| rect |
| grey circle") |
| |
| ## Revisiting mask on a viewport |
| ## upViewport() |
| grid.newpage() |
| pushViewport(viewport(mask=circleGrob(gp=gpar(fill="black")))) |
| grid.rect(gp=gpar(fill="grey")) |
| upViewport() |
| grid.rect(gp=gpar(fill=rgb(0,0,1,.2))) |
| HersheyLabel("push mask |
| grey circle |
| upViewport |
| page all (translucent) blue") |
| |
| ## downViewport() |
| grid.newpage() |
| pushViewport(viewport(mask=circleGrob(gp=gpar(fill="black")), name="vp")) |
| grid.rect(height=.5, gp=gpar(fill="grey")) |
| upViewport() |
| downViewport("vp") |
| grid.rect(gp=gpar(fill=rgb(0,0,1,.2))) |
| HersheyLabel("push mask |
| rounded rect |
| upViewport |
| downViewport |
| blue (translucent) circle") |
| |
| ###################################### |
| ## Replaying the graphics display list |
| |
| ## Resizing device |
| grid.newpage() |
| pushViewport(viewport(mask=circleGrob(gp=gpar(fill="black")))) |
| grid.rect(gp=gpar(fill="grey")) |
| HersheyLabel("push mask |
| rect |
| grey circle |
| (for resizing)") |
| |
| ## Record and replay |
| grid.newpage() |
| pushViewport(viewport(mask=circleGrob(gp=gpar(fill="black")))) |
| grid.rect(gp=gpar(fill="grey")) |
| x <- recordPlot() |
| HersheyLabel("push mask |
| rect |
| grey circle |
| (for recording)") |
| print(x) |
| HersheyLabel("push mask |
| rect |
| record plot |
| replay plot |
| grey circle") |
| |
| ###################################### |
| ## Test of 'grid' display list |
| |
| ## Grabbing a grob with mask |
| ## (replaying the 'grid' display list) |
| grid.newpage() |
| pushViewport(viewport(mask=circleGrob(gp=gpar(fill="black")))) |
| grid.rect(gp=gpar(fill="grey")) |
| x <- grid.grab() |
| HersheyLabel("push mask |
| rect |
| grey circle |
| (for grid.grab)") |
| grid.newpage() |
| grid.draw(x) |
| HersheyLabel("push mask |
| rect |
| grey circle |
| grid.grab |
| grid.draw |
| grey circle") |
| |
| ## A mask from two grobs, with ONE grob making use of a mask |
| grid.newpage() |
| mask <- gTree(children=gList(rectGrob(x=.25, width=.3, height=.8, |
| gp=gpar(fill="black"), |
| vp=viewport(mask=circleGrob(r=.4, |
| gp=gpar(fill="black")))), |
| rectGrob(x=.75, width=.3, height=.8, |
| gp=gpar(fill="black")))) |
| pushViewport(viewport(mask=mask)) |
| grid.rect(gp=gpar(fill="grey")) |
| popViewport() |
| HersheyLabel("mask is two grobs, ONE with its own (circle) mask |
| push mask |
| rect |
| result is one slice of circle and one rectangle") |
| |
| ## A mask within a makeContent() method |
| grid.newpage() |
| g <- gTree(cl="test") |
| makeContent.test <- function(x) { |
| setChildren(x, gList(rectGrob(gp=gpar(fill="grey"), |
| vp=viewport(mask=circleGrob(gp=gpar(fill="black")))))) |
| } |
| grid.draw(g) |
| HersheyLabel("custom grob class with makeContent() method |
| makeContent() adds rectangle with viewport |
| viewport has circle mask |
| result is grey circle") |
| |
| ## A mask that makes use of makeContent() method |
| grid.newpage() |
| mask <- gTree(cl="test") |
| makeContent.test <- function(x) { |
| setChildren(x, gList(circleGrob(gp=gpar(fill="black")))) |
| } |
| pushViewport(viewport(mask=mask)) |
| grid.rect(gp=gpar(fill="grey")) |
| popViewport() |
| HersheyLabel("push viewport with mask |
| mask is grob with makeContent() method |
| makeContent() adds circle |
| draw rect |
| result is grey circle") |
| |
| ###################### |
| ## Check resource exhaustion |
| grid.newpage() |
| for (i in 1:65) { |
| pushViewport(viewport(mask=circleGrob(gp=gpar(fill="black")))) |
| grid.rect(gp=gpar(fill="grey")) |
| HersheyLabel(paste0("viewport ", i, " with mask |
| result is grey circle")) |
| popViewport() |
| } |
| |
| ## Bug from 4.1.0 (mask should NOT be applied to pattern) |
| grid.newpage() |
| pat <- pattern(circleGrob(r=.1), |
| width=.17, height=.17, |
| extend="repeat") |
| mask <- rectGrob(0:1/2, 0:1/2, width=.5, height=.5, |
| just=c("left", "bottom"), |
| gp=gpar(fill=rgb(0,0,0,1:2/2))) |
| pushViewport(viewport(mask=mask)) |
| grid.rect(gp=gpar(fill=pat)) |
| |
| ## Mask from text |
| grid.newpage() |
| mask <- textGrob("test", gp=gpar(cex=10)) |
| pushViewport(viewport(mask=mask)) |
| grid.rect(width=.5, height=.5, gp=gpar(fill=linearGradient())) |
| popViewport() |
| HersheyLabel("rect filled with linear gradient |
| masked by text", y=.8) |
| |
| ## Text being masked |
| grid.newpage() |
| mask <- rectGrob(width=.5, height=.5, |
| gp=gpar(fill=linearGradient(c("black", "transparent")))) |
| grid.segments(gp=gpar(col=2, lwd=50)) |
| pushViewport(viewport(mask=mask)) |
| grid.text("test", gp=gpar(cex=10)) |
| popViewport() |
| HersheyLabel("text with mask |
| mask is rect with semitransparent linear gradient", y=.8) |
| |
| ## Mask from raster |
| grid.newpage() |
| mask <- rasterGrob(matrix(rgb(0,0,0,1:3/4), nrow=1), interpolate=FALSE) |
| grid.segments(gp=gpar(col=2, lwd=100)) |
| pushViewport(viewport(mask=mask)) |
| grid.circle(r=.4, gp=gpar(fill="black")) |
| popViewport() |
| HersheyLabel("circle with mask |
| mask is semitransparent raster", y=.8) |
| |
| ## Raster being masked |
| grid.newpage() |
| mask <- circleGrob(r=.4, gp=gpar(col=NA, fill=rgb(0,0,0,.5))) |
| grid.segments(gp=gpar(col=2, lwd=100)) |
| pushViewport(viewport(mask=mask)) |
| grid.raster(matrix(1:3/4, nrow=1), interpolate=FALSE) |
| popViewport() |
| HersheyLabel("raster with mask |
| mask is semitransparent circle", y=.8) |
| |
| |
| ################################################################################ |
| ## Need to test ... |
| |