public UnderOverAtom(Atom baseAtom, Atom underOver, TexUnit underOverUnit, double underOverSpace, bool underOverScriptSize, bool over) { SpaceAtom.CheckUnit(underOverUnit); this.BaseAtom = baseAtom; if (over) { this.UnderAtom = null; this.UnderSpace = 0; this.UnderSpaceUnit = 0; this.UnderScriptSmaller = false; this.OverAtom = underOver; this.OverSpaceUnit = underOverUnit; this.OverSpace = underOverSpace; this.OverScriptSmaller = underOverScriptSize; } else { this.UnderAtom = underOver; this.UnderSpaceUnit = underOverUnit; this.UnderSpace = underOverSpace; this.UnderScriptSmaller = underOverScriptSize; this.OverSpace = 0; this.OverAtom = null; this.OverSpaceUnit = 0; this.OverScriptSmaller = false; } }
protected FractionAtom(Atom numerator, Atom denominator, bool useDefaultThickness, TexUnit unit, double thickness) { SpaceAtom.CheckUnit(unit); this.Type = TexAtomType.Inner; this.Numerator = numerator; this.Denominator = denominator; this.numeratorAlignment = TexAlignment.Center; this.denominatorAlignment = TexAlignment.Center; this.useDefaultThickness = useDefaultThickness; this.lineThicknessUnit = unit; this.lineThickness = thickness; }
public UnderOverAtom(Atom baseAtom, Atom under, TexUnit underUnit, double underSpace, bool underScriptSize, Atom over, TexUnit overUnit, double overSpace, bool overScriptSize) { SpaceAtom.CheckUnit(underUnit); SpaceAtom.CheckUnit(overUnit); this.BaseAtom = baseAtom; this.UnderAtom = under; this.UnderSpaceUnit = underUnit; this.UnderSpace = underSpace; this.UnderScriptSmaller = underScriptSize; this.OverAtom = over; this.OverSpaceUnit = overUnit; this.OverSpace = overSpace; this.OverScriptSmaller = overScriptSize; }
public override Box CreateBox(TexEnvironment environment) { var texFont = environment.TexFont; var style = environment.Style; // Calculate minimum clearance amount. double clearance; var defaultRuleThickness = texFont.GetDefaultLineThickness(style); if (style < TexStyle.Text) clearance = texFont.GetXHeight(style, texFont.GetCharInfo(sqrtSymbol, style).FontId); else clearance = defaultRuleThickness; clearance = defaultRuleThickness + Math.Abs(clearance) / 4; // Create box for base atom, in cramped style. var baseBox = this.BaseAtom.CreateBox(environment.GetCrampedStyle()); // Create box for radical sign. var totalHeight = baseBox.Height + baseBox.Depth; var radicalSignBox = DelimiterFactory.CreateBox(sqrtSymbol, totalHeight + clearance + defaultRuleThickness, environment); // Add half of excess height to clearance. var delta = radicalSignBox.Depth - (totalHeight + clearance); clearance += delta / 2; // Create box for square-root containing base box. radicalSignBox.Shift = -(baseBox.Height + clearance); var overBar = new OverBar(baseBox, clearance, radicalSignBox.Height); overBar.Shift = -(baseBox.Height + clearance + defaultRuleThickness); var radicalContainerBox = new HorizontalBox(radicalSignBox); radicalContainerBox.Add(overBar); // If atom is simple radical, just return square-root box. if (this.DegreeAtom == null) return radicalContainerBox; // Atom is complex radical (nth-root). // Create box for root atom. var rootBox = this.DegreeAtom.CreateBox(environment.GetRootStyle()); var bottomShift = scale * (radicalContainerBox.Height + radicalContainerBox.Depth); rootBox.Shift = radicalContainerBox.Depth - rootBox.Depth - bottomShift; // Create result box. var resultBox = new HorizontalBox(); // Add box for negative kern. var negativeKern = new SpaceAtom(TexUnit.Mu, -10, 0, 0).CreateBox(environment); var xPos = rootBox.Width + negativeKern.Width; if (xPos < 0) resultBox.Add(new StrutBox(-xPos, 0, 0, 0)); resultBox.Add(rootBox); resultBox.Add(negativeKern); resultBox.Add(radicalContainerBox); return resultBox; }
public override Box CreateBox(TexEnvironment environment) { var texFont = environment.MathFont; var style = environment.Style; // Calculate minimum clearance amount. double clearance; var defaultRuleThickness = texFont.GetDefaultLineThickness(style); if (style < TexStyle.Text) { clearance = texFont.GetXHeight(style, texFont.GetCharInfo(sqrtSymbol, style).FontId); } else { clearance = defaultRuleThickness; } clearance = defaultRuleThickness + Math.Abs(clearance) / 4; // Create box for base atom, in cramped style. var baseBox = this.BaseAtom.CreateBox(environment.GetCrampedStyle()); // Create box for radical sign. var totalHeight = baseBox.Height + baseBox.Depth; var radicalSignBox = DelimiterFactory.CreateBox(sqrtSymbol, totalHeight + clearance + defaultRuleThickness, environment); // Add half of excess height to clearance. var delta = radicalSignBox.Depth - (totalHeight + clearance); clearance += delta / 2; // Create box for square-root containing base box. radicalSignBox.Shift = -(baseBox.Height + clearance); var overBar = new OverBar(environment, baseBox, clearance, radicalSignBox.Height); overBar.Shift = -(baseBox.Height + clearance + defaultRuleThickness); var radicalContainerBox = new HorizontalBox(radicalSignBox); radicalContainerBox.Add(overBar); // If atom is simple radical, just return square-root box. if (this.DegreeAtom == null) { return(radicalContainerBox); } // Atom is complex radical (nth-root). // Create box for root atom. var rootBox = this.DegreeAtom.CreateBox(environment.GetRootStyle()); var bottomShift = scale * (radicalContainerBox.Height + radicalContainerBox.Depth); rootBox.Shift = radicalContainerBox.Depth - rootBox.Depth - bottomShift; // Create result box. var resultBox = new HorizontalBox(); // Add box for negative kern. var negativeKern = new SpaceAtom(TexUnit.Mu, -10, 0, 0).CreateBox(environment); var xPos = rootBox.Width + negativeKern.Width; if (xPos < 0) { resultBox.Add(new StrutBox(-xPos, 0, 0, 0)); } resultBox.Add(rootBox); resultBox.Add(negativeKern); resultBox.Add(radicalContainerBox); return(resultBox); }
public override Box CreateBox(TexEnvironment environment) { var texFont = environment.TexFont; var style = environment.Style; // set thickness to default if default value should be used double lineHeight; var defaultLineThickness = texFont.GetDefaultLineThickness(style); if (this.useDefaultThickness) { lineHeight = this.lineRelativeThickness.HasValue ? this.lineRelativeThickness.Value * defaultLineThickness : defaultLineThickness; } else { lineHeight = new SpaceAtom(this.lineThicknessUnit, 0, this.lineThickness, 0).CreateBox(environment).Height; } // Create boxes for numerator and demoninator atoms, and make them of equal width. var numeratorBox = this.Numerator == null ? StrutBox.Empty : this.Numerator.CreateBox(environment.GetNumeratorStyle()); var denominatorBox = this.Denominator == null ? StrutBox.Empty : this.Denominator.CreateBox(environment.GetDenominatorStyle()); if (numeratorBox.Width < denominatorBox.Width) { numeratorBox = new HorizontalBox(numeratorBox, denominatorBox.Width, numeratorAlignment); } else { denominatorBox = new HorizontalBox(denominatorBox, numeratorBox.Width, denominatorAlignment); } // Calculate preliminary shift-up and shift-down amounts. double shiftUp, shiftDown; if (style < TexStyle.Text) { shiftUp = texFont.GetNum1(style); shiftDown = texFont.GetDenom1(style); } else { shiftDown = texFont.GetDenom2(style); if (lineHeight > 0) { shiftUp = texFont.GetNum2(style); } else { shiftUp = texFont.GetNum3(style); } } // Create result box. var resultBox = new VerticalBox(); // add box for numerator. resultBox.Add(numeratorBox); // Calculate clearance and adjust shift amounts. var axis = texFont.GetAxisHeight(style); if (lineHeight > 0) { // Draw fraction line. // Calculate clearance amount. double clearance; if (style < TexStyle.Text) { clearance = 3 * lineHeight; } else { clearance = lineHeight; } // Adjust shift amounts. var delta = lineHeight / 2; var kern1 = shiftUp - numeratorBox.Depth - (axis + delta); var kern2 = axis - delta - (denominatorBox.Height - shiftDown); var delta1 = clearance - kern1; var delta2 = clearance - kern2; if (delta1 > 0) { shiftUp += delta1; kern1 += delta1; } if (delta2 > 0) { shiftDown += delta2; kern2 += delta2; } resultBox.Add(new StrutBox(0, kern1, 0, 0)); resultBox.Add(new HorizontalRule(environment, lineHeight, numeratorBox.Width, 0)); resultBox.Add(new StrutBox(0, kern2, 0, 0)); } else { // Do not draw fraction line. // Calculate clearance amount. double clearance; if (style < TexStyle.Text) { clearance = 7 * defaultLineThickness; } else { clearance = 3 * defaultLineThickness; } // Adjust shift amounts. var kern = shiftUp - numeratorBox.Depth - (denominatorBox.Height - shiftDown); var delta = (clearance - kern) / 2; if (delta > 0) { shiftUp += delta; shiftDown += delta; kern += 2 * delta; } resultBox.Add(new StrutBox(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 + denominatorBox.Depth; return(resultBox); }
public override Box CreateBox(TexEnvironment environment) { var texFont = environment.TexFont; var style = environment.Style; // set thickness to default if default value should be used double lineHeight; var defaultLineThickness = texFont.GetDefaultLineThickness(style); if (this.useDefaultThickness) lineHeight = this.lineRelativeThickness.HasValue ? this.lineRelativeThickness.Value * defaultLineThickness : defaultLineThickness; else lineHeight = new SpaceAtom(this.lineThicknessUnit, 0, this.lineThickness, 0).CreateBox(environment).Height; // Create boxes for numerator and demoninator atoms, and make them of equal width. var numeratorBox = this.Numerator == null ? StrutBox.Empty : this.Numerator.CreateBox(environment.GetNumeratorStyle()); var denominatorBox = this.Denominator == null ? StrutBox.Empty : this.Denominator.CreateBox(environment.GetDenominatorStyle()); if (numeratorBox.Width < denominatorBox.Width) numeratorBox = new HorizontalBox(numeratorBox, denominatorBox.Width, numeratorAlignment); else denominatorBox = new HorizontalBox(denominatorBox, numeratorBox.Width, denominatorAlignment); // Calculate preliminary shift-up and shift-down amounts. double shiftUp, shiftDown; if (style < TexStyle.Text) { shiftUp = texFont.GetNum1(style); shiftDown = texFont.GetDenom1(style); } else { shiftDown = texFont.GetDenom2(style); if (lineHeight > 0) shiftUp = texFont.GetNum2(style); else shiftUp = texFont.GetNum3(style); } // Create result box. var resultBox = new VerticalBox(); // add box for numerator. resultBox.Add(numeratorBox); // Calculate clearance and adjust shift amounts. var axis = texFont.GetAxisHeight(style); if (lineHeight > 0) { // Draw fraction line. // Calculate clearance amount. double clearance; if (style < TexStyle.Text) clearance = 3 * lineHeight; else clearance = lineHeight; // Adjust shift amounts. var delta = lineHeight / 2; var kern1 = shiftUp - numeratorBox.Depth - (axis + delta); var kern2 = axis - delta - (denominatorBox.Height - shiftDown); var delta1 = clearance - kern1; var delta2 = clearance - kern2; if (delta1 > 0) { shiftUp += delta1; kern1 += delta1; } if (delta2 > 0) { shiftDown += delta2; kern2 += delta2; } resultBox.Add(new StrutBox(0, kern1, 0, 0)); resultBox.Add(new HorizontalRule(lineHeight, numeratorBox.Width, 0)); resultBox.Add(new StrutBox(0, kern2, 0, 0)); } else { // Do not draw fraction line. // Calculate clearance amount. double clearance; if (style < TexStyle.Text) clearance = 7 * defaultLineThickness; else clearance = 3 * defaultLineThickness; // Adjust shift amounts. var kern = shiftUp - numeratorBox.Depth - (denominatorBox.Height - shiftDown); var delta = (clearance - kern) / 2; if (delta > 0) { shiftUp += delta; shiftDown += delta; kern += 2 * delta; } resultBox.Add(new StrutBox(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 + denominatorBox.Depth; return resultBox; }
private TexFormula Parse( SourceSpan value, ref int position, bool allowClosingDelimiter, string?textStyle, ICommandEnvironment environment) { var formula = new TexFormula { Source = value, TextStyle = textStyle }; var closedDelimiter = false; var skipWhiteSpace = ShouldSkipWhiteSpace(textStyle); var initialPosition = position; while (position < value.Length && !(allowClosingDelimiter && closedDelimiter)) { char ch = value[position]; var source = value.Segment(position, 1); if (IsWhiteSpace(ch)) { if (!skipWhiteSpace) { formula.Add(new SpaceAtom(source), source); } position++; } else if (ch == escapeChar) { ProcessEscapeSequence( formula, value, ref position, allowClosingDelimiter, ref closedDelimiter, environment); } else if (ch == leftGroupChar) { var groupValue = ReadElement(value, ref position); var parsedGroup = Parse(groupValue, textStyle, environment.CreateChildEnvironment()); var innerGroupAtom = parsedGroup.RootAtom ?? new RowAtom(groupValue); var groupAtom = new TypedAtom( innerGroupAtom.Source, innerGroupAtom, TexAtomType.Ordinary, TexAtomType.Ordinary); var scriptsAtom = this.AttachScripts(formula, value, ref position, groupAtom, true, environment); formula.Add(scriptsAtom, value.Segment(initialPosition, position - initialPosition)); } else if (ch == rightGroupChar) { throw new TexParseException("Found a closing '" + rightGroupChar + "' without an opening '" + leftGroupChar + "'!"); } else if (ch == superScriptChar || ch == subScriptChar || ch == primeChar) { if (position == 0) { var sp = new SpaceAtom(source); var scriptsAtom = AttachScripts(formula, value, ref position, sp, skipWhiteSpace, environment); formula.Add(scriptsAtom, value.Segment(initialPosition, position - initialPosition)); //throw new TexParseException("Every script needs a base: \"" // + superScriptChar + "\", \"" + subScriptChar + "\" and \"" // + primeChar + "\" can't be the first character!"); } else { throw new TexParseException("Double scripts found! Try using more braces."); } } else { var character = ConvertCharacter(formula, ref position, source, environment); if (character != null) { var scriptsAtom = AttachScripts( formula, value, ref position, character, skipWhiteSpace, environment); formula.Add(scriptsAtom, value.Segment(initialPosition, position)); } } } return(formula); }