public override Box CreateBox(TexEnvironment environment) { var tex_font = environment.TexFont; var style = environment.Style; // Calculate minimum clearance amount. var default_rule_thickness = tex_font.GetDefaultLineThickness(style); var clearance = style < TexStyle.Text ? tex_font.GetXHeight(style, tex_font.GetCharInfo(__SqrtSymbol, style).FontId) : default_rule_thickness; clearance = default_rule_thickness + Math.Abs(clearance) / 4; // Create box for base atom, in cramped style. var base_box = BaseAtom.CreateBox(environment.GetCrampedStyle()); // Create box for radical sign. var total_height = base_box.Height + base_box.Depth; var radical_sign_box = DelimiterFactory.CreateBox(__SqrtSymbol, total_height + clearance + default_rule_thickness, environment); // Add half of excess height to clearance. var delta = radical_sign_box.Depth - (total_height + clearance); clearance += delta / 2; // Create box for square-root containing base box. radical_sign_box.Shift = -(base_box.Height + clearance); var over_bar = new OverBar(base_box, clearance, radical_sign_box.Height) { Shift = -(base_box.Height + clearance + default_rule_thickness) }; var radical_container_box = new HorizontalBox(radical_sign_box); radical_container_box.Add(over_bar); // If atom is simple radical, just return square-root box. if (DegreeAtom is null) { return(radical_container_box); } // Atom is complex radical (nth-root). // Create box for root atom. var root_box = DegreeAtom.CreateBox(environment.GetRootStyle()); var bottom_shift = __Scale * (radical_container_box.Height + radical_container_box.Depth); root_box.Shift = radical_container_box.Depth - root_box.Depth - bottom_shift; // Create result box. var result_box = new HorizontalBox(); // Add box for negative kern. var negative_kern = new SpaceAtom(TexUnit.Mu, -10, 0, 0).CreateBox(environment); var x_pos = root_box.Width + negative_kern.Width; if (x_pos < 0) { result_box.Add(new StrutBox(-x_pos, 0, 0, 0)); } result_box.Add(root_box); result_box.Add(negative_kern); result_box.Add(radical_container_box); return(result_box); }
public override Box CreateBox(TexEnvironment environment) { var texFont = environment.TexFont; var style = environment.Style; // Create box for base atom. var baseBox = (BaseAtom is null ? StrutBox.Empty : BaseAtom.CreateBox(environment)); if (SubscriptAtom is null && SuperscriptAtom is null) { return(baseBox); } // Create result box. var resultBox = new HorizontalBox(baseBox); // Get last font used or default Mu font. var 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 (BaseAtom is AccentedAtom) { var accentedBox = ((AccentedAtom)BaseAtom).BaseAtom.CreateBox(environment.GetCrampedStyle()); shiftUp = accentedBox.Height - texFont.GetSupDrop(superscriptStyle.Style); shiftDown = accentedBox.Depth + texFont.GetSubDrop(subscriptStyle.Style); } else if (BaseAtom is SymbolAtom && BaseAtom.Type == TexAtomType.BigOperator) { var charInfo = texFont.GetCharInfo(((SymbolAtom)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 && SubscriptAtom is 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 (BaseAtom is CharSymbol) { var charFont = ((CharSymbol)BaseAtom).GetCharFont(texFont); if (!((CharSymbol)BaseAtom).IsTextSymbol || !texFont.HasSpace(charFont.FontId)) { delta = texFont.GetCharInfo(charFont, style).Metrics.Italic; } if (delta > TexUtilities.FloatPrecision && SubscriptAtom is 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 (SuperscriptAtom != null) { // Create box for superscript atom. superscriptBox = 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 (SubscriptAtom != null) { // Create box for subscript atom. subscriptBox = 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 is null) { superscriptContainerBox.Shift = -shiftUp; resultBox.Add(superscriptContainerBox); return(resultBox); } // Check if only subscript is set. if (superscriptBox is 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. var defaultLineThickness = texFont.GetDefaultLineThickness(style); // Space between subscript and superscript. var 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. var 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 = BaseAtom is null ? StrutBox.Empty : BaseAtom.CreateBox(environment.GetCrampedStyle()); var skew = 0d; if (BaseAtom is CharSymbol) { skew = texFont.GetSkew(((CharSymbol)BaseAtom).GetCharFont(texFont), style); } // Find character of best scale for accent symbol. var accentChar = texFont.GetCharInfo(AccentAtom.Name, style); while (texFont.HasNextLarger(accentChar)) { var nextLargerChar = texFont.GetNextLargerCharInfo(accentChar, style); if (nextLargerChar.Metrics.Width > baseBox.Width) { break; } accentChar = nextLargerChar; } var resultBox = new VerticalBox(); // Create and add box for accent symbol. Box accentBox; var accentItalicWidth = accentChar.Metrics.Italic; if (accentItalicWidth > TexUtilities.FloatPrecision) { accentBox = new HorizontalBox(new CharBox(environment, accentChar)); accentBox.Add(new StrutBox(accentItalicWidth, 0, 0, 0)); } else { accentBox = new CharBox(environment, accentChar); } resultBox.Add(accentBox); var delta = Math.Min(baseBox.Height, texFont.GetXHeight(style, accentChar.FontId)); resultBox.Add(new StrutBox(0, -delta, 0, 0)); // Centre and add box for base atom. Centre base box and accent box with respect to each other. var boxWidthsDiff = (baseBox.Width - accentBox.Width) / 2; accentBox.Shift = skew + Math.Max(boxWidthsDiff, 0); if (boxWidthsDiff < 0) { baseBox = new HorizontalBox(baseBox, accentBox.Width, TexAlignment.Center); } resultBox.Add(baseBox); // Adjust height and depth of result box. var depth = baseBox.Depth; var totalHeight = resultBox.Height + resultBox.Depth; resultBox.Depth = depth; resultBox.Height = totalHeight - depth; return(resultBox); }