ShapeGenerator.cs 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  1. using DocumentFormat.OpenXml.Drawing;
  2. using DocumentFormat.OpenXml.Packaging;
  3. using DocumentFormat.OpenXml.Presentation;
  4. using HiTeachCC.Model.PowerPoint;
  5. using HiTeachCC.Service.PowerPoint.Interface;
  6. using Microsoft.AspNetCore.Http;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Threading.Tasks;
  12. using System.Xml;
  13. using System.Xml.Linq;
  14. using System.Xml.XPath;
  15. using TEAMModelOS.SDK.Context.Constant;
  16. using TEAMModelOS.SDK.Context.Constant.Common;
  17. using TEAMModelOS.SDK.Context.Exception;
  18. using TEAMModelOS.SDK.Helper.Common.JsonHelper;
  19. using TEAMModelOS.SDK.Helper.Common.StringHelper;
  20. using TEAMModelOS.SDK.Helper.Security.ShaHash;
  21. using TEAMModelOS.SDK.Module.AzureBlob.Container;
  22. using TEAMModelOS.SDK.Module.AzureBlob.Interfaces;
  23. using ColorMap = DocumentFormat.OpenXml.Presentation.ColorMap;
  24. using Fill = HiTeachCC.Model.PowerPoint.Fill;
  25. namespace HiTeachCC.Service.PowerPoint.Implement
  26. {
  27. public class ShapeGenerator : IShapeGenerator
  28. {
  29. bool isDone = false;
  30. List<object> MsgQueue = new List<object>();
  31. private Dictionary<string, string> slideLayoutClrOvride { get; set; }
  32. private XmlNode themeContent { get; set; }
  33. int chartID = 0;
  34. int _order = 1;
  35. int titleFontSize = 42;
  36. int bodyFontSize = 20;
  37. int otherFontSize = 16;
  38. bool isSlideMode = false;
  39. Dictionary<string, Dictionary<string, string>> styleTable = new Dictionary<string, Dictionary<string, string>>();
  40. const double px96 = 96.00, px72 = 72.00, px914400 = 914400.00, px12700 = 12700.00;
  41. const double rot60000 = 60000.00;
  42. private readonly IAzureBlobDBRepository azureBlobDBRepository;
  43. public ShapeGenerator(IAzureBlobDBRepository _azureBlobDBRepository)
  44. {
  45. azureBlobDBRepository = _azureBlobDBRepository;
  46. }
  47. public async Task<Dictionary<string, object>> LoadPresentation(IFormFile file)
  48. {
  49. Dictionary<string, object> resdict = new Dictionary<string, object>();
  50. if (FileType.GetExtention(file.FileName).ToLower().Equals("pptx"))
  51. {
  52. ConvertPPTX(file, resdict);
  53. return resdict;
  54. }
  55. else if (FileType.GetExtention(file.FileName).ToLower().Equals("pdf"))
  56. {
  57. // await ProcessPDF(file, resdict);
  58. return resdict;
  59. }
  60. else
  61. {
  62. throw new BizException("file type does not support!", 500);
  63. }
  64. }
  65. public Dictionary<string, object> ConvertPPTX(IFormFile file, Dictionary<string, object> resdict)
  66. {
  67. string shaCode = ShaHashHelper.GetSHA1(file.OpenReadStream());
  68. using (PresentationDocument presentationDocument = PresentationDocument.Open(file.OpenReadStream(), false))
  69. {
  70. if (presentationDocument == null)
  71. {
  72. throw new ArgumentNullException("presentationDocument");
  73. }
  74. XDocument xdoc = presentationDocument.ToFlatOpcDocument();
  75. XmlDocument xmlDocument = new XmlDocument();
  76. xmlDocument.LoadXml(xdoc.ToString());
  77. var rslt_ary = ProcessPPTX(xmlDocument, shaCode);
  78. //TODO
  79. return null;
  80. }
  81. }
  82. /// <summary>
  83. /// 加载PPTX文件
  84. /// </summary>
  85. /// <param name="presentationFile"></param>
  86. /// <returns></returns>
  87. public async Task<List<Dictionary<string, object>>> ProcessPPTX(XmlDocument xdoc, string shaCode)
  88. {
  89. List<Dictionary<string, object>> post_ary = new List<Dictionary<string, object>>();
  90. var dateBefore = DateTimeOffset.Now.UtcTicks;
  91. AzureBlobModel thumbnailModel = await GetThumbnailModel(xdoc, shaCode);
  92. post_ary.Add(new Dictionary<string, object> { { "pptx-thumb", thumbnailModel } });
  93. //获取全部的/ppt/slides/slide1.xml--->>/ppt/slides/slide(n).xml
  94. var slideNodes = xdoc.GetTextByPathList("//pkg:part[@pkg:contentType='application/vnd.openxmlformats-officedocument.presentationml.slide+xml']");
  95. //获取全部的/ppt/slideLayouts/slideLayout1.xml--->>/ppt/slideLayouts/slideLayout(n).xml
  96. var slideLayoutNodes = xdoc.GetTextByPathList("//pkg:part[@pkg:contentType='application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml']");
  97. //获取ppt的宽高
  98. var slideSize = GetSlideSize(xdoc);
  99. post_ary.Add(new Dictionary<string, object> { { "slideSize", slideSize } });
  100. //加载当前PPT使用到的PPT节点
  101. themeContent = LoadTheme(xdoc);
  102. //获取所有的表格样式节点
  103. var tableStyles = xdoc.GetTextByPath("//pkg:part[@pkg:name='/ppt/tableStyles.xml']/pkg:xmlData/a:tblStyleLst");
  104. //处理slide1---slide(n)
  105. int numOfSlides = slideNodes.Count;
  106. for (int i = 0; i < numOfSlides; i++)
  107. {
  108. string filename = slideNodes[i].GetTextByPath("@pkg:name").Value;
  109. //处理当前页的幻灯片
  110. string slideHtml = ProcessSingleSlide(xdoc, slideNodes[i], filename, i, slideSize);
  111. post_ary.Add(new Dictionary<string, object> { { "slide", slideHtml } });
  112. post_ary.Add(new Dictionary<string, object> { { "progress-update", (i + 1) * 100 / numOfSlides } });
  113. }
  114. post_ary.Add(new Dictionary<string, object> { { "globalCSS", GenGlobalCSS() } });
  115. var dateAfter = DateTimeOffset.Now.UtcTicks;
  116. post_ary.Add(new Dictionary<string, object> { { "ExecutionTime", dateAfter - dateBefore } });
  117. return post_ary;
  118. }
  119. private Dictionary<string, string> GenGlobalCSS()
  120. {
  121. Dictionary<string, string> cssText = new Dictionary<string, string>();
  122. foreach (var key in styleTable.Keys)
  123. {
  124. // cssText += "div ." + styleTable[key]["name"] + "{" + styleTable[key]["text"] + "}\n"; //section > div
  125. var cssTextKey = styleTable[key]["name"];
  126. var cssTextValue = styleTable[key]["text"];
  127. cssText.Add(cssTextKey, cssTextValue);
  128. }
  129. return cssText;
  130. }
  131. private string ProcessSingleSlide(XmlDocument xdoc, XmlNode xnode, string sldFileName, int index, dynamic slideSize)
  132. {
  133. var resName = sldFileName.Replace("slides/slide", "slides/_rels/slide") + ".rels";
  134. var RelationshipArray = xdoc.GetTextByPathList("//pkg:part[@pkg:name='" + resName + "']/pkg:xmlData/rel:Relationships/rel:Relationship");
  135. Dictionary<string, Dictionary<string, string>> slideResObj = new Dictionary<string, Dictionary<string, string>>();
  136. var layoutFilename = "";
  137. foreach (XmlNode Relationship in RelationshipArray)
  138. {
  139. var RelationshipType = Relationship.GetTextByPath("@Type");
  140. if (RelationshipType.Value.Equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"))
  141. {
  142. layoutFilename = Relationship.GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  143. }
  144. else
  145. {
  146. //case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide":
  147. //case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image":
  148. //case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart":
  149. //case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink":
  150. Dictionary<string, string> dict = new Dictionary<string, string>();
  151. string Type = Relationship.GetTextByPath("@Type").Value.Replace("http://schemas.openxmlformats.org/officeDocument/2006/relationships/", "");
  152. string Target = Relationship.GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  153. string Id = Relationship.GetTextByPath("@Id").Value;
  154. dict.Add("type", Type);
  155. dict.Add("target", Target);
  156. slideResObj.Add(Id, dict);
  157. }
  158. }
  159. // Open slideLayoutXX.xml
  160. var slideLayoutContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + layoutFilename + "']");
  161. dynamic slideLayoutTables = IndexNodes(slideLayoutContent.GetTextByPath("pkg:xmlData/p:sldLayout"));
  162. ///ppt/slides/slide5.xml 也包含a:overrideClrMapping
  163. ////ppt/slideLayouts/slideLayout13.xml 也包含a:overrideClrMapping
  164. var sldLayoutClrOvr = slideLayoutContent.GetTextByPath("pkg:xmlData/p:sldLayout/p:clrMapOvr/a:overrideClrMapping");
  165. if (sldLayoutClrOvr != null)
  166. {
  167. //获取 overrideClrMapping所有属性节点
  168. slideLayoutClrOvride = new Dictionary<string, string>() {
  169. { "accent1", sldLayoutClrOvr.GetTextByPath("@accent1").Value},
  170. { "accent2", sldLayoutClrOvr.GetTextByPath("@accent2").Value},
  171. { "accent3", sldLayoutClrOvr.GetTextByPath("@accent3").Value},
  172. { "accent4", sldLayoutClrOvr.GetTextByPath("@accent4").Value},
  173. { "accent5", sldLayoutClrOvr.GetTextByPath("@accent5").Value},
  174. { "accent6", sldLayoutClrOvr.GetTextByPath("@accent6").Value},
  175. { "bg1", sldLayoutClrOvr.GetTextByPath("@bg1").Value},
  176. { "bg2", sldLayoutClrOvr.GetTextByPath("@bg2").Value},
  177. { "folHlink", sldLayoutClrOvr.GetTextByPath("@folHlink").Value},
  178. { "hlink", sldLayoutClrOvr.GetTextByPath("@hlink").Value},
  179. { "tx1", sldLayoutClrOvr.GetTextByPath("@tx1").Value},
  180. { "tx2", sldLayoutClrOvr.GetTextByPath("@tx2").Value}
  181. };
  182. }
  183. // =====< Step 2 >=====
  184. // Read slide master filename of the slidelayout (Get slideMasterXX.xml)
  185. // @resName: ppt/slideLayouts/slideLayout1.xml
  186. // @masterName: ppt/slideLayouts/_rels/slideLayout1.xml.rels
  187. var slideLayoutResFilename = layoutFilename.Replace("slideLayouts/slideLayout", "slideLayouts/_rels/slideLayout") + ".rels";
  188. var slideLayoutResContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + slideLayoutResFilename + "']");
  189. ///查看js 是替换之前 还是添加
  190. RelationshipArray = slideLayoutResContent.GetTextByPathList("pkg:xmlData/rel:Relationships/rel:Relationship");
  191. var masterFilename = "";
  192. Dictionary<string, Dictionary<string, string>> layoutResObj = new Dictionary<string, Dictionary<string, string>>();
  193. for (int i = 0; i < RelationshipArray.Count; i++)
  194. {
  195. if (RelationshipArray[i].GetTextByPath("@Type").Value.Equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster"))
  196. {
  197. masterFilename = RelationshipArray[i].GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  198. }
  199. else
  200. {
  201. Dictionary<string, string> dict = new Dictionary<string, string>();
  202. string Type = RelationshipArray[i].GetTextByPath("@Type").Value.Replace("http://schemas.openxmlformats.org/officeDocument/2006/relationships/", "");
  203. string Target = RelationshipArray[i].GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  204. string Id = RelationshipArray[i].GetTextByPath("@Id").Value;
  205. dict.Add("type", Type);
  206. dict.Add("target", Target);
  207. layoutResObj.Add(Id, dict);
  208. }
  209. }
  210. // Open slideMasterXX.xml
  211. var slideMasterContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + masterFilename + "']");
  212. var slideMasterTextStyles = slideMasterContent.GetTextByPath("pkg:xmlData/p:sldMaster/p:txStyles");
  213. var slideMasterTables = IndexNodes(slideMasterContent.GetTextByPath("pkg:xmlData/p:sldMaster"));
  214. /////////////////Amir/////////////
  215. //Open slideMasterXX.xml.rels
  216. var slideMasterResFilename = masterFilename.Replace("slideMasters/slideMaster", "slideMasters/_rels/slideMaster") + ".rels";
  217. var slideMasterResContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + slideMasterResFilename + "']");
  218. RelationshipArray = slideLayoutResContent.GetTextByPathList("pkg:xmlData/rel:Relationships/rel:Relationship");
  219. var themeFilename = "";
  220. Dictionary<string, Dictionary<string, string>> masterResObj = new Dictionary<string, Dictionary<string, string>>();
  221. for (int i = 0; i < RelationshipArray.Count; i++)
  222. {
  223. if (RelationshipArray[i].GetTextByPath("@Type").Value.Equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"))
  224. {
  225. themeFilename = RelationshipArray[i].GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  226. }
  227. else
  228. {
  229. Dictionary<string, string> dict = new Dictionary<string, string>();
  230. string Type = RelationshipArray[i].GetTextByPath("@Type").Value.Replace("http://schemas.openxmlformats.org/officeDocument/2006/relationships/", "");
  231. string Target = RelationshipArray[i].GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  232. string Id = RelationshipArray[i].GetTextByPath("@Id").Value;
  233. dict.Add("type", Type);
  234. dict.Add("target", Target);
  235. masterResObj.Add(Id, dict);
  236. }
  237. }
  238. //Load Theme file
  239. if (!string.IsNullOrEmpty(themeFilename))
  240. {
  241. themeContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + themeFilename + "']");
  242. }
  243. // =====< Step 3 >=====
  244. var slideContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + sldFileName + "']");
  245. var nodes = slideContent.GetTextByPath("p:sld/p:cSld/p:spTree").ChildNodes;
  246. dynamic warpObj = new
  247. {
  248. zip = xdoc,
  249. slideLayoutTables,
  250. slideMasterTables,
  251. slideResObj,
  252. slideMasterTextStyles,
  253. layoutResObj,
  254. masterResObj
  255. };
  256. var bgColor = GetSlideBackgroundFill(slideContent, slideLayoutContent, slideMasterContent, warpObj);
  257. var 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. foreach (XmlNode node in nodes)
  260. {
  261. result += ProcessNodesInSlide(node.Name, node, warpObj);
  262. }
  263. return "";
  264. }
  265. private dynamic ProcessNodesInSlide(string nodeKey, XmlNode nodeValue, dynamic warpObj)
  266. {
  267. var result = "";
  268. switch (nodeKey)
  269. {
  270. case "p:sp": // Shape, Text
  271. result = ProcessSpNode(nodeValue, warpObj);
  272. break;
  273. case "p:cxnSp": // Shape, Text (with connection)
  274. result = ProcessCxnSpNode(nodeValue, warpObj);
  275. break;
  276. case "p:pic": // Picture
  277. result = ProcessPicNode(nodeValue, warpObj);
  278. break;
  279. case "p:graphicFrame": // Chart, Diagram, Table
  280. result = ProcessGraphicFrameNode(nodeValue, warpObj);
  281. break;
  282. case "p:grpSp":
  283. result = ProcessGroupSpNode(nodeValue, warpObj);
  284. break;
  285. case "mc:AlternateContent": //Equations and formulas as Image
  286. var mcFallbackNode = nodeValue.GetTextByPath("mc:Fallback/p:sp");
  287. result = ProcessSpNode(mcFallbackNode, warpObj);
  288. break;
  289. default:
  290. break;
  291. }
  292. return result;
  293. }
  294. private string ProcessGroupSpNode(XmlNode node, dynamic warpObj)
  295. {
  296. var factor =1.00* px96 / px914400;
  297. var xfrmNode = node.GetTextByPath("p:grpSpPr/a:xfrm");
  298. var x = int.Parse(xfrmNode.GetTextByPath("a:off/@x").Value) * factor;
  299. var y = int.Parse(xfrmNode.GetTextByPath("a:off/@y").Value) * factor;
  300. var chx = int.Parse(xfrmNode.GetTextByPath("a:chOff/@x").Value) * factor;
  301. var chy = int.Parse(xfrmNode.GetTextByPath("a:chOff/@y").Value) * factor;
  302. var cx = int.Parse(xfrmNode.GetTextByPath("a:ext/@cx").Value) * factor;
  303. var cy = int.Parse(xfrmNode.GetTextByPath("a:ext/@cy").Value) * factor;
  304. var chcx = int.Parse(xfrmNode.GetTextByPath("a:chExt/@cx").Value) * factor;
  305. var chcy = int.Parse(xfrmNode.GetTextByPath("a:chExt/@cy").Value) * factor;
  306. var order = node["attrs"]["order"];
  307. var 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;'>";
  308. // Procsee all child nodes
  309. var nodes = node.ChildNodes;
  310. foreach(XmlNode nd in nodes)
  311. {
  312. result += ProcessNodesInSlide(nd.Name, nd, warpObj);
  313. }
  314. result += "</div>";
  315. return result;
  316. }
  317. private string ProcessGraphicFrameNode(XmlNode nodeValue, dynamic warpObj)
  318. {
  319. throw new NotImplementedException();
  320. }
  321. private string ProcessPicNode(XmlNode nodeValue, dynamic warpObj)
  322. {
  323. throw new NotImplementedException();
  324. }
  325. private string ProcessCxnSpNode(XmlNode nodeValue, dynamic warpObj)
  326. {
  327. throw new NotImplementedException();
  328. }
  329. private string ProcessSpNode(XmlNode nodeValue, dynamic warpObj)
  330. {
  331. throw new NotImplementedException();
  332. }
  333. private Fill GetSlideBackgroundFill(XmlNode slideContent ,XmlNode slideLayoutContent , XmlNode slideMasterContent , dynamic warpObj) {
  334. var bgPr = slideContent.GetTextByPath("p:sld/p:cSld/p:bg/p:bgPr");
  335. var bgRef = slideContent.GetTextByPath("p:sld/p:cSld/p:bg/p:bgRef");
  336. var bgcolor="";
  337. if (bgPr != null)
  338. {
  339. var bgFillTyp = GetFillType(bgPr);
  340. if (bgFillTyp == "SOLID_FILL")
  341. {
  342. var sldFill = bgPr.GetTextByPath("a:solidFill");
  343. var bgColor = GetSolidFill(sldFill);
  344. var sldTint = GetColorOpacity(sldFill);
  345. bgcolor = "background: rgba(" + HexToRgbNew(bgColor.Color) + "," + sldTint + ");";
  346. }
  347. else if (bgFillTyp == "GRADIENT_FILL")
  348. {
  349. bgcolor = getBgGradientFill(bgPr, null, slideMasterContent);
  350. }
  351. else if (bgFillTyp == "PIC_FILL")
  352. {
  353. bgcolor = getBgPicFill(bgPr, "slideBg", warpObj);
  354. }
  355. }
  356. else if (bgRef != null)
  357. {
  358. }
  359. else {
  360. }
  361. return null;
  362. }
  363. private string getBgPicFill(XmlNode bgPr, string sorce,dynamic warpObj)
  364. {
  365. var bgcolor="";
  366. var picFillBase64 = GetPicFill(sorce, bgPr.GetTextByPath("a:blipFill"), warpObj);
  367. var ordr = bgPr["attrs"]["order"];
  368. //a:srcRect
  369. //a:stretch => a:fillRect =>attrs (l:-17000, r:-17000)
  370. bgcolor = "background-image: url(" + picFillBase64 + "); z-index: " + ordr + ";";
  371. return bgcolor;
  372. }
  373. private static Fill GetPicFill(string type, XmlNode node, dynamic warpObj)
  374. {
  375. //Need to test/////////////////////////////////////////////
  376. //rId
  377. //TODO - Image Properties - Tile, Stretch, or Display Portion of Image
  378. //(http://officeopenxml.com/drwPic-tile.php)
  379. var img = "";
  380. var rId = PowerPointHelper.GetTextByPath(node, "a:blip/@r:embed");//node["a:blip"]["attrs"]["r:embed"];
  381. var imgPath = "";
  382. if (type == "slideBg")
  383. {
  384. imgPath = PowerPointHelper.GetTextByPath(warpObj, "slideResObj/" + rId + "/target").Value;
  385. }
  386. else if (type == "layoutBg")
  387. {
  388. imgPath = PowerPointHelper.GetTextByPath(warpObj, "layoutResObj/" + rId + "/target").Value;
  389. }
  390. else if (type == "masterBg")
  391. {
  392. imgPath = PowerPointHelper.GetTextByPath(warpObj, "masterResObj/" + rId + "/target").Value;
  393. }
  394. if (imgPath == null)
  395. {
  396. return null;
  397. }
  398. var imgExt = imgPath.Split(".").Last();
  399. if (imgExt == "xml")
  400. {
  401. return null;
  402. }
  403. var imgArrayBuffer = warpObj.zip.file(imgPath).asArrayBuffer();
  404. //var imgMimeType = GetMimeType(imgExt);
  405. //img = "data:" + imgMimeType + ";base64," + base64ArrayBuffer(imgArrayBuffer);
  406. return null;
  407. }
  408. private string getBgGradientFill(XmlNode bgPr, XmlNode phClr, XmlNode slideMasterContent)
  409. {
  410. var bgcolor = "";
  411. if (bgPr !=null)
  412. {
  413. var grdFill = bgPr.GetTextByPath("a:gradFill");
  414. var gsLst = grdFill.GetTextByPathList("a:gsLst/a:gs");
  415. // var startColorNode, endColorNode;
  416. var color_ary = new List<string >();
  417. var tint_ary = new List<int>();
  418. for (var i = 0; i < gsLst.Count; i++)
  419. {
  420. var lo_tint ="" ;
  421. var lo_color = "";
  422. if (gsLst[i]["a:srgbClr"] != null)
  423. {
  424. if (phClr == null)
  425. {
  426. lo_color = gsLst[i].GetTextByPath("a:srgbClr/@val").Value; //#...
  427. }
  428. lo_tint = gsLst[i].GetTextByPath("a:srgbClr/a:tint/@val").Value;
  429. }
  430. else if (gsLst[i]["a:schemeClr"] != null)
  431. { //a:schemeClr
  432. if (phClr == null)
  433. {
  434. var schemeClr = gsLst[i].GetTextByPath("a:schemeClr/@val");
  435. lo_color = GetSchemeColorFromTheme("a:" + schemeClr, slideMasterContent); //#...
  436. }
  437. lo_tint = gsLst[i].GetTextByPath("a:schemeClr/a:tint/@val").Value;
  438. //console.log("schemeClr",schemeClr,slideMasterContent)
  439. }
  440. //console.log("lo_color",lo_color)
  441. color_ary[i] = lo_color;
  442. tint_ary[i] = (lo_tint !=null) ? int.Parse(lo_tint) / 100000 : 1;
  443. }
  444. //get rot
  445. var lin = grdFill["a:lin"];
  446. var rot = 90.0;
  447. if (lin !=null)
  448. {
  449. rot = AngleToDegrees(lin.GetTextByPath("@ang")) + 90;
  450. }
  451. bgcolor = "background: linear-gradient(" + rot + "deg,";
  452. for (var i = 0; i < gsLst.Count; i++)
  453. {
  454. if (i == gsLst.Count - 1)
  455. {
  456. if (phClr ==null)
  457. {
  458. bgcolor += "rgba(" + HexToRgbNew(color_ary[i]) + "," + tint_ary[i] + ")" + ");";
  459. }
  460. else
  461. {
  462. bgcolor += "rgba(" + HexToRgbNew(phClr.Value) + "," + tint_ary[i] + ")" + ");";
  463. }
  464. }
  465. else
  466. {
  467. if (phClr == null)
  468. {
  469. bgcolor += "rgba(" + HexToRgbNew(color_ary[i]) + "," + tint_ary[i] + ")" + ", ";
  470. }
  471. else
  472. {
  473. bgcolor += "rgba(" + HexToRgbNew(phClr.Value) + "," + tint_ary[i] + ")" + ", ";
  474. }
  475. }
  476. }
  477. }
  478. else
  479. {
  480. if (phClr == null)
  481. {
  482. bgcolor = "rgba(" + HexToRgbNew(phClr.Value) + ",0);";
  483. }
  484. }
  485. return bgcolor;
  486. }
  487. public double AngleToDegrees(XmlNode angle)
  488. {
  489. if (angle.Value == "" || angle == null)
  490. {
  491. return 0;
  492. }
  493. int.TryParse(angle.Value, out int angleInt);
  494. double a = angleInt / 60000;
  495. return System.Math.Round(a);
  496. }
  497. private string HexToRgbNew(string bgColor)
  498. {
  499. //var arrBuff = new ArrayBuffer(4);
  500. //var vw = new DataView(arrBuff);
  501. //vw.setUint32(0, parseInt(hex, 16), false);
  502. //var arrByte = new Uint8Array(arrBuff);
  503. int r = Convert.ToInt32("0x" + bgColor.Substring(0, 2), 16);
  504. int g = Convert.ToInt32("0x" + bgColor.Substring(2, 2), 16);
  505. int b = Convert.ToInt32("0x" + bgColor.Substring(4, 2), 16);
  506. return r + "," + g+ "," +b;
  507. }
  508. private double GetColorOpacity(XmlNode solidFill)
  509. {
  510. double opcity = 1;
  511. if (solidFill == null)
  512. {
  513. return opcity;
  514. }
  515. if (solidFill.GetTextByPath("a:srgbClr") != null)
  516. {
  517. var tint = solidFill.GetTextByPath("a:srgbClr/a:tint/@val");
  518. if (tint !=null)
  519. {
  520. opcity = double.Parse(tint.Value) / 100000;
  521. }
  522. }
  523. else if (solidFill.GetTextByPath("a:schemeClr") != null)
  524. {
  525. var tint = solidFill.GetTextByPath("a:schemeClr/a:tint/@val");
  526. if (tint != null)
  527. {
  528. opcity = double.Parse(tint.Value) / 100000;
  529. }
  530. }
  531. else if (solidFill.GetTextByPath("a:scrgbClr")!= null)
  532. {
  533. var tint = solidFill.GetTextByPath("a:scrgbClr/a:tint/@val");
  534. if (tint != null)
  535. {
  536. opcity = double.Parse(tint.Value) / 100000;
  537. }
  538. }
  539. else if (solidFill.GetTextByPath("a:prstClr") != null)
  540. {
  541. var tint = solidFill.GetTextByPath("a:prstClr/a:tint/@val");
  542. if (tint != null)
  543. {
  544. opcity = double.Parse(tint.Value) / 100000;
  545. }
  546. }
  547. else if (solidFill.GetTextByPath("a:hslClr") != null)
  548. {
  549. var tint = solidFill.GetTextByPath("a:hslClr/a:tint/@val");
  550. if (tint != null)
  551. {
  552. opcity = double.Parse(tint.Value) / 100000;
  553. }
  554. }
  555. else if (solidFill.GetTextByPath("a:sysClr") !=null)
  556. {
  557. var tint = solidFill.GetTextByPath("a:sysClr/a:tint/@val");
  558. if (tint != null)
  559. {
  560. opcity = double.Parse(tint.Value) / 100000;
  561. }
  562. }
  563. return opcity;
  564. }
  565. public Fill GetSolidFill(XmlNode node)
  566. {
  567. if (node == null)
  568. {
  569. return null;
  570. }
  571. Fill fill = new Fill() { Color = "FFF" };
  572. if (PowerPointHelper.GetTextByPath(node, "a:srgbClr").Value != null)
  573. {
  574. fill.Color = PowerPointHelper.GetTextByPath(node, "a:srgbClr/@val").Value; //#...
  575. }
  576. else if (PowerPointHelper.GetTextByPath(node, "a:schemeClr").Value != null)//node["a:schemeClr"] != null)
  577. { //a:schemeClr
  578. var schemeClr = PowerPointHelper.GetTextByPath(node, "a:schemeClr/@val");
  579. //console.log(schemeClr)
  580. fill.Color = GetSchemeColorFromTheme(schemeClr.Value, null); //#...
  581. }
  582. else if (PowerPointHelper.GetTextByPath(node, "a:scrgbClr").Value != null)
  583. {
  584. //<a:scrgbClr r="50%" g="50%" b="50%"/> //Need to test/////////////////////////////////////////////
  585. var defBultColorValsR = PowerPointHelper.GetTextByPath(node, "a:scrgbClr/@r");
  586. var defBultColorValsG = PowerPointHelper.GetTextByPath(node, "a:scrgbClr/@g");
  587. var defBultColorValsB = PowerPointHelper.GetTextByPath(node, "a:scrgbClr/@b");
  588. var red = (defBultColorValsR.Value.IndexOf("%") != -1) ? defBultColorValsR.Value.Split("%").First() : defBultColorValsR.Value;
  589. var green = (defBultColorValsG.Value.IndexOf("%") != -1) ? defBultColorValsG.Value.Split("%").First() : defBultColorValsG.Value;
  590. var blue = (defBultColorValsB.Value.IndexOf("%") != -1) ? defBultColorValsB.Value.Split("%").First() : defBultColorValsB.Value;
  591. var scrgbClr = red + "," + green + "," + blue;
  592. fill.Color = ToHex(255 * (double.Parse(red) / 100)) + ToHex(255 * (double.Parse(green) / 100)) + ToHex(255 * (double.Parse(blue) / 100));
  593. //console.log("scrgbClr: " + scrgbClr);
  594. }
  595. else if (PowerPointHelper.GetTextByPath(node, "a:prstClr").Value != null)
  596. {
  597. //<a:prstClr val="black"/> //Need to test/////////////////////////////////////////////
  598. var prstClr = PowerPointHelper.GetTextByPath(node, "a:prstClr/@val");// node["a:prstClr"]["attrs"]["val"];
  599. fill.Color = GetColorName2Hex(prstClr.Value);
  600. //console.log("prstClr: " + prstClr+" => hexClr: "+color);
  601. }
  602. else if (PowerPointHelper.GetTextByPath(node, "a:hslClr").Value != null)
  603. {
  604. //<a:hslClr hue="14400000" sat="100%" lum="50%"/> //Need to test/////////////////////////////////////////////
  605. var defBultColorVals = PowerPointHelper.GetTextByPath(node, "a:hslClr");//["attrs"];
  606. var defBultColorVals_hue = PowerPointHelper.GetTextByPath(defBultColorVals, "@hue");
  607. var defBultColorVals_sat = PowerPointHelper.GetTextByPath(defBultColorVals, "@sat");
  608. var defBultColorVals_lum = PowerPointHelper.GetTextByPath(defBultColorVals, "@lum");
  609. var hue = double.Parse(defBultColorVals_hue.Value) / 100000;
  610. var sat = double.Parse((defBultColorVals_sat.Value.IndexOf("%") != -1) ? defBultColorVals_sat.Value.Split("%").First() : defBultColorVals_sat.Value) / 100;
  611. var lum = double.Parse((defBultColorVals_lum.Value.IndexOf("%") != -1) ? defBultColorVals_lum.Value.Split("%").First() : defBultColorVals_lum.Value) / 100;
  612. var hslClr = defBultColorVals_hue.Value.ToString() + "," + defBultColorVals_sat.Value.ToString() + "," + defBultColorVals_lum.Value.ToString();
  613. var hsl2rgb = HslToRgb(hue, sat, lum);
  614. fill.Color = ToHex(hsl2rgb.r) + ToHex(hsl2rgb.g) + ToHex(hsl2rgb.b);
  615. //defBultColor = cnvrtHslColor2Hex(hslClr); //TODO
  616. // console.log("hslClr: " + hslClr);
  617. }
  618. else if (PowerPointHelper.GetTextByPath(node, "a:sysClr").Value != null)
  619. {
  620. //<a:sysClr val="windowText" lastClr="000000"/> //Need to test/////////////////////////////////////////////
  621. var sysClr = PowerPointHelper.GetTextByPath(node, "a:sysClr/@lastClr").Value;
  622. if (sysClr != null)
  623. {
  624. fill.Color = sysClr;
  625. }
  626. }
  627. return fill;
  628. }
  629. public string GetSchemeColorFromTheme(string schemeClr, XmlNode sldMasterNode)
  630. {
  631. //<p:clrMap ...> in slide master
  632. // e.g. tx2="dk2" bg2="lt2" tx1="dk1" bg1="lt1" slideLayoutClrOvride
  633. if (slideLayoutClrOvride == null ||slideLayoutClrOvride.Count<=0)
  634. {
  635. var sldLayoutClrOvr = PowerPointHelper.GetTextByPath(sldMasterNode, "p:sldMaster/p:clrMap");
  636. if (sldLayoutClrOvr != null)
  637. {
  638. //获取 overrideClrMapping所有属性节点 检查测试 是否slideLayoutClrOvride 需要被覆盖
  639. slideLayoutClrOvride = new Dictionary<string, string>() {
  640. { "accent1", sldLayoutClrOvr.GetTextByPath("@accent1").Value},
  641. { "accent2", sldLayoutClrOvr.GetTextByPath("@accent2").Value},
  642. { "accent3", sldLayoutClrOvr.GetTextByPath("@accent3").Value},
  643. { "accent4", sldLayoutClrOvr.GetTextByPath("@accent4").Value},
  644. { "accent5", sldLayoutClrOvr.GetTextByPath("@accent5").Value},
  645. { "accent6", sldLayoutClrOvr.GetTextByPath("@accent6").Value},
  646. { "bg1", sldLayoutClrOvr.GetTextByPath("@bg1").Value},
  647. { "bg2", sldLayoutClrOvr.GetTextByPath("@bg2").Value},
  648. { "folHlink", sldLayoutClrOvr.GetTextByPath("@folHlink").Value},
  649. { "hlink", sldLayoutClrOvr.GetTextByPath("@hlink").Value},
  650. { "tx1", sldLayoutClrOvr.GetTextByPath("@tx1").Value},
  651. { "tx2", sldLayoutClrOvr.GetTextByPath("@tx2").Value}
  652. };
  653. }
  654. }
  655. //console.log(slideLayoutClrOvride);
  656. var schmClrName = schemeClr.Substring(2);
  657. if (slideLayoutClrOvride != null)
  658. {
  659. switch (schmClrName)
  660. {
  661. case "tx1":
  662. case "tx2":
  663. case "bg1":
  664. case "bg2":
  665. schemeClr = "a:" +slideLayoutClrOvride[schmClrName];
  666. //schemeClr = "a:" + slideLayoutClrOvride[schmClrName];
  667. //console.log(schmClrName+ "=> "+schemeClr);
  668. break;
  669. }
  670. }
  671. else
  672. {
  673. switch (schmClrName)
  674. {
  675. case "tx1":
  676. schemeClr = "a:dk1";
  677. break;
  678. case "tx2":
  679. schemeClr = "a:dk2";
  680. break;
  681. case "bg1":
  682. schemeClr = "a:lt1";
  683. break;
  684. case "bg2":
  685. schemeClr = "a:lt2";
  686. break;
  687. }
  688. }
  689. //var refNode = PowerPointHelper.GetTextByPathList(themeContent, "a:theme/a:themeElements/a:clrScheme/"+ schemeClr.Value);
  690. var color = PowerPointHelper.GetTextByPath(themeContent, "a:theme/a:themeElements/a:clrScheme/" + schemeClr + "/a:srgbClr/@val");
  691. if (color == null)//&& refNode != null
  692. {
  693. color = PowerPointHelper.GetTextByPath(themeContent, "a:theme/a:themeElements/a:clrScheme/" + schemeClr + "/a:sysClr/@lastClr");
  694. }
  695. //console.log(color)
  696. return color.Value;
  697. }
  698. private static string ToHex(dynamic n)
  699. {
  700. string hex = n.toString(16);
  701. while (hex.Length < 2) { hex = "0" + hex; }
  702. return hex;
  703. }
  704. private static dynamic HslToRgb(double hue, double sat, double light)
  705. {
  706. double t1, t2, r, g, b;
  707. hue /= 60;
  708. if (light <= 0.5)
  709. {
  710. t2 = light * (sat + 1);
  711. }
  712. else
  713. {
  714. t2 = light + sat - (light * sat);
  715. }
  716. t1 = light * 2 - t2;
  717. r = HueToRgb(t1, t2, hue + 2) * 255;
  718. g = HueToRgb(t1, t2, hue) * 255;
  719. b = HueToRgb(t1, t2, hue - 2) * 255;
  720. return new { r, g, b };
  721. }
  722. private static double HueToRgb(double t1, double t2, double hue)
  723. {
  724. if (hue < 0) hue += 6;
  725. if (hue >= 6) hue -= 6;
  726. if (hue < 1) return (t2 - t1) * hue + t1;
  727. else if (hue < 3) return t2;
  728. else if (hue < 4) return (t2 - t1) * (4 - hue) + t1;
  729. else return t1;
  730. }
  731. private static string GetColorName2Hex(string name)
  732. {
  733. var hex = "";
  734. var colorName = new List<string> { "AntiqueWhite", "Aqua", "Aquamarine", "Azure", "Beige", "Bisque", "Black", "BlanchedAlmond", "Blue", "BlueViolet", "Brown", "BurlyWood", "CadetBlue", "Chartreuse", "Chocolate", "Coral", "CornflowerBlue", "Cornsilk", "Crimson", "Cyan", "DarkBlue", "DarkCyan", "DarkGoldenRod", "DarkGray", "DarkGrey", "DarkGreen", "DarkKhaki", "DarkMagenta", "DarkOliveGreen", "DarkOrange", "DarkOrchid", "DarkRed", "DarkSalmon", "DarkSeaGreen", "DarkSlateBlue", "DarkSlateGray", "DarkSlateGrey", "DarkTurquoise", "DarkViolet", "DeepPink", "DeepSkyBlue", "DimGray", "DimGrey", "DodgerBlue", "FireBrick", "FloralWhite", "ForestGreen", "Fuchsia", "Gainsboro", "GhostWhite", "Gold", "GoldenRod", "Gray", "Grey", "Green", "GreenYellow", "HoneyDew", "HotPink", "IndianRed", "Indigo", "Ivory", "Khaki", "Lavender", "LavenderBlush", "LawnGreen", "LemonChiffon", "LightBlue", "LightCoral", "LightCyan", "LightGoldenRodYellow", "LightGray", "LightGrey", "LightGreen", "LightPink", "LightSalmon", "LightSeaGreen", "LightSkyBlue", "LightSlateGray", "LightSlateGrey", "LightSteelBlue", "LightYellow", "Lime", "LimeGreen", "Linen", "Magenta", "Maroon", "MediumAquaMarine", "MediumBlue", "MediumOrchid", "MediumPurple", "MediumSeaGreen", "MediumSlateBlue", "MediumSpringGreen", "MediumTurquoise", "MediumVioletRed", "MidnightBlue", "MintCream", "MistyRose", "Moccasin", "NavajoWhite", "Navy", "OldLace", "Olive", "OliveDrab", "Orange", "OrangeRed", "Orchid", "PaleGoldenRod", "PaleGreen", "PaleTurquoise", "PaleVioletRed", "PapayaWhip", "PeachPuff", "Peru", "Pink", "Plum", "PowderBlue", "Purple", "RebeccaPurple", "Red", "RosyBrown", "RoyalBlue", "SaddleBrown", "Salmon", "SandyBrown", "SeaGreen", "SeaShell", "Sienna", "Silver", "SkyBlue", "SlateBlue", "SlateGray", "SlateGrey", "Snow", "SpringGreen", "SteelBlue", "Tan", "Teal", "Thistle", "Tomato", "Turquoise", "Violet", "Wheat", "White", "WhiteSmoke", "Yellow", "YellowGreen" };
  735. var colorHex = new List<string> { "f0f8ff", "faebd7", "00ffff", "7fffd4", "f0ffff", "f5f5dc", "ffe4c4", "000000", "ffebcd", "0000ff", "8a2be2", "a52a2a", "deb887", "5f9ea0", "7fff00", "d2691e", "ff7f50", "6495ed", "fff8dc", "dc143c", "00ffff", "00008b", "008b8b", "b8860b", "a9a9a9", "a9a9a9", "006400", "bdb76b", "8b008b", "556b2f", "ff8c00", "9932cc", "8b0000", "e9967a", "8fbc8f", "483d8b", "2f4f4f", "2f4f4f", "00ced1", "9400d3", "ff1493", "00bfff", "696969", "696969", "1e90ff", "b22222", "fffaf0", "228b22", "ff00ff", "dcdcdc", "f8f8ff", "ffd700", "daa520", "808080", "808080", "008000", "adff2f", "f0fff0", "ff69b4", "cd5c5c", "4b0082", "fffff0", "f0e68c", "e6e6fa", "fff0f5", "7cfc00", "fffacd", "add8e6", "f08080", "e0ffff", "fafad2", "d3d3d3", "d3d3d3", "90ee90", "ffb6c1", "ffa07a", "20b2aa", "87cefa", "778899", "778899", "b0c4de", "ffffe0", "00ff00", "32cd32", "faf0e6", "ff00ff", "800000", "66cdaa", "0000cd", "ba55d3", "9370db", "3cb371", "7b68ee", "00fa9a", "48d1cc", "c71585", "191970", "f5fffa", "ffe4e1", "ffe4b5", "ffdead", "000080", "fdf5e6", "808000", "6b8e23", "ffa500", "ff4500", "da70d6", "eee8aa", "98fb98", "afeeee", "db7093", "ffefd5", "ffdab9", "cd853f", "ffc0cb", "dda0dd", "b0e0e6", "800080", "663399", "ff0000", "bc8f8f", "4169e1", "8b4513", "fa8072", "f4a460", "2e8b57", "fff5ee", "a0522d", "c0c0c0", "87ceeb", "6a5acd", "708090", "708090", "fffafa", "00ff7f", "4682b4", "d2b48c", "008080", "d8bfd8", "ff6347", "40e0d0", "ee82ee", "f5deb3", "ffffff", "f5f5f5", "ffff00", "9acd32" };
  736. var findIndx = colorName.IndexOf(name);
  737. if (findIndx != -1)
  738. {
  739. hex = colorHex[findIndx];
  740. }
  741. return hex;
  742. }
  743. public static string GetFillType(XmlNode node)
  744. {
  745. //Need to test/////////////////////////////////////////////
  746. //SOLID_FILL
  747. //PIC_FILL
  748. //GRADIENT_FILL
  749. //PATTERN_FILL
  750. //NO_FILL
  751. var fillType = "";
  752. if( node.GetTextByPath( "a:noFill")!= null)
  753. {
  754. fillType = "NO_FILL";
  755. }
  756. if (node.GetTextByPath("a:solidFill") != null)
  757. {
  758. fillType = "SOLID_FILL";
  759. }
  760. if (node.GetTextByPath("a:gradFill") != null)
  761. {
  762. fillType = "GRADIENT_FILL";
  763. }
  764. if (node.GetTextByPath("a:pattFill") != null)
  765. {
  766. fillType = "PATTERN_FILL";
  767. }
  768. if (node.GetTextByPath("a:blipFill") != null)
  769. {
  770. fillType = "PIC_FILL";
  771. }
  772. return fillType;
  773. }
  774. private dynamic IndexNodes(XmlNode content)
  775. {
  776. var idTable = new Dictionary<string, Dictionary<string,XmlNode>>();
  777. var idxTable = new Dictionary<string, Dictionary<string, XmlNode>>();
  778. var typeTable = new Dictionary<string, Dictionary<string, XmlNode>>();
  779. var spTreeNode = content.GetTextByPath("p:cSld/p:spTree");
  780. Dictionary<string, Dictionary<string, string>> slideResObj = new Dictionary<string, Dictionary<string, string>>();
  781. var spTreeNodeChildren = spTreeNode.ChildNodes;
  782. foreach (XmlNode child in spTreeNodeChildren)
  783. {
  784. if (child.Name.Equals("p:nvGrpSpPr") || child.Name.Equals("p:grpSpPr"))
  785. {
  786. continue;
  787. }
  788. //var targetNode = child.ChildNodes;
  789. var targetNode = child.GetTextByPath("p:nvSpPr");
  790. // < p:cNvCxnSpPr >
  791. // < a:cxnSpLocks /> ///这个是什么意思
  792. // </ p:cNvCxnSpPr >
  793. if (targetNode == null) {
  794. targetNode = child.GetTextByPath("p:nvCxnSpPr");
  795. }
  796. var id = targetNode.GetTextByPath("p:cNvPr/@id");
  797. var idx = targetNode.GetTextByPath("p:nvPr/p:ph/@idx");
  798. var type = targetNode.GetTextByPath("p:nvPr/p:ph/@type");
  799. Dictionary<string, XmlNode> node = new Dictionary<string, XmlNode>();
  800. if (child.ChildNodes != null) {
  801. foreach (XmlNode xmlNode in child.ChildNodes) {
  802. node.TryAdd(xmlNode.Name, xmlNode);
  803. }
  804. }
  805. if (id != null)
  806. {
  807. idTable.Add(id.Value, node);
  808. }
  809. if (idx != null)
  810. {
  811. idxTable.Add(idx.Value, node);
  812. }
  813. if (type != null)
  814. {
  815. typeTable.Add(type.Value, node);
  816. }
  817. }
  818. return new { idTable, idxTable, typeTable };
  819. }
  820. private dynamic GetSlideSize(XmlDocument xdoc)
  821. {
  822. var sldSzNode = xdoc.GetTextByPath("//pkg:part[@pkg:name='/ppt/presentation.xml']/pkg:xmlData/p:presentation/p:sldSz");
  823. double width = double.Parse(sldSzNode.GetTextByPath("@cx").Value) * px96 / px914400;
  824. double height = double.Parse(sldSzNode.GetTextByPath("@cy").Value) * px96 / px914400;
  825. return new { width, height };
  826. }
  827. private async Task<AzureBlobModel> GetThumbnailModel(XmlDocument xdoc, string shaCode)
  828. {
  829. var thumbnailNode = xdoc.GetTextByPath("//pkg:part[@pkg:name='/docProps/thumbnail.jpeg']");
  830. if (thumbnailNode != null)
  831. {
  832. var contentType = thumbnailNode.GetTextByPath("@pkg:contentType");
  833. var thumbnail = thumbnailNode.InnerText;
  834. return await PowerPointHelper.SaveBase64ToBolob(thumbnail, contentType.Value, shaCode, "thumbnail", azureBlobDBRepository);
  835. }
  836. return null;
  837. }
  838. private XmlNode LoadTheme(XmlDocument xdoc)
  839. {
  840. 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");
  841. // "/ppt/theme/theme1.xml"
  842. string themeURI = "/ppt/" + themeRelationship.Value;
  843. return xdoc.GetTextByPath("//pkg:part[@pkg:name='" + themeURI + "']");
  844. }
  845. }
  846. }