Mathjax: Replacing font of MathJax3

Created on 14 Dec 2020  路  3Comments  路  Source: mathjax/MathJax

In our project, we want to use a different font in the math expressions.
This is what we did:

  1. set the ascent and descent of the font to 30
  2. generate new font data

this is how we get the new padding style from the glyphs

padding-top: glyph.yMax / font.unitsPerEm
padding-left: glyph.advanceWidth / font.unitsPerEm
padding-bottom: -glyph.yMin / font.unitsPerEm
padding-right: 0

So far the math expressions looks good.
But there are still some questions:
How do we get the padding-top and padding-bottom if the glyph is above the baseline (yMin > 0)?
Is there some other things that we are missing?

Question v3

Most helpful comment

You shouldn't be generating CSS yourself, as MathJax will do that for you from the font data. I'm assuming you are going to be replacing the font data for the characters that you are taking from a new font (rather than defining a completely new MathJax font). This would require subclassing the TeXFont object and adding your new characters to it, overriding the ones it contains, and adding the needed CSS definitions for the font identifiers and @font-face rules for the web-fonts that you are using.

Here is a small example that replaces A in the normal, bold, and italic variants with the ones from the Arial font (taken as a local font).

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
<title>Replace Glyph in CHTML Font</title>
<script>
MathJax = {
  startup: {
    ready() {
      //
      //  If you make your own component, these would be obtained
      //  via require() or import commands
      //
      const TeXFont = MathJax._.output.chtml.fonts.tex_ts.TeXFont;
      const Package = MathJax._.components.package.Package;

      //
      //  Font data, by variant and Unicode position.  The array is 
      //  height, depth, width, and additional information.  Here f gives 
      //  the font specifier (which refers to the defaultStyles and 
      //  defaultFonts given below).
      //
      const chars = {
        normal: {
          0x41: [.73, 0, .667, {f: 'M-R'}] 
        },
        bold: {
          0x41: [.73, 0, .722, {f: 'M-B'}]
        },
        italic: {
          0x41: [.73, 0, .667, {f: 'M-I'}]
        },
      };

      class MyFont extends TeXFont {
        constructor(options) {
          super(options);
          //
          //  Add in the characters for the substitute font defined in chars
          //
          for (const variant of Object.keys(chars)) {
            this.defineChars(variant, chars[variant]);
          }
        }
      }

      //
      //  Add the font styles to select the proper fonts
      //
      Object.assign(MyFont.defaultStyles, {
        '.TEX-M-R': {
          'font-family': 'MJXZERO, MJXTEX-M-R'
        },
        '.TEX-M-B': {
          'font-family': 'MJXZERO, MJXTEX-M-B',
        },
        '.TEX-M-I': {
          'font-family': 'MJXZERO, MJXTEX-M-I'
        }
      });

      //
      //  Add the font definitions (using local fonts, but could be web fonts)
      //
      Object.assign(MyFont.defaultFonts, {
        '@font-face /* M-R */': {
          'font-family': 'MJXTEX-M-R',
          src: 'local("Arial"), local("Arial-Regular")'
        },
        '@font-face /* M-B */': {
          'font-family': 'MJXTEX-M-B',
          src: 'local("Arial Bold"), local("Arial-Bold")'
        },
        '@font-face /* M-I */': {
          'font-family': 'MJXTEX-M-I',
          src: 'local("Arial Italic"), local("Arial-italic")'
        }
      });

      //
      //  Configure CommonHTML to use the new font
      //
      MathJax.config.chtml = {font: new MyFont({fontURL: Package.resolvePath('output/chtml/fonts/woff-v2', false)})};

      MathJax.startup.defaultReady();
    }
  }
};
</script>
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
</head>
<body>

<p style="font-size: 200%">
$$ABx + {\bf AB} + {\rm AB}$$
</p>

</body>
</html>

Perhaps that will get you started.

We are working on adding more font support, and are developing the tools to create the data files needed, but they aren't ready for prime time yet. They should be available by Q2 next year, if all goes well.

All 3 comments

You shouldn't be generating CSS yourself, as MathJax will do that for you from the font data. I'm assuming you are going to be replacing the font data for the characters that you are taking from a new font (rather than defining a completely new MathJax font). This would require subclassing the TeXFont object and adding your new characters to it, overriding the ones it contains, and adding the needed CSS definitions for the font identifiers and @font-face rules for the web-fonts that you are using.

Here is a small example that replaces A in the normal, bold, and italic variants with the ones from the Arial font (taken as a local font).

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
<title>Replace Glyph in CHTML Font</title>
<script>
MathJax = {
  startup: {
    ready() {
      //
      //  If you make your own component, these would be obtained
      //  via require() or import commands
      //
      const TeXFont = MathJax._.output.chtml.fonts.tex_ts.TeXFont;
      const Package = MathJax._.components.package.Package;

      //
      //  Font data, by variant and Unicode position.  The array is 
      //  height, depth, width, and additional information.  Here f gives 
      //  the font specifier (which refers to the defaultStyles and 
      //  defaultFonts given below).
      //
      const chars = {
        normal: {
          0x41: [.73, 0, .667, {f: 'M-R'}] 
        },
        bold: {
          0x41: [.73, 0, .722, {f: 'M-B'}]
        },
        italic: {
          0x41: [.73, 0, .667, {f: 'M-I'}]
        },
      };

      class MyFont extends TeXFont {
        constructor(options) {
          super(options);
          //
          //  Add in the characters for the substitute font defined in chars
          //
          for (const variant of Object.keys(chars)) {
            this.defineChars(variant, chars[variant]);
          }
        }
      }

      //
      //  Add the font styles to select the proper fonts
      //
      Object.assign(MyFont.defaultStyles, {
        '.TEX-M-R': {
          'font-family': 'MJXZERO, MJXTEX-M-R'
        },
        '.TEX-M-B': {
          'font-family': 'MJXZERO, MJXTEX-M-B',
        },
        '.TEX-M-I': {
          'font-family': 'MJXZERO, MJXTEX-M-I'
        }
      });

      //
      //  Add the font definitions (using local fonts, but could be web fonts)
      //
      Object.assign(MyFont.defaultFonts, {
        '@font-face /* M-R */': {
          'font-family': 'MJXTEX-M-R',
          src: 'local("Arial"), local("Arial-Regular")'
        },
        '@font-face /* M-B */': {
          'font-family': 'MJXTEX-M-B',
          src: 'local("Arial Bold"), local("Arial-Bold")'
        },
        '@font-face /* M-I */': {
          'font-family': 'MJXTEX-M-I',
          src: 'local("Arial Italic"), local("Arial-italic")'
        }
      });

      //
      //  Configure CommonHTML to use the new font
      //
      MathJax.config.chtml = {font: new MyFont({fontURL: Package.resolvePath('output/chtml/fonts/woff-v2', false)})};

      MathJax.startup.defaultReady();
    }
  }
};
</script>
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
</head>
<body>

<p style="font-size: 200%">
$$ABx + {\bf AB} + {\rm AB}$$
</p>

</body>
</html>

Perhaps that will get you started.

We are working on adding more font support, and are developing the tools to create the data files needed, but they aren't ready for prime time yet. They should be available by Q2 next year, if all goes well.

PS, characters with yMin > 0 will have negative depth, which is allowed.

Thank you. I will do it like your example.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

albertodiazdorado picture albertodiazdorado  路  6Comments

cebola2 picture cebola2  路  3Comments

abhikhatri picture abhikhatri  路  4Comments

henok-tesfaye picture henok-tesfaye  路  6Comments

MasaYan24 picture MasaYan24  路  4Comments