| |
| 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")) |
| } |
| |
| ################################################################################ |
| ## Enforce a clipping path on a viewport |
| grid.newpage() |
| pushViewport(viewport(clip=circleGrob())) |
| grid.rect(gp=gpar(fill="grey")) |
| HersheyLabel("push circle clipping path |
| rect |
| grey circle") |
| |
| ## NORMAL clipping(!) |
| grid.newpage() |
| pushViewport(viewport(width=.5, height=.5, clip=TRUE)) |
| grid.circle(r=.6, gp=gpar(fill="grey")) |
| HersheyLabel("push clipping rect |
| circle |
| squared circle") |
| |
| ## A slightly more complex clipping path |
| grid.newpage() |
| pushViewport(viewport(clip=circleGrob(1:2/3, r=unit(.5, "in")))) |
| grid.rect(gp=gpar(fill="grey")) |
| popViewport() |
| HersheyLabel("push two circles clipping path |
| rect |
| two circles") |
| |
| ## Clip to a polygon |
| grid.newpage() |
| pushViewport(viewport(width=.5, height=.5, |
| clip=polygonGrob(c(.2, .4, .6, .2), c(.2, .6, .4, .1)))) |
| grid.rect(gp=gpar(fill="grey")) |
| popViewport() |
| HersheyLabel("push clipping path |
| rect |
| grey wedge") |
| |
| ## Rotated clip rect! |
| grid.newpage() |
| pushViewport(viewport(width=.5, height=.6, angle=45, clip=rectGrob())) |
| grid.circle(r=.6, gp=gpar(fill="grey")) |
| HersheyLabel("push rotated viewport |
| with clipping path |
| circle |
| square-sided circle") |
| |
| ## Clipping gradient output |
| ## (gradient on viewport) |
| grid.newpage() |
| pushViewport(viewport(clip=circleGrob(1:2/3, r=unit(.5, "in")), |
| gp=gpar(fill=linearGradient()))) |
| grid.rect() |
| popViewport() |
| HersheyLabel("push clipping path |
| gradient on viewport |
| two circles (one gradient)") |
| |
| ## Clipping gradient output |
| ## (gradient on grob) |
| grid.newpage() |
| pushViewport(viewport(clip=circleGrob(1:2/3, r=unit(.5, "in")))) |
| grid.rect(gp=gpar(fill=linearGradient())) |
| popViewport() |
| HersheyLabel("push clipping path |
| rect with gradient |
| two circles (one gradient)") |
| |
| ## Inheriting clipping paths (between viewports) |
| grid.newpage() |
| pushViewport(viewport(clip=circleGrob())) |
| pushViewport(viewport()) |
| grid.rect(gp=gpar(fill="grey")) |
| HersheyLabel("push clipping path |
| push again (inherit clip path) |
| rect |
| grey circle") |
| |
| ## Restoring clipping paths (between viewports) |
| grid.newpage() |
| pushViewport(viewport(clip=circleGrob())) |
| pushViewport(viewport()) |
| pushViewport(viewport()) |
| upViewport() |
| grid.rect(gp=gpar(fill="grey")) |
| HersheyLabel("push clipping path |
| push again (inherit clip path) |
| push again (inherit clip path) |
| up (restore inherited clip path) |
| rect |
| grey circle") |
| |
| ## Revisiting clipping on a viewport |
| ## upViewport() |
| grid.newpage() |
| pushViewport(viewport(clip=circleGrob())) |
| grid.rect(gp=gpar(fill="grey")) |
| upViewport() |
| grid.rect(gp=gpar(fill=rgb(0,0,1,.2))) |
| HersheyLabel("push clipping path |
| grey circle |
| upViewport |
| page all (translucent) blue") |
| |
| ## downViewport() |
| grid.newpage() |
| pushViewport(viewport(clip=circleGrob(), 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 clipping path |
| rounded rect |
| upViewport |
| downViewport |
| blue (translucent) circle") |
| |
| ## clip rect to clip path back to clip rect |
| grid.newpage() |
| pushViewport(viewport(width=.5, height=.5, clip=TRUE)) |
| pushViewport(viewport(clip=circleGrob())) |
| grid.rect(gp=gpar(fill="grey")) |
| upViewport() |
| grid.circle(r=.6, gp=gpar(fill=rgb(0,0,1,.2))) |
| HersheyLabel("push clipping rect |
| push clipping path |
| grey circle |
| upViewport |
| squared (translucent) blue circle") |
| |
| ## clip path to clip rect back to clip path |
| grid.newpage() |
| pushViewport(viewport(clip=circleGrob())) |
| pushViewport(viewport(width=.5, height=.5, clip=TRUE)) |
| grid.circle(r=.6, gp=gpar(fill="grey")) |
| upViewport() |
| grid.rect(gp=gpar(fill=rgb(0,0,1,.2))) |
| HersheyLabel("push clipping path |
| push clipping rect |
| squared circle |
| upViewport |
| grey (translucent) blue circle") |
| |
| ## Clipping path makes the clipping region BIGGER |
| grid.newpage() |
| pushViewport(viewport(width=.5, height=.5, clip=TRUE)) |
| grid.rect() |
| pushViewport(viewport(clip=circleGrob(r=.6))) |
| grid.rect(width=1.2, height=1.2, gp=gpar(fill=rgb(0,0,1,.2))) |
| HersheyLabel("push clip rect (small) |
| rect |
| push clip path (bigger) |
| rect (big) |
| blue (translucent) circle") |
| |
| ## Clipping path makes the clipping region BIGGER |
| ## (even when clipping path contains viewport) |
| grid.newpage() |
| pushViewport(viewport(width=.5, height=.5, clip=TRUE)) |
| grid.rect() |
| pushViewport(viewport(clip=circleGrob(r=.6, vp=viewport()))) |
| grid.rect(width=1.2, height=1.2, gp=gpar(fill=rgb(0,0,1,.2))) |
| HersheyLabel("push clip rect (small) |
| rect |
| push clip path with viewport (bigger) |
| rect (big) |
| blue (translucent) circle") |
| |
| |
| ###################################### |
| ## Replaying the graphics display list |
| |
| ## Resizing device |
| grid.newpage() |
| pushViewport(viewport(clip=circleGrob())) |
| grid.rect(gp=gpar(fill="grey")) |
| HersheyLabel("push clip path |
| rect |
| grey circle |
| (for resizing)") |
| |
| ## Record and replay |
| grid.newpage() |
| pushViewport(viewport(clip=circleGrob())) |
| grid.rect(gp=gpar(fill="grey")) |
| x <- recordPlot() |
| HersheyLabel("push clip path |
| rect |
| grey circle |
| (for recording)") |
| print(x) |
| HersheyLabel("push clip path |
| rect |
| record plot |
| replay plot |
| grey circle") |
| |
| |
| ###################################### |
| ## Test of 'grid' display list |
| |
| ## Grabbing a grob with clipping |
| ## (replaying the 'grid' display list) |
| grid.newpage() |
| pushViewport(viewport(clip=circleGrob())) |
| grid.rect(gp=gpar(fill="grey")) |
| HersheyLabel("push clip path |
| rect |
| grey circle |
| (for grid.grab)") |
| x <- grid.grab() |
| grid.newpage() |
| grid.draw(x) |
| HersheyLabel("push clip path |
| rect |
| grey circle |
| grid.grab |
| grid.draw |
| grey circle") |
| |
| |
| |
| ###################### |
| ## Check for outlawed behaviour |
| ## (clipping and masks are turned off during clipping path resolution) |
| |
| grid.newpage() |
| path <- circleGrob(r=.6, |
| vp=viewport(width=.5, height=.5, clip=TRUE)) |
| pushViewport(viewport(clip=path)) |
| grid.rect(gp=gpar(fill="grey")) |
| popViewport() |
| HersheyLabel("clipping path is circle with viewport with clip=TRUE |
| AND circle is larger than viewport |
| BUT viewport clipping is ignored within clipping path |
| SO clipping path is just circle |
| draw rect |
| result is grey circle") |
| |
| grid.newpage() |
| path <- circleGrob(vp=viewport(clip=rectGrob(width=.8, height=.8))) |
| pushViewport(viewport(clip=path)) |
| grid.rect(gp=gpar(fill="grey")) |
| popViewport() |
| HersheyLabel("clip path is circle with viewport with clip path |
| viewport clip path is rect that squares off the circle |
| BUT clip paths are ignored within clipping path (with warning) |
| SO clipping path is just circle |
| draw rect |
| result is grey circle") |
| |
| grid.newpage() |
| path <- circleGrob(vp=viewport(mask=rectGrob(width=.8, height=.8, |
| gp=gpar(fill="black")))) |
| pushViewport(viewport(clip=path)) |
| grid.rect(gp=gpar(fill="grey")) |
| popViewport() |
| HersheyLabel("clip path is circle with viewport with mask |
| viewport mask is rect that squares off the circle |
| BUT masks are ignored within clipping path (with warning) |
| SO clipping path is just circle |
| draw rect |
| result is grey circle") |
| |
| grid.newpage() |
| path <- circleGrob(vp=viewport(mask=rectGrob(width=.8, height=.8, |
| gp=gpar(fill="black")))) |
| pushViewport(viewport(clip=path, name="test")) |
| upViewport() |
| downViewport("test") |
| grid.rect(gp=gpar(fill="grey")) |
| popViewport() |
| HersheyLabel("same as previous test |
| EXCEPT that push viewport then pop then down |
| (and only push should warn) |
| draw rect |
| result is grey circle") |
| |
| ## A clipping path within a makeContent() method |
| grid.newpage() |
| g <- gTree(cl="test") |
| makeContent.test <- function(x) { |
| setChildren(x, gList(rectGrob(gp=gpar(fill="grey"), |
| vp=viewport(clip=circleGrob())))) |
| } |
| grid.draw(g) |
| HersheyLabel("custom grob class with makeContent() method |
| makeContent() adds rectangle with viewport |
| viewport has circle clip path |
| result is grey circle") |
| |
| ## A clipping path that makes use of makeContent() method |
| grid.newpage() |
| path <- gTree(cl="test") |
| makeContent.test <- function(x) { |
| setChildren(x, gList(circleGrob())) |
| } |
| pushViewport(viewport(clip=path)) |
| grid.rect(gp=gpar(fill="grey")) |
| popViewport() |
| HersheyLabel("push viewport with clip path |
| clip path is grob with makeContent() method |
| makeContent() adds circle |
| draw rect |
| result is grey circle") |
| |
| |
| ## save()/load() a recordedPlot containing a clipping path |
| grid.newpage() |
| pushViewport(viewport(clip=circleGrob())) |
| grid.rect(gp=gpar(fill="grey")) |
| x <- recordPlot() |
| HersheyLabel("push circle clipping path |
| rect |
| grey circle |
| (for save(recordPlot()))") |
| f <- tempfile() |
| saveRDS(x, file=f) |
| grid.newpage() |
| y <- readRDS(f) |
| replayPlot(y) |
| HersheyLabel("push circle clipping path |
| rect |
| grey circle |
| saveRDS(recordPlot()) |
| replayPlot(readRDS())") |
| |
| ################################################################################ |
| ## Clipping paths from text |
| |
| grid.newpage() |
| tg <- textGrob("testing", gp=gpar(fontface="bold", cex=4)) |
| pushViewport(viewport(clip=tg)) |
| grid.rect(gp=gpar(fill="grey")) |
| grid.rect(width=.1, gp=gpar(fill="2")) |
| popViewport() |
| HersheyLabel("clipping path from text |
| grey rect clipped to text |
| thin red rect (black border) also clipped to text", y=.9) |
| |
| grid.newpage() |
| gt <- gTree(children=gList(circleGrob(), |
| textGrob("testing", gp=gpar(fontface="bold", cex=4)), |
| rectGrob(width=.8, height=.5))) |
| pushViewport(viewport(clip=as.path(gt, rule="evenodd"))) |
| grid.rect(gp=gpar(fill="grey")) |
| grid.rect(width=.1, gp=gpar(fill="2")) |
| popViewport() |
| HersheyLabel("clipping path based on circle and text and rect |
| with even-odd rule |
| draw large grey rect and thin red rect |
| both clipped to text and space between circle and rect |
| (PDF will NOT include text in clipping path", y=.85) |
| |
| grid.newpage() |
| gt <- gTree(children=gList(textGrob("testing", gp=gpar(fontface="bold", cex=4)), |
| circleGrob(), |
| rectGrob(width=.8, height=.5))) |
| pushViewport(viewport(clip=as.path(gt, rule="evenodd"))) |
| grid.rect(gp=gpar(fill="grey")) |
| grid.rect(width=.1, gp=gpar(fill="2")) |
| popViewport() |
| HersheyLabel("clipping path based on text and circle and rect |
| with even-odd rule |
| draw large grey rect and thin red rect |
| both clipped to text and space between circle and rect |
| (PDF will ONLY include text in clipping path", y=.85) |
| |
| ###################### |
| ## Check resource exhaustion |
| grid.newpage() |
| for (i in 1:65) { |
| pushViewport(viewport(clip=circleGrob())) |
| grid.rect(gp=gpar(fill="grey")) |
| HersheyLabel(paste0("viewport ", i, " with clip path |
| result is grey circle")) |
| upViewport() |
| } |
| |
| ## Text being clipped by path |
| grid.newpage() |
| grid.text("testing", gp=gpar(col="grey", cex=3)) |
| path <- circleGrob(r=.05, gp=gpar(fill=NA)) |
| grid.draw(path) |
| pushViewport(viewport(clip=path)) |
| grid.text("testing", gp=gpar(cex=3)) |
| popViewport() |
| HersheyLabel("text clipped by circle", y=.8) |
| |
| ## Raster being clipped by path |
| grid.newpage() |
| grid.raster(matrix(c(.5, 1, 1, .5), nrow=2), |
| width=.2, height=.2, |
| interpolate=FALSE) |
| path <- circleGrob(r=.05, gp=gpar(fill=NA)) |
| grid.draw(path) |
| pushViewport(viewport(clip=path)) |
| grid.raster(matrix(c(0:1, 1:0), nrow=2), |
| width=.2, height=.2, |
| interpolate=FALSE) |
| popViewport() |
| HersheyLabel("raster clipped by circle", y=.8) |
| |
| |
| |
| |