コード例 #1
0
ファイル: MainWindow.xaml.cs プロジェクト: nenaaki/wpf-math
        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);
        }
コード例 #2
0
        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)));
            }
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
            }
        }
コード例 #5
0
            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);
            }
コード例 #6
0
        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);
        }
コード例 #7
0
ファイル: MathBlockRenderer.cs プロジェクト: olesar/Altaxo
        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);
        }
コード例 #8
0
 public void AddPhantom(TexFormula formula) => Add(new PhantomAtom(formula?.RootAtom));
コード例 #9
0
 public void AddOperator(TexFormula operatorFormula, TexFormula lowerLimitFormula, TexFormula upperLimitFormula) => Add(new BigOperatorAtom(operatorFormula?.RootAtom,
                                                                                                                                            lowerLimitFormula?.RootAtom,
                                                                                                                                            upperLimitFormula?.RootAtom));
コード例 #10
0
 public void AddRadical(TexFormula baseFormula) => AddRadical(baseFormula, (TexFormula)null);
コード例 #11
0
 public void AddRadical(string baseFormula, TexFormula nthRoot) => AddRadical(FormulaParser.Parse(baseFormula), nthRoot);
コード例 #12
0
 public void Add(TexFormula formula) => Formula.Add(formula);
コード例 #13
0
 public TexFormulaHelper(TexFormula formula)
 {
     FormulaParser = new TexFormulaParser();
     Formula       = formula;
 }
コード例 #14
0
 public bool ProcessUnknownCharacter(TexFormula formula, char character) => false;
コード例 #15
0
        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));
            }
        }
コード例 #16
0
 public void AddFraction(TexFormula numerator, TexFormula denominator, bool drawLine) => Add(new FractionAtom(numerator?.RootAtom,
                                                                                                              denominator?.RootAtom, drawLine));
コード例 #17
0
 public void AddFraction(TexFormula numerator, TexFormula denominator, bool drawLine,
                         TexAlignment numeratorAlignment, TexAlignment denominatorAlignment) => Add(new FractionAtom(numerator?.RootAtom,
                                                                                                                     denominator?.RootAtom, drawLine, numeratorAlignment, denominatorAlignment));
コード例 #18
0
 public void PutOver(TexFormula overFormula, TexUnit overUnit, double overSpace, bool overScriptSize)
 {
     Formula.RootAtom = new UnderOverAtom(Formula.RootAtom,
                                          overFormula?.RootAtom, overUnit, overSpace, overScriptSize, true);
 }
コード例 #19
0
 public void AddRadical(TexFormula baseFormula, string degreeFormula) => AddRadical(baseFormula, FormulaParser.Parse(degreeFormula));
コード例 #20
0
 public void AddAccent(TexFormula baseAtom, string accentName) => Add(new AccentedAtom(baseAtom?.RootAtom, accentName));
コード例 #21
0
 public void AddRadical(TexFormula baseFormula, TexFormula degreeFormula) => Add(new Radical(baseFormula?.RootAtom,
                                                                                             degreeFormula?.RootAtom));
コード例 #22
0
 public void AddAccent(TexFormula baseAtom, TexFormula accent) => Add(new AccentedAtom(baseAtom?.RootAtom, accent));
コード例 #23
0
 public void AddOperator(TexFormula operatorFormula, TexFormula lowerLimitFormula, TexFormula upperLimitFormula,
                         bool useVerticalLimits) => Add(new BigOperatorAtom(operatorFormula?.RootAtom,
                                                                            lowerLimitFormula?.RootAtom,
                                                                            upperLimitFormula?.RootAtom, useVerticalLimits));
コード例 #24
0
 public void AddEmbraced(TexFormula formula, char leftChar, char rightChar) =>
 AddEmbraced(formula, TexFormulaParser.GetDelimeterMapping(leftChar), TexFormulaParser.GetDelimeterMapping(rightChar));
コード例 #25
0
 public void AddPhantom(TexFormula phantom, bool useWidth, bool useHeight, bool useDepth) => Add(new PhantomAtom(phantom?.RootAtom, useWidth, useHeight, useDepth));
コード例 #26
0
 public void AddEmbraced(TexFormula formula, string leftSymbol, string rightSymbol) => Add(new FencedAtom(formula?.RootAtom, TexFormulaParser.GetDelimiterSymbol(leftSymbol),
                                                                                                          TexFormulaParser.GetDelimiterSymbol(rightSymbol)));
コード例 #27
0
 public abstract bool ProcessUnknownCharacter(TexFormula formula, char character);
コード例 #28
0
 public void AddFraction(string numerator, TexFormula denominator, bool drawLine) => AddFraction(FormulaParser.Parse(numerator), denominator, drawLine);
コード例 #29
0
        /// <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);
        }
コード例 #30
0
 public void AddFraction(TexFormula numerator, string denominator, bool drawLine) => AddFraction(numerator, FormulaParser.Parse(denominator), drawLine);