Skip to content

LaTeX without npm #448

@davibarreira

Description

@davibarreira

Hello Javis developers. This is actually a tip. I've been playing around with Luxor, and I've implemented LaTeX without the need to install LaTeX in the users computer. To do so, I've used the package MathTeXEngine.jl. This awesome package is the one used by Makie to write LaTeX. Here is my implementation for a package that I'm working on

"""
    latex_text_size(lstr::LaTeXString)
Returns the width and height of a latex string.
"""
function latex_text_size(lstr::LaTeXString)
    sentence = generate_tex_elements(lstr)
    els = filter(x -> x[1] isa TeXChar, sentence)
    chars = [x[1].char for x in els]
    fonts = [x[1].font for x in els]
    pos_x = [x[2][1] for x in els]
    pos_y = [x[2][2] for x in els]
    scales = [x[3] for x in els]
    extents = [get_extent(f, c) for (f, c) in zip(fonts, chars)]

    textw = []
    texth= []
    for i in 1:length(extents)
        textw = push!(textw,height_insensitive_boundingbox(extents[i], fonts[i]).widths[1]*scales[i]+pos_x[i])
        texth = push!(texth,height_insensitive_boundingbox(extents[i], fonts[i]).widths[2]*scales[i]-pos_y[i])
    end
    return (maximum(textw), maximum(texth))
end


"""
    Luxor.text(lstr::LaTeXString, valign=:baseline, halign=:left; kwargs...)
Draws LaTeX string using `MathTexEngine.jl`. Hence, uses ModernCMU as font family.
Note that `valign` is not perfect.
This function assumes that the axis are in the standard Luxor directions,
i.e. ↓→.
"""
function Luxor.text(lstr::LaTeXString, pt::Point; valign=:baseline, halign=:left, kwargs...)

    # Function from MathTexEngine
    sentence = generate_tex_elements(lstr)

    # Get current font size.
    textsize = get_fontsize()

    textw, texth = latex_text_size(lstr)
    
    if halign === :left
        translate_x = 0
    elseif halign === :right
        translate_x = -textw * textsize
    elseif halign === :center
        translate_x = -textw/2 * textsize
    end
    
    if valign === :baseline
        translate_y = 0
    elseif valign === :top
        translate_y = -textsize
    elseif valign === :bottom
        translate_y = texth * textsize
    elseif valign === :middle
        translate_y = textsize/2
    end

    # Writes text using ModernCMU font.
    for text in sentence
        if text[1] isa TeXChar
            @layer begin
                translate(translate_x,translate_y)
                fontface(text[1].font.family_name)
                fontsize(textsize*text[3])
                Luxor.text(string(text[1].char), pt + Point(text[2]...)*textsize*(1,-1))
            end
        elseif text[1] isa HLine
            @layer begin
                translate(translate_x,translate_y)
                pointstart = pt+Point(text[2]...)*textsize*(1,-1)
                pointend = pointstart + Point(text[1].width,0)*textsize
                setline(1*text[1].thickness*textsize)
                line(pointstart, pointend,:stroke)
            end
        end
    end
end

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions