Coloring Mathematical Formulas
The simple way
The easy way to colorize some parts of a mathematical expression is shown in this example:
def formula=LatexMathObject.make(r"$${-b\pm\sqrt{b^2-4ac}\over 2a}$$")
def latexStyle=LatexStyle.make()//Creates a latex style class that holds several "instructions"
latexStyle.setColorToChar("a", "red") //All "a" glyphs should be red
latexStyle.setColorToChar("b", "green")//All "b" glyphs should be green
latexStyle.setColorToChar("c", "blue")//All "c" glyphs should be blue
formula.setLatexStyle(latexStyle)
scene.add(formula)
camera.zoomToAllObjects()
You should obtain something like that:

Easy, right? Well, to get the job done, a lot of internal work had to be done, mostly to correctly identify which LatexShapeobjects correspond to certain LaTeX tokens. When creating the LatexMathObject using the JLaTeXMath library to generate the formula, the parsing capabilities of that library (and a bit of tweaking) are used to properly assign a LatexToken object to each generated LatexShape, that holds useful information to identify and assign colors to it.
This is the simplest use of the coloring capabilities, but there are many more, using the LatexToken class. If you want to get more fine-tuned coloring effects, read the next subsections.
The DSL way
Instead of building LatexStyle, LatexStyleItem and LatexToken objects by hand, you can describe the whole style declaratively with the latexStyle(...) DSL. Each entry in rules is one coloring rule, applied in order (a later rule overrides an earlier one on the glyphs they share). The example above becomes:
def formula = LatexMathObject.make(r"$${-b\pm\sqrt{b^2-4ac}\over 2a}$$")
latexStyle(apply: formula, rules: [
[char: "a", color: "red"],
[char: "b", color: "green"],
[char: "c", color: "blue"],
])
scene.add(formula)
camera.zoomToAllObjects()
The char key is a shortcut that matches a CHAR token with that exact string (exactly like setColorToChar). For anything more precise, use a token spec: a map describing the token to match. For example, to colour X in steel blue and every subscript in gold:
latexStyle(apply: formula, rules: [
[char: "X", color: "steelblue"],
[match: [subscript: true], color: "gold"],
])
A token spec accepts the keys type (char, number, greek_letter, binary_operator, relation, delimiter, operator, sqrt, fraction_bar, named_function, arrow, non_math_char), string (the LaTeX name of the glyph; also available as char), depth (delimiter depth) and boolean flags such as subscript, superscript, numerator, denominator, fromIndex, toIndex, bold. Unset keys act as wildcards.
Besides the current glyph (match / differ), a rule can constrain its neighbours with prev / prevDiffer and next / nextDiffer. Each of them takes a token spec, and a plain String is shorthand for [string: ...]. This is all you need for the matrix row/column example — colour the subscript numbers followed by a comma (row) differently from those preceded by a comma (column):
latexStyle(apply: formula, name: "rowColMatrix", rules: [
[color: "slateblue", match: [type: "number", subscript: true], next: ","],
[color: "coral", match: [type: "number", subscript: true], prev: ","],
])
The optional name parameter registers the built style in the global config, so it can be reused later on any formula with formula.setLatexStyle("rowColMatrix") or latex(text: ..., latexStyle: "rowColMatrix"). Omit apply if you only want to build (and perhaps register) the style without attaching it to a formula yet — latexStyle(...) always returns the LatexStyle object.
Every rule also accepts a full style map (delegated to the styling DSL: thickness, drawColor, fillColor, fillAlpha, ...) or a named style String, instead of (or in addition to) the plain color.
The point-and-click way: the LaTeX Style Editor
If even the DSL feels like too much typing, the gui editor has you covered: the LaTeX Style Editor (Tools -> LaTeX Style Editor..., or Ctrl+Shift+E) lets you build coloring rules visually:
- Pick a formula to preview (the tool detects the LaTeX objects defined in your script).
- Add rules with the dialog controls — "this character gets this color", "everything in a subscript gets that one" — and watch the preview recolor live as you edit.
- When it looks right, press Insert DSL Code: the tool writes the corresponding
latexStyle(...)block into your script.
As with the Transform LaTeX tool, the generated block is round-trippable: place the cursor inside it and reopen the editor to keep tweaking the rules visually. The dialog can also export the style as XML, ready to paste into a config file if you want to reuse it across projects (see the end of this chapter).

