Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. using System;
  2. using System.Linq;
  3. using System.Xml.Linq;
  4. using System.Drawing;
  5. using System.Globalization;
  6. namespace Novacode
  7. {
  8. /// <summary>
  9. /// A text formatting.
  10. /// </summary>
  11. public class Formatting : IComparable
  12. {
  13. private XElement rPr;
  14. private bool hidden;
  15. private bool bold;
  16. private bool italic;
  17. private StrikeThrough strikethrough;
  18. private Script script;
  19. private Highlight highlight;
  20. private double? size;
  21. private Color? fontColor;
  22. private Color? underlineColor;
  23. private UnderlineStyle underlineStyle;
  24. private Misc misc;
  25. private CapsStyle capsStyle;
  26. private FontFamily fontFamily;
  27. private int? percentageScale;
  28. private int? kerning;
  29. private int? position;
  30. private double? spacing;
  31. private CultureInfo language;
  32. /// <summary>
  33. /// A text formatting.
  34. /// </summary>
  35. public Formatting()
  36. {
  37. capsStyle = CapsStyle.none;
  38. strikethrough = StrikeThrough.none;
  39. script = Script.none;
  40. highlight = Highlight.none;
  41. underlineStyle = UnderlineStyle.none;
  42. misc = Misc.none;
  43. // Use current culture by default
  44. language = CultureInfo.CurrentCulture;
  45. rPr = new XElement(XName.Get("rPr", DocX.w.NamespaceName));
  46. }
  47. /// <summary>
  48. /// Text language
  49. /// </summary>
  50. public CultureInfo Language
  51. {
  52. get
  53. {
  54. return language;
  55. }
  56. set
  57. {
  58. language = value;
  59. }
  60. }
  61. public static Formatting Parse(XElement rPr)
  62. {
  63. Formatting formatting = new Formatting();
  64. // Build up the Formatting object.
  65. foreach (XElement option in rPr.Elements())
  66. {
  67. switch (option.Name.LocalName)
  68. {
  69. case "lang":
  70. formatting.Language = new CultureInfo(
  71. option.GetAttribute(XName.Get("val", DocX.w.NamespaceName), null) ??
  72. option.GetAttribute(XName.Get("eastAsia", DocX.w.NamespaceName), null) ??
  73. option.GetAttribute(XName.Get("bidi", DocX.w.NamespaceName)));
  74. break;
  75. case "spacing":
  76. formatting.Spacing = Double.Parse(
  77. option.GetAttribute(XName.Get("val", DocX.w.NamespaceName))) / 20.0;
  78. break;
  79. case "position":
  80. formatting.Position = Int32.Parse(
  81. option.GetAttribute(XName.Get("val", DocX.w.NamespaceName))) / 2;
  82. break;
  83. case "kern":
  84. formatting.Position = Int32.Parse(
  85. option.GetAttribute(XName.Get("val", DocX.w.NamespaceName))) / 2;
  86. break;
  87. case "w":
  88. formatting.PercentageScale = Int32.Parse(
  89. option.GetAttribute(XName.Get("val", DocX.w.NamespaceName)));
  90. break;
  91. // <w:sz w:val="20"/><w:szCs w:val="20"/>
  92. case "sz":
  93. formatting.Size = Int32.Parse(
  94. option.GetAttribute(XName.Get("val", DocX.w.NamespaceName))) / 2;
  95. break;
  96. case "rFonts":
  97. formatting.FontFamily =
  98. new FontFamily(
  99. option.GetAttribute(XName.Get("cs", DocX.w.NamespaceName), null) ??
  100. option.GetAttribute(XName.Get("ascii", DocX.w.NamespaceName), null) ??
  101. option.GetAttribute(XName.Get("hAnsi", DocX.w.NamespaceName), null) ??
  102. option.GetAttribute(XName.Get("eastAsia", DocX.w.NamespaceName)));
  103. break;
  104. case "color" :
  105. try
  106. {
  107. string color = option.GetAttribute(XName.Get("val", DocX.w.NamespaceName));
  108. formatting.FontColor = System.Drawing.ColorTranslator.FromHtml(string.Format("#{0}", color));
  109. }
  110. catch { }
  111. break;
  112. case "vanish": formatting.hidden = true; break;
  113. case "b": formatting.Bold = true; break;
  114. case "i": formatting.Italic = true; break;
  115. case "u": formatting.UnderlineStyle = HelperFunctions.GetUnderlineStyle(option.GetAttribute(XName.Get("val", DocX.w.NamespaceName)));
  116. break;
  117. default: break;
  118. }
  119. }
  120. return formatting;
  121. }
  122. internal XElement Xml
  123. {
  124. get
  125. {
  126. rPr = new XElement(XName.Get("rPr", DocX.w.NamespaceName));
  127. if (language != null)
  128. rPr.Add(new XElement(XName.Get("lang", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), language.Name)));
  129. if(spacing.HasValue)
  130. rPr.Add(new XElement(XName.Get("spacing", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), spacing.Value * 20)));
  131. if(position.HasValue)
  132. rPr.Add(new XElement(XName.Get("position", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), position.Value * 2)));
  133. if (kerning.HasValue)
  134. rPr.Add(new XElement(XName.Get("kern", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), kerning.Value * 2)));
  135. if (percentageScale.HasValue)
  136. rPr.Add(new XElement(XName.Get("w", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), percentageScale)));
  137. if (fontFamily != null)
  138. {
  139. rPr.Add
  140. (
  141. new XElement
  142. (
  143. XName.Get("rFonts", DocX.w.NamespaceName),
  144. new XAttribute(XName.Get("ascii", DocX.w.NamespaceName), fontFamily.Name),
  145. new XAttribute(XName.Get("hAnsi", DocX.w.NamespaceName), fontFamily.Name), // Added by Maurits Elbers to support non-standard characters. See http://docx.codeplex.com/Thread/View.aspx?ThreadId=70097&ANCHOR#Post453865
  146. new XAttribute(XName.Get("cs", DocX.w.NamespaceName), fontFamily.Name) // Added by Maurits Elbers to support non-standard characters. See http://docx.codeplex.com/Thread/View.aspx?ThreadId=70097&ANCHOR#Post453865
  147. )
  148. );
  149. }
  150. if(hidden)
  151. rPr.Add(new XElement(XName.Get("vanish", DocX.w.NamespaceName)));
  152. if (bold)
  153. rPr.Add(new XElement(XName.Get("b", DocX.w.NamespaceName)));
  154. if (italic)
  155. rPr.Add(new XElement(XName.Get("i", DocX.w.NamespaceName)));
  156. switch (underlineStyle)
  157. {
  158. case UnderlineStyle.none:
  159. break;
  160. case UnderlineStyle.singleLine:
  161. rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), "single")));
  162. break;
  163. case UnderlineStyle.doubleLine:
  164. rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), "double")));
  165. break;
  166. default:
  167. rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), underlineStyle.ToString())));
  168. break;
  169. }
  170. if(underlineColor.HasValue)
  171. {
  172. // If an underlineColor has been set but no underlineStyle has been set
  173. if (underlineStyle == UnderlineStyle.none)
  174. {
  175. // Set the underlineStyle to the default
  176. underlineStyle = UnderlineStyle.singleLine;
  177. rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), "single")));
  178. }
  179. rPr.Element(XName.Get("u", DocX.w.NamespaceName)).Add(new XAttribute(XName.Get("color", DocX.w.NamespaceName), underlineColor.Value.ToHex()));
  180. }
  181. switch (strikethrough)
  182. {
  183. case StrikeThrough.none:
  184. break;
  185. case StrikeThrough.strike:
  186. rPr.Add(new XElement(XName.Get("strike", DocX.w.NamespaceName)));
  187. break;
  188. case StrikeThrough.doubleStrike:
  189. rPr.Add(new XElement(XName.Get("dstrike", DocX.w.NamespaceName)));
  190. break;
  191. default:
  192. break;
  193. }
  194. switch (script)
  195. {
  196. case Script.none:
  197. break;
  198. default:
  199. rPr.Add(new XElement(XName.Get("vertAlign", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), script.ToString())));
  200. break;
  201. }
  202. if (size.HasValue)
  203. {
  204. rPr.Add(new XElement(XName.Get("sz", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), (size * 2).ToString())));
  205. rPr.Add(new XElement(XName.Get("szCs", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), (size * 2).ToString())));
  206. }
  207. if(fontColor.HasValue)
  208. rPr.Add(new XElement(XName.Get("color", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), fontColor.Value.ToHex())));
  209. switch (highlight)
  210. {
  211. case Highlight.none:
  212. break;
  213. default:
  214. rPr.Add(new XElement(XName.Get("highlight", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), highlight.ToString())));
  215. break;
  216. }
  217. switch (capsStyle)
  218. {
  219. case CapsStyle.none:
  220. break;
  221. default:
  222. rPr.Add(new XElement(XName.Get(capsStyle.ToString(), DocX.w.NamespaceName)));
  223. break;
  224. }
  225. switch (misc)
  226. {
  227. case Misc.none:
  228. break;
  229. case Misc.outlineShadow:
  230. rPr.Add(new XElement(XName.Get("outline", DocX.w.NamespaceName)));
  231. rPr.Add(new XElement(XName.Get("shadow", DocX.w.NamespaceName)));
  232. break;
  233. case Misc.engrave:
  234. rPr.Add(new XElement(XName.Get("imprint", DocX.w.NamespaceName)));
  235. break;
  236. default:
  237. rPr.Add(new XElement(XName.Get(misc.ToString(), DocX.w.NamespaceName)));
  238. break;
  239. }
  240. return rPr;
  241. }
  242. }
  243. /// <summary>
  244. /// This formatting will apply Bold.
  245. /// </summary>
  246. public bool Bold { get { return bold; } set { bold = value;} }
  247. /// <summary>
  248. /// This formatting will apply Italic.
  249. /// </summary>
  250. public bool Italic { get { return italic; } set { italic = value; } }
  251. /// <summary>
  252. /// This formatting will apply StrickThrough.
  253. /// </summary>
  254. public StrikeThrough StrikeThrough { get { return strikethrough; } set { strikethrough = value; } }
  255. /// <summary>
  256. /// The script that this formatting should be, normal, superscript or subscript.
  257. /// </summary>
  258. public Script Script { get { return script; } set { script = value; } }
  259. /// <summary>
  260. /// The Size of this text, must be between 0 and 1638.
  261. /// </summary>
  262. public double? Size
  263. {
  264. get { return size; }
  265. set
  266. {
  267. double? temp = value * 2;
  268. if (temp - (int)temp == 0)
  269. {
  270. if(value > 0 && value < 1639)
  271. size = value;
  272. else
  273. throw new ArgumentException("Size", "Value must be in the range 0 - 1638");
  274. }
  275. else
  276. throw new ArgumentException("Size", "Value must be either a whole or half number, examples: 32, 32.5");
  277. }
  278. }
  279. /// <summary>
  280. /// Percentage scale must be one of the following values 200, 150, 100, 90, 80, 66, 50 or 33.
  281. /// </summary>
  282. public int? PercentageScale
  283. {
  284. get { return percentageScale; }
  285. set
  286. {
  287. if ((new int?[] { 200, 150, 100, 90, 80, 66, 50, 33 }).Contains(value))
  288. percentageScale = value;
  289. else
  290. throw new ArgumentOutOfRangeException("PercentageScale", "Value must be one of the following: 200, 150, 100, 90, 80, 66, 50 or 33");
  291. }
  292. }
  293. /// <summary>
  294. /// The Kerning to apply to this text must be one of the following values 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72.
  295. /// </summary>
  296. public int? Kerning
  297. {
  298. get { return kerning; }
  299. set
  300. {
  301. if(new int?[] {8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72}.Contains(value))
  302. kerning = value;
  303. else
  304. throw new ArgumentOutOfRangeException("Kerning", "Value must be one of the following: 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48 or 72");
  305. }
  306. }
  307. /// <summary>
  308. /// Text position must be in the range (-1585 - 1585).
  309. /// </summary>
  310. public int? Position
  311. {
  312. get { return position; }
  313. set
  314. {
  315. if (value > -1585 && value < 1585)
  316. position = value;
  317. else
  318. throw new ArgumentOutOfRangeException("Position", "Value must be in the range -1585 - 1585");
  319. }
  320. }
  321. /// <summary>
  322. /// Text spacing must be in the range (-1585 - 1585).
  323. /// </summary>
  324. public double? Spacing
  325. {
  326. get { return spacing; }
  327. set
  328. {
  329. double? temp = value * 20;
  330. if (temp - (int)temp == 0)
  331. {
  332. if (value > -1585 && value < 1585)
  333. spacing = value;
  334. else
  335. throw new ArgumentException("Spacing", "Value must be in the range: -1584 - 1584");
  336. }
  337. else
  338. throw new ArgumentException("Spacing", "Value must be either a whole or acurate to one decimal, examples: 32, 32.1, 32.2, 32.9");
  339. }
  340. }
  341. /// <summary>
  342. /// The colour of the text.
  343. /// </summary>
  344. public Color? FontColor { get { return fontColor; } set { fontColor = value; } }
  345. /// <summary>
  346. /// Highlight colour.
  347. /// </summary>
  348. public Highlight Highlight { get { return highlight; } set { highlight = value; } }
  349. /// <summary>
  350. /// The Underline style that this formatting applies.
  351. /// </summary>
  352. public UnderlineStyle UnderlineStyle { get { return underlineStyle; } set { underlineStyle = value; } }
  353. /// <summary>
  354. /// The underline colour.
  355. /// </summary>
  356. public Color? UnderlineColor { get { return underlineColor; } set { underlineColor = value; } }
  357. /// <summary>
  358. /// Misc settings.
  359. /// </summary>
  360. public Misc Misc { get { return misc; } set { misc = value; } }
  361. /// <summary>
  362. /// Is this text hidden or visible.
  363. /// </summary>
  364. public bool Hidden { get { return hidden; } set { hidden = value; } }
  365. /// <summary>
  366. /// Capitalization style.
  367. /// </summary>
  368. public CapsStyle CapsStyle { get { return capsStyle; } set { capsStyle = value; } }
  369. /// <summary>
  370. /// The font familt of this formatting.
  371. /// </summary>
  372. /// <!--
  373. /// Bug found and fixed by krugs525 on August 12 2009.
  374. /// Use TFS compare to see exact code change.
  375. /// -->
  376. public FontFamily FontFamily { get { return fontFamily; } set { fontFamily = value; } }
  377. public int CompareTo(object obj)
  378. {
  379. Formatting other = (Formatting)obj;
  380. if(other.hidden != this.hidden)
  381. return -1;
  382. if(other.bold != this.bold)
  383. return -1;
  384. if(other.italic != this.italic)
  385. return -1;
  386. if(other.strikethrough != this.strikethrough)
  387. return -1;
  388. if(other.script != this.script)
  389. return -1;
  390. if(other.highlight != this.highlight)
  391. return -1;
  392. if(other.size != this.size)
  393. return -1;
  394. if(other.fontColor != this.fontColor)
  395. return -1;
  396. if(other.underlineColor != this.underlineColor)
  397. return -1;
  398. if(other.underlineStyle != this.underlineStyle)
  399. return -1;
  400. if(other.misc != this.misc)
  401. return -1;
  402. if(other.capsStyle != this.capsStyle)
  403. return -1;
  404. if(other.fontFamily != this.fontFamily)
  405. return -1;
  406. if(other.percentageScale != this.percentageScale)
  407. return -1;
  408. if(other.kerning != this.kerning)
  409. return -1;
  410. if(other.position != this.position)
  411. return -1;
  412. if(other.spacing != this.spacing)
  413. return -1;
  414. if (!other.language.Equals(this.language))
  415. return -1;
  416. return 0;
  417. }
  418. }
  419. }