TextExamples.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. using System;
  2. using System.Linq;
  3. using System.Text;
  4. using NUnit.Framework;
  5. using QuestPDF.Elements.Text;
  6. using QuestPDF.Examples.Engine;
  7. using QuestPDF.Fluent;
  8. using QuestPDF.Helpers;
  9. using QuestPDF.Infrastructure;
  10. namespace QuestPDF.Examples
  11. {
  12. public class TextExamples
  13. {
  14. [Test]
  15. public void SimpleText()
  16. {
  17. RenderingTest
  18. .Create()
  19. .PageSize(500, 100)
  20. .ProduceImages()
  21. .ShowResults()
  22. .Render(container =>
  23. {
  24. container
  25. .Padding(5)
  26. .MinimalBox()
  27. .Border(1)
  28. .Padding(10)
  29. .Text(Placeholders.Paragraph());
  30. });
  31. }
  32. [Test]
  33. public void SimpleTextBlock()
  34. {
  35. RenderingTest
  36. .Create()
  37. .PageSize(600, 300)
  38. .ProduceImages()
  39. .ShowResults()
  40. .Render(container =>
  41. {
  42. container
  43. .Padding(5)
  44. .MinimalBox()
  45. .Border(1)
  46. .MaxWidth(300)
  47. .Padding(10)
  48. .Text(text =>
  49. {
  50. text.DefaultTextStyle(TextStyle.Default.FontSize(20));
  51. text.Span("This is a normal text, followed by an ");
  52. text.Span("underlined red text").FontColor(Colors.Red.Medium).Underline();
  53. text.Span(".");
  54. });
  55. });
  56. }
  57. [Test]
  58. public void TextWeight()
  59. {
  60. RenderingTest
  61. .Create()
  62. .PageSize(500, 500)
  63. .ProduceImages()
  64. .ShowResults()
  65. .Render(container =>
  66. {
  67. container
  68. .Padding(20)
  69. .MinimalBox()
  70. .Border(1)
  71. .Padding(20)
  72. .Text(text =>
  73. {
  74. text.DefaultTextStyle(x => x.FontFamily(Fonts.Calibri).FontSize(20));
  75. text.Line("Thin").Thin();
  76. text.Line("ExtraLight").ExtraLight();
  77. text.Line("Light").Light();
  78. text.Line("NormalWeight").NormalWeight();
  79. text.Line("Medium").Medium();
  80. text.Line("SemiBold").SemiBold();
  81. text.Line("Bold").Bold();
  82. text.Line("ExtraBold").ExtraBold();
  83. text.Line("Black").Black();
  84. text.Line("ExtraBlack").ExtraBlack();
  85. });
  86. });
  87. }
  88. [Test]
  89. public void LineHeight()
  90. {
  91. RenderingTest
  92. .Create()
  93. .PageSize(500, 700)
  94. .ProduceImages()
  95. .ShowResults()
  96. .Render(container =>
  97. {
  98. container
  99. .Padding(20)
  100. .Column(column =>
  101. {
  102. var lineHeights = new[] { 0.8f, 1f, 1.5f };
  103. var paragraph = Placeholders.Paragraph();
  104. foreach (var lineHeight in lineHeights)
  105. {
  106. column
  107. .Item()
  108. .Border(1)
  109. .Padding(10)
  110. .Text(paragraph)
  111. .FontSize(16)
  112. .LineHeight(lineHeight);
  113. }
  114. });
  115. });
  116. }
  117. [Test]
  118. public void SuperscriptSubscript_Simple()
  119. {
  120. RenderingTest
  121. .Create()
  122. .PageSize(500, 500)
  123. .ProduceImages()
  124. .ShowResults()
  125. .Render(container =>
  126. {
  127. container
  128. .Padding(20)
  129. .MinimalBox()
  130. .Border(1)
  131. .Padding(20)
  132. .Text(text =>
  133. {
  134. text.DefaultTextStyle(x => x.FontSize(20));
  135. text.ParagraphSpacing(10);
  136. var highlight = TextStyle.Default.BackgroundColor(Colors.Green.Lighten3);
  137. text.Span("E=mc").Style(highlight);
  138. text.Span("2").Superscript().Style(highlight);
  139. text.Span(" is the equation of mass–energy equivalence.");
  140. text.EmptyLine();
  141. text.Span("H").Style(highlight);
  142. text.Span("2").Subscript().Style(highlight);
  143. text.Span("O").Style(highlight);
  144. text.Span(" is the chemical formula for water.");
  145. });
  146. });
  147. }
  148. [Test]
  149. public void SuperscriptSubscript_Effects()
  150. {
  151. RenderingTest
  152. .Create()
  153. .PageSize(800, 400)
  154. .ProduceImages()
  155. .ShowResults()
  156. .Render(container =>
  157. {
  158. container
  159. .Padding(25)
  160. .DefaultTextStyle(x => x.FontSize(30))
  161. .Column(column =>
  162. {
  163. column.Spacing(25);
  164. column.Item().Text(text =>
  165. {
  166. text.DefaultTextStyle(x => x.Underline());
  167. text.Span("Underline of the superscript (E = mc");
  168. text.Span("2").Superscript();
  169. text.Span(") should be at the same height as for normal text.");
  170. });
  171. column.Item().Text(text =>
  172. {
  173. text.DefaultTextStyle(x => x.Underline());
  174. text.Span("Underline of the subscript(H");
  175. text.Span("2").Subscript();
  176. text.Span("O) should be slightly lower than a normal text.");
  177. });
  178. column.Item().Text(text =>
  179. {
  180. text.DefaultTextStyle(x => x.Strikethrough());
  181. text.Span("Strikethrough of both superscript (E=mc");
  182. text.Span("2").Superscript();
  183. text.Span(") and subscript(H");
  184. text.Span("2").Subscript();
  185. text.Span("O) should be visible in the middle of the text.");
  186. });
  187. });
  188. });
  189. }
  190. [Test]
  191. public void ParagraphSpacing()
  192. {
  193. RenderingTest
  194. .Create()
  195. .PageSize(500, 500)
  196. .ProduceImages()
  197. .ShowResults()
  198. .Render(container =>
  199. {
  200. container
  201. .Padding(5)
  202. .MinimalBox()
  203. .Border(1)
  204. .Padding(10)
  205. .Text(text =>
  206. {
  207. text.Line(Placeholders.Paragraph());
  208. });
  209. });
  210. }
  211. [Test]
  212. public void CustomElement()
  213. {
  214. RenderingTest
  215. .Create()
  216. .PageSize(500, 200)
  217. .ProduceImages()
  218. .ShowResults()
  219. .Render(container =>
  220. {
  221. container
  222. .Padding(5)
  223. .MinimalBox()
  224. .Border(1)
  225. .Padding(10)
  226. .Text(text =>
  227. {
  228. text.DefaultTextStyle(TextStyle.Default.FontSize(20));
  229. text.Span("This is a random image aligned to the baseline: ");
  230. text.Element()
  231. .PaddingBottom(-6)
  232. .Height(24)
  233. .Width(48)
  234. .Image(Placeholders.Image);
  235. text.Span(".");
  236. });
  237. });
  238. }
  239. [Test]
  240. public void TextElements()
  241. {
  242. RenderingTest
  243. .Create()
  244. .PageSize(PageSizes.A4)
  245. .ProducePdf()
  246. .ShowResults()
  247. .Render(container =>
  248. {
  249. container
  250. .Padding(20)
  251. .Padding(10)
  252. .MinimalBox()
  253. .Border(1)
  254. .Padding(5)
  255. .Padding(10)
  256. .Text(text =>
  257. {
  258. text.DefaultTextStyle(TextStyle.Default);
  259. text.AlignLeft();
  260. text.ParagraphSpacing(10);
  261. text.Line(Placeholders.LoremIpsum());
  262. text.Span($"This is target text that should show up. {DateTime.UtcNow:T} > This is a short sentence that will be wrapped into second line hopefully, right? <").Underline();
  263. });
  264. });
  265. }
  266. [Test]
  267. public void Textcolumn()
  268. {
  269. RenderingTest
  270. .Create()
  271. .PageSize(PageSizes.A4)
  272. .ProducePdf()
  273. .ShowResults()
  274. .Render(container =>
  275. {
  276. container
  277. .Padding(20)
  278. .Padding(10)
  279. .MinimalBox()
  280. .Border(1)
  281. .Padding(5)
  282. .Padding(10)
  283. .Text(text =>
  284. {
  285. text.DefaultTextStyle(TextStyle.Default);
  286. text.AlignLeft();
  287. text.ParagraphSpacing(10);
  288. foreach (var i in Enumerable.Range(1, 100))
  289. text.Line($"{i}: {Placeholders.Paragraph()}");
  290. });
  291. });
  292. }
  293. [Test]
  294. public void SpaceIssue()
  295. {
  296. RenderingTest
  297. .Create()
  298. .PageSize(PageSizes.A4)
  299. .ProducePdf()
  300. .ShowResults()
  301. .Render(container =>
  302. {
  303. container
  304. .Padding(20)
  305. .Padding(10)
  306. .MinimalBox()
  307. .Border(1)
  308. .Padding(5)
  309. .Padding(10)
  310. .Text(text =>
  311. {
  312. text.DefaultTextStyle(x => x.Bold());
  313. text.DefaultTextStyle(TextStyle.Default);
  314. text.AlignLeft();
  315. text.ParagraphSpacing(10);
  316. text.Span(Placeholders.LoremIpsum());
  317. text.EmptyLine();
  318. text.Span("This text is a normal text, ");
  319. text.Span("this is a bold text, ").Bold();
  320. text.Span("this is a red and underlined text, ").FontColor(Colors.Red.Medium).Underline();
  321. text.Span("and this is slightly bigger text.").FontSize(16);
  322. text.EmptyLine();
  323. text.Span("The new text element also supports injecting custom content between words: ");
  324. text.Element().PaddingBottom(-4).Height(16).Width(32).Image(Placeholders.Image);
  325. text.Span(".");
  326. text.EmptyLine();
  327. text.Span("This is page number ");
  328. text.CurrentPageNumber();
  329. text.Span(" out of ");
  330. text.TotalPages();
  331. text.EmptyLine();
  332. text.Hyperlink("Please visit QuestPDF website", "https://www.questpdf.com");
  333. text.EmptyLine();
  334. text.Span(Placeholders.Paragraphs());
  335. text.EmptyLine();
  336. text.Span(Placeholders.Paragraphs()).Italic();
  337. text.Line("This is target text that does not show up. " + Placeholders.Paragraph());
  338. });
  339. });
  340. }
  341. [Test]
  342. public void HugeList()
  343. {
  344. RenderingTest
  345. .Create()
  346. .PageSize(PageSizes.A4)
  347. .ProducePdf()
  348. .ShowResults()
  349. .Render(container =>
  350. {
  351. container
  352. .Padding(20)
  353. .Padding(10)
  354. .MinimalBox()
  355. .Border(1)
  356. .Padding(5)
  357. .Padding(10)
  358. .Text(text =>
  359. {
  360. text.DefaultTextStyle(TextStyle.Default.FontSize(20).BackgroundColor(Colors.Red.Lighten4));
  361. text.AlignLeft();
  362. text.ParagraphSpacing(10);
  363. text.Span("This text is a normal text, ");
  364. text.Span("this is a bold text, ").Bold();
  365. text.Span("this is a red and underlined text, ").FontColor(Colors.Red.Medium).Underline();
  366. text.Span("and this is slightly bigger text.").FontSize(16);
  367. text.Span("The new text element also supports injecting custom content between words: ");
  368. text.Element().PaddingBottom(-4).Height(16).Width(32).Image(Placeholders.Image);
  369. text.Span(".");
  370. text.EmptyLine();
  371. foreach (var i in Enumerable.Range(1, 100))
  372. {
  373. text.Line($"{i}: {Placeholders.Paragraph()}");
  374. text.Hyperlink("Please visit QuestPDF website. ", "https://www.questpdf.com");
  375. text.Span("This is page number ");
  376. text.CurrentPageNumber();
  377. text.Span(" out of ");
  378. text.TotalPages();
  379. text.EmptyLine();
  380. }
  381. });
  382. });
  383. }
  384. [Test]
  385. public void MeasureIssueWhenSpaceAtLineEnd()
  386. {
  387. // issue 135
  388. RenderingTest
  389. .Create()
  390. .ProduceImages()
  391. .ShowResults()
  392. .RenderDocument(container =>
  393. {
  394. container.Page(page =>
  395. {
  396. page.Margin(50);
  397. page.PageColor(Colors.White);
  398. page.Size(PageSizes.A4);
  399. page.Content().Text("This is a specially crafted sentence with a specially chosen length for demonstration of the bug that occurs ;;;;;. ").FontSize(11).BackgroundColor(Colors.Red.Lighten3);
  400. });
  401. });
  402. }
  403. [Test]
  404. public void EmptyText()
  405. {
  406. // issue 135
  407. RenderingTest
  408. .Create()
  409. .ProduceImages()
  410. .ShowResults()
  411. .RenderDocument(container =>
  412. {
  413. container.Page(page =>
  414. {
  415. page.Margin(50);
  416. page.PageColor(Colors.White);
  417. page.Size(PageSizes.A4);
  418. page.Content().Text(" ").FontSize(11).BackgroundColor(Colors.Red.Lighten3);
  419. });
  420. });
  421. }
  422. [Test]
  423. public void Whitespaces()
  424. {
  425. // issue 135
  426. RenderingTest
  427. .Create()
  428. .ProduceImages()
  429. .ShowResults()
  430. .RenderDocument(container =>
  431. {
  432. container.Page(page =>
  433. {
  434. page.Margin(50);
  435. page.PageColor(Colors.White);
  436. page.Size(PageSizes.A4);
  437. page.Content().Text(" x ").FontSize(11).BackgroundColor(Colors.Red.Lighten3);
  438. });
  439. });
  440. }
  441. [Test]
  442. public void DrawingNullTextShouldNotThrowException()
  443. {
  444. RenderingTest
  445. .Create()
  446. .ProduceImages()
  447. .ShowResults()
  448. .RenderDocument(container =>
  449. {
  450. container.Page(page =>
  451. {
  452. page.Margin(50);
  453. page.PageColor(Colors.White);
  454. page.Size(PageSizes.A4);
  455. page.Content().Column(column =>
  456. {
  457. column.Item().Text(null);
  458. column.Item().Text(text =>
  459. {
  460. text.Span(null);
  461. text.Line(null);
  462. text.Hyperlink(null, "http://www.questpdf.com");
  463. text.TotalPages().Format(x => null);
  464. });
  465. });
  466. });
  467. });
  468. }
  469. [Test]
  470. public void BreakingLongWord()
  471. {
  472. RenderingTest
  473. .Create()
  474. .ProduceImages()
  475. .ShowResults()
  476. .RenderDocument(container =>
  477. {
  478. container.Page(page =>
  479. {
  480. page.Margin(50);
  481. page.PageColor(Colors.White);
  482. page.Size(PageSizes.A4);
  483. page.Content().Column(column =>
  484. {
  485. column.Item().Text(null);
  486. column.Item().Text(text =>
  487. {
  488. text.DefaultTextStyle(x => x.BackgroundColor(Colors.Red.Lighten3).FontSize(24));
  489. text.Span(" " + Placeholders.LoremIpsum());
  490. text.Span(" 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 ").WrapAnywhere();
  491. });
  492. });
  493. });
  494. });
  495. }
  496. [Test]
  497. public void TextShaping_Unicode()
  498. {
  499. RenderingTest
  500. .Create()
  501. .PageSize(600, 100)
  502. .ProduceImages()
  503. .ShowResults()
  504. .Render(container =>
  505. {
  506. container
  507. .Padding(35)
  508. .MinimalBox()
  509. .Background(Colors.Grey.Lighten2)
  510. .Text(text =>
  511. {
  512. text.DefaultTextStyle(TextStyle.Default.FontSize(20));
  513. text.Span("Complex Unicode structure: ");
  514. text.Span("T̶̖̔͆͆̽̔ḩ̷̼̫̐̈́̀͜͝͝ì̶͇̤͓̱̣͇͓͉̎s̵̡̟̹͍̜͉̗̾͛̈̐́͋͂͝͠ͅ ̴̨͙͍͇̭̒͗̀́͝ì̷̡̺͉̼̏̏̉̌͝s̷͍͙̗̰̖͙̈̑̂̔͑͊̌̓̊̇͜ ̶̛̼͚͊̅͘ṭ̷̨̘̣̙̖͉͌̏̂̅͑̄̽̕͝ȅ̶̲̲̙̭͈̬̣͔̝͔̈́͝s̸̢̯̪̫͓̭̮̓̀͆͜ț̸̢͉̞̥̤̏̌̓͝").FontFamily(Fonts.Calibri).FontColor(Colors.Red.Medium);
  515. text.Span(".");
  516. });
  517. });
  518. }
  519. [Test]
  520. public void TextShaping_Arabic()
  521. {
  522. RenderingTest
  523. .Create()
  524. .PageSize(500, 100)
  525. .ProduceImages()
  526. .ShowResults()
  527. .Render(container =>
  528. {
  529. container
  530. .Padding(25)
  531. .MinimalBox()
  532. .Background(Colors.Grey.Lighten2)
  533. .Text("ينا الألم. في بعض الأحيان ونظراً للالتزامات التي يفرضها علينا")
  534. .FontFamily(Fonts.Calibri)
  535. .FontSize(20);
  536. });
  537. }
  538. [Test]
  539. public void FontFallback()
  540. {
  541. RenderingTest
  542. .Create()
  543. .ProduceImages()
  544. .ShowResults()
  545. .RenderDocument(container =>
  546. {
  547. container.Page(page =>
  548. {
  549. page.Margin(50);
  550. page.PageColor(Colors.White);
  551. page.DefaultTextStyle(x => x
  552. .Fallback(y => y.FontFamily("Segoe UI Emoji")
  553. .Fallback(y => y.FontFamily("Microsoft YaHei"))));
  554. page.Size(PageSizes.A4);
  555. page.Content().Text(t =>
  556. {
  557. t.Line("This is normal text.");
  558. t.EmptyLine();
  559. t.Line("Following line should use font fallback:");
  560. t.Line("中文文本");
  561. t.EmptyLine();
  562. t.Line("The following line contains a mix of known and unknown characters.");
  563. t.Line("Mixed line: This 中文 is 文文 a mixed 本 本 line 本 中文文本!");
  564. t.EmptyLine();
  565. t.Line("Emojis work out of the box because of font fallback: 😊😅🥳👍❤😍👌");
  566. });
  567. });
  568. });
  569. }
  570. [Test]
  571. public void WordWrappingStability()
  572. {
  573. // instruction: check if any characters repeat when performing the word-wrapping algorithm
  574. RenderingTest
  575. .Create()
  576. .PageSize(PageSizes.A4)
  577. .ProducePdf()
  578. .ShowResults()
  579. .Render(container =>
  580. {
  581. var text = "Lorem ipsum dolor sit amet consectetuer";
  582. container
  583. .Padding(20)
  584. .Column(column =>
  585. {
  586. column.Spacing(10);
  587. foreach (var width in Enumerable.Range(25, 200))
  588. {
  589. column
  590. .Item()
  591. .MaxWidth(width)
  592. .Background(Colors.Grey.Lighten3)
  593. .Text(text);
  594. }
  595. });
  596. });
  597. }
  598. }
  599. }