ShapeGenerator.cs 65 KB

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