private void Parse_MouseDown(object sender, MouseButtonEventArgs e) { canvasString = InputTextBox.Text; canvasString = canvasString.Replace(" ", ""); if (canvasString == "") { imageCanvas.Source = null; return; } if (ParseFormula()) { imageCanvas.Source = null; return; } TexFormula formula = Parse_Formula(canvasString); if (formula == null) { return; } TexRenderer renderer = formula.GetRenderer(TexStyle.Display, 20.0, "Arial"); savePng = renderer.RenderToBitmap(0.0, 0.0); imageCanvas.Source = savePng; }
private void Render() { // Create formula object from input text. if (texFormula == null) { formulaContainerElement.Visual = null; return; } // Render formula to visual. var visual = new DrawingVisual(); var renderer = texFormula.GetRenderer(TexStyle.Display, Scale); using (var drawingContext = visual.RenderOpen()) { renderer.Render(drawingContext, 0, 0); } formulaContainerElement.Visual = visual; }
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); } }
/// <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); }
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); }
private static Table genFormulaeTable(List <Formula> formulae, MainDocumentPart mainPart) { Table tableOfInputs = new Table(); var tableGrid = new TableGrid(); tableGrid.AppendChild(new GridColumn()); tableGrid.AppendChild(new GridColumn()); tableGrid.AppendChild(new GridColumn()); tableOfInputs.AppendChild(tableGrid); var tableProps = new TableProperties(); tableProps.AppendChild(new TableLayout() { Type = TableLayoutValues.Fixed }); tableProps.AppendChild(new TableWidth() { Width = "9000", Type = TableWidthUnitValues.Dxa }); tableProps.AppendChild(new TableBorders() { InsideHorizontalBorder = new InsideHorizontalBorder() { Color = "c0c0c0", Size = 4, Val = BorderValues.Single } }); tableProps.AppendChild(new TableBorders() { BottomBorder = new BottomBorder() { Color = "c0c0c0", Size = 4, Val = BorderValues.Single } }); tableProps.AppendChild(new TableBorders() { TopBorder = new TopBorder() { Color = "c0c0c0", Size = 4, Val = BorderValues.Single } }); //tableProps.AppendChild(new TableBorders() { LeftBorder = new LeftBorder() { Color = "c0c0c0", Size = 4, Val = BorderValues.Single } }); //tableProps.AppendChild(new TableBorders() { InsideVerticalBorder = new InsideVerticalBorder() { Color = "c0c0c0", Size = 4, Val = BorderValues.Single } }); //tableProps.AppendChild(new TableBorders() { RightBorder = new RightBorder() { Color = "c0c0c0", Size = 4, Val = BorderValues.Single } }); tableOfInputs.AppendChild(tableProps); foreach (var item in formulae) { TableRow row = new TableRow(); var para = new Paragraph(); para.AppendChild((new Run(new Text(item.Ref)))); TableCell cell1 = new TableCell(); cell1.Append(para); cell1.Append(new TableCellProperties(new TableCellWidth() { Type = TableWidthUnitValues.Dxa, Width = "1200" })); TableCell cell2 = new TableCell(); cell2.Append(new TableCellProperties(new TableCellWidth() { Type = TableWidthUnitValues.Dxa, Width = "6100" })); cell2.AppendChild(new Paragraph(new Run(new Text(item.Narrative)))); //foreach (var formula in item.Expression) //{ // var mathPara = new Paragraph(); // var myMath = new M.OfficeMath(new M.Run(new M.Text(formula + Environment.NewLine) { Space = SpaceProcessingModeValues.Preserve })); // mathPara.AppendChild(myMath); // mathPara.AppendChild(new Run(new Text(" ") { Space = SpaceProcessingModeValues.Preserve })); // cell2.AppendChild(mathPara); //} foreach (var formula in item.Expression) { if (formula != "") { TexFormula formulaToParse = new TexFormula(); try { var parser = new TexFormulaParser(); formulaToParse = parser.Parse(formula); } catch (Exception) { var parser = new TexFormulaParser(); formulaToParse = parser.Parse("Error in LaTeX string..."); } var test = formulaToParse.GetRenderer(TexStyle.Script, 100, "Franklin Gothic Book"); if (test.RenderSize.Width > 0 && test.RenderSize.Height > 0) { var formulaImage = formulaToParse.RenderToPng(100, 0, 0, "Franklin Gothic Book"); ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Png); using (var stream = new MemoryStream(formulaImage)) { imagePart.FeedData(stream); var img = new BitmapImage(); img.BeginInit(); img.StreamSource = stream; img.CacheOption = BitmapCacheOption.OnLoad; img.EndInit(); img.Freeze(); var paraImage = AddImageToBody(mainPart.GetIdOfPart(imagePart), img.Width * 2.54 / 600, img.Height * 2.54 / 600); cell2.AppendChild(new Paragraph(new Run(paraImage))); } } GC.WaitForPendingFinalizers(); } //var myMath = new M.OfficeMath(new M.Run(new M.Text(formula + Environment.NewLine) { Space = SpaceProcessingModeValues.Preserve })); //mathPara.AppendChild(myMath); //mathPara.AppendChild(new Run(new Text(" ") { Space = SpaceProcessingModeValues.Preserve })); //cell2.AppendChild(mathPara); } if (item.Image != null) { ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Png); var tempFile = Path.GetTempFileName(); PngBitmapEncoder png = new PngBitmapEncoder(); //CHANGEBITMAP //png.Frames.Add(BitmapFrame.Create(item.Image)); var width = Math.Min(10d, item.Image.Width * 2.54 / 96); var height = ((double)item.Image.Height / (double)item.Image.Width) * width; using (SkiaSharp.SKWStream stm = new SkiaSharp.SKFileWStream(tempFile)) { item.Image.Encode(stm, SkiaSharp.SKEncodedImageFormat.Png, 0); } using (FileStream stream = new FileStream(tempFile, FileMode.Open)) { imagePart.FeedData(stream); } var paraImage = AddImageToBody(mainPart.GetIdOfPart(imagePart), width, height); cell2.AppendChild(new Paragraph(new Run(paraImage))); } TableCell cell3 = new TableCell(); cell3.Append(new Paragraph(new Run(new Text(item.Conclusion)))); cell3.Append(new TableCellProperties(new TableCellWidth() { Type = TableWidthUnitValues.Dxa, Width = "1700" })); row.Append(cell1, cell2, cell3); tableOfInputs.AppendChild(row); } return(tableOfInputs); }