Latex in Luxor

i want to text latex in luxor but it seems wrong with fonts

ther is the code:

using Luxor
using MathTeXEngine

@svg begin
background("khaki")
f(t) = Point(4cos(t) + 2cos(5t), 4sin(t) + 2sin(5t))
setline(15)
fontsize(35)
@layer begin
    setopacity(0.4)
    sethue("purple")
    poly(20f.(range(0, 2π, length=160)), :stroke)
end
sethue("grey5")
text(L"f(t) = [4cos(t) + 2cos(5t), 4sin(t) + 2sin(5t)]", halign=:center)
end

But i get the wrong result:

i have installed the fonts in the MathTeXEngine into the system.
where is the problem and what can i do

Does this help?

https://github.com/JuliaGraphics/Luxor.jl/issues/32

Yes the fonts have to be installed correctly for it to work. In my testing, the fonts have to be available from two places: inside the MathTEXEngine folder and from the system’s font folder (which depends on the OS, among other things). While it does work eventually (as you can see from the examples in the docs), it’s sometimes a struggle getting there. The problem is that successfully installing fonts on all OS combinations isn’t as easy as it should be.

Any update on this? I have the same problem with Ubuntu Linux. MathTexEngine is working, but the resulting font is not Computer Modern.

I would recommend the Luxor GitHub page. If there is nothing about this in the documentation, add a comment on an issue if you find one or make an issue if you don’t.

2 Likes

It’s an active issue at the moment.

It’s fair to describe LaTEX support as experimental at present. But if you don’t see the right fonts at all, then it might be something to do with how you installed them. Perhaps you could provide more details in a new issue …

I got it working nicely. One question, though.
Does anyone know if drawing math variables in italics, as in latex, is possible?

Could you give an example of what you’d normally type in LaTeX? I can check the code to see if it’s possible. (Note that Latex support in Luxor is currently on hold, pending developments in Cairo.jl.)

For example, the figure below shows the text “coordinate” and the function name “sin” as regular text, while the variable “x” is shown in italics. The input for xlabel would be L"$x$ coordinate" and for ylabel L"$\sin(x^2)$".


I noticed that Makie can render this way using MathTexEngine; however, I could not figure out how they implemented that.

Haha, yes, I don’t think this is possible. The Makie folks have implemented a powerful font system that does all kind of things; Luxor isn’t in the same league… :slight_smile:

There’s a possible workaround for text placement, an old experimental function which was kind of made obsolete when MathTeXEngine.jl came along: Luxor.textplace() . I had to use it once…

@drawsvg begin
    background("black")
    sethue("gold")
    fontface("Cmr10")
    textplace("sin x2", Point(-250, 0),
        [
            (face = "Cmr10", color = colorant"gold", size = 200,),    # s
            (),   # i
            (),   # n 
            (),   # ' '
            (face = "Cmmi10",),  #x
            (size = 150, shift = 50,),  #2
        ],
        action=:fill
    )
end

but doing this by hand for more than two text strings isn’t going to be fun, though…

1 Like

sure… haha

I thought changing the font while traversing each character in a LaTeXString would be possible in Luxor. It does not seem to be the case.

I managed to display regular and italic text in equations using Luxor, LaTeXStrings, and MathTexEngine. Thanks @cormullion, for the insights.

Below is an example figure and the code I used. The function setlatex is similar to the settext function but for latex strings. I believe that something like this can be easily added to Luxor.

function getwidth(texelems)
    fsize = get_fontsize()
    width = maximum([elem[2][1] for elem in texelems], init=0.5)
    return width*fsize
end

function getheight(texelems)
    fsize = get_fontsize()
    maxh = maximum([elem[2][2] for elem in texelems], init=1.0)
    minh = minimum([elem[2][2] for elem in texelems], init=0.0)
    return (maxh-minh)*fsize
end

function setlatex(str, pt; halign="center", valign="center", angle=0)
    str = latexstring(str)
    elems = generate_tex_elements(str)
    fsize = get_fontsize()

    width = getwidth(elems)
    height = getheight(elems)

    rw = halign=="center" ? 0.5 : halign=="right" ? 1.0 : 0.0
    rh = valign=="center" ? 0.5 : valign=="top" ? 1.0 : 0.0

    xref = pt.x + rw*width
    yref = pt.y - rh*height

    θ = angle*pi/180
    T = [ cos(-θ) -sin(-θ); sin(-θ) cos(-θ)]

    for elem in elems
        point = elem[2]
        x = pt.x + point[1]*fsize
        y = pt.y - point[2]*fsize
        elem[1] isa TeXChar && (y += 0.4*fsize)

        x, y = T*[ x-xref, y-yref ] .+ [ pt.x, pt.y]
        if elem[1] isa TeXChar
            texchar = elem[1]
            scale = elem[3]
            glyph = texchar.represented_char

            fnt = texchar.slanted ? "NewComputerModern Italic" : "NewComputerModern Regular"
            setfont(fnt, fsize*scale)
            settext(string(glyph), Pt(x,y), halign="left", valign="bottom", angle=angle)
        elseif elem[1] isa HLine
            hline = elem[1]
            w = hline.width*fsize
            setline(hline.thickness*fsize)
            line(Pt(x, y), Pt(x+w*cos(-θ), y+w*sin(-θ)), :stroke)
        end
    end
end
2 Likes