Rev 81097 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
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"))}devMask <- function(aMask, lMask) {support <- dev.capabilities()$masksif (is.character(support)) {if ("alpha" %in% support) {aMask} else {if ("luminance" %in% support) {as.mask(lMask, type="luminance")} else {FALSE}}} else {FALSE}}################################################################################## Simple maskmask <- devMask(circleGrob(r=.3, gp=gpar(fill="black")),circleGrob(r=.3, gp=gpar(col="white", fill="white")))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 maskmask <- devMask(circleGrob(r=.3, gp=gpar(fill=NA)),circleGrob(r=.3, gp=gpar(col="white", 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 maskmask <- devMask(circleGrob(x=1:3/4, y=1:3/4, r=.1, gp=gpar(fill="black")),circleGrob(x=1:3/4, y=1:3/4, r=.1, gp=gpar(col="white",fill="white")))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 grobmask <- devMask(circleGrob(gp=gpar(col=NA,fill=radialGradient(c("black","transparent")))),circleGrob(gp=gpar(col=NA,fill=radialGradient(c("white","black")))))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 grobsgrid.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 pathmask <- devMask(gTree(children=gList(rectGrob(gp=gpar(fill="black"))),vp=viewport(clip=circleGrob(r=.4))),gTree(children=gList(rectGrob(gp=gpar(col="white",fill="white"))),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 greymask is full rect with circle clipping pathresult is half width rect with rounded top and bottom", y=.1)## Mask with a maskmask <- devMask(gTree(children=gList(rectGrob(gp=gpar(fill="black"))),vp=viewport(mask=circleGrob(r=.4,gp=gpar(fill="black")))),gTree(children=gList(rectGrob(gp=gpar(col="white",fill="white"))),vp=viewport(mask=as.mask(circleGrob(r=.4,gp=gpar(col="white",fill="white")),type="luminance"))))grid.newpage()pushViewport(viewport(mask=mask))grid.rect(width=.5, gp=gpar(fill="grey"))popViewport()HersheyLabel("rect is half width and filled greymask is full rect with circle maskresult is half width rect with rounded top and bottom", y=.1)## A mask from two grobs, with ONE grob making use of a clipping pathgrid.newpage()mask <- devMask(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")))),gTree(children=gList(rectGrob(x=.25, width=.3, height=.8,gp=gpar(col="white",fill="white"),vp=viewport(clip=circleGrob(r=.4))),rectGrob(x=.75, width=.3, height=.8,gp=gpar(col="white",fill="white")))))pushViewport(viewport(mask=mask))grid.rect(gp=gpar(fill="grey"))popViewport()HersheyLabel("mask is two grobs, ONE with its own (circle) clip pathpush maskrectresult 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 <- devMask(rectGrob(gp=gpar(fill="black"),vp=viewport(width=.5, height=.5, clip=circleGrob())),rectGrob(gp=gpar(col="white", fill="white"),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 maskrectsmall grey circle")## A mask that is equivalent to ...## A clipping path that itself makes use of a rectangular clipping !?grid.newpage()mask <- devMask(circleGrob(r=.6,gp=gpar(fill="black"),vp=viewport(width=.5, height=.5, clip=TRUE)),circleGrob(r=.6,gp=gpar(col="white", fill="white"),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 maskrectgrey squared circle")## Inheriting masks (between viewports)grid.newpage()pushViewport(viewport(mask=devMask(circleGrob(gp=gpar(fill="black")),circleGrob(gp=gpar(col="white",fill="white")))))pushViewport(viewport())grid.rect(gp=gpar(fill="grey"))HersheyLabel("push maskpush again (inherit mask)rectgrey circle")## Restoring masks (between viewports)grid.newpage()pushViewport(viewport(mask=devMask(circleGrob(gp=gpar(fill="black")),circleGrob(gp=gpar(col="white",fill="white")))))pushViewport(viewport())pushViewport(viewport())upViewport()grid.rect(gp=gpar(fill="grey"))HersheyLabel("push maskpush again (inherit mask)push again (inherit mask)up (restore inherited mask)rectgrey circle")## Revisiting mask on a viewport## upViewport()grid.newpage()pushViewport(viewport(mask=devMask(circleGrob(gp=gpar(fill="black")),circleGrob(gp=gpar(col="white",fill="white")))))grid.rect(gp=gpar(fill="grey"))upViewport()grid.rect(gp=gpar(fill=rgb(0,0,1,.2)))HersheyLabel("push maskgrey circleupViewportpage all (translucent) blue")## downViewport()grid.newpage()pushViewport(viewport(mask=devMask(circleGrob(gp=gpar(fill="black")),circleGrob(gp=gpar(col="white",fill="white"))),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 maskrounded rectupViewportdownViewportblue (translucent) circle")######################################## Replaying the graphics display list## Resizing devicegrid.newpage()pushViewport(viewport(mask=devMask(circleGrob(gp=gpar(fill="black")),circleGrob(gp=gpar(col="white",fill="white")))))grid.rect(gp=gpar(fill="grey"))HersheyLabel("push maskrectgrey circle(for resizing)")## Record and replaygrid.newpage()pushViewport(viewport(mask=devMask(circleGrob(gp=gpar(fill="black")),circleGrob(gp=gpar(col="white",fill="white")))))grid.rect(gp=gpar(fill="grey"))x <- recordPlot()HersheyLabel("push maskrectgrey circle(for recording)")print(x)HersheyLabel("push maskrectrecord plotreplay plotgrey circle")######################################## Test of 'grid' display list## Grabbing a grob with mask## (replaying the 'grid' display list)grid.newpage()pushViewport(viewport(mask=devMask(circleGrob(gp=gpar(fill="black")),circleGrob(gp=gpar(col="white",fill="white")))))grid.rect(gp=gpar(fill="grey"))x <- grid.grab()HersheyLabel("push maskrectgrey circle(for grid.grab)")grid.newpage()grid.draw(x)HersheyLabel("push maskrectgrey circlegrid.grabgrid.drawgrey circle")## A mask from two grobs, with ONE grob making use of a maskgrid.newpage()mask <- devMask(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")))),gTree(children=gList(rectGrob(x=.25, width=.3, height=.8,gp=gpar(col="white",fill="white"),vp=viewport(mask=as.mask(circleGrob(r=.4,gp=gpar(col="white", fill="white")),type="luminance"))),rectGrob(x=.75, width=.3, height=.8,gp=gpar(col="white",fill="white")))))pushViewport(viewport(mask=mask))grid.rect(gp=gpar(fill="grey"))popViewport()HersheyLabel("mask is two grobs, ONE with its own (circle) maskpush maskrectresult is one slice of circle and one rectangle")## A mask within a makeContent() methodgrid.newpage()g <- gTree(cl="test")makeContent.test <- function(x) {mask <- devMask(circleGrob(gp=gpar(fill="black")),circleGrob(gp=gpar(col="white", fill="white")))setChildren(x, gList(rectGrob(gp=gpar(fill="grey"),vp=viewport(mask=mask))))}grid.draw(g)HersheyLabel("custom grob class with makeContent() methodmakeContent() adds rectangle with viewportviewport has circle maskresult is grey circle")## A mask that makes use of makeContent() methodgrid.newpage()mask <- devMask(gTree(cl="test"), gTree(cl="testLuminance"))makeContent.test <- function(x) {setChildren(x, gList(circleGrob(gp=gpar(fill="black"))))}makeContent.testLuminance <- function(x) {setChildren(x, gList(circleGrob(gp=gpar(col="white", fill="white"))))}pushViewport(viewport(mask=mask))grid.rect(gp=gpar(fill="grey"))popViewport()HersheyLabel("push viewport with maskmask is grob with makeContent() methodmakeContent() adds circledraw rectresult is grey circle")######################## Check resource exhaustiongrid.newpage()for (i in 1:65) {pushViewport(viewport(mask=devMask(circleGrob(gp=gpar(fill="black")),circleGrob(gp=gpar(col="white",fill="white")))))grid.rect(gp=gpar(fill="grey"))HersheyLabel(paste0("viewport ", i, " with maskresult 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 <- devMask(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))),rectGrob(0:1/2, 0:1/2, width=.5, height=.5,just=c("left", "bottom"),gp=gpar(col="white", fill=grey(1:2/2))))pushViewport(viewport(mask=mask))grid.rect(gp=gpar(fill=pat))## Mask from textgrid.newpage()mask <- devMask(textGrob("test", gp=gpar(cex=10)),textGrob("test", gp=gpar(col="white", cex=10)))pushViewport(viewport(mask=mask))grid.rect(width=.5, height=.5, gp=gpar(fill=linearGradient()))popViewport()HersheyLabel("rect filled with linear gradientmasked by text", y=.8)## Text being maskedgrid.newpage()mask <- devMask(rectGrob(width=.5, height=.5,gp=gpar(fill=linearGradient(c("black","transparent")))),rectGrob(width=.5, height=.5,gp=gpar(fill=linearGradient(c("white","black")))))grid.segments(gp=gpar(col=2, lwd=50))pushViewport(viewport(mask=mask))grid.text("test", gp=gpar(cex=10))popViewport()HersheyLabel("text with maskmask is rect with semitransparent linear gradient", y=.8)## Mask from rastergrid.newpage()mask <- devMask(rasterGrob(matrix(rgb(0,0,0,1:3/4), nrow=1), interpolate=FALSE),rasterGrob(matrix(grey(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 maskmask is semitransparent raster", y=.8)## Raster being maskedgrid.newpage()mask <- devMask(circleGrob(r=.4, gp=gpar(col=NA, fill=rgb(0,0,0,.5))),circleGrob(r=.4, gp=gpar(col=NA, fill=grey(.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 maskmask is semitransparent circle", y=.8)################################################################################## Need to test ...