Makie text with variable styling

I’m often plotting things where I need the labels to have some styling. Particularly species names that need to be in italics, eg a y-label that’s something like

“Relative abundance of E. coli

There are easy ways to set the overall font of a label or other text element, but as far as I can tell, no way to have different fonts withing the same text element.

If this feature doesn’t currently exist, I’d be interested in taking a stab at implementing it, though I imagine that the way that stuff interacts with layouts could get pretty complicated, and I haven’t spent much time in the Makie internals. In an ideal world, this would work with @md_str or the stuff from CommonMark.jl, in the same way that @L_str currently works for LaTeX, but even if it requires something a bit more hacky, that would be really useful.

It does exist but this part of the API is pretty rough/hacky. Currently you can pass a vector of font names and each glyph takes its own font. Text shaping / styling / font substitution, etc, is a verrry deep rabbit hole and so far we’ve gotten pretty far without relying on complex tools like Pango / Harfbuzz. However that also means that we don’t have any of their more advanced features like style markup, bidirectional text, etc.

text("Relative abundance of E. coli",
    font = [fill("TeX Gyre Heros Makie", 22); fill("TeX Gyre Heros Makie Italic", 7)],
    textsize = 30,
    align = (:center, :center))

3 Likes

I had no idea such tools existed :exploding_head:

I’m happy to use the hacky solution for now in my own stuff - would there be interest in a PR that attempts to support a small number of markdown styles (I’m thinking just bold and italic really) using that hack, or does it make more sense to wait for a more complete solution (which I do not feel capable of tackling)?

what about a different colour for E. coli?

Sorry gentlemen to chime in, as I am not yet a regular Makie user but would like to become one.

As I understand that Makie supports LaTeXStrings, is it not possible to write the equivalent of Plots.jl annotate!() using the pgfplotsx() backend:

using LaTeXStrings, Plots; pgfplotsx()
st0 = "Relative abundance of: "
st1 = "E. coli"
plot();
annotate!(0.5,0.5, (L"\textcolor{blue}{\textrm{%$st0}} \textcolor{red}{\textbf{\textit{%$st1}}}", 12))

Thank you.

1 Like

I got really excited for a moment, but I tried:

ax = Axis(fig[1, 1]; xlabel=L"Relative abundance of \textit{E. coli}")

and got

caused by: TeXParseError: unsupported command \textit
at position 30 (string index 30)
Relative abundance of \textit{E. coli}
                             ^

LaTeXStrings.jl does not do any rendering. It is only for convenience to avoid mess with all the escaping when interpolating strings that contain LaTeX commands, as far as I understand. The rendering in Makie.jl is done via MathTexEngine.jl but it looks like it has not yet implemented different fonts. It could be a good pathway to contribute to MathTexEngine, no?

You can just use Unicode italics (assuming you have a font that covers these characters):

text("Relative abundance of 𝘌. 𝘤𝘰𝘭𝘪")

(In Julia, type by tab-completing \itE, \itc, etcetera. You could easily write a function that converts ASCII letters in a string to their Unicode italic, bold, etcetera equivalents, but the web site linked above is also pretty convenient.)

2 Likes

This no longer seems to work:

text("Relative abundance of E. coli",
           font = [fill("TeX Gyre Heros Makie", 22); fill("TeX Gyre Heros Makie Italic", 7)])
ERROR: BoundsError: attempt to access 1-element UnitRange{Int64} at index [2]
Stacktrace:

what about rich()?

1 Like

Ah, lovely. TIL

fig=Figure()
ax = Axis(fig[1,1], 
          xlabel=rich("Relative abundance of ", rich("E. coli"; font=:italic))
)

1 Like

Is there a chance to get sans-serif font?
\textsf{} does not work for me under GLMakie

Yes, Unicode has codepoints for sans-serif characters, which you can type in Julia by tab-completing \sansE, \sanst etcetera to get text like “𝖤𝗍𝖼”.

1 Like

Cool!!! - Thanks!!! :heart: