diff --git a/.Rbuildignore b/.Rbuildignore
index e309982..0ff1239 100644
--- a/.Rbuildignore
+++ b/.Rbuildignore
@@ -1,4 +1,4 @@
-^hexbase\.Rproj$
+^gex\.Rproj$
^\.Rproj\.user$
^LICENSE\.md$
^\.github$
diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml
deleted file mode 100644
index e050312..0000000
--- a/.github/workflows/test-coverage.yaml
+++ /dev/null
@@ -1,61 +0,0 @@
-# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
-# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
-on:
- push:
- branches: [main, master]
- pull_request:
-
-name: test-coverage.yaml
-
-permissions: read-all
-
-jobs:
- test-coverage:
- runs-on: ubuntu-latest
- env:
- GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
-
- steps:
- - uses: actions/checkout@v4
-
- - uses: r-lib/actions/setup-r@v2
- with:
- use-public-rspm: true
-
- - uses: r-lib/actions/setup-r-dependencies@v2
- with:
- extra-packages: any::covr, any::xml2
- needs: coverage
-
- - name: Test coverage
- run: |
- cov <- covr::package_coverage(
- quiet = FALSE,
- clean = FALSE,
- install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package")
- )
- covr::to_cobertura(cov)
- shell: Rscript {0}
-
- - uses: codecov/codecov-action@v4
- with:
- # Fail if error if not on PR, or if on PR and token is given
- fail_ci_if_error: ${{ github.event_name != 'pull_request' || secrets.CODECOV_TOKEN }}
- file: ./cobertura.xml
- plugin: noop
- disable_search: true
- token: ${{ secrets.CODECOV_TOKEN }}
-
- - name: Show testthat output
- if: always()
- run: |
- ## --------------------------------------------------------------------
- find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true
- shell: bash
-
- - name: Upload test results
- if: failure()
- uses: actions/upload-artifact@v4
- with:
- name: coverage-test-failures
- path: ${{ runner.temp }}/package
diff --git a/.gitignore b/.gitignore
index 9356de0..7f7db4c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -52,3 +52,6 @@ rsconnect/
.DS_Store
docs
inst/doc
+
+# tests
+_tinysnapshot_review/
diff --git a/DESCRIPTION b/DESCRIPTION
index dcae902..d8b65a6 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,20 +1,26 @@
-Package: hexbase
-Title: Create Simple Dependency-Free Hex Logos
-Version: 0.1.0
+Package: gex
+Title: A Dependency-Light Hex-Logo Builder
+Version: 0.2.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 base R only.
+ promote your R package or other projects. Uses the 'grid' system.
License: MIT + file LICENSE
-URL: https://github.com/matt-dray/hexbase
-BugReports: https://github.com/matt-dray/hexbase/bugs
+URL: https://github.com/matt-dray/gex
+BugReports: https://github.com/matt-dray/gex/bugs
Imports:
grDevices,
- grid
+ grid,
+ gridGeometry
Suggests:
- png
+ magick,
+ png,
+ rsvg,
+ svglite,
+ tinysnapshot,
+ tinytest
Config/testthat/edition: 3
Encoding: UTF-8
-Issues: https://github.com/matt-dray/hexbase
+Issues: https://github.com/matt-dray/gex
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.2
diff --git a/LICENSE b/LICENSE
index 282a3b5..356df75 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,2 +1,2 @@
YEAR: 2022
-COPYRIGHT HOLDER: hexbase authors
+COPYRIGHT HOLDER: Matt Dray
diff --git a/LICENSE.md b/LICENSE.md
index 1d3cf5a..0480018 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,6 +1,6 @@
# MIT License
-Copyright (c) 2022 hexbase authors
+Copyright (c) 2022 Matt Dray
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/NAMESPACE b/NAMESPACE
index 7340d38..142ad34 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -1,5 +1,6 @@
# Generated by roxygen2: do not edit by hand
+export(add_border)
export(add_hex)
export(add_image)
export(add_text)
diff --git a/NEWS.md b/NEWS.md
index bc230bc..e73a96c 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,3 +1,17 @@
+# gex 0.2.0
+
+## Breaking
+
+* Renamed the package from 'hexbase' to 'gex'.
+* Separated `add_hex()` into `add_hex()` and `add_border()`.
+* Simplified argument names by dropping prefixes.
+
+## Other
+
+* Added dependency: 'gridGeometry'.
+* Updated checks and added tests with 'tinytest' and 'tinysnapshot'.
+* Updated README and DESCRIPTION documentation.
+
# hexbase 0.1.0
* Created package and added boilerplate.
diff --git a/R/hexbase-package.R b/R/gex-package.R
similarity index 100%
rename from R/hexbase-package.R
rename to R/gex-package.R
diff --git a/R/hexagon.R b/R/hexagon.R
index 3886ef7..760f9e1 100644
--- a/R/hexagon.R
+++ b/R/hexagon.R
@@ -1,33 +1,47 @@
-#' Open a Device
+#' Open a PNG Device with Sticker-Standard Dimensions
#'
#' 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_path Character. File path to a .png where the output file will be
+#' saved. The containing directory must already exist.
+#'
+#' @details
+#'
+#' ## Order
+#'
+#' When building a hex, this function should be called first, followed by
+#' [add_hex]. You can then use [add_text], [add_image] and [add_border] (if
+#' desired) and finally [close_device].
#'
#' @returns Nothing. A graphics device is opened.
#'
+#' @family hex device handlers
+#'
#' @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)
+#' img_path <- system.file("img", "Rlogo.png", package = "png")
+#' img_png <- png::readPNG(img_path)
+#' add_image(img_png)
#' add_text()
+#' add_border()
#' close_device()
open_device <- function(file_path) {
- if (grepl(file_path, "\\.png$")) {
- stop("Argument 'file_path' must end with '.png'.")
+ if (tools::file_ext(file_path) != "png") {
+ stop("Argument 'file_path' must end with '.png'.", call. = FALSE)
}
if (!dir.exists(dirname(file_path))) {
- stop("Argument 'file_path' must resolve to an existing directory.")
+ stop(
+ "Argument 'file_path' must resolve to an existing directory.",
+ call. = FALSE
+ )
}
grDevices::png(
@@ -41,20 +55,21 @@ open_device <- function(file_path) {
}
-#' Add a Hexagon with a Border
+#' Add a Hexagon
#'
-#' Add two hexagons, where the exposed region between the two creates a border.
+#' Add a hexagon 'canvas' to which elements can be added.
#'
-#' @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
+#' @param col Character. Named R colour or hexadecimal code for the interior
#' background.
#'
#' @details
#'
+#' ## Order
+#'
+#' When building a hex, this function should be called after [open_device]. You can then use
+#' [add_text], [add_image] and [add_border] (if desired) and finally
+#' [close_device].
+#'
#' ## Colours
#'
#' Named colour values must be listed in [grDevices::colours()]. Hexadecimal
@@ -63,39 +78,27 @@ open_device <- function(file_path) {
#'
#' @returns `NULL`. Adds to an existing graphics device.
#'
+#' @family hex elements
+#'
#' @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)
+#' img_path <- system.file("img", "Rlogo.png", package = "png")
+#' img_png <- png::readPNG(img_path)
+#' add_image(img_png)
#' add_text()
+#' add_border()
#' 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.")
- }
+add_hex <- function(col = "grey") {
- 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.")
+ if (!(col %in% grDevices::colours() | grepl("^#[0-9A-Fa-f]{6,8}$", col))) {
+ stop("Argument 'col' must a named R colour or a hex code.", call. = FALSE)
}
- 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"]]))
@@ -105,9 +108,11 @@ add_hex <- function(
hex_grob_outer <- grid::polygonGrob(
hex_coords_outer[["x"]],
hex_coords_outer[["y"]],
- gp = grid::gpar(lwd = 0, fill = border_col),
+ gp = grid::gpar(lwd = 0, fill = col),
default.units = "native"
)
+
+ # Remove anything outside the outer hex boundary when popped
grid::pushViewport(
grid::viewport(
xscale = x_scale,
@@ -118,52 +123,32 @@ add_hex <- function(
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
+#' Add Text to the Hexagon
#'
-#' 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.
+#' Overlay text on the hexagon. Call this function separately for each string
+#' you want to add.
#'
-#' @param text_string Character. Text to display. `NULL` (or an empty string) if
+#' @param 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
+#' @param x Numeric. Text location on the hexagon's x-axis.
+#' @param y Numeric. Text location on the hexagon's y-axis.
+#' @param 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.
+#' @param size Numeric. Text point-size.
+#' @param col Character. Text colour. A named R colour or hexadecimal code.
+#' @param family Character. Name of a font family available on your system.
+#' @param face Character. Font face for the text.
#'
#' @details
#'
+#' ## Order
+#'
+#' When building a hex, this function should be called after [open_device] and
+#' [add_hex]. You can then use further calls to [add_text], [add_image] and
+#' [add_border] (if desired) and finally [close_device].
+#'
#' ## Coordinates
#'
#' Coordinates should be provided within the x- and y-axis ranges, which are
@@ -177,95 +162,105 @@ add_hex <- function(
#'
#' @returns `NULL`. Adds to an existing graphics device.
#'
+#' @family hex content adders
+#'
#' @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)
+#' img_path <- system.file("img", "Rlogo.png", package = "png")
+#' img_png <- png::readPNG(img_path)
+#' add_image(img_png)
#' add_text()
+#' add_border()
#' 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")
+ string = "example",
+ x = 0.5,
+ y = 0.4,
+ angle = 0,
+ size = 20,
+ col = "black",
+ family = "sans",
+ face = c("plain", "bold", "italic", "bold.italic")
) {
- if (!inherits(text_string, "character")) {
- stop("Argument 'text_string' must be a character string.")
+ if (!inherits(string, "character")) {
+ stop("Argument 'string' must be a character string.", call. = FALSE)
}
- if (!inherits(text_x, "numeric") | !inherits(text_y, "numeric")) {
- stop("Arguments 'text_x' and 'text_y' must be numeric values.")
+ if (!inherits(x, "numeric") | !inherits(y, "numeric")) {
+ stop("Arguments 'x' and 'y' must be numeric values.", call. = FALSE)
}
- if (!inherits(text_size, "numeric")) {
- stop("Argument 'text_size' must be a numeric value.")
+ if (!inherits(angle, "numeric")) {
+ stop("Argument 'angle' must be a numeric value.", call. = FALSE)
}
- if (!inherits(text_size, "numeric")) {
- stop("Argument 'text_size' must be a numeric value.")
+ if (!inherits(size, "numeric")) {
+ stop("Argument 'size' must be a numeric value.", call. = FALSE)
}
- 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.")
+ if (!(col %in% grDevices::colours() | grepl("^#[0-9A-Fa-f]{6,8}$", col))) {
+ stop("Argument 'col' must a named R colour or a hex code.", call. = FALSE)
}
- if (!inherits(text_family, "character")) {
+ if (!inherits(family, "character")) {
stop(
- "Argument 'text_family' must be a character string
- representing an available font family."
+ "Argument 'family' must be a character string representing ",
+ "an available font family.",
+ call. = FALSE
)
}
- if (!inherits(text_face, "character")) {
+ if (!inherits(face, "character")) {
stop(
- "Argument 'text_face' must be one of the following character strings:
- 'plain', 'bold', 'italic', 'bold-italic'."
+ "Argument 'face' must be one of the following character strings: ",
+ "'plain', 'bold', 'italic', 'bold.italic'.",
+ call. = FALSE
)
}
- text_face <- match.arg(text_face)
+ face <- match.arg(face)
- grid::pushViewport(grid::viewport(x = text_x, y = text_y))
+ grid::pushViewport(grid::viewport(x = x, y = y))
grid::grid.text(
- text_string,
+ string,
gp = grid::gpar(
- col = text_col,
- fontsize = text_size,
- fontfamily = text_family,
- fontface = text_face
+ col = col,
+ fontsize = size,
+ fontfamily = family,
+ fontface = face
),
- vp = grid::viewport(angle = text_angle)
+ vp = grid::viewport(angle = angle)
)
grid::popViewport()
}
-#' Add an Image
+#' Add an Image to the Hexagon
#'
-#' 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.
+#' Overlay an image on the hexagon. 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.
+#' @param img Array. A PNG or JPEG file read in by the user, most likely
+#' using packages 'png' or 'jpeg'.
+#' @param x Numeric. Image location on the hexagon's x-axis.
+#' @param y Numeric. Image location on the hexagon's y-axis.
+#' @param angle Numeric. Text rotation in degrees.
+#' @param width Numeric. Image width.
#'
#' @details
#'
+#' ## Order
+#'
+#' When building a hex, this function should be called after [open_device] and
+#' [add_hex]. You can then use further calls to [add_image], [add_text] and
+#' [add_border] (if desired) and finally [close_device].
+#'
#' ## Coordinates
#'
#' Coordinates should be provided within the x- and y-axis ranges, which are
@@ -273,71 +268,202 @@ add_text <- function(
#'
#' @returns `NULL`. Adds to an existing graphics device.
#'
+#' @family hex content adders
+#'
#' @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)
+#' img_path <- system.file("img", "Rlogo.png", package = "png")
+#' img_png <- png::readPNG(img_path)
+#' add_image(img_png)
#' add_text()
+#' add_border()
#' close_device()
add_image <- function(
- image_object,
- image_x = 0.5,
- image_y = 0.7,
- image_angle = 0,
- image_width = 0.4
+ img,
+ x = 0.5,
+ y = 0.7,
+ angle = 0,
+ width = 0.4
) {
- if (!inherits(image_x, "numeric") | !inherits(image_y, "numeric")) {
- stop("Arguments 'image_x' and 'image_y' must be numeric values.")
+ if (!inherits(img, "array")) {
+ stop(
+ "Argument 'img' must be an array (a png or jpeg file).",
+ call. = FALSE)
+ }
+
+ if (!inherits(x, "numeric") | !inherits(y, "numeric")) {
+ stop("Arguments 'x' and 'y' must be numeric values.", call. = FALSE)
}
- if (!inherits(image_angle, "numeric")) {
- stop("Argument 'image_angle' must be a numeric value.")
+ if (!inherits(angle, "numeric")) {
+ stop("Argument 'angle' must be a numeric value.", call. = FALSE)
}
- if (!inherits(image_width, "numeric")) {
- stop("Argument 'image_width' must be a numeric value.")
+ if (!inherits(width, "numeric")) {
+ stop("Argument 'width' must be a numeric value.", call. = FALSE)
}
grid::pushViewport(
grid::viewport(
- x = image_x,
- y = image_y,
- width = image_width
+ x = x,
+ y = y,
+ width = width
)
)
grid::grid.raster(
- image_object,
- vp = grid::viewport(angle = image_angle)
+ img,
+ vp = grid::viewport(angle = angle)
)
grid::popViewport()
}
-#' Close the Device
+#' Add a Border to the Edge of the Hexagon
#'
-#' Clip to the area of the outer hexagon and close the PNG plot device, which
-#' writes to the `file_path` specified in [open_device].
+#' Add a border of given thickness and colour to the inner edges of hexagon.
+#'
+#' @param width Numeric. Thickness of the border, expressed as the
+#' inverse ratio of the interior of the hex to the full extent of the hex
+#' (must be between `0` and `1`).
+#' @param col Character. Named R colour or hexadecimal code for the
+#' border around the hex.
+#'
+#' @details
+#'
+#' ## Order
+#'
+#' When building a hex, this function should be called after [open_device],
+#' [add_hex] and any calls to [add_text] and [add_image] (in that order), and
+#' before [close_device].
+#'
+#' ## Colours
+#'
+#' 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 (`#`).
#'
#' @returns `NULL`. Adds to an existing graphics device.
#'
+#' @family hex elements
+#'
#' @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)
+#' img_path <- system.file("img", "Rlogo.png", package = "png")
+#' img_png <- png::readPNG(img_path)
+#' add_image(img_png)
#' add_text()
+#' add_border()
+#' close_device()
+add_border <- function(
+ width = 0.05,
+ col = "black"
+) {
+
+ if (!inherits(width, "numeric") || (width < 0 | width > 1)) {
+ stop(
+ "Argument 'width' must be a numeric value between 0 and 1.",
+ call. = FALSE
+ )
+ }
+
+ if (!(col %in% grDevices::colours() | grepl("^#[0-9A-Fa-f]{6,8}$", col))) {
+ stop("Argument 'col' must a named R colour or a hex code.", call. = FALSE)
+ }
+
+ hex_diameter_inner <- 1 - 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"]],
+ default.units = "native"
+ )
+
+ # Inner hexagon will be clipped from outer, leaving a border polygon
+ hex_grob_inner <- grid::polygonGrob(
+ hex_coords_inner[["x"]],
+ hex_coords_inner[["y"]],
+ default.units = "native"
+ )
+
+ border_grob <- gridGeometry::polyclipGrob(
+ A = hex_grob_outer,
+ B = hex_grob_inner,
+ op = "minus", # removes inner from outer
+ gp = grid::gpar(lwd = 0, fill = col)
+ )
+
+ grid::grid.draw(border_grob)
+
+}
+
+
+#' Close the Device and Write to File
+#'
+#' Clip to the area of the outer hexagon and shut down the PNG plot device,
+#' which writes to the `file_path` specified in [open_device].
+#'
+#' @details
+#'
+#' ## Order
+#'
+#' When building a hex, this function should be called at the end, after
+#' [open_device], [add_hex] and any calls to [add_text], [add_image] and
+#' [add_border].
+#'
+#' @returns Named numeric. The device name and number where the hex has been
+#' written.
+#'
+#' @family hex device handlers
+#'
+#' @export
+#'
+#' @examples
+#' temp_path <- tempfile(fileext = ".png")
+#' open_device(temp_path)
+#' add_hex()
+#' img_path <- system.file("img", "Rlogo.png", package = "png")
+#' img_png <- png::readPNG(img_path)
+#' add_image(img_png)
+#' add_text()
+#' add_border()
#' close_device()
close_device <- function() {
- grid::popViewport(0) # clip to outer hexagon
+ grid::popViewport(0) # close all open viewports, clip to outer hexagon
grDevices::dev.off()
}
+
+#' Get Coordinates of Hexagon Vertices
+#' @param diameter Numeric.
+#' @returns A list of two numeric vectors that represent vertex coordinates of a
+#' regular hexagon (point-side down) within a unit-1 square. 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)
+ )
+
+}
diff --git a/README.md b/README.md
index fdf745f..c1b4561 100644
--- a/README.md
+++ b/README.md
@@ -1,96 +1,104 @@
-# {hexbase}
+# {gex}
-[](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)
+[](https://www.repostatus.org/#active)
+[](https://github.com/matt-dray/gex/actions/workflows/R-CMD-check.yaml)
## What
-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).
+An R package to help create simple hexagon-shaped sticker logos 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.
+{gex}:
+
+* is dependency-lightweight
+* lets you add as many text and image elements as you like
+* uses the grid graphics system, so is 'extensible'
+
+The package does what I need it to do but is not fully tested across all systems.
+[Please contribute](https://github.com/matt-dray/gex/issues) if you have bug reports or ideas.
## Install
-You can install {hexbase} [from GitHub](https://github.com/matt-dray/hexbase) like:
+You can install {gex} [from GitHub](https://github.com/matt-dray/gex) like:
``` r
install.packages("remotes") # if not yet installed
-remotes::install_github("matt-dray/hexbase")
+remotes::install_github("matt-dray/gex")
```
-The package only uses {grid} and {grDevices} from base R.
-Otherwise it's BYOIAF ('bring your own images and fonts').
+The package uses the inbuilt {grid} graphics system and the sister package [{gridGeometry}](https://cran.r-project.org/package=gridGeometry).
+The package may include more 'gridverse' packages in future.
## Example
Build a sticker additively with a series of function calls:
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_hex()` to add the underlying hexagon 'canvas'.
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. `add_border()` to put a border around the edge of the hex (add this after images and text to draw over the top of them).
1. `close_device()` to close the PNG graphics device and save to file.
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.
+It's up to the user to read their own images (via {[png](https://cran.r-project.org/package=png)} or {[jpeg](https://cran.r-project.org/package=jpeg)}) and install the fonts they want to use.
+
Below is an extremely basic example.
-Note how you call each function independently (i.e. no pipes), much like writing base plots.
+Note how you call each function independently, much like writing base plots.
``` r
+# Somewhere to save it
+temp_path <- tempfile(fileext = ".png")
+
# Bring your own image
image_path <- system.file("img", "Rlogo.png", package = "png")
image_png <- png::readPNG(image_path)
-# 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
+# Build and write the hex
+gex::open_device(file_path = temp_path)
+gex::add_hex(col = "#BEBEBE") # named or hexadecimal
+gex::add_image(
+ img = image_png,
+ y = 0.6, # 0 to 1 on x and y axes
+ angle = 20,
+ width = 0.5
)
-hexbase::add_text(
- text_string = "example",
- text_y = 0.35,
- text_col = "red",
- text_family = "mono",
- text_face = "bold.italic"
+gex::add_text(
+ string = "example",
+ y = 0.35,
+ col = "red",
+ family = "mono", # bring your own font
+ 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"
+gex::add_text( # add multiple text and images
+ string = "visit https://rstats.lol/ ftw",
+ x = 0.73,
+ y = 0.17,
+ angle = 30,
+ size = 6,
+ col = "blue",
+ family = "serif"
)
-hexbase::close_device()
-
-# Optionally, open the image for inspection
-system(paste("open", temp_path))
+gex::add_border(col = "grey20")
+gex::close_device() # writes to file
```
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.
+From R, you could do this with a `system()` call:
+
+``` r
+# Open the PNG hex image for inspection
+system(paste("open", temp_path))
+```
## Related
diff --git a/hexbase.Rproj b/gex.Rproj
similarity index 100%
rename from hexbase.Rproj
rename to gex.Rproj
diff --git a/inst/images/hexagon.png b/inst/images/hexagon.png
deleted file mode 100644
index d35ef80..0000000
Binary files a/inst/images/hexagon.png and /dev/null differ
diff --git a/inst/tinytest/_tinysnapshot/add-border-args.svg b/inst/tinytest/_tinysnapshot/add-border-args.svg
new file mode 100644
index 0000000..3d3ab19
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/add-border-args.svg
@@ -0,0 +1,26 @@
+
+
diff --git a/inst/tinytest/_tinysnapshot/add-border.svg b/inst/tinytest/_tinysnapshot/add-border.svg
new file mode 100644
index 0000000..59ca96c
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/add-border.svg
@@ -0,0 +1,26 @@
+
+
diff --git a/inst/tinytest/_tinysnapshot/add-hex-args.svg b/inst/tinytest/_tinysnapshot/add-hex-args.svg
new file mode 100644
index 0000000..35069a7
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/add-hex-args.svg
@@ -0,0 +1,33 @@
+
+
diff --git a/inst/tinytest/_tinysnapshot/add-hex.svg b/inst/tinytest/_tinysnapshot/add-hex.svg
new file mode 100644
index 0000000..0e8f12e
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/add-hex.svg
@@ -0,0 +1,33 @@
+
+
diff --git a/inst/tinytest/_tinysnapshot/add-image-args.svg b/inst/tinytest/_tinysnapshot/add-image-args.svg
new file mode 100644
index 0000000..49ae185
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/add-image-args.svg
@@ -0,0 +1,26 @@
+
+
diff --git a/inst/tinytest/_tinysnapshot/add-image.svg b/inst/tinytest/_tinysnapshot/add-image.svg
new file mode 100644
index 0000000..09f9558
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/add-image.svg
@@ -0,0 +1,26 @@
+
+
diff --git a/inst/tinytest/_tinysnapshot/add-text-args.svg b/inst/tinytest/_tinysnapshot/add-text-args.svg
new file mode 100644
index 0000000..e37aabd
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/add-text-args.svg
@@ -0,0 +1,26 @@
+
+
diff --git a/inst/tinytest/_tinysnapshot/add-text.svg b/inst/tinytest/_tinysnapshot/add-text.svg
new file mode 100644
index 0000000..405feb7
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/add-text.svg
@@ -0,0 +1,26 @@
+
+
diff --git a/inst/tinytest/test_gex.R b/inst/tinytest/test_gex.R
new file mode 100644
index 0000000..6d8d55e
--- /dev/null
+++ b/inst/tinytest/test_gex.R
@@ -0,0 +1,215 @@
+library("tinytest")
+using("tinysnapshot")
+options("tinysnapshot_device" = "svglite")
+
+# Open device -------------------------------------------------------------
+
+temp_path <- tempfile(fileext = ".png")
+dev_open <- open_device(temp_path)
+expect_null(dev_open)
+dev_close <- dev.off()
+expect_true(is.numeric(dev_close))
+unlink(temp_path)
+
+err_arg <- 'argument "file_path" is missing, with no default'
+expect_error(open_device(), err_arg)
+
+err_png <- "Argument 'file_path' must end with '\\.png'\\."
+expect_error(open_device("x"), err_png)
+expect_error(open_device("x/y"), err_png)
+expect_error(open_device("x/y.pdf"), err_png)
+
+err_dir <- "Argument 'file_path' must resolve to an existing directory\\."
+expect_error(open_device("x/y/z.png", err_dir))
+
+# Add hex -----------------------------------------------------------------
+
+hex <- add_hex()
+expect_null(hex)
+
+tinysnapshot::expect_snapshot_plot(
+ function() add_hex(),
+ label = "add-hex"
+)
+
+tinysnapshot::expect_snapshot_plot(
+ function() add_hex(col = "red"),
+ label = "add-hex-args"
+)
+
+temp_path <- tempfile(fileext = ".png")
+open_device(temp_path)
+add_hex()
+dev_close <- dev.off()
+expect_true(is.numeric(dev_close))
+unlink(temp_path)
+
+err_col <- "Argument 'col' must a named R colour or a hex code\\."
+expect_error(add_hex(1), err_col)
+expect_error(add_hex("x"), err_col)
+expect_error(add_hex("#0011"), err_col)
+expect_error(add_hex("#0011223344"), err_col)
+expect_error(add_hex("001122"), err_col)
+
+# Add text ----------------------------------------------------------------
+
+txt <- add_text()
+expect_null(txt)
+
+tinysnapshot::expect_snapshot_plot(
+ function() add_text(),
+ label = "add-text"
+)
+
+tinysnapshot::expect_snapshot_plot(
+ function() {
+ add_text(
+ string = "test",
+ x = 0.4,
+ y = 0.6,
+ angle = 30,
+ size = 25,
+ col = "red",
+ family = "mono",
+ face = "bold"
+ )
+ },
+ label = "add-text-args"
+)
+
+temp_path <- tempfile(fileext = ".png")
+open_device(temp_path)
+add_hex()
+add_text()
+dev_close <- dev.off()
+expect_true(is.numeric(dev_close))
+unlink(temp_path)
+
+err_str <- "Argument 'string' must be a character string\\."
+expect_error(add_text(string = 1), err_str)
+
+err_xy <- "Arguments 'x' and 'y' must be numeric values\\."
+expect_error(add_text(x = "x"), err_xy)
+expect_error(add_text(y = "y"), err_xy)
+
+err_angle <- "Argument 'angle' must be a numeric value\\."
+expect_error(add_text(angle = "x"), err_angle)
+
+err_size <- "Argument 'size' must be a numeric value\\."
+expect_error(add_text(size = "x"), err_size)
+
+err_col <- "Argument 'col' must a named R colour or a hex code\\."
+expect_error(add_text(col = 1), err_col)
+expect_error(add_text(col = "x"), err_col)
+expect_error(add_text(col = "#0011"), err_col)
+expect_error(add_text(col = "#0011223344"), err_col)
+expect_error(add_text(col = "001122"), err_col)
+
+err_fam <- paste(
+ "Argument 'family' must be a character string representing",
+ "an available font family\\."
+)
+expect_error(add_text(family = 1), err_fam)
+err_fam_2 <- "invalid font type"
+expect_error(suppressWarnings(add_text(family = "x")), err_fam_2)
+
+err_face <- paste(
+ "Argument 'face' must be one of the following character strings:",
+ "'plain', 'bold', 'italic', 'bold\\.italic'\\."
+)
+expect_error(add_text(face = 1), err_face)
+err_face_2 <- '\'arg\' should be one of "plain", "bold", "italic", "bold\\.italic"'
+expect_error(add_text(face = "x"), err_face_2)
+
+# Add image ---------------------------------------------------------------
+
+img_path <- system.file("img", "Rlogo.png", package = "png")
+img_png <- png::readPNG(img_path)
+img <- add_image(img_png)
+expect_null(img)
+
+tinysnapshot::expect_snapshot_plot(
+ function() add_image(img_png),
+ label = "add-image"
+)
+
+tinysnapshot::expect_snapshot_plot(
+ function() {
+ add_image(
+ img = img_png,
+ x = 0.6,
+ y = 0.4,
+ angle = 30,
+ width = 0.5
+ )
+ },
+ label = "add-image-args"
+)
+
+temp_path <- tempfile(fileext = ".png")
+open_device(temp_path)
+add_hex()
+add_image(img_png)
+dev_close <- dev.off()
+expect_true(is.numeric(dev_close))
+unlink(temp_path)
+
+err_img <- "Argument 'img' must be an array \\(a png or jpeg file\\)\\."
+expect_error(add_image(img = 1), err_img)
+expect_error(add_image(img = "x"), err_img)
+
+err_xy <- "Arguments 'x' and 'y' must be numeric values\\."
+expect_error(add_image(img_png, x = "x"), err_xy)
+expect_error(add_image(img_png, y = "y"), err_xy)
+
+err_angle <- "Argument 'angle' must be a numeric value\\."
+expect_error(add_image(img_png, angle = "x"), err_angle)
+
+err_width <- "Argument 'width' must be a numeric value\\."
+expect_error(add_image(img_png, width = "x"), err_width)
+
+# Add border --------------------------------------------------------------
+
+border <- add_border()
+expect_null(border)
+
+tinysnapshot::expect_snapshot_plot(
+ function() add_border(),
+ label = "add-border"
+)
+
+tinysnapshot::expect_snapshot_plot(
+ function() add_border(width = 0.1, col = "red"),
+ label = "add-border-args"
+)
+
+temp_path <- tempfile(fileext = ".png")
+open_device(temp_path)
+add_hex()
+add_border()
+dev_close <- dev.off()
+expect_true(is.numeric(dev_close))
+unlink(temp_path)
+
+err_col <- "Argument 'col' must a named R colour or a hex code\\."
+expect_error(add_border(col = 1), err_col)
+expect_error(add_border(col = "x"), err_col)
+expect_error(add_border(col = "#0011"), err_col)
+expect_error(add_border(col = "#0011223344"), err_col)
+expect_error(add_border(col = "001122"), err_col)
+
+err_width <- "Argument 'width' must be a numeric value between 0 and 1\\."
+expect_error(add_border(width = -1), err_width)
+expect_error(add_border(width = 2), err_width)
+expect_error(add_border(width = "x"), err_width)
+
+# Close device ------------------------------------------------------------
+
+expect_error(close_device("x"), 'unused argument \\("x"\\)')
+
+temp_path <- tempfile(fileext = ".png")
+open_device(temp_path)
+add_hex()
+dev_off <- close_device()
+expect_true(is.numeric(dev_close))
+unlink(temp_path)
diff --git a/man/add_border.Rd b/man/add_border.Rd
new file mode 100644
index 0000000..9146d45
--- /dev/null
+++ b/man/add_border.Rd
@@ -0,0 +1,53 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/hexagon.R
+\name{add_border}
+\alias{add_border}
+\title{Add a Border to the Edge of the Hexagon}
+\usage{
+add_border(width = 0.05, col = "black")
+}
+\arguments{
+\item{width}{Numeric. Thickness of the border, expressed as the
+inverse ratio of the interior of the hex to the full extent of the hex
+(must be between \code{0} and \code{1}).}
+
+\item{col}{Character. Named R colour or hexadecimal code for the
+border around the hex.}
+}
+\value{
+\code{NULL}. Adds to an existing graphics device.
+}
+\description{
+Add a border of given thickness and colour to the inner edges of hexagon.
+}
+\details{
+\subsection{Order}{
+
+When building a hex, this function should be called after \link{open_device},
+\link{add_hex} and any calls to \link{add_text} and \link{add_image} (in that order), and
+before \link{close_device}.
+}
+
+\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()
+img_path <- system.file("img", "Rlogo.png", package = "png")
+img_png <- png::readPNG(img_path)
+add_image(img_png)
+add_text()
+add_border()
+close_device()
+}
+\seealso{
+Other hex elements:
+\code{\link{add_hex}()}
+}
+\concept{hex elements}
diff --git a/man/add_hex.Rd b/man/add_hex.Rd
index 74baa34..d4f5f1a 100644
--- a/man/add_hex.Rd
+++ b/man/add_hex.Rd
@@ -2,28 +2,28 @@
% Please edit documentation in R/hexagon.R
\name{add_hex}
\alias{add_hex}
-\title{Add a Hexagon with a Border}
+\title{Add a Hexagon}
\usage{
-add_hex(border_width = 0.05, border_col = "black", bg_col = "grey")
+add_hex(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
+\item{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.
+Add a hexagon 'canvas' to which elements can be added.
}
\details{
+\subsection{Order}{
+
+When building a hex, this function should be called after \link{open_device}. You can then use
+\link{add_text}, \link{add_image} and \link{add_border} (if desired) and finally
+\link{close_device}.
+}
+
\subsection{Colours}{
Named colour values must be listed in \code{\link[grDevices:colors]{grDevices::colours()}}. Hexadecimal
@@ -35,9 +35,15 @@ octothorpe (\verb{#}).
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)
+img_path <- system.file("img", "Rlogo.png", package = "png")
+img_png <- png::readPNG(img_path)
+add_image(img_png)
add_text()
+add_border()
close_device()
}
+\seealso{
+Other hex elements:
+\code{\link{add_border}()}
+}
+\concept{hex elements}
diff --git a/man/add_image.Rd b/man/add_image.Rd
index f540d00..c78c34b 100644
--- a/man/add_image.Rd
+++ b/man/add_image.Rd
@@ -2,37 +2,37 @@
% Please edit documentation in R/hexagon.R
\name{add_image}
\alias{add_image}
-\title{Add an Image}
+\title{Add an Image to the Hexagon}
\usage{
-add_image(
- image_object,
- image_x = 0.5,
- image_y = 0.7,
- image_angle = 0,
- image_width = 0.4
-)
+add_image(img, x = 0.5, y = 0.7, angle = 0, width = 0.4)
}
\arguments{
-\item{image_object}{Array. A PNG file read in by the user. \code{NULL} for no
-image.}
+\item{img}{Array. A PNG or JPEG file read in by the user, most likely
+using packages 'png' or 'jpeg'.}
-\item{image_x}{Numeric. Image location x-axis.}
+\item{x}{Numeric. Image location on the hexagon's x-axis.}
-\item{image_y}{Numeric. Image location y-axis.}
+\item{y}{Numeric. Image location on the hexagon's y-axis.}
-\item{image_angle}{Numeric. Text rotation in degrees.}
+\item{angle}{Numeric. Text rotation in degrees.}
-\item{image_width}{Numeric. Image width.}
+\item{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.
+Overlay an image on the hexagon. Call this function separately for each image
+you want to add.
}
\details{
+\subsection{Order}{
+
+When building a hex, this function should be called after \link{open_device} and
+\link{add_hex}. You can then use further calls to \link{add_image}, \link{add_text} and
+\link{add_border} (if desired) and finally \link{close_device}.
+}
+
\subsection{Coordinates}{
Coordinates should be provided within the x- and y-axis ranges, which are
@@ -43,9 +43,15 @@ both from 0 to 1, giving the centre as x = 0.5 and y = 0.5.
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)
+img_path <- system.file("img", "Rlogo.png", package = "png")
+img_png <- png::readPNG(img_path)
+add_image(img_png)
add_text()
+add_border()
close_device()
}
+\seealso{
+Other hex content adders:
+\code{\link{add_text}()}
+}
+\concept{hex content adders}
diff --git a/man/add_text.Rd b/man/add_text.Rd
index 8471f85..44e0186 100644
--- a/man/add_text.Rd
+++ b/man/add_text.Rd
@@ -2,47 +2,53 @@
% Please edit documentation in R/hexagon.R
\name{add_text}
\alias{add_text}
-\title{Add Text}
+\title{Add Text to the Hexagon}
\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")
+ string = "example",
+ x = 0.5,
+ y = 0.4,
+ angle = 0,
+ size = 20,
+ col = "black",
+ family = "sans",
+ face = c("plain", "bold", "italic", "bold.italic")
)
}
\arguments{
-\item{text_string}{Character. Text to display. \code{NULL} (or an empty string) if
+\item{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{x}{Numeric. Text location on the hexagon's x-axis.}
-\item{text_y}{Numeric. Text location y-axis.}
+\item{y}{Numeric. Text location on the hexagon's y-axis.}
-\item{text_angle}{Numeric. Rotation of text string in degrees. Positive
+\item{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{size}{Numeric. Text point-size.}
-\item{text_col}{Character. Text colour. A named R colour or hexadecimal code.}
+\item{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{family}{Character. Name of a font family available on your system.}
-\item{text_face}{Character. Font face for the text.}
+\item{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.
+Overlay text on the hexagon. Call this function separately for each string
+you want to add.
}
\details{
+\subsection{Order}{
+
+When building a hex, this function should be called after \link{open_device} and
+\link{add_hex}. You can then use further calls to \link{add_text}, \link{add_image} and
+\link{add_border} (if desired) and finally \link{close_device}.
+}
+
\subsection{Coordinates}{
Coordinates should be provided within the x- and y-axis ranges, which are
@@ -60,9 +66,15 @@ octothorpe (\verb{#}).
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)
+img_path <- system.file("img", "Rlogo.png", package = "png")
+img_png <- png::readPNG(img_path)
+add_image(img_png)
add_text()
+add_border()
close_device()
}
+\seealso{
+Other hex content adders:
+\code{\link{add_image}()}
+}
+\concept{hex content adders}
diff --git a/man/close_device.Rd b/man/close_device.Rd
index e6e0ef3..690b952 100644
--- a/man/close_device.Rd
+++ b/man/close_device.Rd
@@ -2,24 +2,39 @@
% Please edit documentation in R/hexagon.R
\name{close_device}
\alias{close_device}
-\title{Close the Device}
+\title{Close the Device and Write to File}
\usage{
close_device()
}
\value{
-\code{NULL}. Adds to an existing graphics device.
+Named numeric. The device name and number where the hex has been
+written.
}
\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}.
+Clip to the area of the outer hexagon and shut down the PNG plot device,
+which writes to the \code{file_path} specified in \link{open_device}.
+}
+\details{
+\subsection{Order}{
+
+When building a hex, this function should be called at the end, after
+\link{open_device}, \link{add_hex} and any calls to \link{add_text}, \link{add_image} and
+\link{add_border}.
+}
}
\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)
+img_path <- system.file("img", "Rlogo.png", package = "png")
+img_png <- png::readPNG(img_path)
+add_image(img_png)
add_text()
+add_border()
close_device()
}
+\seealso{
+Other hex device handlers:
+\code{\link{open_device}()}
+}
+\concept{hex device handlers}
diff --git a/man/figures/logo.png b/man/figures/logo.png
deleted file mode 100644
index 90226ad..0000000
Binary files a/man/figures/logo.png and /dev/null differ
diff --git a/man/gex-package.Rd b/man/gex-package.Rd
new file mode 100644
index 0000000..1cd29ee
--- /dev/null
+++ b/man/gex-package.Rd
@@ -0,0 +1,23 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/gex-package.R
+\docType{package}
+\name{gex-package}
+\alias{gex}
+\alias{gex-package}
+\title{gex: A Dependency-Light Hex-Logo Builder}
+\description{
+A simple interface to create hexagon-shaped logos that help promote your R package or other projects. Uses the 'grid' system.
+}
+\seealso{
+Useful links:
+\itemize{
+ \item \url{https://github.com/matt-dray/gex}
+ \item Report bugs at \url{https://github.com/matt-dray/gex/bugs}
+}
+
+}
+\author{
+\strong{Maintainer}: Matt Dray \email{mwdray@gmail.com}
+
+}
+\keyword{internal}
diff --git a/man/hexbase-package.Rd b/man/hexbase-package.Rd
deleted file mode 100644
index 5372f0a..0000000
--- a/man/hexbase-package.Rd
+++ /dev/null
@@ -1,25 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/hexbase-package.R
-\docType{package}
-\name{hexbase-package}
-\alias{hexbase}
-\alias{hexbase-package}
-\title{hexbase: Create Simple Dependency-Free Hex Logos}
-\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 base R only.
-}
-\seealso{
-Useful links:
-\itemize{
- \item \url{https://github.com/matt-dray/hexbase}
- \item Report bugs at \url{https://github.com/matt-dray/hexbase/bugs}
-}
-
-}
-\author{
-\strong{Maintainer}: Matt Dray \email{mwdray@gmail.com}
-
-}
-\keyword{internal}
diff --git a/man/open_device.Rd b/man/open_device.Rd
index 68e8b24..8db1321 100644
--- a/man/open_device.Rd
+++ b/man/open_device.Rd
@@ -2,13 +2,13 @@
% Please edit documentation in R/hexagon.R
\name{open_device}
\alias{open_device}
-\title{Open a Device}
+\title{Open a PNG Device with Sticker-Standard Dimensions}
\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.}
+\item{file_path}{Character. 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.
@@ -18,13 +18,27 @@ 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).
}
+\details{
+\subsection{Order}{
+
+When building a hex, this function should be called first, followed by
+\link{add_hex}. You can then use \link{add_text}, \link{add_image} and \link{add_border} (if
+desired) and finally \link{close_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)
+img_path <- system.file("img", "Rlogo.png", package = "png")
+img_png <- png::readPNG(img_path)
+add_image(img_png)
add_text()
+add_border()
close_device()
}
+\seealso{
+Other hex device handlers:
+\code{\link{close_device}()}
+}
+\concept{hex device handlers}
diff --git a/tests/tinytest.R b/tests/tinytest.R
new file mode 100644
index 0000000..77d9df4
--- /dev/null
+++ b/tests/tinytest.R
@@ -0,0 +1,12 @@
+# Throttle magick CPU threads if R CMD check (for CRAN)
+# See https://github.com/vincentarelbundock/tinysnapshot?tab=readme-ov-file#cran-multithreading-warning
+if (any(grepl("_R_CHECK", names(Sys.getenv()), fixed = TRUE))) {
+ if (requireNamespace("magick", quietly = TRUE)) {
+ library(magick)
+ magick:::magick_threads(1)
+ }
+}
+
+if (requireNamespace("tinytest", quietly = TRUE)) {
+ tinytest::test_package("gex")
+}