jsMath (Authors)

# Making Your Own jsMath Fonts

make-jsMath-font-1.2.zip (24KB)
It contains the scripts you need in order to create the files used by jsMath for extra fonts.

## Overview:

In order for jsMath to handle an extra font, it needs to have several things: first, it needs a subdirectory in the jsMath/fonts directory named for the new font, and in that directory should be a def.js file that tells jsMath about the font and the characters in it. Second, in order to handle the image fallback mode for the font, this directory should contain two sub-directories called "alpha" and "plain", which store the images of the characters in the font at the various sizes that jsMath needs.

The make-jsMath-font command will make all these files for you. If you want the extra font to work in unicode fallback mode, you will need to hand edit the file to include the unicode code points for the characters in the font. This is tedious, but will make your font work in all viewing modes, and your users will be thankful for it. On the other hand, image mode works very well in most situations, so you can get by without unicode tables in most cases.

## Configuration:

The make-jsMath-font script uses several programs to help it create the necessary files. These include latex, dvipng (1.6 or later), mftrace, fontforge, and (optionally) ImageMagick's convert command. You will need to have these programs installed on your machine before you can generate jsMath fonts.

You also need to tell make-jsMath-font where these programs are located on your system. This is done by editing the bin/config.pl file. It contains the paths to the various commands that make-jsMath-font will require. You should not need to edit other files. If you don't have the convert command, set \$CONVERT to an empty string; it is only used to reduce the size of the alpha-channel images, and is not strictly necessary.

## Making a Font:

To create a new jsMath font, cd to the directory containing the make-jsMath-font script and type
./make-jsMath-font fontname
where "fontname" is the name of the TeX font to be created. For example,
./make-jsMath-font cmbsy10
would create the files jsMath needs to handle the Computer Modern bold symbol font. It takes several minutes to generate all the images, but the script will give you updates on its progress.

You can specify a value for Metafont's "blacker" parameter to make a version of the TTF file that is heavier than the default.

./make-jsMath-font 25 cmsy10
The CM fonts are designed to be rather thing, and on the PC in particular, these do not render well on screen, so a heavier version is helpful. Values between 10 and 35 seem to work well for most fonts. Note, however, that some fonts, or some characters within a font, may not honor the "blacker" value, and so this setting may not always help. A reasonable value for the PC is 25 and for the Mac is 10.

When the script completes, you should have several new files in this directory. First, there is a fonts directory containing a subdirectory for your font. In the example above, you would get fonts/cmbsy10. The cmbsy10 directory needs to be placed in your jsMath/fonts directory on your web server in order to make this new font available to your web pages.

You will also see a .ttf file (in this example, cmbsy10.ttf), which is the TrueType font file that your users should install on their computers in order to take full advantage of the font. (Note that the name includes "jsMath", since the encoding for the font is not one that will be useful in other applications. This also prevents the font from conflicting with the ones used by Firefox or the MathPlayer plugin for MSIE on the PC.) You probably should make the .ttf file available on your website for them to download. If they don't install the font, they may get a font warning message, and jsMath will use the image fallback method for these fonts. That will work fine, except that you can not use the \color command to change the math displayed in this font to another color, and it will not print at as high a resolution as the rest of the text.

[If you want to make additional .ttf files without rebuilding all the images, use, for example,

./bin/mkttf.pl 10 cmsy10
to make just the .ttf file for cmsy10 with blacker set to 10. You may want to make darker versions for the PC and ligher for the Mac, and make both available on your website.]

Finally, you should also find an .html file (for example, cmbsy10.html) that contains an HTML font table (like the ones appearing on the jsMath website) that should display the contents of the new font. Note, however, that this is not a complete HTML file, just the table itself; you will need to insert this into an HTML file that loads jsMath.js from the proper location on your server and then calls jsMath.Process() before you can actually view the font table.

Before you can use the font with jsMath.js, however, you will have to do one bit of editing by hand, which is described in the next section.

When your browser loads a page that includes an extra jsMath font, jsMath will try to determine if you have the .ttf file for that font installed on your computer. It does this by trying to access a character within the new font, and compares that to what it would have gotten in the browser's default serif font. If the new font is not available, the browser will take the character from the serif font, so jsMath can compare the size of the character it got to the size of the character it would normally get from the serif font. If they differ, then jsMath assumes the .ttf file is present, and if they are the same, jsMath assumes the font is unavailable.

To make this work correctly, jsMath needs to test a character that will have a noticeably different size in the new font from what it would normally have in the serif font. But jsMath can usually only distinguish the WIDTHs of the characters (since all characters in the same font return the same character height to the browser). That means that in order for jsMath to test the font, you need to specify a character for it to use, and that character should be significantly different in its width from the usual character in that font position. You specify the character using the position within the TeX font (a number from 0 to 127, or 0x00 to 0x7F in hex), but you should stick to the characters between 33 and 126 (0x21 and 0x7E), since the other ones are mapped to unusual locations by the font encoding. Some usual candidates are thin characters like "|" (0x7C), ":" (0x3A), ";" (0x3B), "." (0x2E), "," (0x2C), and "!" (0x21), when the corresponding positions contain wide characters in the new font. Alternatively, you can look for thin characters in the new font that correspond to wide ones in the standard font, though there are usually fewer of those.

