wch / extrafont

Tools for using fonts in R graphics
315 stars 48 forks source link

Font_import imports no fonts #74

Open Martingales opened 4 years ago

Martingales commented 4 years ago

Hi all,

I run R 3.6.1 on a macOS Catalina (10.15) and have installed R, extrafont and extrafontdb with conda. Ghostscript and Xcode are installed.

When running font_import() it goes through a lot of fonts but somehow doesn't install them for R. Here are the last lines of the output:

/Users/[xxx]/Library/Fonts/Roboto-ThinItalic.ttf => /Users/[xxx]/miniconda3/lib/R/library/extrafontdb/metrics/Roboto-ThinItalic
/Users/[xxx]/Library/Fonts/thedeadsaloon-Regular.ttf => /Users/[xxx]/miniconda3/lib/R/library/extrafontdb/metrics/thedeadsaloon-Regular
/Users/[xxx]/Library/Fonts/WhiteVinegar-Regular.ttf => /Users/[xxx]/miniconda3/lib/R/library/extrafontdb/metrics/WhiteVinegar-Regular
Found FontName for 175 fonts.
Scanning afm files in /Users/[xxx]/miniconda3/lib/R/library/extrafontdb/metrics
Error in if (grepl("Symbol", FamilyName)) Symbol <- TRUE else Symbol <- FALSE :
  argument is of length zero
In addition: There were 50 or more warnings (use warnings() to see the first 50)

The warnings contain the following messages:

