Title: | System Native Font Finding |
---|---|
Description: | Provides system native access to the font catalogue. As font handling varies between systems it is difficult to correctly locate installed fonts across different operating systems. The 'systemfonts' package provides bindings to the native libraries on Windows, macOS and Linux for finding font files that can then be used further by e.g. graphic devices. The main use is intended to be from compiled code but 'systemfonts' also provides access from R. |
Authors: | Thomas Lin Pedersen [aut, cre] , Jeroen Ooms [aut] , Devon Govett [aut] (Author of font-manager), Posit, PBC [cph, fnd] |
Maintainer: | Thomas Lin Pedersen <[email protected]> |
License: | MIT + file LICENSE |
Version: | 1.1.0 |
Built: | 2024-11-11 07:30:01 UTC |
Source: | CRAN |
A fallback font is a font to use as a substitute if the chosen font does not contain the requested characters. Using font fallbacks means that the user doesn't have to worry about mixing characters from different scripts or mixing text and emojies. Fallback is calculated for the full string and the result is platform specific. If no font covers all the characters in the string an undefined "best match" is returned. The best approach is to figure out which characters are not covered by your chosen font and figure out fallbacks for these, rather than just request a fallback for the full string.
font_fallback( string, family = "", italic = FALSE, bold = FALSE, path = NULL, index = 0 )
font_fallback( string, family = "", italic = FALSE, bold = FALSE, path = NULL, index = 0 )
string |
The strings to find fallbacks for |
family |
The name of the font families to match |
italic |
logical indicating the font slant |
bold |
logical indicating whether the font weight |
path , index
|
path an index of a font file to circumvent lookup based on family and style |
A data frame with a path
and index
column giving fallback for the
specified string and font combinations
font_fallback("\U0001f604") # Smile emoji
font_fallback("\U0001f604") # Smile emoji
This function encapsulates the specification of OpenType font features. Some specific features have named arguments, but all available features can be set by using its specific 4-letter tag For a list of the 4-letter tags available see e.g. the overview on Wikipedia.
font_feature(ligatures = NULL, letters = NULL, numbers = NULL, ...)
font_feature(ligatures = NULL, letters = NULL, numbers = NULL, ...)
ligatures |
Settings related to ligatures. One or more types of ligatures to turn on (see details). |
letters |
Settings related to the appearance of single letters (as opposed to ligatures that substitutes multiple letters). See details for supported values. |
numbers |
Settings related to the appearance of numbers. See details for supported values. |
... |
key-value pairs with the key being the 4-letter tag and the value
being the setting (usually |
OpenType features are defined by a 4-letter tag along with an integer value.
Often that value is a simple 0
(off) or 1
(on), but some features support
additional values, e.g. stylistic alternates (salt
) where a font may
provide multiple variants of a letter and the value will be used to chose
which one to use.
Common features related to appearance may be given with a long form name to
either the ligatures
, letters
, or numbers
argument to avoid remembering
the often arbitrary 4-letter tag. Providing a long form name is the same as
setting the tag to 1
and can thus not be used to set tags to other values.
The possible long form names are given below with the tag in parenthesis:
Ligatures
standard
(liga): Turns on standard multiple letter substitution
historical
(hlig): Use obsolete historical ligatures
contextual
(clig): Apply secondary ligatures based on the character
patterns surrounding the potential ligature
discretionary
(dlig): Use ornamental ligatures
Letters
swash
(cswh): Use contextual swashes (ornamental decorations)
alternates
(calt): Use alternate letter forms based on the sourrounding
pattern
historical
(hist): Use obsolete historical forms of the letters
localized
(locl): Use alternate forms preferred by the script language
randomize
(rand): Use random variants of the letters (e.g. to mimick
handwriting)
alt_annotation
(nalt): Use alternate annotations (e.g. circled digits)
stylistic
(salt): Use a stylistic alternative form of the letter
subscript
(subs): Set letter in subscript
superscript
(sups): Set letter in superscript
titling
(titl): Use letter forms well suited for large text and titles
small_caps
(smcp): Use small caps variants of the letters
Numbers
lining
(lnum): Use number variants that rest on the baseline
oldstyle
(onum): Use old style numbers that use descender and ascender
for various numbers
proportional
(pnum): Let numbers take up width based on the visual
width of the glyph
tabular
(tnum): Enforce all numbers to take up the same width
fractions
(frac): Convert numbers separated by /
into a fraction
glyph
fractions_alt
(afrc): Use alternate fraction form with a horizontal
divider
A font_feature
object
font_feature(letters = "stylistic", numbers = c("lining", "tabular")) # Use the tag directly to access additional stylistic variants font_feature(numbers = c("lining", "tabular"), salt = 2)
font_feature(letters = "stylistic", numbers = c("lining", "tabular")) # Use the tag directly to access additional stylistic variants font_feature(numbers = c("lining", "tabular"), salt = 2)
Get general information about a font, relative to a given size. Size specific measures will be returned in pixel units. The function is vectorised to the length of the longest argument.
font_info( family = "", italic = FALSE, bold = FALSE, size = 12, res = 72, path = NULL, index = 0 )
font_info( family = "", italic = FALSE, bold = FALSE, size = 12, res = 72, path = NULL, index = 0 )
family |
The name of the font families to match |
italic |
logical indicating the font slant |
bold |
logical indicating whether the font weight |
size |
The pointsize of the font to use for size related measures |
res |
The ppi of the size related mesures |
path , index
|
path an index of a font file to circumvent lookup based on family and style |
A data.frame giving info on the requested font + size combinations. The data.frame will contain the following columns:
The path to the font file
The 0-based index of the font in the fontfile
The family name of the font
The style name of the font
A logical giving if the font is italic
A logical giving if the font is bold
A logical giving if the font is monospace
A factor giving the weight of the font
A factor giving the width of the font
A logical giving if the font supports kerning
A logical giving if the font has color glyphs
A logical giving if the font is scalable
A logical giving if the font is vertical
The number of glyphs in the font
The number of predefined sizes in the font
The number of character mappings in the font file
A bounding box large enough to contain any of the glyphs in the font
The maximum ascend of the tallest glyph in the font
The maximum descend of the most descending glyph in the font
The maximum horizontal advance a glyph can make
The maximum vertical advance a glyph can make
The height of a single line of text in the font
The position of a potential underlining segment
The width the the underline
font_info('serif') # Avoid lookup if font file is already known sans <- match_fonts('sans') font_info(path = sans$path, index = sans$index)
font_info('serif') # Avoid lookup if font file is already known sans <- match_fonts('sans') font_info(path = sans$path, index = sans$index)
This function allows you to extract information about the individual glyphs
in a font, based on a specified size. All size related measures are in
pixel-units. The function is vectorised to the length of the glyphs
vector.
glyph_info( glyphs, family = "", italic = FALSE, bold = FALSE, size = 12, res = 72, path = NULL, index = 0 )
glyph_info( glyphs, family = "", italic = FALSE, bold = FALSE, size = 12, res = 72, path = NULL, index = 0 )
glyphs |
A vector of glyphs. Strings will be split into separate glyphs automatically |
family |
The name of the font families to match |
italic |
logical indicating the font slant |
bold |
logical indicating whether the font weight |
size |
The pointsize of the font to use for size related measures |
res |
The ppi of the size related mesures |
path , index
|
path an index of a font file to circumvent lookup based on family and style |
A data.frame with information about each glyph, containing the following columns:
The glyph as a character
The index of the glyph in the font file
The width of the glyph
The height of the glyph
The horizontal distance from the origin to the leftmost part of the glyph
The vertical distance from the origin to the top part of the glyph
The horizontal distance to move the cursor after adding the glyph
The vertical distance to move the cursor after adding the glyph
The tight bounding box surrounding the glyph
This function locates the font file (and index) best matching a name and
optional style. A font file will be returned even if a perfect match
isn't found, but it is not necessarily similar to the requested family and
it should not be relied on for font substitution. The aliases "sans"
,
"serif"
, "mono"
, "symbol"
, and "emoji"
match to their respective
system defaults (""
is equivalent to "sans"
). match_font()
has been
deprecated in favour of match_fonts()
which provides vectorisation, as well
as querying for different weights (rather than just "normal" and "bold") as
well as different widths.
match_fonts(family, italic = FALSE, weight = "normal", width = "undefined") match_font(family, italic = FALSE, bold = FALSE)
match_fonts(family, italic = FALSE, weight = "normal", width = "undefined") match_font(family, italic = FALSE, bold = FALSE)
family |
The name of the font families to match |
italic |
logical indicating the font slant |
weight |
The weight to query for, either in numbers ( |
width |
The width to query for either in numbers ( |
bold |
logical indicating whether the font weight |
A list containing the paths locating the font files, the 0-based index of the font in the files and the features for the font in case a registered font was located.
# Get the system default sans-serif font in italic match_fonts('sans', italic = TRUE) # Try to match it to a thin variant match_fonts(c('sans', 'serif'), weight = "thin")
# Get the system default sans-serif font in italic match_fonts('sans', italic = TRUE) # Try to match it to a thin variant match_fonts(c('sans', 'serif'), weight = "thin")
By design, systemfonts searches the fonts installed natively on the system.
It is possible, however, to register other fonts from e.g. font packages or
local font files, that will get searched before searching any installed
fonts. You can always get an overview over all registered fonts with the
registry_fonts()
function that works as a registry focused analogue to
system_fonts()
. If you wish to clear out the registry, you can either
restart the R session or call clear_registry()
.
register_font( name, plain, bold = plain, italic = plain, bolditalic = plain, features = font_feature() ) registry_fonts() clear_registry()
register_font( name, plain, bold = plain, italic = plain, bolditalic = plain, features = font_feature() ) registry_fonts() clear_registry()
name |
The name the collection will be known under (i.e. family) |
plain , bold , italic , bolditalic
|
Fontfiles for the different faces of the
collection. can either be a filepath or a list containing a filepath and an
index (only for font files containing multiple fonts). If not given it will
default to the |
features |
A |
register_font
also makes it possible to use system fonts with traits that
is not covered by the graphic engine in R. In plotting operations it is only
possible to specify a family name and whether or not the font should be bold
and/or italic. There are numerous fonts that will never get matched to this,
especially because bold is only one of many weights.
Apart from granting a way to use new varieties of fonts, font registration
also allows you to override the default sans
, serif
, and mono
mappings,
simply by registering a collection to the relevant default name. As
registered fonts are searched first it will take precedence over the default.
register_font()
and clear_registry()
returns NULL
invisibly.
registry_fonts()
returns a data table in the same style as system_fonts()
though less detailed and not based on information in the font file.
# Create a random font collection fonts <- system_fonts() plain <- sample(which(!fonts$italic & fonts$weight <= 'normal'), 1) bold <- sample(which(!fonts$italic & fonts$weight > 'normal'), 1) italic <- sample(which(fonts$italic & fonts$weight <= 'normal'), 1) bolditalic <- sample(which(fonts$italic & fonts$weight > 'normal'), 1) register_font( 'random', plain = list(fonts$path[plain], fonts$index[plain]), bold = list(fonts$path[bold], fonts$index[bold]), italic = list(fonts$path[italic], fonts$index[italic]), bolditalic = list(fonts$path[bolditalic], fonts$index[bolditalic]) ) # Look at your creation registry_fonts() # Reset clear_registry()
# Create a random font collection fonts <- system_fonts() plain <- sample(which(!fonts$italic & fonts$weight <= 'normal'), 1) bold <- sample(which(!fonts$italic & fonts$weight > 'normal'), 1) italic <- sample(which(fonts$italic & fonts$weight <= 'normal'), 1) bolditalic <- sample(which(fonts$italic & fonts$weight > 'normal'), 1) register_font( 'random', plain = list(fonts$path[plain], fonts$index[plain]), bold = list(fonts$path[bold], fonts$index[bold]), italic = list(fonts$path[italic], fonts$index[italic]), bolditalic = list(fonts$path[bolditalic], fonts$index[bolditalic]) ) # Look at your creation registry_fonts() # Reset clear_registry()
This function is a wrapper around register_font()
that allows you to easily
create variants of existing system fonts, e.g. to target different weights
and/or widths, or for attaching OpenType features to a font.
register_variant( name, family, weight = NULL, width = NULL, features = font_feature() )
register_variant( name, family, weight = NULL, width = NULL, features = font_feature() )
name |
The new family name the variant should respond to |
family |
The name of an existing font family that this is a variant of |
weight |
One or two of |
width |
One of |
features |
A |
# Get the default "sans" family sans <- match_fonts("sans")$path sans <- system_fonts()$family[system_fonts()$path == sans][1] # Register a variant of it: register_variant( "sans_ligature", sans, features = font_feature(ligatures = "discretionary") ) registry_fonts() # clean up clear_registry()
# Get the default "sans" family sans <- match_fonts("sans")$path sans <- system_fonts()$family[system_fonts()$path == sans][1] # Register a variant of it: register_variant( "sans_ligature", sans, features = font_feature(ligatures = "discretionary") ) registry_fonts() # clean up clear_registry()
Building the list of system fonts is time consuming and is therefore cached.
This, in turn, means that changes to the system fonts (i.e. installing new
fonts), will not propagate to systemfonts. The solution is to reset the
cache, which will result in the next call to e.g. match_fonts()
will
trigger a rebuild of the cache.
reset_font_cache()
reset_font_cache()
all_fonts <- system_fonts() ##-- Install a new font on the system --## all_fonts_new <- system_fonts() ## all_fonts_new will be equal to all_fonts reset_font_cache() all_fonts_new <- system_fonts() ## all_fonts_new will now contain the new font
all_fonts <- system_fonts() ##-- Install a new font on the system --## all_fonts_new <- system_fonts() ## all_fonts_new will be equal to all_fonts reset_font_cache() all_fonts_new <- system_fonts() ## all_fonts_new will now contain the new font
Do basic text shaping of strings. This function will use freetype to
calculate advances, doing kerning if possible. It will not perform any font
substitution or ligature resolving and will thus be much in line with how
the standard graphic devices does text shaping. Inputs are recycled to the
length of strings
.
shape_string( strings, id = NULL, family = "", italic = FALSE, bold = FALSE, size = 12, res = 72, lineheight = 1, align = "left", hjust = 0, vjust = 0, width = NA, tracking = 0, indent = 0, hanging = 0, space_before = 0, space_after = 0, path = NULL, index = 0 )
shape_string( strings, id = NULL, family = "", italic = FALSE, bold = FALSE, size = 12, res = 72, lineheight = 1, align = "left", hjust = 0, vjust = 0, width = NA, tracking = 0, indent = 0, hanging = 0, space_before = 0, space_after = 0, path = NULL, index = 0 )
strings |
A character vector of strings to shape |
id |
A vector grouping the strings together. If strings share an id the shaping will continue between strings |
family |
The name of the font families to match |
italic |
logical indicating the font slant |
bold |
logical indicating whether the font weight |
size |
The pointsize of the font to use for size related measures |
res |
The ppi of the size related mesures |
lineheight |
A multiplier for the lineheight |
align |
Within text box alignment, either |
hjust , vjust
|
The justification of the textbox surrounding the text |
width |
The requested with of the string in inches. Setting this to
something other than |
tracking |
Tracking of the glyphs (space adjustment) measured in 1/1000 em. |
indent |
The indent of the first line in a paragraph measured in inches. |
hanging |
The indent of the remaining lines in a paragraph measured in inches. |
space_before , space_after
|
The spacing above and below a paragraph, measured in points |
path , index
|
path an index of a font file to circumvent lookup based on family and style |
A list with two element: shape
contains the position of each glyph,
relative to the origin in the enclosing textbox. metrics
contain metrics
about the full strings.
shape
is a data.frame with the following columns:
The glyph as a character
The index of the glyph in the font file
The index of the string the glyph is part of (referencing a row in the metrics
data.frame)
The index of the string the glyph came from (referencing an element in the strings
input)
The x offset in pixels from the origin of the textbox
The y offset in pixels from the origin of the textbox
The x offset in pixels to the middle of the glyph, measured from the origin of the glyph
metrics
is a data.frame with the following columns:
The text the string consist of
The width of the string
The height of the string
The distance from the left edge of the textbox and the leftmost glyph
The distance from the right edge of the textbox and the rightmost glyph
The distance from the top edge of the textbox and the topmost glyph
The distance from the bottom edge of the textbox and the bottommost glyph
The position of the leftmost edge of the textbox related to the origin
The position of the topmost edge of the textbox related to the origin
The horizontal position of the next glyph after the string
The vertical position of the next glyph after the string
string <- "This is a long string\nLook; It spans multiple lines\nand all" # Shape with default settings shape_string(string) # Mix styles within the same string string <- c( "This string will have\na ", "very large", " text style\nin the middle" ) shape_string(string, id = c(1, 1, 1), size = c(12, 24, 12))
string <- "This is a long string\nLook; It spans multiple lines\nand all" # Shape with default settings shape_string(string) # Mix styles within the same string string <- c( "This string will have\na ", "very large", " text style\nin the middle" ) shape_string(string, id = c(1, 1, 1), size = c(12, 24, 12))
In order to do correct text rendering, the font needed must be figured out. A
common case is rendering of emojis within a string where the system emoji
font is used rather than the requested font. This function will inspect the
provided strings and split them up in runs that must be rendered with the
emoji font, and the rest. Arguments are recycled to the length of the string
vector.
str_split_emoji( string, family = "", italic = FALSE, bold = FALSE, path = NULL, index = 0 )
str_split_emoji( string, family = "", italic = FALSE, bold = FALSE, path = NULL, index = 0 )
string |
A character vector of strings that should be splitted. |
family |
The name of the font families to match |
italic |
logical indicating the font slant |
bold |
logical indicating whether the font weight |
path , index
|
path an index of a font file to circumvent lookup based on family and style |
A data.frame containing the following columns:
The substring containing a consecutive run of glyphs
The index into the original string
vector that the substring is part of
A logical vector giving if the substring is a run of emojis or not
emoji_string <- "This is a joke\U0001f642. It should be obvious from the smiley" str_split_emoji(emoji_string)
emoji_string <- "This is a joke\U0001f642. It should be obvious from the smiley" str_split_emoji(emoji_string)
This function is much like string_widths_dev()
but also returns the ascent
and descent of the string making it possible to construct a tight bounding
box around the string.
string_metrics_dev( strings, family = "", face = 1, size = 12, cex = 1, unit = "cm" )
string_metrics_dev( strings, family = "", face = 1, size = 12, cex = 1, unit = "cm" )
strings |
A character vector of strings to measure |
family |
The font families to use. Will get recycled |
face |
The font faces to use. Will get recycled |
size |
The font size to use. Will get recycled |
cex |
The cex multiplier to use. Will get recycled |
unit |
The unit to return the width in. Either |
A data.frame with width
, ascent
, and descent
columns giving the
metrics in the requested unit.
Other device metrics:
string_widths_dev()
# Get the metrics as measured in cm (default) string_metrics_dev(c('some text', 'a string with descenders'))
# Get the metrics as measured in cm (default) string_metrics_dev(c('some text', 'a string with descenders'))
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
.
string_width( strings, family = "", italic = FALSE, bold = FALSE, size = 12, res = 72, include_bearing = TRUE, path = NULL, index = 0 )
string_width( strings, family = "", italic = FALSE, bold = FALSE, size = 12, res = 72, include_bearing = TRUE, path = NULL, index = 0 )
strings |
A character vector of strings |
family |
The name of the font families to match |
italic |
logical indicating the font slant |
bold |
logical indicating whether the font weight |
size |
The pointsize of the font to use for size related measures |
res |
The ppi of the size related mesures |
include_bearing |
Logical, should left and right bearing be included in the string width? |
path , index
|
path an index of a font file to circumvent lookup based on family and style |
A numeric vector giving the width of the strings in pixels. Use the
provided res
value to convert it into absolute values.
strings <- c('A short string', 'A very very looong string') string_width(strings)
strings <- c('A short string', 'A very very looong string') string_width(strings)
For certain composition tasks it is beneficial to get the width of a string
as interpreted by the device that is going to plot it. grid provides this
through construction of a textGrob
and then converting the corresponding
grob width to e.g. cm, but this comes with a huge overhead.
string_widths_dev()
provides direct, vectorised, access to the graphic
device for as high performance as possible.
string_widths_dev( strings, family = "", face = 1, size = 12, cex = 1, unit = "cm" )
string_widths_dev( strings, family = "", face = 1, size = 12, cex = 1, unit = "cm" )
strings |
A character vector of strings to measure |
family |
The font families to use. Will get recycled |
face |
The font faces to use. Will get recycled |
size |
The font size to use. Will get recycled |
cex |
The cex multiplier to use. Will get recycled |
unit |
The unit to return the width in. Either |
A numeric vector with the width of each of the strings given in
strings
in the unit given in unit
Other device metrics:
string_metrics_dev()
# Get the widths as measured in cm (default) string_widths_dev(c('a string', 'an even longer string'))
# Get the widths as measured in cm (default) string_widths_dev(c('a string', 'an even longer string'))
List all fonts installed on your system
system_fonts()
system_fonts()
A data frame with a row for each font and various information in each column
# See all monospace fonts fonts <- system_fonts() fonts[fonts$monospace, ]
# See all monospace fonts fonts <- system_fonts() fonts[fonts$monospace, ]