private TexFormula ParseFormula(string input) { // Create formula object from input text. TexFormula formula = null; try { formula = this._formulaParser.Parse(input); } catch (Exception ex) { MessageBox.Show("An error occurred while parsing the given input:" + Environment.NewLine + Environment.NewLine + ex.Message, "WPF-Math Example", MessageBoxButton.OK, MessageBoxImage.Error); } return(formula); }
private TexFormula ReadScript(TexFormula formula, string value, ref int position) { if (position == value.Length) { //throw new TexParseException("illegal end, missing script!"); return(formula); } SkipWhiteSpace(value, ref position); var ch = value[position]; if (ch == leftGroupChar) { return(Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar))); } else { return(Parse(ReadScriptGroup(value, ref position))); } }
protected override void Write([NotNull] WpfRenderer renderer, [NotNull] MathInline obj) { var text = obj.Content.Text.Substring(obj.Content.Start, obj.Content.Length); TexFormula formula = null; try { formula = formulaParser.Parse(text); } catch (Exception) { renderer.WriteInline(new Run("[!!FORMULA PARSE ERROR!!]") { Tag = obj }); return; } var fontSize = renderer.CurrentFontSize(); var formulaRenderer = formula.GetRenderer(TexStyle.Display, fontSize, "Arial"); var geo = formulaRenderer.RenderToGeometry(0, 0); var geoD = new System.Windows.Media.GeometryDrawing(Brushes.Black, null, geo); var di = new DrawingImage(geoD); var uiImage = new System.Windows.Controls.Image() { Source = di }; uiImage.Height = formulaRenderer.RenderSize.Height; // size image to match rendersize -> get a zoom of 100% uiImage.Margin = new System.Windows.Thickness(0, 0, 0, -formulaRenderer.RenderSize.Height * formulaRenderer.RelativeDepth); // Move image so that baseline matches that of text var uiInline = new System.Windows.Documents.InlineUIContainer() { Child = uiImage, Background = Brushes.Yellow, BaselineAlignment = System.Windows.BaselineAlignment.Baseline, Tag = obj, }; renderer.WriteInline(uiInline); }
public void SaveGeometry(string filename) { TexFormulaParser formulaParser = new TexFormulaParser(); if (filename == null) { return; } // Create formula object from input text. TexFormula formula = null; try { formula = formulaParser.Parse(Formula); } catch (Exception ex) { MessageBox.Show("An error occurred while parsing the given input:" + Environment.NewLine + Environment.NewLine + ex.Message, "WPF-Math Example", MessageBoxButton.OK, MessageBoxImage.Error); } // Create formula object from input text. if (formula == null) { return; } var renderer = formula.GetRenderer(TexStyle.Display, Scale, SystemTextFontName); using (var fs = new FileStream(filename, FileMode.Create, FileAccess.Write)) { var geometry = renderer.RenderToGeometry(0, 0); var svgPathText = ConvertGeometry(geometry); var svgText = AddSVGHeader(svgPathText); using (var writer = new StreamWriter(fs)) writer.WriteLine(svgText); } }
public override void Parse(SourceSpan source, XElement element) { var name = element.AttributeValue("name"); var args = element.Elements("Argument"); var argTypes = GetArgumentTypes(args); var argValues = GetArgumentValues(this.TempFormulas, args); Debug.Assert(argValues.Length == 1 || argValues.Length == 0); TexFormula formula = null; if (argValues.Length == 1) { var parser = new TexFormulaParser(); formula = parser.Parse((string)argValues[0]); } else { formula = new TexFormula(); } this.TempFormulas.Add(name, formula); }
protected override void Write(OpenXMLRenderer renderer, MathBlock obj) { string text = string.Empty; // obj.Content.Text.Substring(obj.Content.Start, obj.Content.Length); for (int i = 0; i < obj.Lines.Count; ++i) { var l = obj.Lines.Lines[i]; text += l.Slice.Text.Substring(l.Slice.Start, l.Slice.Length); } if (string.IsNullOrEmpty(text)) { return; } TexFormula formula = null; try { formula = _formulaParser.Parse(text); } catch (Exception) { return; } var mathRenderer = new MathRendering.OpenXMLWpfMathRenderer(); var mathObj = (DocumentFormat.OpenXml.OpenXmlCompositeElement)mathRenderer.Render(formula.RootAtom); var wordParagraph = renderer.PushNewParagraph(); // this is a Word paragraph renderer.Push(new Paragraph()); // Attention this is a __Math__ paragraph! renderer.Push(mathObj); renderer.PopTo(wordParagraph); }
protected override void Write([NotNull] WpfRenderer renderer, [NotNull] MathBlock obj) { string text = string.Empty; // obj.Content.Text.Substring(obj.Content.Start, obj.Content.Length); for (int i = 0; i < obj.Lines.Count; ++i) { var l = obj.Lines.Lines[i]; text += l.Slice.Text.Substring(l.Slice.Start, l.Slice.Length); } if (string.IsNullOrEmpty(text)) { return; } TexFormula formula = null; try { formula = formulaParser.Parse(text); } catch (Exception) { var paragraph = new Paragraph() { Tag = obj }; renderer.Push(paragraph); renderer.WriteInline(new Run("[!!FORMULA PARSE ERROR!!]") { Tag = obj }); renderer.Pop(); return; } var fontSize = renderer.CurrentFontSize(); if (fontSize <= 0) { throw new InvalidProgramException(); } var formulaRenderer = formula.GetRenderer(TexStyle.Display, fontSize, "Arial"); var geo = formulaRenderer.RenderToGeometry(0, 0); var geoD = new System.Windows.Media.GeometryDrawing(Brushes.Black, null, geo); var di = new DrawingImage(geoD); var uiImage = new System.Windows.Controls.Image() { Source = di }; uiImage.Height = formulaRenderer.RenderSize.Height; // size image to match rendersize -> get a zoom of 100% // uiImage.Margin = new System.Windows.Thickness(0, 0, 0, -formulaRenderer.RenderSize.Height * formulaRenderer.RelativeDepth); // Move image so that baseline matches that of text var uiBlock = new System.Windows.Documents.BlockUIContainer() { Child = uiImage, Tag = obj, }; renderer.WriteBlock(uiBlock); }
public void AddPhantom(TexFormula formula) => Add(new PhantomAtom(formula?.RootAtom));
public void AddOperator(TexFormula operatorFormula, TexFormula lowerLimitFormula, TexFormula upperLimitFormula) => Add(new BigOperatorAtom(operatorFormula?.RootAtom, lowerLimitFormula?.RootAtom, upperLimitFormula?.RootAtom));
public void AddRadical(TexFormula baseFormula) => AddRadical(baseFormula, (TexFormula)null);
public void AddRadical(string baseFormula, TexFormula nthRoot) => AddRadical(FormulaParser.Parse(baseFormula), nthRoot);
public void Add(TexFormula formula) => Formula.Add(formula);
public TexFormulaHelper(TexFormula formula) { FormulaParser = new TexFormulaParser(); Formula = formula; }
public bool ProcessUnknownCharacter(TexFormula formula, char character) => false;
private Atom AttachScripts(TexFormula formula, string value, ref int position, Atom atom) { if (position == value.Length) { return(atom); } if (value[position] == superScriptChar || value[position] == subScriptChar) { if (position == value.Length - 1) { position++; return(atom); } } else { return(atom); } TexFormula superscriptFormula = null; TexFormula subscriptFormula = null; //0: Undetermined; 1: Not Yet; 2: Yes, we are; 3: Yes, and make it smaller int markAsBig = 0; //0: In Beginning;1: We are in _;2: we are in ^ int lastIsSuper = 0; while (position < value.Length) { var ch = value[position]; if (ch == superScriptChar || ch == subScriptChar) { if (++position < value.Length && (value[position] == ch)) { markAsBig = 2; if (++position < value.Length && (value[position] == ch)) { markAsBig = 3; position++; } } bool v = ch == superScriptChar; if ((v ? superscriptFormula : subscriptFormula) == null) { lastIsSuper = v ? 2 : 1; } continue; } else if (ch == rightGroupChar || (value[position - 1] != '^' && value[position - 1] != '_')) { break; } if (lastIsSuper == 2) { if (superscriptFormula == null) { superscriptFormula = ReadScript(formula, value, ref position); } else { position--; superscriptFormula.RootAtom = AttachScripts(formula, value, ref position, superscriptFormula.RootAtom); } } else if (lastIsSuper == 1) { if (subscriptFormula == null) { subscriptFormula = ReadScript(formula, value, ref position); } else { position--; subscriptFormula.RootAtom = AttachScripts(formula, value, ref position, subscriptFormula.RootAtom); } } else { break; } } if (superscriptFormula == null && subscriptFormula == null) { return(atom); } // Check whether to return Big Operator or Scripts. if (atom != null && (atom.GetRightType() == CharType.BigOperator || markAsBig >= 2)) { return(BigOperatorAtom.Get(atom, subscriptFormula == null ? null : subscriptFormula.GetRoot, superscriptFormula == null ? null : superscriptFormula.GetRoot, markAsBig == 3)); } else { return(ScriptsAtom.Get(atom, subscriptFormula == null ? null : subscriptFormula.GetRoot, superscriptFormula == null ? null : superscriptFormula.GetRoot)); } }
public void AddFraction(TexFormula numerator, TexFormula denominator, bool drawLine) => Add(new FractionAtom(numerator?.RootAtom, denominator?.RootAtom, drawLine));
public void AddFraction(TexFormula numerator, TexFormula denominator, bool drawLine, TexAlignment numeratorAlignment, TexAlignment denominatorAlignment) => Add(new FractionAtom(numerator?.RootAtom, denominator?.RootAtom, drawLine, numeratorAlignment, denominatorAlignment));
public void PutOver(TexFormula overFormula, TexUnit overUnit, double overSpace, bool overScriptSize) { Formula.RootAtom = new UnderOverAtom(Formula.RootAtom, overFormula?.RootAtom, overUnit, overSpace, overScriptSize, true); }
public void AddRadical(TexFormula baseFormula, string degreeFormula) => AddRadical(baseFormula, FormulaParser.Parse(degreeFormula));
public void AddAccent(TexFormula baseAtom, string accentName) => Add(new AccentedAtom(baseAtom?.RootAtom, accentName));
public void AddRadical(TexFormula baseFormula, TexFormula degreeFormula) => Add(new Radical(baseFormula?.RootAtom, degreeFormula?.RootAtom));
public void AddAccent(TexFormula baseAtom, TexFormula accent) => Add(new AccentedAtom(baseAtom?.RootAtom, accent));
public void AddOperator(TexFormula operatorFormula, TexFormula lowerLimitFormula, TexFormula upperLimitFormula, bool useVerticalLimits) => Add(new BigOperatorAtom(operatorFormula?.RootAtom, lowerLimitFormula?.RootAtom, upperLimitFormula?.RootAtom, useVerticalLimits));
public void AddEmbraced(TexFormula formula, char leftChar, char rightChar) => AddEmbraced(formula, TexFormulaParser.GetDelimeterMapping(leftChar), TexFormulaParser.GetDelimeterMapping(rightChar));
public void AddPhantom(TexFormula phantom, bool useWidth, bool useHeight, bool useDepth) => Add(new PhantomAtom(phantom?.RootAtom, useWidth, useHeight, useDepth));
public void AddEmbraced(TexFormula formula, string leftSymbol, string rightSymbol) => Add(new FencedAtom(formula?.RootAtom, TexFormulaParser.GetDelimiterSymbol(leftSymbol), TexFormulaParser.GetDelimiterSymbol(rightSymbol)));
public abstract bool ProcessUnknownCharacter(TexFormula formula, char character);
public void AddFraction(string numerator, TexFormula denominator, bool drawLine) => AddFraction(FormulaParser.Parse(numerator), denominator, drawLine);
/// <inheritdoc/> public (Stream bitmapStream, string placement, int yoffset, int width96thInch, int height96thInch) Parse(string text, string fontFamily, double fontSize, double dpiResolution, bool isIntendedForHelp1File) { TexFormula formula = null; try { formula = _formulaParser.Parse(text); } catch (Exception) { return(null, null, 0, 0, 0); } double cyAscent; double cyDescent; double cyMiddle; { var gdiFont = new System.Drawing.Font(fontFamily, (float)fontSize, System.Drawing.FontStyle.Regular); int iCellSpace = gdiFont.FontFamily.GetLineSpacing(gdiFont.Style); int iEmHeight = gdiFont.FontFamily.GetEmHeight(gdiFont.Style); int iCellAscent = gdiFont.FontFamily.GetCellAscent(gdiFont.Style); int iCellDescent = gdiFont.FontFamily.GetCellDescent(gdiFont.Style); cyAscent = fontSize * iCellAscent / iEmHeight; cyDescent = fontSize * iCellDescent / iEmHeight; cyMiddle = cyAscent / 3; // is only a first guess, details coming from the Wpf font gdiFont.Dispose(); var ff = new FontFamily(fontFamily); var tf = new Typeface(ff, System.Windows.FontStyles.Normal, System.Windows.FontWeights.Normal, System.Windows.FontStretches.Normal); if (tf.TryGetGlyphTypeface(out var gtf)) { cyMiddle = Math.Floor(fontSize * gtf.Height * gtf.StrikethroughPosition); } } var formulaRenderer = formula.GetRenderer(TexStyle.Display, fontSize, fontFamily); // the placement of the image depends on the depth value var absoluteDepth = formulaRenderer.RenderSize.Height * formulaRenderer.RelativeDepth; var absoluteAscent = formulaRenderer.RenderSize.Height * (1 - formulaRenderer.RelativeDepth); double yoffset = 0; BitmapSource bmp; int width96thInch, height96thInch; string alignment; if (isIntendedForHelp1File) { // dictionary that holds the number of additional pixels neccessary to exactly align the formula, and the value is the alignment var sort = new SortedDictionary <double, (double, string)>(); if (formulaRenderer.RelativeDepth < (1 / 16.0)) // if the formulas baseline is almost at the bottom of the image { sort.Add(0, (0.0, "baseline")); // then we can use baseline as vertical alight } if (absoluteAscent <= cyAscent) // if our formula is higher than the top of the text { yoffset = cyAscent - absoluteAscent; sort.Add(Math.Abs(yoffset), (yoffset, "texttop")); // then we can use texttop alignment, and we shift the formula downwards (positive offset) } if (absoluteDepth <= cyDescent) // then we can use bottom alignment, and we shift the formula upwards (negative offset) { yoffset = absoluteDepth - cyDescent; sort.Add(Math.Abs(yoffset), (yoffset, "bottom")); } { // Alignment: middle // Note that this is a moving target: we must change the vertical size of the image, but by that // we change the middle of the image, which changes again the offset... if (isIntendedForHelp1File) { yoffset = absoluteDepth - absoluteAscent; // in help1 file, the baseline of text is aligned with the middle of the image } else { yoffset = 2 * cyMiddle + absoluteDepth - absoluteAscent; // if yoffset is negative, then pad at the bottom, else pad at the top } sort.Add(Math.Abs(yoffset), (yoffset, "middle")); } var firstEntry = sort.First(); (bmp, width96thInch, height96thInch) = RenderToBitmap(formulaRenderer, 0, firstEntry.Value.Item1, dpiResolution); alignment = firstEntry.Value.Item2; yoffset = 0; // 0 as return value } else // MAML is intended for HTML help (so we can use HTML5 alignment with pixel accuracy ) { alignment = "baseline"; var yshift = Math.Ceiling(absoluteAscent) - absoluteAscent; // we shift the formula downwards, so that the new absoluteAscent is Math.Ceiling(absoluteAscent) // by providing a positive offset in arg2, the image is lowered compared to the baseline (bmp, width96thInch, height96thInch) = RenderToBitmap(formulaRenderer, 0, yshift, dpiResolution); yoffset = Math.Ceiling(absoluteAscent) - height96thInch; // number of pixels from image bottom to baseline (negative sign) } var fileStream = new MemoryStream(); BitmapEncoder encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(bmp)); encoder.Save(fileStream); fileStream.Seek(0, SeekOrigin.Begin); return(fileStream, alignment, (int)Math.Round(yoffset), width96thInch, height96thInch); }
public void AddFraction(TexFormula numerator, string denominator, bool drawLine) => AddFraction(numerator, FormulaParser.Parse(denominator), drawLine);