diff --git a/.Rbuildignore b/.Rbuildignore index 90bb697..e309982 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -2,3 +2,4 @@ ^\.Rproj\.user$ ^LICENSE\.md$ ^\.github$ +^CODEOWNERS$ diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..663f8d1 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @matt-dray diff --git a/DESCRIPTION b/DESCRIPTION index 526f948..dcae902 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,10 +1,10 @@ Package: hexbase Title: Create Simple Dependency-Free Hex Logos -Version: 0.0.0.9000 +Version: 0.1.0 Authors@R: person("Matt", "Dray", , "mwdray@gmail.com", role = c("aut", "cre")) Description: A simple interface to create hexagon-shaped logos that help - promote your R package or other projects. Uses only base R. + promote your R package or other projects. Uses base R only. License: MIT + file LICENSE URL: https://github.com/matt-dray/hexbase BugReports: https://github.com/matt-dray/hexbase/bugs @@ -12,7 +12,7 @@ Imports: grDevices, grid Suggests: - testthat (>= 3.0.0) + png Config/testthat/edition: 3 Encoding: UTF-8 Issues: https://github.com/matt-dray/hexbase diff --git a/NAMESPACE b/NAMESPACE index 3354d06..7340d38 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,3 +1,7 @@ # Generated by roxygen2: do not edit by hand -export(make_hex) +export(add_hex) +export(add_image) +export(add_text) +export(close_device) +export(open_device) diff --git a/NEWS.md b/NEWS.md index 3510460..bc230bc 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,5 @@ -# hexbase 0.0.0.9000 +# hexbase 0.1.0 -* Created package and added README, NEWS, LICENSE, initial functions to `make_hex()`. +* Created package and added boilerplate. +* Added `*_device()` and `add_*()` functions for building hex stickers. +* Added basic example to the README. diff --git a/R/coords.R b/R/coords.R deleted file mode 100644 index 9deb31c..0000000 --- a/R/coords.R +++ /dev/null @@ -1,37 +0,0 @@ -.get_hex_coords <- function(d = 1) { - a <- d / 2 - b <- sqrt(3) * a - list( - x = c(-b, 0, b, b, 0, -b), - y = c(-a, -2 * a, -a, a, 2 * a, a) - ) -} - -.scale_outer_coords <- function(outer_coord_val) { - num <- outer_coord_val - min(outer_coord_val) - dem <- max(outer_coord_val) - min(outer_coord_val) - num / dem -} - -.get_inner_hex_coords_scaled <- function(coords_inner, coords_outer) { - - coords_inner_scaled <- vector("list", length = length(coords_inner)) - names(coords_inner_scaled) <- c("x", "y") - - for (i in seq_along(coords_inner)) { - coords_inner_scaled[[i]] <- .scale_inner_coords( - coords_inner[[i]], - min(coords_outer[[i]]), - max(coords_outer[[i]]) - ) - } - - coords_inner_scaled - -} - -.scale_inner_coords <- function(inner_val, outer_val_min, outer_val_max) { - num <- inner_val - pmin(min(inner_val), outer_val_min) - dem <- pmax(max(inner_val), outer_val_max) - pmin(min(inner_val), outer_val_min) - num / dem -} diff --git a/R/grobs.R b/R/grobs.R deleted file mode 100644 index 26f2fc4..0000000 --- a/R/grobs.R +++ /dev/null @@ -1,29 +0,0 @@ -#' Create Graphics Object: Hexagon -#' @param coords List. Coordinates to draw polygon. Elements named `x` and `y`. -#' @param fill_col Character. Named or hexadecimal colour. -#' @noRd -.engrob_hex <- function(coords, fill_col) { - grid::polygonGrob( - coords[["x"]], - coords[["y"]], - gp = grid::gpar(fill = fill_col) - ) -} - -#' Create Graphics Object: Text -#' @param txt_string Character. Text to print on hex. -#' @param txt_col Character. Named or hexadecimal colour. -#' @param txt_size Numeric. Point size of text. -#' @param txt_font Character. Font family for text. Must exist on system. -#' @noRd -.engrob_text <- function(txt_string, txt_col, txt_size, txt_font) { - grid::textGrob( - txt_string, - gp = grid::gpar( - col = txt_col, - fontsize = txt_size, - fontfamily = txt_font, - lineheight = 0.75 - ) - ) -} diff --git a/R/hexagon.R b/R/hexagon.R index 984f282..3886ef7 100644 --- a/R/hexagon.R +++ b/R/hexagon.R @@ -1,51 +1,173 @@ -#' Write a Hex Sticker to File +#' Open a Device #' -#' Generate a simple hexagon-shaped sticker design with a border, image and -#' text. +#' Begin a PNG plot device with dimensions matching +#' [the Stickers Standard](https://sticker.how/#type-hexagon): 4.39 cm wide by +#' 5.08 cm high (2 by 1.73 inches). #' #' @param file_path Character. Full file path to a .png where the output file #' will be saved. The containing directory must already exist. -#' @param file_open Logical. Open the PNG file once it's written? -#' @param border_width Numeric. Thickness of the border, expressed as a ratio -#' of the 'inner' hexagon to 'outer' hexagon (must be less than 1). +#' +#' @returns Nothing. A graphics device is opened. +#' +#' @export +#' +#' @examples +#' temp_path <- tempfile(fileext = ".png") +#' open_device(temp_path) +#' add_hex() +#' image_path <- system.file("img", "Rlogo.png", package = "png") +#' image_png <- png::readPNG(image_path) +#' add_image(image_png) +#' add_text() +#' close_device() +open_device <- function(file_path) { + + if (grepl(file_path, "\\.png$")) { + stop("Argument 'file_path' must end with '.png'.") + } + + if (!dir.exists(dirname(file_path))) { + stop("Argument 'file_path' must resolve to an existing directory.") + } + + grDevices::png( + filename = file_path, + width = 4.39, + height = 5.08, + units = "cm", + res = 1200, + bg = "transparent" + ) + +} + +#' Add a Hexagon with a Border +#' +#' Add two hexagons, where the exposed region between the two creates a border. +#' +#' @param border_width Numeric. Thickness of the border, expressed as the +#' inverse ratio of the 'inner' hexagon to 'outer' hexagon (must be between +#' `0` and `1`). #' @param border_col Character. Named R colour or hexadecimal code for the #' border around the hex. #' @param bg_col Character. Named R colour or hexadecimal code for the interior #' background. -#' @param txt_string Character. Text to display. `NULL` (or an empty string) if -#' you don't want to place text. -#' @param txt_x Numeric. Text location x-axis. -#' @param txt_y Numeric. Text location y-axis. -#' @param txt_angle Numeric. Rotation of text string in degrees. Positive values -#' will rotate anticlockwise by the given angle. -#' @param txt_size Numeric. Text point-size. -#' @param txt_col Character. Text colour. A named R colour or hexadecimal code. -#' @param txt_font Character. Name of a font family available on your system. -#' @param img_object Array. A PNG file read in by the user. `NULL` for no image. -#' @param img_x Numeric. Image location x-axis. -#' @param img_y Numeric. Image location y-axis. -#' @param img_width Numeric. Image width. -#' @param img_height Numeric. Image height. -#' @param img_angle Numeric. Text rotation in degrees. #' #' @details #' -#' ## Dimensions +#' ## Colours #' -#' Writes a hexagon to the dimensions of -#' [the Stickers Standard](https://sticker.how/#type-hexagon): 4.39 cm wide by -#' 5.08 cm high (2 by 1.73 inches). +#' Named colour values must be listed in [grDevices::colours()]. Hexadecimal +#' colour values must be provided with length 6 or 8 and must begin with an +#' octothorpe (`#`). #' -#' Any elements falling outside of the hexagon will be clipped out. +#' @returns `NULL`. Adds to an existing graphics device. #' -#' ## Coordinates +#' @export +#' +#' @examples +#' temp_path <- tempfile(fileext = ".png") +#' open_device(temp_path) +#' add_hex() +#' image_path <- system.file("img", "Rlogo.png", package = "png") +#' image_png <- png::readPNG(image_path) +#' add_image(image_png) +#' add_text() +#' close_device() +add_hex <- function( + border_width = 0.05, + border_col = "black", + bg_col = "grey" +) { + + if (!inherits(border_width, "numeric") || border_width >= 1) { + stop("Argument 'border_width' must be a numeric value below 1.") + } + + if (!(border_col %in% grDevices::colours() | grepl("^#[0-9A-Fa-f]{6}$", border_col))) { + stop("Argument 'border_col' must a named R colour or a hex code.") + } + + if (!(bg_col %in% grDevices::colours() | grepl("^#[0-9A-Fa-f]{6}$", bg_col))) { + stop("Argument 'bg_col' must a named R colour or a hex code.") + } + + hex_diameter_inner <- 1 - border_width + + hex_coords_outer <- .get_hex_coords(diameter = 1) + hex_coords_inner <- .get_hex_coords(diameter = hex_diameter_inner) + + x_scale <- c(min(hex_coords_outer[["x"]]), max(hex_coords_outer[["x"]])) + y_scale <- c(min(hex_coords_outer[["y"]]), max(hex_coords_outer[["y"]])) + + grid::pushViewport(grid::viewport(xscale = x_scale, yscale = y_scale)) + + hex_grob_outer <- grid::polygonGrob( + hex_coords_outer[["x"]], + hex_coords_outer[["y"]], + gp = grid::gpar(lwd = 0, fill = border_col), + default.units = "native" + ) + grid::pushViewport( + grid::viewport( + xscale = x_scale, + yscale = y_scale, + clip = hex_grob_outer + ) + ) + + grid::grid.draw(hex_grob_outer) + + grid::grid.polygon( + x = hex_coords_inner[["x"]], + y = hex_coords_inner[["y"]], + default.units = "native", + gp = grid::gpar(lwd = 0, fill = bg_col) + ) + +} + +#' Get Coordinates of Hexagon Vertices +#' @param diameter Numeric. +#' @returns A list of two numeric vectors that represent points of a hexagon. +#' The elements are named 'x' and 'y'. +#' @noRd +.get_hex_coords <- function(diameter = 1) { + + radius <- diameter / 2 + centre <- 0.5 + angles <- seq(0, 2 * pi, length.out = 7) + + list( + x = centre + radius * cos(angles - pi / 6), + y = centre + radius * sin(angles - pi / 6) + ) + +} + +#' Add Text #' -#' Coordinates should be provided as native units ('Normalised Parent -#' Coordinates'), which means that the x- and y-axes range from 0 to 1 with the -#' centre at x = 0.5 and y = 0.5. +#' Overlay text on the hexagon. Text outside the hexagon will be clipped. Should +#' be called after [open_device] and [add_hex], in that order. Call this function +#' separately for each text item that you want to add. #' -#' This applies to arguments `txt_x`, `txt_y`, `img_x`, `img_y`, `img_width` -#' and `img_height`. +#' @param text_string Character. Text to display. `NULL` (or an empty string) if +#' you don't want to place text. +#' @param text_x Numeric. Text location x-axis. +#' @param text_y Numeric. Text location y-axis. +#' @param text_angle Numeric. Rotation of text string in degrees. Positive +#' values will rotate anticlockwise by the given angle. +#' @param text_size Numeric. Text point-size. +#' @param text_col Character. Text colour. A named R colour or hexadecimal code. +#' @param text_family Character. Name of a font family available on your system. +#' @param text_face Character. Font face for the text. +#' +#' @details +#' +#' ## Coordinates +#' +#' Coordinates should be provided within the x- and y-axis ranges, which are +#' both from 0 to 1, giving the centre as x = 0.5 and y = 0.5. #' #' ## Colours #' @@ -53,105 +175,169 @@ #' colour values must be provided with length 6 or 8 and must begin with an #' octothorpe (`#`). #' -#' This applies to arguments `border_col`, `bg_col` and `txt_col`. -#' -#' ## Write order -#' -#' Each subsequent element overlays the last. The order of action when building -#' the hex is: -#' -#' 1. Add outer hexagon. -#' 2. Add inner hexagon. -#' 3. Add image. -#' 4. Add text. -#' 5. Clip to outer hexagon. -#' -#' @return Nothing. +#' @returns `NULL`. Adds to an existing graphics device. #' #' @export #' #' @examples -#' tmp <- tempfile(fileext = ".png") -#' make_hex(file_path = tmp) -make_hex <- function( - file_path, - file_open = FALSE, - border_width = 0.95, - border_col = "blue", - bg_col = "grey80", - txt_string = "example\ntext", - txt_x = 0.5, - txt_y = 0.5, - txt_angle = 30, - txt_size = 20, - txt_col = "red", - txt_font = "mono", - img_object = NULL, - img_x = 0.5, - img_y = 0.5, - img_width = 0.5, - img_height = 0.5, - img_angle = 0 +#' temp_path <- tempfile(fileext = ".png") +#' open_device(temp_path) +#' add_hex() +#' image_path <- system.file("img", "Rlogo.png", package = "png") +#' image_png <- png::readPNG(image_path) +#' add_image(image_png) +#' add_text() +#' close_device() +add_text <- function( + text_string = "example", + text_x = 0.5, + text_y = 0.3, + text_angle = 0, + text_size = 20, + text_col = "black", + text_family = "sans", + text_face = c("plain", "bold", "italic", "bold.italic") ) { - grDevices::png( - filename = file_path, - width = 4.39, - height = 5.08, - units = "cm", - res = 1200, - bg = "transparent" - ) + if (!inherits(text_string, "character")) { + stop("Argument 'text_string' must be a character string.") + } - coords_outer <- .get_hex_coords(d = 1) - coords_outer_scaled <- lapply(coords_outer, .scale_outer_coords) - grob_outer <- .engrob_hex(coords_outer_scaled, border_col) + if (!inherits(text_x, "numeric") | !inherits(text_y, "numeric")) { + stop("Arguments 'text_x' and 'text_y' must be numeric values.") + } - coords_inner <- .get_hex_coords(d = border_width) - coords_inner_scaled <- .get_inner_hex_coords_scaled(coords_inner, coords_outer) - grob_inner <- .engrob_hex(coords_inner_scaled, bg_col) + if (!inherits(text_size, "numeric")) { + stop("Argument 'text_size' must be a numeric value.") + } - if (!is.null(img_object)) { - grob_img <- grid::rasterGrob(img_object, width = img_width, height = img_height) + if (!inherits(text_size, "numeric")) { + stop("Argument 'text_size' must be a numeric value.") } - if (!is.null(txt_string)) { - grob_txt <- .engrob_text(txt_string, txt_col, txt_size, txt_font) + if (!(text_col %in% grDevices::colours() | grepl("^#[0-9A-Fa-f]{6}$", text_col))) { + stop("Argument 'text_col' must a named R colour or a hex code.") } - vp_clip <- grid::viewport(clip = grob_outer) - grid::pushViewport(vp_clip) + if (!inherits(text_family, "character")) { + stop( + "Argument 'text_family' must be a character string + representing an available font family." + ) + } - for (grob in list(grob_outer, grob_inner)) { - vp_hex <- grid::viewport(gp = grid::gpar(lwd = 0)) - grid::pushViewport(vp_hex) - grid::grid.draw(grob) + if (!inherits(text_face, "character")) { + stop( + "Argument 'text_face' must be one of the following character strings: + 'plain', 'bold', 'italic', 'bold-italic'." + ) } - if (!is.null(img_object)) { - vp_img_parent <- grid::viewport(x = img_x, y = img_y) - grid::pushViewport(vp_img_parent) - vp_img <- grid::viewport(angle = img_angle) - grid::pushViewport(vp_img) - grid::grid.draw(grob_img) - grid::popViewport() - grid::popViewport() + text_face <- match.arg(text_face) + + grid::pushViewport(grid::viewport(x = text_x, y = text_y)) + grid::grid.text( + text_string, + gp = grid::gpar( + col = text_col, + fontsize = text_size, + fontfamily = text_family, + fontface = text_face + ), + vp = grid::viewport(angle = text_angle) + ) + grid::popViewport() + + +} + +#' Add an Image +#' +#' Overlay an image on the hexagon. Image content outside the hexagon will be +#' clipped. Should be called after [open_device] and [add_hex], in that order. +#' Call this function separately for each image you want to add. +#' +#' @param image_object Array. A PNG file read in by the user. `NULL` for no +#' image. +#' @param image_x Numeric. Image location x-axis. +#' @param image_y Numeric. Image location y-axis. +#' @param image_angle Numeric. Text rotation in degrees. +#' @param image_width Numeric. Image width. +#' +#' @details +#' +#' ## Coordinates +#' +#' Coordinates should be provided within the x- and y-axis ranges, which are +#' both from 0 to 1, giving the centre as x = 0.5 and y = 0.5. +#' +#' @returns `NULL`. Adds to an existing graphics device. +#' +#' @export +#' +#' @examples +#' temp_path <- tempfile(fileext = ".png") +#' open_device(temp_path) +#' add_hex() +#' image_path <- system.file("img", "Rlogo.png", package = "png") +#' image_png <- png::readPNG(image_path) +#' add_image(image_png) +#' add_text() +#' close_device() +add_image <- function( + image_object, + image_x = 0.5, + image_y = 0.7, + image_angle = 0, + image_width = 0.4 +) { + + if (!inherits(image_x, "numeric") | !inherits(image_y, "numeric")) { + stop("Arguments 'image_x' and 'image_y' must be numeric values.") } - if (!is.null(txt_string)) { - vp_txt_parent <- grid::viewport(x = txt_x, y = txt_y) - grid::pushViewport(vp_txt_parent) - vp_txt <- grid::viewport(angle = txt_angle) - grid::pushViewport(vp_txt) - grid::grid.draw(grob_txt) - grid::popViewport() - grid::popViewport() + if (!inherits(image_angle, "numeric")) { + stop("Argument 'image_angle' must be a numeric value.") } - grid::popViewport() # clip + if (!inherits(image_width, "numeric")) { + stop("Argument 'image_width' must be a numeric value.") + } - grDevices::dev.off() + grid::pushViewport( + grid::viewport( + x = image_x, + y = image_y, + width = image_width + ) + ) + grid::grid.raster( + image_object, + vp = grid::viewport(angle = image_angle) + ) + grid::popViewport() - if (file_open) system(paste("open", file_path)) +} +#' Close the Device +#' +#' Clip to the area of the outer hexagon and close the PNG plot device, which +#' writes to the `file_path` specified in [open_device]. +#' +#' @returns `NULL`. Adds to an existing graphics device. +#' +#' @export +#' +#' @examples +#' temp_path <- tempfile(fileext = ".png") +#' open_device(temp_path) +#' add_hex() +#' image_path <- system.file("img", "Rlogo.png", package = "png") +#' image_png <- png::readPNG(image_path) +#' add_image(image_png) +#' add_text() +#' close_device() +close_device <- function() { + grid::popViewport(0) # clip to outer hexagon + grDevices::dev.off() } diff --git a/README.md b/README.md index 87fb618..fdf745f 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,19 @@ -# {hexbase} A hexagon sticker logo for the package hexbase. It has a darkblue hexagon with a grey border. There is an a white hexagon with a thick grey border inside. In the centre is darkblue text saying hexbase. +# {hexbase} -[![Project Status: WIP – Initial development is in progress, but there has not yet been a stable, usable release suitable for the public.](https://www.repostatus.org/badges/latest/wip.svg)](https://www.repostatus.org/#wip) +[![Project Status: Concept – Minimal or no implementation has been done yet, or the repository is only intended to be a limited example, demo, or proof-of-concept.](https://www.repostatus.org/badges/latest/concept.svg)](https://www.repostatus.org/#concept) [![R-CMD-check](https://github.com/matt-dray/hexbase/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/matt-dray/hexbase/actions/workflows/R-CMD-check.yaml) [![test-coverage](https://github.com/matt-dray/hexbase/actions/workflows/test-coverage.yaml/badge.svg)](https://github.com/matt-dray/hexbase/actions/workflows/test-coverage.yaml) ## What -A dependency-free R package to help create simple hexagon-shaped sticker logos. +A dependency-free R package to help create simple hexagon-shaped sticker logos with the dimensions of [the Stickers Standard](https://sticker.how/#type-hexagon). -The package's only function, `make_hex()`, is intentionally limited and opinionated. For now, you can only: - -* adjust the width and colour of the border -* colour the background -* add text and adjust its location, rotation, size, colour and font family -* provide an image from file and adjust its location, size and rotation -* save to PNG with the dimensions of [the Stickers Standard](https://sticker.how/#type-hexagon) +This a concept package that may be unstable. +It has little testing across systems. +[Please contribute](https://github.com/matt-dray/hexbase/issues) if you have ideas or want to fix my code. ## Install @@ -28,45 +24,74 @@ install.packages("remotes") # if not yet installed remotes::install_github("matt-dray/hexbase") ``` +The package only uses {grid} and {grDevices} from base R. +Otherwise it's BYOIAF ('bring your own images and fonts'). + ## Example -The hex logo for {hexbase} was made using {hexbase} (so meta). -You can see it at the top of this README. -It's composed of two main elements: an image (a grey-bordered white hexagon) read from a PNG file overlaid with some text ('hexbase'). +Build a sticker additively with a series of function calls: -You can make this hex using the `make_hex()` function. -The output is saved to a PNG at the `file_path` location. +1. `open_device()` to set up a PNG graphics device with the dimensions of [the Stickers Standard](https://sticker.how/#type-hexagon). +1. `add_hex()` to add the hexagon and border. +1. `add_image()` to place an image (run multiple times for more images). +1. `add_text()` to place and style text (run multiple times for more text). +1. `close_device()` to close the PNG graphics device and save to file. -``` r -# Create temporary PNG file where hex will be written -temp_path <- tempfile(fileext = ".png") +You can set various text and image properties like position, size, colour and angle. +Text and images will be clipped if they exceed the boundary of the hexagon. -# Read an image file to use as an element in the hex -image_path <- system.file("images", "hexagon.png", package = "hexbase") +Below is an extremely basic example. +Note how you call each function independently (i.e. no pipes), much like writing base plots. + +``` r +# Bring your own image +image_path <- system.file("img", "Rlogo.png", package = "png") image_png <- png::readPNG(image_path) -# Generate the hex with border, background, text and image elements -hexbase::make_hex( - file_path = temp_path, - file_open = TRUE, # open the file after being written - border_col = "grey", # named colour or hexadecimal - bg_col = "darkblue", - txt_string = "hex\nbase", # includes linebreak - txt_x = 0.5, - txt_y = 0.5, - txt_angle = 30, - txt_size = 18, - txt_col = "darkblue", - txt_font = "Routed Gothic Wide", # downloaded via webonastick.com/fonts/routed-gothic/ - img_object = image_png, - img_x = 0.5, - img_y = 0.5, - img_width = 0.7, - img_height = 0.7, - img_angle = 30 +# Somewhere to save it +temp_path <- tempfile(fileext = ".png") + +# Build up and write the sticker +hexbase::open_device(file_path = temp_path) +hexbase::add_hex( + border_col = "grey20", + bg_col = "#BEBEBE" ) +hexbase::add_image( + image_object = image_png, + image_y = 0.6, + image_angle = 20, + image_width = 0.5 +) +hexbase::add_text( + text_string = "example", + text_y = 0.35, + text_col = "red", + text_family = "mono", + text_face = "bold.italic" +) +hexbase::add_text( + text_string = "visit https://rstats.lol/ ftw", + text_x = 0.73, + text_y = 0.17, + text_angle = 30, + text_size = 6, + text_col = "blue", + text_family = "serif" +) +hexbase::close_device() + +# Optionally, open the image for inspection +system(paste("open", temp_path)) ``` +That creates this absolutely stunning sticker, written to the specified `file_path`: + +A grey hexagon with a thin black border. An R logo is shown just above centre. Just below centre is the text 'example' in monospace red and bold font. On the lower right edge is the URL 'htps://rstats.lol' in smaller, blue italic serif font. + +Note that you can't rely on plot-window previews when you're developing your sticker (they lie). +You must inspect the generated PNG file instead. + ## Related For more established hex-making tools with R, try: diff --git a/man/add_hex.Rd b/man/add_hex.Rd new file mode 100644 index 0000000..74baa34 --- /dev/null +++ b/man/add_hex.Rd @@ -0,0 +1,43 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/hexagon.R +\name{add_hex} +\alias{add_hex} +\title{Add a Hexagon with a Border} +\usage{ +add_hex(border_width = 0.05, border_col = "black", bg_col = "grey") +} +\arguments{ +\item{border_width}{Numeric. Thickness of the border, expressed as the +inverse ratio of the 'inner' hexagon to 'outer' hexagon (must be between +\code{0} and \code{1}).} + +\item{border_col}{Character. Named R colour or hexadecimal code for the +border around the hex.} + +\item{bg_col}{Character. Named R colour or hexadecimal code for the interior +background.} +} +\value{ +\code{NULL}. Adds to an existing graphics device. +} +\description{ +Add two hexagons, where the exposed region between the two creates a border. +} +\details{ +\subsection{Colours}{ + +Named colour values must be listed in \code{\link[grDevices:colors]{grDevices::colours()}}. Hexadecimal +colour values must be provided with length 6 or 8 and must begin with an +octothorpe (\verb{#}). +} +} +\examples{ +temp_path <- tempfile(fileext = ".png") +open_device(temp_path) +add_hex() +image_path <- system.file("img", "Rlogo.png", package = "png") +image_png <- png::readPNG(image_path) +add_image(image_png) +add_text() +close_device() +} diff --git a/man/add_image.Rd b/man/add_image.Rd new file mode 100644 index 0000000..f540d00 --- /dev/null +++ b/man/add_image.Rd @@ -0,0 +1,51 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/hexagon.R +\name{add_image} +\alias{add_image} +\title{Add an Image} +\usage{ +add_image( + image_object, + image_x = 0.5, + image_y = 0.7, + image_angle = 0, + image_width = 0.4 +) +} +\arguments{ +\item{image_object}{Array. A PNG file read in by the user. \code{NULL} for no +image.} + +\item{image_x}{Numeric. Image location x-axis.} + +\item{image_y}{Numeric. Image location y-axis.} + +\item{image_angle}{Numeric. Text rotation in degrees.} + +\item{image_width}{Numeric. Image width.} +} +\value{ +\code{NULL}. Adds to an existing graphics device. +} +\description{ +Overlay an image on the hexagon. Image content outside the hexagon will be +clipped. Should be called after \link{open_device} and \link{add_hex}, in that order. +Call this function separately for each image you want to add. +} +\details{ +\subsection{Coordinates}{ + +Coordinates should be provided within the x- and y-axis ranges, which are +both from 0 to 1, giving the centre as x = 0.5 and y = 0.5. +} +} +\examples{ +temp_path <- tempfile(fileext = ".png") +open_device(temp_path) +add_hex() +image_path <- system.file("img", "Rlogo.png", package = "png") +image_png <- png::readPNG(image_path) +add_image(image_png) +add_text() +close_device() +} diff --git a/man/add_text.Rd b/man/add_text.Rd new file mode 100644 index 0000000..8471f85 --- /dev/null +++ b/man/add_text.Rd @@ -0,0 +1,68 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/hexagon.R +\name{add_text} +\alias{add_text} +\title{Add Text} +\usage{ +add_text( + text_string = "example", + text_x = 0.5, + text_y = 0.3, + text_angle = 0, + text_size = 20, + text_col = "black", + text_family = "sans", + text_face = c("plain", "bold", "italic", "bold.italic") +) +} +\arguments{ +\item{text_string}{Character. Text to display. \code{NULL} (or an empty string) if +you don't want to place text.} + +\item{text_x}{Numeric. Text location x-axis.} + +\item{text_y}{Numeric. Text location y-axis.} + +\item{text_angle}{Numeric. Rotation of text string in degrees. Positive +values will rotate anticlockwise by the given angle.} + +\item{text_size}{Numeric. Text point-size.} + +\item{text_col}{Character. Text colour. A named R colour or hexadecimal code.} + +\item{text_family}{Character. Name of a font family available on your system.} + +\item{text_face}{Character. Font face for the text.} +} +\value{ +\code{NULL}. Adds to an existing graphics device. +} +\description{ +Overlay text on the hexagon. Text outside the hexagon will be clipped. Should +be called after \link{open_device} and \link{add_hex}, in that order. Call this function +separately for each text item that you want to add. +} +\details{ +\subsection{Coordinates}{ + +Coordinates should be provided within the x- and y-axis ranges, which are +both from 0 to 1, giving the centre as x = 0.5 and y = 0.5. +} + +\subsection{Colours}{ + +Named colour values must be listed in \code{\link[grDevices:colors]{grDevices::colours()}}. Hexadecimal +colour values must be provided with length 6 or 8 and must begin with an +octothorpe (\verb{#}). +} +} +\examples{ +temp_path <- tempfile(fileext = ".png") +open_device(temp_path) +add_hex() +image_path <- system.file("img", "Rlogo.png", package = "png") +image_png <- png::readPNG(image_path) +add_image(image_png) +add_text() +close_device() +} diff --git a/man/close_device.Rd b/man/close_device.Rd new file mode 100644 index 0000000..e6e0ef3 --- /dev/null +++ b/man/close_device.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/hexagon.R +\name{close_device} +\alias{close_device} +\title{Close the Device} +\usage{ +close_device() +} +\value{ +\code{NULL}. Adds to an existing graphics device. +} +\description{ +Clip to the area of the outer hexagon and close the PNG plot device, which +writes to the \code{file_path} specified in \link{open_device}. +} +\examples{ +temp_path <- tempfile(fileext = ".png") +open_device(temp_path) +add_hex() +image_path <- system.file("img", "Rlogo.png", package = "png") +image_png <- png::readPNG(image_path) +add_image(image_png) +add_text() +close_device() +} diff --git a/man/figures/readme-hex.png b/man/figures/readme-hex.png new file mode 100644 index 0000000..61ed615 Binary files /dev/null and b/man/figures/readme-hex.png differ diff --git a/man/hexbase-package.Rd b/man/hexbase-package.Rd index b1bb609..5372f0a 100644 --- a/man/hexbase-package.Rd +++ b/man/hexbase-package.Rd @@ -8,7 +8,7 @@ \description{ \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} -A simple interface to create hexagon-shaped logos that help promote your R package or other projects. Uses only base R. +A simple interface to create hexagon-shaped logos that help promote your R package or other projects. Uses base R only. } \seealso{ Useful links: diff --git a/man/make_hex.Rd b/man/make_hex.Rd deleted file mode 100644 index 4383c86..0000000 --- a/man/make_hex.Rd +++ /dev/null @@ -1,123 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/hexagon.R -\name{make_hex} -\alias{make_hex} -\title{Write a Hex Sticker to File} -\usage{ -make_hex( - file_path, - file_open = FALSE, - border_width = 0.95, - border_col = "blue", - bg_col = "grey80", - txt_string = "example\\ntext", - txt_x = 0.5, - txt_y = 0.5, - txt_angle = 30, - txt_size = 20, - txt_col = "red", - txt_font = "mono", - img_object = NULL, - img_x = 0.5, - img_y = 0.5, - img_width = 0.5, - img_height = 0.5, - img_angle = 0 -) -} -\arguments{ -\item{file_path}{Character. Full file path to a .png where the output file -will be saved. The containing directory must already exist.} - -\item{file_open}{Logical. Open the PNG file once it's written?} - -\item{border_width}{Numeric. Thickness of the border, expressed as a ratio -of the 'inner' hexagon to 'outer' hexagon (must be less than 1).} - -\item{border_col}{Character. Named R colour or hexadecimal code for the -border around the hex.} - -\item{bg_col}{Character. Named R colour or hexadecimal code for the interior -background.} - -\item{txt_string}{Character. Text to display. \code{NULL} (or an empty string) if -you don't want to place text.} - -\item{txt_x}{Numeric. Text location x-axis.} - -\item{txt_y}{Numeric. Text location y-axis.} - -\item{txt_angle}{Numeric. Rotation of text string in degrees. Positive values -will rotate anticlockwise by the given angle.} - -\item{txt_size}{Numeric. Text point-size.} - -\item{txt_col}{Character. Text colour. A named R colour or hexadecimal code.} - -\item{txt_font}{Character. Name of a font family available on your system.} - -\item{img_object}{Array. A PNG file read in by the user. \code{NULL} for no image.} - -\item{img_x}{Numeric. Image location x-axis.} - -\item{img_y}{Numeric. Image location y-axis.} - -\item{img_width}{Numeric. Image width.} - -\item{img_height}{Numeric. Image height.} - -\item{img_angle}{Numeric. Text rotation in degrees.} -} -\value{ -Nothing. -} -\description{ -Generate a simple hexagon-shaped sticker design with a border, image and -text. -} -\details{ -\subsection{Dimensions}{ - -Writes a hexagon to the dimensions of -\href{https://sticker.how/#type-hexagon}{the Stickers Standard}: 4.39 cm wide by -5.08 cm high (2 by 1.73 inches). - -Any elements falling outside of the hexagon will be clipped out. -} - -\subsection{Coordinates}{ - -Coordinates should be provided as native units ('Normalised Parent -Coordinates'), which means that the x- and y-axes range from 0 to 1 with the -centre at x = 0.5 and y = 0.5. - -This applies to arguments \code{txt_x}, \code{txt_y}, \code{img_x}, \code{img_y}, \code{img_width} -and \code{img_height}. -} - -\subsection{Colours}{ - -Named colour values must be listed in \code{\link[grDevices:colors]{grDevices::colours()}}. Hexadecimal -colour values must be provided with length 6 or 8 and must begin with an -octothorpe (\verb{#}). - -This applies to arguments \code{border_col}, \code{bg_col} and \code{txt_col}. -} - -\subsection{Write order}{ - -Each subsequent element overlays the last. The order of action when building -the hex is: -\enumerate{ -\item Add outer hexagon. -\item Add inner hexagon. -\item Add image. -\item Add text. -\item Clip to outer hexagon. -} -} -} -\examples{ -tmp <- tempfile(fileext = ".png") -make_hex(file_path = tmp) -} diff --git a/man/open_device.Rd b/man/open_device.Rd new file mode 100644 index 0000000..68e8b24 --- /dev/null +++ b/man/open_device.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/hexagon.R +\name{open_device} +\alias{open_device} +\title{Open a Device} +\usage{ +open_device(file_path) +} +\arguments{ +\item{file_path}{Character. Full file path to a .png where the output file +will be saved. The containing directory must already exist.} +} +\value{ +Nothing. A graphics device is opened. +} +\description{ +Begin a PNG plot device with dimensions matching +\href{https://sticker.how/#type-hexagon}{the Stickers Standard}: 4.39 cm wide by +5.08 cm high (2 by 1.73 inches). +} +\examples{ +temp_path <- tempfile(fileext = ".png") +open_device(temp_path) +add_hex() +image_path <- system.file("img", "Rlogo.png", package = "png") +image_png <- png::readPNG(image_path) +add_image(image_png) +add_text() +close_device() +}