Atom Matrix(string value, ref int position, bool vertical) { MatrixAtom matrixAtom = MatrixAtom.Get(); List <List <Atom> > childs = matrixAtom.Elements; Atom parsedChild = (Parse(ReadGroup( value, ref position, leftGroupChar, rightGroupChar)).ExtractRoot()); childs.Add(ListPool <Atom> .Get()); if (parsedChild == null) { MatrixAtom.Last(childs).Add(SpaceAtom.Get()); } if (parsedChild is RowAtom) { List <Atom> el = ((RowAtom)parsedChild).Elements; if (vertical) { MatrixAtom.ParseMatrixVertical(el, childs); } else { MatrixAtom.ParseMatrix(el, childs); } el.Clear(); ObjPool <RowAtom> .Release((RowAtom)parsedChild); } else { MatrixAtom.Last(childs).Add(parsedChild); } matrixAtom.Elements = childs; return(matrixAtom); }
Box CreateBoxDefault(TexStyle style, Box baseBox) { var factor = TexUtility.SizeFactor(style); var clearance = TEXConfiguration.main.RootMargin * factor; var lineThickness = TEXConfiguration.main.LineThickness * factor; // Create box for radical sign. var totalHeight = baseBox.totalHeight; var radicalSignBox = DelimiterFactory.CreateBox(rootSymbol, totalHeight + clearance + lineThickness, style); // Add some clearance to left and right side baseBox = HorizontalBox.Get(baseBox, baseBox.width + clearance * 2, TexAlignment.Center); // Add half of excess height to clearance. lineThickness = Mathf.Max(radicalSignBox.height, lineThickness); clearance = radicalSignBox.totalHeight - totalHeight - lineThickness * 2; // Create box for square-root containing base box. TexUtility.CentreBox(radicalSignBox, style); var overBar = OverBar.Get(baseBox, clearance, lineThickness); TexUtility.CentreBox(overBar, style); var radicalContainerBox = HorizontalBox.Get(radicalSignBox); radicalContainerBox.Add(overBar); // If atom is simple radical, just return square-root box. if (DegreeAtom == null) { return(radicalContainerBox); } // Atom is complex radical (nth-root). // Create box for root atom. var rootBox = DegreeAtom.CreateBox(TexUtility.GetRootStyle()); var bottomShift = scale * (radicalContainerBox.height + radicalContainerBox.depth); rootBox.shift = radicalContainerBox.depth - rootBox.depth - bottomShift; // Create result box. var resultBox = HorizontalBox.Get(); // Add box for negative kern. var negativeKern = SpaceAtom.Get(-((radicalSignBox.width) / 2f), 0, 0).CreateBox(TexStyle.Display); var xPos = rootBox.width + negativeKern.width; if (xPos < 0) { resultBox.Add(StrutBox.Get(-xPos, 0, 0, 0)); } resultBox.Add(rootBox); resultBox.Add(negativeKern); resultBox.Add(radicalContainerBox); return(resultBox); }
public static AccentedAtom Get(Atom baseAtom, string accentName) { var atom = ObjPool <AccentedAtom> .Get(); atom.BaseAtom = baseAtom ?? SpaceAtom.Get(0, 0, 0); atom.AccentAtom = SymbolAtom.GetAtom(accentName); return(atom); }
public static AccentedAtom Get(Atom baseAtom, Atom accent) { var atom = ObjPool <AccentedAtom> .Get(); atom.BaseAtom = baseAtom ?? SpaceAtom.Get(0, 0, 0); atom.AccentAtom = accent as SymbolAtom; return(atom); }
// the secret sauce begin here public TexFormula Parse(string value) { if (value == null) { return(null); } var formula = ObjPool <TexFormula> .Get(); var position = 0; while (position < value.Length) { char ch = value[position]; if (ch == '\r' || ch == '\0' || ch == '\x200c') { position++; // Skip chars that have zero width length } else if (IsWhiteSpace(ch)) { formula.Add(AttachScripts(formula, value, ref position, SpaceAtom.Get())); position++; } else if (ch == escapeChar) { ProcessEscapeSequence(formula, value, ref position); } else if (ch == leftGroupChar) { formula.Add(AttachScripts(formula, value, ref position, Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)).ExtractRoot())); } else if (ch == rightGroupChar) { position++; } else if (ch == superScriptChar || ch == subScriptChar) { formula.Add(AttachScripts(formula, value, ref position, SpaceAtom.Get(0, TexUtility.spaceHeight, 0))); } else { var scriptsAtom = AttachScripts(formula, value, ref position, ConvertCharacter(value, ref position, ch)); formula.Add(scriptsAtom); } } if (formula.RootAtom == null && formula.AttachedMetaRenderer == null) { formula.Add(SpaceAtom.Get()); // a blank paragraph } return(formula); }
public static AccentedAtom Get(Atom baseAtom, Atom accent) { var atom = ObjPool <AccentedAtom> .Get(); var rootSymbol = accent; atom.AccentAtom = (SymbolAtom)rootSymbol; atom.BaseAtom = baseAtom; if (atom.BaseAtom == null) { atom.BaseAtom = SpaceAtom.Get(0, 0, 0); } return(atom); }
public override Box CreateBox(TexStyle style) { // Create box for base atom. var baseBox = BaseAtom == null ? StrutBox.Empty : BaseAtom.CreateBox(style); // Create boxes for over and under atoms. Box overBox = null, underBox = null; var maxWidth = baseBox.width; if (OverAtom != null) { overBox = OverAtom.CreateBox(OverScriptSmaller ? TexUtility.GetSuperscriptStyle(style) : style); maxWidth = Mathf.Max(maxWidth, overBox.width); } if (UnderAtom != null) { underBox = UnderAtom.CreateBox(UnderScriptSmaller ? TexUtility.GetSubscriptStyle(style) : style); maxWidth = Mathf.Max(maxWidth, underBox.width); } // Create result box. var resultBox = VerticalBox.Get(); // Create and add box for over atom. if (OverAtom != null) { resultBox.Add(ChangeWidth(overBox, maxWidth)); resultBox.Add(TexUtility.GetBox(SpaceAtom.Get(0, OverSpace, 0), style)); } // Add box for base atom. resultBox.Add(ChangeWidth(baseBox, maxWidth)); float totalHeight = resultBox.height + resultBox.depth - baseBox.depth; // Create and add box for under atom. if (UnderAtom != null) { resultBox.Add(TexUtility.GetBox(SpaceAtom.Get(0, UnderSpace, 0), style)); resultBox.Add(ChangeWidth(underBox, maxWidth)); } resultBox.depth = resultBox.height + resultBox.depth - totalHeight; resultBox.height = totalHeight; return(resultBox); }
Atom Table(string value, ref int position, int align, int h, int v, bool vertical) { List <List <Atom> > childs = new List <List <Atom> >(); MatrixAtom matrixAtom = ObjPool <MatrixAtom> .Get(); matrixAtom.horizontalAlign = align; matrixAtom.horizontalLine = h; matrixAtom.verticalLine = v; Atom parsedChild = (Parse(ReadGroup( value, ref position, leftGroupChar, rightGroupChar)).ExtractRoot()); childs.Add(ListPool <Atom> .Get()); if (parsedChild == null) { MatrixAtom.Last(childs).Add(SpaceAtom.Get()); } if (parsedChild is RowAtom) { List <Atom> el = ((RowAtom)parsedChild).Elements; if (!vertical) { MatrixAtom.ParseMatrix(el, childs); } else { MatrixAtom.ParseMatrixVertical(el, childs); } el.Clear(); ObjPool <RowAtom> .Release((RowAtom)parsedChild); } else { MatrixAtom.Last(childs).Add(parsedChild); } matrixAtom.Elements = childs; return(matrixAtom); }
private Atom ProcessCommand(TexFormula formula, string value, ref int position, string command) { SkipWhiteSpace(value, ref position); if (position == value.Length) { return(null); } switch (command) { case "meta": // Command is meta var metaRule = formula.AttachedMetaRenderer; if (metaRule == null) { metaRule = formula.AttachedMetaRenderer = ObjPool <TexMetaRenderer> .Get(); } else { metaRule.Reset(); } string metaPar = null; if (value[position] == leftBracketChar) { metaPar = ReadGroup(value, ref position, leftBracketChar, rightBracketChar); SkipWhiteSpace(value, ref position); metaRule.ParseString(metaPar); } return(null); case "root": case "sqrt": // Command is radical. TexFormula degreeFormula = null; if (value[position] == leftBracketChar) { degreeFormula = Parse(ReadGroup(value, ref position, leftBracketChar, rightBracketChar)); SkipWhiteSpace(value, ref position); } return(Radical.Get(Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)) .GetRoot, degreeFormula == null ? null : degreeFormula.GetRoot)); case "vmatrix": case "matrix": //Command is Matrix MatrixAtom matrixAtom = MatrixAtom.Get(); List <List <Atom> > childs = matrixAtom.Elements; Atom parsedChild = (Parse(ReadGroup( value, ref position, leftGroupChar, rightGroupChar)).GetRoot); childs.Add(ListPool <Atom> .Get()); if (parsedChild == null) { MatrixAtom.Last(childs).Add(SpaceAtom.Get()); } if (parsedChild is RowAtom) { List <Atom> el = ((RowAtom)parsedChild).Elements; if (command == "matrix") { MatrixAtom.ParseMatrix(el, childs); } else { MatrixAtom.ParseMatrixVertical(el, childs); } el.Clear(); ObjPool <RowAtom> .Release((RowAtom)parsedChild); } else { MatrixAtom.Last(childs).Add(parsedChild); } matrixAtom.Elements = childs; return(matrixAtom); case "math": case "text": var idx = TexUtility.RawRenderFont < 0 ? TEXConfiguration.main.Typeface_Text : -2; var style = TexUtility.RenderFontStyle; if (value[position] == leftBracketChar) { var str = ReadGroup(value, ref position, leftBracketChar, rightBracketChar); if (!int.TryParse(str, out idx)) { idx = TexUtility.RawRenderFont < 0 ? TEXConfiguration.main.Typeface_Text : -2; style = ParseFontStyle(str); } SkipWhiteSpace(value, ref position); } else if (command == "math") { idx = -1; } var oldType = TexUtility.RenderFont; var oldStyle = TexUtility.RenderFontStyle; TexUtility.RenderFont = idx; TexUtility.RenderFontStyle = style; var parsed = Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)).GetRoot; TexUtility.RenderFont = oldType; TexUtility.RenderFontStyle = oldStyle; return(parsed); case "clr": case "mclr": case "color": // Command is color string clr = null; if (value[position] == leftBracketChar) { clr = ReadGroup(value, ref position, leftBracketChar, rightBracketChar); SkipWhiteSpace(value, ref position); } if (position == value.Length) { return(null); } AttrColorAtom endColor; var startColor = AttrColorAtom.Get(clr, command == "color" ? 1 : (command == "clr" ? 0 : 2), out endColor); return(InsertAttribute(Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)).GetRoot, startColor, endColor)); case "bg": case "vbg": if (value[position] == leftBracketChar) { clr = ReadGroup(value, ref position, leftBracketChar, rightBracketChar); SkipWhiteSpace(value, ref position); } else { clr = null; } return(AttrBgAtom.Get(Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)) .GetRoot, clr, command == "bg")); case "size": // Command is size string sz = null; if (value[position] == leftBracketChar) { sz = ReadGroup(value, ref position, leftBracketChar, rightBracketChar); SkipWhiteSpace(value, ref position); } if (position == value.Length) { return(null); } return(AttrSizeAtom.Get(Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)) .GetRoot, sz)); case "link": case "ulink": // Command is Link string meta = null; if (value[position] == leftBracketChar) { meta = ReadGroup(value, ref position, leftBracketChar, rightBracketChar); SkipWhiteSpace(value, ref position); } if (position == value.Length) { return(null); } string groupBrack = ReadGroup(value, ref position, leftGroupChar, rightGroupChar); if (meta == null) { meta = groupBrack; } return(AttrLinkAtom.Get(Parse(groupBrack).GetRoot, meta, command == "ulink")); case "under": command = "anot"; break; case "over": command = "bnot"; break; } if (command.Length > 2 && command.Substring(command.Length - 3) == "not") { int NotMode = 0; bool UseMargin = true; string prefix = command.Substring(0, command.Length - 3); if (prefix.Length > 0) { switch (prefix[0]) { case 'n': NotMode = 1; break; case 'h': NotMode = 2; break; case 'd': NotMode = 3; break; case 'u': NotMode = 4; break; case 'o': NotMode = 5; break; case 'v': if (prefix.Length > 1 && prefix[1] == 'n') { NotMode = 7; } else { NotMode = 6; } break; case 'a': NotMode = 4; UseMargin = false; break; case 'b': NotMode = 5; UseMargin = false; break; } } if (position == value.Length) { return(null); } string sz = null; if (value[position] == leftBracketChar) { sz = ReadGroup(value, ref position, leftBracketChar, rightBracketChar); SkipWhiteSpace(value, ref position); } return(NegateAtom.Get(Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)) .GetRoot, NotMode, sz, UseMargin)); } if (command.Length > 2 && command.Substring(command.Length - 3) == "trs") { int PivotMode = 0; string prefix = command.Substring(0, command.Length - 3); if (prefix.Length > 0) { switch (prefix[0]) { case 'm': PivotMode = 1; break; case 'l': PivotMode = 2; break; } } if (position == value.Length) { return(null); } string trs = null; if (value[position] == leftBracketChar) { trs = ReadGroup(value, ref position, leftBracketChar, rightBracketChar); SkipWhiteSpace(value, ref position); } AttrTransformationAtom endTRS; var startTRS = AttrTransformationAtom.Get(trs, PivotMode, out endTRS); return(InsertAttribute(Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)).GetRoot, startTRS, endTRS)); } if (command.Length > 3 && command.Substring(command.Length - 4) == "frac") { int FracAlignT = 0, FracAlignB = 0; bool FracAlignN = true; string prefix = command.Substring(0, command.Length - 4); if (prefix.Length > 0) { if (prefix[0] == 'n') { FracAlignN = false; prefix = prefix.Substring(1); } if (prefix.Length == 1) { FracAlignT = fracP(prefix[0]); FracAlignB = FracAlignT; } else if (prefix.Length == 2) { FracAlignT = fracP(prefix[0]); FracAlignB = fracP(prefix[1]); } } if (position == value.Length) { return(null); } Atom numeratorFormula = null, denominatorFormula = null; numeratorFormula = Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)).GetRoot; SkipWhiteSpace(value, ref position); if (position != value.Length) { denominatorFormula = Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)).GetRoot; } return(FractionAtom.Get(numeratorFormula, denominatorFormula, FracAlignN, (TexAlignment)FracAlignT, (TexAlignment)FracAlignB)); } if (command.Length > 3 && command.Substring(command.Length - 4) == "hold") { TexAlignment align = TexAlignment.Center; bool isVertical = false; string prefix = command.Substring(0, command.Length - 3); if (prefix.Length > 0) { switch (prefix[0]) { case 'v': isVertical = true; break; case 'l': align = TexAlignment.Left; break; case 'r': align = TexAlignment.Right; break; case 'b': align = TexAlignment.Bottom; goto case 'v'; case 't': align = TexAlignment.Top; goto case 'v'; } } Vector2 sz = Vector2.zero; if (position < value.Length && value[position] == leftBracketChar) { var frag = ReadGroup(value, ref position, leftBracketChar, rightBracketChar); int idx = frag.IndexOf(','); if (idx >= 0) { var fragL = frag.Substring(0, idx); var fragR = frag.Substring(idx + 1); float.TryParse(fragL, out sz.x); float.TryParse(fragR, out sz.y); } else { if (isVertical) { float.TryParse(frag, out sz.y); } else { float.TryParse(frag, out sz.x); } } SkipWhiteSpace(value, ref position); } if (position < value.Length && value[position] == leftGroupChar) { return(HolderAtom.Get(Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)) .GetRoot, sz.x, sz.y, align)); } else { return(HolderAtom.Get(null, sz.x, sz.y, align)); } } if (command.Length > 4 && command.Substring(command.Length - 5) == "table") { bool vertical = false; int align = 1 + 8 + 64; string prefix = command.Substring(0, command.Length - 5); if (prefix.Length > 0) { if (prefix[0] == 'v') { vertical = true; prefix = prefix.Substring(1); } if (prefix.Length == 1) { var pref = fracP(prefix[0]); align = Math.Max(1, pref * 2) + Math.Max(8, pref * 16) + Math.Max(64, pref * 128); } else if (prefix.Length == 3) { var pref0 = fracP(prefix[0]); var pref1 = fracP(prefix[1]); var pref2 = fracP(prefix[2]); align = Math.Max(1, pref0 * 2) + Math.Max(8, pref1 * 16) + Math.Max(64, pref2 * 128); } } int lineStyleH = 0, lineStyleV = 0; if (value[position] == leftBracketChar) { string lineOpt; int lineP = 0; lineOpt = ReadGroup(value, ref position, leftBracketChar, rightBracketChar); for (int i = 0; i < lineOpt.Length; i++) { if (!int.TryParse(lineOpt[i].ToString(), out lineP)) { continue; } if (i >= 6) { break; } switch (i) { case 0: lineStyleH += lineP >= 2 ? 17 : lineP; break; case 1: lineStyleH += lineP >= 2 ? 10 : (lineP == 1 ? 2 : 0); break; case 2: lineStyleH += lineP >= 1 ? 4 : 0; break; case 3: lineStyleV += lineP >= 2 ? 17 : lineP; break; case 4: lineStyleV += lineP >= 2 ? 10 : (lineP == 1 ? 2 : 0); break; case 5: lineStyleV += lineP >= 1 ? 4 : 0; break; } } SkipWhiteSpace(value, ref position); } else { lineStyleH = 7; lineStyleV = 7; } List <List <Atom> > childs = new List <List <Atom> >(); MatrixAtom matrixAtom = ObjPool <MatrixAtom> .Get(); matrixAtom.horizontalAlign = align; matrixAtom.horizontalLine = lineStyleH; matrixAtom.verticalLine = lineStyleV; Atom parsedChild = (Parse(ReadGroup( value, ref position, leftGroupChar, rightGroupChar)).GetRoot); childs.Add(ListPool <Atom> .Get()); if (parsedChild == null) { MatrixAtom.Last(childs).Add(SpaceAtom.Get()); } if (parsedChild is RowAtom) { List <Atom> el = ((RowAtom)parsedChild).Elements; if (!vertical) { MatrixAtom.ParseMatrix(el, childs); } else { MatrixAtom.ParseMatrixVertical(el, childs); } el.Clear(); ObjPool <RowAtom> .Release((RowAtom)parsedChild); } else { MatrixAtom.Last(childs).Add(parsedChild); } matrixAtom.Elements = childs; return(matrixAtom); } throw new TexParseException("Invalid command."); }