TextObject.cs 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770
  1. using System;
  2. using System.Text;
  3. using System.Collections.Generic;
  4. using System.Drawing;
  5. using System.Drawing.Text;
  6. using System.Drawing.Drawing2D;
  7. using System.ComponentModel;
  8. using FastReport.Utils;
  9. using FastReport.Format;
  10. using FastReport.Code;
  11. using System.Windows.Forms;
  12. using System.Drawing.Design;
  13. namespace FastReport
  14. {
  15. /// <summary>
  16. /// Specifies the horizontal alignment of a text in the TextObject object.
  17. /// </summary>
  18. public enum HorzAlign
  19. {
  20. /// <summary>
  21. /// Specifies that text is aligned in the left of the layout rectangle.
  22. /// </summary>
  23. Left,
  24. /// <summary>
  25. /// Specifies that text is aligned in the center of the layout rectangle.
  26. /// </summary>
  27. Center,
  28. /// <summary>
  29. /// Specifies that text is aligned in the right of the layout rectangle.
  30. /// </summary>
  31. Right,
  32. /// <summary>
  33. /// Specifies that text is aligned in the left and right sides of the layout rectangle.
  34. /// </summary>
  35. Justify
  36. }
  37. /// <summary>
  38. /// Specifies the vertical alignment of a text in the TextObject object.
  39. /// </summary>
  40. public enum VertAlign
  41. {
  42. /// <summary>
  43. /// Specifies that text is aligned in the top of the layout rectangle.
  44. /// </summary>
  45. Top,
  46. /// <summary>
  47. /// Specifies that text is aligned in the center of the layout rectangle.
  48. /// </summary>
  49. Center,
  50. /// <summary>
  51. /// Specifies that text is aligned in the bottom of the layout rectangle.
  52. /// </summary>
  53. Bottom
  54. }
  55. /// <summary>
  56. /// The type of text renderer
  57. /// </summary>
  58. public enum TextRenderType
  59. {
  60. /// <summary>
  61. /// The default render
  62. /// </summary>
  63. Default,
  64. /// <summary>
  65. /// Render with some html tags and stable logic
  66. /// </summary>
  67. HtmlTags,
  68. /// <summary>
  69. /// Render with img tags, span etc. Experimental and unstable logic
  70. /// </summary>
  71. HtmlParagraph,
  72. /// <summary>
  73. /// Renders a text in a simplest way. For internal use only.
  74. /// </summary>
  75. Inline
  76. }
  77. /// <summary>
  78. /// The format of paragraph
  79. /// </summary>
  80. [TypeConverter(typeof(TypeConverters.FRExpandableObjectConverter))]
  81. public class ParagraphFormat
  82. {
  83. private float firstLineIndent;
  84. private float lineSpacing;
  85. private LineSpacingType lineSpacingType;
  86. private bool skipFirstLineIndent;
  87. /// <summary>
  88. /// The first line on each paragraph, not effect if value less then 0
  89. /// </summary>
  90. [Browsable(true)]
  91. [DefaultValue(0f)]
  92. [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
  93. public float FirstLineIndent
  94. {
  95. get { return firstLineIndent; }
  96. set { if (value >= 0) firstLineIndent = value; }
  97. }
  98. /// <summary>
  99. /// The distance between lines, not effect if value less then 0
  100. /// </summary>
  101. [Browsable(true)]
  102. [DefaultValue(0f)]
  103. [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
  104. public float LineSpacing
  105. {
  106. get { return lineSpacing; }
  107. set { if (value >= 0) lineSpacing = value; }
  108. }
  109. /// <summary>
  110. /// The spacing type for distance between line calculation
  111. /// </summary>
  112. [Browsable(true)]
  113. [DefaultValue(LineSpacingType.Single)]
  114. public LineSpacingType LineSpacingType
  115. {
  116. get { return lineSpacingType; }
  117. set { lineSpacingType = value; }
  118. }
  119. /// <summary>
  120. /// The value for a multiplication line height for adding spacing
  121. /// </summary>
  122. [Browsable(true)]
  123. [DefaultValue(0f)]
  124. public float LineSpacingMultiple
  125. {
  126. get { return lineSpacing / 100f; }
  127. set { if (value >= 0) lineSpacing = value * 100f; }
  128. }
  129. /// <summary>
  130. /// Skip the line indent in the first paragraph, for broken paragraphs
  131. /// </summary>
  132. [Browsable(false)]
  133. [DefaultValue(false)]
  134. public bool SkipFirstLineIndent
  135. {
  136. get { return skipFirstLineIndent; }
  137. set { skipFirstLineIndent = value; }
  138. }
  139. /// <summary>
  140. /// clone with new scale;
  141. /// </summary>
  142. /// <param name="scale"></param>
  143. /// <returns></returns>
  144. internal ParagraphFormat MultipleScale(float scale)
  145. {
  146. ParagraphFormat clone = new ParagraphFormat();
  147. clone.lineSpacingType = lineSpacingType;
  148. if (LineSpacingType == LineSpacingType.Multiple)
  149. clone.lineSpacing = lineSpacing;
  150. else
  151. clone.lineSpacing = lineSpacing * scale;
  152. clone.firstLineIndent = firstLineIndent * scale;
  153. clone.skipFirstLineIndent = skipFirstLineIndent;
  154. return clone;
  155. }
  156. internal void Assign(ParagraphFormat p)
  157. {
  158. lineSpacingType = p.lineSpacingType;
  159. lineSpacing = p.lineSpacing;
  160. firstLineIndent = p.firstLineIndent;
  161. skipFirstLineIndent = p.skipFirstLineIndent;
  162. }
  163. public override bool Equals(object obj)
  164. {
  165. ParagraphFormat format = obj as ParagraphFormat;
  166. return format != null &&
  167. firstLineIndent == format.firstLineIndent &&
  168. lineSpacing == format.lineSpacing &&
  169. lineSpacingType == format.lineSpacingType &&
  170. skipFirstLineIndent == format.skipFirstLineIndent;
  171. }
  172. public override int GetHashCode()
  173. {
  174. unchecked
  175. {
  176. int hashCode = -1051315095;
  177. hashCode = hashCode * -1521134295 + firstLineIndent.GetHashCode();
  178. hashCode = hashCode * -1521134295 + lineSpacing.GetHashCode();
  179. hashCode = hashCode * -1521134295 + lineSpacingType.GetHashCode();
  180. hashCode = hashCode * -1521134295 + skipFirstLineIndent.GetHashCode();
  181. return hashCode;
  182. }
  183. }
  184. }
  185. /// <summary>
  186. /// The spacing type between lines
  187. /// </summary>
  188. public enum LineSpacingType
  189. {
  190. /// <summary>
  191. /// Single spacing, not effect from LineSpacing
  192. /// </summary>
  193. Single,
  194. /// <summary>
  195. /// Minimal spacing in exactly size
  196. /// </summary>
  197. AtLeast,
  198. /// <summary>
  199. /// The specific distance between the lines, for some exports, does not work if the distance value is too small.
  200. /// </summary>
  201. Exactly,
  202. /// <summary>
  203. /// The calculated distance between lines, for some exports, does not work if the distance value is too small.
  204. /// </summary>
  205. Multiple
  206. }
  207. /// <summary>
  208. /// Specifies the behavior of the <b>AutoShrink</b> feature of <b>TextObject</b>.
  209. /// </summary>
  210. public enum AutoShrinkMode
  211. {
  212. /// <summary>
  213. /// AutoShrink is disabled.
  214. /// </summary>
  215. None,
  216. /// <summary>
  217. /// AutoShrink decreases the <b>Font.Size</b> property of the <b>TextObject</b>.
  218. /// </summary>
  219. FontSize,
  220. /// <summary>
  221. /// AutoShrink decreases the <b>FontWidthRatio</b> property of the <b>TextObject</b>.
  222. /// </summary>
  223. FontWidth
  224. }
  225. /// <summary>
  226. /// Represents the Text object that may display one or several text lines.
  227. /// </summary>
  228. /// <remarks>
  229. /// Specify the object's text in the <see cref="TextObjectBase.Text">Text</see> property.
  230. /// Text may contain expressions and data items, for example: "Today is [Date]". When report
  231. /// is running, all expressions are calculated and replaced with actual values, so the text
  232. /// would be "Today is 01.01.2008".
  233. /// <para/>The symbols used to find expressions in a text are set in the
  234. /// <see cref="TextObjectBase.Brackets">Brackets</see> property. You also may disable expressions
  235. /// using the <see cref="TextObjectBase.AllowExpressions">AllowExpressions</see> property.
  236. /// <para/>To format an expression value, use the <see cref="Format"/> property.
  237. /// </remarks>
  238. public partial class TextObject : TextObjectBase
  239. {
  240. #region Fields
  241. private bool autoWidth;
  242. private HorzAlign horzAlign;
  243. private VertAlign vertAlign;
  244. private int angle;
  245. private bool rightToLeft;
  246. private bool wordWrap;
  247. private bool underlines;
  248. private Font font;
  249. private FillBase textFill;
  250. private TextOutline textOutline;
  251. private StringTrimming trimming;
  252. private float fontWidthRatio;
  253. private float firstTabOffset;
  254. private float tabWidth;
  255. private FloatCollection tabPositions;
  256. private bool clip;
  257. private ConditionCollection highlight;
  258. private bool wysiwyg;
  259. private float lineHeight;
  260. private bool forceJustify;
  261. private TextRenderType textRenderType;
  262. private AutoShrinkMode autoShrink;
  263. private float autoShrinkMinSize;
  264. private float paragraphOffset;
  265. private FillBase savedTextFill;
  266. private Font savedFont;
  267. private string savedText;
  268. private FormatBase savedFormat;
  269. private InlineImageCache inlineImageCache;
  270. private ParagraphFormat paragraphFormat;
  271. private bool preserveLastLineSpace;
  272. #endregion
  273. #region Properties
  274. /// <summary>
  275. /// Gets or sets a paragraph format for a new html rendering type, not for others rendering
  276. /// </summary>
  277. [Category("Appearance")]
  278. public ParagraphFormat ParagraphFormat
  279. {
  280. get { return paragraphFormat; }
  281. set { paragraphFormat = value; }
  282. }
  283. /// <summary>
  284. /// Gets or sets a value that determines if the text object should handle its width automatically.
  285. /// </summary>
  286. [DefaultValue(false)]
  287. [Category("Behavior")]
  288. public bool AutoWidth
  289. {
  290. get { return autoWidth; }
  291. set { autoWidth = value; }
  292. }
  293. /// <summary>
  294. /// Gets or sets a value that indicates whether the font size should shrink to
  295. /// display the longest text line without word wrap.
  296. /// </summary>
  297. /// <remarks>
  298. /// To limit the minimum size, use the <see cref="AutoShrinkMinSize"/> property.
  299. /// </remarks>
  300. [DefaultValue(AutoShrinkMode.None)]
  301. [Category("Behavior")]
  302. public AutoShrinkMode AutoShrink
  303. {
  304. get { return autoShrink; }
  305. set { autoShrink = value; }
  306. }
  307. /// <summary>
  308. /// Gets or sets the minimum size of font (or minimum width ratio) if the <see cref="AutoShrink"/>
  309. /// mode is on.
  310. /// </summary>
  311. /// <remarks>
  312. /// This property determines the minimum font size (in case the <see cref="AutoShrink"/> property is set to
  313. /// <b>FontSize</b>), or the minimum font width ratio (if <b>AutoShrink</b> is set to <b>FontWidth</b>).
  314. /// <para/>The default value is 0, that means no limits.
  315. /// </remarks>
  316. [DefaultValue(0f)]
  317. [Category("Behavior")]
  318. public float AutoShrinkMinSize
  319. {
  320. get { return autoShrinkMinSize; }
  321. set { autoShrinkMinSize = value; }
  322. }
  323. /// <summary>
  324. /// Gets or sets the horizontal alignment of a text in the TextObject object.
  325. /// </summary>
  326. [DefaultValue(HorzAlign.Left)]
  327. [Category("Appearance")]
  328. public HorzAlign HorzAlign
  329. {
  330. get { return horzAlign; }
  331. set { horzAlign = value; }
  332. }
  333. /// <summary>
  334. /// Gets or sets the vertical alignment of a text in the TextObject object.
  335. /// </summary>
  336. [DefaultValue(VertAlign.Top)]
  337. [Category("Appearance")]
  338. public VertAlign VertAlign
  339. {
  340. get { return vertAlign; }
  341. set { vertAlign = value; }
  342. }
  343. /// <summary>
  344. /// Gets or sets the text angle, in degrees.
  345. /// </summary>
  346. [DefaultValue(0)]
  347. [Category("Appearance")]
  348. [Editor("FastReport.TypeEditors.AngleEditor, FastReport", typeof(UITypeEditor))]
  349. public int Angle
  350. {
  351. get { return angle; }
  352. set { angle = value; }
  353. }
  354. /// <summary>
  355. /// Gets or sets a value that indicates whether the component should draw right-to-left for RTL languages.
  356. /// </summary>
  357. [DefaultValue(false)]
  358. [Category("Behavior")]
  359. public bool RightToLeft
  360. {
  361. get { return rightToLeft; }
  362. set { rightToLeft = value; }
  363. }
  364. /// <summary>
  365. /// Gets or sets a value that indicates if lines are automatically word-wrapped.
  366. /// </summary>
  367. [DefaultValue(true)]
  368. [Category("Behavior")]
  369. public bool WordWrap
  370. {
  371. get { return wordWrap; }
  372. set { wordWrap = value; }
  373. }
  374. /// <summary>
  375. /// Gets or sets a value that determines if the text object will underline each text line.
  376. /// </summary>
  377. [DefaultValue(false)]
  378. [Category("Appearance")]
  379. public bool Underlines
  380. {
  381. get { return underlines; }
  382. set { underlines = value; }
  383. }
  384. /// <summary>
  385. /// Gets or sets the font settings for this object.
  386. /// </summary>
  387. [Category("Appearance")]
  388. public Font Font
  389. {
  390. get { return font; }
  391. set
  392. {
  393. font = value;
  394. if (!String.IsNullOrEmpty(Style))
  395. Style = "";
  396. }
  397. }
  398. /// <summary>
  399. /// Gets or sets a collection of TAB symbol positions, in pixels.
  400. /// </summary>
  401. /// <remarks>Use collection methods to add or remove TAB positions.</remarks>
  402. public FloatCollection TabPositions
  403. {
  404. get { return tabPositions; }
  405. set
  406. {
  407. if (value == null)
  408. tabPositions.Clear();
  409. else
  410. tabPositions = value;
  411. }
  412. }
  413. /// <summary>
  414. /// Gets or sets the fill color used to draw a text.
  415. /// </summary>
  416. /// <remarks>
  417. /// Default fill is <see cref="SolidFill"/>. You may specify other fill types, for example:
  418. /// <code>
  419. /// text1.TextFill = new HatchFill(Color.Black, Color.White, HatchStyle.Cross);
  420. /// </code>
  421. /// Use the <see cref="TextColor"/> property to set the solid text color.
  422. /// </remarks>
  423. [Category("Appearance")]
  424. [Editor("FastReport.TypeEditors.FillEditor, FastReport", typeof(UITypeEditor))]
  425. public FillBase TextFill
  426. {
  427. get { return textFill; }
  428. set
  429. {
  430. if (value == null)
  431. throw new ArgumentNullException("TextFill");
  432. textFill = value;
  433. if (!String.IsNullOrEmpty(Style))
  434. Style = "";
  435. }
  436. }
  437. /// <summary>
  438. /// Gets or sets the text outline.
  439. /// </summary>
  440. [Category("Appearance")]
  441. [Editor("FastReport.TypeEditors.OutlineEditor, FastReport", typeof(UITypeEditor))]
  442. public TextOutline TextOutline
  443. {
  444. get { return textOutline; }
  445. set
  446. {
  447. if (value == null)
  448. throw new ArgumentNullException("TextOutline");
  449. textOutline = value;
  450. if (!String.IsNullOrEmpty(Style))
  451. Style = "";
  452. }
  453. }
  454. /// <summary>
  455. /// Gets or sets the text color in a simple manner.
  456. /// </summary>
  457. /// <remarks>
  458. /// This property can be used in a report script to change the text color of the object. It is
  459. /// equivalent to: <code>textObject1.TextFill = new SolidFill(color);</code>
  460. /// </remarks>
  461. [Browsable(false)]
  462. public Color TextColor
  463. {
  464. get { return TextFill is SolidFill ? (TextFill as SolidFill).Color : Color.Black; }
  465. set { TextFill = new SolidFill(value); }
  466. }
  467. /// <summary>
  468. /// Gets or sets the string trimming options.
  469. /// </summary>
  470. [DefaultValue(StringTrimming.None)]
  471. [Category("Behavior")]
  472. public StringTrimming Trimming
  473. {
  474. get { return trimming; }
  475. set { trimming = value; }
  476. }
  477. /// <summary>
  478. /// Gets or sets the width ratio of the font.
  479. /// </summary>
  480. /// <remarks>
  481. /// Default value is 1. To make a font wider, set a value grether than 1; to make a font narrower,
  482. /// set a value less than 1.
  483. /// </remarks>
  484. [DefaultValue(1f)]
  485. [Category("Appearance")]
  486. public float FontWidthRatio
  487. {
  488. get { return fontWidthRatio; }
  489. set
  490. {
  491. if (value > 0)
  492. fontWidthRatio = value;
  493. else
  494. fontWidthRatio = 1;
  495. }
  496. }
  497. /// <summary>
  498. /// Gets or sets the height of single text line, in pixels.
  499. /// </summary>
  500. [DefaultValue(0f)]
  501. [Category("Appearance")]
  502. public float LineHeight
  503. {
  504. get { return lineHeight; }
  505. set { lineHeight = value; }
  506. }
  507. /// <summary>
  508. /// Gets or sets the offset of the first TAB symbol.
  509. /// </summary>
  510. [DefaultValue(0f)]
  511. [Category("Appearance")]
  512. //[TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
  513. public float FirstTabOffset
  514. {
  515. get { return firstTabOffset; }
  516. set { firstTabOffset = value; }
  517. }
  518. /// <summary>
  519. /// Gets or sets the width of TAB symbol, in pixels.
  520. /// </summary>
  521. [DefaultValue(58f)]
  522. [Category("Appearance")]
  523. public float TabWidth
  524. {
  525. get { return tabWidth; }
  526. set { tabWidth = value; }
  527. }
  528. /// <summary>
  529. /// Gets or sets a value that indicates if text should be clipped inside the object's bounds.
  530. /// </summary>
  531. [DefaultValue(true)]
  532. [Category("Behavior")]
  533. public bool Clip
  534. {
  535. get { return clip; }
  536. set { clip = value; }
  537. }
  538. /// <summary>
  539. /// Gets the collection of conditional highlight attributes.
  540. /// </summary>
  541. /// <remarks>
  542. /// Conditional highlight is used to change the visual appearance of the Text object
  543. /// depending on some condition(s). For example, you may highlight negative values displayed by
  544. /// the Text object with red color. To do this, add the highlight condition:
  545. /// <code>
  546. /// TextObject text1;
  547. /// HighlightCondition highlight = new HighlightCondition();
  548. /// highlight.Expression = "Value &lt; 0";
  549. /// highlight.Fill = new SolidFill(Color.Red);
  550. /// highlight.ApplyFill = true;
  551. /// text1.Highlight.Add(highlight);
  552. /// </code>
  553. /// </remarks>
  554. [Category("Data")]
  555. [Editor("FastReport.TypeEditors.HighlightEditor, FastReport", typeof(UITypeEditor))]
  556. public ConditionCollection Highlight
  557. {
  558. get { return highlight; }
  559. }
  560. /// <summary>
  561. /// Gets or sets a value that indicates if the text object should display its contents similar to the printout.
  562. /// </summary>
  563. [DefaultValue(false)]
  564. [Category("Behavior")]
  565. public bool Wysiwyg
  566. {
  567. get { return wysiwyg; }
  568. set { wysiwyg = value; }
  569. }
  570. /// <summary>
  571. /// Forces justify for the last text line.
  572. /// </summary>
  573. [Browsable(false)]
  574. public bool ForceJustify
  575. {
  576. get { return forceJustify; }
  577. set { forceJustify = value; }
  578. }
  579. /// <summary>
  580. /// Allows handling html tags in the text.
  581. /// </summary>
  582. /// <remarks>
  583. /// The following html tags can be used in the object's text: &lt;b&gt;, &lt;i&gt;, &lt;u&gt;,
  584. /// &lt;strike&gt;, &lt;sub&gt;, &lt;sup&gt;, &lt;/b&gt;, &lt;/i&gt;, &lt;/u&gt;,
  585. /// &lt;/strike&gt;, &lt;/sub&gt;, &lt;/sup&gt;,
  586. /// &lt;font color=&amp;...&amp;&gt;, &lt;/font&gt;. Font size cannot
  587. /// be changed due to limitations in the rendering engine.
  588. /// </remarks>
  589. [DefaultValue(false)]
  590. [Category("Behavior")]
  591. [Browsable(false)]
  592. [Obsolete("This method is deprecated please use TextRenderer")]
  593. public bool HtmlTags
  594. {
  595. get
  596. {
  597. return HasHtmlTags;
  598. }
  599. set { textRenderType = value ? TextRenderType.HtmlTags : TextRenderType.Default; }
  600. }
  601. /// <summary>
  602. /// Indicates handling html tags in the text.
  603. /// </summary>
  604. /// <remarks>To set the value use the TextRenderer property.</remarks>
  605. [DefaultValue(false)]
  606. [Category("Behavior")]
  607. [Browsable(false)]
  608. public bool HasHtmlTags
  609. {
  610. get
  611. {
  612. switch (textRenderType)
  613. {
  614. case TextRenderType.HtmlTags:
  615. case TextRenderType.HtmlParagraph:
  616. return true;
  617. default:
  618. return false;
  619. }
  620. }
  621. }
  622. /// <summary>
  623. /// The type of text render
  624. /// </summary>
  625. /// /// <remarks>
  626. /// The following html tags can be used in the object's text: &lt;b&gt;, &lt;i&gt;, &lt;u&gt;,
  627. /// &lt;strike&gt;, &lt;sub&gt;, &lt;sup&gt;, &lt;/b&gt;, &lt;/i&gt;, &lt;/u&gt;,
  628. /// &lt;/strike&gt;, &lt;/sub&gt;, &lt;/sup&gt;,
  629. /// &lt;font color=&amp;...&amp;&gt;, &lt;/font&gt;. Font size cannot
  630. /// be changed due to limitations in the rendering engine.
  631. /// </remarks>
  632. [DefaultValue(TextRenderType.Default)]
  633. [Category("Behavior")]
  634. public TextRenderType TextRenderType
  635. {
  636. get { return textRenderType; }
  637. set { textRenderType = value; }
  638. }
  639. /// <summary>
  640. /// Gets or sets the paragraph offset, in pixels. For HtmlParagraph use ParagraphFormat.FirstLineIndent.
  641. /// </summary>
  642. [DefaultValue(0f)]
  643. [Category("Appearance")]
  644. [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
  645. public float ParagraphOffset
  646. {
  647. get { return paragraphOffset; }
  648. set { paragraphOffset = value; }
  649. }
  650. internal bool IsAdvancedRendererNeeded
  651. {
  652. get { return HorzAlign == HorzAlign.Justify || Wysiwyg || LineHeight != 0 || HasHtmlTags; }
  653. }
  654. internal bool PreserveLastLineSpace { get { return preserveLastLineSpace; } set { preserveLastLineSpace = value; } }
  655. /// <summary>
  656. /// Cache for inline images
  657. /// </summary>
  658. [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  659. public InlineImageCache InlineImageCache
  660. {
  661. get
  662. {
  663. if (inlineImageCache == null)
  664. inlineImageCache = new InlineImageCache();
  665. return inlineImageCache;
  666. }
  667. }
  668. #endregion
  669. #region Private Methods
  670. private void DrawUnderlines(FRPaintEventArgs e)
  671. {
  672. if (!Underlines || Angle != 0)
  673. return;
  674. IGraphics g = e.Graphics;
  675. float lineHeight = LineHeight == 0 ? Font.GetHeight() * DrawUtils.ScreenDpiFX : LineHeight;
  676. lineHeight *= e.ScaleY;
  677. float curY = AbsTop * e.ScaleY + lineHeight + 1;
  678. Pen pen = e.Cache.GetPen(Border.Color, Border.Width * e.ScaleY, DashStyle.Solid);
  679. while (curY < AbsBottom * e.ScaleY)
  680. {
  681. g.DrawLine(pen, AbsLeft * e.ScaleX, curY, AbsRight * e.ScaleY, curY);
  682. curY += lineHeight;
  683. }
  684. }
  685. private SizeF CalcSize()
  686. {
  687. Report report = Report;
  688. if (String.IsNullOrEmpty(Text) || report == null)
  689. return new SizeF(0, 0);
  690. Font font = report.GraphicCache.GetFont(Font.FontFamily, Font.Size * 96f / DrawUtils.ScreenDpi, Font.Style);
  691. float width = 0;
  692. if (WordWrap)
  693. {
  694. if (Angle == 90 || Angle == 270)
  695. width = Height - Padding.Vertical;
  696. else
  697. width = Width - Padding.Horizontal;
  698. }
  699. IGraphics g = report.MeasureGraphics;
  700. IGraphicsState state = g.Save();
  701. try
  702. {
  703. if (report.TextQuality != TextQuality.Default)
  704. g.TextRenderingHint = report.GetTextQuality();
  705. if (TextRenderType == TextRenderType.HtmlParagraph)
  706. {
  707. if (width == 0)
  708. width = 100000;
  709. using (HtmlTextRenderer htmlRenderer = GetHtmlTextRenderer(g, new RectangleF(0, 0, width, 100000), 1, 1))
  710. {
  711. float height = htmlRenderer.CalcHeight();
  712. width = htmlRenderer.CalcWidth();
  713. width += Padding.Horizontal + 1;
  714. if (LineHeight == 0)
  715. height += Padding.Vertical + 1;
  716. return new SizeF(width, height);
  717. }
  718. }
  719. #if SKIA || !CROSSPLATFORM
  720. if (IsAdvancedRendererNeeded)
  721. #endif
  722. {
  723. if (width == 0)
  724. width = 100000;
  725. AdvancedTextRenderer renderer = new AdvancedTextRenderer(Text, g, font, Brushes.Black, Pens.Black,
  726. new RectangleF(0, 0, width, 100000), GetStringFormat(report.GraphicCache, 0),
  727. HorzAlign, VertAlign, LineHeight, Angle, FontWidthRatio, false, Wysiwyg, HasHtmlTags, false, 96f / DrawUtils.ScreenDpi,
  728. 96f / DrawUtils.ScreenDpi, InlineImageCache);
  729. float height = renderer.CalcHeight();
  730. width = renderer.CalcWidth();
  731. width += Padding.Horizontal + 1;
  732. if (LineHeight == 0)
  733. height += Padding.Vertical + 1;
  734. return new SizeF(width, height);
  735. }
  736. #if SKIA || !CROSSPLATFORM
  737. else
  738. {
  739. if (FontWidthRatio != 1)
  740. width /= FontWidthRatio;
  741. SizeF size = g.MeasureString(Text, font, new SizeF(width, 100000));
  742. size.Width += Padding.Horizontal + 1;
  743. size.Height += Padding.Vertical + 1;
  744. return size;
  745. }
  746. #endif
  747. }
  748. finally
  749. {
  750. g.Restore(state);
  751. }
  752. }
  753. private float InternalCalcWidth()
  754. {
  755. bool saveWordWrap = WordWrap;
  756. WordWrap = false;
  757. float result = 0;
  758. try
  759. {
  760. SizeF size = CalcSize();
  761. result = size.Width;
  762. }
  763. finally
  764. {
  765. WordWrap = saveWordWrap;
  766. }
  767. return result;
  768. }
  769. private float InternalCalcHeight()
  770. {
  771. return CalcSize().Height;
  772. }
  773. private string BreakTextHtml(out bool endOnEnter)
  774. {
  775. endOnEnter = false;
  776. ForceJustify = false;
  777. if (String.IsNullOrEmpty(Text))
  778. return "";
  779. string result = null;
  780. Report report = Report;
  781. if (report == null)
  782. return "";
  783. StringFormat format = GetStringFormat(report.GraphicCache, StringFormatFlags.LineLimit);
  784. RectangleF textRect = new RectangleF(0, 0, Width - Padding.Horizontal, Height - Padding.Vertical);
  785. int charactersFitted;
  786. IGraphics g = report.MeasureGraphics;
  787. IGraphicsState state = g.Save();
  788. if (report.TextQuality != TextQuality.Default)
  789. g.TextRenderingHint = report.GetTextQuality();
  790. try
  791. {
  792. using (HtmlTextRenderer htmlRenderer = GetHtmlTextRenderer(g, 1, 1, textRect, format))
  793. {
  794. htmlRenderer.CalcHeight(out charactersFitted);
  795. if (charactersFitted == 0)
  796. return null;
  797. Text = HtmlTextRenderer.BreakHtml(Text, charactersFitted, out result, out endOnEnter);
  798. if (HorzAlign == HorzAlign.Justify && !endOnEnter && result != "")
  799. {
  800. if (Text.EndsWith(" "))
  801. Text = Text.TrimEnd(' ');
  802. ForceJustify = true;
  803. }
  804. }
  805. }
  806. finally
  807. {
  808. g.Restore(state);
  809. }
  810. return result;
  811. }
  812. private string BreakText()
  813. {
  814. ForceJustify = false;
  815. if (String.IsNullOrEmpty(Text))
  816. return "";
  817. string result = null;
  818. Report report = Report;
  819. if (report == null)
  820. return "";
  821. Font font = report.GraphicCache.GetFont(Font.FontFamily, Font.Size * 96f / DrawUtils.ScreenDpi, Font.Style);
  822. StringFormat format = GetStringFormat(report.GraphicCache, StringFormatFlags.LineLimit);
  823. RectangleF textRect = new RectangleF(0, 0, Width - Padding.Horizontal, Height - Padding.Vertical);
  824. if (textRect.Height < 0)
  825. return null;
  826. int charactersFitted;
  827. int linesFilled;
  828. IGraphics g = report.MeasureGraphics;
  829. IGraphicsState state = g.Save();
  830. try
  831. {
  832. if (report.TextQuality != TextQuality.Default)
  833. g.TextRenderingHint = report.GetTextQuality();
  834. AdvancedTextRenderer.StyleDescriptor htmlStyle = null;
  835. if (IsAdvancedRendererNeeded)
  836. {
  837. AdvancedTextRenderer renderer = new AdvancedTextRenderer(Text, g, font, Brushes.Black, Pens.Black,
  838. textRect, format, HorzAlign, VertAlign, LineHeight, Angle, FontWidthRatio, false, Wysiwyg, HasHtmlTags, false, 96f / DrawUtils.ScreenDpi,
  839. 96f / DrawUtils.ScreenDpi, InlineImageCache);
  840. renderer.CalcHeight(out charactersFitted, out htmlStyle);
  841. if (charactersFitted == 0)
  842. linesFilled = 0;
  843. else
  844. linesFilled = 2;
  845. }
  846. else
  847. {
  848. g.MeasureString(Text, font, textRect.Size, format, out charactersFitted, out linesFilled);
  849. }
  850. if (linesFilled == 0)
  851. return null;
  852. if (linesFilled == 1)
  853. {
  854. // check if there is enough space for one line
  855. float lineHeight = g.MeasureString("Wg", font).Height;
  856. if (textRect.Height < lineHeight)
  857. return null;
  858. }
  859. if (charactersFitted < Text.Length)
  860. result = Text.Substring(charactersFitted);
  861. else
  862. result = "";
  863. Text = Text.Substring(0, charactersFitted);
  864. if (HorzAlign == HorzAlign.Justify && !Text.EndsWith("\n") && result != "")
  865. {
  866. if (Text.EndsWith(" "))
  867. Text = Text.Substring(0, Text.Length - 1);
  868. ForceJustify = true;
  869. }
  870. if (HasHtmlTags && htmlStyle != null && result != "")
  871. result = htmlStyle.ToString() + result;
  872. }
  873. finally
  874. {
  875. g.Restore(state);
  876. }
  877. return result;
  878. }
  879. private void ProcessAutoShrink()
  880. {
  881. if (TextRenderType == TextRenderType.HtmlParagraph)
  882. return;
  883. if (String.IsNullOrEmpty(Text))
  884. return;
  885. if (AutoShrink == AutoShrinkMode.FontSize)
  886. {
  887. while (CalcWidth() > Width - 1 && Font.Size > AutoShrinkMinSize && Font.Size>1)
  888. {
  889. Font = new Font(Font.FontFamily, Font.Size - 1, Font.Style);
  890. }
  891. }
  892. else if (AutoShrink == AutoShrinkMode.FontWidth)
  893. {
  894. FontWidthRatio = 1;
  895. float ratio = Converter.DecreasePrecision((Width - 1) / CalcWidth(), 2) - 0.01f;
  896. if (ratio < 1)
  897. FontWidthRatio = Math.Max(ratio, AutoShrinkMinSize);
  898. }
  899. }
  900. private string MakeParagraphOffset(string text)
  901. {
  902. // fixed issue 2823
  903. FirstTabOffset = ParagraphOffset;
  904. string[] lines = text.Split('\n');
  905. for (int i = 0; i < lines.Length; i++)
  906. {
  907. if (!lines[i].StartsWith("\t"))
  908. lines[i] = "\t" + lines[i];
  909. }
  910. return String.Join("\n", lines);
  911. }
  912. #endregion
  913. #region Protected Methods
  914. /// <inheritdoc/>
  915. protected override void DeserializeSubItems(FRReader reader)
  916. {
  917. if (String.Compare(reader.ItemName, "Highlight", true) == 0)
  918. reader.Read(Highlight);
  919. else
  920. base.DeserializeSubItems(reader);
  921. }
  922. #endregion
  923. #region Public Methods
  924. /// <summary>
  925. /// Returns StringFormat object.
  926. /// </summary>
  927. /// <param name="cache">Report graphic cache.</param>
  928. /// <param name="flags">StringFormat flags.</param>
  929. /// <returns>StringFormat object.</returns>
  930. public StringFormat GetStringFormat(GraphicCache cache, StringFormatFlags flags)
  931. {
  932. return GetStringFormat(cache, flags, 1);
  933. }
  934. internal StringFormat GetStringFormat(GraphicCache cache, StringFormatFlags flags, float scale)
  935. {
  936. StringAlignment align = StringAlignment.Near;
  937. if (HorzAlign == HorzAlign.Center)
  938. align = StringAlignment.Center;
  939. else if (HorzAlign == HorzAlign.Right)
  940. align = StringAlignment.Far;
  941. StringAlignment lineAlign = StringAlignment.Near;
  942. if (VertAlign == VertAlign.Center)
  943. lineAlign = StringAlignment.Center;
  944. else if (VertAlign == VertAlign.Bottom)
  945. lineAlign = StringAlignment.Far;
  946. if (RightToLeft)
  947. flags |= StringFormatFlags.DirectionRightToLeft;
  948. if (!WordWrap)
  949. flags |= StringFormatFlags.NoWrap;
  950. if (!Clip)
  951. flags |= StringFormatFlags.NoClip;
  952. if (TabPositions.Count > 0)
  953. {
  954. FloatCollection tabPositions = new FloatCollection();
  955. foreach (var i in TabPositions)
  956. tabPositions.Add((float)i * scale);
  957. return cache.GetStringFormat(align, lineAlign, Trimming, flags, firstTabOffset * scale, tabPositions,
  958. 48 * scale);
  959. }
  960. return cache.GetStringFormat(align, lineAlign, Trimming, flags, firstTabOffset * scale, tabWidth * scale);
  961. }
  962. /// <inheritdoc/>
  963. public override void Assign(Base source)
  964. {
  965. base.Assign(source);
  966. TextObject src = source as TextObject;
  967. AutoWidth = src.AutoWidth;
  968. HorzAlign = src.HorzAlign;
  969. VertAlign = src.VertAlign;
  970. Angle = src.Angle;
  971. RightToLeft = src.RightToLeft;
  972. WordWrap = src.WordWrap;
  973. Underlines = src.Underlines;
  974. Font = src.Font;
  975. TextFill = src.TextFill.Clone();
  976. TextOutline.Assign(src.TextOutline);
  977. Trimming = src.Trimming;
  978. FontWidthRatio = src.FontWidthRatio;
  979. FirstTabOffset = src.FirstTabOffset;
  980. TabWidth = src.TabWidth;
  981. TabPositions.Assign(src.TabPositions);
  982. Clip = src.Clip;
  983. Highlight.Assign(src.Highlight);
  984. Wysiwyg = src.Wysiwyg;
  985. LineHeight = src.LineHeight;
  986. TextRenderType = src.TextRenderType;
  987. AutoShrink = src.AutoShrink;
  988. AutoShrinkMinSize = src.AutoShrinkMinSize;
  989. ParagraphOffset = src.ParagraphOffset;
  990. inlineImageCache = src.inlineImageCache;
  991. paragraphFormat.Assign(src.paragraphFormat);
  992. }
  993. /// <summary>
  994. /// Returns an instance of html text renderer.
  995. /// </summary>
  996. /// <param name="scale">Scale ratio.</param>
  997. /// <param name="fontScale">Font scale ratio.</param>
  998. /// <returns>The html text renderer.</returns>
  999. public HtmlTextRenderer GetHtmlTextRenderer(float scale, float fontScale)
  1000. {
  1001. return GetHtmlTextRenderer(Report.MeasureGraphics, scale, fontScale);
  1002. }
  1003. internal HtmlTextRenderer GetHtmlTextRenderer(IGraphics g, float scale, float fontScale)
  1004. {
  1005. StringFormat format = GetStringFormat(Report.GraphicCache, 0, scale);
  1006. RectangleF textRect = new RectangleF(
  1007. (AbsLeft + Padding.Left) * scale,
  1008. (AbsTop + Padding.Top) * scale,
  1009. (Width - Padding.Horizontal) * scale,
  1010. (Height - Padding.Vertical) * scale);
  1011. return GetHtmlTextRenderer(g, scale, fontScale, textRect, format);
  1012. }
  1013. internal HtmlTextRenderer GetHtmlTextRenderer(IGraphics g, RectangleF textRect, float scale, float fontScale)
  1014. {
  1015. StringFormat format = GetStringFormat(Report.GraphicCache, 0, fontScale);
  1016. return GetHtmlTextRenderer(g, scale, fontScale, textRect, format);
  1017. }
  1018. internal HtmlTextRenderer GetHtmlTextRenderer(IGraphics g, float scale, float fontScale, RectangleF textRect, StringFormat format)
  1019. {
  1020. return GetHtmlTextRenderer(Text, g, fontScale, scale, fontScale, textRect, format, false);
  1021. }
  1022. internal HtmlTextRenderer GetHtmlTextRenderer(string text, IGraphics g, float formatScale, float scale, float fontScale,
  1023. RectangleF textRect, StringFormat format, bool isPrinting)
  1024. {
  1025. #if true
  1026. HtmlTextRenderer.RendererContext context;
  1027. context.text = text;
  1028. context.g = g;
  1029. context.font = font.FontFamily;
  1030. context.size = font.Size;
  1031. context.style = font.Style; // no keep
  1032. context.color = TextColor; // no keep
  1033. context.underlineColor = textOutline.Color;
  1034. context.rect = textRect;
  1035. context.underlines = Underlines;
  1036. context.format = format; // no keep
  1037. context.horzAlign = horzAlign;
  1038. context.vertAlign = vertAlign;
  1039. context.paragraphFormat = ParagraphFormat.MultipleScale(formatScale);
  1040. context.forceJustify = ForceJustify;
  1041. context.scale = scale* 96f / DrawUtils.ScreenDpi;
  1042. context.fontScale = fontScale * 96f / DrawUtils.ScreenDpi;
  1043. context.cache = InlineImageCache;
  1044. context.isPrinting = isPrinting;
  1045. context.isDifferentTabPositions = TabPositions.Count > 0;
  1046. context.keepLastLineSpace = this.PreserveLastLineSpace;
  1047. return new HtmlTextRenderer(context);
  1048. #else
  1049. bool isDifferentTabPositions = TabPositions.Count > 0;
  1050. return new HtmlTextRenderer(text, g, font.FontFamily, font.Size, font.Style, TextColor,
  1051. textOutline.Color, textRect, Underlines,
  1052. format, horzAlign, vertAlign, ParagraphFormat.MultipleScale(formatScale), ForceJustify,
  1053. scale * 96f / DrawUtils.ScreenDpi, fontScale * 96f / DrawUtils.ScreenDpi, InlineImageCache,
  1054. isPrinting, isDifferentTabPositions);
  1055. #endif
  1056. }
  1057. /// <summary>
  1058. /// Draws a text.
  1059. /// </summary>
  1060. /// <param name="e">Paint event data.</param>
  1061. public void DrawText(FRPaintEventArgs e)
  1062. {
  1063. string text = GetDisplayText();
  1064. if (!String.IsNullOrEmpty(text))
  1065. {
  1066. IGraphics g = e.Graphics;
  1067. RectangleF textRect = new RectangleF(
  1068. (AbsLeft + Padding.Left) * e.ScaleX,
  1069. (AbsTop + Padding.Top) * e.ScaleY,
  1070. (Width - Padding.Horizontal) * e.ScaleX,
  1071. (Height - Padding.Vertical) * e.ScaleY);
  1072. if (ParagraphOffset != 0 && IsDesigning)
  1073. text = MakeParagraphOffset(text);
  1074. StringFormat format = GetStringFormat(e.Cache, 0, e.ScaleX);
  1075. Font font = e.Cache.GetFont(Font.FontFamily,
  1076. IsPrinting ? Font.Size : Font.Size * e.ScaleX * 96f / DrawUtils.ScreenDpi,
  1077. Font.Style);
  1078. Brush textBrush = null;
  1079. if (TextFill is SolidFill)
  1080. textBrush = e.Cache.GetBrush((TextFill as SolidFill).Color);
  1081. else
  1082. textBrush = TextFill.CreateBrush(textRect, e.ScaleX, e.ScaleY);
  1083. Pen outlinePen = null;
  1084. if (textOutline.Enabled)
  1085. outlinePen = e.Cache.GetPen(textOutline.Color, textOutline.Width * e.ScaleX, textOutline.Style);
  1086. Report report = Report;
  1087. if (report != null && report.TextQuality != TextQuality.Default)
  1088. g.TextRenderingHint = report.GetTextQuality();
  1089. if (textRect.Width > 0 && textRect.Height > 0)
  1090. {
  1091. switch (TextRenderType)
  1092. {
  1093. case TextRenderType.Inline:
  1094. g.DrawString(text, font, textBrush, textRect.X, textRect.Y, StringFormat.GenericTypographic);
  1095. break;
  1096. case TextRenderType.HtmlParagraph:
  1097. try
  1098. {
  1099. using (HtmlTextRenderer htmlRenderer = GetHtmlTextRenderer(text, e.Graphics, e.ScaleX,
  1100. IsPrinting ? 1 : e.ScaleX, IsPrinting ? 1 / (96f / DrawUtils.ScreenDpi) : e.ScaleX, textRect, format, IsPrinting))
  1101. {
  1102. htmlRenderer.Draw();
  1103. }
  1104. }
  1105. catch
  1106. {
  1107. textBrush.Dispose();
  1108. textBrush = null;
  1109. }
  1110. break;
  1111. default:
  1112. if (IsAdvancedRendererNeeded)
  1113. {
  1114. // use advanced rendering
  1115. AdvancedTextRenderer advancedRenderer = new AdvancedTextRenderer(text, g, font, textBrush,
  1116. outlinePen, textRect, format, HorzAlign, VertAlign, LineHeight * e.ScaleY, Angle,
  1117. FontWidthRatio, ForceJustify, Wysiwyg, HasHtmlTags, false,
  1118. e.ScaleX * 96f / DrawUtils.ScreenDpi,
  1119. IsPrinting ? 1 : e.ScaleX * 96f / DrawUtils.ScreenDpi, InlineImageCache, IsPrinting);
  1120. advancedRenderer.Draw();
  1121. }
  1122. else
  1123. {
  1124. // use simple rendering
  1125. if (Angle == 0 && FontWidthRatio == 1)
  1126. {
  1127. if (outlinePen == null)
  1128. {
  1129. if (WordWrap)
  1130. format.Trimming = StringTrimming.Word;
  1131. g.DrawString(text, font, textBrush, textRect, format);
  1132. }
  1133. else
  1134. {
  1135. GraphicsPath path = new GraphicsPath();
  1136. path.AddString(text, font.FontFamily, Convert.ToInt32(font.Style),
  1137. g.DpiY * font.Size / 72, textRect, format);
  1138. IGraphicsState state = g.Save();
  1139. g.SetClip(textRect);
  1140. //g.FillPath(textBrush, path);
  1141. //regime for text output with drawbehind
  1142. if (TextOutline.DrawBehind)
  1143. {
  1144. g.DrawPath(outlinePen, path);
  1145. g.FillPath(textBrush, path);
  1146. }
  1147. else //without. default
  1148. {
  1149. g.FillAndDrawPath(outlinePen, textBrush, path);
  1150. }
  1151. g.Restore(state);
  1152. }
  1153. }
  1154. else
  1155. StandardTextRenderer.Draw(text, g, font, textBrush, outlinePen, textRect, format, Angle,
  1156. FontWidthRatio);
  1157. }
  1158. DrawUnderlines(e);
  1159. break;
  1160. }
  1161. }
  1162. if (!(TextFill is SolidFill))
  1163. {
  1164. textBrush.Dispose();
  1165. }
  1166. }
  1167. }
  1168. /// <inheritdoc/>
  1169. public override void Draw(FRPaintEventArgs e)
  1170. {
  1171. base.Draw(e);
  1172. DrawText(e);
  1173. DrawMarkers(e);
  1174. Border.Draw(e, new RectangleF(AbsLeft, AbsTop, Width, Height));
  1175. DrawDesign(e);
  1176. }
  1177. /// <inheritdoc/>
  1178. public override void ApplyStyle(Style style)
  1179. {
  1180. if (style.ApplyTextFill)
  1181. TextFill = style.TextFill.Clone();
  1182. if (style.ApplyFont)
  1183. Font = style.Font;
  1184. base.ApplyStyle(style);
  1185. }
  1186. /// <inheritdoc/>
  1187. public override void SaveStyle()
  1188. {
  1189. base.SaveStyle();
  1190. savedTextFill = TextFill;
  1191. savedFont = Font;
  1192. }
  1193. /// <inheritdoc/>
  1194. public override void RestoreStyle()
  1195. {
  1196. base.RestoreStyle();
  1197. TextFill = savedTextFill;
  1198. Font = savedFont;
  1199. }
  1200. /// <inheritdoc/>
  1201. public override void Serialize(FRWriter writer)
  1202. {
  1203. if (writer.SerializeTo == SerializeTo.Preview && AutoWidth)
  1204. {
  1205. WordWrap = false;
  1206. float width = CalcSize().Width;
  1207. if ((Anchor & AnchorStyles.Right) != 0)
  1208. Left = Right - width;
  1209. Width = width;
  1210. }
  1211. TextObject c = writer.DiffObject as TextObject;
  1212. base.Serialize(writer);
  1213. if (c == null)
  1214. return; // RichObject here
  1215. if (AutoWidth != c.AutoWidth)
  1216. writer.WriteBool("AutoWidth", AutoWidth);
  1217. if (AutoShrink != c.AutoShrink)
  1218. writer.WriteValue("AutoShrink", AutoShrink);
  1219. if (FloatDiff(AutoShrinkMinSize, c.AutoShrinkMinSize))
  1220. writer.WriteFloat("AutoShrinkMinSize", AutoShrinkMinSize);
  1221. if (HorzAlign != c.HorzAlign)
  1222. writer.WriteValue("HorzAlign", HorzAlign);
  1223. if (VertAlign != c.VertAlign)
  1224. writer.WriteValue("VertAlign", VertAlign);
  1225. if (Angle != c.Angle)
  1226. writer.WriteInt("Angle", Angle);
  1227. if (RightToLeft != c.RightToLeft)
  1228. writer.WriteBool("RightToLeft", RightToLeft);
  1229. if (WordWrap != c.WordWrap)
  1230. writer.WriteBool("WordWrap", WordWrap);
  1231. if (Underlines != c.Underlines)
  1232. writer.WriteBool("Underlines", Underlines);
  1233. if ((writer.SerializeTo != SerializeTo.Preview || !Font.Equals(c.Font)) && writer.ItemName != "inherited")
  1234. writer.WriteValue("Font", Font);
  1235. TextFill.Serialize(writer, "TextFill", c.TextFill);
  1236. if (TextOutline != null)
  1237. TextOutline.Serialize(writer, "TextOutline", c.TextOutline);
  1238. if (Trimming != c.Trimming)
  1239. writer.WriteValue("Trimming", Trimming);
  1240. if (FontWidthRatio != c.FontWidthRatio)
  1241. writer.WriteFloat("FontWidthRatio", FontWidthRatio);
  1242. if (FirstTabOffset != c.FirstTabOffset)
  1243. writer.WriteFloat("FirstTabOffset", FirstTabOffset);
  1244. if (TabWidth != c.TabWidth)
  1245. writer.WriteFloat("TabWidth", TabWidth);
  1246. if (TabPositions.Count > 0)
  1247. writer.WriteValue("TabPositions", TabPositions);
  1248. if (Clip != c.Clip)
  1249. writer.WriteBool("Clip", Clip);
  1250. if (Wysiwyg != c.Wysiwyg)
  1251. writer.WriteBool("Wysiwyg", Wysiwyg);
  1252. if (LineHeight != c.LineHeight)
  1253. writer.WriteFloat("LineHeight", LineHeight);
  1254. if (TextRenderType != c.TextRenderType)
  1255. writer.WriteValue("TextRenderType", TextRenderType);
  1256. if (ParagraphOffset != c.ParagraphOffset)
  1257. writer.WriteFloat("ParagraphOffset", ParagraphOffset);
  1258. if (ForceJustify != c.ForceJustify)
  1259. writer.WriteBool("ForceJustify", ForceJustify);
  1260. if (writer.SerializeTo != SerializeTo.Preview)
  1261. {
  1262. if (Style != c.Style)
  1263. writer.WriteStr("Style", Style);
  1264. if (Highlight.Count > 0)
  1265. writer.Write(Highlight);
  1266. }
  1267. if (ParagraphFormat.FirstLineIndent > 0)
  1268. writer.WriteFloat("ParagraphFormat.FirstLineIndent", ParagraphFormat.FirstLineIndent);
  1269. if (ParagraphFormat.LineSpacing > 0)
  1270. writer.WriteFloat("ParagraphFormat.LineSpacing", ParagraphFormat.LineSpacing);
  1271. if (ParagraphFormat.LineSpacingType != LineSpacingType.Single)
  1272. writer.WriteValue("ParagraphFormat.LineSpacingType", ParagraphFormat.LineSpacingType);
  1273. if (ParagraphFormat.SkipFirstLineIndent)
  1274. writer.WriteBool("ParagraphFormat.SkipFirstLineIndent", ParagraphFormat.SkipFirstLineIndent);
  1275. StringBuilder sb = null;
  1276. if (InlineImageCache != null && writer.BlobStore != null && HasHtmlTags == true)
  1277. foreach (InlineImageCache.CacheItem item in InlineImageCache.AllItems())
  1278. {
  1279. if (item.Src.StartsWith("data:")) continue;
  1280. if (sb == null)
  1281. sb = new StringBuilder();
  1282. sb.Append(writer.BlobStore.AddOrUpdate(item.Stream, item.Src))
  1283. .Append(',');
  1284. }
  1285. if (sb != null)
  1286. {
  1287. sb.Length--;
  1288. writer.WriteStr("InlineImageCacheIndexes", sb.ToString());
  1289. }
  1290. }
  1291. /// <inheritdoc/>
  1292. public override void Deserialize(FRReader reader)
  1293. {
  1294. base.Deserialize(reader);
  1295. TextFill.Deserialize(reader, "TextFill");
  1296. if (reader.BlobStore != null)
  1297. {
  1298. string indexes = reader.ReadStr("InlineImageCacheIndexes");
  1299. if (indexes != "null" && !String.IsNullOrEmpty(indexes))
  1300. {
  1301. string[] arr = indexes.Split(',');
  1302. foreach (string index in arr)
  1303. {
  1304. int val = 0;
  1305. if (Int32.TryParse(index, out val))
  1306. {
  1307. if (val >= 0 && val < reader.BlobStore.Count)
  1308. {
  1309. InlineImageCache.CacheItem it = new InlineImageCache.CacheItem();
  1310. it.Set(reader.BlobStore.Get(val));
  1311. InlineImageCache.Set(reader.BlobStore.GetSource(val), it);
  1312. }
  1313. }
  1314. }
  1315. }
  1316. }
  1317. switch (reader.DeserializeFrom)
  1318. {
  1319. case SerializeTo.Undo:
  1320. case SerializeTo.Preview:
  1321. case SerializeTo.Clipboard:
  1322. // skip
  1323. break;
  1324. default:
  1325. if (!reader.HasProperty("Font") && reader.ItemName != "inherited")
  1326. {
  1327. string creatorVersion = reader.Root.GetProp("ReportInfo.CreatorVersion");
  1328. if (!String.IsNullOrEmpty(creatorVersion))
  1329. {
  1330. try
  1331. {
  1332. string[] versions = creatorVersion.Split('.');
  1333. int major = 0;
  1334. if (Int32.TryParse(versions[0], out major))
  1335. {
  1336. if (major < 2016)
  1337. {
  1338. Font = new Font("Arial", 10);
  1339. }
  1340. }
  1341. }
  1342. catch
  1343. {
  1344. }
  1345. }
  1346. }
  1347. break;
  1348. }
  1349. }
  1350. public override void InitializeComponent()
  1351. {
  1352. base.InitializeComponent();
  1353. TextFill.InitializeComponent();
  1354. }
  1355. public override void FinalizeComponent()
  1356. {
  1357. base.FinalizeComponent();
  1358. TextFill.FinalizeComponent();
  1359. }
  1360. internal void ApplyCondition(HighlightCondition c)
  1361. {
  1362. if (c.ApplyBorder)
  1363. Border = c.Border.Clone();
  1364. if (c.ApplyFill)
  1365. Fill = c.Fill.Clone();
  1366. if (c.ApplyTextFill)
  1367. TextFill = c.TextFill.Clone();
  1368. if (c.ApplyFont)
  1369. Font = c.Font;
  1370. Visible = c.Visible;
  1371. }
  1372. #endregion
  1373. #region Report Engine
  1374. /// <inheritdoc/>
  1375. public override string[] GetExpressions()
  1376. {
  1377. List<string> expressions = new List<string>();
  1378. expressions.AddRange(base.GetExpressions());
  1379. if (AllowExpressions && !String.IsNullOrEmpty(Brackets))
  1380. {
  1381. string[] brackets = Brackets.Split(',');
  1382. // collect expressions found in the text
  1383. expressions.AddRange(CodeUtils.GetExpressions(Text, brackets[0], brackets[1]));
  1384. }
  1385. // add highlight conditions
  1386. foreach (HighlightCondition condition in Highlight)
  1387. {
  1388. expressions.Add(condition.Expression);
  1389. }
  1390. return expressions.ToArray();
  1391. }
  1392. /// <inheritdoc/>
  1393. public override void SaveState()
  1394. {
  1395. base.SaveState();
  1396. savedText = Text;
  1397. savedTextFill = TextFill;
  1398. savedFont = Font;
  1399. savedFormat = Format;
  1400. }
  1401. /// <inheritdoc/>
  1402. public override void RestoreState()
  1403. {
  1404. base.RestoreState();
  1405. Text = savedText;
  1406. TextFill = savedTextFill;
  1407. Font = savedFont;
  1408. Format = savedFormat;
  1409. }
  1410. /// <summary>
  1411. /// Calculates the object's width.
  1412. /// </summary>
  1413. /// <returns>The width, in pixels.</returns>
  1414. public float CalcWidth()
  1415. {
  1416. if (Angle == 90 || Angle == 270)
  1417. return InternalCalcHeight();
  1418. return InternalCalcWidth();
  1419. }
  1420. /// <inheritdoc/>
  1421. public override float CalcHeight()
  1422. {
  1423. if (Angle == 90 || Angle == 270)
  1424. return InternalCalcWidth();
  1425. return InternalCalcHeight();
  1426. }
  1427. /// <inheritdoc/>
  1428. public override void GetData()
  1429. {
  1430. base.GetData();
  1431. // process expressions
  1432. if (AllowExpressions)
  1433. {
  1434. if (!String.IsNullOrEmpty(Brackets))
  1435. {
  1436. string[] brackets = Brackets.Split(',');
  1437. FindTextArgs args = new FindTextArgs();
  1438. args.Text = new FastString(Text);
  1439. args.OpenBracket = brackets[0];
  1440. args.CloseBracket = brackets[1];
  1441. int expressionIndex = 0;
  1442. while (args.StartIndex < args.Text.Length)
  1443. {
  1444. string expression = CodeUtils.GetExpression(args, false);
  1445. if (expression == null)
  1446. break;
  1447. string formattedValue = CalcAndFormatExpression(expression, expressionIndex);
  1448. args.Text.Remove(args.StartIndex, args.EndIndex - args.StartIndex);
  1449. args.Text.Insert(args.StartIndex, formattedValue);
  1450. args.StartIndex += formattedValue.Length;
  1451. expressionIndex++;
  1452. }
  1453. Text = args.Text.ToString();
  1454. }
  1455. }
  1456. // process highlight
  1457. Variant varValue = new Variant(Value);
  1458. foreach (HighlightCondition condition in Highlight)
  1459. {
  1460. try
  1461. {
  1462. object val = Report.Calc(condition.Expression, varValue);
  1463. if (val != null && (bool)val == true)
  1464. {
  1465. ApplyCondition(condition);
  1466. break;
  1467. }
  1468. }
  1469. catch (Exception e)
  1470. {
  1471. throw new Exception(Name + ": " + Res.Get("Messages,ErrorInHighlightCondition") + ": " + condition.Expression, e.InnerException);
  1472. }
  1473. }
  1474. // make paragraph offset
  1475. if (ParagraphOffset != 0)
  1476. Text = MakeParagraphOffset(Text);
  1477. // process AutoShrink
  1478. ProcessAutoShrink();
  1479. }
  1480. /// <inheritdoc/>
  1481. public override bool Break(BreakableComponent breakTo)
  1482. {
  1483. switch (TextRenderType)
  1484. {
  1485. case TextRenderType.HtmlParagraph:
  1486. bool endOnEnter;
  1487. string breakTextHtml = BreakTextHtml(out endOnEnter);
  1488. if (breakTextHtml != null && breakTo != null)
  1489. {
  1490. (breakTo as TextObject).Text = breakTextHtml;
  1491. if (!endOnEnter)
  1492. (breakTo as TextObject).ParagraphFormat.SkipFirstLineIndent = true;
  1493. }
  1494. return breakTextHtml != null;
  1495. default:
  1496. string breakText = BreakText();
  1497. if (breakText != null && breakTo != null)
  1498. (breakTo as TextObject).Text = breakText;
  1499. return breakText != null;
  1500. }
  1501. }
  1502. internal IEnumerable<PictureObject> GetPictureFromHtmlText(AdvancedTextRenderer renderer)
  1503. {
  1504. if (renderer == null)
  1505. {
  1506. using (Bitmap b = new Bitmap(1, 1))
  1507. using (IGraphics g = new GdiGraphics(b))
  1508. {
  1509. RectangleF textRect = new RectangleF(
  1510. (AbsLeft + Padding.Left),
  1511. (AbsTop + Padding.Top),
  1512. (Width - Padding.Horizontal),
  1513. (Height - Padding.Vertical));
  1514. StringFormat format = GetStringFormat(Report.GraphicCache, StringFormatFlags.LineLimit);
  1515. renderer = new AdvancedTextRenderer(Text, g, Font, Brushes.Black, Pens.Black,
  1516. textRect, format, HorzAlign, VertAlign, LineHeight, Angle, FontWidthRatio,
  1517. ForceJustify, Wysiwyg, HasHtmlTags, false, 1, 1,
  1518. InlineImageCache);
  1519. foreach (PictureObject obj in GetPictureFromHtmlText(renderer))
  1520. yield return obj;
  1521. }
  1522. }
  1523. else
  1524. {
  1525. RectangleF textRect = renderer.DisplayRect;
  1526. foreach (AdvancedTextRenderer.Paragraph paragraph in renderer.Paragraphs)
  1527. foreach (AdvancedTextRenderer.Line line in paragraph.Lines)
  1528. foreach (AdvancedTextRenderer.Word word in line.Words)
  1529. foreach (AdvancedTextRenderer.Run run in word.Runs)
  1530. if (run is AdvancedTextRenderer.RunImage)
  1531. {
  1532. AdvancedTextRenderer.RunImage runImage = run as AdvancedTextRenderer.RunImage;
  1533. PictureObject obj = new PictureObject();
  1534. float left = runImage.Left - textRect.Left;
  1535. float top = runImage.Top - textRect.Top;
  1536. float width =
  1537. runImage.Left + runImage.Width > textRect.Right ?
  1538. textRect.Right - (left < 0 ? textRect.Left : runImage.Left) :
  1539. (
  1540. runImage.Left < textRect.Left ?
  1541. runImage.Left + runImage.Width - textRect.Left :
  1542. runImage.Width
  1543. );
  1544. float height =
  1545. runImage.Top + runImage.Height > textRect.Bottom ?
  1546. textRect.Bottom - (top < 0 ? textRect.Top : runImage.Top) :
  1547. (
  1548. runImage.Top < textRect.Top ?
  1549. runImage.Top + runImage.Height - textRect.Top :
  1550. runImage.Height
  1551. );
  1552. if (left < 0 || top < 0 || width < runImage.Width || height < runImage.Height)
  1553. {
  1554. Bitmap bmp = new Bitmap((int)width, (int)height);
  1555. using (Graphics g = Graphics.FromImage(bmp))
  1556. {
  1557. g.DrawImage(runImage.Image, new PointF(
  1558. left < 0 ? left : 0,
  1559. top < 0 ? top : 0
  1560. ));
  1561. }
  1562. obj.Image = bmp;
  1563. obj.Left = (left < 0 ? textRect.Left : runImage.Left) / renderer.Scale;
  1564. obj.Top = (top < 0 ? textRect.Top : runImage.Top) / renderer.Scale;
  1565. obj.Width = width / renderer.Scale;
  1566. obj.Height = height / renderer.Scale;
  1567. obj.SizeMode = PictureBoxSizeMode.StretchImage;
  1568. }
  1569. else
  1570. {
  1571. obj.Image = runImage.Image;
  1572. obj.Left = runImage.Left / renderer.Scale;
  1573. obj.Top = runImage.Top / renderer.Scale;
  1574. obj.Width = runImage.Width / renderer.Scale;
  1575. obj.Height = runImage.Height / renderer.Scale;
  1576. obj.SizeMode = PictureBoxSizeMode.StretchImage;
  1577. }
  1578. yield return obj;
  1579. }
  1580. }
  1581. }
  1582. #endregion
  1583. /// <summary>
  1584. /// Initializes a new instance of the <see cref="TextObject"/> class with default settings.
  1585. /// </summary>
  1586. public TextObject()
  1587. {
  1588. paragraphFormat = new ParagraphFormat();
  1589. wordWrap = true;
  1590. font = DrawUtils.DefaultReportFont;
  1591. textFill = new SolidFill(Color.Black);
  1592. textOutline = new TextOutline();
  1593. trimming = StringTrimming.None;
  1594. fontWidthRatio = 1;
  1595. tabWidth = 58;
  1596. tabPositions = new FloatCollection();
  1597. clip = true;
  1598. highlight = new ConditionCollection();
  1599. FlagSerializeStyle = false;
  1600. SetFlags(Flags.HasSmartTag, true);
  1601. preserveLastLineSpace = false;
  1602. }
  1603. }
  1604. }