protected override Box CreateBoxCore(TexEnvironment environment) { var texFont = environment.MathFont; var style = environment.Style; // Create box for base atom. var baseBox = this.BaseAtom.CreateBox(environment); // Create result box. var resultBox = new HorizontalBox(); var axis = texFont.GetAxisHeight(style); var delta = Math.Max(baseBox.Height - axis, baseBox.Depth + axis); var minHeight = Math.Max((delta / 500) * delimeterFactor, 2 * delta - delimeterShortfall); // Create and add box for left delimeter. if (this.LeftDelimeter != null && this.LeftDelimeter.Name != SymbolAtom.EmptyDelimiterName) { var leftDelimeterBox = DelimiterFactory.CreateBox(this.LeftDelimeter.Name, minHeight, environment); leftDelimeterBox.Source = this.LeftDelimeter.Source; CentreBox(leftDelimeterBox, axis); resultBox.Add(leftDelimeterBox); } // add glueElement between left delimeter and base Atom, unless base Atom is whitespace. if (!(this.BaseAtom is SpaceAtom)) { resultBox.Add(Glue.CreateBox(TexAtomType.Opening, this.BaseAtom.GetLeftType(), environment)); } // add box for base Atom. resultBox.Add(baseBox); // add glueElement between right delimeter and base Atom, unless base Atom is whitespace. if (!(this.BaseAtom is SpaceAtom)) { resultBox.Add(Glue.CreateBox(this.BaseAtom.GetRightType(), TexAtomType.Closing, environment)); } // Create and add box for right delimeter. if (this.RightDelimeter != null && this.RightDelimeter.Name != SymbolAtom.EmptyDelimiterName) { var rightDelimeterBox = DelimiterFactory.CreateBox(this.RightDelimeter.Name, minHeight, environment); rightDelimeterBox.Source = this.RightDelimeter.Source; CentreBox(rightDelimeterBox, axis); resultBox.Add(rightDelimeterBox); } return(resultBox); }
protected override Box CreateBoxCore(TexEnvironment environment) { // Create result box. var resultBox = new HorizontalBox(environment.Foreground, environment.Background); var previousAtom = this.PreviousAtom; // Create and add box for each atom in row. for (int i = 0; i < this.Elements.Count; i++) { var curAtom = new DummyAtom(this.Elements[i]); // Change atom type to Ordinary, if required. var hasNextAtom = i < this.Elements.Count - 1; var nextAtom = hasNextAtom ? (Atom)this.Elements[i + 1] : null; curAtom = ChangeAtomToOrdinary(curAtom, previousAtom, nextAtom); // Check if atom is part of ligature or should be kerned. var kern = 0d; if (hasNextAtom && curAtom.GetRightType() == TexAtomType.Ordinary && curAtom.Atom is CharSymbol cs) { if (nextAtom is CharSymbol ns && ligatureKernChangeSet[(int)nextAtom.GetLeftType()]) { var font = ns.GetStyledFont(environment); var style = environment.Style; curAtom = curAtom.AsTextSymbol(); if (font.SupportsMetrics && cs.IsSupportedByFont(font, style)) { var leftAtomCharFont = curAtom.GetCharFont(font).Value; var rightAtomCharFont = ns.GetCharFont(font).Value; var ligatureCharFont = font.GetLigature(leftAtomCharFont, rightAtomCharFont); if (ligatureCharFont == null) { // Atom should be kerned. kern = font.GetKern(leftAtomCharFont, rightAtomCharFont, style); } else { // Atom is part of ligature. curAtom = DummyAtom.CreateLigature(new FixedCharAtom(null, ligatureCharFont)); i++; } } } } // Create and add glue box, unless atom is first of row or previous/current atom is kern. if (i != 0 && previousAtom != null && !previousAtom.IsKern && !curAtom.IsKern) { resultBox.Add(Glue.CreateBox(previousAtom.GetRightType(), curAtom.GetLeftType(), environment)); } // Create and add box for atom. var curBox = curAtom.WithPreviousAtom(previousAtom).CreateBox(environment); resultBox.Add(curBox); environment.LastFontId = curBox.GetLastFontId(); // Insert kern, if required. if (kern > TexUtilities.FloatPrecision) { resultBox.Add(new StrutBox(0, kern, 0, 0)); } if (!curAtom.IsKern) { previousAtom = curAtom; } } return(resultBox); }