The make-jsMath-font script will make an educated guess about what the best character and multiplication factor should be for your font. It uses a table of "typical" widths for the serif font to do this, and since these widths might not match your browser's fonts exactly, the test it picks might not be the best one. In particular, if the scaling factor is less than 2, you might need to adjust the character or the factor by hand.

To help you find an appropriate character, you can use the font-table.tex file located in this directory. If you tex this file, you will be prompted for the name of a font (e.g., cmbsy10) and the magnification (5 is a good value for most fonts). The result will be a table that shows all the characters in the font (with small numbers indicating the position of each character within the font, in both hex and decimal). If you make a table for your new font and for cmtt10 (which has the normal ASCII characters in positions 33 through 126), so you can compare these to see which characters differ in width the most.

When you have selected a suitable character, edit the def.js file in the fonts subdirectory for your new font (e.g., fonts/cmbsy10/def.js in our example above). Near the bottom of the file is a section where the font is registered with jsMath. Look for the testChar specification and set the value that follows to be the position of the character you selected (either in decimal or hex). The testFactor says how much larger the character in the new font has to be in order to count as indicating the presence of the font. Try to pick a character where the factor can be at least 2. This is not always possible, however, so you can reduce that factor if necessary. Remember that some people may have a different default font setting than yours, so leave a little leeway in your factor. Also, test your setting using both large and small font sizes (zoom the test page in or out and reload it) to make sure that the factor is suitable in a variety of sizes. Finally test your choice with more than one browser if you can. If you are testing a character that is thinner in the new font than in the serif font, change the test value from jsMath.Font.Test1 to jsMath.Font.Test2.

Once you have a working test character, the new font should work well in jsMath's TeX-font mode and in the two image-font modes. The user may still select the unicode fallback method, however, and make-jsMath-font does not create a unicode fallback table for the font. That is because it does not know what the characters in the font look like, so can't tell what unicode code points to map them to; you'll have to do that yourself. This is described in the next section.

## Setting up a Unicode Fallback Table:

If you want your new font to work in unicode fallback mode, you will need to tell jsMath what unicode code points to use for each character when the the TeX font is not installed on the user's computer. Unfortunately, this needs to be done by hand, in most cases. You might find the character charts at http://www.unicode.org/charts/ to be of benefit in this; it includes an alphabetical list of code points by name in addition to the charts. For Mac OS X users, the Edit menu contains a Special Characters item which can be used to locate unicode characters (select "Code Tables" or "All Characters" from the View menu at the top of the dialog for the most complete listings).

There are several methods for entering the code tables into the def.js file. One of them is given in a comment at the bottom of the file (in the fallback item of the Register command). This method allows you to replace individual items in the main list at the top of the page; if the font contains the usual alphabetic and numeric characters, for example, you would not need to replace them, so this might be the most convenient method. Another method allows you to replace all the character fields for all the characters in the font at once; see the msam10/def.js file for an example of how this is done.

Determining the unicode code points for all the characters in the font can be a tedious job. The find-unicode command in this directory can help. It requires a .pfa file that contains the correct encoding for the font, and uses the character names from that encoding to look up the corresponding unicode code points. Many TeX installations include properly encoded .pfb files (look in texmf/fonts/type1); if yours doesn't, you can find them on http://www.ctan.org/ by searching for the filename you are interested in. If you have a .pfb file, you can convert it to a .pfa file using the pfbtopfa command.

If you don't have a .pfa or .pfb file, you may be able to create one using mftace, but only if it is able to determine the correct encoding file. If it uses tex256.enc, you are probably out of luck, because that is unlikely to be the correct encoding. You may be able to find the right one in the texmf/dvips hierarchy (look for .enc files), or on CTAN.

Once you have a usable .pfa file, use the command

./find-unicode file
where file is the name of the .pfa file. This will look through the .pfa file for named character positions, and use FontForge to look those names up. Unfortunately, not all .pfa files use names that FontForge will recognize, but it can sometimes be a help. The output of find-unicode will be the table that you need to past into the def.js file in fallback function. When FontForge doesn't know the character, find-unicode will use '??' for the character value; you will need to look through the unicode tables by hand to find appropriate code points. Only those code points that are not already properly set in the main table will be printed (e.g., for fonts that have the alphabetic characters in their usual places).

Note that you will need to remove the comma following the last entry in the list when you paste the table into the def.js file. Although Mozilla will process the list when there is an extra comma, other browsers won't so you need to be careful about that.

Sometimes FontForge does know the proper code point, but only if the name were capitalized differently. For example, the wasy10.pfa file lists one of its entries as "aries", but FontForge will only recognize "Aries". You might use the command

strings which fontforge | grep -i name
where name is the name of the character you are interested in. It might show you names that FontForge would recognize. You can edit the .pfa file to use these names instead and run find-unicode again.

To use your new font in your own web page, first load jsMath.js in the usual way, then include