protected override Box CreateBoxCore(TexEnvironment environment) { // Create boxes for base, delimeter, and script atoms. var baseBox = this.BaseAtom == null ? StrutBox.Empty : this.BaseAtom.CreateBox(environment); var delimeterBox = DelimiterFactory.CreateBox(this.Symbol.Name, baseBox.Width, environment); var scriptBox = this.Script == null ? null : this.Script.CreateBox(this.Over ? environment.GetSuperscriptStyle() : environment.GetSubscriptStyle()); // Create centered horizontal box if any box is smaller than maximum width. var maxWidth = GetMaxWidth(baseBox, delimeterBox, scriptBox); if (Math.Abs(maxWidth - baseBox.Width) > TexUtilities.FloatPrecision) { baseBox = new HorizontalBox(baseBox, maxWidth, TexAlignment.Center); } if (Math.Abs(maxWidth - delimeterBox.Height - delimeterBox.Depth) > TexUtilities.FloatPrecision) { delimeterBox = new VerticalBox(delimeterBox, maxWidth, TexAlignment.Center); } if (scriptBox != null && Math.Abs(maxWidth - scriptBox.Width) > TexUtilities.FloatPrecision) { scriptBox = new HorizontalBox(scriptBox, maxWidth, TexAlignment.Center); } return(new OverUnderBox(baseBox, delimeterBox, scriptBox, this.Kern.CreateBox(environment).Height, this.Over)); }
public override Box CreateBox(TexEnvironment environment) { var texFont = environment.TexFont; var style = environment.Style; // Create box for base atom. var baseBox = (this.BaseAtom == null ? StrutBox.Empty : this.BaseAtom.CreateBox(environment)); if (this.SubscriptAtom == null && this.SuperscriptAtom == null) { return(baseBox); } // Create result box. var resultBox = new HorizontalBox(baseBox); // Get last font used or default Mu font. int lastFontId = baseBox.GetLastFontId(); if (lastFontId == TexFontUtilities.NoFontId) { lastFontId = texFont.GetMuFontId(); } var subscriptStyle = environment.GetSubscriptStyle(); var superscriptStyle = environment.GetSuperscriptStyle(); // Set delta value and preliminary shift-up and shift-down amounts depending on type of base atom. var delta = 0d; double shiftUp, shiftDown; if (this.BaseAtom is AccentedAtom) { var accentedBox = ((AccentedAtom)this.BaseAtom).BaseAtom.CreateBox(environment.GetCrampedStyle()); shiftUp = accentedBox.Height - texFont.GetSupDrop(superscriptStyle.Style); shiftDown = accentedBox.Depth + texFont.GetSubDrop(subscriptStyle.Style); } else if (this.BaseAtom is SymbolAtom && this.BaseAtom.Type == TexAtomType.BigOperator) { var charInfo = texFont.GetCharInfo(((SymbolAtom)this.BaseAtom).Name, style); if (style < TexStyle.Text && texFont.HasNextLarger(charInfo)) { charInfo = texFont.GetNextLargerCharInfo(charInfo, style); } var charBox = new CharBox(environment, charInfo); charBox.Shift = -(charBox.Height + charBox.Depth) / 2 - environment.TexFont.GetAxisHeight( environment.Style); resultBox = new HorizontalBox(charBox); delta = charInfo.Metrics.Italic; if (delta > TexUtilities.FloatPrecision && this.SubscriptAtom == null) { resultBox.Add(new StrutBox(delta, 0, 0, 0)); } shiftUp = resultBox.Height - texFont.GetSupDrop(superscriptStyle.Style); shiftDown = resultBox.Depth + texFont.GetSubDrop(subscriptStyle.Style); } else if (this.BaseAtom is CharSymbol) { var charFont = ((CharSymbol)this.BaseAtom).GetCharFont(texFont); if (!((CharSymbol)this.BaseAtom).IsTextSymbol || !texFont.HasSpace(charFont.FontId)) { delta = texFont.GetCharInfo(charFont, style).Metrics.Italic; } if (delta > TexUtilities.FloatPrecision && SubscriptAtom == null) { resultBox.Add(new StrutBox(delta, 0, 0, 0)); delta = 0; } shiftUp = 0; shiftDown = 0; } else { shiftUp = baseBox.Height - texFont.GetSupDrop(superscriptStyle.Style); shiftDown = baseBox.Depth + texFont.GetSubDrop(subscriptStyle.Style); } Box superscriptBox = null; Box superscriptContainerBox = null; Box subscriptBox = null; Box subscriptContainerBox = null; if (this.SuperscriptAtom != null) { // Create box for superscript atom. superscriptBox = this.SuperscriptAtom.CreateBox(superscriptStyle); superscriptContainerBox = new HorizontalBox(superscriptBox); // Add box for script space. superscriptContainerBox.Add(scriptSpaceAtom.CreateBox(environment)); // Adjust shift-up amount. double p; if (style == TexStyle.Display) { p = texFont.GetSup1(style); } else if (environment.GetCrampedStyle().Style == style) { p = texFont.GetSup3(style); } else { p = texFont.GetSup2(style); } shiftUp = Math.Max(Math.Max(shiftUp, p), superscriptBox.Depth + Math.Abs(texFont.GetXHeight( style, lastFontId)) / 4); } if (this.SubscriptAtom != null) { // Create box for subscript atom. subscriptBox = this.SubscriptAtom.CreateBox(subscriptStyle); subscriptContainerBox = new HorizontalBox(subscriptBox); // Add box for script space. subscriptContainerBox.Add(scriptSpaceAtom.CreateBox(environment)); } // Check if only superscript is set. if (subscriptBox == null) { superscriptContainerBox.Shift = -shiftUp; resultBox.Add(superscriptContainerBox); return(resultBox); } // Check if only subscript is set. if (superscriptBox == null) { subscriptContainerBox.Shift = Math.Max(Math.Max(shiftDown, texFont.GetSub1(style)), subscriptBox.Height - 4 * Math.Abs(texFont.GetXHeight(style, lastFontId)) / 5); resultBox.Add(subscriptContainerBox); return(resultBox); } // Adjust shift-down amount. shiftDown = Math.Max(shiftDown, texFont.GetSub2(style)); // Reposition both subscript and superscript. double defaultLineThickness = texFont.GetDefaultLineThickness(style); // Space between subscript and superscript. double scriptsInterSpace = shiftUp - superscriptBox.Depth + shiftDown - subscriptBox.Height; if (scriptsInterSpace < 4 * defaultLineThickness) { shiftUp += 4 * defaultLineThickness - scriptsInterSpace; // Position bottom of superscript at least 4/5 of X-height above baseline. double psi = 0.8 * Math.Abs(texFont.GetXHeight(style, lastFontId)) - (shiftUp - superscriptBox.Depth); if (psi > 0) { shiftUp += psi; shiftDown -= psi; } } scriptsInterSpace = shiftUp - superscriptBox.Depth + shiftDown - subscriptBox.Height; // Create box containing both superscript and subscript. var scriptsBox = new VerticalBox(); superscriptContainerBox.Shift = delta; scriptsBox.Add(superscriptContainerBox); scriptsBox.Add(new StrutBox(0, scriptsInterSpace, 0, 0)); scriptsBox.Add(subscriptContainerBox); scriptsBox.Height = shiftUp + superscriptBox.Height; scriptsBox.Depth = shiftDown + subscriptBox.Depth; resultBox.Add(scriptsBox); return(resultBox); }
public override Box CreateBox(TexEnvironment environment) { var texFont = environment.TexFont; var style = environment.Style; // Create box for base atom. var baseBox = (this.BaseAtom == null ? StrutBox.Empty : this.BaseAtom.CreateBox(environment)); if (this.SubscriptAtom == null && this.SuperscriptAtom == null) return baseBox; // Create result box. var resultBox = new HorizontalBox(baseBox); // Get last font used or default Mu font. int lastFontId = baseBox.GetLastFontId(); if (lastFontId == TexFontUtilities.NoFontId) lastFontId = texFont.GetMuFontId(); var subscriptStyle = environment.GetSubscriptStyle(); var superscriptStyle = environment.GetSuperscriptStyle(); // Set delta value and preliminary shift-up and shift-down amounts depending on type of base atom. var delta = 0d; double shiftUp, shiftDown; if (this.BaseAtom is AccentedAtom) { var accentedBox = ((AccentedAtom)this.BaseAtom).BaseAtom.CreateBox(environment.GetCrampedStyle()); shiftUp = accentedBox.Height - texFont.GetSupDrop(superscriptStyle.Style); shiftDown = accentedBox.Depth + texFont.GetSubDrop(subscriptStyle.Style); } else if (this.BaseAtom is SymbolAtom && this.BaseAtom.Type == TexAtomType.BigOperator) { var charInfo = texFont.GetCharInfo(((SymbolAtom)this.BaseAtom).Name, style); if (style < TexStyle.Text && texFont.HasNextLarger(charInfo)) charInfo = texFont.GetNextLargerCharInfo(charInfo, style); var charBox = new CharBox(environment, charInfo); charBox.Shift = -(charBox.Height + charBox.Depth) / 2 - environment.TexFont.GetAxisHeight( environment.Style); resultBox = new HorizontalBox(charBox); delta = charInfo.Metrics.Italic; if (delta > TexUtilities.FloatPrecision && this.SubscriptAtom == null) resultBox.Add(new StrutBox(delta, 0, 0, 0)); shiftUp = resultBox.Height - texFont.GetSupDrop(superscriptStyle.Style); shiftDown = resultBox.Depth + texFont.GetSubDrop(subscriptStyle.Style); } else if (this.BaseAtom is CharSymbol) { var charFont = ((CharSymbol)this.BaseAtom).GetCharFont(texFont); if (!((CharSymbol)this.BaseAtom).IsTextSymbol || !texFont.HasSpace(charFont.FontId)) delta = texFont.GetCharInfo(charFont, style).Metrics.Italic; if (delta > TexUtilities.FloatPrecision && SubscriptAtom == null) { resultBox.Add(new StrutBox(delta, 0, 0, 0)); delta = 0; } shiftUp = 0; shiftDown = 0; } else { shiftUp = baseBox.Height - texFont.GetSupDrop(superscriptStyle.Style); shiftDown = baseBox.Depth + texFont.GetSubDrop(subscriptStyle.Style); } Box superscriptBox = null; Box superscriptContainerBox = null; Box subscriptBox = null; Box subscriptContainerBox = null; if (this.SuperscriptAtom != null) { // Create box for superscript atom. superscriptBox = this.SuperscriptAtom.CreateBox(superscriptStyle); superscriptContainerBox = new HorizontalBox(superscriptBox); // Add box for script space. superscriptContainerBox.Add(scriptSpaceAtom.CreateBox(environment)); // Adjust shift-up amount. double p; if (style == TexStyle.Display) p = texFont.GetSup1(style); else if (environment.GetCrampedStyle().Style == style) p = texFont.GetSup3(style); else p = texFont.GetSup2(style); shiftUp = Math.Max(Math.Max(shiftUp, p), superscriptBox.Depth + Math.Abs(texFont.GetXHeight( style, lastFontId)) / 4); } if (this.SubscriptAtom != null) { // Create box for subscript atom. subscriptBox = this.SubscriptAtom.CreateBox(subscriptStyle); subscriptContainerBox = new HorizontalBox(subscriptBox); // Add box for script space. subscriptContainerBox.Add(scriptSpaceAtom.CreateBox(environment)); } // Check if only superscript is set. if (subscriptBox == null) { superscriptContainerBox.Shift = -shiftUp; resultBox.Add(superscriptContainerBox); return resultBox; } // Check if only subscript is set. if (superscriptBox == null) { subscriptBox.Shift = Math.Max(Math.Max(shiftDown, texFont.GetSub1(style)), subscriptBox.Height - 4 * Math.Abs(texFont.GetXHeight(style, lastFontId)) / 5); resultBox.Add(subscriptContainerBox); return resultBox; } // Adjust shift-down amount. shiftDown = Math.Max(shiftDown, texFont.GetSub2(style)); // Reposition both subscript and superscript. double defaultLineThickness = texFont.GetDefaultLineThickness(style); // Space between subscript and superscript. double scriptsInterSpace = shiftUp - superscriptBox.Depth + shiftDown - subscriptBox.Height; if (scriptsInterSpace < 4 * defaultLineThickness) { shiftUp += 4 * defaultLineThickness - scriptsInterSpace; // Position bottom of superscript at least 4/5 of X-height above baseline. double psi = 0.8 * Math.Abs(texFont.GetXHeight(style, lastFontId)) - (shiftUp - superscriptBox.Depth); if (psi > 0) { shiftUp += psi; shiftDown -= psi; } } scriptsInterSpace = shiftUp - superscriptBox.Depth + shiftDown - subscriptBox.Height; // Create box containing both superscript and subscript. var scriptsBox = new VerticalBox(); superscriptContainerBox.Shift = delta; scriptsBox.Add(superscriptContainerBox); scriptsBox.Add(new StrutBox(0, scriptsInterSpace, 0, 0)); scriptsBox.Add(subscriptContainerBox); scriptsBox.Height = shiftUp + superscriptBox.Height; scriptsBox.Depth = shiftDown + subscriptBox.Depth; resultBox.Add(scriptsBox); return resultBox; }
public override Box CreateBox(TexEnvironment environment) { var texFont = environment.MathFont; var style = environment.Style; if ((this.UseVerticalLimits.HasValue && !UseVerticalLimits.Value) || (!this.UseVerticalLimits.HasValue && style >= TexStyle.Text)) { // Attach atoms for limits as scripts. return(new ScriptsAtom(this.BaseAtom, this.LowerLimitAtom, this.UpperLimitAtom).CreateBox(environment)); } // Create box for base atom. Box baseBox; double delta; if (this.BaseAtom is SymbolAtom && this.BaseAtom.Type == TexAtomType.BigOperator) { // Find character of best scale for operator symbol. var opChar = texFont.GetCharInfo(((SymbolAtom)this.BaseAtom).Name, style); if (style < TexStyle.Text && texFont.HasNextLarger(opChar)) { opChar = texFont.GetNextLargerCharInfo(opChar, style); } var charBox = new CharBox(environment, opChar); charBox.Shift = -(charBox.Height + charBox.Depth) / 2 - environment.MathFont.GetAxisHeight(environment.Style); baseBox = new HorizontalBox(charBox); delta = opChar.Metrics.Italic; if (delta > TexUtilities.FloatPrecision) { baseBox.Add(new StrutBox(delta, 0, 0, 0)); } } else { baseBox = new HorizontalBox(this.BaseAtom == null ? StrutBox.Empty : BaseAtom.CreateBox(environment)); delta = 0; } // Create boxes for upper and lower limits. var upperLimitBox = this.UpperLimitAtom == null ? null : this.UpperLimitAtom.CreateBox( environment.GetSuperscriptStyle()); var lowerLimitBox = this.LowerLimitAtom == null ? null : this.LowerLimitAtom.CreateBox( environment.GetSubscriptStyle()); // Make all component boxes equally wide. var maxWidth = Math.Max(Math.Max(baseBox.Width, upperLimitBox == null ? 0 : upperLimitBox.Width), lowerLimitBox == null ? 0 : lowerLimitBox.Width); if (baseBox != null) { baseBox = ChangeWidth(baseBox, maxWidth); } if (upperLimitBox != null) { upperLimitBox = ChangeWidth(upperLimitBox, maxWidth); } if (lowerLimitBox != null) { lowerLimitBox = ChangeWidth(lowerLimitBox, maxWidth); } var resultBox = new VerticalBox(); var opSpacing5 = texFont.GetBigOpSpacing5(style); var kern = 0d; // Create and add box for upper limit. if (UpperLimitAtom != null) { resultBox.Add(new StrutBox(0, opSpacing5, 0, 0)); upperLimitBox.Shift = delta / 2; resultBox.Add(upperLimitBox); kern = Math.Max(texFont.GetBigOpSpacing1(style), texFont.GetBigOpSpacing3(style) - upperLimitBox.Depth); resultBox.Add(new StrutBox(0, kern, 0, 0)); } // Add box for base atom. resultBox.Add(baseBox); // Create and add box for lower limit. if (LowerLimitAtom != null) { resultBox.Add(new StrutBox(0, Math.Max(texFont.GetBigOpSpacing2(style), texFont.GetBigOpSpacing4(style) - lowerLimitBox.Height), 0, 0)); lowerLimitBox.Shift = -delta / 2; resultBox.Add(lowerLimitBox); resultBox.Add(new StrutBox(0, opSpacing5, 0, 0)); } // Adjust height and depth of result box. var baseBoxHeight = baseBox.Height; var totalHeight = resultBox.Height + resultBox.Depth; if (upperLimitBox != null) { baseBoxHeight += opSpacing5 + kern + upperLimitBox.Height + upperLimitBox.Depth; } resultBox.Height = baseBoxHeight; resultBox.Depth = totalHeight - baseBoxHeight; return(resultBox); }
public override Box CreateBox(TexEnvironment environment) { var texFont = environment.TexFont; var style = environment.Style; if ((this.UseVerticalLimits.HasValue && !UseVerticalLimits.Value) || (!this.UseVerticalLimits.HasValue && style >= TexStyle.Text)) // Attach atoms for limits as scripts. return new ScriptsAtom(this.BaseAtom, this.LowerLimitAtom, this.UpperLimitAtom).CreateBox(environment); // Create box for base atom. Box baseBox; double delta; if (this.BaseAtom is SymbolAtom && this.BaseAtom.Type == TexAtomType.BigOperator) { // Find character of best scale for operator symbol. var opChar = texFont.GetCharInfo(((SymbolAtom)this.BaseAtom).Name, style); if (style < TexStyle.Text && texFont.HasNextLarger(opChar)) opChar = texFont.GetNextLargerCharInfo(opChar, style); var charBox = new CharBox(environment, opChar); charBox.Shift = -(charBox.Height + charBox.Depth) / 2 - environment.TexFont.GetAxisHeight(environment.Style); baseBox = new HorizontalBox(charBox); delta = opChar.Metrics.Italic; if (delta > TexUtilities.FloatPrecision) baseBox.Add(new StrutBox(delta, 0, 0, 0)); } else { baseBox = new HorizontalBox(this.BaseAtom == null ? StrutBox.Empty : BaseAtom.CreateBox(environment)); delta = 0; } // Create boxes for upper and lower limits. var upperLimitBox = this.UpperLimitAtom == null ? null : this.UpperLimitAtom.CreateBox( environment.GetSuperscriptStyle()); var lowerLimitBox = this.LowerLimitAtom == null ? null : this.LowerLimitAtom.CreateBox( environment.GetSubscriptStyle()); // Make all component boxes equally wide. var maxWidth = Math.Max(Math.Max(baseBox.Width, upperLimitBox == null ? 0 : upperLimitBox.Width), lowerLimitBox == null ? 0 : lowerLimitBox.Width); if (baseBox != null) baseBox = ChangeWidth(baseBox, maxWidth); if (upperLimitBox != null) upperLimitBox = ChangeWidth(upperLimitBox, maxWidth); if (lowerLimitBox != null) lowerLimitBox = ChangeWidth(lowerLimitBox, maxWidth); var resultBox = new VerticalBox(); var opSpacing5 = texFont.GetBigOpSpacing5(style); var kern = 0d; // Create and add box for upper limit. if (UpperLimitAtom != null) { resultBox.Add(new StrutBox(0, opSpacing5, 0, 0)); upperLimitBox.Shift = delta / 2; resultBox.Add(upperLimitBox); kern = Math.Max(texFont.GetBigOpSpacing1(style), texFont.GetBigOpSpacing3(style) - upperLimitBox.Depth); resultBox.Add(new StrutBox(0, kern, 0, 0)); } // Add box for base atom. resultBox.Add(baseBox); // Create and add box for lower limit. if (LowerLimitAtom != null) { resultBox.Add(new StrutBox(0, Math.Max(texFont.GetBigOpSpacing2(style), texFont.GetBigOpSpacing4(style) - lowerLimitBox.Height), 0, 0)); lowerLimitBox.Shift = -delta / 2; resultBox.Add(lowerLimitBox); resultBox.Add(new StrutBox(0, opSpacing5, 0, 0)); } // Adjust height and depth of result box. var baseBoxHeight = baseBox.Height; var totalHeight = resultBox.Height + resultBox.Depth; if (upperLimitBox != null) baseBoxHeight += opSpacing5 + kern + upperLimitBox.Height + upperLimitBox.Depth; resultBox.Height = baseBoxHeight; resultBox.Depth = totalHeight - baseBoxHeight; return resultBox; }