JuliaGraphics / Cairo.jl

Bindings to the Cairo graphics library.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Font selection?

lobingera opened this issue · comments

I was looking into #311 and downloading the first time a 1.0.0 Cairo - including the binary dependencies.

I didn't expect this:

e

as the selected font in sample_text.jl is "Sans".

@giordano Any idea, what went wrong?

No idea 🙂 Is the problem that a font can't be found?

' but the standard CSS2 generic family names, ("serif", "sans-serif", "cursive", "fantasy", "monospace"), are likely to work as expected.' in https://www.cairographics.org/manual/cairo-text.html.
What did you configure for fontconfig?

Maybe you want to check the list of fonts found by fontconfig with

using Cairo
fc_list = joinpath(dirname(Cairo.Fontconfig_jll.libfontconfig_path), "..", "bin", "fc-list")
run(`$(fc_list)`)

The good news is Fontconfig_jll has reasonable defaults for paths and finds major part of my local fonts, so e.g. "DejaVu Sans" works. I'm still looking into the cairo build, how the defaults for 'sans' 'serif' etc. are build.

lobi@o4:~$ fc-match Sans
DejaVuSans.ttf: "DejaVu Sans" "Book"

vs.

julia> fc_list = joinpath(dirname(Cairo.Fontconfig_jll.libfontconfig_path), "..", "bin", "fc-match")
"/home/lobi/.julia/artifacts/225abdb6d736c3c743dbc9735950947bc064c0cd/lib/../bin/fc-match"

julia> run(`$(fc_list) Sans`)
FreeMono.ttf: "FreeMono" "Regular"
Process(`/home/lobi/.julia/artifacts/225abdb6d736c3c743dbc9735950947bc064c0cd/lib/../bin/fc-match Sans`, ProcessExited(0))

Where is DejaVuSans.ttf? Does running fc-cache help?

DejaVu Sans isn't the problem

julia> run(`$(fc_list) "DejaVu Sans"`)
/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed-Oblique.ttf: DejaVu Sans,DejaVu Sans Condensed:style=Condensed Oblique,Oblique
/usr/share/fonts/truetype/dejavu/DejaVuSans-ExtraLight.ttf: DejaVu Sans,DejaVu Sans Light:style=ExtraLight
/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf: DejaVu Sans:style=Book
/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf: DejaVu Sans:style=Book
/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf: DejaVu Sans:style=Bold
/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed-BoldOblique.ttf: DejaVu Sans,DejaVu Sans Condensed:style=Condensed Bold Oblique,Bold Oblique
/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed.ttf: DejaVu Sans,DejaVu Sans Condensed:style=Condensed,Book
/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed-Bold.ttf: DejaVu Sans,DejaVu Sans Condensed:style=Condensed Bold,Bold
/usr/share/fonts/truetype/dejavu/DejaVuSans-Oblique.ttf: DejaVu Sans:style=Oblique
/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf: DejaVu Sans:style=Bold
/usr/share/fonts/truetype/dejavu/DejaVuSans-BoldOblique.ttf: DejaVu Sans:style=Bold Oblique
Process(`/home/lobi/.julia/artifacts/225abdb6d736c3c743dbc9735950947bc064c0cd/lib/../bin/fc-list 'DejaVu Sans'`, ProcessExited(0))

julia> run(`$(fc_match) "DejaVu Sans"`)
DejaVuSans.ttf: "DejaVu Sans" "Book"
Process(`/home/lobi/.julia/artifacts/225abdb6d736c3c743dbc9735950947bc064c0cd/lib/../bin/fc-match 'DejaVu Sans'`, ProcessExited(0))

So fc-match Sans is not matching it?