The remaining subsections describe the underlying LatexToken / LatexStyleItem classes that this DSL builds on. You rarely need them directly, but they explain exactly what each token spec matches.
A closer look into the LatexToken class
As we have seen, LaTeX formulas are compiled and imported into LatexShape objects, usually one per glyph (in some cases a glyph is composed of more than one LatexShape). If we generate the formulas using the JLaTeXMath library (the default option), additional information about the specific glyph a shape represents is stored in the LatexMathObject. This is done using the LatexParser class, accessible through the getLatexParser() method, which relies heavily on the parsing capabilities of the JLaTeXMath library. Let's have a look at an example that generates a simple and beautiful mathematical formula:
def eulerFormula=LatexMathObject.make(r"$e^{i\pi}+1=0$")
for (int i = 0; i < eulerFormula.getLatexParser().size(); i++) {
LatexToken token = eulerFormula.getLatexParser().get(i)//Gets the i-th identified token
logger.info("Token number "+i + ": " + token)
}
You will see in the log output all the generated tokens:
Token number 0: LatexToken[CHAR, "e"] [delimDepth=0] SEC_NORMAL
Token number 1: LatexToken[CHAR, "i"] [delimDepth=0] SEC_SUPERSCRIPT
Token number 2: LatexToken[GREEK_LETTER, "pi"] [delimDepth=0] SEC_SUPERSCRIPT
Token number 3: LatexToken[BINARY_OPERATOR, "plus"] [delimDepth=0] SEC_NORMAL
Token number 4: LatexToken[NUMBER, "1"] [delimDepth=0] SEC_NORMAL
Token number 5: LatexToken[RELATION, "equals"] [delimDepth=0] SEC_NORMAL
Token number 6: LatexToken[NUMBER, "0"] [delimDepth=0] SEC_NORMAL
There are several useful attributes in the token. The first, the type, accessed through the getType() method, defines what family this glyph belongs to. Currently there are the following types, defined in the LatexTokenType enum:
public enum LatexTokenType {
NONE, //This token will not be assigned never. It is used to always returns false when matching tokens
NON_MATH_CHAR,//Normal, non mathematical text
CHAR,//A char token, mostly a letter
NUMBER, //0-9 digits, including point if used in the decimal context
SYMBOL, //A math symbol
OPERATOR, //A "big" operator like \sum, \int
BINARY_OPERATOR, //A simpler binary operator like +, -, \cap,\cup...
RELATION, // A math relation like =, \geq, \leq, etc.
DELIMITER, //Parenthesis, brackets...of any size
SQRT, // Square (or nth-) root symbol
FRACTION_BAR, //That is, the fraction bar :-)
GREEK_LETTER, //Any greek letter like \pi or \varepsilon
NAMED_FUNCTION, //A named function like \log or \ln
ARROW //An arrow
}
So, we can see the generated formula consists of 2 CHARs, a GREEK_LETTER (\pi), a BINARY_OPERATOR (\plus), etc.
The second LatexToken attribute is the string, accessible through the getString() method, which is basically the LaTeX command which generated the glyph, without the backslashes.
The getDelimiterDepth method returns the "depth" of the glyph in the delimiters, i.e. how many groups of delimiters the glyph is "buried" in. In this case, all glyphs have a delimDepth value of 0, as there are no parentheses or brackets (or any delimiters).
The getSecondaryFlags() method gets some bit flags to add additional classification to the token. Currently these are the various flags:
public static final int SEC_NONE = 0b00000000;//None. A value of 0 should never be matched
public static final int SEC_NORMAL = 0b00000001;//This token is normal style, nothing special about it
public static final int SEC_DELIMITER_NORMAL = 0b00000010;//This token is a delimiter, normal size
public static final int SEC_DELIMITER_BIG1 = 0b00000100;//This token is a delimiter, \big size
public static final int SEC_DELIMITER_BIG2 = 0b00001000;//This token is a delimiter, \Big size
public static final int SEC_DELIMITER_BIG3 = 0b0000100000000000;//This token is a delimiter, \bigg size
public static final int SEC_DELIMITER_BIG4 = 0b0001000000000000;//This token is a delimiter, \Bigg size
public static final int SEC_DELIMITER_EXTENSIBLE = 0b00010000;//This token is a delimiter, extensible size
public static final int SEC_SUPERSCRIPT = 0b00100000;//This token is in a superscript
public static final int SEC_SUBSCRIPT = 0b01000000;//This token is in a subscript
public static final int SEC_FROM_INDEX = 0b10000000;//This token is in the "from" part of an \int, \sum...
public static final int SEC_TO_INDEX = 0b0000000100000000;//This token is in the "to" part of an \int, \sum...
public static final int SEC_NUMERATOR = 0b0000001000000000;//This token is in the numerator part of a fraction
public static final int SEC_DENOMINATOR = 0b0000010000000000;//This token is in the denominator part of a fraction
public static final int SEC_LEFT_ARROW = 0b0010000000000000; //This token is a left arrow
public static final int SEC_RIGHT_ARROW = 0b0100000000000000;//This token is a right arrow
public static final int SEC_LEFTRIGHT_ARROW = 0b1000000000000000;//This token is a leftright arrow
public static final int SEC_BOLD_FONT = 0b10000000000000000;//This token is in bold math
We can use this to fine-tune our coloring in the formula. For example, if you want to color all the subscripts in a formula, you can do this with the following code:
def formula = LatexMathObject.make(r"$$\overline{X}={X_1+X_2+\cdots+X_n\over n}$$")
def latexStyle = LatexStyle.make()//Creates a latex style class that holds several "instructions"
latexStyle.setColorToChar("X", "steelblue") //All "X" glyphs should be steelblue color
def subscriptToken = LatexToken.make();//Generates a LatexToken with all attributes set to null
subscriptToken.activateSecondaryFlag(LatexToken.SEC_SUBSCRIPT)//Any token in a subscript will match this one
def latexStyleItem = LatexStyleItem.make("gold")//This item will apply the color gold to...
latexStyleItem.mustMatchTo(subscriptToken)//Any token that matches the given token
latexStyle.add(latexStyleItem)//Add to the latex style
formula.setLatexStyle(latexStyle)
scene.add(formula)
camera.zoomToAllObjects()
You will get the following colored formula:

Of course, you can use LatexToken objects to select precise Shapes of the LatexMathObject. For example, adding the following lines at the end of the previous code will twist and scale the subscript to draw attention to them:
def subscriptPart = formula.getShapesWith(subscriptToken)//Select all LatexShape objects which match subscriptToken
highlight(type: "twist", obj: subscriptPart.toShapesArray())//Uses to toShapesArray() method to treat each Shape as a separate argument
or, if you already have a LatexStyle object with the token you are interested in:
def subscriptPart = myStyle.getShapesFromRule(formula, 1) //Second token (0-list based, remember!)
highlight(type: "twist", obj: subscriptPart.toShapesArray())
Will generate an animation like this:

A LatexStyle can hold an arbitrary number of LatexStyleItem object, and each of them can use up to 6 LatexToken to compare:
latexStyleItem.mustMatchTo(token)//The token to be colored must match with this
latexStyleItem.mustDifferFrom(token)//The token to be colored must differ from this
latexStyleItem.previousTokenMustMatchTo(token)//The token previous to the one to be colored must match with this
latexStyleItem.previousTokenMustDifferFrom(token)//The token previous to the one to be colored must differ from this
latexStyleItem.nextTokenMustMatchTo(token)//The token after to the one to be colored must match with this
latexStyleItem.nextTokenMustDifferFrom(token)//The token after to the one to be colored must differ from this
It is important to note that "match" or "differ" means to match/differ in all its non-null attributes. That is, if we have a LatexToken object with all its attributes set to null except the string variable, an expression like latexStyleItem.mustDifferFrom(token) will return true for any token with a string different from token.string value, without taking into account the other attributes. Of course a LatexToken with all its attributes set to null will always return true to any match or differs method.
With the next example we can see the flexibility of this method: Suppose we want to show a 3x3 matrix, and assign different colors to row and column indices. Both are numbers in a subscript style. Using the previousTokenMustMatchTo and nextTokenMustMatchTo we can infer if they are the first or second subscript, with a code like this:
def formula =
LatexMathObject.make(r"""$$\left(
\begin{array}{ccc}
a_{1,1} & a_{1,2} & a_{1,3} \\
a_{2,1} & a_{2,2} & a_{2,3} \\
a_{3,1} & a_{3,2} & a_{3,3}
\end{array}
\right)$$""")
scene.add(formula)
//This style will hold 2 latexStyle items,
//one for row and other for colum subscripts
def latexStyle = LatexStyle.make()
//The style for the row subscript: applies to all
//subscript numbers with a comma immediately after
def rowSubscriptStyle = LatexStyleItem.make("slateblue")
rowSubscriptStyle.mustMatchTo(//Must be a number and a subscript
LatexToken.make()
.setType(LatexTokenType.NUMBER)
.activateSecondaryFlag(LatexToken.SEC_SUBSCRIPT)
)
rowSubscriptStyle.nextTokenMustMatchTo(//The next token must be a comma
LatexToken.make()
//The real string name for this token is "comma",
//but jmathanim translates most commons signs to make it easier
.setString(",")
)
//The style for the col subscript: applies to all
//subscript numbers with a comma immediately before
def colSubscriptStyle = LatexStyleItem.make("coral")
colSubscriptStyle.mustMatchTo(//Must be a number and a subscript
LatexToken.make()
.setType(LatexTokenType.NUMBER)
.activateSecondaryFlag(LatexToken.SEC_SUBSCRIPT)
)
colSubscriptStyle.previousTokenMustMatchTo(//The previous token must be a comma
LatexToken.make()
.setString(",")
)
latexStyle.add(rowSubscriptStyle)
latexStyle.add(colSubscriptStyle)
formula.setLatexStyle(latexStyle)
camera.zoomToAllObjects()
It will create a matrix with row and column indices in different colors:

Note that this code will only work if the row and column indices consist of only one digit, because tokens work at a single glyph level. If you want more specialized results, you should write your own method to match tokens. For most purposes, however, the LatexStyle class is sufficient.
Finally, you can store LaTeX coloring styles into config files too. The previous style used can be stored in a config file like follows:
<?xml version="1.0" encoding="UTF-8"?>
<JMathAnimConfig>
<latexStyles>
<latexStyle name="rowColMatrixStyle">
<!--Row subscript-->
<latexStyleItem>
<conditions>
<equals>
<type>NUMBER</type>
<subtype>SEC_SUBSCRIPT</subtype>
</equals>
<equalsAfter>
<!-- <string>,</string> also works-->
<string>comma</string>
</equalsAfter>
</conditions>
<style>
<color>slateblue</color>
</style>
</latexStyleItem>
<!--Column subscript-->
<latexStyleItem>
<conditions>
<equals>
<type>NUMBER</type>
<subtype>SEC_SUBSCRIPT</subtype>
</equals>
<equalsPrev>
<!-- <string>,</string> also works-->
<string>comma</string>
</equalsPrev>
</conditions>
<style>
<color>coral</color>
</style>
</latexStyleItem>
</latexStyle>
</latexStyles>
</JMathAnimConfig>
You can achieve the same effect saving this file under your resources/config directory with a proper name (for example, matrixColor.xml) and the following code:
//You can parse config files with styles
//in the runSketch() method at any time
config.parseFile("matrixColor.xml")
def formula =
LatexMathObject.make(r'''$$\left(
\begin{array}{ccc}
a_{1,1} & a_{1,2} & a_{1,3} \\
a_{2,1} & a_{2,2} & a_{2,3} \\
a_{3,1} & a_{3,2} & a_{3,3}
\end{array}
\right)$$''')
scene.add(formula)
LatexStyle latexStyle = config.getLatexStyles().get("rowColMatrixStyle")
formula.setLatexStyle(latexStyle)
camera.zoomToAllObjects()
The definition of a LatexStleItem in XML format has the following syntax:
<latexStyleItem>
<conditions>
<equals>...</equals> <!-- Optional. Must match the conditions specified inside-->
<equalsPrev>...</equalsPrev> <!-- Optional. Previous token must match the conditions specified inside-->
<equalsAfter>...</equalsAfter> <!-- Optional. Next token must match the conditions specified inside-->
<differs>...</differs> <!-- Optional. Must differ in at least one of the conditions specified inside-->
<differsPrev>...</differsPrev> <!-- Optional. Previous token must differ in at least one of the conditions specified inside-->
<differsAfter>...</differsAfter> <!-- Optional. Next token must differ in at least one of the conditions specified inside-->
</conditions>
<style>...</style> <!-- Style definitions here (see Chapter "Styling") -->
</latexStyleItem>
Each one of the six different condition types may have the following optional items <type>, <subtype>, <string>, <delimiterDepth>.
The <type> element, as its name says, defines the type token. For example the following definition:
<equals>
<type>NUMBER</type>
</equals>
will match any LaTeX token which is a number, and
<differs>
<type>GREEK_LETTER</type>
</differs>
will match any LaTex token which is not a Greek letter.
The element <subtype> will set the flags of the token. For example:
<equals>
<subtype>SEC_NUMERATOR,SEC_SUBSCRIPT</subtype>
</equals>
will match any LaTeX token in a fraction numerator and in a subscript position.
The element
<differs>
<subtype>SEC_FROM_INDEX</subtype>
</differs>
will match any LaTeX token which is not in the "from" position of an operator, like \int or \sum.
The element <string> refers to the LaTeX name this token has. Usually the character ("a") or the command without backslashes ("sqrt", "cdot", etc.). So, for example:
<differs>
<string>x</string>
</differs>
Anything that is not the "x" char (case sensitive) will match this condition.
Finally the element delimiterDepth sets how many delimiters embrace this token. So, for example
<equals>
<delimiterDepth>0</delimiterDepth>
</equals>
will match any token which is not enclosed in any delimiter (parenthesis, brackets, etc.)