1: In system2(ttf2pt1, c(args, shQuote(ttfiles[i]), shQuote(tmpfiles[i])),  ... :
  running command ''/Users/[xxx]/miniconda3/lib/R/library/Rttf2pt1/exec//ttf2pt1' -a -GfAe '/System/Library/Fonts/Apple Symbols.ttf' '/var/folders/3d/386b55_x3ps_plzl5jcqsl813tnsfq/T//Rtmpv1oEK3/fonts/Apple Symbols' 2>&1' had status 1
2: In system2(ttf2pt1, c(args, shQuote(ttfiles[i]), shQuote(tmpfiles[i])),  ... :
  running command ''/Users/[xxx]/miniconda3/lib/R/library/Rttf2pt1/exec//ttf2pt1' -a -GfAe '/System/Library/Fonts/Supplemental/Chalkduster.ttf' '/var/folders/3d/386b55_x3ps_plzl5jcqsl813tnsfq/T//Rtmpv1oEK3/fonts/Chalkduster' 2>&1' had status 134
3: In system2(ttf2pt1, c(args, shQuote(ttfiles[i]), shQuote(tmpfiles[i])),  ... :
  running command ''/Users/[xxx]/miniconda3/lib/R/library/Rttf2pt1/exec//ttf2pt1' -a -GfAe '/System/Library/Fonts/Supplemental/Kokonor.ttf' '/var/folders/3d/386b55_x3ps_plzl5jcqsl813tnsfq/T//Rtmpv1oEK3/fonts/Kokonor' 2>&1' had status 134
[...]
7: In grepl("^FamilyName", text) : input string 4 is invalid in this locale
8: In grepl("^FontName", text) : input string 4 is invalid in this locale
9: In grepl("^FullName", text) : input string 4 is invalid in this locale
10: In grepl("^Weight", text) : input string 4 is invalid in this locale
[...]

When I load extrafont and run load_fonts(), the output of fonts() and fonttable() is NULL.

Would be grateful for a tip or a hint in solving this!

tedtoal commented 3 years ago

I also was unable to import fonts on macOS Catalina 10.15.7. This error occurred:

/System/Library/Fonts/Apple Symbols.ttfError in system2(ttf2pt1, c(args, shQuote(ttfiles[i]), shQuote(tmpfiles[i])),  : 
  (converted from warning) running command ''/Library/Frameworks/R.framework/Versions/3.6/Resources/library/Rttf2pt1/exec//ttf2pt1' -a -GfAe '/System/Library/Fonts/Apple Symbols.ttf' '/var/folders/0x/csx74yk13tggqn2hr4dcg3vh0000gn/T//RtmpdboP8u/fonts/Apple Symbols' 2>&1' had status 1

I tried the following because I was only interested in importing Arial Unicode fonts:

font_import(pattern="Arial Unicode.*")

That gave me this output:

Scanning ttf files in /Library/Fonts/, /System/Library/Fonts, ~/Library/Fonts/ ...
Extracting .afm files from .ttf files...
/System/Library/Fonts/Supplemental/Arial Unicode.ttf => /Library/Frameworks/R.framework/Versions/3.6/Resources/library/extrafontdb/metrics/Arial Unicode
/System/Library/Fonts/Supplemental/Arial Unicode.ttf => /Library/Frameworks/R.framework/Versions/3.6/Resources/library/extrafontdb/metrics/Arial Unicode
Found FontName for 2 fonts.
Scanning afm files in /Library/Frameworks/R.framework/Versions/3.6/Resources/library/extrafontdb/metrics
Error in grepl("^FamilyName", text) : 
  (converted from warning) input string 4 is invalid in this locale

I'm not sure what "string 4" refers to.

My locale is set as follows:

> Sys.getlocale()
[1] "en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8"

R session info:

R version 3.6.3 (2020-02-29)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Catalina 10.15.7

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] parallel  stats4    stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] extrafont_0.17                    showtext_0.9-1                    showtextdb_3.0                    sysfonts_0.8.2                   
 [5] abind_1.4-5                       vcfR_1.12.0                       BSgenome.Hsapiens.UCSC.hg38_1.4.1 BSgenome_1.54.0                  
 [9] rtracklayer_1.46.0                Biostrings_2.54.0                 XVector_0.26.0                    GenomicFeatures_1.38.2           
[13] AnnotationDbi_1.48.0              Biobase_2.46.0                    GenomicRanges_1.38.0              GenomeInfoDb_1.22.1              
[17] IRanges_2.20.2                    S4Vectors_0.24.4                  BiocGenerics_0.32.0               assertthat_0.2.1                 

loaded via a namespace (and not attached):
 [1] httr_1.4.2                  bit64_4.0.5                 viridisLite_0.3.0           splines_3.6.3               memuse_4.1-0               
 [6] askpass_1.1                 BiocFileCache_1.10.2        blob_1.2.1                  GenomeInfoDbData_1.2.2      Rsamtools_2.2.3            
[11] progress_1.2.2              Rttf2pt1_1.3.8              pillar_1.4.6                RSQLite_2.2.1               lattice_0.20-41            
[16] glue_1.4.2                  extrafontdb_1.0             digest_0.6.27               Matrix_1.2-18               XML_3.99-0.3               
[21] pkgconfig_2.0.3             biomaRt_2.42.1              zlibbioc_1.32.0             purrr_0.3.4                 BiocParallel_1.20.1        
[26] tibble_3.0.4                openssl_1.4.3               mgcv_1.8-33                 generics_0.1.0              ellipsis_0.3.1             
[31] SummarizedExperiment_1.16.1 magrittr_2.0.1              crayon_1.3.4                memoise_1.1.0               nlme_3.1-150               
[36] MASS_7.3-53                 vegan_2.5-6                 tools_3.6.3                 prettyunits_1.1.1           hms_0.5.3                  
[41] lifecycle_0.2.0             matrixStats_0.57.0          stringr_1.4.0               cluster_2.1.0               DelayedArray_0.12.3        
[46] compiler_3.6.3              rlang_0.4.8                 grid_3.6.3                  RCurl_1.98-1.2              rappdirs_0.3.1             
[51] bitops_1.0-6                DBI_1.1.0                   curl_4.3                    R6_2.5.0                    GenomicAlignments_1.22.1   
[56] dplyr_1.0.2                 pinfsc50_1.2.0              bit_4.0.4                   permute_0.9-5               ape_5.4-1                  
[61] stringi_1.5.3               Rcpp_1.0.5                  vctrs_0.3.5                 dbplyr_2.0.0                tidyselect_1.1.0           
tedtoal commented 3 years ago

I was able to get farther along in the process. Turns out I had option(warn=2), which turned warnings into errors. I did option(warn=0) and reran font_import(pattern="Arial Unicode.*"). This gave me the following output:

...
There were 50 or more warnings (use warnings() to see the first 50)
> warnings()
Warning messages:
1: In grepl("^FamilyName", text) : input string 4 is invalid in this locale
2: In grepl("^FontName", text) : input string 4 is invalid in this locale
3: In grepl("^FullName", text) : input string 4 is invalid in this locale
4: In grepl("^Weight", text) : input string 4 is invalid in this locale
5: In grepl("^FamilyName", text) : input string 4 is invalid in this locale
6: In grepl("^FontName", text) : input string 4 is invalid in this locale
7: In grepl("^FullName", text) : input string 4 is invalid in this locale
8: In grepl("^Weight", text) : input string 4 is invalid in this locale
9: In grepl("^FamilyName", text) : input string 4 is invalid in this locale
10: In grepl("^FontName", text) : input string 4 is invalid in this locale
11: In grepl("^FullName", text) : input string 4 is invalid in this locale
12: In grepl("^Weight", text) : input string 4 is invalid in this locale
13: In grepl("^FamilyName", text) : input string 4 is invalid in this locale
14: In grepl("^FontName", text) : input string 4 is invalid in this locale
15: In grepl("^FullName", text) : input string 4 is invalid in this locale
16: In grepl("^Weight", text) : input string 4 is invalid in this locale
17: In grepl("^FamilyName", text) : input string 4 is invalid in this locale
18: In grepl("^FontName", text) : input string 4 is invalid in this locale
19: In grepl("^FullName", text) : input string 4 is invalid in this locale
20: In grepl("^Weight", text) : input string 4 is invalid in this locale
21: In grepl("^FamilyName", text) : input string 4 is invalid in this locale
22: In grepl("^FontName", text) : input string 4 is invalid in this locale
23: In grepl("^FullName", text) : input string 4 is invalid in this locale
24: In grepl("^Weight", text) : input string 4 is invalid in this locale
25: In grepl("^FamilyName", text) : input string 4 is invalid in this locale
26: In grepl("^FontName", text) : input string 4 is invalid in this locale
27: In grepl("^FullName", text) : input string 4 is invalid in this locale
28: In grepl("^Weight", text) : input string 4 is invalid in this locale
29: In grepl("^FamilyName", text) : input string 4 is invalid in this locale
30: In grepl("^FontName", text) : input string 4 is invalid in this locale
31: In grepl("^FullName", text) : input string 4 is invalid in this locale
32: In grepl("^Weight", text) : input string 4 is invalid in this locale
33: In grepl("^FamilyName", text) : input string 4 is invalid in this locale
34: In grepl("^FontName", text) : input string 4 is invalid in this locale
35: In grepl("^FullName", text) : input string 4 is invalid in this locale
36: In grepl("^Weight", text) : input string 4 is invalid in this locale
37: In grepl("^FamilyName", text) : input string 4 is invalid in this locale
38: In grepl("^FontName", text) : input string 4 is invalid in this locale
39: In grepl("^FullName", text) : input string 4 is invalid in this locale
40: In grepl("^Weight", text) : input string 4 is invalid in this locale
41: In grepl("^FamilyName", text) : input string 4 is invalid in this locale
42: In grepl("^FontName", text) : input string 4 is invalid in this locale
43: In grepl("^FullName", text) : input string 4 is invalid in this locale
44: In grepl("^Weight", text) : input string 4 is invalid in this locale
45: In grepl("^FamilyName", text) : input string 4 is invalid in this locale
46: In grepl("^FontName", text) : input string 4 is invalid in this locale
47: In grepl("^FullName", text) : input string 4 is invalid in this locale
48: In grepl("^Weight", text) : input string 4 is invalid in this locale
49: In grepl("^FamilyName", text) : input string 4 is invalid in this locale
50: In grepl("^FontName", text) : input string 4 is invalid in this locale
> fonts()
[1] "Arial Unicode MS"
> fonttable()
  package              afmfile                                             fontfile         FullName       FamilyName       FontName  Bold
1      NA Arial Unicode.afm.gz /System/Library/Fonts/Supplemental/Arial Unicode.ttf Arial Unicode MS Arial Unicode MS ArialUnicodeMS FALSE
  Italic Symbol afmsymfile
1  FALSE  FALSE         NA

I was hoping the font would work, but got the following error when testing it:

> pdf(fn, width=4, height=4, family="Arial Unicode MS")
> plot(mtcars$mpg, mtcars$wt, 
+      main = "Fuel Efficiency of 32 Cars",
+      xlab = "Weight (x1000 lb)",
+      ylab = "Miles per Gallon")
> 
> par("usr")
[1]  9.46000 34.84000  1.35656  5.58044
> text(20, 3, "⚐")
Warning messages:
1: In text.default(20, 3, "\u2690") :
  conversion failure on '⚐' in 'mbcsToSbcs': dot substituted for <e2>
2: In text.default(20, 3, "\u2690") :
  conversion failure on '⚐' in 'mbcsToSbcs': dot substituted for <9a>
3: In text.default(20, 3, "\u2690") :
  conversion failure on '⚐' in 'mbcsToSbcs': dot substituted for <90>
4: In text.default(20, 3, "\u2690") :
  font metrics unknown for Unicode character U+2690
5: In text.default(20, 3, "\u2690") :
  conversion failure on '⚐' in 'mbcsToSbcs': dot substituted for <e2>
6: In text.default(20, 3, "\u2690") :
  conversion failure on '⚐' in 'mbcsToSbcs': dot substituted for <9a>
7: In text.default(20, 3, "\u2690") :
  conversion failure on '⚐' in 'mbcsToSbcs': dot substituted for <90>

It seems that it doesn't want to recognize the Unicode character U+2690, which is the entire reason I tried to install this font.

I was able to get around the above problem by using the cairo_pdf() device. It no longer gave the above errors, but I still saw only a rectangle instead of the "flag" Unicode character, in the pdf file, even after embedding the font into the file.

I also tried something that was recommended:

Sys.setlocale('LC_ALL','C')

I tried rerunning font_import(pattern="Arial Unicode.*") but it did not re-import the font because it was already imported. I guessed that I could fix this problem by re-installing extrafont as the install instructions said this would "reset the font database" and that sounded like something to try. It worked and then I was able to do the font_import, and this time, I did not get any errors. And, I was able to make a pdf file with either pdf() or cairo_pdf() with no errors occurring. But still, the Unicode "flag" character displayed as a square, even with fonts embedded.

tedtoal commented 3 years ago

Suggestion: in the extrafont installation instructions, add "options(warn=0)".

tedtoal commented 3 years ago

Unicode has been around for decades now, but it still isn't possible to use many Unicode characters in R within a PDF file. Why not? My reading so far has led me to conclude that it might be because the design of the PDF file standard by Adobe is old and predates Unicode and revisions to the PDF standard have not adequately incorporated Unicode. I'm suspecting that with a PDF file we are back to dealing with 8-bit fonts that only have room for 256 characters, so using Unicode characters outside the usual ones means that somehow we have to provide 8-bit fonts containing the characters we need to use.

Suggestion: as part of the "extrafont" installation instructions, include a paragraph summarizing the state of affairs of Unicode characters and PDF files. Indicate what problems can be solved by extrafont and which problems cannot be solved by it. Describe difference between true-type fonts and adobe type 1 fonts. Describe what the "encoding" concept means, how it affects putting Unicode characters into PDF files, and what the deal is with UTF-8 encoding and pdf files. Describe what embedding a font does, that doesn't happen when the font is not embedded. Say what the mysterious mbcsToSbcs function does. Say something about what causes a square to appear in a pdf file when a Unicode character is used, vs. what causes a string such as "UTF-8" to appear in place of the character in the pdf file. Explain about arm files and font width tables and how this might relate to "extrafont" failure to install the Arial Unicode MS.ttf font file such that every character in it can be used in a pdf file. Give the reader enough of an understanding that he can figure out what is wrong when he is trying to put a Unicode character into a pdf file and it doesn't work. A nice introduction to the problem like this would be invaluable, I think, for so many people struggling with this problem.

tedtoal commented 3 years ago

Suggestion: make font_import() import even if the font already exists, or have an argument "force" that forces such import.