Configuring MathFlow for XMetaL

Behind the scenes, MathFlow consists of executable components integrated with the XMetaL editor via JavaScript code. The executable components and most of the script code do not depend on the specific document type with which MathFlow is being used. However, some of the script code must deal with the particular way in which MathML elements have been incorporated into a document-level markup language. This script code must be customized to work with specific document types.

Setting up a document type for use with MathFlow consists of the following general tasks:

  • Integrating the MathML DTD into your DTD for the document-level markup. The sample document type (doctype for short) included with MathFlow integrates the MathML DTD into the Journalist DTD.
  • Adding the ‹math› element to your customization file
  • Defining DTD-specific macros to call the corresponding MathFlow macros
  • Setting the MathML namespace prefix for the custom doctype
  • Adding an entry for the ‹math› element to the cascading stylesheet
  • Adding an entry for the ‹math› element to the HTML stylesheet

We will take a closer look at each of these steps in the next pages. However, before going into details, it is useful to have a broad view of the MathFlow architecture.

Application macros

The integration of MathFlow with XMetaL is defined in the mathflow.mcr file, which is located in <path-to-xmetal>\Author\Startup. This and the following topics give a brief summary of what these macros do.

These macros operate at the application level. They perform such functions as defining global variables and functions, initializing ActiveX objects and customizing the menus and toolbar.

  • On_Application_Open: This macro, which is triggered when XMetal is started, performs the following tasks:
    • Defines the global variables
    • Creates an instance of MathFlowXm.Util, which includes functions to load the Java VM, set the application path and set the license path.
    • Creates an instance of MathFlowXm.ImageWriter, which is used to generate images from MathML.
    • Creates an instance of MathFlowXm.Editor, which is the actual MathFlow Editor.
  • On_Application_Open_Complete: This macro reads the MathFlow preferences relating to the XMetaL editor (e.g., whether Fast Equation Rendering is on or off).
  • On_Application_Close: This macro, which is triggered when XMetal closes, cleans up the temporary images generated during the MathFlow editing session.
  • On_Macro_File_Load: This macro, which is triggered when mathflow.mcr is loaded, defines the global functions used during the MathFlow editing session
  • On_Default_CommandBars_Complete: This macro, which is triggered when the application is loading, customizes the menus and toolbars to include MathFlow options.

Document macros

These macros are invoked when the user performs an action on the document. The document's macros will simply call these macros. This places the MathFlow logic in one place and allows new doctypes to easily include MathFlow functionality.

  • MF_On_Before_Document_Save
  • MF_On_Before_Document_SaveAs

    These macros, which are triggered before a document is saved, remove MathFlow specific attributes from the document. MathFlow uses temporary attributes during the editing sessions. For example, when MathFlow generates an image from the MathML, it places its location in the "altimg" attribute.

  • MF_On_Document_Save
  • MF_On_Document_SaveAs

    These macros, which are triggered after a document is saved, set MathFlow specific attributes from the document.

  • MF_On_Document_First_Draw
  • MF_On_View_Change

    These macros, which are triggered when a document becomes active or inactive, enable or disable specific MathFlow menu items.

  • MF_On_Document_Activate
  • MF_On_Document_Deactivate

    These macros are triggered when the view of a document changes. They determine if the document is a MathML document and if images need to be updated.

  • MF_On_Double_Click: This macro, which is triggered when the user double clicks an equation, opens the MathFlow Editor for the equation.
  • MF_On_Document_Close: This macro, which is triggered when the document is closed, checks in the MathFlow license if there are no other documents with MathML still open. If there are, XMetaL will keep the MathFlow license checked out.
  • MF_On_Document_Before_DropText
  • MF_On_Document_After_DropText

    These macros, which are triggered when text is dropped onto the document, handle generating images if MathML is part of the dropped text.

CommandBar macros

