systemfonts icon indicating copy to clipboard operation
systemfonts copied to clipboard

Enable adding a custom directory to the system font search path(s)?

Open hrbrmstr opened this issue 5 years ago • 2 comments

From what I gather, with something like this — https://github.com/hrbrmstr/hrbragg/tree/master/inst/fonts/inter —

fs::dir_tree(system.file("fonts/inter", package = "hrbragg"))
## /Library/Frameworks/R.framework/Versions/4.0/Resources/library/hrbragg/fonts/inter
## ├── Inter-Black.otf
## ├── Inter-BlackItalic.otf
## ├── Inter-Bold.otf
## ├── Inter-BoldItalic.otf
## ├── Inter-ExtraBold.otf
## ├── Inter-ExtraBoldItalic.otf
## ├── Inter-ExtraLight.otf
## ├── Inter-ExtraLightItalic.otf
## ├── Inter-Italic.otf
## ├── Inter-Light.otf
## ├── Inter-LightItalic.otf
## ├── Inter-Medium.otf
## ├── Inter-MediumItalic.otf
## ├── Inter-Regular.otf
## ├── Inter-SemiBold.otf
## ├── Inter-SemiBoldItalic.otf
## ├── Inter-Thin.otf
## └── Inter-ThinItalic.otf

in a package, to get the equivalent of this:

# A tibble: 18 x 9
   path                                        index name               family style           weight   width italic monospace
   <chr>                                       <int> <chr>              <chr>  <chr>           <ord>    <ord> <lgl>  <lgl>    
 1 /Users/hrbrmstr/Library/Fonts/Inter-ExtraL…     0 Inter-ExtraLight   Inter  Extra Light     light    norm… FALSE  FALSE    
 2 /Users/hrbrmstr/Library/Fonts/Inter-Bold.o…     0 Inter-Bold         Inter  Bold            bold     norm… FALSE  FALSE    
 3 /Users/hrbrmstr/Library/Fonts/Inter-Italic…     0 Inter-Italic       Inter  Italic          normal   norm… TRUE   FALSE    
 4 /Users/hrbrmstr/Library/Fonts/Inter-ExtraB…     0 Inter-ExtraBold    Inter  Extra Bold      ultrabo… norm… FALSE  FALSE    
 5 /Users/hrbrmstr/Library/Fonts/Inter-Regula…     0 Inter-Regular      Inter  Regular         normal   norm… FALSE  FALSE    
 6 /Users/hrbrmstr/Library/Fonts/Inter-Medium…     0 Inter-MediumItalic Inter  Medium Italic   medium   norm… TRUE   FALSE    
 7 /Users/hrbrmstr/Library/Fonts/Inter-ExtraL…     0 Inter-ExtraLightI… Inter  Extra Light It… light    norm… TRUE   FALSE    
 8 /Users/hrbrmstr/Library/Fonts/Inter-ExtraB…     0 Inter-ExtraBoldIt… Inter  Extra Bold Ita… ultrabo… norm… TRUE   FALSE    
 9 /Users/hrbrmstr/Library/Fonts/Inter-Black.…     0 Inter-Black        Inter  Black           heavy    norm… FALSE  FALSE    
10 /Users/hrbrmstr/Library/Fonts/Inter-SemiBo…     0 Inter-SemiBoldIta… Inter  Semi Bold Ital… semibold norm… TRUE   FALSE    
11 /Users/hrbrmstr/Library/Fonts/Inter-LightI…     0 Inter-LightItalic  Inter  Light Italic    normal   norm… TRUE   FALSE    
12 /Users/hrbrmstr/Library/Fonts/Inter-Light.…     0 Inter-Light        Inter  Light           normal   norm… FALSE  FALSE    
13 /Users/hrbrmstr/Library/Fonts/Inter-Thin.o…     0 Inter-Thin         Inter  Thin            ultrali… norm… FALSE  FALSE    
14 /Users/hrbrmstr/Library/Fonts/Inter-ThinIt…     0 Inter-ThinItalic   Inter  Thin Italic     ultrali… norm… TRUE   FALSE    
15 /Users/hrbrmstr/Library/Fonts/Inter-SemiBo…     0 Inter-SemiBold     Inter  Semi Bold       semibold norm… FALSE  FALSE    
16 /Users/hrbrmstr/Library/Fonts/Inter-BlackI…     0 Inter-BlackItalic  Inter  Black Italic    heavy    norm… TRUE   FALSE    
17 /Users/hrbrmstr/Library/Fonts/Inter-Medium…     0 Inter-Medium       Inter  Medium          medium   norm… FALSE  FALSE    
18 /Users/hrbrmstr/Library/Fonts/Inter-BoldIt…     0 Inter-BoldItalic   Inter  Bold Italic     bold     norm… TRUE   FALSE    

in an R session registry, I'd have to deal with the individual registrations for the various weights. Is there any way with the new underlying tooling to specify another search path or have a registration function that just takes a path and registers all the fonts in that directory?

hrbrmstr avatar Feb 21 '21 13:02 hrbrmstr

There is no way to add a path that would be treated equally as the fonts installed in the system. I can see a good reason for some path scanning functionality however so let me think about the right API

thomasp85 avatar Feb 21 '21 16:02 thomasp85

Would it be possible to add a function that helps installing the font in the correct user directory instead ?
I mean, if I have a custom font in my package and I want users to install the font on their system, instead of only registering it for the session, currently I will ask them to do it manually. But, that would be nice if a R function could install it directly from command line.
This would also simplify CI integration I guess.

It seems that {extrafont} will hardly be maintained now (https://github.com/wch/Rttf2pt1)

Maybe we can retrieve this function that list all possible user font directories.
I think that this is a little different from what can currently return {systemfonts} because this requires the directory to already exist.
Below is the code that list system fonts directories, even if they do not exist for now. I guess that we can limit this to writable directories as the aim is to be able to copy a ttf directory into one of these like:

install_font <- function(from, to) {
  # writeable directory
  if (is.empty(to)) {
    to <- ttf_find_default_path()[file.access(ttf_find_default_path(), mode = 2)[[1]] == 0)][1]
  }
  # Copy from internal package and external directory
  file.copy(
    from,
    to
  )
}

install_font(system.file("my_fonts", package = "a.package.with.fonts"))

Retrieved from: https://github.com/wch/extrafont/blob/054a41fcba237cbb693144a0fc7b23a9e30f0c2b/R/truetype.r#L125

# Returns vector of default truetype paths, depending on platform.
ttf_find_default_path <- function() {

  if (grepl("^darwin", R.version$os)) {
    paths <-
      c("/Library/Fonts/",                      # System fonts
        "/System/Library/Fonts",                # More system fonts
        "/System/Library/Fonts/Supplemental",   # More system fonts
        "~/Library/Fonts/")                     # User fonts
    return(paths[file.exists(paths)])

  } else if (grepl("^linux-gnu", R.version$os)) {
    # Possible font paths, depending on the system
    paths <-
      c("/usr/share/fonts/",                    # Ubuntu/Debian/Arch/Gentoo
        "/usr/X11R6/lib/X11/fonts/TrueType/",   # RH 6
        "~/.local/share/fonts/",                # Added with Gnome font viewer
        "~/.fonts/")                            # User fonts
    return(paths[file.exists(paths)])

  } else if (grepl("^freebsd", R.version$os)) {
    # Possible font paths, depending on installed ports
    paths <-
      c("/usr/local/share/fonts/truetype/",
        "/usr/local/lib/X11/fonts/",
        "~/.fonts/")                            # User fonts
    return(paths[file.exists(paths)])

  } else if (grepl("^mingw", R.version$os)) {
    paths <-
      c(file.path(Sys.getenv("SystemRoot"), "Fonts"),
        file.path(Sys.getenv("LOCALAPPDATA"), "Microsoft", "Windows", "Fonts")
      )
    return(paths[file.exists(paths)])
  } else {
    stop("Unknown platform. Don't know where to look for truetype fonts. Sorry!")
  }

}

In which, I would add

if (.Platform == "windows") {
  user_font <- normalizePath(file.path(dirname(Sys.getenv("HOME")), "AppData/Local/Microsoft/Windows/Fonts"))
}

statnmap avatar Nov 17 '21 10:11 statnmap