Skip to content

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

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions