Skip to content

Font size calculation for text and MathTex is very confusing #4690

@rambip

Description

@rambip

Hello there !

I'm currently working on manim-web, a js port of this amazing project.
I noticed that the font-size logic was different, so I wanted to investigate to be sure the behavior is the same.

But looking at the source-code of manim, I'm very confused. I think this would be a good opportunity to rewrite, simplify, comment, and rename variables in the code regarding this logic.

I consider contributing, but I have some questions I would like to clarify before.

From what I understand, the pipeline for MathTex is:

  1. render the source string to Tex, DPI then SVG. You get an arbitrary size measured empirically (~10 units in the SVG world ?)
  2. extract the paths of the SVG, do NOT normalize them
  3. call self.font_size = self._font_size which in turns call the setter
  4. the setter does self.scale(font_val / self.font_size), where font_size is a getter
  5. the font_size getter returns the confusing self.height / self.initial_height / SCALE_FACTOR_PER_FONT_POINT where SCALE_FACTOR_PER_FONT_POINT=1/960.

So that means the output height is SVG_COMPUTED_HEIGHT * (INPUT_FONT_SIZE / (1 / SCALE_FACTOR_PER_FONT_POINT)), which means SCALE_FACTOR_PER_FONT_POINT is a combination of 2 things: "X svg points should be Y pt" and "Y pts should be Z units in manim"

And the pipeline for Text is:

  1. compute size = self._font_size and size /= TEXT2SVG_ADJUSTMENT_FACTOR where TEXT2SVG_ADJUSTMENT_FACTOR = 4.8 (
    size = self._font_size
    line_spacing = self.line_spacing
    size /= TEXT2SVG_ADJUSTMENT_FACTOR
    )
  2. Use manimpango to extract svg from text with size=size
  3. call self.scale(TEXT_MOB_SCALE_FACTOR) where TEXT_MOB_SCALE_FACTOR=0.05

And for one obscure reason the font-size is defined as:

@property
    def font_size(self) -> float:
        return (
            self.height
            / self.initial_height
            / TEXT_MOB_SCALE_FACTOR
            * 2.4
            * self._font_size
            / DEFAULT_FONT_SIZE
        )

with a hardcoded 2.4 value

For this one, I'm still trying to make sense of it.

Questions

  • is it true that the svg paths returned by Tex are not normalized ? It's a probably naive question but why ?
  • has SCALE_FACTOR_PER_FONT_POINT been set empirically or is there a reason ?
  • what does the size argument of manimpango do ? Why is there scaling after svg generation ?
  • I suspect the 2.4 has been added just because 2.4 / TEXT_MOB_SCALE_FACTOR is exactly 48, the default font size. Since they cancel out, why not just do self.height / self.initial_height * self._font_size ?
  • Wouldn't it be cleaner to have the same logic for Tex and SVG ? Render SVG in SVG point space, and do the same scaling afterward with one single SCALE_FACTOR_PER_SVG_FONT_POINT constant ?

Notes:

  • self.font_size = self._font_size
    has both font_size as a setter and _font_size, quite hard to make sense of
  • _font_size could be renamed _required_font_size, and assertions could be added so that the person reading the code knows what properties to expect in the code
  • SCALE_FACTOR_PER_FONT_POINT should be renamed SCALE_FACTOR_PER_SVG_FONT_POINT at least
  • TEXT_MOB_SCALE_FACTOR is defined in this file: https://github.com/ManimCommunity/manim/blob/main/manim/mobject/text/text_mobject.py . If it is really needed, it should go to the constants.py file
  • the size argument of manimpango is not documented

I hope my walkthrough is understandable, It was quite an adventure 😅

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions