Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect base anchors for equations #794

Open
hooyuser opened this issue Jan 15, 2025 · 0 comments
Open

Incorrect base anchors for equations #794

hooyuser opened this issue Jan 15, 2025 · 0 comments
Milestone

Comments

@hooyuser
Copy link

hooyuser commented Jan 15, 2025

In Issue #683 Content-Relative Anchors and #684 PR, CeTZ added support for base anchors, which works well for text. However, I observed incorrect results when using base anchors with equations. Below are examples demonstrating the issue, along with a proposed solution.

Examples of Incorrect Base Anchors

  1. Inline Equation
    The equation is $limits(sum)_(i in I)F(U_i)$
  1. Block Equation
    The equation is $ limits(sum)_(i in I)F(U_i) $

Proposed Solution

The #684 PR introduced a measure function to calculate the base anchor. While it works for text, it fails to measure equation baselines correctly.

@Enter-tainer suggested a way to accurately calculate the baseline of equations. I adapted this approach from the rehype-typst project and created a demo measure_equation.typ. The code for measure_equation.typ is hosted on (Typst App) and here are some tests for this baseline measure function:

measure_equation_test

This method uses the following strategy:

  • Define height as the part of the equation above the baseline.
  • Define depth as the part below the baseline.
  • Insert a function call pin(label) at the start of the equation.
    // a dict that stores the height of equations
    #let s = state("eq_height_dict", (:))
    
    // when called, retrieves the height of the equation, which is then stored in a state variable
    #let pin(label) = context {
      let height = measure(line(length: here().position().y)).width
      s.update(it => it.insert(label, height) + it)
    }
    
    // get the bounding box of an equation
    #let bounded(eq) = text(top-edge: "bounds", bottom-edge: "bounds", eq)
    
    // insert a function call `pin(label)`` at the start of the equation.
    #let add_pin(eq) = {
      let label = repr(eq)
      let formula = if eq.block == true {
        $ pin(label)#eq $
      } else {
        $pin(label)#eq$
      }
      bounded(formula)
    }
    The function is triggered when the equation is displayed at the top-left corner of the page. Within the function, here().position().y retrieves the height of the equation, which is then stored in a state variable.
  • Calculate height + depth using measure(text(top-edge: "bounds", bottom-edge: "bounds", eq)), and subtract the height to derive depth.
  • The equation must be displayed before any call to state.get(). The hide function is used to display the equation "virtually", preventing the equation from appearing in the final output.

Accurate base anchor for equation is crucial in math diagramming, as we expect math formulas within a line to align perfectly by their baselines. This alignment is essential for achieving a professional and polished look in mathematical diagrams. Currently, the incorrect calculation of base anchors blocks me from using Typst for diagram drawing, as demonstrated as follows:

unaligned

I hope we could introduce a specialized method for measuring equation to ensure correct base anchors, achieving functionality on par with LaTeX TikZ, and making it a more viable option for math diagrams. Let me know if there’s more I can do to help!

@johannes-wolf johannes-wolf added this to the 0.4.0 milestone Jan 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants