using DocumentFormat.OpenXml.Drawing; using DocumentFormat.OpenXml.Math; using HTEXLib.Helpers.ShapeHelpers; using HTEXLib.Models.Inner; using HTEXLib.Models.PPTX; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Xml; using System.Xml.Linq; using System.Xml.Xsl; namespace HTEXLib.Models.HTEX { public class HtexMath: HtexElement { public PPTMath pptMath { get; set; } // public double Rotate { get; set; } public string HyperLink { get; set; } private int slideIndex; public HtexMath(string id, double rot, double width, double height, double top, double left, bool invisible, bool animatable, int slideIndex, int index, PPTMath shape, PPTSlide slide, string partForm) { base.slide = slide; this.rot = rot; this.pptMath = shape; base.id = id; base.top = top; base.left = left; base.width = width; base.height = height; base.invisible = invisible; base.animatable = animatable; this.slideIndex = slideIndex; base.index = index; base.type = "Math"; base.partForm = partForm; } public override List DrawElement() { Position position = new Position { cx = width, cy = height, x = left, y = top, rot = rot }; var ShapeStyle = PPTXHelper.DoShapeProperties(pptMath.element.ShapeProperties, slide, type, partForm); var shapeTypeNode = pptMath.element.ShapeProperties.GetFirstChild(); Math math = new Math { type = type, index = index, animatable = animatable, invisible = invisible }; math.style.position = position; SlideColor slideColor = PPTXHelper.DoShapeStyle(pptMath.element.ShapeStyle, slide, type); //从ShapeProperties 获取 p:spPr //再从 ShapeStyle 获取 p:spPr if (ShapeStyle.border == null || ShapeStyle.border.color == null || ShapeStyle.border.color.type == -1) { if (slideColor != null) { math.style.border.color.solidFill = slideColor.LineColor; math.style.border.color.type = 2; } } else { math.style.border = ShapeStyle.border; } if (ShapeStyle.fill == null || ShapeStyle.fill.type == -1) { if (slideColor != null) { math.style.fill.solidFill = slideColor.FillColor; math.style.fill.type = 2; } } else { math.style.fill = ShapeStyle.fill; } if (shapeTypeNode != null && shapeTypeNode.Preset != null && !string.IsNullOrEmpty(shapeTypeNode.Preset.InnerText)) { var shapeType = shapeTypeNode.Preset.InnerText; Svg svg = PPTXSvg.GenShapeSvg(pptMath.element, index, shapeType, position, math.style.border); math.svg = svg; math.shapeType = shapeType; } var AlternateContentChoice= pptMath.AlternateContentChoice; var shp = AlternateContentChoice.GetFirstChild(); var Paragraphs = shp.TextBody.Elements(); foreach (var pa in Paragraphs) { // OfficeMath ///公式插入 线性 专用,普通文本区别 var oMath = shp.GetTextByPath("//p:txBody/a:p/a14:m/m:oMathPara/m:oMath"); double pitchFamily = 18.0; string typeface = ""; OfficeMath officeMath = new OfficeMath(oMath.ToString()); var rRr = oMath.GetTextByPath("//a:rPr"); if (rRr != null) { var TextCharacterPropertiesType = new DocumentFormat.OpenXml.Drawing.RunProperties(rRr.ToString()); if (TextCharacterPropertiesType != null) { //TODO 计算拿到的相关属性的个数,遵循多数的样式。 /* .Outline .NoFill .SolidFill .GradientFill .BlipFill .PatternFill .GroupFill .EffectList .EffectDag .Highlight .UnderlineFollowsText .Underline .UnderlineFillText .UnderlineFill .LatinFont .EastAsianFont .ComplexScriptFont .SymbolFont .HyperlinkOnClick .HyperlinkOnMouseOver .RightToLeft */ LatinFont LatinFont = TextCharacterPropertiesType.GetFirstChild(); if (LatinFont != null) { pitchFamily = LatinFont.PitchFamily.Value; typeface = LatinFont.Typeface.Value; } } } var els = XElement.Parse(officeMath.OuterXml); UTF32Encoding encoding = new UTF32Encoding(); Dictionary dict = new Dictionary(); DoXml(els, dict,encoding); els = ProcessOMath(els); DoMathXml(els,dict,encoding); var mathML = els.ToString(); math.mathML=new MathML { formula=mathML,typeface=typeface,pitchFamily=pitchFamily}; } var AlternateContentFallback= pptMath.AlternateContentFallback; if (AlternateContentFallback.ChildElements.First() is DocumentFormat.OpenXml.Presentation.Shape shapea) { PPTShape baseShape = new PPTShape(slide.SlidePart, shapea, slide); double left = baseShape.VisualShapeProp.Left(); double width = baseShape.VisualShapeProp.PixelWidth(); double top = baseShape.VisualShapeProp.Top(); double height = baseShape.VisualShapeProp.PixelHeight(); double rot = baseShape.VisualShapeProp.Rotate; string Id = baseShape.NonVisualShapeProp.Id; bool invisible = baseShape.Invisible; bool animatable = baseShape.Animatable; string clickLinkUrl = baseShape.ClickLinkUrl; HtexShape htmlShape = new HtexShape(Id, rot, width, height, top, left, invisible, animatable, slideIndex, index, baseShape, slide, baseShape.PartForm) { Shape = baseShape, //rot = baseShape.VisualShapeProp.Rotate, HyperLink = clickLinkUrl }; var elmt= htmlShape.DrawElement(); if (elmt != null && elmt.Count > 0) { math.back = elmt[0]; } } math.uid = pptMath.suid; return new List { math }; } /// /// 处理xml 中的非ASCII编码的特殊公式字符 /// /// public void DoXml(XElement element,Dictionary Replace, UTF32Encoding encoding ) { foreach (var elm in element.Elements()) { var child = elm.Elements().ToList(); if (child != null && child.Count > 0) { DoXml(elm,Replace, encoding); } else { if (!string.IsNullOrEmpty(elm.Value)) { // //Byte[] encodedBytes = encoding.GetBytes(a); //string ad = encoding.GetString(encodedBytes, 0, 4); string em = elm.Value; List chars = new List(); Byte[] encodedBytes = encoding.GetBytes(em); if (encodedBytes != null) { var len = encodedBytes.Length/4; for (int i = 0; i < len; i++) { string od= encoding.GetString(encodedBytes, i * 4, 4); if (CharHelper.MathChar.TryGetValue(od, out string ne)) { em = em.Replace(od, ne); Replace[ne] = od; } } } // var keys = CharHelper.MathChar.Keys; // foreach (string key in keys) // { // em = em.Replace(key, CharHelper.MathChar[key]); // } elm.Value = em; elm.ReplaceWith(elm); } } } }/// /// 处理xml 中的非ASCII编码的特殊公式字符 /// /// public void DoMathXml(XElement element, Dictionary Replace, UTF32Encoding encoding) { foreach (var elm in element.Elements()) { var child = elm.Elements().ToList(); if (child != null && child.Count > 0) { DoMathXml(elm, Replace, encoding); } else { if (!string.IsNullOrEmpty(elm.Value)) { // //Byte[] encodedBytes = encoding.GetBytes(a); //string ad = encoding.GetString(encodedBytes, 0, 4); string em = elm.Value; List chars = new List(); Byte[] encodedBytes = encoding.GetBytes(em); if (encodedBytes != null) { var len = encodedBytes.Length / 4; for (int i = 0; i < len; i++) { string od = encoding.GetString(encodedBytes, i * 4, 4); if (Replace.TryGetValue(od, out string ne)) { em = em.Replace(od, ne); } } } // var keys = CharHelper.MathChar.Keys; // foreach (string key in keys) // { // em = em.Replace(key, CharHelper.MathChar[key]); // } elm.Value = em; elm.ReplaceWith(elm); } } } } public XElement ProcessOMath(XElement element) { XmlReader OMML2MML = XmlReader.Create( new StringReader(Globals.OMML2MML)); XslCompiledTransform xslTransform = new XslCompiledTransform(); xslTransform.Load(OMML2MML); // xslTransform.Load("F:\\OMML2MML.XSL"); string mathXml = element.ToString(); string officeML = string.Empty; using (TextReader tr = new StringReader(mathXml)) { using (XmlReader reader = XmlReader.Create(tr)) { using (MemoryStream ms = new MemoryStream()) { XmlWriterSettings settings = xslTransform.OutputSettings.Clone(); settings.ConformanceLevel = ConformanceLevel.Fragment; settings.OmitXmlDeclaration = true; XmlWriter xw = XmlWriter.Create(ms, settings); xslTransform.Transform(reader, xw); ms.Seek(0, SeekOrigin.Begin); using (StreamReader sr = new StreamReader(ms, Encoding.UTF8)) { officeML = sr.ReadToEnd(); // Console.Out.WriteLine(officeML); } } } } officeML = officeML.Replace("mml:", ""); XElement officeElement = XElement.Load(new StringReader(officeML)); return officeElement; } } }