blob: 6eabc6bee54a4bbd29e68610700258b32c9b0fae [file] [log] [blame]
# File src/library/grid/R/roundrect.R
# Part of the R package, https://www.R-project.org
#
# Copyright (C) 1995-2016 The R Core Team
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# A copy of the GNU General Public License is available at
# https://www.R-project.org/Licenses/
# Good idea to choose r as absolute unit or "snpc"
roundrectGrob <- function(x=0.5, y=0.5, width=1, height=1,
default.units="npc",
r=unit(0.1, "snpc"),
just="centre",
name=NULL, gp=NULL, vp=NULL) {
if (!is.unit(x))
x <- unit(x, default.units)
if (!is.unit(y))
y <- unit(y, default.units)
if (!is.unit(width))
width <- unit(width, default.units)
if (!is.unit(height))
height <- unit(height, default.units)
grob(x=x, y=y, width=width, height=height, r=r, just=just,
name=name, gp=gp, vp=vp, cl="roundrect")
}
grid.roundrect <- function(...) {
grid.draw(roundrectGrob(...))
}
validDetails.roundrect <- function(x) {
if (!is.unit(x$x) ||
!is.unit(x$y) ||
!is.unit(x$width) ||
!is.unit(x$height))
stop("'x', 'y', 'width', and 'height' must be units")
if (!is.unit(x$r))
stop("'r' must be a 'unit' object")
valid.just(x$just)
# Make sure that x and y are of length 1
if (length(x$x) != 1 | length(x$y) != 1 |
length(x$width) != 1 | length(x$height) != 1)
stop("'x', 'y', 'width', and 'height' must have length 1")
x
}
makeContext.roundrect <- function(x) {
rrvp <- viewport(x$x, x$y, x$width, x$height, just=x$just,
name="rrvp")
if (!is.null(x$vp)) {
x$vp <- vpStack(x$vp, rrvp)
} else {
x$vp <- rrvp
}
x
}
# x, y, is the real corner
roundCorner <- function(num, x, y, r) {
n <- 10*4
t <- seq(0, 2*pi, length.out=n)
cost <- cos(t)
sint <- sin(t)
if (num == 1) {
xc <- x + r
yc <- y + r
subset <- (n/2):(3*n/4)
} else if (num == 2) {
xc <- x + r
yc <- y - r
subset <- (n/4):(n/2)
} else if (num == 3) {
xc <- x - r
yc <- y - r
subset <- 1L:(n/4)
} else if (num == 4) {
xc <- x - r
yc <- y + r
subset <- (3*n/4):n
}
list(x=xc + (cost*r)[subset], y=yc + (sint*r)[subset])
}
rrpoints <- function(x) {
left <- 0
bottom <- 0
right <- convertX(unit(1, "npc"), "inches", valueOnly=TRUE)
top <- convertY(unit(1, "npc"), "inches", valueOnly=TRUE)
r <- min(convertWidth(x$r, "inches", valueOnly=TRUE),
convertHeight(x$r, "inches", valueOnly=TRUE))
corner1 <- roundCorner(1, left, bottom, r)
corner2 <- roundCorner(2, left, top, r)
corner3 <- roundCorner(3, right, top, r)
corner4 <- roundCorner(4, right, bottom, r)
xx <- unit(c(left + r, right - r, corner4$x,
right, right, corner3$x,
right - r, left + r, corner2$x,
left, left, corner1$x),
"inches")
yy <- unit(c(bottom, bottom, corner4$y,
bottom + r, top - r, corner3$y,
top, top, corner2$y,
top - r, bottom + r, corner1$y),
"inches")
list(x=xx, y=yy)
}
makeContent.roundrect <- function(x) {
boundary <- rrpoints(x)
polygonGrob(boundary$x, boundary$y,
name=x$name, gp=x$gp, vp=x$vp)
}
xDetails.roundrect <- function(x, theta) {
boundary <- rrpoints(x)
bounds <- grid.Call(C_locnBounds, boundary$x, boundary$y, theta)
if (is.null(bounds))
unit(0.5, "npc")
else
unit(bounds[1L], "inches")
}
yDetails.roundrect <- function(x, theta) {
boundary <- rrpoints(x)
bounds <- grid.Call(C_locnBounds, boundary$x, boundary$y, theta)
if (is.null(bounds))
unit(0.5, "npc")
else
unit(bounds[2L], "inches")
}
widthDetails.roundrect <- function(x) {
boundary <- rrpoints(x)
bounds <- grid.Call(C_locnBounds, boundary$x, boundary$y, 0)
if (is.null(bounds))
unit(0, "inches")
else
unit(bounds[3L], "inches")
}
heightDetails.roundrect <- function(x) {
boundary <- rrpoints(x)
bounds <- grid.Call(C_locnBounds, boundary$x, boundary$y, 0)
if (is.null(bounds))
unit(0, "inches")
else
unit(bounds[4L], "inches")
}