ShapeGenerator.cs 81 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789
  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.Drawing;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Threading.Tasks;
  13. using System.Xml;
  14. using System.Xml.Linq;
  15. using System.Xml.XPath;
  16. using TEAMModelOS.SDK.Context.Constant;
  17. using TEAMModelOS.SDK.Context.Constant.Common;
  18. using TEAMModelOS.SDK.Context.Exception;
  19. using TEAMModelOS.SDK.Helper.Common.ColorHelper;
  20. using TEAMModelOS.SDK.Helper.Common.JsonHelper;
  21. using TEAMModelOS.SDK.Helper.Common.StringHelper;
  22. using TEAMModelOS.SDK.Helper.Security.ShaHash;
  23. using TEAMModelOS.SDK.Module.AzureBlob.Container;
  24. using TEAMModelOS.SDK.Module.AzureBlob.Interfaces;
  25. using TEAMModelOS.Service.Models.PowerPoint.Inner;
  26. using ColorMap = DocumentFormat.OpenXml.Presentation.ColorMap;
  27. using Fill = HiTeachCC.Model.PowerPoint.Fill;
  28. using Position = HiTeachCC.Model.PowerPoint.Position;
  29. namespace HiTeachCC.Service.PowerPoint.Implement
  30. {
  31. public class ShapeGenerator : IShapeGenerator
  32. {
  33. public string fileShaCode { get; set; }
  34. bool isDone = false;
  35. List<object> MsgQueue = new List<object>();
  36. private Dictionary<string, string> slideLayoutClrOvride { get; set; }
  37. private XmlNode themeContent { get; set; }
  38. int chartID = 0;
  39. int _order = 1;
  40. int titleFontSize = 42;
  41. int bodyFontSize = 20;
  42. int otherFontSize = 16;
  43. bool isSlideMode = false;
  44. Dictionary<string, Dictionary<string, string>> styleTable = new Dictionary<string, Dictionary<string, string>>();
  45. const double px96 = 96.00, px72 = 72.00, px914400 = 914400.00, px12700 = 12700.00;
  46. const double rot60000 = 60000.00;
  47. private readonly IAzureBlobDBRepository azureBlobDBRepository;
  48. public ShapeGenerator(IAzureBlobDBRepository _azureBlobDBRepository)
  49. {
  50. azureBlobDBRepository = _azureBlobDBRepository;
  51. }
  52. public async Task<Dictionary<string, object>> LoadPresentation(IFormFile file)
  53. {
  54. Dictionary<string, object> resdict = new Dictionary<string, object>();
  55. if (FileType.GetExtention(file.FileName).ToLower().Equals("pptx"))
  56. {
  57. ConvertPPTX(file, resdict);
  58. return resdict;
  59. }
  60. else if (FileType.GetExtention(file.FileName).ToLower().Equals("pdf"))
  61. {
  62. // await ProcessPDF(file, resdict);
  63. return resdict;
  64. }
  65. else
  66. {
  67. throw new BizException("file type does not support!", 500);
  68. }
  69. }
  70. public Dictionary<string, object> ConvertPPTX(IFormFile file, Dictionary<string, object> resdict)
  71. {
  72. string shaCode= fileShaCode = ShaHashHelper.GetSHA1(file.OpenReadStream());
  73. using (PresentationDocument presentationDocument = PresentationDocument.Open(file.OpenReadStream(), false))
  74. {
  75. if (presentationDocument == null)
  76. {
  77. throw new ArgumentNullException("presentationDocument");
  78. }
  79. XDocument xdoc = presentationDocument.ToFlatOpcDocument();
  80. XmlDocument xmlDocument = new XmlDocument();
  81. xmlDocument.LoadXml(xdoc.ToString());
  82. var rslt_ary = ProcessPPTX(xmlDocument, shaCode);
  83. //TODO
  84. return null;
  85. }
  86. }
  87. /// <summary>
  88. /// 加载PPTX文件
  89. /// </summary>
  90. /// <param name="presentationFile"></param>
  91. /// <returns></returns>
  92. public async Task<List<Dictionary<string, object>>> ProcessPPTX(XmlDocument xdoc, string shaCode)
  93. {
  94. List<Dictionary<string, object>> post_ary = new List<Dictionary<string, object>>();
  95. var dateBefore = DateTimeOffset.Now.UtcTicks;
  96. AzureBlobModel thumbnailModel = await GetThumbnailModel(xdoc, shaCode);
  97. post_ary.Add(new Dictionary<string, object> { { "pptx-thumb", thumbnailModel } });
  98. //获取全部的/ppt/slides/slide1.xml--->>/ppt/slides/slide(n).xml
  99. var slideNodes = xdoc.GetTextByPathList("//pkg:part[@pkg:contentType='application/vnd.openxmlformats-officedocument.presentationml.slide+xml']");
  100. //获取全部的/ppt/slideLayouts/slideLayout1.xml--->>/ppt/slideLayouts/slideLayout(n).xml
  101. var slideLayoutNodes = xdoc.GetTextByPathList("//pkg:part[@pkg:contentType='application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml']");
  102. //获取ppt的宽高
  103. var slideSize = GetSlideSize(xdoc);
  104. post_ary.Add(new Dictionary<string, object> { { "slideSize", slideSize } });
  105. //加载当前PPT使用到的PPT节点
  106. themeContent = LoadTheme(xdoc);
  107. //获取所有的表格样式节点
  108. var tableStyles = xdoc.GetTextByPath("//pkg:part[@pkg:name='/ppt/tableStyles.xml']/pkg:xmlData/a:tblStyleLst");
  109. //处理slide1---slide(n)
  110. int numOfSlides = slideNodes.Count;
  111. for (int i = 0; i < numOfSlides; i++)
  112. {
  113. string filename = slideNodes[i].GetTextByPath("@pkg:name").Value;
  114. //处理当前页的幻灯片
  115. string slideHtml = ProcessSingleSlide(xdoc, slideNodes[i], filename, i, slideSize);
  116. post_ary.Add(new Dictionary<string, object> { { "slide", slideHtml } });
  117. post_ary.Add(new Dictionary<string, object> { { "progress-update", (i + 1) * 100 / numOfSlides } });
  118. }
  119. post_ary.Add(new Dictionary<string, object> { { "globalCSS", GenGlobalCSS() } });
  120. var dateAfter = DateTimeOffset.Now.UtcTicks;
  121. post_ary.Add(new Dictionary<string, object> { { "ExecutionTime", dateAfter - dateBefore } });
  122. return post_ary;
  123. }
  124. private Dictionary<string, string> GenGlobalCSS()
  125. {
  126. Dictionary<string, string> cssText = new Dictionary<string, string>();
  127. foreach (var key in styleTable.Keys)
  128. {
  129. // cssText += "div ." + styleTable[key]["name"] + "{" + styleTable[key]["text"] + "}\n"; //section > div
  130. var cssTextKey = styleTable[key]["name"];
  131. var cssTextValue = styleTable[key]["text"];
  132. cssText.Add(cssTextKey, cssTextValue);
  133. }
  134. return cssText;
  135. }
  136. private string ProcessSingleSlide(XmlDocument xdoc, XmlNode xnode, string sldFileName, int index, dynamic slideSize)
  137. {
  138. var resName = sldFileName.Replace("slides/slide", "slides/_rels/slide") + ".rels";
  139. var RelationshipArray = xdoc.GetTextByPathList("//pkg:part[@pkg:name='" + resName + "']/pkg:xmlData/rel:Relationships/rel:Relationship");
  140. Dictionary<string, Dictionary<string, string>> slideResObj = new Dictionary<string, Dictionary<string, string>>();
  141. var layoutFilename = "";
  142. foreach (XmlNode Relationship in RelationshipArray)
  143. {
  144. var RelationshipType = Relationship.GetTextByPath("@Type");
  145. if (RelationshipType.Value.Equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"))
  146. {
  147. layoutFilename = Relationship.GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  148. }
  149. else
  150. {
  151. //case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide":
  152. //case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image":
  153. //case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart":
  154. //case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink":
  155. Dictionary<string, string> dict = new Dictionary<string, string>();
  156. string Type = Relationship.GetTextByPath("@Type").Value.Replace("http://schemas.openxmlformats.org/officeDocument/2006/relationships/", "");
  157. string Target = Relationship.GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  158. string Id = Relationship.GetTextByPath("@Id").Value;
  159. dict.Add("type", Type);
  160. dict.Add("target", Target);
  161. slideResObj.Add(Id, dict);
  162. }
  163. }
  164. // Open slideLayoutXX.xml
  165. var slideLayoutContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + layoutFilename + "']");
  166. NodesTable slideLayoutTables = IndexNodes(slideLayoutContent.GetTextByPath("pkg:xmlData/p:sldLayout"));
  167. ///ppt/slides/slide5.xml 也包含a:overrideClrMapping
  168. ////ppt/slideLayouts/slideLayout13.xml 也包含a:overrideClrMapping
  169. var sldLayoutClrOvr = slideLayoutContent.GetTextByPath("pkg:xmlData/p:sldLayout/p:clrMapOvr/a:overrideClrMapping");
  170. if (sldLayoutClrOvr != null)
  171. {
  172. //获取 overrideClrMapping所有属性节点
  173. slideLayoutClrOvride = new Dictionary<string, string>() {
  174. { "accent1", sldLayoutClrOvr.GetTextByPath("@accent1").Value},
  175. { "accent2", sldLayoutClrOvr.GetTextByPath("@accent2").Value},
  176. { "accent3", sldLayoutClrOvr.GetTextByPath("@accent3").Value},
  177. { "accent4", sldLayoutClrOvr.GetTextByPath("@accent4").Value},
  178. { "accent5", sldLayoutClrOvr.GetTextByPath("@accent5").Value},
  179. { "accent6", sldLayoutClrOvr.GetTextByPath("@accent6").Value},
  180. { "bg1", sldLayoutClrOvr.GetTextByPath("@bg1").Value},
  181. { "bg2", sldLayoutClrOvr.GetTextByPath("@bg2").Value},
  182. { "folHlink", sldLayoutClrOvr.GetTextByPath("@folHlink").Value},
  183. { "hlink", sldLayoutClrOvr.GetTextByPath("@hlink").Value},
  184. { "tx1", sldLayoutClrOvr.GetTextByPath("@tx1").Value},
  185. { "tx2", sldLayoutClrOvr.GetTextByPath("@tx2").Value}
  186. };
  187. }
  188. // =====< Step 2 >=====
  189. // Read slide master filename of the slidelayout (Get slideMasterXX.xml)
  190. // @resName: ppt/slideLayouts/slideLayout1.xml
  191. // @masterName: ppt/slideLayouts/_rels/slideLayout1.xml.rels
  192. var slideLayoutResFilename = layoutFilename.Replace("slideLayouts/slideLayout", "slideLayouts/_rels/slideLayout") + ".rels";
  193. var slideLayoutResContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + slideLayoutResFilename + "']");
  194. ///查看js 是替换之前 还是添加
  195. RelationshipArray = slideLayoutResContent.GetTextByPathList("pkg:xmlData/rel:Relationships/rel:Relationship");
  196. var masterFilename = "";
  197. Dictionary<string, Dictionary<string, string>> layoutResObj = new Dictionary<string, Dictionary<string, string>>();
  198. for (int i = 0; i < RelationshipArray.Count; i++)
  199. {
  200. if (RelationshipArray[i].GetTextByPath("@Type").Value.Equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster"))
  201. {
  202. masterFilename = RelationshipArray[i].GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  203. }
  204. else
  205. {
  206. Dictionary<string, string> dict = new Dictionary<string, string>();
  207. string Type = RelationshipArray[i].GetTextByPath("@Type").Value.Replace("http://schemas.openxmlformats.org/officeDocument/2006/relationships/", "");
  208. string Target = RelationshipArray[i].GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  209. string Id = RelationshipArray[i].GetTextByPath("@Id").Value;
  210. dict.Add("type", Type);
  211. dict.Add("target", Target);
  212. layoutResObj.Add(Id, dict);
  213. }
  214. }
  215. // Open slideMasterXX.xml
  216. var slideMasterContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + masterFilename + "']");
  217. var slideMasterTextStyles = slideMasterContent.GetTextByPath("pkg:xmlData/p:sldMaster/p:txStyles");
  218. var slideMasterTables = IndexNodes(slideMasterContent.GetTextByPath("pkg:xmlData/p:sldMaster"));
  219. /////////////////Amir/////////////
  220. //Open slideMasterXX.xml.rels
  221. var slideMasterResFilename = masterFilename.Replace("slideMasters/slideMaster", "slideMasters/_rels/slideMaster") + ".rels";
  222. var slideMasterResContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + slideMasterResFilename + "']");
  223. RelationshipArray = slideMasterResContent.GetTextByPathList("pkg:xmlData/rel:Relationships/rel:Relationship");
  224. var themeFilename = "";
  225. Dictionary<string, Dictionary<string, string>> masterResObj = new Dictionary<string, Dictionary<string, string>>();
  226. for (int i = 0; i < RelationshipArray.Count; i++)
  227. {
  228. if (RelationshipArray[i].GetTextByPath("@Type").Value.Equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"))
  229. {
  230. themeFilename = RelationshipArray[i].GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  231. }
  232. else
  233. {
  234. Dictionary<string, string> dict = new Dictionary<string, string>();
  235. string Type = RelationshipArray[i].GetTextByPath("@Type").Value.Replace("http://schemas.openxmlformats.org/officeDocument/2006/relationships/", "");
  236. string Target = RelationshipArray[i].GetTextByPath("@Target").Value.Replace("../", "/ppt/");
  237. string Id = RelationshipArray[i].GetTextByPath("@Id").Value;
  238. dict.Add("type", Type);
  239. dict.Add("target", Target);
  240. masterResObj.Add(Id, dict);
  241. }
  242. }
  243. //Load Theme file
  244. if (!string.IsNullOrEmpty(themeFilename))
  245. {
  246. themeContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + themeFilename + "']");
  247. }
  248. Console.WriteLine(sldFileName, layoutFilename, masterFilename, themeFilename);
  249. // =====< Step 3 >=====
  250. var slideContent = xdoc.GetTextByPath("//pkg:part[@pkg:name='" + sldFileName + "']");
  251. var spTreeNode = slideContent.GetTextByPath("pkg:xmlData/p:sld/p:cSld/p:spTree");
  252. WarpObj warpObj = new WarpObj
  253. {
  254. zip = xdoc,
  255. slideLayoutTables= slideLayoutTables,
  256. slideMasterTables = slideMasterTables,
  257. slideMasterTextStyles= slideMasterTextStyles,
  258. slideResObj= slideResObj,
  259. layoutResObj= layoutResObj,
  260. masterResObj= masterResObj
  261. };
  262. var bgColor = GetSlideBackgroundFill(slideContent, slideLayoutContent, slideMasterContent, warpObj);
  263. var result = "<div class='slide' style='width:" + slideSize.width + "px; height:" + slideSize.height + "px;" + bgColor + "'>";
  264. //result += "<div>"+getBackgroundShapes(slideContent, slideLayoutContent, slideMasterContent,warpObj) + "</div>" - TODO
  265. if (spTreeNode != null) {
  266. var nodes = spTreeNode.ChildNodes;
  267. foreach (XmlNode node in nodes)
  268. {
  269. result += ProcessNodesInSlide(node.Name, node, warpObj);
  270. }
  271. }
  272. return "";
  273. }
  274. private async Task<dynamic> ProcessNodesInSlide(string nodeKey, XmlNode nodeValue, WarpObj warpObj)
  275. {
  276. var result = "";
  277. switch (nodeKey)
  278. {
  279. case "p:sp": // Shape, Text
  280. result = await ProcessSpNode(nodeValue, warpObj);
  281. break;
  282. case "p:cxnSp": // Shape, Text (with connection)
  283. result = ProcessCxnSpNode(nodeValue, warpObj);
  284. break;
  285. case "p:pic": // Picture
  286. result = ProcessPicNode(nodeValue, warpObj);
  287. break;
  288. case "p:graphicFrame": // Chart, Diagram, Table
  289. result = ProcessGraphicFrameNode(nodeValue, warpObj);
  290. break;
  291. case "p:grpSp":
  292. result = ProcessGroupSpNode(nodeValue, warpObj);
  293. break;
  294. case "mc:AlternateContent": //Equations and formulas as Image
  295. var mcFallbackNode = nodeValue.GetTextByPath("mc:Fallback/p:sp");
  296. result = await ProcessSpNode(mcFallbackNode, warpObj);
  297. break;
  298. default:
  299. break;
  300. }
  301. return result;
  302. }
  303. private string ProcessGroupSpNode(XmlNode node, WarpObj warpObj)
  304. {
  305. var factor =1.00* px96 / px914400;
  306. var xfrmNode = node.GetTextByPath("p:grpSpPr/a:xfrm");
  307. var x = int.Parse(xfrmNode.GetTextByPath("a:off/@x").Value) * factor;
  308. var y = int.Parse(xfrmNode.GetTextByPath("a:off/@y").Value) * factor;
  309. var chx = int.Parse(xfrmNode.GetTextByPath("a:chOff/@x").Value) * factor;
  310. var chy = int.Parse(xfrmNode.GetTextByPath("a:chOff/@y").Value) * factor;
  311. var cx = int.Parse(xfrmNode.GetTextByPath("a:ext/@cx").Value) * factor;
  312. var cy = int.Parse(xfrmNode.GetTextByPath("a:ext/@cy").Value) * factor;
  313. var chcx = int.Parse(xfrmNode.GetTextByPath("a:chExt/@cx").Value) * factor;
  314. var chcy = int.Parse(xfrmNode.GetTextByPath("a:chExt/@cy").Value) * factor;
  315. var order = node["attrs"]["order"];
  316. 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;'>";
  317. // Procsee all child nodes
  318. var nodes = node.ChildNodes;
  319. foreach(XmlNode nd in nodes)
  320. {
  321. result += ProcessNodesInSlide(nd.Name, nd, warpObj);
  322. }
  323. result += "</div>";
  324. return result;
  325. }
  326. private string ProcessGraphicFrameNode(XmlNode nodeValue, WarpObj warpObj)
  327. {
  328. throw new NotImplementedException();
  329. }
  330. private string ProcessPicNode(XmlNode node , WarpObj warpObj)
  331. {
  332. var rtrnData = "";
  333. var mediaPicFlag = false;
  334. var order = node.GetTextByPath("@order");
  335. var rid = node.GetTextByPath("p:blipFill/a:blip/@r:embed");
  336. var imgName = warpObj.slideResObj[rid.Value]["target"];
  337. // var imgFileExt = extractFileExtension(imgName).toLowerCase();
  338. //var zip = warpObj["zip"];
  339. var imgData = warpObj.zip.GetTextByPath("//pkg:part[@pkg:name='" + imgName+ "']");
  340. var imgFileExt = imgData.GetTextByPath("@pkg:contentType").Value;
  341. var imgArrayBuffer = imgData.InnerText;
  342. var mimeType = "";
  343. var xfrmNode = node.GetTextByPath("p:spPr/a:xfrm");
  344. ///////////////////////////////////////Amir//////////////////////////////
  345. double rotate = 0;
  346. var rotateNode = node.GetTextByPath("p:spPr/a:xfrm/@rot");
  347. if (rotateNode != null)
  348. {
  349. rotate = AngleToDegrees(rotateNode);
  350. }
  351. //video
  352. var vdoNode = node.GetTextByPath("p:nvPicPr/p:nvPr/a:videoFile");
  353. XmlNode vdoRid, vdoMimeType, uInt8Array, blob, vdoBlob;
  354. string vdoFile , vdoFileExt;
  355. bool mediaSupportFlag = false;
  356. // var mediaProcess = settings.mediaProcess;
  357. if (vdoNode != null)
  358. {
  359. vdoRid = vdoNode.GetTextByPath("@r:link");
  360. vdoFile = warpObj.slideResObj[vdoRid.Value]["target"];
  361. uInt8Array = warpObj.zip.GetTextByPath("//pkg:part[@pkg:name='" + vdoFile + "']");
  362. vdoFileExt = uInt8Array.GetTextByPath("@pkg:contentType").Value;
  363. if (vdoFileExt == "mp4" || vdoFileExt == "webm" || vdoFileExt == "ogg")
  364. {
  365. /// 处理为AzureBlob 上传
  366. // vdoMimeType = getMimeType(vdoFileExt);
  367. // blob = new Blob([uInt8Array], {
  368. // type: vdoMimeType
  369. // });
  370. // vdoBlob = URL.createObjectURL(blob);
  371. mediaSupportFlag = true;
  372. mediaPicFlag = true;
  373. }
  374. }
  375. //Audio
  376. var audioNode = node.GetTextByPath("p:nvPicPr/p:nvPr/a:audioFile");
  377. XmlNode audioRid, audioMimeType, uInt8ArrayAudio, blobAudio, audioBlob;
  378. string audioFile, audioFileExt;
  379. var audioPlayerFlag = false;
  380. // var audioObjc;
  381. if (audioNode !=null )
  382. {
  383. audioRid = audioNode.GetTextByPath("@r:link");
  384. audioFile = warpObj.slideResObj[audioRid.Value]["target"];
  385. uInt8ArrayAudio = warpObj.zip.GetTextByPath("//pkg:part[@pkg:name='" + audioFile + "']");
  386. audioFileExt = uInt8ArrayAudio.GetTextByPath("@pkg:contentType").Value;
  387. if (audioFileExt == "mp3" || audioFileExt == "wav" || audioFileExt == "ogg")
  388. {
  389. //uInt8ArrayAudio = zip.file(audioFile).asArrayBuffer();
  390. //blobAudio = new Blob([uInt8ArrayAudio]);
  391. //audioBlob = URL.createObjectURL(blobAudio);
  392. //var cx = parseInt(xfrmNode["a:ext"]["attrs"]["cx"]) * 20;
  393. //var cy = xfrmNode["a:ext"]["attrs"]["cy"];
  394. //var x = parseInt(xfrmNode["a:off"]["attrs"]["x"]) / 2.5;
  395. //var y = xfrmNode["a:off"]["attrs"]["y"];
  396. //audioObjc = {
  397. // "a:ext" : {
  398. // "attrs":{
  399. // "cx":cx,
  400. // "cy":cy
  401. // }
  402. // },
  403. // "a:off":{
  404. // "attrs":{
  405. // "x":x,
  406. // "y":y
  407. // }
  408. // }
  409. //}
  410. audioPlayerFlag = true;
  411. mediaSupportFlag = true;
  412. mediaPicFlag = true;
  413. }
  414. }
  415. //console.log(node)
  416. //////////////////////////////////////////////////////////////////////////
  417. mimeType = imgFileExt ;
  418. //rtrnData = "<div class='block content' style='" +
  419. // (( audioPlayerFlag) ? GetPosition(audioObjc, null, null) : GetPosition(xfrmNode, null, null)) +
  420. // (( audioPlayerFlag) ? GetSize(audioObjc, null, null) :GetSize(xfrmNode, null, null)) +
  421. // " z-index: " + order + ";" +
  422. // "transform: rotate(" + rotate + "deg);'>";
  423. //if ((vdoNode ==null && audioNode ==null) || !mediaSupportFlag)
  424. //{
  425. // rtrnData += "<img src='data:" + mimeType + ";base64," + base64ArrayBuffer(imgArrayBuffer) + "' style='width: 100%; height: 100%'/>";
  426. //}
  427. //else if ((vdoNode !=null || audioNode !=null) && mediaSupportFlag)
  428. //{
  429. // if (vdoNode !=null)
  430. // {
  431. // rtrnData += "<video src='" + vdoBlob + "' controls style='width: 100%; height: 100%'>Your browser does not support the video tag.</video>";
  432. // }
  433. // if (audioNode !=null)
  434. // {
  435. // rtrnData += "<audio id='audio_player' controls ><source src='" + audioBlob + "'></audio>";
  436. // }
  437. //}
  438. if (!mediaSupportFlag && mediaPicFlag)
  439. {
  440. rtrnData += "<span style='color:red;font-size:40px;position: absolute;'>This media file Not supported by HTML5</span>";
  441. }
  442. if ((vdoNode !=null || audioNode !=null) && mediaSupportFlag)
  443. {
  444. //console.log("Founded supported media file but media process disabled (mediaProcess=false)");
  445. }
  446. rtrnData += "</div>";
  447. //console.log(rtrnData)
  448. return rtrnData;
  449. //throw new NotImplementedException();
  450. }
  451. private string ProcessCxnSpNode(XmlNode nodeValue, WarpObj warpObj)
  452. {
  453. throw new NotImplementedException();
  454. }
  455. private async Task<string> ProcessSpNode(XmlNode node , WarpObj warpObj)
  456. {
  457. /*
  458. * 958 <xsd:complexType name="CT_GvmlShape">
  459. * 959 <xsd:sequence>
  460. * 960 <xsd:element name="nvSpPr" type="CT_GvmlShapeNonVisual" minOccurs="1" maxOccurs="1"/>
  461. * 961 <xsd:element name="spPr" type="CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
  462. * 962 <xsd:element name="txSp" type="CT_GvmlTextShape" minOccurs="0" maxOccurs="1"/>
  463. * 963 <xsd:element name="style" type="CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
  464. * 964 <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
  465. * 965 </xsd:sequence>
  466. * 966 </xsd:complexType>
  467. */
  468. var id =node.GetTextByPath("p:nvSpPr/p:cNvPr/@id");
  469. var name = node.GetTextByPath("p:nvSpPr/p:cNvPr/@name");
  470. var idx = node.GetTextByPath("p:nvSpPr/p:nvPr/p:ph/@idx") ;
  471. var type = node.GetTextByPath("p:nvSpPr/p:nvPr/p:ph/@type") ;
  472. var order = node.GetTextByPath("@order");
  473. XmlNode slideLayoutSpNode = null;
  474. XmlNode slideMasterSpNode = null;
  475. if (type != null)
  476. {
  477. if (idx !=null)
  478. {
  479. if (warpObj.slideLayoutTables.typeTable.TryGetValue(type.Value, out Dictionary<string,XmlNode> LayoutNode)) {
  480. slideLayoutSpNode = LayoutNode[type.Value];
  481. };
  482. if (warpObj.slideMasterTables.typeTable.TryGetValue(type.Value, out Dictionary<string, XmlNode> MasterNode))
  483. {
  484. slideMasterSpNode = MasterNode[type.Value];
  485. };
  486. }
  487. else
  488. {
  489. if (warpObj.slideLayoutTables.typeTable.TryGetValue(type.Value, out Dictionary<string, XmlNode> LayoutNode))
  490. {
  491. slideLayoutSpNode = LayoutNode[type.Value];
  492. };
  493. if (warpObj.slideMasterTables.typeTable.TryGetValue(type.Value, out Dictionary<string, XmlNode> MasterNode))
  494. {
  495. slideMasterSpNode = MasterNode[type.Value];
  496. };
  497. }
  498. }
  499. else
  500. {
  501. if (idx !=null)
  502. {
  503. if (warpObj.slideLayoutTables.typeTable.TryGetValue(type.Value, out Dictionary<string, XmlNode> LayoutNode))
  504. {
  505. slideLayoutSpNode = LayoutNode[type.Value];
  506. };
  507. if (warpObj.slideMasterTables.typeTable.TryGetValue(type.Value, out Dictionary<string, XmlNode> MasterNode))
  508. {
  509. slideMasterSpNode = MasterNode[type.Value];
  510. };
  511. }
  512. else
  513. {
  514. // Nothing
  515. }
  516. }
  517. if (type == null)
  518. {
  519. if (slideLayoutSpNode != null) {
  520. type = slideLayoutSpNode.GetTextByPath("p:nvSpPr/p:nvPr/p:ph/@type");
  521. }
  522. // type = slideLayoutSpNode.TryGetValue"p:nvSpPr", "p:nvPr", "p:ph", "attrs", "type"]);
  523. if (type ==null)
  524. {
  525. if (slideMasterSpNode != null) {
  526. type = slideMasterSpNode.GetTextByPath("p:nvSpPr/p:nvPr/p:ph/@type");
  527. }
  528. // type = getTextByPathList(slideMasterSpNode, ["p:nvSpPr", "p:nvPr", "p:ph", "attrs", "type"]);
  529. }
  530. }
  531. string s = await GenShape(node, slideLayoutSpNode, slideMasterSpNode, id, name, idx, type, order, warpObj);
  532. throw new NotImplementedException();
  533. }
  534. private async Task<string> GenShape(XmlNode node, XmlNode slideLayoutSpNode, XmlNode slideMasterSpNode, XmlNode id, XmlNode name, XmlNode idx, XmlNode type, XmlNode order, WarpObj warpObj)
  535. {
  536. var xfrmList = "p:spPr/a:xfrm";
  537. var slideXfrmNode = node.GetTextByPath(xfrmList);
  538. XmlNode slideLayoutXfrmNode;
  539. if (slideLayoutSpNode != null) {
  540. slideLayoutXfrmNode = slideLayoutSpNode.GetTextByPath(xfrmList);
  541. }
  542. XmlNode slideMasterXfrmNode;
  543. if (slideMasterSpNode != null) {
  544. slideMasterXfrmNode = slideMasterSpNode.GetTextByPath(xfrmList);
  545. }
  546. var result = "";
  547. var shpId = node.GetTextByPath("/@order");
  548. var shapType = node.GetTextByPath("p:spPr/a:prstGeom/@prst");
  549. var custShapType = node.GetTextByPath("p:spPr/a:custGeom");
  550. var isFlipV = 0;
  551. var isFlipH = 0;
  552. if (slideXfrmNode.GetTextByPath("@flipV") != null && slideXfrmNode.GetTextByPath("@flipV").Value == "1")
  553. {// if ( getTextByPathList(slideXfrmNode, ["attrs", "flipV"]) === "1" || getTextByPathList(slideXfrmNode, ["attrs", "flipH"]) === "1")
  554. isFlipV = 1;
  555. }
  556. if (slideXfrmNode.GetTextByPath("@flipH") != null && slideXfrmNode.GetTextByPath("@flipH").Value == "1")
  557. {
  558. isFlipH = 1;
  559. }
  560. //rotate
  561. var rotate = AngleToDegrees(slideXfrmNode.GetTextByPath("@rot"));
  562. //console.log("rotate: "+rotate);
  563. double txtRotate;
  564. var txtXframeNode = node.GetTextByPath("p:txXfrm/@rot");
  565. if (txtXframeNode != null)
  566. {
  567. txtRotate = AngleToDegrees(txtXframeNode) + 90;
  568. }
  569. else
  570. {
  571. txtRotate = rotate;
  572. }
  573. if (shapType != null || custShapType != null) {
  574. var x = int.Parse(slideXfrmNode.GetTextByPath("a:off/@x").Value) * px96 / px914400;
  575. var y = int.Parse(slideXfrmNode.GetTextByPath("a:off/@y").Value) * px96 / px914400;
  576. var w = int.Parse(slideXfrmNode.GetTextByPath("a:ext/@cx").Value) * px96 / px914400;
  577. var h = int.Parse(slideXfrmNode.GetTextByPath("a:ext/@cy").Value) * px96 / px914400;
  578. Position position= GetPosition(slideXfrmNode, null, null);
  579. position.Cx = w;
  580. position.Cy = h;
  581. position.Rot = rotate;
  582. position.FlipH = isFlipH;
  583. position.FlipV = isFlipV;
  584. //result += "<svg class='drawing' _id='" + id + "' _idx='" + idx + "' _type='" + type + "' _name='" + name +
  585. // "' style='" +
  586. // getPosition(slideXfrmNode, null, null) +
  587. // getSize(slideXfrmNode, null, null) +
  588. // " z-index: " + order + ";" +
  589. // "transform: rotate(" + rotate + "deg);" +
  590. // "'>";
  591. //result += "<defs>";
  592. // Fill Color
  593. var Fill = await GetShapeFill(node, warpObj);
  594. var grndFillFlg = false;
  595. var imgFillFlg = false;
  596. var clrFillType = GetFillType(node.GetTextByPath("p:spPr"));
  597. /////////////////////////////////////////
  598. if (clrFillType == "GRADIENT_FILL")
  599. {
  600. grndFillFlg = true;
  601. var color_arry = Fill.gradColor;
  602. var angl = Fill.Rot;
  603. var svgGrdnt = GetSvgGradient(w, h, angl, color_arry, shpId);
  604. //fill="url(#linGrd)"
  605. result += svgGrdnt;
  606. }
  607. else if (clrFillType == "PIC_FILL")
  608. {
  609. imgFillFlg = true;
  610. var svgBgImg = GetSvgImagePattern(Fill.Image, shpId.Value);
  611. //fill="url(#imgPtrn)"
  612. //console.log(svgBgImg)
  613. result += svgBgImg;
  614. }
  615. else
  616. {
  617. if (clrFillType != "SOLID_FILL" && clrFillType != "PATTERN_FILL" &&
  618. (shapType.Value == "arc" ||
  619. shapType.Value == "bracketPair" ||
  620. shapType.Value == "bracePair" ||
  621. shapType.Value == "leftBracket" ||
  622. shapType.Value == "leftBrace" ||
  623. shapType.Value == "rightBrace" ||
  624. shapType.Value == "rightBracket"))
  625. { //Temp. solution - TODO
  626. Fill.HtmlText = "none";
  627. }
  628. }
  629. // Border Color
  630. var border = GetBorder(node, true, "shape");
  631. var headEndNodeAttrs = node.GetTextByPath("p:spPr/a:ln/a:headEnd");
  632. var tailEndNodeAttrs = node.GetTextByPath("p:spPr/a:ln/a:tailEnd");
  633. // type: none, triangle, stealth, diamond, oval, arrow
  634. if ((headEndNodeAttrs !=null&& (headEndNodeAttrs.GetTextByPath("@type").Value == "triangle" || (headEndNodeAttrs.GetTextByPath("@type").Value == "arrow")) ||
  635. (tailEndNodeAttrs != null && (tailEndNodeAttrs.GetTextByPath("@type").Value == "triangle" || (tailEndNodeAttrs.GetTextByPath("@type").Value == "arrow")))))
  636. {
  637. var triangleMarker = "<marker id='markerTriangle_" + shpId + "' viewBox='0 0 10 10' refX='1' refY='5' markerWidth='5' markerHeight='5' stroke='" + border.Color + "' fill='" + border.Color +
  638. "' orient='auto-start-reverse' markerUnits='strokeWidth'><path d='M 0 0 L 10 5 L 0 10 z' /></marker>";
  639. result += triangleMarker;
  640. }
  641. result += "</defs>";
  642. }
  643. throw new NotImplementedException();
  644. }
  645. public Border GetBorder(XmlNode node, bool isSvgMode, string bType)
  646. {
  647. Border border = new Border();
  648. string cssText = "";
  649. XmlNode lineNode = null;
  650. if (bType == "shape")
  651. {
  652. cssText = "border: ";
  653. lineNode = PowerPointHelper.GetTextByPath(node, "p:spPr/a:ln");// node["p:spPr"]["a:ln"];
  654. }
  655. else if (bType == "text")
  656. {
  657. cssText = "";
  658. lineNode = PowerPointHelper.GetTextByPath(node, "p:rPr/a:ln");// node["a:rPr"]["a:ln"];
  659. }
  660. // Border width: 1pt = 12700, default = 0.75pt
  661. var borderWidth = int.Parse(PowerPointHelper.GetTextByPath(lineNode, "@w").Value) / 12700;
  662. if (PowerPointHelper.GetTextByPath(lineNode, "@w") != null || borderWidth < 1)
  663. {
  664. cssText += "1pt ";
  665. }
  666. else
  667. {
  668. cssText += borderWidth + "pt ";
  669. }
  670. // Border type
  671. var borderType = PowerPointHelper.GetTextByPath(lineNode, "a:prstDash/@val").Value;
  672. var strokeDasharray = "0";
  673. switch (borderType)
  674. {
  675. case "solid":
  676. cssText += "solid";
  677. strokeDasharray = "0";
  678. break;
  679. case "dash":
  680. cssText += "dashed";
  681. strokeDasharray = "5";
  682. break;
  683. case "dashDot":
  684. cssText += "dashed";
  685. strokeDasharray = "5, 5, 1, 5";
  686. break;
  687. case "dot":
  688. cssText += "dotted";
  689. strokeDasharray = "1, 5";
  690. break;
  691. case "lgDash":
  692. cssText += "dashed";
  693. strokeDasharray = "10, 5";
  694. break;
  695. case "lgDashDotDot":
  696. cssText += "dashed";
  697. strokeDasharray = "10, 5, 1, 5, 1, 5";
  698. break;
  699. case "sysDash":
  700. cssText += "dashed";
  701. strokeDasharray = "5, 2";
  702. break;
  703. case "sysDashDot":
  704. cssText += "dashed";
  705. strokeDasharray = "5, 2, 1, 5";
  706. break;
  707. case "sysDashDotDot":
  708. cssText += "dashed";
  709. strokeDasharray = "5, 2, 1, 5, 1, 5";
  710. break;
  711. case "sysDot":
  712. cssText += "dotted";
  713. strokeDasharray = "2, 5";
  714. break;
  715. case null:
  716. //console.log(borderType);
  717. default:
  718. cssText += "solid";
  719. strokeDasharray = "0";
  720. break;
  721. }
  722. // Border color
  723. var borderColor = PowerPointHelper.GetTextByPath(lineNode, "a:solidFill/:srgbClr/@val").Value;
  724. if (borderColor == null)
  725. {
  726. var schemeClrNode = PowerPointHelper.GetTextByPathList(lineNode, "a:solidFill/a:schemeClr");
  727. if (schemeClrNode != null)
  728. {
  729. var schemeClr = PowerPointHelper.GetTextByPath(lineNode, "a:solidFill/a:schemeClr/@val");
  730. borderColor = GetSchemeColorFromTheme(schemeClr.Value, null);
  731. }
  732. }
  733. // 2. drawingML namespace
  734. if (borderColor == null)
  735. {
  736. var schemeClrNode = PowerPointHelper.GetTextByPathList(node, "p:style/a:lnRef/a:schemeClr");
  737. if (schemeClrNode != null)
  738. {
  739. var schemeClr = PowerPointHelper.GetTextByPath(node, "p:style/a:lnRef/a:schemeClr/@val");
  740. borderColor = GetSchemeColorFromTheme(schemeClr.Value, null);
  741. }
  742. if (borderColor != null)
  743. {
  744. var shade = PowerPointHelper.GetTextByPath(node, "p:style/a:lnRef/a:schemeClr/a:shade/@val").Value;
  745. if (shade != null)
  746. {
  747. int shaded = int.Parse(shade) / 100000 ;
  748. var color = ColorTranslator.FromHtml("#"+ borderColor);
  749. ColorHSL colorHSL = ColorHelper.RgbToHsl(new ColorRGB(color.R, color.G, color.B));
  750. colorHSL.L= colorHSL.L * shaded;
  751. ColorRGB colorRGB = colorHSL.HslToRgb();
  752. borderColor =ColorTranslator.ToHtml(Color.FromArgb(colorRGB.R, colorRGB.G, colorRGB.B));
  753. // borderColor = color.hex.replace("#", "");
  754. }
  755. }
  756. }
  757. if (borderColor == null)
  758. {
  759. if (isSvgMode)
  760. {
  761. borderColor = "none";
  762. }
  763. else
  764. {
  765. borderColor = "#000";
  766. }
  767. }
  768. else
  769. {
  770. borderColor = "#" + borderColor;
  771. }
  772. cssText += " " + borderColor + " ";
  773. if (isSvgMode)
  774. {
  775. return new Border { Color = borderColor, Width = borderWidth, Type = borderType, Stroke = strokeDasharray };
  776. }
  777. else
  778. {
  779. return border;
  780. }
  781. }
  782. public static string GetSvgImagePattern(string fillColor, string shpId)
  783. {
  784. var ptrn = "<pattern id=\"imgPtrn_" + shpId + "\"patternContentUnits=\"objectBoundingBox\" width=\"1\" height=\"1\">";// '<pattern id="imgPtrn_' + shpId + '" patternContentUnits="objectBoundingBox" width="1" height="1">';
  785. ptrn += "<image xlink:href=\"" + fillColor + "\"preserveAspectRatio=\"none\" width=\"1\" height=\"1\"></image>";// '<image xlink:href="' + fillColor + '" preserveAspectRatio="none" width="1" height="1"></image>';
  786. ptrn += "</pattern>";// '';
  787. return ptrn;
  788. }
  789. private string GetSvgGradient(double w, double h, double angl, List<string> color_arry, XmlNode shpId)
  790. {
  791. var stopsArray = GetMiddleStops(color_arry.Count - 2);
  792. var svgAngle = "";
  793. double svgHeight = h;
  794. double svgWidth = w;
  795. string svg = "";
  796. List<double> xy_ary = SVGangle(angl, svgHeight, svgWidth);
  797. double x1 = xy_ary[0];
  798. double y1 = xy_ary[1];
  799. double x2 = xy_ary[2];
  800. double y2 = xy_ary[3];
  801. var sal = stopsArray.Count;
  802. double sr = sal < 20 ? 100 : 1000;
  803. svgAngle = " gradientUnits=\"userSpaceOnUse\" x1=\"" + x1 + "%\" y1=\"" + y1 + "%\" x2=\"" + x2 + "%\" y2=\"" + y2 + "%\"";
  804. svgAngle = "<linearGradient id=\"linGrd_" + shpId + "\"" + svgAngle + ">\n";
  805. svg += svgAngle;
  806. for (var i = 0; i < sal; i++)
  807. {
  808. svg += "<stop offset=\"" +(System. Math.Round(double.Parse(stopsArray[i])) / 100 * sr) / sr + "\" stop-color=\"" + color_arry[i] + "\"";
  809. svg += "/>\n";
  810. }
  811. svg += "</linearGradient>\n" + "";
  812. return svg;
  813. }
  814. private List<string> GetMiddleStops(int s)
  815. {
  816. var sArry = new List<string> { "0%" };
  817. if (s == 0)
  818. {
  819. return sArry;
  820. }
  821. else
  822. {
  823. for (int i = s; i < 0; i--)
  824. {
  825. var middleStop = 100 - ((100 / (s + 1)) * (i + 1)); // AM: Ex - For 3 middle stops, progression will be 25%, 50%, and 75%, plus 0% and 100% at the ends.
  826. var middleStopString = middleStop + "%";
  827. sArry.Add(middleStopString);
  828. // sArry.splice(-1, 0, middleStopString);
  829. }
  830. // AM: add into stopsArray before 100%
  831. }
  832. sArry.Add("100%");
  833. return sArry;
  834. }
  835. public async Task<Fill> GetShapeFill(XmlNode node, WarpObj warpObj)
  836. {
  837. // 1. presentationML
  838. // p:spPr/ [a:noFill, solidFill, gradFill, blipFill, pattFill, grpFill]
  839. // From slide
  840. //Fill Type:
  841. //console.log("ShapeFill: ", node)
  842. var fillType = GetFillType(PowerPointHelper.GetTextByPath(node, "p:spPr"));
  843. Fill fill = new Fill();
  844. if (fillType == "NO_FILL")
  845. {
  846. fill.SvgText = "node";
  847. fill.Type = 0;
  848. fill.HtmlText = "background-color: initial;";
  849. return fill;
  850. //return isSvgMode ? "none" : "background-color: initial;";
  851. }
  852. else if (fillType == "SOLID_FILL")
  853. {
  854. XmlNode shpFill = PowerPointHelper.GetTextByPath(node, "p:spPr/a:solidFill");// node["p:spPr"]["a:solidFill"];
  855. fill = GetSolidFill(shpFill);
  856. }
  857. else if (fillType == "GRADIENT_FILL")
  858. {
  859. var shpFill = PowerPointHelper.GetTextByPath(node, "p:spPr/a:gradFill");// node["p:spPr"]["a:gradFill"];
  860. // fillColor = GetSolidFill(shpFill);
  861. fill = GetGradientFill(shpFill);
  862. //console.log("shpFill",shpFill,grndColor.color)
  863. }
  864. else if (fillType == "PATTERN_FILL")
  865. {
  866. var shpFill = PowerPointHelper.GetTextByPath(node, "p:spPr/a:pattFill");// node["p:spPr"]["a:pattFill"];
  867. fill = GetPatternFill(shpFill);
  868. }
  869. else if (fillType == "PIC_FILL")
  870. {
  871. var shpFill = PowerPointHelper.GetTextByPath(node, "p:spPr/a:blipFill"); //node["p:spPr"]["a:blipFill"];
  872. fill = await GetPicFill("slideBg", shpFill, warpObj);
  873. }
  874. // 2. drawingML namespace
  875. if (fill == null)
  876. {
  877. var clrName = PowerPointHelper.GetTextByPath(node, "p:style/a:fillRef");
  878. fill = GetSolidFill(clrName);
  879. }
  880. if (fill != null)
  881. {
  882. if (fillType == "GRADIENT_FILL")
  883. {
  884. //if (isSvgMode)
  885. //{
  886. // // console.log("GRADIENT_FILL color", fillColor.color[0])
  887. // return fill;
  888. //}
  889. //else
  890. //{
  891. var colorAry = fill.Color;
  892. var rot = fill.Rot;
  893. var bgcolor = "background: linear-gradient(" + rot + "deg,";
  894. for (var i = 0; i < colorAry.Length; i++)
  895. {
  896. if (i == colorAry.Length - 1)
  897. {
  898. bgcolor += colorAry[i] + ");";
  899. }
  900. else
  901. {
  902. bgcolor += colorAry[i] + ", ";
  903. }
  904. }
  905. fill.HtmlText = bgcolor;
  906. return fill;
  907. // }
  908. }
  909. else if (fillType == "PIC_FILL")
  910. {
  911. //if (isSvgMode)
  912. //{
  913. // return fill;
  914. //}
  915. //else
  916. //{
  917. fill.HtmlText = "background-image:url(" + fill.Image + ");";
  918. return fill;
  919. // }
  920. }
  921. else
  922. {
  923. Console.WriteLine("#"+fill.Color);
  924. //if (isSvgMode)
  925. //{
  926. // var color = new colz.Color(fill);
  927. // fill = color.rgb.toString();
  928. fill.HtmlText = "background-color: #" + fill.Color + ";";
  929. return fill;
  930. //}
  931. //else
  932. //{
  933. // //console.log(node,"fillColor: ",fillColor,"fillType: ",fillType,"isSvgMode: ",isSvgMode)
  934. // return fill;
  935. //}
  936. }
  937. }
  938. else
  939. {
  940. //if (isSvgMode)
  941. //{
  942. // return fill;
  943. //}
  944. //else
  945. //{
  946. fill.SvgText = "none";
  947. fill.HtmlText = "background-color: initial;";
  948. return fill;
  949. // }
  950. }
  951. }
  952. private static List<double> SVGangle(double deg, double svgHeight, double svgWidth)
  953. {
  954. double w = svgWidth;
  955. double h = svgHeight;
  956. double ang = deg;
  957. double o = 2;
  958. double n = 2;
  959. double wc = w / 2;
  960. double hc = h / 2;
  961. double tx1 = 2;
  962. double ty1 = 2;
  963. double tx2 = 2;
  964. double ty2 = 2;
  965. double k = (((ang % 360) + 360) % 360);
  966. double j = (360 - k) * System.Math.PI / 180;
  967. double i = System.Math.Tan(j);
  968. double l = hc - i * wc;
  969. if (k == 0)
  970. {
  971. tx1 = w;
  972. ty1 = hc;
  973. tx2 = 0;
  974. ty2 = hc;
  975. }
  976. else if (k < 90)
  977. {
  978. n = w;
  979. o = 0;
  980. }
  981. else if (k == 90)
  982. {
  983. tx1 = wc;
  984. ty1 = 0;
  985. tx2 = wc;
  986. ty2 = h;
  987. }
  988. else if (k < 180)
  989. {
  990. n = 0;
  991. o = 0;
  992. }
  993. else if (k == 180)
  994. {
  995. tx1 = 0;
  996. ty1 = hc;
  997. tx2 = w;
  998. ty2 = hc;
  999. }
  1000. else if (k < 270)
  1001. {
  1002. n = 0;
  1003. o = h;
  1004. }
  1005. else if (k == 270)
  1006. {
  1007. tx1 = wc;
  1008. ty1 = h;
  1009. tx2 = wc;
  1010. ty2 = 0;
  1011. }
  1012. else
  1013. {
  1014. n = w;
  1015. o = h;
  1016. }
  1017. // AM: I could not quite figure out what m, n, and o are supposed to represent from the original code on visualcsstools.com.
  1018. var m = o + (n / i);
  1019. tx1 = tx1 == 2 ? i * (m - l) / (System.Math.Pow(i, 2) + 1) : tx1;
  1020. ty1 = ty1 == 2 ? i * tx1 + l : ty1;
  1021. tx2 = tx2 == 2 ? w - tx1 : tx2;
  1022. ty2 = ty2 == 2 ? h - ty1 : ty2;
  1023. double x1 = System.Math.Round(tx2 / w * 100 * 100) / 100;
  1024. double y1 = System.Math.Round(ty2 / h * 100 * 100) / 100;
  1025. double x2 = System.Math.Round(tx1 / w * 100 * 100) / 100;
  1026. double y2 = System.Math.Round(ty1 / h * 100 * 100) / 100;
  1027. return new List<double> { x1, y1, x2, y2 };
  1028. }
  1029. private Fill GetPatternFill(XmlNode node)
  1030. {
  1031. Fill fill = new Fill { Type=4};
  1032. var fgClr = PowerPointHelper.GetTextByPath(node, "a:fgClr");
  1033. fill = GetSolidFill(fgClr);
  1034. return fill;
  1035. }
  1036. private Fill GetGradientFill(XmlNode node )
  1037. {
  1038. XmlNodeList gsLst = PowerPointHelper.GetTextByPathList(node, "a:gsLst/a:gs");// node["a:gsLst"]["a:gs"];
  1039. //get start color
  1040. var color_ary = new List<string>();
  1041. var tint_ary = new string[] { };
  1042. for (int i = 0; i < gsLst.Count; i++)
  1043. {
  1044. var lo_color = GetSolidFill(gsLst[i]);
  1045. if (gsLst[i].GetTextByPath("a:srgbClr") != null)
  1046. {
  1047. //var mod = PowerPointHelper.GetTextByPath(gsLst[i], "a:srgbClr/a:lumMod/@val");
  1048. //var off = PowerPointHelper.GetTextByPath(gsLst[i], "a:srgbClr/a:lumOff/@val");
  1049. //double lumMod = 1.0;
  1050. //double lumOff = 1.0;
  1051. //if (mod!=null)
  1052. //{
  1053. // lumMod = double.Parse(mod.Value) /100000;
  1054. //}
  1055. //if (off!=null)
  1056. //{
  1057. // lumOff = double.Parse(off.Value) / 100000;
  1058. //}
  1059. //console.log([lumMod, lumOff]);
  1060. lo_color.Color = PowerPointHelper.ColorToning(gsLst[i].OuterXml, lo_color.Color);
  1061. // lo_color = ApplyLumModify(lo_color, lumMod, lumOff);
  1062. }
  1063. else if (gsLst[i].GetTextByPath("a:schemeClr") != null)
  1064. {
  1065. //a:schemeClr
  1066. //var mod = PowerPointHelper.GetTextByPath(gsLst[i], "a:schemeClr/a:lumMod/@val");
  1067. //var off = PowerPointHelper.GetTextByPath(gsLst[i], "a:schemeClr/a:lumOff/@val");
  1068. //double lumMod = 1.0;
  1069. //double lumOff = 1.0;
  1070. //if (mod != null)
  1071. //{
  1072. // lumMod = double.Parse(mod.Value) / 100000;
  1073. //}
  1074. //if (off != null)
  1075. //{
  1076. // lumOff = double.Parse(off.Value) / 100000;
  1077. //}
  1078. //console.log([lumMod, lumOff]);
  1079. lo_color.Color= PowerPointHelper.ColorToning(gsLst[i].OuterXml, lo_color.Color);
  1080. // lo_color = ApplyLumModify(lo_color, lumMod, lumOff);
  1081. }
  1082. color_ary.Add(lo_color.Color);
  1083. }
  1084. //get rot
  1085. var lin = PowerPointHelper.GetTextByPathList(node, "a:lin");// node["a:lin"];
  1086. double rot = 0;
  1087. if (lin != null)
  1088. {
  1089. rot = AngleToDegrees(PowerPointHelper.GetTextByPath(node, "a:lin/@ang")) + 90;
  1090. }
  1091. return new Fill()
  1092. {
  1093. Type = 2,
  1094. gradColor = color_ary,
  1095. Rot = rot
  1096. };
  1097. }
  1098. //private static Fill ApplyLumModify(Fill rgbStr, double factor, double offset)
  1099. //{
  1100. // Color color = ColorTranslator.FromHtml("#" + "1CADE4");
  1101. // ColorRGB RGB = new ColorRGB(color.R,color.G,color.B);
  1102. // ColorHSL HSL= ColorHelper.RgbToHsl(RGB);
  1103. // HSL.L= HSL.L * (1 + offset);
  1104. // RGB = ColorHelper.HslToRgb(HSL);
  1105. // color= Color.FromArgb(RGB.R, RGB.G, RGB.B);
  1106. // rgbStr.Color=ColorTranslator.ToHtml(color).Replace("#","");
  1107. // return rgbStr;
  1108. //}
  1109. public static Position GetPosition(XmlNode slideXfrmNode, XmlNode slideLayoutXfrmNode, XmlNode slideMasterXfrmNode)
  1110. {
  1111. XmlNode off = null;
  1112. double x, y;
  1113. if (slideXfrmNode != null)
  1114. {
  1115. off = PowerPointHelper.GetTextByPath(slideXfrmNode, "a:off");
  1116. }
  1117. else if (slideLayoutXfrmNode != null)
  1118. {
  1119. off = PowerPointHelper.GetTextByPath(slideLayoutXfrmNode, "a:off");
  1120. }
  1121. else if (slideMasterXfrmNode != null)
  1122. {
  1123. off = PowerPointHelper.GetTextByPath(slideMasterXfrmNode, "a:off");
  1124. }
  1125. x = double.Parse(PowerPointHelper.GetTextByPath(off, "@x").Value) * px96 / px914400;
  1126. y = double.Parse(PowerPointHelper.GetTextByPath(off, "@y").Value) * px96 / px914400;
  1127. return new Position()
  1128. {
  1129. X = x,
  1130. Y = y
  1131. };
  1132. //if (off == null)
  1133. //{
  1134. // return "";
  1135. //}
  1136. //else
  1137. //{
  1138. // // return (IsNaN(x) || IsNaN(y)) ? "" : "top:" + y + "px; left:" + x + "px;";
  1139. //}
  1140. }
  1141. private double AngleToDegrees(XmlNode angle)
  1142. {
  1143. if ( angle == null)
  1144. {
  1145. return 0;
  1146. }
  1147. return System.Math.Round(double.Parse(angle.Value) / 60000);
  1148. }
  1149. private Fill GetSlideBackgroundFill(XmlNode slideContent ,XmlNode slideLayoutContent , XmlNode slideMasterContent , WarpObj warpObj) {
  1150. var bgPr = slideContent.GetTextByPath("p:sld/p:cSld/p:bg/p:bgPr");
  1151. var bgRef = slideContent.GetTextByPath("p:sld/p:cSld/p:bg/p:bgRef");
  1152. var bgcolor="";
  1153. if (bgPr != null)
  1154. {
  1155. var bgFillTyp = GetFillType(bgPr);
  1156. if (bgFillTyp == "SOLID_FILL")
  1157. {
  1158. var sldFill = bgPr.GetTextByPath("a:solidFill");
  1159. var bgColor = GetSolidFill(sldFill);
  1160. var sldTint = GetColorOpacity(sldFill);
  1161. bgcolor = "background: rgba(" + HexToRgbNew(bgColor.Color) + "," + sldTint + ");";
  1162. }
  1163. else if (bgFillTyp == "GRADIENT_FILL")
  1164. {
  1165. bgcolor = GetBgGradientFill(bgPr, null, slideMasterContent);
  1166. }
  1167. else if (bgFillTyp == "PIC_FILL")
  1168. {
  1169. bgcolor = GetBgPicFill(bgPr, "slideBg", warpObj);
  1170. }
  1171. }
  1172. else if (bgRef != null)
  1173. {
  1174. }
  1175. else {
  1176. }
  1177. return null;
  1178. }
  1179. private string GetBgPicFill(XmlNode bgPr, string sorce, WarpObj warpObj)
  1180. {
  1181. string bgcolor;
  1182. var picFillBase64 = GetPicFill(sorce, bgPr.GetTextByPath("a:blipFill"), warpObj);
  1183. var ordr = bgPr["attrs"]["order"];
  1184. //a:srcRect
  1185. //a:stretch => a:fillRect =>attrs (l:-17000, r:-17000)
  1186. bgcolor = "background-image: url(" + picFillBase64 + "); z-index: " + ordr + ";";
  1187. return bgcolor;
  1188. }
  1189. private async Task<Fill> GetPicFill(string type, XmlNode node, WarpObj warpObj)
  1190. {
  1191. //Need to test/////////////////////////////////////////////
  1192. //rId
  1193. //TODO - Image Properties - Tile, Stretch, or Display Portion of Image
  1194. //(http://officeopenxml.com/drwPic-tile.php)
  1195. // var img = "";
  1196. var rId = PowerPointHelper.GetTextByPath(node, "a:blip/@r:embed");//node["a:blip"]["attrs"]["r:embed"];
  1197. Dictionary<string, string> imgPath = new Dictionary<string, string>() ;
  1198. if (type == "slideBg")
  1199. {
  1200. imgPath = warpObj.slideResObj[rId.Value];
  1201. }
  1202. else if (type == "layoutBg")
  1203. {
  1204. imgPath = warpObj.layoutResObj[rId.Value];
  1205. }
  1206. else if (type == "masterBg")
  1207. {
  1208. imgPath = warpObj.masterResObj[rId.Value];
  1209. }
  1210. if (imgPath == null)
  1211. {
  1212. return null;
  1213. }
  1214. //var imgExt = imgPath["type"];
  1215. //if (imgExt == "xml")
  1216. //{
  1217. // return null;
  1218. //}
  1219. var imgData= warpObj.zip.GetTextByPath("//pkg:part[@pkg:name='"+ imgPath["target"] + "']");
  1220. if (imgData != null)
  1221. {
  1222. AzureBlobModel model = await PowerPointHelper.SaveBase64ToBolob(imgData.InnerText, imgData.GetTextByPath("@pkg:contentType").Value,
  1223. fileShaCode + "/imgs", null, azureBlobDBRepository);
  1224. return new Fill { Type = 3, Image = model.BlobUrl };
  1225. }
  1226. else { return null; }
  1227. // var imgArrayBuffer = warpObj.zip.GetTextByPath(imgPath).Value.asArrayBuffer();
  1228. //var imgMimeType = GetMimeType(imgExt);
  1229. //img = "data:" + imgMimeType + ";base64," + base64ArrayBuffer(imgArrayBuffer);
  1230. }
  1231. private string GetBgGradientFill(XmlNode bgPr, XmlNode phClr, XmlNode slideMasterContent)
  1232. {
  1233. var bgcolor = "";
  1234. if (bgPr !=null)
  1235. {
  1236. var grdFill = bgPr.GetTextByPath("a:gradFill");
  1237. var gsLst = grdFill.GetTextByPathList("a:gsLst/a:gs");
  1238. // var startColorNode, endColorNode;
  1239. var color_ary = new List<string >();
  1240. var tint_ary = new List<int>();
  1241. for (var i = 0; i < gsLst.Count; i++)
  1242. {
  1243. var lo_tint ="" ;
  1244. var lo_color = "";
  1245. if (gsLst[i]["a:srgbClr"] != null)
  1246. {
  1247. if (phClr == null)
  1248. {
  1249. lo_color = gsLst[i].GetTextByPath("a:srgbClr/@val").Value; //#...
  1250. }
  1251. lo_tint = gsLst[i].GetTextByPath("a:srgbClr/a:tint/@val").Value;
  1252. }
  1253. else if (gsLst[i]["a:schemeClr"] != null)
  1254. { //a:schemeClr
  1255. if (phClr == null)
  1256. {
  1257. var schemeClr = gsLst[i].GetTextByPath("a:schemeClr/@val");
  1258. lo_color = GetSchemeColorFromTheme("a:" + schemeClr, slideMasterContent); //#...
  1259. }
  1260. lo_tint = gsLst[i].GetTextByPath("a:schemeClr/a:tint/@val").Value;
  1261. //console.log("schemeClr",schemeClr,slideMasterContent)
  1262. }
  1263. //console.log("lo_color",lo_color)
  1264. color_ary[i] = lo_color;
  1265. tint_ary[i] = (lo_tint !=null) ? int.Parse(lo_tint) / 100000 : 1;
  1266. }
  1267. //get rot
  1268. var lin = grdFill["a:lin"];
  1269. var rot = 90.0;
  1270. if (lin !=null)
  1271. {
  1272. rot = AngleToDegrees(lin.GetTextByPath("@ang")) + 90;
  1273. }
  1274. bgcolor = "background: linear-gradient(" + rot + "deg,";
  1275. for (var i = 0; i < gsLst.Count; i++)
  1276. {
  1277. if (i == gsLst.Count - 1)
  1278. {
  1279. if (phClr ==null)
  1280. {
  1281. bgcolor += "rgba(" + HexToRgbNew(color_ary[i]) + "," + tint_ary[i] + ")" + ");";
  1282. }
  1283. else
  1284. {
  1285. bgcolor += "rgba(" + HexToRgbNew(phClr.Value) + "," + tint_ary[i] + ")" + ");";
  1286. }
  1287. }
  1288. else
  1289. {
  1290. if (phClr == null)
  1291. {
  1292. bgcolor += "rgba(" + HexToRgbNew(color_ary[i]) + "," + tint_ary[i] + ")" + ", ";
  1293. }
  1294. else
  1295. {
  1296. bgcolor += "rgba(" + HexToRgbNew(phClr.Value) + "," + tint_ary[i] + ")" + ", ";
  1297. }
  1298. }
  1299. }
  1300. }
  1301. else
  1302. {
  1303. if (phClr == null)
  1304. {
  1305. bgcolor = "rgba(" + HexToRgbNew(phClr.Value) + ",0);";
  1306. }
  1307. }
  1308. return bgcolor;
  1309. }
  1310. private string HexToRgbNew(string bgColor)
  1311. {
  1312. //var arrBuff = new ArrayBuffer(4);
  1313. //var vw = new DataView(arrBuff);
  1314. //vw.setUint32(0, parseInt(hex, 16), false);
  1315. //var arrByte = new Uint8Array(arrBuff);
  1316. int r = Convert.ToInt32("0x" + bgColor.Substring(0, 2), 16);
  1317. int g = Convert.ToInt32("0x" + bgColor.Substring(2, 2), 16);
  1318. int b = Convert.ToInt32("0x" + bgColor.Substring(4, 2), 16);
  1319. return r + "," + g+ "," +b;
  1320. }
  1321. private double GetColorOpacity(XmlNode solidFill)
  1322. {
  1323. double opcity = 1;
  1324. if (solidFill == null)
  1325. {
  1326. return opcity;
  1327. }
  1328. if (solidFill.GetTextByPath("a:srgbClr") != null)
  1329. {
  1330. var tint = solidFill.GetTextByPath("a:srgbClr/a:tint/@val");
  1331. if (tint !=null)
  1332. {
  1333. opcity = double.Parse(tint.Value) / 100000;
  1334. }
  1335. }
  1336. else if (solidFill.GetTextByPath("a:schemeClr") != null)
  1337. {
  1338. var tint = solidFill.GetTextByPath("a:schemeClr/a:tint/@val");
  1339. if (tint != null)
  1340. {
  1341. opcity = double.Parse(tint.Value) / 100000;
  1342. }
  1343. }
  1344. else if (solidFill.GetTextByPath("a:scrgbClr")!= null)
  1345. {
  1346. var tint = solidFill.GetTextByPath("a:scrgbClr/a:tint/@val");
  1347. if (tint != null)
  1348. {
  1349. opcity = double.Parse(tint.Value) / 100000;
  1350. }
  1351. }
  1352. else if (solidFill.GetTextByPath("a:prstClr") != null)
  1353. {
  1354. var tint = solidFill.GetTextByPath("a:prstClr/a:tint/@val");
  1355. if (tint != null)
  1356. {
  1357. opcity = double.Parse(tint.Value) / 100000;
  1358. }
  1359. }
  1360. else if (solidFill.GetTextByPath("a:hslClr") != null)
  1361. {
  1362. var tint = solidFill.GetTextByPath("a:hslClr/a:tint/@val");
  1363. if (tint != null)
  1364. {
  1365. opcity = double.Parse(tint.Value) / 100000;
  1366. }
  1367. }
  1368. else if (solidFill.GetTextByPath("a:sysClr") !=null)
  1369. {
  1370. var tint = solidFill.GetTextByPath("a:sysClr/a:tint/@val");
  1371. if (tint != null)
  1372. {
  1373. opcity = double.Parse(tint.Value) / 100000;
  1374. }
  1375. }
  1376. return opcity;
  1377. }
  1378. public Fill GetSolidFill(XmlNode node)
  1379. {
  1380. if (node == null)
  1381. {
  1382. return null;
  1383. }
  1384. Fill fill = new Fill() { Color = "FFF" ,Type=1 };
  1385. if (PowerPointHelper.GetTextByPath(node, "a:srgbClr") != null)
  1386. {
  1387. fill.Color = PowerPointHelper.GetTextByPath(node, "a:srgbClr/@val").Value; //#...
  1388. }
  1389. else if (PowerPointHelper.GetTextByPath(node, "a:schemeClr") != null)//node["a:schemeClr"] != null)
  1390. { //a:schemeClr
  1391. var schemeClr = PowerPointHelper.GetTextByPath(node, "a:schemeClr/@val");
  1392. //console.log(schemeClr)
  1393. fill.Color = GetSchemeColorFromTheme(schemeClr.Value, null); //#...
  1394. }
  1395. else if (PowerPointHelper.GetTextByPath(node, "a:scrgbClr") != null)
  1396. {
  1397. //<a:scrgbClr r="50%" g="50%" b="50%"/> //Need to test/////////////////////////////////////////////
  1398. var defBultColorValsR = PowerPointHelper.GetTextByPath(node, "a:scrgbClr/@r");
  1399. var defBultColorValsG = PowerPointHelper.GetTextByPath(node, "a:scrgbClr/@g");
  1400. var defBultColorValsB = PowerPointHelper.GetTextByPath(node, "a:scrgbClr/@b");
  1401. var red = (defBultColorValsR.Value.IndexOf("%") != -1) ? defBultColorValsR.Value.Split("%").First() : defBultColorValsR.Value;
  1402. var green = (defBultColorValsG.Value.IndexOf("%") != -1) ? defBultColorValsG.Value.Split("%").First() : defBultColorValsG.Value;
  1403. var blue = (defBultColorValsB.Value.IndexOf("%") != -1) ? defBultColorValsB.Value.Split("%").First() : defBultColorValsB.Value;
  1404. var scrgbClr = red + "," + green + "," + blue;
  1405. fill.Color = ToHex(255 * (double.Parse(red) / 100)) + ToHex(255 * (double.Parse(green) / 100)) + ToHex(255 * (double.Parse(blue) / 100));
  1406. //console.log("scrgbClr: " + scrgbClr);
  1407. }
  1408. else if (PowerPointHelper.GetTextByPath(node, "a:prstClr") != null)
  1409. {
  1410. //<a:prstClr val="black"/> //Need to test/////////////////////////////////////////////
  1411. var prstClr = PowerPointHelper.GetTextByPath(node, "a:prstClr/@val");// node["a:prstClr"]["attrs"]["val"];
  1412. fill.Color = GetColorName2Hex(prstClr.Value);
  1413. //console.log("prstClr: " + prstClr+" => hexClr: "+color);
  1414. }
  1415. else if (PowerPointHelper.GetTextByPath(node, "a:hslClr") != null)
  1416. {
  1417. //<a:hslClr hue="14400000" sat="100%" lum="50%"/> //Need to test/////////////////////////////////////////////
  1418. var defBultColorVals = PowerPointHelper.GetTextByPath(node, "a:hslClr");//["attrs"];
  1419. var defBultColorVals_hue = PowerPointHelper.GetTextByPath(defBultColorVals, "@hue");
  1420. var defBultColorVals_sat = PowerPointHelper.GetTextByPath(defBultColorVals, "@sat");
  1421. var defBultColorVals_lum = PowerPointHelper.GetTextByPath(defBultColorVals, "@lum");
  1422. var hue = double.Parse(defBultColorVals_hue.Value) / 100000;
  1423. var sat = double.Parse((defBultColorVals_sat.Value.IndexOf("%") != -1) ? defBultColorVals_sat.Value.Split("%").First() : defBultColorVals_sat.Value) / 100;
  1424. var lum = double.Parse((defBultColorVals_lum.Value.IndexOf("%") != -1) ? defBultColorVals_lum.Value.Split("%").First() : defBultColorVals_lum.Value) / 100;
  1425. var hslClr = defBultColorVals_hue.Value.ToString() + "," + defBultColorVals_sat.Value.ToString() + "," + defBultColorVals_lum.Value.ToString();
  1426. var hsl2rgb = HslToRgb(hue, sat, lum);
  1427. fill.Color = ToHex(hsl2rgb.r) + ToHex(hsl2rgb.g) + ToHex(hsl2rgb.b);
  1428. //defBultColor = cnvrtHslColor2Hex(hslClr); //TODO
  1429. // console.log("hslClr: " + hslClr);
  1430. }
  1431. else if (PowerPointHelper.GetTextByPath(node, "a:sysClr") != null)
  1432. {
  1433. //<a:sysClr val="windowText" lastClr="000000"/> //Need to test/////////////////////////////////////////////
  1434. var sysClr = PowerPointHelper.GetTextByPath(node, "a:sysClr/@lastClr").Value;
  1435. if (sysClr != null)
  1436. {
  1437. fill.Color = sysClr;
  1438. }
  1439. }
  1440. return fill;
  1441. }
  1442. public string GetSchemeColorFromTheme(string schemeClr, XmlNode sldMasterNode)
  1443. {
  1444. //<p:clrMap ...> in slide master
  1445. // e.g. tx2="dk2" bg2="lt2" tx1="dk1" bg1="lt1" slideLayoutClrOvride
  1446. if (slideLayoutClrOvride == null ||slideLayoutClrOvride.Count<=0)
  1447. {
  1448. if(sldMasterNode!= null) {
  1449. var sldLayoutClrOvr = PowerPointHelper.GetTextByPath(sldMasterNode, "p:sldMaster/p:clrMap");
  1450. if (sldLayoutClrOvr != null)
  1451. {
  1452. //获取 overrideClrMapping所有属性节点 检查测试 是否slideLayoutClrOvride 需要被覆盖
  1453. slideLayoutClrOvride = new Dictionary<string, string>() {
  1454. { "accent1", sldLayoutClrOvr.GetTextByPath("@accent1").Value},
  1455. { "accent2", sldLayoutClrOvr.GetTextByPath("@accent2").Value},
  1456. { "accent3", sldLayoutClrOvr.GetTextByPath("@accent3").Value},
  1457. { "accent4", sldLayoutClrOvr.GetTextByPath("@accent4").Value},
  1458. { "accent5", sldLayoutClrOvr.GetTextByPath("@accent5").Value},
  1459. { "accent6", sldLayoutClrOvr.GetTextByPath("@accent6").Value},
  1460. { "bg1", sldLayoutClrOvr.GetTextByPath("@bg1").Value},
  1461. { "bg2", sldLayoutClrOvr.GetTextByPath("@bg2").Value},
  1462. { "folHlink", sldLayoutClrOvr.GetTextByPath("@folHlink").Value},
  1463. { "hlink", sldLayoutClrOvr.GetTextByPath("@hlink").Value},
  1464. { "tx1", sldLayoutClrOvr.GetTextByPath("@tx1").Value},
  1465. { "tx2", sldLayoutClrOvr.GetTextByPath("@tx2").Value}
  1466. };
  1467. }
  1468. }
  1469. }
  1470. if (!schemeClr.StartsWith("a:"))
  1471. {
  1472. schemeClr = "a:" + schemeClr;
  1473. }
  1474. //console.log(slideLayoutClrOvride);
  1475. var schmClrName = schemeClr.Replace("a:","");
  1476. if (slideLayoutClrOvride != null)
  1477. {
  1478. switch (schmClrName)
  1479. {
  1480. case "tx1":
  1481. case "tx2":
  1482. case "bg1":
  1483. case "bg2":
  1484. schemeClr = "a:" +slideLayoutClrOvride[schmClrName];
  1485. //schemeClr = "a:" + slideLayoutClrOvride[schmClrName];
  1486. //console.log(schmClrName+ "=> "+schemeClr);
  1487. break;
  1488. }
  1489. }
  1490. else
  1491. {
  1492. switch (schmClrName)
  1493. {
  1494. case "tx1":
  1495. schemeClr = "a:dk1";
  1496. break;
  1497. case "tx2":
  1498. schemeClr = "a:dk2";
  1499. break;
  1500. case "bg1":
  1501. schemeClr = "a:lt1";
  1502. break;
  1503. case "bg2":
  1504. schemeClr = "a:lt2";
  1505. break;
  1506. }
  1507. }
  1508. //var refNode = PowerPointHelper.GetTextByPathList(themeContent, "a:theme/a:themeElements/a:clrScheme/"+ schemeClr.Value);
  1509. var color = PowerPointHelper.GetTextByPath(themeContent, "pkg:xmlData/a:theme/a:themeElements/a:clrScheme/" + schemeClr + "/a:srgbClr/@val");
  1510. if (color == null)//&& refNode != null
  1511. {
  1512. color = PowerPointHelper.GetTextByPath(themeContent, "pkg:xmlData/a:theme/a:themeElements/a:clrScheme/" + schemeClr + "/a:sysClr/@lastClr");
  1513. }
  1514. //console.log(color)
  1515. return color.Value;
  1516. }
  1517. private static string ToHex(dynamic n)
  1518. {
  1519. string hex = n.toString(16);
  1520. while (hex.Length < 2) { hex = "0" + hex; }
  1521. return hex;
  1522. }
  1523. private static dynamic HslToRgb(double hue, double sat, double light)
  1524. {
  1525. double t1, t2, r, g, b;
  1526. hue /= 60;
  1527. if (light <= 0.5)
  1528. {
  1529. t2 = light * (sat + 1);
  1530. }
  1531. else
  1532. {
  1533. t2 = light + sat - (light * sat);
  1534. }
  1535. t1 = light * 2 - t2;
  1536. r = HueToRgb(t1, t2, hue + 2) * 255;
  1537. g = HueToRgb(t1, t2, hue) * 255;
  1538. b = HueToRgb(t1, t2, hue - 2) * 255;
  1539. return new { r, g, b };
  1540. }
  1541. private static double HueToRgb(double t1, double t2, double hue)
  1542. {
  1543. if (hue < 0) hue += 6;
  1544. if (hue >= 6) hue -= 6;
  1545. if (hue < 1) return (t2 - t1) * hue + t1;
  1546. else if (hue < 3) return t2;
  1547. else if (hue < 4) return (t2 - t1) * (4 - hue) + t1;
  1548. else return t1;
  1549. }
  1550. private static string GetColorName2Hex(string name)
  1551. {
  1552. var hex = "";
  1553. 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" };
  1554. 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" };
  1555. var findIndx = colorName.IndexOf(name);
  1556. if (findIndx != -1)
  1557. {
  1558. hex = colorHex[findIndx];
  1559. }
  1560. return hex;
  1561. }
  1562. public static string GetFillType(XmlNode node)
  1563. {
  1564. //Need to test/////////////////////////////////////////////
  1565. //SOLID_FILL
  1566. //PIC_FILL
  1567. //GRADIENT_FILL
  1568. //PATTERN_FILL
  1569. //NO_FILL
  1570. var fillType = "";
  1571. if( node.GetTextByPath( "a:noFill")!= null)
  1572. {
  1573. fillType = "NO_FILL";
  1574. }
  1575. if (node.GetTextByPath("a:solidFill") != null)
  1576. {
  1577. fillType = "SOLID_FILL";
  1578. }
  1579. if (node.GetTextByPath("a:gradFill") != null)
  1580. {
  1581. fillType = "GRADIENT_FILL";
  1582. }
  1583. if (node.GetTextByPath("a:pattFill") != null)
  1584. {
  1585. fillType = "PATTERN_FILL";
  1586. }
  1587. if (node.GetTextByPath("a:blipFill") != null)
  1588. {
  1589. fillType = "PIC_FILL";
  1590. }
  1591. return fillType;
  1592. }
  1593. private NodesTable IndexNodes(XmlNode content)
  1594. {
  1595. var idTable = new Dictionary<string, Dictionary<string,XmlNode>>();
  1596. var idxTable = new Dictionary<string, Dictionary<string, XmlNode>>();
  1597. var typeTable = new Dictionary<string, Dictionary<string, XmlNode>>();
  1598. var spTreeNode = content.GetTextByPath("p:cSld/p:spTree");
  1599. // Dictionary<string, Dictionary<string, string>> slideResObj = new Dictionary<string, Dictionary<string, string>>();
  1600. var spTreeNodeChildren = spTreeNode.ChildNodes;
  1601. foreach (XmlNode child in spTreeNodeChildren)
  1602. {
  1603. if (child.Name.Equals("p:nvGrpSpPr") || child.Name.Equals("p:grpSpPr"))
  1604. {
  1605. continue;
  1606. }
  1607. //var targetNode = child.ChildNodes;
  1608. var targetNode = child.GetTextByPath("p:nvSpPr");
  1609. // < p:cNvCxnSpPr >
  1610. // < a:cxnSpLocks /> ///这个是什么意思
  1611. // </ p:cNvCxnSpPr >
  1612. if (targetNode == null) {
  1613. targetNode = child.GetTextByPath("p:nvCxnSpPr");
  1614. }
  1615. var id = targetNode.GetTextByPath("p:cNvPr/@id");
  1616. var idx = targetNode.GetTextByPath("p:nvPr/p:ph/@idx");
  1617. var type = targetNode.GetTextByPath("p:nvPr/p:ph/@type");
  1618. Dictionary<string, XmlNode> node = new Dictionary<string, XmlNode>();
  1619. if (child.ChildNodes != null) {
  1620. foreach (XmlNode xmlNode in child.ChildNodes) {
  1621. node.TryAdd(xmlNode.Name, xmlNode);
  1622. }
  1623. }
  1624. if (id != null)
  1625. {
  1626. idTable.Add(id.Value, node);
  1627. }
  1628. if (idx != null)
  1629. {
  1630. idxTable.Add(idx.Value, node);
  1631. }
  1632. if (type != null)
  1633. {
  1634. typeTable.Add(type.Value, node);
  1635. }
  1636. }
  1637. return new NodesTable { idTable =idTable, idxTable=idxTable, typeTable= typeTable };
  1638. }
  1639. private dynamic GetSlideSize(XmlDocument xdoc)
  1640. {
  1641. var sldSzNode = xdoc.GetTextByPath("//pkg:part[@pkg:name='/ppt/presentation.xml']/pkg:xmlData/p:presentation/p:sldSz");
  1642. double width = double.Parse(sldSzNode.GetTextByPath("@cx").Value) * px96 / px914400;
  1643. double height = double.Parse(sldSzNode.GetTextByPath("@cy").Value) * px96 / px914400;
  1644. return new { width, height };
  1645. }
  1646. private async Task<AzureBlobModel> GetThumbnailModel(XmlDocument xdoc, string shaCode)
  1647. {
  1648. var thumbnailNode = xdoc.GetTextByPath("//pkg:part[@pkg:name='/docProps/thumbnail.jpeg']");
  1649. if (thumbnailNode != null)
  1650. {
  1651. var contentType = thumbnailNode.GetTextByPath("@pkg:contentType");
  1652. var thumbnail = thumbnailNode.InnerText;
  1653. return await PowerPointHelper.SaveBase64ToBolob(thumbnail, contentType.Value, shaCode+"/imgs", "thumbnail", azureBlobDBRepository);
  1654. }
  1655. return null;
  1656. }
  1657. private XmlNode LoadTheme(XmlDocument xdoc)
  1658. {
  1659. 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");
  1660. // "/ppt/theme/theme1.xml"
  1661. string themeURI = "/ppt/" + themeRelationship.Value;
  1662. return xdoc.GetTextByPath("//pkg:part[@pkg:name='" + themeURI + "']");
  1663. }
  1664. }
  1665. }