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")) } ################################################################################ ## Paths that produce same result as normal drawing grid.newpage() grid.stroke(circleGrob()) HersheyLabel("Single circle stroked same as normal drawing") grid.newpage() grid.stroke(circleGrob(1:2/3, r=.3)) HersheyLabel("Two overlapping circles stroked same as normal drawing") grid.newpage() grid.stroke(circleGrob(1:2/3, r=.1)) HersheyLabel("Two distinct circles stroked same as normal drawing") grid.newpage() grid.fillStroke(circleGrob(1:2/3, r=.3), gp=gpar(col=NA, fill="grey")) HersheyLabel("Two overlapping circles filled ONLY non-zero winding rule same as normal drawing") grid.newpage() grid.fillStroke(circleGrob(1:2/3, r=.3), gp=gpar(fill="grey")) HersheyLabel("Two overlapping circles filled and stroked non-zero winding rule same as normal drawing") grid.newpage() grid.fillStroke(circleGrob(r=c(.1, .3)), gp=gpar(fill="grey")) HersheyLabel("Two nested circles stroked and filled non-zero winding rule same as normal drawing") ################################################################################ ## Paths that produce DIFFERENT result compared to normal drawing grid.newpage() grid.stroke(circleGrob(gp=gpar(fill="grey"))) HersheyLabel("Filled circle stroked NO fill!") grid.newpage() grid.fill(circleGrob(1:2/3, r=.3), gp=gpar(fill="grey")) HersheyLabel("Two overlapping circles filled non-zero winding rule NO stroke!") grid.newpage() grid.segments(gp=gpar(lwd=10, col=4)) grid.fill(circleGrob(1:2/3, r=.3), gp=gpar(fill=rgb(1,0,0,.5))) HersheyLabel("Two overlapping circles filled non-zero winding rule semitransparent fill NO overlap!") grid.newpage() grid.fill(circleGrob(1:2/3, r=.3), gp=gpar(fill="grey"), rule="evenodd") HersheyLabel("Two overlapping circles filled even-odd rule get a HOLE!") grid.newpage() grid.fillStroke(circleGrob(1:2/3, r=.3), gp=gpar(fill="grey"), rule="evenodd") HersheyLabel("Two overlapping circles stroked and filled even-odd rule get a HOLE!") grid.newpage() grid.fillStroke(circleGrob(r=c(.1, .3)), gp=gpar(fill="grey"), rule="evenodd") HersheyLabel("Two nested circles stroked and filled even-odd rule get a HOLE!") grid.newpage() grid.fillStroke(polylineGrob(c(.2, .5, .8), c(.2, .8, .2)), gp=gpar(lwd=5, fill="grey")) HersheyLabel("Polyline (open) stroked and filled get filled region (even though not closed)") grid.newpage() pushViewport(viewport(clip=as.path(circleGrob(r=c(.3, .1)), rule="evenodd"))) grid.rect(gp=gpar(fill="grey")) HersheyLabel("Clipping path is nested circles even-odd rule clip filled rect get donut", y=.7) grid.newpage() grid.stroke(textGrob("testing", gp=gpar(fontface="bold", cex=4))) HersheyLabel("Path based on text stroke produces glyph outlines", y=.8) grid.newpage() gt <- gTree(children=gList(circleGrob(), textGrob("testing", gp=gpar(fontface="bold", cex=4)), rectGrob(width=.8, height=.5))) grid.fillStroke(gt, gp=gpar(fill="grey"), rule="evenodd") HersheyLabel("Path based on circle and text and rect stroked and filled with even-odd rule all outlines and glyphs stroked and glyphs filled and space between circle and rect filled (PDF will NOT draw text)", y=.85) grid.newpage() gt <- gTree(children=gList(textGrob("testing", gp=gpar(fontface="bold", cex=4)), circleGrob(), rectGrob(width=.8, height=.5))) grid.fillStroke(gt, gp=gpar(fill="grey"), rule="evenodd") HersheyLabel("Path based on text and circle and rect stroked and filled with even-odd rule all outlines and glyphs stroked and glyphs filled and space between circle and rect filled (PDF will ONLY draw text)", y=.85) grid.newpage() grid.fill(pathGrob(c(.2, .2, .8, .8, .4, .4, .6, .6), c(.2, .8, .8, .2, .4, .6, .6, .4), id.lengths=c(4, 4), rule="winding"), gp=gpar(fill="grey")) HersheyLabel("Path based on pathGrob same fill rule for both (winding) no hole") grid.newpage() grid.fill(pathGrob(c(.2, .2, .8, .8, .4, .4, .6, .6), c(.2, .8, .8, .2, .4, .6, .6, .4), id.lengths=c(4, 4), rule="winding"), rule="evenodd", gp=gpar(fill="grey")) HersheyLabel("Path based on pathGrob DIFFERENT fill rules (grobPath has winding but path has even-odd) get a hole!") ## Gradient in path grid.newpage() grad <- linearGradient(y1=.5, y2=.5) grid.fill(circleGrob(1:2/3, r=.1), gp=gpar(fill=grad)) HersheyLabel("path (two circles) with gradient fill gradient relative to circle bounds (black at left to white at right)", y=.8) ## Pattern in path grid.newpage() rects <- gTree(children=gList(rectGrob(width=unit(5, "mm"), height=unit(5, "mm"), just=c("left", "bottom"), gp=gpar(fill="black")), rectGrob(width=unit(5, "mm"), height=unit(5, "mm"), just=c("right", "top"), gp=gpar(fill="black")))) checkerBoard <- pattern(rects, width=unit(1, "cm"), height=unit(1, "cm"), extend="repeat") grid.fill(circleGrob(1:2/3, r=.1), gp=gpar(fill=checkerBoard)) HersheyLabel("path (two circles) with pattern fill", y=.8) ## Path that is clipped grid.newpage() pushViewport(viewport(clip=circleGrob(r=.2))) grid.fill(circleGrob(1:2/3, r=.1), gp=gpar(fill="grey")) popViewport() HersheyLabel("filled path (two circles) clipped by circle path result is two half-moons", .8) ## path that is masked grid.newpage() pushViewport(viewport(mask=circleGrob(r=.2, gp=gpar(fill="black")))) grid.fill(circleGrob(1:2/3, r=.1), gp=gpar(fill="grey")) popViewport() HersheyLabel("filled path (two circles) masked by filled circle result is two half-moons", .8) ## raster-based pattern in path grid.newpage() checkerBoard <- pattern(rasterGrob(matrix(c(0:1, 1:0), nrow=2), width=.2, height=.2, interpolate=FALSE), width=.2, height=.2, extend="repeat") grid.fill(circleGrob(1:2/3, r=.1), gp=gpar(fill=checkerBoard)) HersheyLabel("path (two circles) with pattern fill pattern is (repeated) raster (pattern size/shape relative to circle bbox)", y=.8) ################################################################################ ## TODO notrun <- function() { ## UTF8 text in path } ## notrun()