These macros are invoked when the user clicks on a MathFlow icon on the toolbar or a menu item in the MathFlow menu.

  • refreshEquationImages: This macro, which is triggered when the user clicks on "MathFlow | Refresh Equation Images" from the menu, refreshes the MathML equation images in the current document.
  • mathflowInsertEquation: This macro, which is triggered when the user clicks on the MathFlow icon in the toolbar or selects "MathFlow | Insert Equation…" from the menu, opens the MathFlow Editor.
  • toggleFastRendering: This macro, which is triggered when the user clicks on "MathFlow | Fast Equation Rendering" from the menu, toggles whether or not MathFlow should use the C++ fast equation rendering component.
  • mathflowHelp: This macro, which is triggered when the user clicks on "MathFlow | MathFlow Help…" from the menu, opens the MathFlow documentation in a browser window.
  • aboutMathFlow: This macro, which is triggered when the user clicks on "MathFlow | About MathFlow…" from the menu, opens the MathFlow About box.

This information is on a separate page.

Overview, font style management

MathFlow allows users to style characters and expressions by requesting particular font faces, weights and slants. While users can specify any font, weight or slant in the underlying MathML markup, what MathFlow actually renders is limited by the availability of fonts on the system. On Windows systems, MathFlow uses two rendering engines, a Java-based engine for the Editor, and a Win32-based engine for preview images and PDF composition. The font and style behavior of both engines is similar, but there are some differences in details as described below.

There are three cases that must be distinguished to understand how MathFlow selects fonts:

Default Rendering

When no explicit style information is specified, the MathFlow rendering engines apply internal algorithms to select fonts. The Java engine firsts attempts to locate characters in a set of preferred system fonts: Times New Roman for alphanumeric characters, Euclid Symbol for common symbol characters, and Code 2000 for rarer symbol characters. Note that Euclid Symbol is included with MathFlow, but Code 2000 must be obtained separately. The choice of preferred system fonts is configurable. See Configuring preferred fonts.

When characters cannot be located in MathFlow's preferred system fonts, the Java engine also contains built-in fonts containing around 500 symbol characters and will use these fonts instead. Characters that cannot be located either in preferred system fonts or internal fonts render as missing glyphs, generally represented by an empty box. In these cases, explicitly specifying a system font known to contain the character is generally the best solution.

The Win32 rendering engine employs a similar, but more complex model. Characters are first sought in a collection of preferred system fonts, primarily Times New Roman, Symbol and MT Extra. For certain classes of characters, Mathematica fonts, Euclid fonts, and/or Adobe's Mathematical Pi fonts may also be utilized. When characters cannot be located in preferred fonts, the rendering engine searches all available system fonts. At this point, there is no control over the order in which fonts are searched, which can lead to unpredictable results. As in the Java case, explicitly specifying a system font known to contain the character is generally the best solution.

Pre-defined MathML Styles

MathML contains twelve pre-defined logical styles, such as "sans-serif" and "script." When one of these styles is selected, both the Java and Win32 engines reformulate these requests in terms of specific fonts. As above, the renderers first look for characters in preferred fonts, and then fall back to either internal fonts or other system fonts, depending on the rendering engine.

User-defined Custom Styles

For user-defined custom styles, both engines will attempt to literally honor the request. If the specified font is not available, an attempt is made to render the character in some font containing the character. If no font can be found, the character is rendered with a missing glyph indicator.

Styles in MathML markup

MathFlow enables the use of user-defined custom styles definitions as described in Customizing font styles. Custom styles are represented in the MathML markup by attributes specifying style names. Here we give more details about how the association between the style name and the actual font being used is managed.

All character data in a MathML expression must be contained in a token element (MI, MO, MN, MTEXT, etc.) The font used to render the character data is determined by the values of the "mathvariant", "class", "fontfamily", "fontweight" and "fontslant" attributes. The last three attributes are deprecated by MathML 3.0 and are not generated by MathFlow (though they are still honored by the MathFlow rendering engine.) The values for any of these attributes may either be set explicitly on token elements, or inherited from a parent element, usually an MSTYLE element.

When several of these attributes are used, MathFlow uses the following precedences in determining which of them controls the font:

  1. Explicit "mathvariant" values
  2. Inherited "mathvariant" values
  3. Explicit "class" values
  4. Inherited "class" values
  5. Explicit "fontfamily" "fontweight" and "fontslant" values
  6. Inherited "fontfamily" "fontweight" and "fontslant" values

Both the "mathvariant" and "class" values are interpreted as specifying all three components of the fonts specification -- family, weight and slant. Thus, the "mathvariant" value "bold" actually specifies a serif font face, in bold weight, with normal (upright) slant.

To illustrate the above precedence rules, consider and example. If we define the style "myArial" to have family="Arial", weight="normal" and slant="automatic", then the following will display the x in an Arial, normal, upright font, and the y in serif, bold, upright (since mathvariant="bold" takes precedence over fontstyle="italic"):

<math>
  <mstyle mathvariant="bold" fontstyle="italic">
    <mi class="myArial">x</mi><mo>+</mo><mi>y</mi>
  </mstyle>
</math>

Whereas this will display the x in a serif, bold, upright font, and the y in Arial, normal, italic:

<math>
  <mstyle class="myArial" fontstyle="italic">
    <mi mathvariant="bold" >x</mi><mo>+</mo><mi>y</mi>
  </mstyle>
</math>

Custom Font Styles

MathFlow stores the custom font styles you have defined in a file, so that it can be reused from session to session. This file can also be edited directly as a more convenient way of defining a large number of styles, to be shared among many users.

The file in question is named .mfstyles and is stored in the same directory as your MathFlow preferences file, usually the following on Windows systems: C:\Users\<username>.

Font style language

The font style definition file has an XML syntax with seven elements:

<styles>

The root element that can contain any number of <style> elements.

<style>

Each <style> element must contain one <label> element and one <fontspec> element. It is an error if either of these is missing or appears more than once.

<label>

The name of the style.

If the inner text of this element matches the value of the class attribute in a MathML element, then that MathML element will be stylized according to the <fontspec> element that is a sibling of this <label>.

<fontspec>

This can contain 0-3 of the following three elements which describe the font characteristics of the style. If any of these elements are omitted, the corresponding font characteristic adopts a default value listed below.

  • <fontfamily> - Accepted values are any legal font family name, or "inherited". Default is "inherited".
  • <fontweight> - Accepted values are "normal", "bold" or "automatic". Default is "automatic".
  • <fontslant> - Accepted values are normal, italic or automatic. Default is "automatic".

For example, the following code defines two font styles named my Arial, my Arial2, and myEmphasis:

<styles>
  <style>
    <label>myArial</label>
    <fontspec>
      <fontfamily>Arial</fontfamily>
      <fontweight>normal</fontweight>
      <fontslant>automatic</fontslant>
    </fontspec>
  </style>
  <style>
    <label>myArial2</label>
    <fontspec>
      <fontfamily>Arial</fontfamily>
      <fontweight>bold</fontweight>
      <fontslant>normal</fontslant>
    </fontspec>
  </style>
  <style>
    <label>myEmphasis</label>
    <fontspec>
      <fontfamily>inherited</fontfamily>
      <fontweight>bold</fontweight>
      <fontslant>italic</fontslant>
    </fontspec>
  </style>
</styles>

The MathFlow Java rendering engine first attempts to render characters using a collection of four preferred system fonts. The specific system fonts to be used may be identified through the use of a configuration file as described below. Internally, MathFlow considers all characters as belonging in one of the following four broad classes:

  • ALPHA_NUMERIC
  • GREEK
  • SYMBOL
  • EXTRA SYMBOL

The SYMBOL class corresponds to characters found in the standard Adobe Symbol encoding. EXTRA SYMBOL is a catch-all for everything else. MathFlow associates the following numerical values with the following four classes of characters:

ALPHA_NUMERIC = 100
SYMBOL = 101
EXTRA_SYMBOL = 102
GREEK = 103

The default font associations are as follows:

100=Times New Roman
101=Euclid Symbol
102=Code2000
103=Euclid Symbol

To modify the font associations that will be used by MathFlow Editor, create a file named "FontMapping.opt" and place it in this folder:

Windows: C:\Users\<username>

Write four lines in the file, one for each character class of the form NNN=<font name>, as shown above. Once you restart MathFlow, these fonts will become the preferred system fonts for character display.

Example

In this example, you need all of the characters that are alpha-numeric to use the system font "Arial." To do this, you will need to change the ALPHA_NUMERIC value (ID is 100 in the FontMapping.opt file) to Arial, rather than Times New Roman as shown above. To accomplish this, use the following FontMapping.opt file:

100=Arial
101=Euclid Symbol
102=Code2000
103=Euclid Symbol

This mapping will cause every character MathFlow identifies as an "alpha numeric" character to be displayed in the specified font. Be aware that if you use the wrong font name in FontMapping.opt, you will not see the correct font. It will use MathFlow's internal font if it can't find the system font listed in the file. It is possible to pick any system font, but be aware that most system fonts do not contain glyphs for non-alphanumeric characters. Euclid Symbol is a high quality font for common symbol characters, and you will generally not need to change it. However, Code 2000 is a lower-quality, shareware font whose main appeal is that it has exceptionally comprehensive coverage of Unicode, and depending on what symbols you need, you may wish to replace it with a higher quality font. The "GREEK" font defaults to Euclid symbol, since it has high-quality Greek characters, but high-quality fonts with Greek characters in other styles are not uncommon. In general, you may need to experiment to make sure that the system fonts that you pick contain the proper glyph for the Unicode characters you plan to use.

Operators have certain properties that are set in an Operator Dictionary, such as the size of the space to the left or right of the operator, how it changes when in display or inline style, how it stretches, etc.

