public override Box CreateBox() { var result = HorizontalBox.Get(); var margin = TEXConfiguration.main.BackdropMargin * TexContext.Scale * 2; var box = baseAtom.CreateBox(); if (this.margin) { box = VerticalBox.Get(HorizontalBox.Get(box, box.width + margin, TexAlignment.Center), box.totalHeight + margin, TexAlignment.Center); } var bg = HorizontalRule.Get(box.height, box.width, 0, box.depth, true); if (color != Color.clear) { result.Add(AttrColorBox.Get(0, color)); } result.Add(bg); if (color != Color.clear) { result.Add(AttrColorBox.Get(3, color)); } result.Add(StrutBox.Get(-box.width, 0, 0, 0)); result.Add(box); return(result); }
Box CreateGenericRadicalBox(Box baseBox, string genericSymbol) { float clearance; var lineThickness = TEXConfiguration.main.LineThickness * TexContext.Scale; clearance = lineThickness; // Create box for radical sign. var totalHeight = baseBox.totalHeight; var radicalSignBox = DelimiterFactory.CreateBox(genericSymbol, totalHeight + clearance + lineThickness); // 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); var overBar = OverBar.Get(baseBox, clearance, lineThickness); var expansion = radicalSignBox.width - CustomizedGenericDelimOffset(genericSymbol, radicalSignBox.totalHeight) * radicalSignBox.width; overBar.children[0].width += expansion; overBar.children[0].shift -= expansion; TexUtility.CentreBox(overBar); var radicalContainerBox = HorizontalBox.Get(radicalSignBox); radicalContainerBox.Add(overBar); // There is no generic root then ... return(radicalContainerBox); }
public override Box CreateBox(TexStyle style) { // Create result box. var resultBox = HorizontalBox.Get(); Atom curAtom = null, prevAtom = null; var resultPos = 0; // Create and add box for each atom in row. for (int i = 0; i < Elements.Count; i++) { curAtom = (Elements[i]); // Create and add glue box, unless atom is first of row or previous/current atom is spaces. if (prevAtom != null && !(prevAtom is SpaceAtom) && !(curAtom is SpaceAtom)) { Box spaceBox = SpaceAtom.CreateGlueBox(prevAtom.GetRightType(), curAtom.GetLeftType(), style); if (spaceBox != null) { resultBox.Add(spaceBox); resultPos++; } } // Create and add box for atom. GenerateDelimiterBox(resultBox, ref i, ref resultPos, style); //resultBox.Add(curBox); prevAtom = curAtom; } return(resultBox); }
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 void AddRange(HorizontalBox box) { var ch = box.children; for (int i = 0; i < ch.Count; i++) { Add(ch[i]); } }
public void AddRange(HorizontalBox box, int position) { var ch = box.children; for (int i = 0; i < ch.Count; i++) { Add(position++, ch[i]); } }
private static Box ChangeWidth(Box box, float maxWidth) { if (box != null && Mathf.Abs(maxWidth - box.width) > TexUtility.FloatPrecision) { return(HorizontalBox.Get(box, maxWidth, TexAlignment.Center)); } else { return(box); } }
private static Box ChangeWidth(Box box, float maxWidth) { // Centre specified box in new box of specified width, if necessary. if (Mathf.Abs(maxWidth - box.width) > TexUtility.FloatPrecision) { return(HorizontalBox.Get(box, maxWidth, TexAlignment.Center)); } else { return(box); } }
public override Box CreateBox(TexStyle style) { // Create box for base atom. var baseBox = BaseAtom == null ? StrutBox.Empty : BaseAtom.CreateBox(TexUtility.GetCrampedStyle(style)); // Find character of best scale for accent symbol. TexCharMetric accentChar = TEXPreference.main.GetCharMetric(AccentAtom.Name, style); while (accentChar.ch.nextLargerExist) { var nextLargerChar = TEXPreference.main.GetCharMetric(accentChar.ch.nextLarger, style); if (nextLargerChar.width > baseBox.width) { break; } accentChar = nextLargerChar; } var resultBox = VerticalBox.Get(); // Create and add box for accent symbol. var accentBox = CharBox.Get(style, accentChar); var accentWidth = (accentBox.bearing + accentBox.italic) * .5f; accentBox.italic = accentWidth + (accentBox.width * .5f); accentBox.bearing = accentWidth - (accentBox.width * .5f); //accentBox. = accentBox.width + accentBox.italic - accentBox.bearing; resultBox.Add((accentBox)); //var delta = Mathf.Min(-accentChar.depth, baseBox.height); resultBox.Add(StrutBox.Get(0, TEXConfiguration.main.AccentMargin * TexUtility.SizeFactor(style), 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) / 2f; accentBox.shift = Mathf.Max(boxWidthsDiff, 0); if (boxWidthsDiff < 0) { baseBox = HorizontalBox.Get(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); }
public void Flush() { if (Box != null) { Box.Flush(); Box = null; } partOfPreviousLine = 0; if (metaRules != null) { //metaRules.Flush(); metaRules = null; } ObjPool <TexRenderer> .Release(this); }
public override Box CreateBox() { // Create box for base atom. TexContext.Environment.Push(TexUtility.GetCrampedStyle()); var baseBox = BaseAtom == null ? StrutBox.Empty : BaseAtom.CreateBox(); TexContext.Environment.Pop(); // Find character of best scale for accent symbol. var acct = TEXPreference.main.GetChar(AccentAtom.Name).GetMetric(); while (acct.width < baseBox.width && acct.ch.nextLargerExist) { acct.Flush(); acct = acct.ch.nextLarger.GetMetric(); } var resultBox = VerticalBox.Get(); // Create and add box for accent symbol. var accentWidth = (acct.bearing + acct.italic) * .5f; acct.italic = accentWidth + (acct.width * .5f); acct.bearing = accentWidth - (acct.width * .5f); resultBox.Add(acct); resultBox.Add(StrutBox.Get(0, TEXConfiguration.main.AccentMargin * TexContext.Scale, 0, 0)); // Centre and add box for base atom. Centre base box and accent box with respect to each other. var boxWidthsDiff = (baseBox.width - acct.width) / 2f; acct.shift = Mathf.Max(boxWidthsDiff, 0); if (boxWidthsDiff < 0) { baseBox = HorizontalBox.Get(baseBox, acct.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); }
public override Box CreateBox() { // radius will be implemented later var margin = this.margin ? TEXConfiguration.main.BackdropMargin * TexContext.Scale : 0; var box = baseAtom.CreateBox(); var hbox = HorizontalBox.Get(box, box.width + margin * 2, TexAlignment.Center); if (thickness.x > 0) { var rule = HorizontalRule.Get(hbox.height, thickness.x, 0, hbox.depth); hbox.Add(0, rule); rule.Set(rule.width, rule.height + margin + thickness.w, rule.depth + margin + thickness.y, 0); } if (thickness.z > 0) { var rule = HorizontalRule.Get(hbox.height, thickness.z, 0, hbox.depth); hbox.Add(rule); rule.Set(rule.width, rule.height + margin + thickness.w, rule.depth + margin + thickness.y, 0); } var vbox = VerticalBox.Get(hbox, hbox.totalHeight + margin * 2, TexAlignment.Center); if (thickness.y > 0) { vbox.Add(HorizontalRule.Get(thickness.y, vbox.width, 0)); } if (thickness.w > 0) { vbox.Add(0, HorizontalRule.Get(thickness.w, vbox.width, 0)); } if (color != Color.clear) { vbox.Add(0, AttrColorBox.Get(0, color)); vbox.Add(AttrColorBox.Get(3, color)); } // readjust vbox.height = box.height + margin + thickness.w; vbox.depth = box.depth + margin + thickness.y; return(vbox); }
public TexRenderer GetRenderer() { // For compactness: // Scale isn't saved, but stored in TexUtility.RenderSizeFactor (and normalized) // The actual scaling (param above) is just saved in here, not on each boxes. // Color isn't saved, but stored in TexUtility.RenderColor or as a box of AttrColorBox (for \color). // FontIndex & FontStyle isn't saved, but stored in TexUtility.RenderFont & TexUtility.Style try { var box = CreateBox(); return(TexRenderer.Get(box as HorizontalBox ?? HorizontalBox.Get(box), AttachedMetaRenderer)); } catch (Exception e) { throw e; } }
public static TexRenderer Get(Box box, float scale, TexMetaRenderer meta) { var renderer = ObjPool <TexRenderer> .Get(); renderer.Box = box; renderer.Scale = scale; renderer.metaRules = meta; // There's an additional step if meta 'line' are declared if (renderer.usingMetaRules && renderer.metaRules.line != 0 && box.totalHeight > 0) { if (!(box is HorizontalBox)) { renderer.Box = box = HorizontalBox.Get(box); } box.height = renderer.metaRules.line; box.depth = 0; } return(renderer); }
public override Box CreateBox() { var width = size.x; var height = size.y; Box result; if (BaseAtom == null) { result = StrutBox.Get(width, height, 0, 0); } else if (BaseAtom is SpaceAtom) { result = StrutBox.Get(width, height, 0, 0); } else if (width == 0 && BaseAtom is SymbolAtom) { result = VerticalBox.Get(DelimiterFactory.CreateBox(((SymbolAtom)BaseAtom).Name, height), height, align); } else if (height == 0 && BaseAtom is SymbolAtom) { result = HorizontalBox.Get(DelimiterFactory.CreateBoxHorizontal(((SymbolAtom)BaseAtom).Name, width), width, align); } else if (width == 0) { result = VerticalBox.Get(BaseAtom.CreateBox(), height, align); } else if (height == 0) { result = HorizontalBox.Get(BaseAtom.CreateBox(), width, align); } else { result = VerticalBox.Get(HorizontalBox.Get(BaseAtom.CreateBox(), width, align), height, align); } if (size.x + size.y > 1e-3f) { TexUtility.CentreBox(result); } return(result); }
public override Box CreateBox(TexStyle style) { var result = HorizontalBox.Get(); var margin = TEXConfiguration.main.BackdropMargin * TexUtility.SizeFactor(style); var box = baseAtom.CreateBox(style); box = VerticalBox.Get(HorizontalBox.Get(box, box.width + (horizontalMargin ? margin * 2 : 0), TexAlignment.Center), box.totalHeight + margin * 2, TexAlignment.Center); var endColor = AttrColorBox.Get(0, color, null); var startColor = AttrColorBox.Get(0, color, endColor); var bg = HorizontalRule.Get(box.height, box.width, 0, box.depth, true); result.Add(startColor); result.Add(bg); result.Add(endColor); result.Add(StrutBox.Get(-box.width, 0, 0, 0)); result.Add(box); return(result); }
public static TexRenderer Get(HorizontalBox box, TexMetaRenderer meta, int isPartOfPrev = 0) { var renderer = ObjPool <TexRenderer> .Get(); renderer.Box = box; //renderer.Scale = scale; renderer.metaRules = meta; renderer.partOfPreviousLine = isPartOfPrev; // must horizontal box to avoid headache if (!(box is HorizontalBox)) { renderer.Box = box = HorizontalBox.Get(box); } // There's an additional step if meta 'line' are declared if (renderer.usingMetaRules && renderer.metaRules.line != 0 && box.totalHeight > 0) { box.height = renderer.metaRules.line; box.depth = TexUtility.spaceLine; } return(renderer); }
public override Box CreateBox() { // Create box for base atom. // Save it shift and use it later // Create result box. // Set delta value and preliminary shift-up and shift-down amounts depending on type of base atom. float shiftUp = 0, shiftDown = 0; Box baseBox; HorizontalBox resultBox; if (SubscriptAtom == null && SuperscriptAtom == null) { return(BaseAtom == null ? StrutBox.Empty : BaseAtom.CreateBox()); } if (BaseAtom is AccentedAtom) { TexContext.Environment.Push(TexUtility.GetCrampedStyle()); baseBox = ((AccentedAtom)BaseAtom).BaseAtom.CreateBox(); TexContext.Environment.Pop(); } else { baseBox = (BaseAtom == null ? StrutBox.Empty : BaseAtom.CreateBox()); //if (BaseAtom is CharSymbol) //{ // var delta = 0f; // var ch = ((CharSymbol)BaseAtom).GetChar(); // if (!((CharSymbol)BaseAtom).IsTextSymbol) // delta = ch.italix + bearing - width; // if (delta > TexUtility.FloatPrecision && SubscriptAtom == null) // { // resultBox.Add(StrutBox.Get(delta, 0, 0, 0)); // delta = 0; // } //} } resultBox = HorizontalBox.Get(baseBox); var shift = baseBox.shift; Box superscriptBox = null; HorizontalBox superscriptContainerBox = null; Box subscriptBox = null; HorizontalBox subscriptContainerBox = null; TexContext.Environment.Push(TexUtility.GetSuperscriptStyle()); shiftUp = baseBox.height - TEXConfiguration.main.SupDrop * TexContext.Scale; if (SuperscriptAtom != null) { // Create box for superscript atom. superscriptBox = SuperscriptAtom.CreateBox(); superscriptContainerBox = HorizontalBox.Get(superscriptBox); // Add box for script space. superscriptContainerBox.Add(scriptSpaceAtom.CreateBox()); // Adjust shift-up amount. float p; if (TexContext.Environment.value == TexEnvironment.Display) { p = TEXConfiguration.main.SupMin * TexContext.Scale; } else { p = TEXConfiguration.main.SupMinNarrow * TexContext.Scale; } shiftUp = Mathf.Max(shiftUp, p); } TexContext.Environment.Pop(); TexContext.Environment.Push(TexUtility.GetSubscriptStyle()); shiftDown = baseBox.depth + TEXConfiguration.main.SubDrop * TexContext.Scale; if (SubscriptAtom != null) { // Create box for subscript atom. subscriptBox = SubscriptAtom.CreateBox(); subscriptContainerBox = HorizontalBox.Get(subscriptBox); // Add box for script space. subscriptContainerBox.Add(scriptSpaceAtom.CreateBox()); } TexContext.Environment.Pop(); // Check if only superscript is set. if (subscriptBox == null) { superscriptContainerBox.shift = -shiftUp; resultBox.Add(superscriptContainerBox); resultBox.height = shiftUp + superscriptBox.height; return(resultBox); } // Check if only subscript is set. if (superscriptBox == null) { subscriptBox.shift = Mathf.Max(shiftDown, TEXConfiguration.main.SubMinNoSup * TexContext.Scale); resultBox.Add(subscriptContainerBox); resultBox.depth = shiftDown + subscriptBox.depth; return(resultBox); } // Adjust shift-down amount. shiftDown = Mathf.Max(shiftDown, TEXConfiguration.main.SubMinOnSup * TexContext.Scale); // Space between subscript and superscript. float scriptsInterSpace = shiftUp - superscriptBox.depth + shiftDown - subscriptBox.height; scriptsInterSpace = shiftUp - superscriptBox.depth + shiftDown - subscriptBox.height; // If baseAtom is null, make it right-aligned if (BaseAtom is SpaceAtom && ((SpaceAtom)BaseAtom).policy == StrutPolicy.Misc) { var max = Mathf.Max(superscriptContainerBox.width, subscriptContainerBox.width); if (superscriptContainerBox.width < max) { superscriptContainerBox.Add(0, StrutBox.Get(max - superscriptContainerBox.width, 0, 0, 0)); } if (subscriptContainerBox.width < max) { subscriptContainerBox.Add(0, StrutBox.Get(max - subscriptContainerBox.width, 0, 0, 0)); } } // Create box containing both superscript and subscript. var scriptsBox = VerticalBox.Get(); scriptsBox.Add(superscriptContainerBox); scriptsBox.Add(StrutBox.Get(0, scriptsInterSpace, 0, 0)); scriptsBox.Add(subscriptContainerBox); scriptsBox.height = shiftUp + superscriptBox.height; scriptsBox.depth = shiftDown + subscriptBox.depth; scriptsBox.shift = shift; resultBox.Add(scriptsBox); return(resultBox); }
public override Box CreateBox(TexStyle style) { float lineHeight = lineThickness * TexUtility.SizeFactor(style); // Create boxes for numerator and demoninator atoms, and make them of equal width. var numeratorBox = numerator == null ? StrutBox.Empty : numerator.CreateBox(TexUtility.GetNumeratorStyle(style)); var denominatorBox = denominator == null ? StrutBox.Empty : denominator.CreateBox(TexUtility.GetDenominatorStyle(style)); float maxWidth = (numeratorBox.width < denominatorBox.width ? denominatorBox.width : numeratorBox.width) + TEXConfiguration.main.FractionMargin * TexUtility.SizeFactor(style); numeratorBox = HorizontalBox.Get(numeratorBox, maxWidth, numeratorAlignment); denominatorBox = HorizontalBox.Get(denominatorBox, maxWidth, denominatorAlignment); // Calculate preliminary shift-up and shift-down amounts. float shiftUp, shiftDown; var styleFactor = TexUtility.SizeFactor(style); if (style >= TexStyle.Text) { styleFactor *= TEXConfiguration.main.FractionNarrowFactor; } shiftUp = TEXConfiguration.main.NumeratorShift * styleFactor; shiftDown = TEXConfiguration.main.DenominatorShift * styleFactor; // Create result box. var resultBox = VerticalBox.Get(); // add box for numerator. resultBox.Add(numeratorBox); // Calculate clearance and adjust shift amounts. //var axis = TEXConfiguration.main.AxisHeight * TexUtility.SizeFactor(style); // Calculate clearance amount. float clearance = lineHeight > 0 ? TEXConfiguration.main.FractionGap : TEXConfiguration.main.FractionGapNoLine; // Adjust shift amounts. var kern1 = shiftUp - numeratorBox.depth; var kern2 = shiftDown - denominatorBox.height; var delta1 = clearance - kern1; var delta2 = clearance - kern2; if (delta1 > 0) { shiftUp += delta1; kern1 += delta1; } if (delta2 > 0) { shiftDown += delta2; kern2 += delta2; } if (lineHeight > 0) { // Draw fraction line. resultBox.Add(StrutBox.Get(0, kern1, 0, 0)); resultBox.Add(HorizontalRule.Get(lineHeight, numeratorBox.width, 0)); resultBox.Add(StrutBox.Get(0, kern2, 0, 0)); } else { // Do not draw fraction line. var kern = kern1 + kern2; resultBox.Add(StrutBox.Get(0, kern, 0, 0)); } // add box for denominator. resultBox.Add(denominatorBox); // Adjust height and depth of result box. resultBox.height = shiftUp + numeratorBox.height; resultBox.depth = shiftDown + lineHeight + denominatorBox.depth; TexUtility.CentreBox(resultBox, style); return(resultBox); }
public override Box CreateBox() { // Create box for base atom. Box baseBox; float delta; if (BaseAtom is SymbolAtom && BaseAtom.Type == CharType.BigOperator) { // Find character of best scale for operator symbol. var opChar = TEXPreference.main.GetChar(((SymbolAtom)BaseAtom).Name).GetMetric(); if (TexContext.Environment.value < TexEnvironment.Text && opChar.ch.nextLargerExist) { opChar.Flush(); opChar = opChar.ch.nextLarger.GetMetric(); } opChar.shift = -(opChar.height + opChar.depth) / 2; baseBox = HorizontalBox.Get(opChar); delta = opChar.bearing; } else { baseBox = HorizontalBox.Get(BaseAtom == null ? StrutBox.Empty : BaseAtom.CreateBox()); delta = 0; } // Create boxes for upper and lower limits. Box upperLimitBox, lowerLimitBox; TexContext.Environment.Push(MakeSuperScripts ? TexEnvironment.ScriptScript : TexUtility.GetSuperscriptStyle()); if (UpperLimitAtom is SymbolAtom) { upperLimitBox = DelimiterFactory.CreateBoxHorizontal(((SymbolAtom)UpperLimitAtom).Name, baseBox.width); } else { upperLimitBox = UpperLimitAtom == null ? null : UpperLimitAtom.CreateBox(); } TexContext.Environment.Pop(); TexContext.Environment.Push(MakeSuperScripts ? TexEnvironment.ScriptScript : TexUtility.GetSubscriptStyle()); if (LowerLimitAtom is SymbolAtom) { lowerLimitBox = DelimiterFactory.CreateBoxHorizontal(((SymbolAtom)LowerLimitAtom).Name, baseBox.width); } else { lowerLimitBox = LowerLimitAtom == null ? null : LowerLimitAtom.CreateBox(); } TexContext.Environment.Pop(); // Make all component boxes equally wide. var maxWidth = Mathf.Max(Mathf.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 = VerticalBox.Get(); var opSpacing5 = TEXConfiguration.main.BigOpMargin * TexContext.Scale; var kern = 0f; // Create and add box for upper limit. if (UpperLimitAtom != null) { resultBox.Add(StrutBox.Get(0, opSpacing5, 0, 0)); upperLimitBox.shift = delta / 2; upperLimitBox.shift += TopOffset(BaseAtom); resultBox.Add(upperLimitBox); kern = Mathf.Max(TEXConfiguration.main.BigOpUpShift * TexContext.Scale, TEXConfiguration.main.BigOpUpperGap * TexContext.Scale - upperLimitBox.depth); resultBox.Add(StrutBox.Get(0, kern, 0, 0)); } // Add box for base atom. resultBox.Add(baseBox); // Create and add box for lower limit. if (LowerLimitAtom != null) { resultBox.Add(StrutBox.Get(0, Mathf.Max(TEXConfiguration.main.BigOpLowShift * TexContext.Scale, TEXConfiguration.main.BigOpLowerGap * TexContext.Scale - lowerLimitBox.height), 0, 0)); lowerLimitBox.shift = -delta / 2; lowerLimitBox.shift += BottomOffset(BaseAtom); resultBox.Add(lowerLimitBox); resultBox.Add(StrutBox.Get(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(TexStyle style) { // Create box for base atom. var baseBox = (BaseAtom == null ? StrutBox.Empty : BaseAtom.CreateBox(style)); if (SubscriptAtom == null && SuperscriptAtom == null) { return(baseBox); } // Save it shift and use it later var shift = baseBox.shift; // Create result box. var resultBox = HorizontalBox.Get(baseBox); var subscriptStyle = TexUtility.GetSubscriptStyle(style); var superscriptStyle = TexUtility.GetSuperscriptStyle(style); // Set delta value and preliminary shift-up and shift-down amounts depending on type of base atom. var delta = 0f; float shiftUp, shiftDown; if (BaseAtom is AccentedAtom) { var accentedBox = ((AccentedAtom)BaseAtom).BaseAtom.CreateBox(TexUtility.GetCrampedStyle(style)); shiftUp = accentedBox.height - TEXConfiguration.main.SupDrop * TexUtility.SizeFactor(superscriptStyle); shiftDown = accentedBox.depth + TEXConfiguration.main.SubDrop * TexUtility.SizeFactor(subscriptStyle); } else if (BaseAtom is CharSymbol) { var charFont = ((CharSymbol)BaseAtom).GetChar(); if (!((CharSymbol)BaseAtom).IsTextSymbol) { delta = TEXPreference.main.GetCharMetric(charFont, style).advanceDelta; } if (delta > TexUtility.FloatPrecision && SubscriptAtom == null) { resultBox.Add(StrutBox.Get(delta, 0, 0, 0)); delta = 0; } shiftUp = baseBox.height - TEXConfiguration.main.SupDrop * TexUtility.SizeFactor(superscriptStyle); shiftDown = baseBox.depth + TEXConfiguration.main.SubDrop * TexUtility.SizeFactor(subscriptStyle); } else { shiftUp = baseBox.height - TEXConfiguration.main.SupDrop * TexUtility.SizeFactor(superscriptStyle); shiftDown = baseBox.depth + TEXConfiguration.main.SubDrop * TexUtility.SizeFactor(subscriptStyle); } 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 = HorizontalBox.Get(superscriptBox); // Add box for script space. superscriptContainerBox.Add(scriptSpaceAtom.CreateBox(style)); // Adjust shift-up amount. float p; if (style == TexStyle.Display) { p = TEXConfiguration.main.SupMin * TexUtility.SizeFactor(style); } else // if (TexUtility.GetCrampedStyle (style) == style) { p = TEXConfiguration.main.SupMinNarrow * TexUtility.SizeFactor(style); } //else // p = TEXConfiguration.main.SupMinNarrow * TexUtility.SizeFactor(style); shiftUp = Mathf.Max(shiftUp, p); } if (SubscriptAtom != null) { // Create box for subscript atom. subscriptBox = SubscriptAtom.CreateBox(subscriptStyle); subscriptContainerBox = HorizontalBox.Get(subscriptBox); // Add box for script space. subscriptContainerBox.Add(scriptSpaceAtom.CreateBox(style)); } // Check if only superscript is set. if (subscriptBox == null) { superscriptContainerBox.shift = -shiftUp; resultBox.Add(superscriptContainerBox); resultBox.height = shiftUp + superscriptBox.height; return(resultBox); } // Check if only subscript is set. if (superscriptBox == null) { subscriptBox.shift = Mathf.Max(shiftDown, TEXConfiguration.main.SubMinNoSup * TexUtility.SizeFactor(style)); resultBox.Add(subscriptContainerBox); resultBox.depth = shiftDown + subscriptBox.depth; return(resultBox); } // Adjust shift-down amount. shiftDown = Mathf.Max(shiftDown, TEXConfiguration.main.SubMinOnSup * TexUtility.SizeFactor(style)); // Space between subscript and superscript. float 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. * float psi = 0.8f * TexUtility.SizeFactor(style) - (shiftUp - superscriptBox.depth); * if (psi > 0) * { * shiftUp += psi; * shiftDown -= psi; * } * }*/ scriptsInterSpace = shiftUp - superscriptBox.depth + shiftDown - subscriptBox.height; // If baseAtom is null, make it right-aligned if (BaseAtom is SpaceAtom && ((SpaceAtom)BaseAtom).policy == StrutPolicy.Misc) { var max = Mathf.Max(superscriptContainerBox.width, subscriptContainerBox.width); if (superscriptContainerBox.width < max) { superscriptContainerBox.Add(0, StrutBox.Get(max - superscriptContainerBox.width, 0, 0, 0)); } if (subscriptContainerBox.width < max) { subscriptContainerBox.Add(0, StrutBox.Get(max - subscriptContainerBox.width, 0, 0, 0)); } } // Create box containing both superscript and subscript. var scriptsBox = VerticalBox.Get(); scriptsBox.Add(superscriptContainerBox); scriptsBox.Add(StrutBox.Get(0, scriptsInterSpace, 0, 0)); scriptsBox.Add(subscriptContainerBox); scriptsBox.height = shiftUp + superscriptBox.height; scriptsBox.depth = shiftDown + subscriptBox.depth; scriptsBox.shift = shift; resultBox.Add(scriptsBox); return(resultBox); }
// Branched wrapping algorithm for RTL support based above. private void HandlePerLineWrappingReversed(int i) { TexRenderer row = m_formulas[i], newrow; HorizontalBox box = (HorizontalBox)row.Box; List <Box> ch = box.children; float x = row.PenaltyWidth, xPenalty = x, lastSpaceX = 0; int lastSpaceIdx = -1, last = ch.Count - 1; //Begin Per-character pooling for (int j = ch.Count; j-- > 0;) { var child = ch[j]; //White line? make a mark if (child is StrutBox && ((StrutBox)child).policy == StrutPolicy.BlankSpace) { lastSpaceIdx = j; //last space, index lastSpaceX = x; //last space, x position _spaceIdxs.Add(lastSpaceIdx); //record that space child.width = _realBlankSpaceWidth; // All spaces must have this width (they may modified after WordWarpJusified). } x += ch[j].width; //Total length not yet to break our rect limit? continue if (x * scale <= rectArea.width) { if (_doJustify && (0 == j)) { box.Recalculate(); } continue; } //Now j is maximum limit character length. Now move any //character before that to the new previous line //Did we use word wrap? Track the last space index if (_useWordWrap && lastSpaceIdx >= 0) { j = lastSpaceIdx; x = lastSpaceX; //Justify too? then expand our spaces width if (_doJustify && _spaceIdxs.Count > 1) { float normalizedWidth = rectArea.width / scale; float extraWidth = (normalizedWidth - x) / (_spaceIdxs.Count - 1); for (int k = 0; k < _spaceIdxs.Count; k++) { ch[_spaceIdxs[k]].width += extraWidth; } x = normalizedWidth; } } else { x -= ch[j].width; } if (j == last && (!_useWordWrap || lastSpaceIdx != j)) { // infinite loop prevention x += ch[j].width; continue; } var doOmitSpace = (_useWordWrap && lastSpaceIdx >= 0); m_formulas.Insert(i, newrow = TexRenderer.Get(HorizontalBox.Get(ch.GetRangePool(j + 1, last - j)), row.metaRules, row.partOfPreviousLine)); //Add to previous line, if (doOmitSpace) { j--; box.width -= ch[lastSpaceIdx].width; ch[lastSpaceIdx].Flush(); } ch.RemoveRange(j + 1, last - j); //Update our measurements, remember now m_formulas[i] is different with box row.partOfPreviousLine = doOmitSpace ? 2 : 1; box.width -= newrow.Box.width = x - xPenalty; size.x = Mathf.Max(size.x, x); size.y += newrow.CompleteHeight * scale; break; } }
public static Box CreateBoxHorizontal(string symbol, float minWidth) { minWidth += TEXConfiguration.main.DelimiterRecursiveOffset; var ch = TEXPreference.main.GetChar(symbol).GetMetric(); var ch2 = TEXPreference.main.GetChar(symbol); bool isAlreadyHorizontal = true; while (ch2 != null) { if (ch2.extensionExist && !ch2.extensionHorizontal) { isAlreadyHorizontal = false; break; } ch2 = ch2.nextLarger; } // Find first version of character that has at least minimum width. var totalWidth = isAlreadyHorizontal ? ch.bearing + ch.italic : ch.totalHeight; while (totalWidth < minWidth && ch.ch.nextLargerExist) { ch.Flush(); ch = ch.ch.nextLarger.GetMetric(); totalWidth = isAlreadyHorizontal ? ch.bearing + ch.italic : ch.totalHeight; } if (totalWidth < minWidth && ch.ch.extensionExist) { var resultBox = HorizontalBox.Get(); resultBox.ExtensionMode = true; // Construct box from extension character. var ext = ch.ch.GetExtentMetrics(); if (isAlreadyHorizontal) { if (ext[0] != null) { resultBox.Add(ext[0]); } if (ext[1] != null) { resultBox.Add(ext[1]); } if (ext[2] != null) { resultBox.Add(ext[2]); } } else { if (ext[2] != null) { resultBox.Add(RotatedCharBox.Get(ext[2])); } if (ext[1] != null) { resultBox.Add(RotatedCharBox.Get(ext[1])); } if (ext[0] != null) { resultBox.Add(RotatedCharBox.Get(ext[0])); } } // Insert repeatable part multiple times until box is high enough. if (ext[3] != null) { Box repeatBox = isAlreadyHorizontal ? (Box)ext[3] : RotatedCharBox.Get(ext[3]); do { if (ext[0] != null && ext[2] != null) { resultBox.Add(1, repeatBox); if (ext[1] != null) { resultBox.Add(resultBox.children.Count - 1, repeatBox); } } else if (ext[2] != null) { resultBox.Add(0, repeatBox); } else { resultBox.Add(repeatBox); } }while (resultBox.width < minWidth); } return(resultBox); } else { // Just enough if (isAlreadyHorizontal) { return(ch); } else { return(RotatedCharBox.Get(ch.ch)); } } }
// Branched wrapping algorithm for RTL support based above. void HandlePerLineWrappingReversed(Box box, int i) { float x = formulas[i].PenaltyWidth, xPenalty = x, xOri = 0, y = 0, lastSpaceX = 0; int lastSpaceIdx = -1; bool requestToSkip = false; //Begin Per-character pooling for (int j = box.children.Count; j-- > 0;) { var child = box.children[j]; //White line? make a mark if (child is StrutBox && ((StrutBox)child).policy == StrutPolicy.BlankSpace) { lastSpaceIdx = j; //last space, index lastSpaceX = x; //last space, x position _spaceIdxs.Add(lastSpaceIdx); //record that space child.width = _realBlankSpaceWidth; // All spaces must have this width (they may modified after WordWarpJusified). } x += box.children[j].width; xOri = x - xPenalty; //Total length not yet to break our rect limit? continue if (x * scale <= rectArea.width) { if (_doJustify && (0 == j)) { ((HorizontalBox)box).Recalculate(); } continue; } //Now j is maximum limit character length. Now move any //character before that to the new previous line //Did we use word wrap? Track the last space index if (_useWordWrap && lastSpaceIdx >= 0 && lastSpaceIdx < box.children.Count - 1) { //Already ommited since it is exluded j = lastSpaceIdx; x = lastSpaceX; xOri = lastSpaceX - xPenalty + box.children[lastSpaceIdx].width; requestToSkip = true; //Justify too? then expand our spaces width if (_doJustify && _spaceIdxs.Count > 1) { float normalizedWidth = rectArea.width / scale; float extraWidth = (normalizedWidth - x) / (float)(_spaceIdxs.Count - 1); for (int k = 0; k < _spaceIdxs.Count; k++) { box.children[_spaceIdxs[k]].width += extraWidth; } x = normalizedWidth; } } else if (box.children[j] is StrutBox && ((StrutBox)box.children[j]).policy == StrutPolicy.BlankSpace) { x -= box.children[j].width; requestToSkip = true; } else { x -= box.children[j].width; xOri = x - xPenalty; } if (j > box.children.Count - 2) { x += box.children[j].width; xOri = x - xPenalty; continue; } int oriPartMark = m_formulas[i].partOfPreviousLine; m_formulas[i].partOfPreviousLine = (_useWordWrap && lastSpaceIdx >= 0) ? 2 : 1; if (requestToSkip) { j--; // Skip the unneeded space char } m_formulas.Insert(i, TexRenderer.Get(HorizontalBox.Get( box.children.GetRangePool(j + 1, box.children.Count - j - 1)), originalScale, m_formulas[i].metaRules)); //Add to previous line, box.children.RemoveRange(j + 1, box.children.Count - j - 1); //Update our measurements, remember now m_formulas[i] is different with box if (oriPartMark > 0) { m_formulas[i].partOfPreviousLine = oriPartMark; } box.width -= xOri; y = m_formulas[i].Box.totalHeight; if (oriPartMark > 0) { y += m_formulas[i].PenaltyParagraph; } if (requestToSkip) { formulas[i].Box.shift -= m_formulas[i].Box.children[0].width; } formulas[i].Box.width = x - xPenalty; size.x = Mathf.Max(size.x, x); size.y += (spaceSize + m_formulas[i].PenaltySpacing + y) * scale; break; } }
public Box GenerateDelimiterBox(HorizontalBox result, ref int elementPos, ref int resultPos, TexStyle style) { var curAtom = Elements[elementPos]; if (!(curAtom is CharSymbol) || !((CharSymbol)curAtom).IsDelimiter) { // This is not delimiter, hence just create and do nothing. var box = curAtom.CreateBox(style); if (curAtom.Type == CharType.BigOperator) { TexUtility.CentreBox(box, style); } result.Add(resultPos, box); lastGeneratedBox = box; resultPos++; return(box); } var nextAtom = elementPos + 1 < Elements.Count ? Elements[elementPos + 1] : null; var prevAtom = elementPos > 0 ? Elements[elementPos - 1] : null; var minHeight = 0f; var ourPos = resultPos; if (nextAtom != null && curAtom.GetRightType() == CharType.OpenDelimiter) { elementPos++; var nextBox = GenerateDelimiterBox(result, ref elementPos, ref resultPos, style); minHeight = nextBox.totalHeight; } else if (lastGeneratedBox != null && curAtom.GetLeftType() == CharType.CloseDelimiter) { var prevBox = lastGeneratedBox; minHeight = prevBox.totalHeight; } else { if (prevAtom != null && lastGeneratedBox != null) { var prevBox = lastGeneratedBox; minHeight = prevBox.totalHeight; } if (nextAtom != null) { elementPos++; var nextBox = GenerateDelimiterBox(result, ref elementPos, ref resultPos, style); minHeight = Mathf.Max(nextBox.totalHeight, minHeight); } } var curBox = curAtom is SymbolAtom ? (((SymbolAtom)curAtom).CreateBox(style, minHeight)) : curAtom.CreateBox(style); TexUtility.CentreBox(curBox, style); result.Add(ourPos, curBox); if (ourPos == resultPos) { lastGeneratedBox = curBox; } resultPos++; return(curBox); }
public override Box CreateBox() { List <List <Box> > boxes = ListPool <List <Box> > .Get(); List <float> boxesHeight = ListPool <float> .Get(); List <float> boxesShift = ListPool <float> .Get(); List <float> boxesWidth = ListPool <float> .Get(); TexContext.Environment.Push(TexUtility.GetCrampedStyle()); float padding = TEXConfiguration.main.MatrixMargin * TexContext.Scale; for (int i = 0; i < Elements.Count; i++) { boxes.Add(ListPool <Box> .Get()); float h = 0f, d = 0f; for (int j = 0; j < Elements[i].Count; j++) { Box box; if (Elements[i][j] != null) { box = (Elements[i][j].CreateBox()); } else { box = (ObjPool <StrutBox> .Get()); } boxes[i].Add(box); if (j >= boxesWidth.Count) { boxesWidth.Add(box.width); } else { boxesWidth[j] = Mathf.Max(boxesWidth[j], box.width); } h = Mathf.Max(h, box.height); d = Mathf.Max(d, box.depth); } boxesHeight.Add(Mathf.Max(h + d, padding / 2f)); boxesShift.Add(h); } bool outsideGap = (horizontalLine > 0 && (enumContains(horizontalLine, 0) || enumContains(horizontalLine, 4))) || (verticalLine > 0 && (enumContains(verticalLine, 0) || enumContains(verticalLine, 4))); var vBox = VerticalBox.Get(); Box resultBox = vBox; Box kern = null; Box kernHalf = null; if (boxesWidth.Count > 1 || boxesHeight.Count > 1) { kern = StrutBox.Get(padding, padding, 0, 0); } if (outsideGap) { kernHalf = StrutBox.Get(padding / 2f, padding / 2f, 0, 0); vBox.Add(kernHalf); } TexAlignment firstRowH = alterH(horizontalAlign % 8); TexAlignment firstRowV = alterV(verticalAlign % 8); TexAlignment firstColH = alterH((horizontalAlign >> 3) % 8); TexAlignment firstColV = alterV((verticalAlign >> 3) % 8); TexAlignment bodyH = alterH((horizontalAlign >> 6) % 8); TexAlignment bodyV = alterV((verticalAlign >> 6) % 8); for (int i = 0; i < Elements.Count; i++) { var list = HorizontalBox.Get(); if (outsideGap) { list.Add(kernHalf); } for (int j = 0; j < Elements[i].Count; j++) { if (i == 0) { list.Add(VerticalBox.Get(HorizontalBox.Get(boxes[i][j], boxesWidth[j], firstRowH), boxesHeight[i], firstRowV)); } else if (j == 0) { list.Add(VerticalBox.Get(HorizontalBox.Get(boxes[i][j], boxesWidth[j], firstColH), boxesHeight[i], firstColV)); } else { list.Add(VerticalBox.Get(HorizontalBox.Get(boxes[i][j], boxesWidth[j], bodyH), boxesHeight[i], bodyV)); } if (j < Elements[i].Count - 1) { list.Add(kern); } else if (outsideGap) { list.Add(kernHalf); } } list.depth = boxesHeight[i] - list.height; vBox.Add(list); if (i < Elements.Count - 1) { vBox.Add(kern); } else if (outsideGap) { vBox.Add(kernHalf); } } var lineThick = TEXConfiguration.main.LineThickness * TexContext.Scale; //Add horizontal lines for table if (horizontalLine > 0) { var outside = enumContains(horizontalLine, 0); var first = enumContains(horizontalLine, 1); var inset = enumContains(horizontalLine, 2); var firstThick = enumContains(horizontalLine, 3); var outsideThick = enumContains(horizontalLine, 4); float gapX = (padding - lineThick); float gapXThick = (padding - (lineThick * 2)); float gapXNone = (padding); float gapOutside = (outside ? (outsideThick ? gapXThick : gapX) : gapXNone); float gapInset = (inset ? gapX : gapXNone); float lineOutside = outsideThick ? lineThick * 2 : lineThick; var insideBox = resultBox; var hBox = HorizontalBox.Get(resultBox); resultBox = hBox; if (outsideGap) { hBox.Add(StrutBox.Get(-insideBox.width - lineOutside / 2f, 0, 0, 0)); } else { hBox.Add(StrutBox.Get(-insideBox.width - lineOutside * 1.5f, 0, 0, 0)); } for (int i = 0; i < boxesWidth.Count; i++) { if (i == 0) { if (outside) { hBox.Add(HorizontalRule.Get(insideBox.height, lineOutside, 0, insideBox.depth)); } hBox.Add(StrutBox.Get(boxesWidth[i] + gapOutside, 0, 0, 0)); continue; } if (i == 1) { if (first) { hBox.Add(HorizontalRule.Get(insideBox.height, firstThick ? lineThick * 2 : lineThick, 0, insideBox.depth)); } hBox.Add(StrutBox.Get(boxesWidth[i] + (first ? (firstThick ? gapXThick : gapX) : gapXNone), 0, 0, 0)); continue; } if (inset) { hBox.Add(HorizontalRule.Get(insideBox.height, lineThick, 0, insideBox.depth)); } hBox.Add(StrutBox.Get(boxesWidth[i] + gapInset, 0, 0, 0)); } if (outside) { hBox.Add(HorizontalRule.Get(insideBox.height, lineOutside, 0, insideBox.depth)); } } if (verticalLine > 0) { var outside = enumContains(verticalLine, 0); var first = enumContains(verticalLine, 1); var inset = enumContains(verticalLine, 2); var firstThick = enumContains(verticalLine, 3); var outsideThick = enumContains(verticalLine, 4); float gapX = (padding - lineThick); float gapXThick = (padding - (lineThick * 2)); float gapXNone = (padding); float gapOutside = (outside ? (outsideThick ? gapXThick : gapX) : gapXNone); float gapInset = (inset ? gapX : gapXNone); float lineOutside = outsideThick ? lineThick * 2 : lineThick; var insideBox = resultBox; var size = insideBox.width; vBox = VerticalBox.Get(resultBox); resultBox = vBox; if (outsideGap) { vBox.Add(StrutBox.Get(0, -insideBox.totalHeight - lineOutside / 2f, 0, 0)); } else { vBox.Add(StrutBox.Get(0, -insideBox.totalHeight, 0, 0)); } for (int i = 0; i < boxesHeight.Count; i++) { if (i == 0) { if (outside) { vBox.Add(HorizontalRule.Get(lineOutside, size, 0)); } vBox.Add(StrutBox.Get(0, boxesHeight[i] + (outsideGap ? gapOutside : gapOutside / 2f), 0, 0)); } else if (i == 1) { if (first) { vBox.Add(HorizontalRule.Get(firstThick ? lineThick * 2 : lineThick, size, 0)); } var thick = (first ? (firstThick ? gapXThick : gapX) : gapXNone); vBox.Add(StrutBox.Get(0, boxesHeight[i] + (boxesHeight.Count == 2 && !outsideGap ? thick / 2f : thick), 0, 0)); } else { if (inset) { vBox.Add(HorizontalRule.Get(lineThick, size, 0)); } vBox.Add(StrutBox.Get(0, boxesHeight[i] + (i < boxesHeight.Count - 1 || outsideGap ? gapInset : gapInset / 2f), 0, 0)); } } if (outside && outsideGap) { vBox.Add(HorizontalRule.Get(lineOutside, size, 0, 0)); } } TexUtility.CentreBox(resultBox); TexContext.Environment.Pop(); //Clear resources ListPool <float> .Release(boxesHeight); ListPool <float> .Release(boxesWidth); ListPool <float> .Release(boxesShift); for (int i = 0; i < boxes.Count; i++) { ListPool <Box> .ReleaseNoFlush(boxes[i]); } ListPool <List <Box> > .ReleaseNoFlush(boxes); return(resultBox); }
public Box GenerateDelimiterBox(HorizontalBox result, ref int elementPos, ref int resultPos) { var curAtom = Elements[elementPos]; if (!(curAtom is CharSymbol) || !((CharSymbol)curAtom).IsDelimiter) { // This is not delimiter, hence just create and do nothing. var box = curAtom.CreateBox(); if (curAtom.Type == CharType.BigOperator) // specific patch to BigOperator { TexUtility.CentreBox(box); } if (box is HorizontalBox && (curAtom is AttrSizeAtom || curAtom is AttrStyleAtom)) // specific patch to Atoms that should be wrappable. { var h = box as HorizontalBox; result.AddRange(h, resultPos); resultPos += h.children.Count; } else { result.Add(resultPos++, box); } lastGeneratedBox = box; return(box); } var nextAtom = elementPos + 1 < Elements.Count ? Elements[elementPos + 1] : null; var prevAtom = elementPos > 0 ? Elements[elementPos - 1] : null; var minHeight = 0f; var ourPos = resultPos; if (nextAtom != null && curAtom.RightType == CharType.OpenDelimiter) { elementPos++; var nextBox = GenerateDelimiterBox(result, ref elementPos, ref resultPos); minHeight = nextBox.totalHeight; } else if (lastGeneratedBox != null && curAtom.LeftType == CharType.CloseDelimiter) { var prevBox = lastGeneratedBox; minHeight = prevBox.totalHeight; } else { if (prevAtom != null && lastGeneratedBox != null) { var prevBox = lastGeneratedBox; minHeight = prevBox.totalHeight; } if (nextAtom != null) { elementPos++; var nextBox = GenerateDelimiterBox(result, ref elementPos, ref resultPos); minHeight = Mathf.Max(nextBox.totalHeight, minHeight); } } var curBox = curAtom is SymbolAtom ? (((SymbolAtom)curAtom).CreateBox(minHeight)) : curAtom.CreateBox(); TexUtility.CentreBox(curBox); result.Add(ourPos, curBox); if (ourPos == resultPos) { lastGeneratedBox = curBox; } resultPos++; return(curBox); }
public static Box CreateBoxHorizontal(string symbol, float minWidth, TexStyle style) { var charInfo = TEXPreference.main.GetCharMetric(symbol, style); var charInfo2 = TEXPreference.main.GetChar(symbol); bool isAlreadyHorizontal = true; while (charInfo2 != null) { if (charInfo2.extensionExist && !charInfo2.extensionHorizontal) { isAlreadyHorizontal = false; break; } charInfo2 = charInfo2.nextLarger; } // Find first version of character that has at least minimum width. var totalWidth = isAlreadyHorizontal ? charInfo.bearing + charInfo.italic : charInfo.totalHeight; while (totalWidth < minWidth && charInfo.ch.nextLargerExist) { charInfo = TEXPreference.main.GetCharMetric(charInfo.ch.nextLarger, style); totalWidth = isAlreadyHorizontal ? charInfo.bearing + charInfo.italic : charInfo.totalHeight; } if (totalWidth >= minWidth) { // Character of sufficient height was found. if (isAlreadyHorizontal) { return(CharBox.Get(style, charInfo)); } else { return(RotatedCharBox.Get(style, charInfo)); } } else if (charInfo.ch.extensionExist) { var resultBox = HorizontalBox.Get(); resultBox.ExtensionMode = true; // Construct box from extension character. var extension = charInfo.ch.GetExtentMetrics(style); if (isAlreadyHorizontal) { if (extension[0] != null) { resultBox.Add(CharBox.Get(style, extension[0])); } if (extension[1] != null) { resultBox.Add(CharBox.Get(style, extension[1])); } if (extension[2] != null) { resultBox.Add(CharBox.Get(style, extension[2])); } } else { if (extension[2] != null) { resultBox.Add(RotatedCharBox.Get(style, extension[2])); } if (extension[1] != null) { resultBox.Add(RotatedCharBox.Get(style, extension[1])); } if (extension[0] != null) { resultBox.Add(RotatedCharBox.Get(style, extension[0])); } } // Insert repeatable part multiple times until box is high enough. if (extension[3] != null) { Box repeatBox; if (isAlreadyHorizontal) { repeatBox = CharBox.Get(style, extension[3]); } else { repeatBox = RotatedCharBox.Get(style, extension[3]); } do { if (extension[0] != null && extension[2] != null) { resultBox.Add(1, repeatBox); if (extension[1] != null) { resultBox.Add(resultBox.children.Count - 1, repeatBox); } } else if (extension[2] != null) { resultBox.Add(0, repeatBox); } else { resultBox.Add(repeatBox); } }while (resultBox.width < minWidth); } return(resultBox); } else { // No extensions available, so use tallest available version of character. if (isAlreadyHorizontal) { return(CharBox.Get(style, charInfo)); } else { return(RotatedCharBox.Get(style, charInfo)); } } }