CairoMakie.jl, MathTeXEngine.jl, Small Caps

Hi there!

I have been struggling for the last hour with the following issue.
I want to have a word in small caps within my legend in a CairoMakie plot.

To get a word in small caps in Latex I just do \textsc{Foo}.

Here is what I have done in Julia

using CairoMakie, LaTeXStrings
set_theme!(theme_latexfonts())
fig = Figure()
ax = Axis(fig[1, 1])
lines!(1:5, label=L"\textbf{Foo}")
lines!(1:2:5, label=L"\textsc{Foo}")
axislegend(position=:lt)

EDIT: now the whole error.
This gives me the following error:

Failed to resolve arg1:

[ComputeEdge] arg1 = compute_identity((linesgments_shifted, ), changed, cached)

  @ /Users/markuspirke/.julia/packages/ComputePipeline/03tW7/src/ComputePipeline.jl:737

[ComputeEdge] linesgments_shifted = (::MapFunctionWrapper(#2928))((linesegments, lineindices, preprojection, model_f32c, positions_transformed_f32c, model_clip_planes, space, ), changed, cached)

  @ unknown method location

[ComputeEdge] glyphcollections, glyphindices, font_per_char, glyph_origins, glyph_extents, text_blocks, text_color, text_rotation, text_scales, text_strokewidth, text_strokecolor, linesegments, linewidths, linecolors, lineindices = #2906((input_text, fontsize, selected_font, align, rotation, justification, lineheight, word_wrap_width, offset, fonts, computed_color, strokecolor, strokewidth, ), changed, cached)

  @ /Users/markuspirke/.julia/packages/Makie/4JW9B/src/basic_recipes/text.jl:333

  with edge inputs:

    input_text = LaTeXStrings.LaTeXString[L"$\textsc{Foo}$"]

      fontsize = 14.0f0

    selected_font = FTFont (family = NewComputerModern Math, style = Regular)

    align = (:center, :center)

    rotation = 1.0 + 0.0im + 0.0jm + 0.0km

    justification = :left

    lineheight = 1.0f0

    word_wrap_width = -1.0f0

    offset = Float32[0.0, 0.0, 0.0]

    fonts = Attributes()

    computed_color = RGBA{Float32}(0.0, 0.0, 0.0, 1.0)

    strokecolor = RGBA{Float32}(0.0, 0.0, 0.0, 0.0)

    strokewidth = 0.0f0

Triggered by update of:

  position, text, arg1, fontsize, fonts, font, align, rotation, justification, lineheight, word_wrap_width, offset, fonts, color, colorscale, alpha, colorrange, colorscale, color, colorscale, alpha, colormap, alpha, nan_color, lowclip, colormap, alpha, highclip, colormap, alpha, colormap, alpha, strokecolor or strokewidth

Due to ERROR: TeXParseError: unexpected error

at position 2 (string index 2)

$\textsc{Foo}$

 ^

Stack

[4] TeXExpr :command

└─ "\\textsc"

[3] TeXExpr :inline_math

[2] TeXExpr :line

[1] TeXExpr :lines



Failed to show error:

UndefVarError: `tex` not defined in `MathTeXEngine`

Suggestion: check for spelling errors or missing imports.

Stacktrace:

  [1] showerror(io::IOContext{IOBuffer}, e::MathTeXEngine.TeXParseError)

    @ MathTeXEngine ~/.julia/packages/MathTeXEngine/dUSrK/src/parser/parser.jl:11

  [2] showerror

If I only use \textbf{Foo} it works perfectly fine.

Any ideas how to solve this issues? Or what the problem is?

1 Like

What’s the actual error further down? Maybe this is just not a supported thing in MathTeXEngine, yet?

I added the complete error message. Maybe you are right, but for me that was not entirely clear from the error message.

MathTeXEngine does not support \textsc, and as far as I can tell, it is non-trivial to implement.

This is my understanding:

The supported text styles work because there are separate fonts for them. So when, e.g., bold text is requested, the text is rendered using a bold version of the selected font family (NewCM10-Bold.otf). If there was a small caps font, then it would not be that difficult to plug it in (I think), but New Computer Modern (the default font) provides small caps as an OpenType feature, not as a separate font, and applying OpenType features is not currently implemented.

Something related seems to be implemented in this fork GitHub - manuelbb-upb/MathTeXEngine.jl at ssty. This fork deals with (sub/sup)-scripts in math notation using an OpenType feature, so maybe the same person would be able to implement small caps too.

1 Like

That sounds logical to me. Thank you for clarifying. I will take a look whether I find some hack to incorporate this, maybe with a font that explicitly has small caps.

Alternatively, you could cheat with rich text:

function smallcaps(s; fontsize=10)
    s = uppercase.(s)
    firstletter = s[begin:begin]
    remaining = s[nextind(s, firstindex(s)):end]
    smallersize = fontsize - 2
    return rich(firstletter, rich(uppercase.(remaining);
                                  fontsize=smallersize); 
                fontsize)
end

It does not look that terrible:

julia> set_theme!(theme_latexfonts())

julia> fig = Figure()

julia> ax = Axis(fig[1,1], title=smallcaps("abcd"))

3 Likes

Ah good idea. That is probably enough for what I need. This is just a workaround but I will mark this still as a solution to my problem :slight_smile:

1 Like

Actually, “small caps” is not a font feature (unlike e.g. ligatures), so I guess it’s a legit approach :wink:

1 Like