public IMathAtom Visit(LargeOperator target, bool finalize) => new LargeOperator(target, finalize);
public static string MathListToString(IMathList mathList) { var builder = new StringBuilder(); var currentFontStyle = FontStyle.Default; foreach (var atom in mathList) { if (currentFontStyle != atom.FontStyle) { if (currentFontStyle != FontStyle.Default) { // close the previous font style builder.Append("}"); } if (atom.FontStyle != FontStyle.Default) { // open a new font style var fontStyleName = atom.FontStyle.FontName(); builder.Append(@"\" + fontStyleName + "{"); } } currentFontStyle = atom.FontStyle; switch (atom.AtomType) { case MathAtomType.Fraction: { IFraction fraction = (IFraction)atom; var numerator = MathListToString(fraction.Numerator); var denominator = MathListToString(fraction.Denominator); if (fraction.HasRule) { builder.Append(@"\frac{" + numerator + "}{" + denominator + "}"); } else { string command = null; if (fraction.LeftDelimiter == null && fraction.RightDelimiter == null) { command = "atop"; } else if (fraction.LeftDelimiter == "(" && fraction.RightDelimiter == ")") { command = "choose"; } else if (fraction.LeftDelimiter == "{" && fraction.RightDelimiter == "}") { command = "brace"; } else if (fraction.LeftDelimiter == "[" && fraction.RightDelimiter == "]") { command = "brack"; } else { command = $"atopwithdelims{fraction.LeftDelimiter}{fraction.RightDelimiter}"; } builder.Append("{" + numerator + @" \" + command + " " + denominator + "}"); } } break; case MathAtomType.Radical: { builder.Append(@"\sqrt"); var radical = (IRadical)atom; if (radical.Degree != null) { builder.Append($"[{MathListToString(radical.Degree)}]"); } builder.Append("{" + MathListToString(radical.Radicand) + "}"); break; } case MathAtomType.Inner: { var inner = (IMathInner)atom; if (inner.LeftBoundary == null && inner.RightBoundary == null) { builder.Append("{" + MathListToString(inner.InnerList) + "}"); } else { if (inner.LeftBoundary == null) { builder.Append(@"\left. "); } else { builder.Append(@"\left" + DelimiterToString(inner.LeftBoundary) + " "); } builder.Append(MathListToString(inner.InnerList)); if (inner.RightBoundary == null) { builder.Append(@"\right. "); } else { builder.Append(@"\right" + DelimiterToString(inner.RightBoundary) + " "); } } break; } case MathAtomType.Table: { var table = (IMathTable)atom; if (table.Environment != null) { builder.Append(@"\begin{" + table.Environment + "}"); } for (int i = 0; i < table.NRows; i++) { var row = table.Cells[i]; for (int j = 0; j < row.Count; j++) { var cell = row[j]; if (table.Environment == "matrix") { if (cell.Count >= 1 && cell[0].AtomType == MathAtomType.Style) { // remove the first atom. var atoms = cell.Atoms.GetRange(1, cell.Count - 1); cell = MathLists.WithAtoms(atoms.ToArray()); } } if (table.Environment == "eqalign" || table.Environment == "aligned" || table.Environment == "split") { if (j == 1 && cell.Count >= 1 && cell[0].AtomType == MathAtomType.Ordinary && string.IsNullOrEmpty(cell[0].Nucleus)) { // empty nucleus added for spacing. Remove it. var atoms = cell.Atoms.GetRange(1, cell.Count - 1); cell = MathLists.WithAtoms(atoms.ToArray()); } } builder.Append(MathListToString(cell)); if (j < row.Count - 1) { builder.Append("&"); } } if (i < table.NRows - 1) { builder.Append(@"\\ "); } } if (table.Environment != null) { builder.Append(@"\end{" + table.Environment + "}"); } break; } case MathAtomType.Overline: { var over = (IOverline)atom; builder.Append(@"\overline{" + MathListToString(over.InnerList) + "}"); break; } case MathAtomType.Underline: { var under = (IUnderline)atom; builder.Append(@"\underline{" + MathListToString(under.InnerList) + "}"); break; } case MathAtomType.Accent: { var accent = (IAccent)atom; var list = accent.InnerList; accent.InnerList = null; //for lookup builder.Append(@"\" + MathAtoms.Commands[(MathAtom)atom] + "{" + MathListToString(list) + "}"); break; } case MathAtomType.LargeOperator: { var op = (LargeOperator)atom; var command = MathAtoms.LatexSymbolNameForAtom(op); LargeOperator originalOperator = (LargeOperator)MathAtoms.ForLatexSymbolName(command); builder.Append($@"\{command} "); if (originalOperator.Limits != op.Limits) { switch (op.Limits) { case true: builder.Append(@"\limits "); break; case false: if (!op.NoLimits) { builder.Append(@"\nolimits "); } break; case null: break; } } break; } case MathAtomType.Space: { var space = (ISpace)atom; var intSpace = (int)space.Length; if (SpaceToCommands.ContainsKey(intSpace) && intSpace == space.Length) { var command = SpaceToCommands[intSpace]; builder.Append(@"\" + command + " "); } else { if (space.IsMu) { builder.Append(@"\mkern" + space.Length.ToString("0.0") + "mu"); } else { builder.Append(@"\kern" + space.Length.ToString("0.0") + "pt"); } } break; } case MathAtomType.Style: { var style = (IStyle)atom; var command = StyleToCommands[style.LineStyle]; builder.Append(@"\" + command + " "); break; } case MathAtomType.Color: { var color = (IColor)atom; builder.Append($@"\color{{{color.ColorString}}}{{{MathListToString(color.InnerList)}}}"); break; } case MathAtomType.Group: builder.AppendInBraces(MathListToString(((Group)atom).InnerList), NullHandling.EmptyContent); break; case MathAtomType.Prime: builder.Append('\'', ((Prime)atom).Length); break; default: { var aNucleus = atom.Nucleus; if (String.IsNullOrEmpty(aNucleus)) { builder.Append(@"{}"); } else if (aNucleus == "\u2236") { builder.Append(":"); } else if (aNucleus == "\u2212") { builder.Append("-"); } else { var command = MathAtoms.LatexSymbolNameForAtom((MathAtom)atom); if (command == null) { if (atom is Extension.I_ExtensionAtom ext) { builder.Append(Extension._MathListDestructor.MathAtomToString(ext)); } else { builder.Append(aNucleus); } } else { builder.Append(@"\" + command + " "); } } break; } } if (atom.Superscript != null) { var scriptString = MathListToString(atom.Superscript); builder.Append(scriptString.Length == 1 ? $"^{scriptString}" : $"^{{{scriptString}}}"); } if (atom.Subscript != null) { var scriptString = MathListToString(atom.Subscript); builder.Append(scriptString.Length == 1 ? $"_{scriptString}" : $"_{{{scriptString}}}"); } } if (currentFontStyle != FontStyle.Default) { builder.Append("}"); } return(builder.ToString()); }