No (#312 (comment)) fc_list is misleading here, fc-match is called.

I know, in fact I said fc-match.

Honestly, I'm a bit lost about what's the problem here 🙂

Cairo.jl should support the generic "Sans" "Serif" "Mono", but at least not providing a serif font for Sans.

So is this a Fontconfig problem that it's picking up a serif font when asking for a sans-serif one?

At least i see clearer now: The top-level font.conf is read from an artifact and hard coded.

Could you please elaborate? I still fail to understand where the problem is exactly.

With latest version of Fontconfig_jll (v2.13.1+9), the fonts.conf file is identical to my system fonts.conf, that is a standard Linux configuration:

julia> using Fontconfig_jll

julia> run(`cmp $(Fontconfig_jll.fonts_conf) /etc/fonts/fonts.conf`)
Process(`cmp /home/mose/.julia/artifacts/b20d3b4e71d9209bc0d83410b048e97b4f8c7096/etc/fonts/fonts.conf /etc/fonts/fonts.conf`, ProcessExited(0))

We've now removed all references to paths in the build environment.

Note that calling fc-match with the proper environment gives the expected result:

julia> fc_match() do fc_match_exe
           run(`$fc_match_exe Sans`)
       end
DejaVuSans.ttf: "DejaVu Sans" "Book"
Process(`/home/mose/.julia/artifacts/b20d3b4e71d9209bc0d83410b048e97b4f8c7096/bin/fc-match Sans`, ProcessExited(0))

while directly calling the executable doesn't:

julia> run(`/home/mose/.julia/artifacts/b20d3b4e71d9209bc0d83410b048e97b4f8c7096/bin/fc-match Sans`)
LinLibertine_R.otf: "Linux Libertine O" "Regular"
Process(`/home/mose/.julia/artifacts/b20d3b4e71d9209bc0d83410b048e97b4f8c7096/bin/fc-match Sans`, ProcessExited(0))

We probably need to set some more environment variables to get this working.

It turned out it's just LIBPATH:

julia> withenv(Fontconfig_jll.LIBPATH_env => Fontconfig_jll.LIBPATH) do
           run(`/home/mose/.julia/artifacts/b20d3b4e71d9209bc0d83410b048e97b4f8c7096/bin/fc-match Sans`)
       end
DejaVuSans.ttf: "DejaVu Sans" "Book"
Process(`/home/mose/.julia/artifacts/b20d3b4e71d9209bc0d83410b048e97b4f8c7096/bin/fc-match Sans`, ProcessExited(0))

However setting this environment variable doesn't seem to help with sample_text.jl.

I have similar issues.

Observations: Linux

Breaks going from Cairo v0.6.0 to v0.7.0 (Using Julia v1.3.1)
(Still broken for v0.8.0, 1.0.0, 1.0.2).

Does not appear to be caused by changes in Julia itself:
Also broken for Cairo v0.8.0 (Using Julia v1.1.1)
(Cannot go higher than Cairo v0.8.0 on Julia v1.1.1)

EDIT: Observations: Linux + Local Fonts

As mentioned by @lobingera, local fonts still appear to work:
Local fonts work well even with Cairo v1.0.2 on Julia v1.3.1.

Observations: Windows 10

"built-in" font aliases NOT broken, even for Cairo v0.8.0 (Using Julia v1.1.1)

So, it appears NOT to be an issue in Windows (no idea about mac).
EDIT: and is ONLY a problem with the "built-in" font aliases.

@lobingera what I would like to understand, and I hope you can help me on this, is what is choosing the font in Cairo.jl? Can you track down where the selection happens? That could tell us where to look further. As far as I can tell, the executable fc-match isn't called in this package (not directly at least), so looking at it might not be relevant

afaiu, libcairo actually wants you to select a font and hand over some function handles via the renderer (or the outline conversion if the output isn't a bitmap). However there is a fallback/toy font solution that uses the means provided and configured at built time. If you build on linux this is mostliklely Fontconfig + FreeType. You can see a little bit of that in cairo-ft-font.c _cairo_ft_unscaled_font_create_for_pattern.

So.

I'd expect the provided fc-pattern and fc-match to resolve names like 'serif' and 'sans-serif' to resolve to a TTF that could be loaded.

I'd expect the provided fc-pattern and fc-match to resolve names like 'serif' and 'sans-serif' to resolve to a TTF that could be loaded.

They do:

julia> using Fontconfig_jll

julia> fc_match(cmd -> run(`$cmd Sans`));
DejaVuSans.ttf: "DejaVu Sans" "Book"

julia> fc_match(cmd -> run(`$cmd Serif`));
DejaVuSerif.ttf: "DejaVu Serif" "Book"

Well ...

l1@c5:~$ ./julia-1.4.1/bin/julia 
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.4.1 (2020-04-14)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

shell> cd juliaenvironments/
/home/l1/juliaenvironments

shell> cd Emoji/
/home/l1/juliaenvironments/Emoji

(@v1.4) pkg> activate .
 Activating environment at `~/juliaenvironments/Emoji/Project.toml`

(Emoji) pkg> st
Status `~/juliaenvironments/Emoji/Project.toml`
  [159f3aea] Cairo v1.0.2
  [186bb1d3] Fontconfig v0.4.0
  [a3f928ae] Fontconfig_jll v2.13.1+11

(Emoji) pkg> up
   Updating registry at `~/.julia/registries/General`
   Updating git-repo `https://github.com/JuliaRegistries/General.git`
  Installed Colors ─ v0.12.1
   Updating `~/juliaenvironments/Emoji/Project.toml`
  [159f3aea] ↑ Cairo v1.0.2 ⇒ v1.0.3
   Updating `~/juliaenvironments/Emoji/Manifest.toml`
  [159f3aea] ↑ Cairo v1.0.2 ⇒ v1.0.3
  [3da002f7] ↑ ColorTypes v0.9.0 ⇒ v0.10.3
  [5ae59095] ↑ Colors v0.11.2 ⇒ v0.12.1
  [53c48c17] ↑ FixedPointNumbers v0.7.1 ⇒ v0.8.0
  [a2bd30eb] ↑ Graphics v1.0.1 ⇒ v1.0.2
  [546b0b6d] - X11_jll v1.6.8+5
  [84d6cd60] - Xorg_inputproto_jll v2.3.2+1
  [060dd47b] - Xorg_kbproto_jll v1.0.7+1
  [4f6342f7] ↑ Xorg_libX11_jll v1.6.8+0 ⇒ v1.6.9+2
  [21e99dc2] - Xorg_renderproto_jll v0.11.1+1
  [7c09cfe3] - Xorg_util_macros_jll v1.19.2+1
  [c2e9c405] - Xorg_xcb_proto_jll v1.13.0+1
  [d13bc2ba] - Xorg_xextproto_jll v7.3.0+1
  [46797783] - Xorg_xproto_jll v7.0.31+1

julia> using Fontconfig_jll

julia> fc_match(cmd -> run(`$cmd Sans`));
Fontconfig error: Cannot load default config file
FreeMono.ttf: "FreeMono" "Regular"

julia> fc_match(cmd -> run(`$cmd Serif`));
Fontconfig error: Cannot load default config file
FreeMono.ttf: "FreeMono" "Regular"

Try setting

ENV["FONTCONFIG_FILE"] = fonts_conf
julia> ENV["FONTCONFIG_FILE"] = fonts_conf
"/home/l1/.julia/artifacts/82f1062ef35feaa6d4cc426c15574338f12f5fd1/etc/fonts/fonts.conf"

julia> fc_match(cmd -> run(`$cmd Serif`));
FreeMono.ttf: "FreeMono" "Regular"

julia> fc_match(cmd -> run(`$cmd Sans`));
FreeMono.ttf: "FreeMono" "Regular"

For example what do you get with

julia> fc_list(cmd -> run(`$cmd "DejaVu Sans"`));
/usr/share/fonts/TTF/DejaVuSansCondensed.ttf: DejaVu Sans,DejaVu Sans Condensed:style=Condensed,Book
/usr/share/fonts/TTF/DejaVuSans-BoldOblique.ttf: DejaVu Sans:style=Bold Oblique
/usr/share/fonts/TTF/DejaVuSansCondensed-Oblique.ttf: DejaVu Sans,DejaVu Sans Condensed:style=Condensed Oblique,Oblique
/usr/share/fonts/TTF/DejaVuSansCondensed-BoldOblique.ttf: DejaVu Sans,DejaVu Sans Condensed:style=Condensed Bold Oblique,Bold Oblique
/usr/share/fonts/TTF/DejaVuSans-ExtraLight.ttf: DejaVu Sans,DejaVu Sans Light:style=ExtraLight
/usr/share/fonts/TTF/DejaVuSans-Oblique.ttf: DejaVu Sans:style=Oblique
/usr/share/fonts/TTF/DejaVuSansCondensed-Bold.ttf: DejaVu Sans,DejaVu Sans Condensed:style=Condensed Bold,Bold
/usr/share/fonts/TTF/DejaVuSans.ttf: DejaVu Sans:style=Book
/usr/share/fonts/TTF/DejaVuSans-Bold.ttf: DejaVu Sans:style=Bold

julia> fc_list(cmd -> run(`$cmd "DejaVu Serif"`));
/usr/share/fonts/TTF/DejaVuSerifCondensed.ttf: DejaVu Serif,DejaVu Serif Condensed:style=Condensed,Book
/usr/share/fonts/TTF/DejaVuSerifCondensed-Bold.ttf: DejaVu Serif,DejaVu Serif Condensed:style=Condensed Bold,Bold
/usr/share/fonts/TTF/DejaVuSerif-Bold.ttf: DejaVu Serif:style=Bold
/usr/share/fonts/TTF/DejaVuSerif.ttf: DejaVu Serif:style=Book
/usr/share/fonts/TTF/DejaVuSerifCondensed-Italic.ttf: DejaVu Serif,DejaVu Serif Condensed:style=Condensed Italic,Italic
/usr/share/fonts/TTF/DejaVuSerif-BoldItalic.ttf: DejaVu Serif:style=Bold Italic
/usr/share/fonts/TTF/DejaVuSerifCondensed-BoldItalic.ttf: DejaVu Serif,DejaVu Serif Condensed:style=Condensed Bold Italic,Bold Italic
/usr/share/fonts/TTF/DejaVuSerif-Italic.ttf: DejaVu Serif:style=Italic

?

julia> fc_list(cmd -> run(`$cmd "DejaVu Sans"`));
/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf: DejaVu Sans:style=Book
/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf: DejaVu Sans:style=Bold

julia> fc_list(cmd -> run(`$cmd "DejaVu Serif"`));
/usr/share/fonts/truetype/dejavu/DejaVuSerif-Bold.ttf: DejaVu Serif:style=Bold
/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf: DejaVu Serif:style=Book

Is this different from what you get with system fc-list?

Hmm.

shell> fc-list | grep Deja

julia> 

vs.

l1@c5:~$ fc-list  | grep Deja
/usr/share/fonts/truetype/dejavu/DejaVuSerif-Bold.ttf: DejaVu Serif:style=Bold
/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf: DejaVu Sans Mono:style=Book
/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf: DejaVu Sans:style=Book
/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf: DejaVu Sans:style=Bold
/usr/share/fonts/truetype/dejavu/DejaVuSansMono-Bold.ttf: DejaVu Sans Mono:style=Bold
/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf: DejaVu Serif:style=Book

I'm not sure

shell> fc-list | grep Deja

is doing what you expect. You can't pipe in that way in Julia's shell mode REPL

And i thought, there is a reason, why this is called shell mode ...

Doing a simple fc-list (in julia) i can see in the terminal some DejaVu in the above paths

And i thought, there is a reason, why this is called shell mode ...

There is a reason why it's called "Julia's shell mode" and not "your system's shell": it's Julia doing the parsing of the commands, not your shell.

With JuliaPackaging/Yggdrasil#1287 I finally get a sans serif font in the example, as expected. Could you please confirm that it works also for you after updating the packages in the registry? You should get Fontconfig_jll v2.13.1+12. This is what I get now:

sample_text

For comparison, the image in master is

sample_text

I confirm.

a1

I might come up with some questions, but i put them then to the Yggdrasil issue...