Skip to content

Commit

Permalink
updated text_width to match arguments for shape_text
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasp85 committed Dec 6, 2024
1 parent 26df170 commit 44178e8
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 54 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
width (#45)
* Fixed a mismatch between the default values of the `width` argument in
`shape_text()` and `systemfonts::match_fonts()` (#44)
* Updated `text_width()` to take the same inputs as `shape_text()`

# textshaping 0.4.0

Expand Down
4 changes: 2 additions & 2 deletions R/cpp11.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ get_string_shape_c <- function(string, id, path, index, features, size, res, lin
.Call(`_textshaping_get_string_shape_c`, string, id, path, index, features, size, res, lineheight, align, hjust, vjust, width, tracking, indent, hanging, space_before, space_after)
}

get_line_width_c <- function(string, path, index, size, res, include_bearing) {
.Call(`_textshaping_get_line_width_c`, string, path, index, size, res, include_bearing)
get_line_width_c <- function(string, path, index, size, res, include_bearing, features) {
.Call(`_textshaping_get_line_width_c`, string, path, index, size, res, include_bearing, features)
}
54 changes: 32 additions & 22 deletions R/shape_text.R
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,13 @@ shape_text <- function(strings, id = NULL, family = '', italic = FALSE,
}
#' Calculate the width of a string, ignoring new-lines
#'
#' This is a very simple alternative to [shape_string()] that simply calculates
#' the width of strings without taking any newline into account. As such it is
#' suitable to calculate the width of words or lines that has already been
#' splitted by `\n`. Input is recycled to the length of `strings`.
#' This is a very simple alternative to [systemfonts::shape_string()] that
#' simply calculates the width of strings without taking any newline into
#' account. As such it is suitable to calculate the width of words or lines that
#' has already been splitted by `\n`. Input is recycled to the length of
#' `strings`.
#'
#' @inheritParams systemfonts::font_info
#' @inheritParams shape_text
#' @param strings A character vector of strings
#' @param include_bearing Logical, should left and right bearing be included in
#' the string width?
Expand All @@ -190,30 +191,39 @@ shape_text <- function(strings, id = NULL, family = '', italic = FALSE,
#' strings <- c('A short string', 'A very very looong string')
#' text_width(strings)
#'
text_width <- function(strings, family = '', italic = FALSE, bold = FALSE,
text_width <- function(strings, family = '', italic = FALSE, weight = 'normal',
width = 'undefined', features = font_feature(),
size = 12, res = 72, include_bearing = TRUE, path = NULL,
index = 0) {
index = 0, bold = deprecated()) {
n_strings <- length(strings)

if (lifecycle::is_present(bold)) {
lifecycle::deprecate_soft("0.4.1", "text_width(bold)", "text_width(weight='bold')")
weight <- ifelse(bold, "bold", "normal")
}

if (inherits(features, 'font_feature')) features <- list(features)
features <- rep_len(features, n_strings)

if (is.null(path)) {
fonts <- match_fonts(
rep_len(family, n_strings),
rep_len(italic, n_strings),
ifelse(rep_len(bold, n_strings), "bold", "normal")
)
path <- fonts$path
index <- fonts$index
family <- rep_len(family, n_strings)
italic <- rep_len(italic, n_strings)
weight <- rep_len(weight, n_strings)
width <- rep_len(width, n_strings)
loc <- match_fonts(family, italic, weight, width)
path <- loc$path
index <- loc$index
features <- Map(c, loc$features, features)
} else {
if (!all(c(length(path), length(index)) == 1)) {
path <- rep_len(path, n_strings)
index <- rep_len(index, n_strings)
}
path <- rep_len(path, n_strings)
index <- rep_len(index, n_strings)
}
if (length(size) != 1) size <- rep_len(size, n_strings)
if (length(res) != 1) res <- rep_len(res, n_strings)
if (length(include_bearing) != 1) include_bearing <- rep_len(include_bearing, n_strings)
size <- rep_len(size, n_strings)
res <- rep_len(res, n_strings)
include_bearing <- rep_len(include_bearing, n_strings)
if (!all(file.exists(path))) stop("path must point to a valid file", call. = FALSE)
get_line_width_c(
as.character(strings), path, as.integer(index), as.numeric(size),
as.numeric(res), as.logical(include_bearing)
as.numeric(res), as.logical(include_bearing), features
)
}
38 changes: 29 additions & 9 deletions man/text_width.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions src/cpp11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ extern "C" SEXP _textshaping_get_string_shape_c(SEXP string, SEXP id, SEXP path,
END_CPP11
}
// string_metrics.h
doubles get_line_width_c(strings string, strings path, integers index, doubles size, doubles res, logicals include_bearing);
extern "C" SEXP _textshaping_get_line_width_c(SEXP string, SEXP path, SEXP index, SEXP size, SEXP res, SEXP include_bearing) {
doubles get_line_width_c(strings string, strings path, integers index, doubles size, doubles res, logicals include_bearing, list_of<list> features);
extern "C" SEXP _textshaping_get_line_width_c(SEXP string, SEXP path, SEXP index, SEXP size, SEXP res, SEXP include_bearing, SEXP features) {
BEGIN_CPP11
return cpp11::as_sexp(get_line_width_c(cpp11::as_cpp<cpp11::decay_t<strings>>(string), cpp11::as_cpp<cpp11::decay_t<strings>>(path), cpp11::as_cpp<cpp11::decay_t<integers>>(index), cpp11::as_cpp<cpp11::decay_t<doubles>>(size), cpp11::as_cpp<cpp11::decay_t<doubles>>(res), cpp11::as_cpp<cpp11::decay_t<logicals>>(include_bearing)));
return cpp11::as_sexp(get_line_width_c(cpp11::as_cpp<cpp11::decay_t<strings>>(string), cpp11::as_cpp<cpp11::decay_t<strings>>(path), cpp11::as_cpp<cpp11::decay_t<integers>>(index), cpp11::as_cpp<cpp11::decay_t<doubles>>(size), cpp11::as_cpp<cpp11::decay_t<doubles>>(res), cpp11::as_cpp<cpp11::decay_t<logicals>>(include_bearing), cpp11::as_cpp<cpp11::decay_t<list_of<list>>>(features)));
END_CPP11
}

extern "C" {
static const R_CallMethodDef CallEntries[] = {
{"_textshaping_get_face_features_c", (DL_FUNC) &_textshaping_get_face_features_c, 2},
{"_textshaping_get_line_width_c", (DL_FUNC) &_textshaping_get_line_width_c, 6},
{"_textshaping_get_line_width_c", (DL_FUNC) &_textshaping_get_line_width_c, 7},
{"_textshaping_get_string_shape_c", (DL_FUNC) &_textshaping_get_string_shape_c, 17},
{NULL, NULL, 0}
};
Expand Down
33 changes: 17 additions & 16 deletions src/string_metrics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,32 +266,33 @@ list get_string_shape_c(strings string, integers id, strings path, integers inde
}

doubles get_line_width_c(strings string, strings path, integers index, doubles size,
doubles res, logicals include_bearing) {
doubles res, logicals include_bearing, list_of<list> features) {
int n_strings = string.size();
writable::doubles widths;
if (n_strings != 0) {
bool one_path = path.size() == 1;
const char* first_path = Rf_translateCharUTF8(path[0]);
int first_index = index[0];
bool one_size = size.size() == 1;
double first_size = size[0];
bool one_res = res.size() == 1;
double first_res = res[0];
bool one_bear = include_bearing.size() == 1;
int first_bear = include_bearing[0];
if (n_strings != path.size() ||
n_strings != index.size() ||
n_strings != features.size() ||
n_strings != size.size() ||
n_strings != res.size() ||
n_strings != include_bearing.size()
) {
cpp11::stop("All input must be the same size");
}

auto all_features = create_font_features(features);
auto fonts = create_font_settings(path, index, all_features);

int error = 1;
double width = 0;

for (int i = 0; i < n_strings; ++i) {
error = string_width(
error = ts_string_width(
Rf_translateCharUTF8(string[i]),
one_path ? first_path : Rf_translateCharUTF8(path[i]),
one_path ? first_index : index[i],
one_size ? first_size : size[i],
one_res ? first_res : res[i],
one_bear ? first_bear : static_cast<int>(include_bearing[0]),
fonts[i],
size[i],
res[i],
static_cast<int>(include_bearing[0]),
&width
);
if (error) {
Expand Down
2 changes: 1 addition & 1 deletion src/string_metrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ list get_string_shape_c(strings string, integers id, strings path, integers inde

[[cpp11::register]]
doubles get_line_width_c(strings string, strings path, integers index, doubles size,
doubles res, logicals include_bearing);
doubles res, logicals include_bearing, list_of<list> features);
int ts_string_width(const char* string, FontSettings font_info,
double size, double res, int include_bearing, double* width);
int ts_string_shape(const char* string, FontSettings font_info, double size,
Expand Down

0 comments on commit 44178e8

Please sign in to comment.