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}
+# {hexbase}
-[](https://www.repostatus.org/#wip)
+[](https://www.repostatus.org/#concept)
[](https://github.com/matt-dray/hexbase/actions/workflows/R-CMD-check.yaml)
[](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`:
+
+
+
+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()
+}