HtexChart.cs 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  1. using DocumentFormat.OpenXml;
  2. using DocumentFormat.OpenXml.Drawing;
  3. using DocumentFormat.OpenXml.Drawing.Charts;
  4. using DocumentFormat.OpenXml.Packaging;
  5. using DocumentFormat.OpenXml.Presentation;
  6. using HTEXLib.Helpers.ShapeHelpers;
  7. using HTEXLib.Models.Inner;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Drawing;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Xml.Linq;
  14. namespace HTEXLib.Models.HTEX
  15. {
  16. public class HtexChart : HtexElement
  17. {
  18. public HtexChart(string id, double rot, double width, double height,
  19. double top, double left, bool invisible,
  20. bool animatable, int index, DocumentFormat.OpenXml.Drawing.Charts.ChartReference Chart, PPTSlide slide, string partForm, string timingId)
  21. {
  22. base.slide = slide;
  23. this.rot = rot;
  24. this.Chart = Chart;
  25. base.id = id;
  26. base.top = top;
  27. base.left = left;
  28. base.width = width;
  29. base.height = height;
  30. base.invisible = invisible;
  31. base.animatable = animatable;
  32. base.index = index;
  33. base.type = "Chart";
  34. base.partForm = partForm;
  35. base.sid = timingId;
  36. }
  37. public ChartPart chartPart { get; set; }
  38. public string VerticalAlign { get; set; }
  39. public DocumentFormat.OpenXml.Drawing.Charts.ChartReference Chart { get; set; }
  40. public override List<Item> DrawElement()
  41. {
  42. var ChartNode = slide.SlidePart.Parts.Where(x => x.RelationshipId == Chart.Id).FirstOrDefault();
  43. var url = ChartNode.OpenXmlPart.Uri.ToString().Replace("../", "/ppt/");
  44. var ChartParts = slide.SlidePart.GetPartsOfType<DocumentFormat.OpenXml.Packaging.ChartPart>();
  45. if (ChartParts != null) {
  46. var chart = ChartParts.Where(x => x.Uri.ToString() == url).FirstOrDefault() ;
  47. chartPart = chart;
  48. if (chart != null) {
  49. ChartColorStylePart ChartColorStylePart = null;
  50. ChartStylePart ChartStylePart = null;
  51. foreach (var idp in chart.Parts) {
  52. if (idp.OpenXmlPart is ChartColorStylePart ChartColorStyleParts) {
  53. ChartColorStylePart = ChartColorStyleParts;
  54. }
  55. if (idp.OpenXmlPart is ChartStylePart ChartStyleParts)
  56. {
  57. ChartStylePart = ChartStyleParts;
  58. }
  59. }
  60. if (ChartStylePart != null) {
  61. var ChartStyleChildren = ChartStylePart.ChartStyle.ChildElements;
  62. foreach (var child in ChartStyleChildren)
  63. {
  64. if (child is DocumentFormat.OpenXml.Office2013.Drawing.ChartStyle.StyleEntry StyleEntry)
  65. {
  66. DoStyleEntry(StyleEntry);
  67. }
  68. ///OfficeArtExtensionList cs: extLst
  69. // MarkerLayoutProperties cs: dataPointMarkerLayout
  70. }
  71. }
  72. Chart charts= DrawChart(chart.ChartSpace);
  73. return new List<Item> { charts };
  74. }
  75. }
  76. return null;
  77. }
  78. public Chart DrawChart(DocumentFormat.OpenXml.Drawing.Charts.ChartSpace chartSpace) {
  79. var Chart = chartSpace.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.Chart>();
  80. var ShapeProperties = chartSpace.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.ShapeProperties>();
  81. HTEXLib.Models.HTEX.ShapeStyle shapeStyleChart= PPTXHelper.DoShapeProperties(ShapeProperties,slide,type,partForm);
  82. var TextProperties = chartSpace.GetFirstChild<TextProperties>();
  83. var style = chartSpace.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.Style>();
  84. var ColorMapOverride = chartSpace.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.ColorMapOverride>();
  85. var style2010 = chartSpace.GetFirstChild<DocumentFormat.OpenXml.Office2010.Drawing.Charts.Style>();
  86. var UserShapesReference = chartSpace.GetFirstChild<UserShapesReference>();
  87. var charts = DoPlotArea(Chart.PlotArea);
  88. ShapeStyle shapeStyle = null;
  89. if (Chart.Title != null)
  90. {
  91. var ChartShapeProperties = Chart.Title.ChartShapeProperties;
  92. shapeStyle = PPTXHelper.DoShapeProperties(ChartShapeProperties, slide, type, partForm, chartPart);
  93. }
  94. var(PPTParagraphs, tBody) = DoChartTitle(Chart.Title);
  95. TextBody textBody = DrawText(PPTParagraphs, tBody);
  96. Shape shape= new Shape { type = "Sp", shapeType = "rect", textBody = textBody };
  97. shape.style.fill = shapeStyle != null ? shapeStyle.fill : null;
  98. shape.style.border = shapeStyle != null ? shapeStyle.border : null;
  99. var chart= new Chart {sid=sid, id = this.id, charts =charts,title=shape};
  100. Position position = new Position { cx = width, cy = height, x = left, y = top, rot = rot };
  101. chart.style.position = position;
  102. chart.style.fill = shapeStyleChart != null ? shapeStyleChart.fill : null;
  103. chart.style.border = shapeStyleChart != null ? shapeStyleChart.border : null;
  104. chart.style.effect= shapeStyleChart != null ? shapeStyleChart.effect : null;
  105. if (chart.style.fill.type == -1|| chart.style.fill.type == 0)
  106. {
  107. chart.style.fill = null;
  108. }
  109. if (chart.style.border != null && chart.style.border.type == "none")
  110. {
  111. chart.style.border = null;
  112. }
  113. return chart;
  114. }
  115. public (LinkedList<PPTParagraph> paragraphs, TextBody textBody) DoChartTitle(DocumentFormat.OpenXml.Drawing.Charts.Title title)
  116. {
  117. if (title==null ||title.ChartText == null)
  118. {
  119. return (null, null);
  120. }
  121. LinkedList<PPTParagraph> Texts = new LinkedList<PPTParagraph>();
  122. var BodyProperties = title.ChartText.RichText.BodyProperties;
  123. var ListStyle = title.ChartText.RichText.ListStyle;
  124. var Layout = title.Layout;
  125. if (BodyProperties == null)
  126. {
  127. BodyProperties = title.TextProperties.BodyProperties;
  128. }
  129. if (ListStyle != null&& title.TextProperties!=null)
  130. {
  131. ListStyle = title.TextProperties.ListStyle;
  132. }
  133. if (ListStyle != null)
  134. {
  135. //TODO文本层级内容
  136. }
  137. if (BodyProperties.Anchor != null)
  138. {
  139. string VerticalAlign = BodyProperties.Anchor.Value.ToString();
  140. }
  141. int fontScale = 100000;
  142. double LineSpaceReduction = 0;
  143. TextBody textBody= fillPropertiesFromMasterShape(title.ChartText.RichText, ref fontScale ,ref LineSpaceReduction);
  144. textBody.lnSpRn = LineSpaceReduction;
  145. var ExtensionList = title.ExtensionList;
  146. var Paragraphs = title.ChartText.RichText.Elements<DocumentFormat.OpenXml.Drawing.Paragraph>();
  147. int buIndex = 1;
  148. BuChar buChar = new BuChar();
  149. foreach (var paragraph in Paragraphs)
  150. {
  151. PlaceholderShape placeholder = null;
  152. var par = new PPTParagraph(slide, placeholder,partForm)
  153. {
  154. Paragraph = index++
  155. };
  156. if (paragraph.ParagraphProperties != null)
  157. {
  158. int level = paragraph.ParagraphProperties.Level == null ?
  159. -1 : paragraph.ParagraphProperties.Level.Value;
  160. par.Level = level;
  161. }
  162. par.SetParagraphProperties(paragraph, slide.SlidePart,
  163. slide.shapeListStyleMaster, slide.shapeListStyleLayout,buChar);
  164. bool hasText = false;
  165. foreach (var obj in paragraph.ChildElements)
  166. {
  167. hasText = GetParagraphChildElements(title.ChartText.RichText, par, hasText, obj, fontScale);
  168. }
  169. //This is because when we set paragraph properties we add the bullet to the text runs.
  170. //If we don't have text it still outputs the bullet character.
  171. if (par.bullet != null && hasText)
  172. {
  173. par.bullet.FontSize = par.RunPropList[0].FontSize;
  174. par.bullet.FontColor = par.RunPropList[0].FontColor;
  175. par.bullet.bullIndex = buChar.index - 1;
  176. // par.RunPropList.Insert(0, par.bullet);
  177. }
  178. else
  179. {
  180. if (buChar != null)
  181. {
  182. buChar.index = 1;
  183. }
  184. }
  185. Texts.AddLast(par);
  186. }
  187. return (Texts,textBody);
  188. }
  189. private TextBody fillPropertiesFromMasterShape(DocumentFormat.OpenXml.Drawing.Charts.TextBodyType TxBody/*, bool isLayout, bool addListStyle*/ , ref int fontScale ,ref double LineSpaceReduction)
  190. {
  191. TextBody textBody = new TextBody();
  192. if (null != TxBody)
  193. {
  194. // if (TxBody.ListStyle != null && addListStyle)
  195. // {
  196. // if (isLayout)
  197. // slide.shapeListStyleLayout = TxBody.ListStyle;
  198. // else
  199. // slide.shapeListStyleMaster = TxBody.ListStyle;
  200. // }
  201. if (TxBody.BodyProperties != null && TxBody.BodyProperties.Anchor != null)
  202. textBody.anchor = TxBody.BodyProperties.Anchor;
  203. if (TxBody.BodyProperties.TopInset != null)
  204. {
  205. textBody.top = System.Math.Round((double)TxBody.BodyProperties.TopInset.Value * 1.0 / 12700, Globals.degree);
  206. }
  207. if (TxBody.BodyProperties.BottomInset != null)
  208. {
  209. textBody.bottom = System.Math.Round((double)TxBody.BodyProperties.BottomInset.Value * 1.0 / 12700, Globals.degree);
  210. }
  211. if (TxBody.BodyProperties.RightInset != null)
  212. {
  213. textBody.right = System.Math.Round((double)TxBody.BodyProperties.RightInset.Value * 1.0 / 12700, Globals.degree);
  214. }
  215. if (TxBody.BodyProperties.LeftInset != null)
  216. {
  217. textBody.left = System.Math.Round((double)TxBody.BodyProperties.LeftInset.Value * 1.0 / 12700, Globals.degree);
  218. }
  219. if (TxBody.BodyProperties != null &&
  220. TxBody.BodyProperties.GetFirstChild<DocumentFormat.OpenXml.Drawing.NormalAutoFit>() != null && TxBody.BodyProperties.GetFirstChild<DocumentFormat.OpenXml.Drawing.NormalAutoFit>().FontScale != null)
  221. {
  222. fontScale = TxBody.BodyProperties.GetFirstChild<DocumentFormat.OpenXml.Drawing.NormalAutoFit>().FontScale.Value;
  223. }
  224. if (TxBody.BodyProperties != null &&
  225. TxBody.BodyProperties.GetFirstChild<DocumentFormat.OpenXml.Drawing.NormalAutoFit>() != null && TxBody.BodyProperties.GetFirstChild<DocumentFormat.OpenXml.Drawing.NormalAutoFit>().LineSpaceReduction != null)
  226. {
  227. LineSpaceReduction = TxBody.BodyProperties.GetFirstChild<DocumentFormat.OpenXml.Drawing.NormalAutoFit>().LineSpaceReduction.Value;
  228. }
  229. if (TxBody.BodyProperties.AnchorCenter != null)
  230. {
  231. textBody.anchorCtr = TxBody.BodyProperties.AnchorCenter;
  232. }
  233. if (TxBody.BodyProperties.RightToLeftColumns != null)
  234. {
  235. textBody.rtlCol = TxBody.BodyProperties.RightToLeftColumns;
  236. }
  237. if (TxBody.BodyProperties.Wrap != null)
  238. {
  239. textBody.wrap = TxBody.BodyProperties.Wrap;
  240. }
  241. if (TxBody.BodyProperties.Vertical != null)
  242. {
  243. textBody.vert = TxBody.BodyProperties.Vertical;
  244. }
  245. if (TxBody.BodyProperties.Rotation != null)
  246. {
  247. rot = TxBody.BodyProperties.Rotation.Value / 60000.0;
  248. }
  249. var elements = TxBody.BodyProperties.ChildElements;
  250. foreach (var element in elements)
  251. {
  252. if (element is NoAutoFit)
  253. {
  254. //此元素指定文本主体内的文本不应自动适合于边框。 自动拟合是当文本框内的文本被缩放以保持在文本框内时。
  255. textBody.autoFit = false;
  256. }
  257. if (element is NormalAutoFit normalAutoFit)
  258. {
  259. //每个形状的文本都停留在该形状的范围内
  260. textBody.autoFit = true;
  261. fontScale = normalAutoFit.FontScale != null ? normalAutoFit.FontScale.Value : 0;
  262. }
  263. if (element is ShapeAutoFit)
  264. {
  265. //每个形状的文本都停留在该形状的范围内。
  266. textBody.autoFit = true;
  267. }
  268. //TODO 3D Scene3DType Shape3DType FlatText
  269. }
  270. }
  271. return textBody;
  272. }
  273. public TextBody DrawText(LinkedList<PPTParagraph> Texts, TextBody textBody)
  274. {
  275. if (Texts == null) {
  276. return null;
  277. }
  278. List<Paragraph> Paragraphs = new List<Paragraph>();
  279. foreach (var par in Texts)
  280. {
  281. double paragraphTop = par.getSpaceBeforePoints();
  282. Paragraph paragraph = new HTEXLib.Paragraph { /*animatable = par.Animatable, invisible = par.Invisible */};
  283. paragraph.style.hori = par.Align;
  284. paragraph.style.vert = VerticalAlign;
  285. if (par.bullet != null)
  286. {
  287. var bullet = par.bullet;
  288. paragraph.buChar = new BuChar
  289. {
  290. type=bullet.BulletType,
  291. //left = bullet.Left,
  292. buchar = bullet.Text,
  293. color = bullet.FontColor,
  294. typeface = bullet.FontFamily,
  295. size = bullet.FontSize,
  296. };
  297. }
  298. double newTop = par.getSpaceBeforePoints();
  299. int left = 0;
  300. List<HtexText> textElements = new List<HtexText>();
  301. List<Text> texts = new List<Text>();
  302. if (par.RunPropList == null || par.RunPropList.Count == 0 && par.defaultRunProperties != null) //Only paragraph!
  303. {
  304. float points = float.Parse(par.defaultRunProperties.FontSize.ToString()) * 72.0F / 96.0F;
  305. System.Drawing.Font font = new System.Drawing.Font(par.defaultRunProperties.FontFamily.ToString(), points);
  306. newTop = font.Height;
  307. }
  308. List<HtexText> processedElements = new List<HtexText>();
  309. IEnumerable<PPTRunProperties> pPTRunProperties = breakTextsToShape(par);
  310. foreach (var text in pPTRunProperties)
  311. {
  312. float points = float.Parse(text.FontSize.ToString()) * 72.0F / 96.0F;
  313. System.Drawing.Font font = new System.Drawing.Font(text.FontFamily.ToString(), points);
  314. if (text.Bold) font = new System.Drawing.Font(text.FontFamily.ToString(), points, System.Drawing.FontStyle.Bold);
  315. else if (text.Italic)
  316. font = new System.Drawing.Font(text.FontFamily.ToString(), points, System.Drawing.FontStyle.Italic);
  317. else if (text.Underline != null && text.Underline.Equals("Single"))
  318. font = new System.Drawing.Font(text.FontFamily.ToString(), points, System.Drawing.FontStyle.Underline);
  319. newTop = font.Height > newTop ? font.Height : newTop;
  320. newTop = par.getLineSpacingInPointsFromFont(newTop);
  321. if (text.isBreak)
  322. {
  323. top += newTop;
  324. left = 0;
  325. fixLeftSpacingForAlignment(processedElements, par, font);
  326. processedElements.Clear();
  327. continue;
  328. }
  329. String currentString = text.Text.TrimEnd() + getStringFromTextElements(processedElements);
  330. HtexText t1 = new HtexText(left: left,
  331. top: top,
  332. fontFamily: text.FontFamily,
  333. fontColor: text.FontColor,
  334. fontSize: text.FontSize,
  335. isBullet: text.isBullet,
  336. bold: text.Bold,
  337. italic: text.Italic,
  338. underline: text.Underline,
  339. id: id,
  340. slideIndex: slide.slideIndex)
  341. {
  342. Rotate = this.rot
  343. };
  344. t1.width = MeasureString(text.Text, font);
  345. if (text.isBullet && text.Text != null && text.Text.Contains("rId"))
  346. {
  347. // t1.PictureBullet = true;
  348. t1.width = text.bulletSize;
  349. t1.bulletSize = text.bulletSize;
  350. newTop = text.bulletSize;
  351. }
  352. t1.Text = text.Text;
  353. textElements.Add(t1);
  354. RunStyle runStyle = PPTXHelper.DoRunProperties(text.runProp, slide, "text", partForm);
  355. if (runStyle.border != null && (runStyle.border.color.type == -1 || runStyle.border.color.type == 0))
  356. {
  357. runStyle.border.color = null;
  358. }
  359. texts.Add(new Text
  360. {
  361. content = t1.Text,
  362. link=text.link,
  363. linkType=text.linkType,
  364. style = new FontStyle
  365. {
  366. fill = runStyle.fill.type == -1 || runStyle.fill.type == 0 ? null : runStyle.fill,
  367. border = runStyle.border,
  368. effect = runStyle.effect,
  369. align = par.FontAlign,
  370. spacing = par.defTabSize,
  371. color = text.FontColor,
  372. family = text.FontFamily,
  373. //top = top,
  374. // left = left,
  375. size = text.FontSize,
  376. // isBullet = text.isBullet,
  377. underline = t1.underline,
  378. italic = text.Italic,
  379. bold = text.Bold,
  380. //rot = this.rot,
  381. //width = t1.width,
  382. // pictureBullet = t1.PictureBullet,
  383. //bulletSize = t1.bulletSize
  384. }
  385. });
  386. processedElements.Add(t1);
  387. }
  388. fixLeftSpacingForAlignment(processedElements, par);
  389. HtexText lastTxt = null;
  390. List<HtexText> mergedTextElements = new List<HtexText>();
  391. foreach (HtexText textElement in textElements)
  392. {
  393. if (lastTxt == null || !lastTxt.sameProps(textElement))
  394. mergedTextElements.Add(textElement);
  395. else
  396. mergedTextElements[mergedTextElements.Count - 1].Text += textElement.Text;
  397. lastTxt = textElement;
  398. }
  399. //foreach (HtexText textElement in mergedTextElements) {
  400. // shapeBuilder.Append(textElement.DrawElement());
  401. //}
  402. top += newTop;
  403. top += par.getSpaceAfterPoints(newTop);
  404. top += par.getSpaceBeforePoints(newTop);
  405. paragraph.texts = texts;
  406. Paragraphs.Add(paragraph);
  407. }
  408. if (textBody == null)
  409. {
  410. return null;
  411. }
  412. else {
  413. textBody.paragraphs = Paragraphs;
  414. }
  415. return textBody;
  416. }
  417. private String getStringFromTextElements(List<HtexText> elements)
  418. {
  419. if (elements == null || elements.Count == 0)
  420. return "";
  421. StringBuilder result = new StringBuilder();
  422. foreach (HtexText el in elements)
  423. {
  424. result.Append(el.Text);
  425. }
  426. return result.ToString();
  427. }//We have two similar methods - this one is better because it measures the whole string with the font.
  428. private void fixLeftSpacingForAlignment(List<HtexText> textElements, PPTParagraph par, System.Drawing.Font font)
  429. {
  430. double combinedWidth = 0;
  431. StringBuilder combinedText = new StringBuilder();
  432. foreach (HtexText textElement in textElements)
  433. {
  434. if (textElement.PictureBullet)
  435. combinedWidth += textElement.bulletSize;
  436. else
  437. combinedText.Append(textElement.Text);
  438. }
  439. double bulletOffset = 0;
  440. if (par.bullet != null && textElements.Count > 0 && !textElements[0].isBullet)
  441. {
  442. bulletOffset = par.bullet.bulletSize;
  443. combinedWidth += par.bullet.bulletSize;
  444. }
  445. combinedWidth += MeasureString(combinedText.ToString(), font);
  446. double firstLeft = 0;
  447. if ("Center".Equals(par.Align))
  448. firstLeft = ((this.width - par.Indent - bulletOffset - par.marginLeft - par.marginRight) - combinedWidth) / 2;
  449. else if ("Right".Equals(par.Align))
  450. firstLeft = (this.width - par.Indent - bulletOffset - par.marginLeft - par.marginRight) - combinedWidth;
  451. combinedText = new StringBuilder();
  452. combinedWidth = 0; //Now used only for picture bullets!
  453. foreach (HtexText textElement in textElements)
  454. {
  455. textElement.setLeft(firstLeft + par.Indent + bulletOffset + par.marginLeft + combinedWidth + MeasureString(combinedText.ToString(), font));
  456. if (textElement.PictureBullet)
  457. combinedWidth += textElement.bulletSize;
  458. else
  459. combinedText.Append(textElement.Text);
  460. }
  461. }//We have two similar methods. This is worse because it uses the Width property of each element instead of measuring the whole string.
  462. //There is mistake in the calculations coming from that and the difference is bigger when there are more elements.
  463. private void fixLeftSpacingForAlignment(List<HtexText> textElements, PPTParagraph par)
  464. {
  465. double combinedWidth = 0;
  466. foreach (HtexText textElement in textElements)
  467. combinedWidth += textElement.width;
  468. double bulletOffset = 0;
  469. if (par.bullet != null && textElements.Count > 0 && !textElements[0].isBullet)
  470. {
  471. combinedWidth += par.bullet.bulletSize;
  472. bulletOffset = par.bullet.bulletSize;
  473. }
  474. double currentLeft = 0;
  475. if ("Center".Equals(par.Align))
  476. currentLeft = ((this.width - par.Indent - bulletOffset - par.marginLeft - par.marginRight) - combinedWidth) / 2;
  477. else if ("Right".Equals(par.Align))
  478. currentLeft = (this.width - par.Indent - bulletOffset - par.marginLeft - par.marginRight) - combinedWidth;
  479. foreach (HtexText textElement in textElements)
  480. {
  481. textElement.setLeft(currentLeft + par.Indent + bulletOffset + par.marginLeft);
  482. currentLeft += textElement.width;
  483. }
  484. }
  485. private IEnumerable<PPTRunProperties> breakTextsToShape(PPTParagraph par)
  486. {
  487. List<PPTRunProperties> list = par.RunPropList;
  488. List<PPTRunProperties> result = new List<PPTRunProperties>();
  489. String previousToken = null;
  490. double bulletSize = 0;
  491. foreach (var text in list)
  492. {
  493. float points = float.Parse(text.FontSize.ToString()) * 72.0F / 96.0F;
  494. System.Drawing.Font font = new System.Drawing.Font(text.FontFamily.ToString(), points);
  495. if (text.Bold) font = new System.Drawing.Font(text.FontFamily.ToString(), points, System.Drawing.FontStyle.Bold);
  496. else if (text.Italic) font = new System.Drawing.Font(text.FontFamily.ToString(), points, System.Drawing.FontStyle.Italic);
  497. else if (text.Underline != null && text.Underline.Equals("Single"))
  498. font = new System.Drawing.Font(text.FontFamily.ToString(), points, System.Drawing.FontStyle.Underline);
  499. int size = 0;
  500. if (text.isBullet && text.Text != null && text.Text.Contains("rId"))
  501. bulletSize = text.bulletSize;
  502. else
  503. size = MeasureString((previousToken == null ? "" : previousToken + " ") + text.Text, font);
  504. if (text.isBreak || size + bulletSize < this.width - par.Indent - par.marginLeft - par.marginRight)//- Shape.LeftInset - Shape.RightInset)
  505. {
  506. if (text.Text != null && text.Text.Trim() != "" && !(text.isBullet && text.Text.Contains("rId")))
  507. {
  508. previousToken = (previousToken == null ? "" : previousToken) + text.Text;
  509. }
  510. if (text.isBreak)
  511. previousToken = null;
  512. result.Add(text);
  513. continue;
  514. }
  515. // previousToken = null;
  516. string[] tokens = text.Text.Split(' ');
  517. int index = 0;
  518. foreach (string token in tokens)
  519. {
  520. index++;
  521. int combinedSize = MeasureString((previousToken == null ? "" : previousToken + " ") + token, font);
  522. if (combinedSize + bulletSize > this.width - par.Indent - par.marginLeft - par.marginRight)//- Shape.LeftInset - Shape.RightInset)
  523. {
  524. PPTRunProperties temp = new PPTRunProperties(text);
  525. temp.Text = "";
  526. temp.isBreak = true;
  527. result.Add(temp);
  528. temp = new PPTRunProperties(text);
  529. temp.Text = index < tokens.Length ? token + " " : token;
  530. result.Add(temp);
  531. previousToken = token;
  532. }
  533. else
  534. {
  535. PPTRunProperties temp = new PPTRunProperties(text);
  536. temp.Text = index < tokens.Length ? token + " " : token;
  537. result.Add(temp);
  538. previousToken = (previousToken == null ? "" : previousToken + " ") + token;
  539. }
  540. }
  541. }
  542. return result;
  543. }
  544. public static int MeasureString(string s, System.Drawing.Font font)
  545. {
  546. s = s.Replace("\t", "aaaa");//TODO the replace is dirty hack for measuring tabulations
  547. StringFormat stringFormat = new StringFormat(StringFormat.GenericTypographic);
  548. CharacterRange[] rng = { new CharacterRange(0, s.Length) };
  549. stringFormat.SetMeasurableCharacterRanges(rng);
  550. Graphics g = Graphics.FromImage(new Bitmap(100, 100));
  551. //Use measure character ranges with a big box because we used this for measurement only
  552. //Later we might better use this for drawing the text.
  553. Region[] regions = g.MeasureCharacterRanges(s, font, new System.Drawing.Rectangle(0, 0, 10000, 3000), stringFormat);
  554. foreach (Region region in regions)
  555. {
  556. RectangleF rect = region.GetBounds(g);
  557. return (int)System.Math.Round(rect.Width);
  558. }
  559. return 0;
  560. //
  561. // SizeF result;
  562. // using (var image = new Bitmap(1, 1))
  563. // {
  564. // using (var g = Graphics.FromImage(image))
  565. // {
  566. // result = g.MeasureString(s, font);
  567. // }
  568. // }
  569. //
  570. // return result.ToSize();
  571. }
  572. private bool GetParagraphChildElements(RichText shape, PPTParagraph par, bool hasText, OpenXmlElement obj, int fontScale)
  573. {
  574. LinkedList<string> effectShapes = new LinkedList<string>();
  575. if (obj is Run)
  576. {
  577. Run run = (Run)obj;
  578. hasText = true;
  579. PPTRunProperties runProp = new PPTRunProperties(par.defaultRunProperties);
  580. runProp.Text = run.Text.Text;
  581. runProp.SetRunProperties(run.RunProperties, shape, ref effectShapes);
  582. runProp.FontSize = System.Math.Round(fontScale * runProp.FontSize / Globals.PercentageConstant);
  583. par.RunPropList.Add(runProp);
  584. }
  585. else if (obj is Field)
  586. {
  587. Field run = (Field)obj;
  588. hasText = true;
  589. PPTRunProperties runProp = new PPTRunProperties(par.defaultRunProperties);
  590. runProp.Text = run.Text.Text;
  591. runProp.SetRunProperties(run.RunProperties, shape, ref effectShapes);
  592. runProp.FontSize = System.Math.Round(fontScale * runProp.FontSize / Globals.PercentageConstant);
  593. par.RunPropList.Add(runProp);
  594. }
  595. else if (obj is Break)
  596. {
  597. Break aBreak = (Break)obj;
  598. PPTRunProperties runProp = new PPTRunProperties(par.defaultRunProperties);
  599. runProp.SetRunProperties(aBreak.RunProperties, shape, ref effectShapes);
  600. runProp.FontSize = System.Math.Round(fontScale * runProp.FontSize / Globals.PercentageConstant);
  601. runProp.isBreak = true;
  602. par.RunPropList.Add(runProp);
  603. }
  604. return hasText;
  605. }
  606. public List<CommonChart> DoPlotArea(PlotArea plotArea) {
  607. List<CommonChart> charts = new List<CommonChart>();
  608. foreach (var child in plotArea.ChildElements)
  609. {
  610. string key = child.LocalName;
  611. IEnumerable<XElement> serNodes = null;
  612. switch (key)
  613. {
  614. //break块中不可以随意更换,此条件用于归类不同从Chart
  615. case "pieChart":
  616. case "ofPieChart":
  617. case "pie3DChart":
  618. case "doughnutChart":
  619. PieChart pieChart = new PieChart { chartType = "pie" };
  620. if (key.Equals("pie3DChart"))
  621. {
  622. pieChart.is3D = true;
  623. }
  624. pieChart.pieType = key;
  625. if (key.Equals("ofPieChart"))
  626. {
  627. var ofPieType = child.GetTextByPath("c:ofPieType");
  628. if (ofPieType != null)
  629. {
  630. //ofPieChart-pie ofPieChart-bar 子母饼图
  631. pieChart.pieType += "-" + ofPieType.Attribute("val").Value;
  632. }
  633. }
  634. serNodes = child.GetTextByPathList("c:ser");
  635. pieChart.datas = ExtractChartData(serNodes);
  636. charts.Add(pieChart);
  637. break;
  638. case "lineChart":
  639. case "line3DChart":
  640. LineChart lineChart = new LineChart { chartType = "line" };
  641. if (key.Equals("line3DChart"))
  642. {
  643. lineChart.is3D = true;
  644. }
  645. lineChart.lineType = key;
  646. var LineGrouping = child.GetTextByPath("c:grouping");
  647. if (LineGrouping != null)
  648. {
  649. //standard stacked percentStacked
  650. lineChart.lineType += "-" + LineGrouping.Attribute("val").Value;
  651. }
  652. serNodes = child.GetTextByPathList("c:ser");
  653. lineChart.datas = ExtractChartData(serNodes);
  654. charts.Add(lineChart);
  655. break;
  656. case "barChart":
  657. case "bar3DChart":
  658. var barDir = child.GetTextByPath("c:barDir");
  659. if (barDir != null)
  660. {
  661. if (barDir.Attribute("val").Value.Equals("bar"))
  662. {
  663. BarChart barChart = new BarChart { chartType = "bar" };
  664. charts.Add(barChart);
  665. if (key.Equals("bar3DChart"))
  666. {
  667. barChart.is3D = true;
  668. }
  669. barChart.barType = key;
  670. var BarGrouping = child.GetTextByPath("c:grouping");
  671. if (BarGrouping != null)
  672. {
  673. //standard stacked percentStacked
  674. barChart.barType += "-" + BarGrouping.Attribute("val").Value;
  675. }
  676. serNodes = child.GetTextByPathList("c:ser");
  677. barChart.datas = ExtractChartData(serNodes);
  678. charts.Add(barChart);
  679. }
  680. else if (barDir.Attribute("val").Value.Equals("col"))
  681. {
  682. ColChart colChart = new ColChart { chartType = "col" };
  683. if (key.Equals("bar3DChart"))
  684. {
  685. colChart.is3D = true;
  686. }
  687. colChart.colType = key.Replace("bar", "col");
  688. var ColGrouping = child.GetTextByPath("c:grouping");
  689. if (ColGrouping != null)
  690. {
  691. //standard stacked percentStacked
  692. colChart.colType += "-" + ColGrouping.Attribute("val").Value;
  693. }
  694. serNodes = child.GetTextByPathList("c:ser");
  695. colChart.datas = ExtractChartData(serNodes);
  696. charts.Add(colChart);
  697. }
  698. }
  699. break;
  700. case "areaChart":
  701. case "area3DChart":
  702. AreaChart areaChart = new AreaChart { chartType = "area" };
  703. if (key.Equals("area3DChart"))
  704. {
  705. areaChart.is3D = true;
  706. }
  707. areaChart.areaType = key;
  708. var AreaGrouping = child.GetTextByPath("c:grouping");
  709. if (AreaGrouping != null)
  710. {
  711. //standard stacked percentStacked
  712. areaChart.areaType += "-" + AreaGrouping.Attribute("val").Value;
  713. }
  714. serNodes = child.GetTextByPathList("c:ser");
  715. areaChart.datas = ExtractChartData(serNodes);
  716. charts.Add(areaChart);
  717. break;
  718. case "scatterChart":
  719. case "bubbleChart":
  720. ScatterChart scatterChart = new ScatterChart { chartType = "scatter" };
  721. scatterChart.scatterType = key;
  722. if (key.Equals("scatterChart"))
  723. {
  724. var ScatterStyle = child.GetTextByPath("c:scatterStyle");
  725. if (ScatterStyle != null)
  726. {
  727. scatterChart.scatterType += "-" + ScatterStyle.Attribute("val").Value.Replace("Marker", "");
  728. }
  729. }
  730. serNodes = child.GetTextByPathList("c:ser");
  731. scatterChart.datas = ExtractChartData(serNodes);
  732. charts.Add(scatterChart);
  733. break;
  734. case "radarChart":
  735. RadarChart radarChart = new RadarChart { chartType = "radar" };
  736. radarChart.radarType = key;
  737. var RadarStyle = child.GetTextByPath("c:radarStyle");
  738. if (RadarStyle != null)
  739. {
  740. radarChart.radarType += "-" + RadarStyle.Attribute("val").Value;
  741. }
  742. serNodes = child.GetTextByPathList("c:ser");
  743. radarChart.datas = ExtractChartData(serNodes);
  744. charts.Add(radarChart);
  745. break;
  746. case "plotAreaRegion":
  747. PlotAreaChart plotAreaChart = new PlotAreaChart { chartType = "plotArea" };
  748. plotAreaChart.plotAreaType = key;
  749. var PlotSeries = child.GetTextByPath("cx:series");
  750. if (PlotSeries != null)
  751. {
  752. plotAreaChart.plotAreaType += "-" + PlotSeries.Attribute("val").Value;
  753. }
  754. serNodes = child.GetTextByPathList("c:ser");
  755. plotAreaChart.datas = ExtractChartData(serNodes);
  756. charts.Add(plotAreaChart);
  757. break;
  758. case "stockChart":
  759. StockChart stockChart = new StockChart { chartType = "stock" };
  760. stockChart.stockType = key;
  761. serNodes = child.GetTextByPathList("c:ser");
  762. stockChart.datas = ExtractChartData(serNodes);
  763. charts.Add(stockChart);
  764. break;
  765. case "surfaceChart":
  766. case "surface3DChart":
  767. SurfaceChart surfaceChart = new SurfaceChart { chartType = "surface" };
  768. if (key.Equals("surface3DChart"))
  769. {
  770. surfaceChart.is3D = true;
  771. }
  772. surfaceChart.surfaceType = key;
  773. var Wireframe = child.GetTextByPath("c:wireframe");
  774. if (Wireframe != null)
  775. {
  776. surfaceChart.surfaceType += "-" + Wireframe.Attribute("val").Value;
  777. }
  778. serNodes = child.GetTextByPathList("c:ser");
  779. surfaceChart.datas = ExtractChartData(serNodes);
  780. charts.Add(surfaceChart);
  781. break;
  782. }
  783. }
  784. return charts;
  785. }
  786. public List<Dictionary<string, object>> ExtractChartData(IEnumerable<XElement> nodes)
  787. {
  788. if (nodes != null)
  789. {
  790. List<Dictionary<string, object>> listDict = new List<Dictionary<string, object>>();
  791. foreach (XElement node in nodes)
  792. {
  793. if (node.GetTextByPath("c:xVal") != null)
  794. {
  795. Dictionary<string, object> dict = new Dictionary<string, object>();
  796. var xCvNodes = node.GetTextByPathList("c:xVal/c:numRef/c:numCache/c:pt/c:v");
  797. if (xCvNodes != null)
  798. {
  799. List<string> list = new List<string>();
  800. foreach (XElement cvNode in xCvNodes)
  801. {
  802. list.Add(cvNode.Value);
  803. }
  804. dict.Add("xAxis", list);
  805. }
  806. var yCvNodes = node.GetTextByPathList("c:yVal/c:numRef/c:numCache/c:pt/c:v");
  807. if (yCvNodes != null)
  808. {
  809. List<string> list = new List<string>();
  810. foreach (XElement cvNode in yCvNodes)
  811. {
  812. list.Add(cvNode.Value);
  813. }
  814. dict.Add("yAxis", list);
  815. }
  816. dict.Add("colName", "-");
  817. listDict.Add(dict);
  818. }
  819. else
  820. {
  821. Dictionary<string, object> dict = new Dictionary<string, object>();
  822. var spPr = node.GetTextByPath("c:spPr");
  823. if (spPr != null)
  824. {
  825. var ChartShapeProperties = new ChartShapeProperties(spPr.ToString());
  826. ShapeStyle shapeStyle = PPTXHelper.DoShapeProperties(ChartShapeProperties, slide, type, partForm,chartPart);
  827. dict.Add("colStyle", shapeStyle);
  828. }
  829. else {
  830. dict.Add("colStyle", null);
  831. }
  832. var colNameNode = node.GetTextByPath("c:tx/c:strRef/c:strCache/c:pt/c:v");
  833. if (colNameNode != null)
  834. {
  835. dict.Add("colName", colNameNode.Value);
  836. }
  837. //name
  838. var catNodes = node.GetTextByPathList("c:cat/c:strRef/c:strCache/c:pt/c:v");
  839. if (catNodes == null)
  840. {
  841. catNodes = node.GetTextByPathList("c:cat/c:numRef/c:numCache/c:pt/c:v");
  842. }
  843. if (catNodes != null)
  844. {
  845. List<string> list = new List<string>();
  846. foreach (XElement cvNode in catNodes)
  847. {
  848. list.Add(cvNode.Value);
  849. }
  850. dict.Add("xAxis", list);
  851. }
  852. //value
  853. var valNodes = node.GetTextByPathList("c:val/c:numRef/c:numCache/c:pt/c:v");
  854. if (valNodes != null)
  855. {
  856. List<string> list = new List<string>();
  857. foreach (XElement cvNode in valNodes)
  858. {
  859. list.Add(cvNode.Value);
  860. }
  861. dict.Add("yAxis", list);
  862. }
  863. listDict.Add(dict);
  864. }
  865. }
  866. return listDict;
  867. }
  868. return null;
  869. }
  870. public void DoStyleEntry(DocumentFormat.OpenXml.Office2013.Drawing.ChartStyle.StyleEntry StyleEntry)
  871. {
  872. //TODO
  873. /*
  874. * LineReference
  875. LineWidthScale
  876. FillReference
  877. EffectReference
  878. FontReference
  879. ShapeProperties
  880. TextCharacterPropertiesType
  881. TextBodyProperties
  882. OfficeArtExtensionList
  883. * */
  884. var LineReference = StyleEntry.LineReference;
  885. var LineWidthScale= StyleEntry.LineWidthScale;
  886. var FillReference= StyleEntry.FillReference;
  887. var EffectReference = StyleEntry.EffectReference;
  888. var FontReference= StyleEntry.FontReference;
  889. var ShapeProperties = StyleEntry.ShapeProperties;
  890. var TextCharacterPropertiesType = StyleEntry.TextCharacterPropertiesType;
  891. var TextBodyProperties = StyleEntry.TextBodyProperties;
  892. var OfficeArtExtensionList = StyleEntry.OfficeArtExtensionList;
  893. }
  894. }
  895. public class ChartStyle {
  896. //
  897. }
  898. }