My goal is to type regular LaTeX input, and remap the fonts to produce Nemeth Braille. One answer to the question LaTeX to Braille was to download the font http://www.searchfreefonts.com/free/braille.htm . This doesn't work for me because this font doesn't map (by default) ASCII characters the same way as Nemeth Braille. For instance using that font, 0 and 9 become ⠔ and ⠯ instead of ⠴ and ⠔ respectively.
Furthermore, in any case I'd like to be able to map, in some cases, an individual ASCII character to a pair of Braille characters.

I tried using the font handling features of luatex to make substitutions. They didn't seem to have any effect for the font mentioned in the answer above, but they did for DejaVu.

Here's what I tried:

% -*- TeX-engine: luatex; -*-

fonts.handlers.otf.addfeature {
    name = "braille",
    type = "substitution", 
    data = {
      ["a"] = "⠁", ["b"] = "⠃", ["c"] = "⠉",
      % etc. all the way to z
      ["A"] = {"⠠","⠁"}, ["B"] = {"⠠","⠃"},
      ["C"] = {"⠠","⠉"}, % etc. all the way to Z

fonts.handlers.otf.addfeature {
    name = "combos",
    type = "multiple", 
    data = {
      ["="] = {" ","⠨","⠅"," "}, 
      ["X"] = {"⠠","⠭"}, 
      ["Y"] = {"⠠","⠽"},

\setmainfont{DejaVu Sans}[RawFeature=+braille;+combos]

abc = ABC = XY 

$abc\ =\ ABC\ =\ XY$  % should be identical to previous line


Output of MWE

What still doesn't work: (1) The font feature of type substitution doesn't let me replace one character of input with two characters of output (or I don't know how to make it do this). So A, B, and C are incorrect in both lines. (2) The font feature of type multiple does allow one input go to two output characters, but it's not inherited by the math fonts using the mathastext package (or I don't know how to make it do this). So =, X and Y are incorrect in the math line.

Does anyone know how to get the remapping to work for either DejaVu or the Braille font mentioned above?

Update If I add to the MWE above (plus quite a few more substitutions) I get this:

And now we can conclude that
\int_0^\infty e^{-x^2}\,dx = \sqrt{\pi}/2
Here it is with better Nemeth
\int_0^\infty\baseline e^{-x^^2}\baseline \,dx \eq \sqrt{\pi}/2

and here is the output

Longer sample Nemeth code

The first version of the equation is unmodified LaTeX code, but with all the substitutions and commands translated. I think it's not a bad start.

The second one requires the author to make a few changes: indicating when a subscript/superscript is over, and indicating when there's a double superscript, and I used a command for the equals sign (because, as mentioned above, I couldn't get the combination substitution to work). My guess is that more of the latex code could be automated, requiring fewer changes by the author (especially with Luatex?). But it's still not horrible to imagine adding the extra markup to make the Nemeth more accurate.

  • Can we assume that the font will only be used in math mode? Commented Jul 24, 2019 at 22:15
  • 1
    I don't think it is that simple to convert LaTeX math to Nemeth. See the article by Susan Jolly in the recent TugBoat. She wrote MathML to Nemeth convertor in Java, but I haven't tried it yet.
    – michal.h21
    Commented Jul 24, 2019 at 22:20
  • The font will be used in both main text and math. Commented Jul 25, 2019 at 10:30
  • True, it's not that simple. But the first step, for me, would be to map all the ASCII characters. After that, the basic macros are quite easy. With that, an author could do basic math if they are willing to add/change their markup. Things like tables and matrices would be harder. In any case, at present, I have something that works up to a point, and what's not working is mapping single ASCII characters to pairs of Braille, and someone who knows fonts and/or Luatex probably knows what I could change. Commented Jul 25, 2019 at 10:38
  • multiple substituations don't work with the mode=base used in math. But beside this I'm not convinced that the general idea is sound. Imho you will run into problems as soon as \int, or \frac or limits/superscripts etc are involved. Commented Jul 29, 2019 at 10:02

1 Answer 1


Here, I use tokcycle to parse the input and transform characters (and the macro \eq) into braille. However, it the course of doing this, I discovered a bug in my tokcycle package, in that it was not digesting = tokens properly. The fix, detailed in the postscript, is also incorporated into the MWE.

EDIT: To demonstrate how macros can be remapped in the same way as characters, I mapped the \eq macro to take on the desired meaning of what would otherwise be the = token. Macros can be mapped in this way without destroying their original meaning outside of the \braille pseudo-environment.

By automatically wrapping the braille mappings in a \textrm{}, the issue of math mode becomes moot, except that spaces are intercepted in math mode and converted to explicit \ spacing.

Compiled here with lualatex.

\setmainfont{DejaVu Sans}%[RawFeature=+braille;+combos]
\tokcycleenvironment\braille%  NEW TOKCYCLE ENVIRONMENT:
{\addcytoks[4]{\tcremap{##1}}}%   HOW TO TREAT CHARACTERS
{\processtoks{##1}}%              HOW TO TREAT GROUP CONTENTS
{\addcytoks[4]{\tcremap{##1}}}%   HOW TO TREAT MACROS
{\addcytoks{\ }}%                 HOW TO TREAT SPACES
\newcommand*\tcmapto[2]{\expandafter\def\csname tcmapto\string#1\endcsname{\textrm{#2}}}
\newcommand*\tcremap[1]{\ifcsname tcmapto\string#1\endcsname
  \csname tcmapto\string#1\expandafter\endcsname\else\expandafter#1\fi}
\tcmapto a{⠁} \tcmapto b{⠃} \tcmapto c{⠉} 
\tcmapto A{⠠⠁} \tcmapto B{⠠⠃} \tcmapto C{⠠⠉}
\tcmapto X{⠠⠭} \tcmapto Y{⠠⠽} \tcmapto ={ ⠨⠨ } 
1. \braille abc = ABC = XY\endbraille

2. \braille$abc = ABC = XY$\endbraille  % should be identical to previous line

3. \braille abc \eq{} ABC \eq{} XY\endbraille

4. \braille$abc \eq{} ABC \eq{} XY$\endbraille  % should be identical to previous line


$\eq$ reverts to non-braille

enter image description here

  • 1
    I haven't had time to play with this recently, but I'll check it out soon. It looks like a good approach. Commented Feb 4, 2020 at 21:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .