math:mo[not(@t:stretchVertical) or @t:stretchVertical != true()] (in formatting mode) — Formatting an operator.


<xsl:template match="math:mo[not(@t:stretchVertical) or @t:stretchVertical != true()]" mode="formatting">
<xsl:param name="x"/>
<xsl:param name="y"/>
<xsl:param name="baseline" select="0"/>
<xsl:param name="fontName" tunnel="yes"/>
<xsl:param name="scriptlevel" tunnel="yes"/>
<xsl:param name="displayStyle" tunnel="yes"/>
<xsl:param name="mathvariant" tunnel="yes"/>
<xsl:param name="mathcolor" tunnel="yes"/>
<xsl:param name="mathbackground" tunnel="yes"/>
<xsl:param name="thickmathspace" tunnel="yes"/>


It is one of the most complex elements to render. It has a lot of attributes that determine many different ways to display it. The default behaviour of operators is contained in a dictionary called operator dictionary. This dictionary, coming from the specification[1], is implemented in the file operator-dictionary.xml. It has been implemented in XML to make access easier using XPath. Modifications have been done to add useful information for our renderer and to add new characters. Characters Prime and Times have been added to the dictionary to facilitate the rendering of these elements. New attributes have also been added:


If an operator has to stretch, this attributes tells our renderer that it will stretch horizontally.


If an operator has to stretch, this attributes tells our renderer that it will stretch vertically.

These two attributes can be both set to true. In this case, the operator has to stretch vertically and horizontally. None of these operators will be stretched in the current version of pMML2SVG.

The formatting mode for a mo element has two different behaviours. The first one is the normal mode that annotate the tree like the other elements. The second is used to correct the annotation of the tree when the operator has to be stretched vertically.

The specification tells us that such an operator should have the size of the biggest non-stretchy element present in the same row of it. Therefore, when an operator has to be stretched, the bottom and the top Y of this big element have to be known to compute the final size of the stretched operator. When the second mode is called, these two values are retrieved by the following template paramaters: upperY and lowerY. The way these values are computed and how this second template mode is called is explained in detail in the alignChild template.

This template is the normal mode, the correcting mode takes part in another template that is exmplained further.

First of all, all attribute values of the operator are retrieved. To determine the default behaviour of these values, the operator dictionary entries for this operator are retrieved. It is done by using XPath and the document function. This function is used to browse an external file. After that, the best operator dictionary entry is chosen with respect to the number of entries and the form attribute. If there is only one entry, this entry is chosen. If there is more than one entry, a default form attribute has to be computed. The rules to determine it are:

  • If the operator is a member of a row, if there is more than one element in this row (excluding mspace) and if this operator is the first element in the row (excluding mspace), the form attribute is prefix

  • If the operator is a member of a row, if there is more than one element in this row (excluding mspace and if this operator is the last element in the row (excluding mspace), the form attribute is postfix

  • In all other cases, the form attribute is infix.

If there is an entry with this form attribute value, this entry will be chosen. If not, an entry will be chosen with preference to infix form attribute value, then postfix and finally prefix. This choosing rule is implemented in the function chooseEntry.

After choosing an entry, all other attributes will be finally retrieved. The value will be the user's specified one, if it exists, then, the value from the operator dictionary and finally a default value from the specification. The following attribute is retrieved:

lspace, rspace

Determine the space around the operator, respectively, on the left and on the right. Default value is thickmathspace.


Determines if an operator has to be stretched. Default value is false. If this value is true, stretchHorizontal and stretchVertical variables are retrieved from the dictionary, if it is possible. In all other cases, these two last values are set to false. These variables are specific to pMML2SVG renderer.


Determines if the operator will be stretched symmetrically. The default value is true.

maxsize, minsize

Determine, respectively, the maximum and minimum size of an operator. These two attributes are used to control the stretching of the operator. The default value is, respectively, infinity and 1.


Determines if the operator is a large operator such as integral, summation, etc. The default value is false. If displayStyle values, from tunnel, and if largeop are true, then the operator will be rendered with higher font size. Typically, the scriptlevel to render this operator will decrease by one.


Determines if the limit under or above an operator (such as integral, summation, etc.) can be moved and be rendered on the left of the operator instead of under or above. The default value is false. This attribute is not yet used in pMML2SVG.


Determines if an operator must behave like an accent. The default value is false. This attribute is used to correct the vertical position of accent operator such as circumflex accent, etc.

After all attributes have been retrieved, the font size for the box is computed. The font size has to be bigger if the largeop attribute is true. Therefore, the scriptlevel value is decremented by one in this case. Otherwise, the font size is computed normally.

Some operators have to be replaced by similar glyphes to be retrieved in the font metrics. It is the case with the under (and over) brackets.

After that, a correction is computed if the operator is an accent. This correction includes the computation of the height of each glyph part that compose the operator if this last has to be stretched. It is done by retrieving the bouding box of each part of the composed operator. This correction is necessary since the parts that compose an operator have a higher height than the non-composed operator.

The left and right bearings are also computed the same way as in other tokens. They have the same behaviour as in others tokens.

The box size and position is then computed and the computation in pixel of minsize, maxsize, lspace and rspace is done.

Finally, the tree node is annotated with box information, stretchy information (STRETCHY, stretchHorizontal and stretchVertical attributes), minsize and maxsize (in pixel) that will be used when the operator will be corrected to stretch, lspace and rspace (in pixel), EMBELLISH information, style information, SYMMETRIC information that will be used when the operator will be corrected to stretch and a shift value (ACCENTSHIFT) that is used to correct the vertical position of an accent.

The EMBELLISH information is used to know where to add lspace and rspace. The specification tells us what an embellished operator is:

Adjustements have to be done when an embellished operator is computed. For example, if an munder element is an embellished operator, the space determined by lspace and rspace has to be placed around this munder element and not around its first mo child.