ShapeGenerator.cs 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174
  1. using DocumentFormat.OpenXml.Packaging;
  2. using HiTeachCC.Model.PowerPoint;
  3. using HiTeachCC.Service.PowerPoint.Interface;
  4. using Microsoft.AspNetCore.Http;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.IO;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. using System.Xml;
  11. using System.Xml.Linq;
  12. using TEAMModelOS.SDK.Context.Constant;
  13. using TEAMModelOS.SDK.Context.Constant.Common;
  14. using TEAMModelOS.SDK.Context.Exception;
  15. using TEAMModelOS.SDK.Helper.Security.ShaHash;
  16. using TEAMModelOS.SDK.Module.AzureBlob.Container;
  17. using TEAMModelOS.SDK.Module.AzureBlob.Interfaces;
  18. using TEAMModelOS.Service.Models.PowerPoint.Inner;
  19. using TEAMModelOS.Service.Services.PowerPoint.Implement;
  20. using Fill = HiTeachCC.Model.PowerPoint.Fill;
  21. using Media = HiTeachCC.Model.PowerPoint.Media;
  22. using Position = HiTeachCC.Model.PowerPoint.Position;
  23. namespace HiTeachCC.Service.PowerPoint.Implement
  24. {
  25. public class ShapeGenerator : IShapeGenerator
  26. {
  27. private string fileShaCode { get; set; }
  28. private bool isDone = false;
  29. private List<object> MsgQueue = new List<object>();
  30. private Dictionary<string, string> slideLayoutClrOvride { get; set; }
  31. // private XmlNode themeContent { get; set; }
  32. private int chartID = 0;
  33. private int _order = 1;
  34. private int titleFontSize = 42;
  35. private int bodyFontSize = 20;
  36. private int otherFontSize = 16;
  37. private bool isSlideMode = false;
  38. private Dictionary<string, Dictionary<string, string>> styleTable = new Dictionary<string, Dictionary<string, string>>();
  39. private const double px96 = 96.00, px72 = 72.00, px914400 = 914400.00, px12700 = 12700.00;
  40. private const double rot60000 = 60000.00;
  41. public readonly IAzureBlobDBRepository azureBlobDBRepository;
  42. public ShapeGenerator(IAzureBlobDBRepository _azureBlobDBRepository)
  43. {
  44. azureBlobDBRepository = _azureBlobDBRepository;
  45. }
  46. public async Task<Dictionary<string, object>> LoadPresentation(IFormFile file)
  47. {
  48. Dictionary<string, object> resdict = new Dictionary<string, object>();
  49. if (FileType.GetExtention(file.FileName).ToLower().Equals("pptx"))
  50. {
  51. await ConvertPPTX(file, resdict);
  52. return resdict;
  53. }
  54. else if (FileType.GetExtention(file.FileName).ToLower().Equals("pdf"))
  55. {
  56. // await ProcessPDF(file, resdict);
  57. return resdict;
  58. }
  59. else
  60. {
  61. throw new BizException("file type does not support!", 500);
  62. }
  63. }
  64. public async Task<Dictionary<string, object>> ConvertPPTX(IFormFile file, Dictionary<string, object> resdict)
  65. {
  66. string shaCode = fileShaCode = ShaHashHelper.GetSHA1(file.OpenReadStream());
  67. PresentationDocument presentationDocument = PresentationDocument.Open(file.OpenReadStream(), false);
  68. if (presentationDocument == null)
  69. {
  70. throw new ArgumentNullException("presentationDocument");
  71. }
  72. XDocument xdoc = presentationDocument.ToFlatOpcDocument();
  73. XmlDocument xmlDocument = new XmlDocument();
  74. xmlDocument.LoadXml(xdoc.ToString());
  75. var rslt_ary = await ProcessPPTX(xmlDocument, shaCode);
  76. //TODO
  77. return null;
  78. }
  79. /// <summary>
  80. /// 加载PPTX文件
  81. /// </summary>
  82. /// <param name="presentationFile"></param>
  83. /// <returns></returns>
  84. public async Task<List<Dictionary<string, object>>> ProcessPPTX(XmlDocument xdoc, string shaCode)
  85. {
  86. List<Dictionary<string, object>> post_ary = new List<Dictionary<string, object>>();
  87. var dateBefore = DateTimeOffset.Now.UtcTicks;
  88. AzureBlobModel thumbnailModel = await GetThumbnailModel(xdoc, shaCode);
  89. post_ary.Add(new Dictionary<string, object> { { "pptx-thumb", thumbnailModel } });
  90. //获取全部的/ppt/slides/slide1.xml--->>/ppt/slides/slide(n).xml
  91. var slideNodes = xdoc.GetTextByPathList("//pkg:part[@pkg:contentType='application/vnd.openxmlformats-officedocument.presentationml.slide+xml']");
  92. //获取全部的/ppt/slideLayouts/slideLayout1.xml--->>/ppt/slideLayouts/slideLayout(n).xml
  93. var slideLayoutNodes = xdoc.GetTextByPathList("//pkg:part[@pkg:contentType='application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml']");
  94. //获取ppt的宽高
  95. var slideSize = ShapeHelper.GetSlideSize(xdoc);
  96. post_ary.Add(new Dictionary<string, object> { { "slideSize", slideSize } });
  97. //加载当前PPT使用到的PPT节点
  98. var themeContent = LoadTheme(xdoc);
  99. //获取所有的表格样式节点
  100. var tableStyles = xdoc.GetTextByPath("//pkg:part[@pkg:name='/ppt/tableStyles.xml']/pkg:xmlData/a:tblStyleLst");
  101. //处理slide1---slide(n)
  102. int numOfSlides = slideNodes.Count;
  103. for (int i = 0; i < numOfSlides; i++)
  104. {
  105. string filename = slideNodes[i].GetTextByPath("@pkg:name").Value;
  106. //处理当前页的幻灯片
  107. string slideHtml = await ProcessSingleSlide(xdoc, slideNodes[i], filename, i, slideSize, themeContent);
  108. post_ary.Add(new Dictionary<string, object> { { "slide", slideHtml } });
  109. post_ary.Add(new Dictionary<string, object> { { "progress-update", (i + 1) * 100 / numOfSlides } });
  110. }
  111. post_ary.Add(new Dictionary<string, object> { { "globalCSS", GenGlobalCSS() } });
  112. var dateAfter = DateTimeOffset.Now.UtcTicks;
  113. post_ary.Add(new Dictionary<string, object> { { "ExecutionTime", dateAfter - dateBefore } });
  114. return post_ary;
  115. }
  116. public Dictionary<string, string> GenGlobalCSS()
  117. {
  118. Dictionary<string, string> cssText = new Dictionary<string, string>();
  119. foreach (var key in styleTable.Keys)
  120. {
  121. // cssText += "div ." + styleTable[key]["name"] + "{" + styleTable[key]["text"] + "}\n"; //section > div
  122. var cssTextKey = styleTable[key]["name"];
  123. var cssTextValue = styleTable[key]["text"];
  124. cssText.Add(cssTextKey, cssTextValue);
  125. }
  126. return cssText;
  127. }
  128. public async Task<string> ProcessSingleSlide(XmlDocument xdoc, XmlNode xnode, string sldFileName, int index, dynamic slideSize, XmlNode themeContent)
  129. {
  130. var resName = sldFileName.Replace("slides/slide", "slides/_rels/slide") + ".rels";
  131. var RelationshipArray = xdoc.GetTextByPathList("//pkg:part[@pkg:name='" + resName + "']/pkg:xmlData/rel:Relationships/rel:Relationship");
  132. Dictionary<string, Dictionary<string, string>> slideResObj = new Dictionary<string, Dictionary<string, string>>();
  133. var layoutFilename = "";
  134. foreach (XmlNode Relationship in RelationshipArray)
  135. {
  136. var RelationshipType = Relationship.GetTextByPath("@Type");
  137. if (RelationshipType.Value.Equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"))
  138. {
  139. layoutFilename = Relationship.GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  140. }
  141. else
  142. {
  143. //case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide":
  144. //case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image":
  145. //case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart":
  146. //case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink":
  147. Dictionary<string, string> dict = new Dictionary<string, string>();
  148. string Type = Relationship.GetTextByPath("@Type").Value.Replace("http://schemas.openxmlformats.org/officeDocument/2006/relationships/", "");
  149. string Target = Relationship.GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  150. string Id = Relationship.GetTextByPath("@Id").Value;
  151. dict.Add("type", Type);
  152. dict.Add("target", Target);
  153. slideResObj.Add(Id, dict);
  154. }
  155. }
  156. // Open slideLayoutXX.xml
  157. var slideLayoutContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + layoutFilename + "']");
  158. NodesTable slideLayoutTables = ShapeHelper.IndexNodes(slideLayoutContent.GetTextByPath("pkg:xmlData/p:sldLayout"));
  159. ///ppt/slides/slide5.xml 也包含a:overrideClrMapping
  160. ////ppt/slideLayouts/slideLayout13.xml 也包含a:overrideClrMapping
  161. var sldLayoutClrOvr = slideLayoutContent.GetTextByPath("pkg:xmlData/p:sldLayout/p:clrMapOvr/a:overrideClrMapping");
  162. if (sldLayoutClrOvr != null)
  163. {
  164. //获取 overrideClrMapping所有属性节点
  165. slideLayoutClrOvride = new Dictionary<string, string>() {
  166. { "accent1", sldLayoutClrOvr.GetTextByPath("@accent1").Value},
  167. { "accent2", sldLayoutClrOvr.GetTextByPath("@accent2").Value},
  168. { "accent3", sldLayoutClrOvr.GetTextByPath("@accent3").Value},
  169. { "accent4", sldLayoutClrOvr.GetTextByPath("@accent4").Value},
  170. { "accent5", sldLayoutClrOvr.GetTextByPath("@accent5").Value},
  171. { "accent6", sldLayoutClrOvr.GetTextByPath("@accent6").Value},
  172. { "bg1", sldLayoutClrOvr.GetTextByPath("@bg1").Value},
  173. { "bg2", sldLayoutClrOvr.GetTextByPath("@bg2").Value},
  174. { "folHlink", sldLayoutClrOvr.GetTextByPath("@folHlink").Value},
  175. { "hlink", sldLayoutClrOvr.GetTextByPath("@hlink").Value},
  176. { "tx1", sldLayoutClrOvr.GetTextByPath("@tx1").Value},
  177. { "tx2", sldLayoutClrOvr.GetTextByPath("@tx2").Value}
  178. };
  179. }
  180. // =====< Step 2 >=====
  181. // Read slide master filename of the slidelayout (Get slideMasterXX.xml)
  182. // @resName: ppt/slideLayouts/slideLayout1.xml
  183. // @masterName: ppt/slideLayouts/_rels/slideLayout1.xml.rels
  184. var slideLayoutResFilename = layoutFilename.Replace("slideLayouts/slideLayout", "slideLayouts/_rels/slideLayout") + ".rels";
  185. var slideLayoutResContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + slideLayoutResFilename + "']");
  186. ///查看js 是替换之前 还是添加
  187. RelationshipArray = slideLayoutResContent.GetTextByPathList("pkg:xmlData/rel:Relationships/rel:Relationship");
  188. var masterFilename = "";
  189. Dictionary<string, Dictionary<string, string>> layoutResObj = new Dictionary<string, Dictionary<string, string>>();
  190. for (int i = 0; i < RelationshipArray.Count; i++)
  191. {
  192. if (RelationshipArray[i].GetTextByPath("@Type").Value.Equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster"))
  193. {
  194. masterFilename = RelationshipArray[i].GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  195. }
  196. else
  197. {
  198. Dictionary<string, string> dict = new Dictionary<string, string>();
  199. string Type = RelationshipArray[i].GetTextByPath("@Type").Value.Replace("http://schemas.openxmlformats.org/officeDocument/2006/relationships/", "");
  200. string Target = RelationshipArray[i].GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  201. string Id = RelationshipArray[i].GetTextByPath("@Id").Value;
  202. dict.Add("type", Type);
  203. dict.Add("target", Target);
  204. layoutResObj.Add(Id, dict);
  205. }
  206. }
  207. // Open slideMasterXX.xml
  208. var slideMasterContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + masterFilename + "']");
  209. var slideMasterTextStyles = slideMasterContent.GetTextByPath("pkg:xmlData/p:sldMaster/p:txStyles");
  210. var slideMasterTables = ShapeHelper.IndexNodes(slideMasterContent.GetTextByPath("pkg:xmlData/p:sldMaster"));
  211. /////////////////Amir/////////////
  212. //Open slideMasterXX.xml.rels
  213. var slideMasterResFilename = masterFilename.Replace("slideMasters/slideMaster", "slideMasters/_rels/slideMaster") + ".rels";
  214. var slideMasterResContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + slideMasterResFilename + "']");
  215. RelationshipArray = slideMasterResContent.GetTextByPathList("pkg:xmlData/rel:Relationships/rel:Relationship");
  216. var themeFilename = "";
  217. Dictionary<string, Dictionary<string, string>> masterResObj = new Dictionary<string, Dictionary<string, string>>();
  218. for (int i = 0; i < RelationshipArray.Count; i++)
  219. {
  220. if (RelationshipArray[i].GetTextByPath("@Type").Value.Equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"))
  221. {
  222. themeFilename = RelationshipArray[i].GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  223. }
  224. else
  225. {
  226. Dictionary<string, string> dict = new Dictionary<string, string>();
  227. string Type = RelationshipArray[i].GetTextByPath("@Type").Value.Replace("http://schemas.openxmlformats.org/officeDocument/2006/relationships/", "");
  228. string Target = RelationshipArray[i].GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  229. string Id = RelationshipArray[i].GetTextByPath("@Id").Value;
  230. dict.Add("type", Type);
  231. dict.Add("target", Target);
  232. masterResObj.Add(Id, dict);
  233. }
  234. }
  235. //Load Theme file
  236. if (!string.IsNullOrEmpty(themeFilename))
  237. {
  238. themeContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + themeFilename + "']");
  239. }
  240. // =====< Step 3 >===== throw new NotImplementedException();
  241. var slideContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + sldFileName + "']");
  242. var spTreeNode = slideContent.GetTextByPath("pkg:xmlData/p:sld/p:cSld/p:spTree");
  243. WarpObj warpObj = new WarpObj
  244. {
  245. zip = xdoc,
  246. slideLayoutTables = slideLayoutTables,
  247. slideMasterTables = slideMasterTables,
  248. slideMasterTextStyles = slideMasterTextStyles,
  249. slideResObj = slideResObj,
  250. layoutResObj = layoutResObj,
  251. masterResObj = masterResObj,
  252. slideLayoutContent = slideLayoutContent,
  253. slideMasterContent = slideMasterContent,
  254. themeContent = themeContent
  255. };
  256. var bgColor = GetSlideBackgroundFill(slideContent, index, warpObj);
  257. string result = "<div class='slide' style='width:" + slideSize.width + "px; height:" + slideSize.height + "px;" + bgColor + "'>";
  258. //result += "<div>"+getBackgroundShapes(slideContent, slideLayoutContent, slideMasterContent,warpObj) + "</div>" - TODO
  259. if (spTreeNode != null)
  260. {
  261. var nodes = spTreeNode.ChildNodes;
  262. int order = 1;
  263. foreach (XmlNode node in nodes)
  264. {
  265. result += await ProcessNodesInSlide(node.Name, node, order, warpObj);
  266. order += 1;
  267. }
  268. }
  269. return result;
  270. }
  271. public async Task<string> ProcessNodesInSlide(string nodeKey, XmlNode node, int order, WarpObj warpObj)
  272. {
  273. string result = "";
  274. switch (nodeKey)
  275. {
  276. case "p:sp": // Shape, Text
  277. result = await ProcessSpNode(node, order, warpObj);
  278. break;
  279. case "p:cxnSp": // Shape, Text (with connection)
  280. result = await ProcessCxnSpNode(node, order, warpObj);
  281. break;
  282. case "p:pic": // Picture
  283. await ProcessPicNode(node, order, warpObj);
  284. break;
  285. case "p:graphicFrame": // Chart, Diagram, Table
  286. result = ProcessGraphicFrameNode(node, order, warpObj);
  287. break;
  288. case "p:grpSp":
  289. await ProcessGroupSpNode(node, order, warpObj);
  290. break;
  291. case "mc:AlternateContent": //Equations and formulas as Image 处理公式 方程等
  292. var mcFallbackNode = node.GetTextByPath("mc:Fallback/p:sp");
  293. result = await ProcessSpNode(mcFallbackNode, order, warpObj);
  294. break;
  295. default:
  296. break;
  297. }
  298. return result;
  299. }
  300. public async Task<string> ProcessGroupSpNode(XmlNode node, int order, WarpObj warpObj)
  301. {
  302. var factor = 1.00 * px96 / px914400;
  303. var xfrmNode = node.GetTextByPath("p:grpSpPr/a:xfrm");
  304. var x = int.Parse(xfrmNode.GetTextByPath("a:off/@x").Value) * factor;
  305. var y = int.Parse(xfrmNode.GetTextByPath("a:off/@y").Value) * factor;
  306. var chx = int.Parse(xfrmNode.GetTextByPath("a:chOff/@x").Value) * factor;
  307. var chy = int.Parse(xfrmNode.GetTextByPath("a:chOff/@y").Value) * factor;
  308. var cx = int.Parse(xfrmNode.GetTextByPath("a:ext/@cx").Value) * factor;
  309. var cy = int.Parse(xfrmNode.GetTextByPath("a:ext/@cy").Value) * factor;
  310. var chcx = int.Parse(xfrmNode.GetTextByPath("a:chExt/@cx").Value) * factor;
  311. var chcy = int.Parse(xfrmNode.GetTextByPath("a:chExt/@cy").Value) * factor;
  312. string result = "<div class='block group' style='z-index: " + order + "; top: " + (y - chy) + "px; left: " + (x - chx) + "px; width: " + (cx - chcx) + "px; height: " + (cy - chcy) + "px;'>";
  313. // Procsee all child nodes
  314. var nodes = node.ChildNodes;
  315. foreach (XmlNode nd in nodes)
  316. {
  317. result += await ProcessNodesInSlide(nd.Name, nd, order, warpObj);
  318. order += 1;
  319. }
  320. result += "</div>";
  321. return result;
  322. }
  323. public string ProcessGraphicFrameNode(XmlNode node, int order, WarpObj warpObj)
  324. {
  325. var result = "";
  326. var graphicTypeUri = node.GetTextByPath("a:graphic/a:graphicData/uri");
  327. if (graphicTypeUri != null)
  328. {
  329. switch (graphicTypeUri.Value)
  330. {
  331. case "http://schemas.openxmlformats.org/drawingml/2006/table":
  332. result = GenTable(node, warpObj);
  333. break;
  334. case "http://schemas.openxmlformats.org/drawingml/2006/chart":
  335. result = GenChart(node, warpObj);
  336. break;
  337. case "http://schemas.openxmlformats.org/drawingml/2006/diagram":
  338. result = GenDiagram(node, warpObj);
  339. break;
  340. default:
  341. break;
  342. }
  343. }
  344. return result;
  345. }
  346. public string GenDiagram(XmlNode node, WarpObj warpObj)
  347. {
  348. return "";
  349. }
  350. public string GenChart(XmlNode node, WarpObj warpObj)
  351. {
  352. return "";
  353. }
  354. public string GenTable(XmlNode node, WarpObj warpObj)
  355. {
  356. return "";
  357. }
  358. public async Task<string> ProcessCxnSpNode(XmlNode node, int order, WarpObj warpObj)
  359. {
  360. var id = node.GetTextByPath("p:nvCxnSpPr/p:cNvPr/@id");
  361. var name = node.GetTextByPath("p:nvCxnSpPr/p:cNvPr/@name");
  362. return await GenShape(node, null, null, id, name, null, null, order, warpObj);
  363. }
  364. public async Task<string> ProcessSpNode(XmlNode node, int order, WarpObj warpObj)
  365. {
  366. /*
  367. * 958 <xsd:complexType name="CT_GvmlShape">
  368. * 959 <xsd:sequence>
  369. * 960 <xsd:element name="nvSpPr" type="CT_GvmlShapeNonVisual" minOccurs="1" maxOccurs="1"/>
  370. * 961 <xsd:element name="spPr" type="CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
  371. * 962 <xsd:element name="txSp" type="CT_GvmlTextShape" minOccurs="0" maxOccurs="1"/>
  372. * 963 <xsd:element name="style" type="CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
  373. * 964 <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
  374. * 965 </xsd:sequence>
  375. * 966 </xsd:complexType>
  376. */
  377. var id = node.GetTextByPath("p:nvSpPr/p:cNvPr/@id");
  378. var name = node.GetTextByPath("p:nvSpPr/p:cNvPr/@name");
  379. var idx = node.GetTextByPath("p:nvSpPr/p:nvPr/p:ph/@idx");
  380. var type = node.GetTextByPath("p:nvSpPr/p:nvPr/p:ph/@type");
  381. XmlNode slideLayoutSpNode = ShapeHelper.GetNodesTable(id, idx, type, warpObj, "Layout");
  382. XmlNode slideMasterSpNode = ShapeHelper.GetNodesTable(id, idx, type, warpObj, "Master");
  383. if (type == null)
  384. {
  385. if (slideLayoutSpNode != null)
  386. {
  387. type = slideLayoutSpNode.GetTextByPath("p:nvSpPr/p:nvPr/p:ph/@type");
  388. }
  389. // type = slideLayoutSpNode.TryGetValue"p:nvSpPr", "p:nvPr", "p:ph", "attrs", "type"]);
  390. if (type == null)
  391. {
  392. if (slideMasterSpNode != null)
  393. {
  394. type = slideMasterSpNode.GetTextByPath("p:nvSpPr/p:nvPr/p:ph/@type");
  395. }
  396. // type = getTextByPathList(slideMasterSpNode, ["p:nvSpPr", "p:nvPr", "p:ph", "attrs", "type"]);
  397. }
  398. }
  399. string s = await GenShape(node, slideLayoutSpNode, slideMasterSpNode, id, name, idx, type, order, warpObj);
  400. return "";
  401. }
  402. public async Task<string> GenShape(XmlNode node, XmlNode slideLayoutSpNode, XmlNode slideMasterSpNode, XmlNode id, XmlNode name, XmlNode idx, XmlNode type, int order, WarpObj warpObj)
  403. {
  404. var xfrmList = "p:spPr/a:xfrm";
  405. var slideXfrmNode = node.GetTextByPath(xfrmList);
  406. XmlNode slideLayoutXfrmNode = null;
  407. if (slideLayoutSpNode != null)
  408. {
  409. slideLayoutXfrmNode = slideLayoutSpNode.GetTextByPath(xfrmList);
  410. }
  411. XmlNode slideMasterXfrmNode = null;
  412. if (slideMasterSpNode != null)
  413. {
  414. slideMasterXfrmNode = slideMasterSpNode.GetTextByPath(xfrmList);
  415. }
  416. if (slideXfrmNode == null)
  417. {
  418. slideXfrmNode = slideLayoutXfrmNode;
  419. }
  420. if (slideXfrmNode == null)
  421. {
  422. slideXfrmNode = slideMasterXfrmNode;
  423. }
  424. var result = "";
  425. var shapeType = node.GetTextByPath("p:spPr/a:prstGeom/@prst");
  426. var custShapType = node.GetTextByPath("p:spPr/a:custGeom");
  427. var isFlipV = 0;
  428. var isFlipH = 0;
  429. if (slideXfrmNode.GetTextByPath("@flipV") != null && slideXfrmNode.GetTextByPath("@flipV").Value == "1")
  430. {// if ( getTextByPathList(slideXfrmNode, ["attrs", "flipV"]) === "1" || getTextByPathList(slideXfrmNode, ["attrs", "flipH"]) === "1")
  431. isFlipV = 1;
  432. }
  433. if (slideXfrmNode.GetTextByPath("@flipH") != null && slideXfrmNode.GetTextByPath("@flipH").Value == "1")
  434. {
  435. isFlipH = 1;
  436. }
  437. //rotate
  438. var rotate = ShapeHelper.AngleToDegrees(slideXfrmNode.GetTextByPath("@rot"));
  439. //console.log("rotate: "+rotate);
  440. double txtRotate;
  441. var txtXframeNode = node.GetTextByPath("p:txXfrm/@rot");
  442. if (txtXframeNode != null)
  443. {
  444. txtRotate = ShapeHelper.AngleToDegrees(txtXframeNode) + 90;
  445. }
  446. else
  447. {
  448. txtRotate = rotate;
  449. }
  450. Position position = ShapeHelper.GetPosition(slideXfrmNode, slideLayoutXfrmNode, slideMasterXfrmNode);
  451. position.Rot = rotate;
  452. position.FlipH = isFlipH;
  453. position.FlipV = isFlipV;
  454. var grndFillFlg = false;
  455. var imgFillFlg = false;
  456. var Fill = await GetShapeFill(node, warpObj);
  457. // Border Color
  458. var shapeBorder = ShapeHelper.GetBorder(node, true, "shape", slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  459. var headEndNodeAttrs = node.GetTextByPath("p:spPr/a:ln/a:headEnd");
  460. var tailEndNodeAttrs = node.GetTextByPath("p:spPr/a:ln/a:tailEnd");
  461. StringBuilder svgPath = new StringBuilder("<svg class='drawing' _id='" + order + id + "' _idx='" + order + idx + "' _type='" + order + type + "' _name='" + order + name+ "'");
  462. svgPath.Append(" style='top:"+position.Y+"px;left:"+position.X+ "px;width:"+position.Cx+ "px;height"+position.Cy+"px;'");
  463. if (shapeType != null || custShapType != null)
  464. {
  465. //result += "<svg class='drawing' _id='" + id + "' _idx='" + idx + "' _type='" + type + "' _name='" + name +
  466. // "' style='" +
  467. // getPosition(slideXfrmNode, null, null) +
  468. // getSize(slideXfrmNode, null, null) +
  469. // " z-index: " + order + ";" +
  470. // "transform: rotate(" + rotate + "deg);" +
  471. // "'>";
  472. //result += "<defs>";
  473. // Fill Color
  474. var clrFillType = ShapeHelper.GetFillType(node.GetTextByPath("p:spPr"));
  475. /////////////////////////////////////////
  476. if (clrFillType == "GRADIENT_FILL")
  477. {
  478. grndFillFlg = true;
  479. var color_arry = Fill.gradColor;
  480. var angl = Fill.Rot;
  481. var svgGrdnt = ShapeHelper.GetSvgGradient(position.Cx, position.Cy, angl, color_arry, order, slideLayoutClrOvride, warpObj.themeContent);
  482. //fill="url(#linGrd)"
  483. Fill.SvgText = svgGrdnt;
  484. result += svgGrdnt;
  485. }
  486. else if (clrFillType == "PIC_FILL")
  487. {
  488. imgFillFlg = true;
  489. var svgBgImg = ShapeHelper.GetSvgImagePattern(Fill.Image, order);
  490. //fill="url(#imgPtrn)"
  491. //console.log(svgBgImg)
  492. Fill.SvgText = svgBgImg;
  493. result += svgBgImg;
  494. }
  495. else
  496. {
  497. if (clrFillType != null && clrFillType != "SOLID_FILL" && clrFillType != "PATTERN_FILL")
  498. {
  499. Fill.HtmlText = "none";
  500. }
  501. if (shapeType != null)
  502. {
  503. if (shapeType.Value == "arc" ||
  504. shapeType.Value == "bracketPair" ||
  505. shapeType.Value == "bracePair" ||
  506. shapeType.Value == "leftBracket" ||
  507. shapeType.Value == "leftBrace" ||
  508. shapeType.Value == "rightBrace" ||
  509. shapeType.Value == "rightBracket")
  510. { //Temp. solution - TODO
  511. Fill.HtmlText = "none";
  512. }
  513. }
  514. }
  515. // type: none, triangle, stealth, diamond, oval, arrow
  516. if ((headEndNodeAttrs != null && (headEndNodeAttrs.GetTextByPath("@type").Value == "triangle" || (headEndNodeAttrs.GetTextByPath("@type").Value == "arrow")) ||
  517. (tailEndNodeAttrs != null && (tailEndNodeAttrs.GetTextByPath("@type").Value == "triangle" || (tailEndNodeAttrs.GetTextByPath("@type").Value == "arrow")))))
  518. {
  519. var triangleMarker = "<marker id='markerTriangle_" + order + "' viewBox='0 0 10 10' refX='1' refY='5' markerWidth='5' markerHeight='5' stroke='" + shapeBorder.Color + "' fill='" + shapeBorder.Color +
  520. "' orient='auto-start-reverse' markerUnits='strokeWidth'><path d='M 0 0 L 10 5 L 0 10 z' /></marker>";
  521. result += triangleMarker;
  522. }
  523. result += "</defs>";
  524. }
  525. if (shapeType != null && custShapType == null) {
  526. result+= ShapeSvg.GenShapeSvg(node, order, shapeType, isFlipV, position, grndFillFlg, imgFillFlg, Fill, shapeBorder, headEndNodeAttrs, tailEndNodeAttrs);
  527. }
  528. return result;
  529. }
  530. /// <summary>
  531. /// 幻灯片 背景色填充
  532. /// </summary>
  533. /// <param name="slideContent"></param>
  534. /// <param name="slideLayoutContent"></param>
  535. /// <param name="slideMasterContent"></param>
  536. /// <param name="index"></param>
  537. /// <param name="warpObj"></param>
  538. /// <returns></returns>
  539. public async Task<Fill> GetSlideBackgroundFill(XmlNode slideContent, int index, WarpObj warpObj)
  540. {
  541. var bgPr = slideContent.GetTextByPath("p:sld/p:cSld/p:bg/p:bgPr");
  542. var bgRef = slideContent.GetTextByPath("p:sld/p:cSld/p:bg/p:bgRef");
  543. if (bgPr != null)
  544. {
  545. var bgFillTyp = ShapeHelper.GetFillType(bgPr);
  546. if (bgFillTyp == "SOLID_FILL")
  547. {
  548. var sldFill = bgPr.GetTextByPath("a:solidFill");
  549. var bgColor = ShapeHelper.GetSolidFill(sldFill, slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  550. bgColor = PowerPointHelper.ColorToning(sldFill.OuterXml, bgColor);
  551. return new Fill { Type = 1, Color = bgColor };
  552. }
  553. else if (bgFillTyp == "GRADIENT_FILL")
  554. {
  555. return ShapeHelper.GetBgGradientFill(bgPr, null, slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  556. }
  557. else if (bgFillTyp == "PIC_FILL")
  558. {
  559. return await GetPicFill("slideBg", bgPr.GetTextByPath("a:blipFill"), warpObj);
  560. }
  561. }
  562. else if (bgRef != null)
  563. {
  564. string phClr = ShapeHelper.GetSolidFill(bgRef, slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  565. phClr = PowerPointHelper.ColorToning(bgRef.OuterXml, phClr);
  566. var idx = bgRef.GetTextByPath("@idx");
  567. if (idx != null)
  568. {
  569. int value = int.Parse(idx.Value);
  570. if (value == 0 || value == 1000)
  571. {
  572. return new Fill { Type = 0 };
  573. //no background
  574. }
  575. else if (value > 0 && value < 1000)
  576. {
  577. //fillStyleLst in themeContent
  578. //themeContent["a:fmtScheme"]["a:fillStyleLst"]
  579. //bgcolor = "background: red;";
  580. }
  581. else if (value > 1000)
  582. {
  583. var trueIdx = value - 1000;
  584. var bgFillLst = warpObj.themeContent.GetTextByPath("a:theme/a:themeElements/a:fmtScheme/a:bgFillStyleLst");
  585. if (bgFillLst != null) {
  586. XmlNodeList nodeList = bgFillLst.ChildNodes;
  587. if (trueIdx < nodeList.Count) {
  588. string type= ShapeHelper.GetFillType(nodeList[trueIdx - 1]);
  589. if (type.Equals("SOLID_FILL"))
  590. {
  591. if (string.IsNullOrEmpty(phClr))
  592. {
  593. phClr = ShapeHelper.GetSolidFill(nodeList[trueIdx - 1], slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  594. }
  595. phClr = PowerPointHelper.ColorToning(nodeList[trueIdx - 1].Value, phClr);
  596. return new Fill { Type = 1, Color = phClr };
  597. }
  598. else if (type.Equals("GRADIENT_FILL"))
  599. {
  600. return ShapeHelper.GetBgGradientFill(nodeList[trueIdx - 1], phClr, slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  601. }
  602. else if (type.Equals("PIC_FILL"))
  603. {
  604. return await GetPicFill("slideBg", nodeList[trueIdx - 1].GetTextByPath("a:blipFill"), warpObj);
  605. }
  606. else {
  607. return new Fill { Type = 0 };
  608. }
  609. }
  610. }
  611. }
  612. }
  613. //var node = bgRef.GetTextByPath("");
  614. //if (bgRef["a:srgbClr"] !== undefined)
  615. //{
  616. // phClr = getTextByPathList(bgRef,["a:srgbClr", "attrs", "val"]); //#...
  617. //}
  618. //else if (bgRef["a:schemeClr"] !== undefined)
  619. //{ //a:schemeClr
  620. // var schemeClr = getTextByPathList(bgRef,["a:schemeClr", "attrs", "val"]);
  621. // phClr = getSchemeColorFromTheme("a:" + schemeClr, slideMasterContent); //#...
  622. // //console.log("schemeClr",schemeClr,"phClr=",phClr)
  623. //}
  624. }
  625. else
  626. {
  627. bgPr =warpObj. slideLayoutContent.GetTextByPath("p:sldLayout/p:cSld/p:bg/p:bgPr");
  628. bgRef = warpObj. slideLayoutContent.GetTextByPath("p:sldLayout/p:cSld/p:bg/p:bgRef");
  629. if (bgPr != null)
  630. {
  631. var bgFillTyp = ShapeHelper.GetFillType(bgPr);
  632. if (bgFillTyp == "SOLID_FILL")
  633. {
  634. var sldFill = bgPr.GetTextByPath("a:solidFill");
  635. var bgColor = ShapeHelper.GetSolidFill(sldFill, slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  636. bgColor = PowerPointHelper.ColorToning(sldFill.OuterXml, bgColor);
  637. return new Fill { Type = 1, Color = bgColor };
  638. }
  639. else if (bgFillTyp == "GRADIENT_FILL")
  640. {
  641. return ShapeHelper.GetBgGradientFill(bgPr, null, slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  642. }
  643. else if (bgFillTyp == "PIC_FILL")
  644. {
  645. return await GetPicFill("slideBg", bgPr.GetTextByPath("a:blipFill"), warpObj);
  646. }
  647. }
  648. else if (bgRef != null)
  649. {
  650. string phClr = ShapeHelper.GetSolidFill(bgRef, slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  651. phClr = PowerPointHelper.ColorToning(bgRef.OuterXml, phClr);
  652. var idx = bgRef.GetTextByPath("@idx");
  653. if (idx != null)
  654. {
  655. int value = int.Parse(idx.Value);
  656. if (value == 0 || value == 1000)
  657. {
  658. return new Fill { Type = 0 };
  659. //no background
  660. }
  661. else if (value > 0 && value < 1000)
  662. {
  663. //fillStyleLst in themeContent
  664. //themeContent["a:fmtScheme"]["a:fillStyleLst"]
  665. //bgcolor = "background: red;";
  666. }
  667. else if (value > 1000)
  668. {
  669. var trueIdx = value - 1000;
  670. var bgFillLst = warpObj.themeContent.GetTextByPath("a:theme/a:themeElements/a:fmtScheme/a:bgFillStyleLst");
  671. if (bgFillLst != null)
  672. {
  673. XmlNodeList nodeList = bgFillLst.ChildNodes;
  674. if (trueIdx < nodeList.Count)
  675. {
  676. string type = ShapeHelper.GetFillType(nodeList[trueIdx - 1]);
  677. if (type.Equals("SOLID_FILL"))
  678. {
  679. if (string.IsNullOrEmpty(phClr))
  680. {
  681. phClr = ShapeHelper.GetSolidFill(nodeList[trueIdx - 1], slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  682. }
  683. phClr = PowerPointHelper.ColorToning(nodeList[trueIdx - 1].Value, phClr);
  684. return new Fill { Type = 1, Color = phClr };
  685. }
  686. else if (type.Equals("GRADIENT_FILL"))
  687. {
  688. return ShapeHelper.GetBgGradientFill(nodeList[trueIdx - 1], phClr, slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  689. }
  690. else if (type.Equals("PIC_FILL"))
  691. {
  692. return await GetPicFill("slideBg", nodeList[trueIdx - 1].GetTextByPath("a:blipFill"), warpObj);
  693. }
  694. else
  695. {
  696. return new Fill { Type = 0 };
  697. }
  698. }
  699. }
  700. }
  701. }
  702. }
  703. }
  704. return null;
  705. }
  706. public async Task<Fill> GetPicFill(string type, XmlNode node, WarpObj warpObj)
  707. {
  708. //Need to test/////////////////////////////////////////////
  709. //rId
  710. //TODO - Image Properties - Tile, Stretch, or Display Portion of Image
  711. //(http://officeopenxml.com/drwPic-tile.php)
  712. // var img = "";
  713. var rId = node.GetTextByPath("a:blip/@r:embed");//node["a:blip"]["attrs"]["r:embed"];
  714. Dictionary<string, string> imgPath = new Dictionary<string, string>();
  715. if (type == "slideBg")
  716. {
  717. imgPath = warpObj.slideResObj[rId.Value];
  718. }
  719. else if (type == "layoutBg")
  720. {
  721. imgPath = warpObj.layoutResObj[rId.Value];
  722. }
  723. else if (type == "masterBg")
  724. {
  725. imgPath = warpObj.masterResObj[rId.Value];
  726. }
  727. if (imgPath == null)
  728. {
  729. return null;
  730. }
  731. //var imgExt = imgPath["type"];
  732. //if (imgExt == "xml")
  733. //{
  734. // return null;
  735. //}
  736. var imgData = warpObj.zip.GetTextByPath("//pkg:part[@pkg:name='" + imgPath["target"] + "']");
  737. if (imgData != null)
  738. {
  739. AzureBlobModel model = await SaveBase64ToBolob(imgData.InnerText, imgData.GetTextByPath("@pkg:contentType").Value,
  740. fileShaCode + "/imgs", null);
  741. return new Fill { Type = 3, Image = model.BlobUrl };
  742. }
  743. else { return null; }
  744. // var imgArrayBuffer = warpObj.zip.GetTextByPath(imgPath).Value.asArrayBuffer();
  745. //var imgMimeType = GetMimeType(imgExt);
  746. //img = "data:" + imgMimeType + ";base64," + base64ArrayBuffer(imgArrayBuffer);
  747. }
  748. public async Task<Fill> GetShapeFill(XmlNode node, WarpObj warpObj)
  749. {
  750. // 1. presentationML
  751. // p:spPr/ [a:noFill, solidFill, gradFill, blipFill, pattFill, grpFill]
  752. // From slide
  753. //Fill Type:
  754. //console.log("ShapeFill: ", node)
  755. var fillType = ShapeHelper.GetFillType(node.GetTextByPath("p:spPr"));
  756. Fill fill =null;
  757. //0
  758. if (fillType == "NO_FILL")
  759. {
  760. fill = new Fill
  761. {
  762. Type = 0,
  763. HtmlText = "background-color: initial;",
  764. SvgText = "node"
  765. };
  766. //return isSvgMode ? "none" : "background-color: initial;";
  767. }
  768. //1纯色填充
  769. else if (fillType == "SOLID_FILL")
  770. {
  771. XmlNode shpFill = node.GetTextByPath("p:spPr/a:solidFill");// node["p:spPr"]["a:solidFill"];
  772. string color = ShapeHelper.GetSolidFill(shpFill, slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  773. fill = new Fill
  774. {
  775. Type = 1,
  776. Color = color,
  777. };
  778. }
  779. //2渐变色填充
  780. else if (fillType == "GRADIENT_FILL")
  781. {
  782. var shpFill = node.GetTextByPath("p:spPr/a:gradFill");// node["p:spPr"]["a:gradFill"];
  783. // fillColor = GetSolidFill(shpFill);
  784. fill = ShapeHelper.GetGradientFill(shpFill, slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  785. //console.log("shpFill",shpFill,grndColor.color)
  786. }//3图片 纹理填充
  787. else if (fillType == "PIC_FILL")
  788. {
  789. var shpFill = node.GetTextByPath("p:spPr/a:blipFill"); //node["p:spPr"]["a:blipFill"];
  790. fill = await GetPicFill("slideBg", shpFill, warpObj);
  791. }//4 图案填充
  792. else if (fillType == "PATTERN_FILL")
  793. {
  794. /*
  795. *
  796. *<a:pattFill prst="ltDnDiag">
  797. <a:fgClr>
  798. <a:schemeClr val="dk1">
  799. <a:lumMod val="15000"/>
  800. <a:lumOff val="85000"/>
  801. </a:schemeClr>
  802. </a:fgClr>
  803. <a:bgClr>
  804. <a:schemeClr val="lt1"/>
  805. </a:bgClr>
  806. </a:pattFill>
  807. */
  808. var shpFill = node.GetTextByPath("p:spPr/a:pattFill");// node["p:spPr"]["a:pattFill"];
  809. fill = ShapeHelper.GetPatternFill(shpFill, slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  810. }
  811. // 2. drawingML namespace
  812. if (fill == null)
  813. {
  814. var clrName = node.GetTextByPath("p:style/a:fillRef");
  815. if (clrName != null) {
  816. fillType = "SOLID_FILL";
  817. }
  818. string color = ShapeHelper.GetSolidFill(clrName, slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  819. color= PowerPointHelper.ColorToning(clrName.OuterXml,color);
  820. fill = new Fill
  821. {
  822. Type = 1,
  823. Color = color,
  824. };
  825. }
  826. if (fill != null)
  827. {
  828. if (fillType == "GRADIENT_FILL")
  829. {
  830. //if (isSvgMode)
  831. //{
  832. // // console.log("GRADIENT_FILL color", fillColor.color[0])
  833. // return fill;
  834. //}
  835. //else
  836. //{
  837. var colorAry = fill.gradColor;
  838. var rot = fill.Rot;
  839. var bgcolor = "background: linear-gradient(" + rot + "deg,";
  840. for (var i = 0; i < colorAry.Count; i++)
  841. {
  842. if (i == colorAry.Count - 1)
  843. {
  844. bgcolor += colorAry[i] + ");";
  845. }
  846. else
  847. {
  848. bgcolor += colorAry[i] + ", ";
  849. }
  850. }
  851. fill.HtmlText = bgcolor;
  852. return fill;
  853. // }
  854. }
  855. else if (fillType == "PIC_FILL")
  856. {
  857. //if (isSvgMode)
  858. //{
  859. // return fill;
  860. //}
  861. //else
  862. //{
  863. fill.HtmlText = "background-image:url(" + fill.Image + ");";
  864. return fill;
  865. // }
  866. }
  867. else
  868. {
  869. Console.WriteLine("#" + fill.Color);
  870. //if (isSvgMode)
  871. //{
  872. // var color = new colz.Color(fill);
  873. // fill = color.rgb.toString();
  874. fill.HtmlText = "background-color: #" + fill.Color + ";";
  875. return fill;
  876. //}
  877. //else
  878. //{
  879. // //console.log(node,"fillColor: ",fillColor,"fillType: ",fillType,"isSvgMode: ",isSvgMode)
  880. // return fill;
  881. //}
  882. }
  883. }
  884. else
  885. {
  886. //if (isSvgMode)
  887. //{
  888. // return fill;
  889. //}
  890. //else
  891. //{
  892. fill.SvgText = "none";
  893. fill.HtmlText = "background-color: initial;";
  894. return fill;
  895. // }
  896. }
  897. }
  898. public async Task<AzureBlobModel> GetThumbnailModel(XmlDocument xdoc, string shaCode)
  899. {
  900. var thumbnailNode = xdoc.GetTextByPath("//pkg:part[@pkg:name='/docProps/thumbnail.jpeg']");
  901. if (thumbnailNode != null)
  902. {
  903. var contentType = thumbnailNode.GetTextByPath("@pkg:contentType");
  904. var thumbnail = thumbnailNode.InnerText;
  905. return await SaveBase64ToBolob(thumbnail, contentType.Value, shaCode + "/imgs", "thumbnail");
  906. }
  907. return null;
  908. }
  909. public XmlNode LoadTheme(XmlDocument xdoc)
  910. {
  911. var themeRelationship = xdoc.GetTextByPath("//pkg:part[@pkg:name='/ppt/_rels/presentation.xml.rels']/pkg:xmlData/rel:Relationships/rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme']/@Target");
  912. // "/ppt/theme/theme1.xml"
  913. string themeURI = "/ppt/" + themeRelationship.Value;
  914. return xdoc.GetTextByPath("//pkg:part[@pkg:name='" + themeURI + "']");
  915. }
  916. public async Task<AzureBlobModel> SaveBase64ToBolob(string data, string contentType, string FolderName, string fileName)
  917. {
  918. string fileExt;
  919. if (ContentTypeDict.extdict.TryGetValue(contentType, out string ext))
  920. {
  921. fileExt = ext;
  922. }
  923. else
  924. {
  925. //解决多种扩展名不能获取的
  926. string[] sp = contentType.Split("/");
  927. fileExt = sp[sp.Length - 1];
  928. sp = fileExt.Split("+");
  929. fileExt = "." + sp[sp.Length - 1];
  930. }
  931. //data:image/jpeg;base64,
  932. if (string.IsNullOrEmpty(fileName))
  933. {
  934. Stream stream = new MemoryStream(Convert.FromBase64String(data));
  935. string shaCode = ShaHashHelper.GetSHA1(stream);
  936. fileName = shaCode + fileExt;
  937. }
  938. else
  939. {
  940. if (fileName.Split(".").Length == 1)
  941. {
  942. fileName += fileExt;
  943. }
  944. }
  945. Stream streamBlob = new MemoryStream(Convert.FromBase64String(data));
  946. AzureBlobModel model = await azureBlobDBRepository.UploadFileByFolder(streamBlob, FolderName, fileName, "pptx", false);
  947. return model;
  948. }
  949. public async Task<Media> ProcessPicNode(XmlNode node, int order, WarpObj warpObj)
  950. {
  951. var xfrmList = "p:spPr/a:xfrm";
  952. var xfrmNode = node.GetTextByPath(xfrmList);
  953. Media media = new Media() { Type = "Pic" };
  954. var id = node.GetTextByPath("p:nvPicPr/p:cNvPr/@id");
  955. XmlNode slideLayoutSpNode = ShapeHelper.GetNodesTable(id, null, null, warpObj, "Layout");
  956. XmlNode slideMasterSpNode = ShapeHelper.GetNodesTable(id, null, null, warpObj, "Master");
  957. XmlNode slideLayoutXfrmNode = null;
  958. if (slideLayoutSpNode != null)
  959. {
  960. slideLayoutXfrmNode = slideLayoutSpNode.GetTextByPath(xfrmList);
  961. }
  962. XmlNode slideMasterXfrmNode = null;
  963. if (slideMasterSpNode != null)
  964. {
  965. slideMasterXfrmNode = slideMasterSpNode.GetTextByPath(xfrmList);
  966. }
  967. double rotate = 0;
  968. var rotateNode = node.GetTextByPath("p:spPr/a:xfrm/@rot");
  969. if (rotateNode != null)
  970. {
  971. rotate = ShapeHelper.AngleToDegrees(rotateNode);
  972. }
  973. Fill fill = await GetShapeFill(node, warpObj);
  974. media.Fill = fill;
  975. Border border = ShapeHelper.GetBorder(node, true, "shape", slideLayoutClrOvride, warpObj.slideMasterContent, warpObj.themeContent);
  976. media.Border = border;
  977. Position position = ShapeHelper.GetPosition(xfrmNode, slideLayoutXfrmNode, slideMasterXfrmNode);
  978. media.Position = position;
  979. position.Rot = rotate;
  980. var rtrnData = "";
  981. //image
  982. var rid = node.GetTextByPath("p:blipFill/a:blip/@r:embed");
  983. if (rid != null)
  984. {
  985. var imgName = warpObj.slideResObj[rid.Value]["target"];
  986. Console.WriteLine(imgName);
  987. if (!string.IsNullOrEmpty(imgName))
  988. {
  989. var imgData = warpObj.zip.GetTextByPath("//pkg:part[@pkg:name='" + imgName + "']");
  990. var imgFileExt = imgData.GetTextByPath("@pkg:contentType");
  991. AzureBlobModel imgModel = await SaveBase64ToBolob(imgData.InnerText, imgFileExt.Value, fileShaCode + "/imgs", "");
  992. media.Image = imgModel.BlobUrl;
  993. media.MediaType = "image";
  994. }
  995. }
  996. ///////////////////////////////////////Amir//////////////////////////////
  997. //video
  998. var vdoNode = node.GetTextByPath("p:nvPicPr/p:nvPr/a:videoFile/@r:link");
  999. if (vdoNode != null)
  1000. {
  1001. string vdoFile = warpObj.slideResObj[vdoNode.Value]["target"];
  1002. if (!string.IsNullOrEmpty(vdoFile))
  1003. {
  1004. var videoData = warpObj.zip.GetTextByPath("//pkg:part[@pkg:name='" + vdoFile + "']");
  1005. var contentType = videoData.GetTextByPath("@pkg:contentType");
  1006. AzureBlobModel vdoModel = await SaveBase64ToBolob(videoData.InnerText, contentType.Value, fileShaCode + "/media", "");
  1007. media.Url = vdoModel.BlobUrl;
  1008. media.MediaType = "video";
  1009. }
  1010. /// 处理为AzureBlob 上传
  1011. // vdoMimeType = getMimeType(vdoFileExt);
  1012. // blob = new Blob([uInt8Array], {
  1013. // type: vdoMimeType
  1014. // });
  1015. // vdoBlob = URL.createObjectURL(blob);
  1016. }
  1017. //audio
  1018. var audioNode = node.GetTextByPath("p:nvPicPr/p:nvPr/a:audioFile/@r:link");
  1019. // var audioObjc;
  1020. if (audioNode != null)
  1021. {
  1022. string audioFile = warpObj.slideResObj[audioNode.Value]["target"];
  1023. if (!string.IsNullOrEmpty(audioFile))
  1024. {
  1025. var audioData = warpObj.zip.GetTextByPath("//pkg:part[@pkg:name='" + audioFile + "']");
  1026. var contentType = audioData.GetTextByPath("@pkg:contentType");
  1027. AzureBlobModel adoModel = await SaveBase64ToBolob(audioData.InnerText, contentType.Value, fileShaCode + "/media", "");
  1028. media.Url = adoModel.BlobUrl;
  1029. media.MediaType = "audio";
  1030. }
  1031. //uInt8ArrayAudio = zip.file(audioFile).asArrayBuffer();
  1032. //blobAudio = new Blob([uInt8ArrayAudio]);
  1033. //audioBlob = URL.createObjectURL(blobAudio);
  1034. //var cx = parseInt(xfrmNode["a:ext"]["attrs"]["cx"]) * 20;
  1035. //var cy = xfrmNode["a:ext"]["attrs"]["cy"];
  1036. //var x = parseInt(xfrmNode["a:off"]["attrs"]["x"]) / 2.5;
  1037. //var y = xfrmNode["a:off"]["attrs"]["y"];
  1038. //audioObjc = {
  1039. // "a:ext" : {
  1040. // "attrs":{
  1041. // "cx":cx,
  1042. // "cy":cy
  1043. // }
  1044. // },
  1045. // "a:off":{
  1046. // "attrs":{
  1047. // "x":x,
  1048. // "y":y
  1049. // }
  1050. // }
  1051. //}
  1052. // mediaSupportFlag = true;
  1053. }
  1054. //console.log(node)
  1055. //////////////////////////////////////////////////////////////////////////
  1056. //mimeType = imgFileExt;
  1057. //rtrnData = "<div class='block content' style='" +
  1058. // (( audioPlayerFlag) ? GetPosition(audioObjc, null, null) : GetPosition(xfrmNode, null, null)) +
  1059. // (( audioPlayerFlag) ? GetSize(audioObjc, null, null) :GetSize(xfrmNode, null, null)) +
  1060. // " z-index: " + order + ";" +
  1061. // "transform: rotate(" + rotate + "deg);'>";
  1062. //if ((vdoNode ==null && audioNode ==null) || !mediaSupportFlag)
  1063. //{
  1064. // rtrnData += "<img src='data:" + mimeType + ";base64," + base64ArrayBuffer(imgArrayBuffer) + "' style='width: 100%; height: 100%'/>";
  1065. //}
  1066. //else if ((vdoNode !=null || audioNode !=null) && mediaSupportFlag)
  1067. //{
  1068. // if (vdoNode !=null)
  1069. // {
  1070. // rtrnData += "<video src='" + vdoBlob + "' controls style='width: 100%; height: 100%'>Your browser does not support the video tag.</video>";
  1071. // }
  1072. // if (audioNode !=null)
  1073. // {
  1074. // rtrnData += "<audio id='audio_player' controls ><source src='" + audioBlob + "'></audio>";
  1075. // }
  1076. //}
  1077. rtrnData += "<span style='color:red;font-size:40px;position: absolute;'>This media file Not supported by HTML5</span>";
  1078. //if ((vdoNode != null || audioNode != null) && mediaSupportFlag)
  1079. //{
  1080. // //console.log("Founded supported media file but media process disabled (mediaProcess=false)");
  1081. //}
  1082. rtrnData += "</div>";
  1083. //console.log(rtrnData)
  1084. return media;
  1085. }
  1086. }
  1087. }