MathFlow sets these properties to sensible values, but in some instances you may want to fine-tune them. To do that, create a file named mfopdict.txt. To specify the path to the operator dictionary for the MathFlow Editor, open the <path-to-xmetal>\Author\StartUp\mathflow.mcr file. Near the top, find this line: if (mfutil != null) {, and somewhere in that section of code (before the close brace), add this code: mfutil.SetOpDictFile("C:\\Program Files\\XMetaL 14.0\\Author\\MathFlow\\auxiliary\\mfopdict.txt");, replacing the path shown with the actual path to XMetaL on your computer. You will need to restart XMetaL before the changes to the operator dictionary take effect.

Note there is a sample mfopdict.txt file located in the <path-to-xmetal>\Author\MathFlow\auxiliary directory.

Format of the configurable operator dictionary

The properties (e.g., spacing) may be different according to the position of the operator in the formula; whether it is in the middle (infix), at the beginning (prefix), or the end (postfix) of an expression. To reflect this, mfopdict.txt should have three tables, each one started by a line with its name: INFIX, PREFIX, or POSTFIX. It is also possible to change the default spacing for all operators (only the spacing, not other properties), by writing a line with an operator name of "default". Values that are not explicitly set for an operator, or not in a "default" line for spacing use MathFlow's internal values.

In brief:

  • Empty lines are ignored.
  • Lines starting with // are considered comments and are ignored.
  • Operators can be more than a single character.
  • There are three keywords: INFIX, PREFIX, and POSTFIX to indicate the beginning of each table. Each one should appear in a line by itself.
  • Each meaningful line is a comma-separated list, in the form opname, lspace, rspace [, largeop=true|false, stretchy=true|false, accent=true|false, moveablelimits=true|false, dsi:linebreakop=true|false, dsi:stretchby=segments|scaling, dsi:scaleratiopct=integer].
    • opname is a character, a MathML entity name, or a numerical reference (#xNNNN for hexadecimal, #NNNN for decimal). For example, comma could be represented by the name "comma", the character ",", or the numerical references #x02C or #44.
    • lspace and rspace are numbers+unit, where the optional unit could be 'u' (1/100 em) or 'em'. The default is 'u'.
    • The other properties should come at the end of the line, and are optional. See the table below for further description of each property.
  • Default spacings for each table can be given by using opname='default'
  • Numerical references start with #, e.g. #x3b1 (hexadecimal reference) or #2271 (decimal reference).
  • Do not include spaces at the ends of the lines.

Example:

////////////////////////////////////////////////
INFIX
////////////////////////////////////////////////
default, 17, 17
minus, 33, 33
plus, 33, 33
sum, 33, 33, moveablelimits=false
////////////////////////////////////////////////
PREFIX
////////////////////////////////////////////////
default, 17, 17
plus, 3em, 5
sum, 33, 33, moveablelimits=false
////////////////////////////////////////////////
POSTFIX
////////////////////////////////////////////////
plus, 5u, 3em
sum, 33, 33, moveablelimits=true

This mfopdict.txt file changes the default spacing of all INFIX and PREFIX operators to 0.17em on both sides, but uses MathFlow's default values for postfix operators. The INFIX minus operator has different spacing (0.33em on both sides), and the same is true for the INFIX plus and sum operators. The INFIX sum operator also has the moveablelimits property set to false. In the prefix table, the PREFIX plus gets a larger left space (3em) and a smaller right space (0.05em). Lastly, the sum operator will have moveablelimits when used as a POSTFIX operator.

The img_attr variable is set to the name of the ‹math› attribute that will hold the name of the temporary preview image file to display. The default value is "altimg" but this can be changed if it is necessary to use a different name. For example, the "other" ‹math› attribute could be used instead.

Make the change by finding and replacing altimg with your attribute of choice in these files:

  • <path-to-xmetal>/Author/Startup/mathflow.mcr
  • <path-to-xmetal>/Author/Display/journalist_math_HTML_Style.xsl
  • <path-to-xmetal>/Author/Rules/journalist_math.ctm

If you're using other Java plug-ins with XMetaL, such as a Java-based content management system, you may find that only one plug-in run at a given time. This is due to the fact that your system can only run one Java virtual machine (JVM) per process. MathFlow includes an out-of-process COM server to avoid conflicts with your other Java plug-ins for XMetaL.

The out-of-process COM server has two minor drawbacks to keep in mind:

  1. The MathFlow Editor will occasionally open behind the XMetaL Editor window, and to find the MathFlow window you have to look for the Editor in the taskbar or Alt+Tab to the window.
  2. After a short time of the MathFlow Editor being open, XMetaL will throw up a "Server is Busy" dialog that does not go away until you close the MathFlow Editor. To avoid this dialog, you'll have to add a line to the <path-to-Author>\xmetal<version>.ini file so that XMetaL gives you 4.66 hours (max time) to close the MathFlow Editor before throwing up the dialog: ole_server_busy_timeout=16777215

To run MathFlow as an out-of-process server, with MathFlow installed

  1. Open a command window and cd into the MathFlow directory where MathFlowXM.DLL lives. By default, for 32-bit Windows, this command would be: cd "C:\Program Files\XMetaL <version>\Author" Likewise, for 64-bit Windows, this command would be: cd "C:\Program Files (x86)\XMetaL <version>\Author"
  2. Unregister it: regsvr32 /u MathFlowXM.dll Just to be safe, it's a good idea to now rename MathFlowXM.dll -- perhaps to MathFlowXM.dll.bak.
  3. Use the cd command to navigate to the MathFlow\resources folder: cd MathFlow\resources
  4. Register MathFlowXM.exe with this command: MathFlowXM.exe -RegServer