ShapeGenerator.cs 86 KB

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