FastReport

Форк
0
/
TextObject.cs 
1815 строк · 66.7 Кб
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

14
namespace FastReport
15
{
16
    /// <summary>
17
    /// Specifies the horizontal alignment of a text in the TextObject object.
18
    /// </summary>
19
    public enum HorzAlign
20
    {
21
        /// <summary>
22
        /// Specifies that text is aligned in the left of the layout rectangle.
23
        /// </summary>
24
        Left,
25

26
        /// <summary>
27
        /// Specifies that text is aligned in the center of the layout rectangle.
28
        /// </summary>
29
        Center,
30

31
        /// <summary>
32
        /// Specifies that text is aligned in the right of the layout rectangle.
33
        /// </summary>
34
        Right,
35

36
        /// <summary>
37
        /// Specifies that text is aligned in the left and right sides of the layout rectangle.
38
        /// </summary>
39
        Justify
40
    }
41

42
    /// <summary>
43
    /// Specifies the vertical alignment of a text in the TextObject object.
44
    /// </summary>
45
    public enum VertAlign
46
    {
47
        /// <summary>
48
        /// Specifies that text is aligned in the top of the layout rectangle.
49
        /// </summary>
50
        Top,
51

52
        /// <summary>
53
        /// Specifies that text is aligned in the center of the layout rectangle.
54
        /// </summary>
55
        Center,
56

57
        /// <summary>
58
        /// Specifies that text is aligned in the bottom of the layout rectangle.
59
        /// </summary>
60
        Bottom
61
    }
62

63
    /// <summary>
64
    /// The type of text renderer
65
    /// </summary>
66
    public enum TextRenderType
67
    {
68
        /// <summary>
69
        /// The default render
70
        /// </summary>
71
        Default,
72
        /// <summary>
73
        /// Render with some html tags and stable logic
74
        /// </summary>
75
        HtmlTags,
76
        /// <summary>
77
        /// Render with img tags, span etc. Experimental and unstable logic
78
        /// </summary>
79
        HtmlParagraph,
80
        /// <summary>
81
        /// Renders a text in a simplest way. For internal use only.
82
        /// </summary>
83
        Inline
84
    }
85

86
    /// <summary>
87
    /// The format of paragraph
88
    /// </summary>
89
    [TypeConverter(typeof(TypeConverters.FRExpandableObjectConverter))]
90
    public class ParagraphFormat
91
    {
92
        private float firstLineIndent;
93
        private float lineSpacing;
94
        private LineSpacingType lineSpacingType;
95
        private bool skipFirstLineIndent;
96

97
        /// <summary>
98
        /// The first line on each paragraph.
99
        /// </summary>
100
        [Browsable(true)]
101
        [DefaultValue(0f)]
102
        [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
103
        public float FirstLineIndent
104
        {
105
            get { return firstLineIndent; }
106
            set { firstLineIndent = value; }
107
        }
108

109
        /// <summary>
110
        /// The distance between lines, not effect if value less then 0
111
        /// </summary>
112
        [Browsable(true)]
113
        [DefaultValue(0f)]
114
        [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
115
        public float LineSpacing
116
        {
117
            get { return lineSpacing; }
118
            set { if (value >= 0) lineSpacing = value; }
119
        }
120

121
        /// <summary>
122
        /// The spacing type for distance between line calculation
123
        /// </summary>
124
        [Browsable(true)]
125
        [DefaultValue(LineSpacingType.Single)]
126
        public LineSpacingType LineSpacingType
127
        {
128
            get { return lineSpacingType; }
129
            set { lineSpacingType = value; }
130
        }
131

132
        /// <summary>
133
        /// The value for a multiplication line height for adding spacing
134
        /// </summary>
135
        [Browsable(true)]
136
        [DefaultValue(0f)]
137
        public float LineSpacingMultiple
138
        {
139
            get { return lineSpacing / 100f; }
140
            set { if (value >= 0) lineSpacing = value * 100f; }
141
        }
142

143
        /// <summary>
144
        /// Skip the line indent in the first paragraph, for broken paragraphs
145
        /// </summary>
146
        [Browsable(false)]
147
        [DefaultValue(false)]
148
        public bool SkipFirstLineIndent
149
        {
150
            get { return skipFirstLineIndent; }
151
            set { skipFirstLineIndent = value; }
152
        }
153

154
        /// <summary>
155
        /// clone with new scale;
156
        /// </summary>
157
        /// <param name="scale"></param>
158
        /// <returns></returns>
159
        internal ParagraphFormat MultipleScale(float scale)
160
        {
161
            ParagraphFormat clone = new ParagraphFormat();
162
            clone.lineSpacingType = lineSpacingType;
163
            if (LineSpacingType == LineSpacingType.Multiple)
164
                clone.lineSpacing = lineSpacing;
165
            else
166
                clone.lineSpacing = lineSpacing * scale;
167
            clone.firstLineIndent = firstLineIndent * scale;
168
            clone.skipFirstLineIndent = skipFirstLineIndent;
169
            return clone;
170
        }
171

172
        internal void Assign(ParagraphFormat p)
173
        {
174
            lineSpacingType = p.lineSpacingType;
175
            lineSpacing = p.lineSpacing;
176
            firstLineIndent = p.firstLineIndent;
177
            skipFirstLineIndent = p.skipFirstLineIndent;
178
        }
179

180
        public override bool Equals(object obj)
181
        {
182
            ParagraphFormat format = obj as ParagraphFormat;
183
            return format != null &&
184
                   firstLineIndent == format.firstLineIndent &&
185
                   lineSpacing == format.lineSpacing &&
186
                   lineSpacingType == format.lineSpacingType &&
187
                   skipFirstLineIndent == format.skipFirstLineIndent;
188
        }
189

190
        public override int GetHashCode()
191
        {
192
            unchecked
193
            {
194
                int hashCode = -1051315095;
195
                hashCode = hashCode * -1521134295 + firstLineIndent.GetHashCode();
196
                hashCode = hashCode * -1521134295 + lineSpacing.GetHashCode();
197
                hashCode = hashCode * -1521134295 + lineSpacingType.GetHashCode();
198
                hashCode = hashCode * -1521134295 + skipFirstLineIndent.GetHashCode();
199
                return hashCode;
200
            }
201
        }
202
    }
203

204
    /// <summary>
205
    /// The spacing type between lines
206
    /// </summary>
207
    public enum LineSpacingType
208
    {
209
        /// <summary>
210
        /// Single spacing, not effect from LineSpacing
211
        /// </summary>
212
        Single,
213
        /// <summary>
214
        /// Minimal spacing in exactly size
215
        /// </summary>
216
        AtLeast,
217
        /// <summary>
218
        /// The specific distance between the lines, for some exports, does not work if the distance value is too small.
219
        /// </summary>
220
        Exactly,
221
        /// <summary>
222
        /// The calculated distance between lines, for some exports, does not work if the distance value is too small.
223
        /// </summary>
224
        Multiple
225
    }
226

227
    /// <summary>
228
    /// Specifies the behavior of the <b>AutoShrink</b> feature of <b>TextObject</b>.
229
    /// </summary>
230
    public enum AutoShrinkMode
231
    {
232
        /// <summary>
233
        /// AutoShrink is disabled.
234
        /// </summary>
235
        None,
236

237
        /// <summary>
238
        /// AutoShrink decreases the <b>Font.Size</b> property of the <b>TextObject</b>.
239
        /// </summary>
240
        FontSize,
241

242
        /// <summary>
243
        /// AutoShrink decreases the <b>FontWidthRatio</b> property of the <b>TextObject</b>.
244
        /// </summary>
245
        FontWidth
246
    }
247

248
    /// <summary>
249
    ///  Specifies the behavior of the <b>MergeMode</b> feature of <b>TextObject</b>.
250
    /// </summary>
251
    [TypeConverter(typeof(FastReport.TypeConverters.FlagConverter))]
252
    [Flags]
253
    public enum MergeMode
254
    {
255
        /// <summary>
256
        /// Merge is disabled.
257
        /// </summary>
258
        None = 0,
259

260
        /// <summary>
261
        /// Allows horizontal merging.
262
        /// </summary>
263
        Horizontal = 1,
264

265
        /// <summary>
266
        /// Allows vertical merging.
267
        /// </summary>
268
        Vertical = 2,
269
    }
270

271
    /// <summary>
272
    /// Represents the Text object that may display one or several text lines.
273
    /// </summary>
274
    /// <remarks>
275
    /// Specify the object's text in the <see cref="TextObjectBase.Text">Text</see> property. 
276
    /// Text may contain expressions and data items, for example: "Today is [Date]". When report 
277
    /// is running, all expressions are calculated and replaced with actual values, so the text 
278
    /// would be "Today is 01.01.2008".
279
    /// <para/>The symbols used to find expressions in a text are set in the 
280
    /// <see cref="TextObjectBase.Brackets">Brackets</see> property. You also may disable expressions 
281
    /// using the <see cref="TextObjectBase.AllowExpressions">AllowExpressions</see> property.
282
    /// <para/>To format an expression value, use the <see cref="Format"/> property.
283
    /// </remarks>
284
    public partial class TextObject : TextObjectBase
285
    {
286
        #region Fields
287
        private MergeMode mergeMode;
288
        private bool autoWidth;
289
        private HorzAlign horzAlign;
290
        private VertAlign vertAlign;
291
        private int angle;
292
        private bool rightToLeft;
293
        private bool wordWrap;
294
        private bool underlines;
295
        private Font font;
296
        private FillBase textFill;
297
        private TextOutline textOutline;
298
        private StringTrimming trimming;
299
        private float fontWidthRatio;
300
        private float firstTabOffset;
301
        private float tabWidth;
302
        private FloatCollection tabPositions;
303
        private bool clip;
304
        private ConditionCollection highlight;
305
        private bool wysiwyg;
306
        private float lineHeight;
307
        private bool forceJustify;
308
        private TextRenderType textRenderType;
309
        private AutoShrinkMode autoShrink;
310
        private float autoShrinkMinSize;
311
        private float paragraphOffset;
312
        private FillBase savedTextFill;
313
        private Font savedFont;
314
        private string savedText;
315
        private FormatBase savedFormat;
316
        private InlineImageCache inlineImageCache;
317
        private ParagraphFormat paragraphFormat;
318
        #endregion
319

320
        #region Properties
321

322
        /// <summary>
323
        /// Gets or sets a paragraph format for a new html rendering type, not for others rendering
324
        /// </summary>
325
        [Category("Appearance")]
326
        public ParagraphFormat ParagraphFormat
327
        {
328
            get { return paragraphFormat; }
329
            set { paragraphFormat = value; }
330
        }
331

332
        /// <summary>
333
        /// Gets or sets a value that determines if the text object should handle its width automatically.
334
        /// </summary>
335
        [DefaultValue(false)]
336
        [Category("Behavior")]
337
        public bool AutoWidth
338
        {
339
            get { return autoWidth; }
340
            set { autoWidth = value; }
341
        }
342

343
        /// <summary>
344
        /// Gets or sets a value that indicates whether the font size should shrink to
345
        /// display the longest text line without word wrap.
346
        /// </summary>
347
        /// <remarks>
348
        /// To limit the minimum size, use the <see cref="AutoShrinkMinSize"/> property.
349
        /// </remarks>
350
        [DefaultValue(AutoShrinkMode.None)]
351
        [Category("Behavior")]
352
        public AutoShrinkMode AutoShrink
353
        {
354
            get { return autoShrink; }
355
            set { autoShrink = value; }
356
        }
357

358
        /// <summary>
359
        /// Gets or sets the minimum size of font (or minimum width ratio) if the <see cref="AutoShrink"/>
360
        /// mode is on.
361
        /// </summary>
362
        /// <remarks>
363
        /// This property determines the minimum font size (in case the <see cref="AutoShrink"/> property is set to
364
        /// <b>FontSize</b>), or the minimum font width ratio (if <b>AutoShrink</b> is set to <b>FontWidth</b>).
365
        /// <para/>The default value is 0, that means no limits.
366
        /// </remarks>
367
        [DefaultValue(0f)]
368
        [Category("Behavior")]
369
        public float AutoShrinkMinSize
370
        {
371
            get { return autoShrinkMinSize; }
372
            set { autoShrinkMinSize = value; }
373
        }
374

375
        /// <summary>
376
        /// Gets or sets the horizontal alignment of a text in the TextObject object.
377
        /// </summary>
378
        [DefaultValue(HorzAlign.Left)]
379
        [Category("Appearance")]
380
        public HorzAlign HorzAlign
381
        {
382
            get { return horzAlign; }
383
            set { horzAlign = value; }
384
        }
385

386
        /// <summary>
387
        /// Gets or sets the vertical alignment of a text in the TextObject object.
388
        /// </summary>
389
        [DefaultValue(VertAlign.Top)]
390
        [Category("Appearance")]
391
        public VertAlign VertAlign
392
        {
393
            get { return vertAlign; }
394
            set { vertAlign = value; }
395
        }
396

397
        /// <summary>
398
        /// Gets or sets the text angle, in degrees.
399
        /// </summary>
400
        [DefaultValue(0)]
401
        [Category("Appearance")]
402
        [Editor("FastReport.TypeEditors.AngleEditor, FastReport", typeof(UITypeEditor))]
403
        public int Angle
404
        {
405
            get { return angle; }
406
            set { angle = value; }
407
        }
408

409
        /// <summary>
410
        /// Gets or sets a value that indicates whether the component should draw right-to-left for RTL languages.
411
        /// </summary>
412
        [DefaultValue(false)]
413
        [Category("Behavior")]
414
        public bool RightToLeft
415
        {
416
            get { return rightToLeft; }
417
            set { rightToLeft = value; }
418
        }
419

420
        /// <summary>
421
        /// Gets or sets a value that indicates if lines are automatically word-wrapped.
422
        /// </summary>
423
        [DefaultValue(true)]
424
        [Category("Behavior")]
425
        public bool WordWrap
426
        {
427
            get { return wordWrap; }
428
            set { wordWrap = value; }
429
        }
430

431
        /// <summary>
432
        /// Gets or sets a value that determines if the text object will underline each text line.
433
        /// </summary>
434
        [DefaultValue(false)]
435
        [Category("Appearance")]
436
        public bool Underlines
437
        {
438
            get { return underlines; }
439
            set { underlines = value; }
440
        }
441

442
        /// <summary>
443
        /// Gets or sets the font settings for this object.
444
        /// </summary>
445
        [Category("Appearance")]
446
        public Font Font
447
        {
448
            get { return font; }
449
            set
450
            {
451
                font = value;
452
                if (!String.IsNullOrEmpty(Style))
453
                    Style = "";
454
            }
455
        }
456

457
        /// <summary>
458
        /// Gets or sets a collection of TAB symbol positions, in pixels. Negative values will not affect this property.
459
        /// </summary>
460
        /// <remarks>Use collection methods to add or remove TAB positions.</remarks>
461
        public FloatCollection TabPositions
462
        {
463
            get { return tabPositions; }
464
            set
465
            {
466
                if (value == null)
467
                    tabPositions.Clear();
468
                else
469
                    tabPositions = value;
470
            }
471
        }
472

473
        /// <summary>
474
        /// Gets or sets the fill color used to draw a text.
475
        /// </summary>
476
        /// <remarks>
477
        /// Default fill is <see cref="SolidFill"/>. You may specify other fill types, for example:
478
        /// <code>
479
        /// text1.TextFill = new HatchFill(Color.Black, Color.White, HatchStyle.Cross);
480
        /// </code>
481
        /// Use the <see cref="TextColor"/> property to set the solid text color.
482
        /// </remarks>
483
        [Category("Appearance")]
484
        [Editor("FastReport.TypeEditors.FillEditor, FastReport", typeof(UITypeEditor))]
485
        public FillBase TextFill
486
        {
487
            get { return textFill; }
488
            set
489
            {
490
                if (value == null)
491
                    throw new ArgumentNullException("TextFill");
492
                textFill = value;
493
                if (!String.IsNullOrEmpty(Style))
494
                    Style = "";
495
            }
496
        }
497

498
        /// <summary>
499
        /// Gets or sets the text outline.
500
        /// </summary>
501
        [Category("Appearance")]
502
        [Editor("FastReport.TypeEditors.OutlineEditor, FastReport", typeof(UITypeEditor))]
503
        public TextOutline TextOutline
504
        {
505
            get { return textOutline; }
506
            set
507
            {
508
                if (value == null)
509
                    throw new ArgumentNullException("TextOutline");
510
                textOutline = value;
511
                if (!String.IsNullOrEmpty(Style))
512
                    Style = "";
513
            }
514
        }
515

516
        /// <summary>
517
        /// Gets or sets the text color in a simple manner.
518
        /// </summary>
519
        /// <remarks>
520
        /// This property can be used in a report script to change the text color of the object. It is 
521
        /// equivalent to: <code>textObject1.TextFill = new SolidFill(color);</code>
522
        /// </remarks>
523
        [Browsable(false)]
524
        public Color TextColor
525
        {
526
            get { return TextFill is SolidFill ? (TextFill as SolidFill).Color : Color.Black; }
527
            set { TextFill = new SolidFill(value); }
528
        }
529

530
        /// <summary>
531
        /// Gets or sets the string trimming options.
532
        /// </summary>
533
        [DefaultValue(StringTrimming.None)]
534
        [Category("Behavior")]
535
        public StringTrimming Trimming
536
        {
537
            get { return trimming; }
538
            set { trimming = value; }
539
        }
540

541
        /// <summary>
542
        /// Gets or sets the width ratio of the font. 
543
        /// </summary>
544
        /// <remarks>
545
        /// Default value is 1. To make a font wider, set a value grether than 1; to make a font narrower,
546
        /// set a value less than 1.
547
        /// </remarks>
548
        [DefaultValue(1f)]
549
        [Category("Appearance")]
550
        public float FontWidthRatio
551
        {
552
            get { return fontWidthRatio; }
553
            set
554
            {
555
                if (value > 0)
556
                    fontWidthRatio = value;
557
                else
558
                    fontWidthRatio = 1;
559
            }
560
        }
561

562
        /// <summary>
563
        /// Gets or sets the height of single text line, in pixels.
564
        /// </summary>
565
        [DefaultValue(0f)]
566
        [Category("Appearance")]
567
        public float LineHeight
568
        {
569
            get { return lineHeight; }
570
            set { lineHeight = value; }
571
        }
572

573
        /// <summary>
574
        /// Gets or sets the offset of the first TAB symbol. Negative value will not affect this property.
575
        /// </summary>
576
        [DefaultValue(0f)]
577
        [Category("Appearance")]
578
        //[TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
579
        public float FirstTabOffset
580
        {
581
            get { return firstTabOffset; }
582
            set { if (value >= 0) firstTabOffset = value; }
583
        }
584

585
        /// <summary>
586
        /// Gets or sets the width of TAB symbol, in pixels. Negative values will not affect this property.
587
        /// </summary>
588
        [DefaultValue(58f)]
589
        [Category("Appearance")]
590
        public float TabWidth
591
        {
592
            get { return tabWidth; }
593
            set { if (value >= 0) tabWidth = value; }
594
        }
595

596
        /// <summary>
597
        /// Gets or sets a value that indicates if text should be clipped inside the object's bounds.
598
        /// </summary>
599
        [DefaultValue(true)]
600
        [Category("Behavior")]
601
        public bool Clip
602
        {
603
            get { return clip; }
604
            set { clip = value; }
605
        }
606

607
        /// <summary>
608
        /// Gets the collection of conditional highlight attributes.
609
        /// </summary>
610
        /// <remarks>
611
        /// Conditional highlight is used to change the visual appearance of the Text object
612
        /// depending on some condition(s). For example, you may highlight negative values displayed by
613
        /// the Text object with red color. To do this, add the highlight condition:
614
        /// <code>
615
        /// TextObject text1;
616
        /// HighlightCondition highlight = new HighlightCondition();
617
        /// highlight.Expression = "Value &lt; 0";
618
        /// highlight.Fill = new SolidFill(Color.Red);
619
        /// highlight.ApplyFill = true;
620
        /// text1.Highlight.Add(highlight);
621
        /// </code>
622
        /// </remarks>
623
        [Category("Data")]
624
        [Editor("FastReport.TypeEditors.HighlightEditor, FastReport", typeof(UITypeEditor))]
625
        public ConditionCollection Highlight
626
        {
627
            get { return highlight; }
628
        }
629

630
        /// <summary>
631
        /// Gets or sets a value that indicates if the text object should display its contents similar to the printout.
632
        /// </summary>
633
        [DefaultValue(false)]
634
        [Category("Behavior")]
635
        public bool Wysiwyg
636
        {
637
            get { return wysiwyg; }
638
            set { wysiwyg = value; }
639
        }
640

641
        /// <summary>
642
        /// Forces justify for the last text line.
643
        /// </summary>
644
        [Browsable(false)]
645
        public bool ForceJustify
646
        {
647
            get { return forceJustify; }
648
            set { forceJustify = value; }
649
        }
650

651
        /// <summary>
652
        /// Allows handling html tags in the text.
653
        /// </summary>
654
        /// <remarks>
655
        /// The following html tags can be used in the object's text: &lt;b&gt;, &lt;i&gt;, &lt;u&gt;,
656
        /// &lt;strike&gt;, &lt;sub&gt;, &lt;sup&gt;, &lt;/b&gt;, &lt;/i&gt;, &lt;/u&gt;,
657
        /// &lt;/strike&gt;, &lt;/sub&gt;, &lt;/sup&gt;,
658
        /// &lt;font color=&amp;...&amp;&gt;, &lt;/font&gt;. Font size cannot
659
        /// be changed due to limitations in the rendering engine.
660
        /// </remarks>
661
        [DefaultValue(false)]
662
        [Category("Behavior")]
663
        [Browsable(false)]
664
        [Obsolete("This method is deprecated please use TextRenderer")]
665
        public bool HtmlTags
666
        {
667
            get
668
            {
669
                return HasHtmlTags;
670
            }
671
            set { textRenderType = value ? TextRenderType.HtmlTags : TextRenderType.Default; }
672
        }
673

674
        /// <summary>
675
        /// Indicates handling html tags in the text.
676
        /// </summary>
677
        /// <remarks>To set the value use the TextRenderer property.</remarks>
678
        [DefaultValue(false)]
679
        [Category("Behavior")]
680
        [Browsable(false)]
681
        public bool HasHtmlTags
682
        {
683
            get
684
            {
685
                switch (textRenderType)
686
                {
687
                    case TextRenderType.HtmlTags:
688
                    case TextRenderType.HtmlParagraph:
689
                        return true;
690
                    default:
691
                        return false;
692
                }
693
            }
694
        }
695

696
        /// <summary>
697
        /// The type of text render
698
        /// </summary>
699
        ///     /// <remarks>
700
        /// The following html tags can be used in the object's text: &lt;b&gt;, &lt;i&gt;, &lt;u&gt;,
701
        /// &lt;strike&gt;, &lt;sub&gt;, &lt;sup&gt;, &lt;/b&gt;, &lt;/i&gt;, &lt;/u&gt;,
702
        /// &lt;/strike&gt;, &lt;/sub&gt;, &lt;/sup&gt;,
703
        /// &lt;font color=&amp;...&amp;&gt;, &lt;/font&gt;. Font size cannot
704
        /// be changed due to limitations in the rendering engine.
705
        /// </remarks>
706
        [DefaultValue(TextRenderType.Default)]
707
        [Category("Behavior")]
708
        public TextRenderType TextRenderType
709
        {
710
            get { return textRenderType; }
711
            set { textRenderType = value; }
712
        }
713

714
        /// <summary>
715
        /// Gets or sets the paragraph offset, in pixels. For HtmlParagraph use ParagraphFormat.FirstLineIndent.
716
        /// </summary>
717
        [DefaultValue(0f)]
718
        [Category("Appearance")]
719
        [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
720
        public float ParagraphOffset
721
        {
722
            get { return paragraphOffset; }
723
            set { paragraphOffset = value; }
724
        }
725

726
        internal bool IsAdvancedRendererNeeded
727
        {
728
            get { return HorzAlign == HorzAlign.Justify || Wysiwyg || LineHeight != 0 || HasHtmlTags; }
729
        }
730

731
        /// <summary>
732
        /// Cache for inline images
733
        /// </summary>
734
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
735
        public InlineImageCache InlineImageCache
736
        {
737
            get
738
            {
739
                if (inlineImageCache == null)
740
                    inlineImageCache = new InlineImageCache();
741
                return inlineImageCache;
742
            }
743
        }
744

745
        /// <summary>
746
        /// Gets or sets a value indicating whether the text should be merged with other nearby text objects.
747
        /// </summary>
748
        [DefaultValue(MergeMode.None)]
749
        [Category("Behavior")]
750
        [Editor("FastReport.TypeEditors.FlagsEditor, FastReport", typeof(UITypeEditor))]
751
        public MergeMode MergeMode
752
        {
753
            get { return mergeMode; }
754
            set { mergeMode = value; }
755
        }
756
        #endregion
757

758
        #region Private Methods
759
        private void DrawUnderlines(FRPaintEventArgs e)
760
        {
761
            if (!Underlines || Angle != 0)
762
                return;
763

764
            IGraphics g = e.Graphics;
765
            float lineHeight = LineHeight == 0 ? Font.GetHeight() * DrawUtils.ScreenDpiFX : LineHeight;
766
            lineHeight *= e.ScaleY;
767
            float curY = AbsTop * e.ScaleY + lineHeight + 1;
768
            Pen pen = e.Cache.GetPen(Border.Color, Border.Width * e.ScaleY, DashStyle.Solid);
769
            while (curY < AbsBottom * e.ScaleY)
770
            {
771
                g.DrawLine(pen, AbsLeft * e.ScaleX, curY, AbsRight * e.ScaleY, curY);
772
                curY += lineHeight;
773
            }
774
        }
775

776
        private SizeF CalcSize()
777
        {
778
            Report report = Report;
779
            if (String.IsNullOrEmpty(Text) || report == null)
780
                return new SizeF(0, 0);
781

782
            Font font = report.GraphicCache.GetFont(Font.FontFamily, Font.Size * 96f / DrawUtils.ScreenDpi, Font.Style);
783
            float width = 0;
784
            if (WordWrap)
785
            {
786
                if (Angle == 90 || Angle == 270)
787
                    width = Height - Padding.Vertical;
788
                else
789
                    width = Width - Padding.Horizontal;
790
            }
791

792
            IGraphics g = report.MeasureGraphics;
793
            IGraphicsState state = g.Save();
794
            try
795
            {
796
                if (report.TextQuality != TextQuality.Default)
797
                    g.TextRenderingHint = report.GetTextQuality();
798
                if (TextRenderType == TextRenderType.HtmlParagraph)
799
                {
800
                    if (width == 0)
801
                        width = 100000;
802

803
                    using (HtmlTextRenderer htmlRenderer = GetHtmlTextRenderer(g, new RectangleF(0, 0, width, 100000), 1, 1))
804
                    {
805
                        float height = htmlRenderer.CalcHeight();
806
                        width = htmlRenderer.CalcWidth();
807

808
                        width += Padding.Horizontal + 1;
809
                        height += Padding.Vertical + 1;
810

811
                        return new SizeF(width, height);
812
                    }
813
                }
814
#if CROSSPLATFORM && !SKIA
815
                // in FR.Core we use AdvancedTextRenderer only if needed (IsAdvancedRendererNeeded) or if it's not Windows
816
                if (IsAdvancedRendererNeeded || !Config.IsWindows)
817
#else
818
                if (IsAdvancedRendererNeeded)
819
#endif
820
                {
821
                    if (width == 0)
822
                        width = 100000;
823
                    AdvancedTextRenderer renderer = new AdvancedTextRenderer(Text, g, font, Brushes.Black, Pens.Black,
824
                        new RectangleF(0, 0, width, 100000), GetStringFormat(report.GraphicCache, 0),
825
                        HorzAlign, VertAlign, LineHeight, Angle, FontWidthRatio, false, Wysiwyg, HasHtmlTags, false, 96f / DrawUtils.ScreenDpi,
826
                        96f / DrawUtils.ScreenDpi, InlineImageCache);
827
                    float height = renderer.CalcHeight();
828
                    width = renderer.CalcWidth();
829

830
                    width += Padding.Horizontal + 1;
831
                    height += Padding.Vertical + 1;
832
                    return new SizeF(width, height);
833
                }
834
                else
835
                {
836
                    if (FontWidthRatio != 1)
837
                        width /= FontWidthRatio;
838
                    SizeF size = g.MeasureString(Text, font, new SizeF(width, 100000));
839
                    size.Width += Padding.Horizontal + 1;
840
                    size.Height += Padding.Vertical + 1;
841
                    return size;
842
                }
843
            }
844
            finally
845
            {
846
                g.Restore(state);
847
            }
848
        }
849

850
        private float InternalCalcWidth()
851
        {
852
            bool saveWordWrap = WordWrap;
853
            WordWrap = false;
854
            float result = 0;
855

856
            try
857
            {
858
                SizeF size = CalcSize();
859
                result = size.Width;
860
            }
861
            finally
862
            {
863
                WordWrap = saveWordWrap;
864
            }
865

866
            return result;
867
        }
868

869
        private float InternalCalcHeight()
870
        {
871
            return CalcSize().Height;
872
        }
873

874
        private string BreakTextHtml(out bool endOnEnter)
875
        {
876
            endOnEnter = false;
877
            ForceJustify = false;
878
            if (String.IsNullOrEmpty(Text))
879
                return "";
880
            string result = null;
881
            Report report = Report;
882
            if (report == null)
883
                return "";
884

885

886
            StringFormat format = GetStringFormat(report.GraphicCache, StringFormatFlags.LineLimit);
887
            RectangleF textRect = new RectangleF(0, 0, Width - Padding.Horizontal, Height - Padding.Vertical);
888

889
            if (textRect.Height <= 0)
890
                return result;
891

892
            int charactersFitted;
893
            IGraphics g = report.MeasureGraphics;
894
            IGraphicsState state = g.Save();
895

896
            if (report.TextQuality != TextQuality.Default)
897
                g.TextRenderingHint = report.GetTextQuality();
898

899
            try
900
            {
901
                using (HtmlTextRenderer htmlRenderer = GetHtmlTextRenderer(g, 1, 1, textRect, format))
902
                {
903
                    htmlRenderer.CalcHeight(out charactersFitted);
904
                    if (charactersFitted == 0)
905
                        return null;
906

907
                    Text = HtmlTextRenderer.BreakHtml(Text, charactersFitted, out result, out endOnEnter);
908

909
                    if (HorzAlign == HorzAlign.Justify && !endOnEnter && result != "")
910
                    {
911
                        if (Text.EndsWith(" "))
912
                            Text = Text.TrimEnd(' ');
913
                        ForceJustify = true;
914
                    }
915
                }
916
            }
917
            finally
918
            {
919
                g.Restore(state);
920
            }
921

922
            return result;
923
        }
924

925
        private string BreakText()
926
        {
927
            ForceJustify = false;
928
            if (String.IsNullOrEmpty(Text))
929
                return "";
930

931
            string result = null;
932
            Report report = Report;
933
            if (report == null)
934
                return "";
935

936
            Font font = report.GraphicCache.GetFont(Font.FontFamily, Font.Size * 96f / DrawUtils.ScreenDpi, Font.Style);
937
            StringFormat format = GetStringFormat(report.GraphicCache, StringFormatFlags.LineLimit);
938
            RectangleF textRect = new RectangleF(0, 0, Width - Padding.Horizontal, Height - Padding.Vertical);
939
            if (textRect.Height < 0)
940
                return null;
941

942
            int charactersFitted;
943
            int linesFilled;
944

945
            IGraphics g = report.MeasureGraphics;
946
            IGraphicsState state = g.Save();
947
            try
948
            {
949
                if (report.TextQuality != TextQuality.Default)
950
                    g.TextRenderingHint = report.GetTextQuality();
951

952
                AdvancedTextRenderer.StyleDescriptor htmlStyle = null;
953

954
                if (IsAdvancedRendererNeeded)
955
                {
956
                    AdvancedTextRenderer renderer = new AdvancedTextRenderer(Text, g, font, Brushes.Black, Pens.Black,
957
                      textRect, format, HorzAlign, VertAlign, LineHeight, Angle, FontWidthRatio, false, Wysiwyg, HasHtmlTags, false, 96f / DrawUtils.ScreenDpi,
958
                       96f / DrawUtils.ScreenDpi, InlineImageCache);
959
                    renderer.CalcHeight(out charactersFitted, out htmlStyle);
960

961
                    if (charactersFitted == 0)
962
                        linesFilled = 0;
963
                    else
964
                        linesFilled = 2;
965
                }
966
                else
967
                {
968
                    g.MeasureString(Text, font, textRect.Size, format, out charactersFitted, out linesFilled);
969
                }
970

971

972
                if (linesFilled == 0)
973
                    return null;
974
                if (linesFilled == 1)
975
                {
976
                    // check if there is enough space for one line
977
                    float lineHeight = g.MeasureString("Wg", font).Height;
978
                    if (textRect.Height < lineHeight)
979
                        return null;
980
                }
981

982
                if (charactersFitted < Text.Length)
983
                    result = Text.Substring(charactersFitted);
984
                else
985
                    result = "";
986

987
                Text = Text.Substring(0, charactersFitted);
988

989

990
                if (HorzAlign == HorzAlign.Justify && !Text.EndsWith("\n") && result != "")
991
                {
992
                    if (Text.EndsWith(" "))
993
                        Text = Text.Substring(0, Text.Length - 1);
994
                    ForceJustify = true;
995
                }
996
                if (HasHtmlTags && htmlStyle != null && result != "")
997
                    result = htmlStyle.ToString() + result;
998
            }
999
            finally
1000
            {
1001
                g.Restore(state);
1002
            }
1003

1004
            return result;
1005
        }
1006

1007
        private void ProcessAutoShrink()
1008
        {
1009
            if (TextRenderType == TextRenderType.HtmlParagraph)
1010
                return;
1011
            if (String.IsNullOrEmpty(Text))
1012
                return;
1013

1014
            if (AutoShrink == AutoShrinkMode.FontSize)
1015
            {
1016
                while (CalcWidth() > Width - 1 && Font.Size > AutoShrinkMinSize && Font.Size > 1)
1017
                {
1018
                    Font = new Font(Font.FontFamily, Font.Size - 1, Font.Style);
1019
                }
1020
            }
1021
            else if (AutoShrink == AutoShrinkMode.FontWidth)
1022
            {
1023
                FontWidthRatio = 1;
1024
                float ratio = Converter.DecreasePrecision((Width - 1) / CalcWidth(), 2) - 0.01f;
1025
                if (ratio < 1)
1026
                    FontWidthRatio = Math.Max(ratio, AutoShrinkMinSize);
1027
            }
1028
        }
1029

1030
        private string MakeParagraphOffset(string text)
1031
        {
1032
            // fixed issue 2823
1033
            FirstTabOffset = ParagraphOffset;
1034
            string[] lines = text.Split('\n');
1035
            for (int i = 0; i < lines.Length; i++)
1036
            {
1037
                if (!lines[i].StartsWith("\t"))
1038
                    lines[i] = "\t" + lines[i];
1039
            }
1040
            return String.Join("\n", lines);
1041
        }
1042

1043

1044
        #endregion
1045

1046
        #region Protected Methods
1047
        /// <inheritdoc/>
1048
        protected override void DeserializeSubItems(FRReader reader)
1049
        {
1050
            if (String.Compare(reader.ItemName, "Highlight", true) == 0)
1051
                reader.Read(Highlight);
1052
            else
1053
                base.DeserializeSubItems(reader);
1054
        }
1055
        #endregion
1056

1057
        #region Public Methods
1058
        /// <summary>
1059
        /// Returns StringFormat object.
1060
        /// </summary>
1061
        /// <param name="cache">Report graphic cache.</param>
1062
        /// <param name="flags">StringFormat flags.</param>
1063
        /// <returns>StringFormat object.</returns>
1064
        public StringFormat GetStringFormat(GraphicCache cache, StringFormatFlags flags)
1065
        {
1066
            return GetStringFormat(cache, flags, 1);
1067
        }
1068

1069
        internal StringFormat GetStringFormat(GraphicCache cache, StringFormatFlags flags, float scale)
1070
        {
1071
            StringAlignment align = StringAlignment.Near;
1072
            if (HorzAlign == HorzAlign.Center)
1073
                align = StringAlignment.Center;
1074
            else if (HorzAlign == HorzAlign.Right)
1075
                align = StringAlignment.Far;
1076

1077
            StringAlignment lineAlign = StringAlignment.Near;
1078
            if (VertAlign == VertAlign.Center)
1079
                lineAlign = StringAlignment.Center;
1080
            else if (VertAlign == VertAlign.Bottom)
1081
                lineAlign = StringAlignment.Far;
1082

1083
            if (RightToLeft)
1084
                flags |= StringFormatFlags.DirectionRightToLeft;
1085
            if (!WordWrap)
1086
                flags |= StringFormatFlags.NoWrap;
1087
            if (!Clip)
1088
                flags |= StringFormatFlags.NoClip;
1089
            if (TabPositions.Count > 0)
1090
            {
1091
                FloatCollection tabPositions = new FloatCollection();
1092
                foreach (var i in TabPositions)
1093
                    tabPositions.Add((float)i * scale);
1094
                return cache.GetStringFormat(align, lineAlign, Trimming, flags, firstTabOffset * scale, tabPositions,
1095
                    48 * scale);
1096
            }
1097
            return cache.GetStringFormat(align, lineAlign, Trimming, flags, firstTabOffset * scale, tabWidth * scale);
1098
        }
1099

1100
        /// <inheritdoc/>
1101
        public override void Assign(Base source)
1102
        {
1103
            base.Assign(source);
1104

1105
            TextObject src = source as TextObject;
1106
            AutoWidth = src.AutoWidth;
1107
            HorzAlign = src.HorzAlign;
1108
            VertAlign = src.VertAlign;
1109
            Angle = src.Angle;
1110
            RightToLeft = src.RightToLeft;
1111
            WordWrap = src.WordWrap;
1112
            Underlines = src.Underlines;
1113
            Font = src.Font;
1114
            TextFill = src.TextFill.Clone();
1115
            TextOutline.Assign(src.TextOutline);
1116
            Trimming = src.Trimming;
1117
            FontWidthRatio = src.FontWidthRatio;
1118
            FirstTabOffset = src.FirstTabOffset;
1119
            TabWidth = src.TabWidth;
1120
            TabPositions.Assign(src.TabPositions);
1121
            Clip = src.Clip;
1122
            Highlight.Assign(src.Highlight);
1123
            Wysiwyg = src.Wysiwyg;
1124
            LineHeight = src.LineHeight;
1125
            TextRenderType = src.TextRenderType;
1126
            AutoShrink = src.AutoShrink;
1127
            AutoShrinkMinSize = src.AutoShrinkMinSize;
1128
            ParagraphOffset = src.ParagraphOffset;
1129
            inlineImageCache = src.inlineImageCache;
1130
            paragraphFormat.Assign(src.paragraphFormat);
1131
            MergeMode = src.MergeMode;
1132
        }
1133

1134
        /// <summary>
1135
        /// Returns an instance of html text renderer.
1136
        /// </summary>
1137
        /// <param name="scale">Scale ratio.</param>
1138
        /// <param name="fontScale">Font scale ratio.</param>
1139
        /// <returns>The html text renderer.</returns>
1140
        public HtmlTextRenderer GetHtmlTextRenderer(float scale, float fontScale)
1141
        {
1142
            return GetHtmlTextRenderer(Report.MeasureGraphics, scale, fontScale);
1143
        }
1144

1145
        internal HtmlTextRenderer GetHtmlTextRenderer(IGraphics g, float scale, float fontScale)
1146
        {
1147
            StringFormat format = GetStringFormat(Report.GraphicCache, 0, scale);
1148
            RectangleF textRect = new RectangleF(
1149
                (AbsLeft + Padding.Left) * scale,
1150
                (AbsTop + Padding.Top) * scale,
1151
                (Width - Padding.Horizontal) * scale,
1152
                (Height - Padding.Vertical) * scale);
1153
            return GetHtmlTextRenderer(g, scale, fontScale, textRect, format);
1154

1155
        }
1156

1157
        internal HtmlTextRenderer GetHtmlTextRenderer(IGraphics g, RectangleF textRect, float scale, float fontScale)
1158
        {
1159
            StringFormat format = GetStringFormat(Report.GraphicCache, 0, fontScale);
1160
            return GetHtmlTextRenderer(g, scale, fontScale, textRect, format);
1161
        }
1162

1163
        internal HtmlTextRenderer GetHtmlTextRenderer(IGraphics g, float scale, float fontScale, RectangleF textRect, StringFormat format)
1164
        {
1165
            return GetHtmlTextRenderer(Text, g, fontScale, scale, fontScale, textRect, format, false);
1166
        }
1167

1168
        internal HtmlTextRenderer GetHtmlTextRenderer(string text, IGraphics g, float formatScale, float scale, float fontScale,
1169
            RectangleF textRect, StringFormat format, bool isPrinting)
1170
        {
1171
#if true
1172
            HtmlTextRenderer.RendererContext context;
1173
            context.angle = angle;
1174
            context.widthRatio = FontWidthRatio;
1175
            context.text = text;
1176
            context.g = g;
1177
            context.font = font.FontFamily;
1178
            context.size = font.Size;
1179
            context.style = font.Style; // no keep
1180
            context.color = TextColor; // no keep
1181
            context.underlineColor = textOutline.Color;
1182
            context.rect = textRect;
1183
            context.underlines = Underlines;
1184
            context.format = format; // no keep
1185
            context.horzAlign = horzAlign;
1186
            context.vertAlign = vertAlign;
1187
            context.paragraphFormat = ParagraphFormat.MultipleScale(formatScale);
1188
            context.forceJustify = ForceJustify;
1189
            context.scale = scale * 96f / DrawUtils.ScreenDpi;
1190
            context.fontScale = fontScale * 96f / DrawUtils.ScreenDpi;
1191
            context.cache = InlineImageCache;
1192
            context.isPrinting = isPrinting;
1193
            context.isDifferentTabPositions = TabPositions.Count > 0;
1194
            context.keepLastLineSpace = false;
1195
            return new HtmlTextRenderer(context);
1196
#else
1197
            bool isDifferentTabPositions = TabPositions.Count > 0;
1198
            return new HtmlTextRenderer(text, g, font.FontFamily, font.Size, font.Style, TextColor,
1199
                      textOutline.Color, textRect, Underlines,
1200
                      format, horzAlign, vertAlign, ParagraphFormat.MultipleScale(formatScale), ForceJustify,
1201
                      scale * 96f / DrawUtils.ScreenDpi, fontScale * 96f / DrawUtils.ScreenDpi, InlineImageCache,
1202
                      isPrinting, isDifferentTabPositions);
1203
#endif
1204
        }
1205

1206
        /// <summary>
1207
        /// Draws a text.
1208
        /// </summary>
1209
        /// <param name="e">Paint event data.</param>
1210
        public void DrawText(FRPaintEventArgs e)
1211
        {
1212
            string text = GetDisplayText();
1213
            if (!String.IsNullOrEmpty(text))
1214
            {
1215
                IGraphics g = e.Graphics;
1216
                RectangleF textRect = new RectangleF(
1217
                  (AbsLeft + Padding.Left) * e.ScaleX,
1218
                  (AbsTop + Padding.Top) * e.ScaleY,
1219
                  (Width - Padding.Horizontal) * e.ScaleX,
1220
                  (Height - Padding.Vertical) * e.ScaleY);
1221

1222
                if (ParagraphOffset != 0 && IsDesigning)
1223
                    text = MakeParagraphOffset(text);
1224
                StringFormat format = GetStringFormat(e.Cache, 0, e.ScaleX);
1225

1226
                Font font = e.Cache.GetFont(Font.FontFamily,
1227
                  IsPrinting ? Font.Size : Font.Size * e.ScaleX * 96f / DrawUtils.ScreenDpi,
1228
                  Font.Style);
1229

1230
                Brush textBrush = null;
1231
                if (TextFill is SolidFill)
1232
                    textBrush = e.Cache.GetBrush((TextFill as SolidFill).Color);
1233
                else
1234
                    textBrush = TextFill.CreateBrush(textRect, e.ScaleX, e.ScaleY);
1235

1236
                Pen outlinePen = null;
1237
                if (textOutline.Enabled)
1238
                    outlinePen = e.Cache.GetPen(textOutline.Color, textOutline.Width * e.ScaleX, textOutline.Style);
1239

1240
                Report report = Report;
1241
                if (report != null && report.TextQuality != TextQuality.Default)
1242
                    g.TextRenderingHint = report.GetTextQuality();
1243

1244
                if (textRect.Width > 0 && textRect.Height > 0)
1245
                {
1246
                    switch (TextRenderType)
1247
                    {
1248
                        case TextRenderType.Inline:
1249
                            g.DrawString(text, font, textBrush, textRect.X, textRect.Y, StringFormat.GenericTypographic);
1250
                            break;
1251
                        case TextRenderType.HtmlParagraph:
1252
                            try
1253
                            {
1254
                                using (HtmlTextRenderer htmlRenderer = GetHtmlTextRenderer(text, e.Graphics, e.ScaleX,
1255
                                    IsPrinting ? 1 : e.ScaleX, IsPrinting ? 1 / (96f / DrawUtils.ScreenDpi) : e.ScaleX, textRect, format, IsPrinting))
1256
                                {
1257
                                    htmlRenderer.Draw();
1258
                                }
1259
                            }
1260
                            catch
1261
                            {
1262
                                textBrush.Dispose();
1263
                                textBrush = null;
1264
                            }
1265
                            break;
1266
                        default:
1267
                            if (IsAdvancedRendererNeeded)
1268
                            {
1269
                                // use advanced rendering
1270
                                AdvancedTextRenderer advancedRenderer = new AdvancedTextRenderer(text, g, font, textBrush,
1271
                                    outlinePen, textRect, format, HorzAlign, VertAlign, LineHeight * e.ScaleY, Angle,
1272
                                    FontWidthRatio, ForceJustify, Wysiwyg, HasHtmlTags, false,
1273
                                    e.ScaleX * 96f / DrawUtils.ScreenDpi,
1274
                                    IsPrinting ? 1 : e.ScaleX * 96f / DrawUtils.ScreenDpi, InlineImageCache, IsPrinting);
1275
                                advancedRenderer.Draw();
1276
                            }
1277
                            else
1278
                            {
1279
                                // use simple rendering
1280
                                if (Angle == 0 && FontWidthRatio == 1)
1281
                                {
1282
                                    if (outlinePen == null)
1283
                                    {
1284
                                        if (WordWrap)
1285
                                            format.Trimming = StringTrimming.Word;
1286

1287
                                        g.DrawString(text, font, textBrush, textRect, format);
1288
                                    }
1289
                                    else
1290
                                    {
1291
                                        GraphicsPath path = new GraphicsPath();
1292
                                        path.AddString(text, font.FontFamily, Convert.ToInt32(font.Style),
1293
                                            g.DpiY * font.Size / 72, textRect, format);
1294

1295
                                        IGraphicsState state = g.Save();
1296
                                        g.SetClip(textRect);
1297
                                        //g.FillPath(textBrush, path);
1298

1299
                                        //regime for text output with drawbehind 
1300
                                        if (TextOutline.DrawBehind)
1301
                                        {
1302
                                            g.DrawPath(outlinePen, path);
1303
                                            g.FillPath(textBrush, path);
1304
                                        }
1305
                                        else //without. default
1306
                                        {
1307
                                            g.FillAndDrawPath(outlinePen, textBrush, path);
1308
                                        }
1309
                                        g.Restore(state);
1310

1311
                                    }
1312
                                }
1313
                                else
1314
                                    StandardTextRenderer.Draw(text, g, font, textBrush, outlinePen, textRect, format, Angle,
1315
                                        FontWidthRatio);
1316

1317
                            }
1318
                            DrawUnderlines(e);
1319
                            break;
1320
                    }
1321

1322
                }
1323
                if (!(TextFill is SolidFill))
1324
                {
1325
                    textBrush.Dispose();
1326
                }
1327
            }
1328
        }
1329

1330

1331
        /// <inheritdoc/>
1332
        public override void Draw(FRPaintEventArgs e)
1333
        {
1334
            base.Draw(e);
1335
            DrawText(e);
1336
            DrawMarkers(e);
1337
            Border.Draw(e, new RectangleF(AbsLeft, AbsTop, Width, Height));
1338
            DrawDesign(e);
1339
        }
1340

1341
        /// <inheritdoc/>
1342
        public override void ApplyStyle(Style style)
1343
        {
1344
            if (style.ApplyTextFill)
1345
                TextFill = style.TextFill.Clone();
1346
            if (style.ApplyFont)
1347
                Font = style.Font;
1348
            base.ApplyStyle(style);
1349
        }
1350

1351
        /// <inheritdoc/>
1352
        public override void SaveStyle()
1353
        {
1354
            base.SaveStyle();
1355
            savedTextFill = TextFill;
1356
            savedFont = Font;
1357
        }
1358

1359
        /// <inheritdoc/>
1360
        public override void RestoreStyle()
1361
        {
1362
            base.RestoreStyle();
1363
            TextFill = savedTextFill;
1364
            Font = savedFont;
1365
        }
1366

1367
        /// <inheritdoc/>
1368
        public override void Serialize(FRWriter writer)
1369
        {
1370
            if (writer.SerializeTo == SerializeTo.Preview && AutoWidth)
1371
            {
1372
                WordWrap = false;
1373
                float width = CalcSize().Width;
1374
                if ((Anchor & AnchorStyles.Right) != 0 || HorzAlign == HorzAlign.Right)
1375
                    Left = Right - width;
1376
                if (HorzAlign == HorzAlign.Center)
1377
                    Left += Width / 2 - width / 2;
1378
                Width = width;
1379
            }
1380
            TextObject c = writer.DiffObject as TextObject;
1381
            base.Serialize(writer);
1382

1383
            if (c == null)
1384
                return; // RichObject here
1385

1386
            if (AutoWidth != c.AutoWidth)
1387
                writer.WriteBool("AutoWidth", AutoWidth);
1388
            if (AutoShrink != c.AutoShrink)
1389
                writer.WriteValue("AutoShrink", AutoShrink);
1390
            if (FloatDiff(AutoShrinkMinSize, c.AutoShrinkMinSize))
1391
                writer.WriteFloat("AutoShrinkMinSize", AutoShrinkMinSize);
1392
            if (HorzAlign != c.HorzAlign)
1393
                writer.WriteValue("HorzAlign", HorzAlign);
1394
            if (VertAlign != c.VertAlign)
1395
                writer.WriteValue("VertAlign", VertAlign);
1396
            if (Angle != c.Angle)
1397
                writer.WriteInt("Angle", Angle);
1398
            if (RightToLeft != c.RightToLeft)
1399
                writer.WriteBool("RightToLeft", RightToLeft);
1400
            if (WordWrap != c.WordWrap)
1401
                writer.WriteBool("WordWrap", WordWrap);
1402
            if (Underlines != c.Underlines)
1403
                writer.WriteBool("Underlines", Underlines);
1404
            if ((writer.SerializeTo != SerializeTo.Preview || !Font.Equals(c.Font)) && writer.ItemName != "inherited")
1405
                writer.WriteValue("Font", Font);
1406
            TextFill.Serialize(writer, "TextFill", c.TextFill);
1407
            if (TextOutline != null)
1408
                TextOutline.Serialize(writer, "TextOutline", c.TextOutline);
1409
            if (Trimming != c.Trimming)
1410
                writer.WriteValue("Trimming", Trimming);
1411
            if (FontWidthRatio != c.FontWidthRatio)
1412
                writer.WriteFloat("FontWidthRatio", FontWidthRatio);
1413
            if (FirstTabOffset != c.FirstTabOffset)
1414
                writer.WriteFloat("FirstTabOffset", FirstTabOffset);
1415
            if (TabWidth != c.TabWidth)
1416
                writer.WriteFloat("TabWidth", TabWidth);
1417
            if (TabPositions.Count > 0)
1418
                writer.WriteValue("TabPositions", TabPositions);
1419
            if (Clip != c.Clip)
1420
                writer.WriteBool("Clip", Clip);
1421
            if (Wysiwyg != c.Wysiwyg)
1422
                writer.WriteBool("Wysiwyg", Wysiwyg);
1423
            if (LineHeight != c.LineHeight)
1424
                writer.WriteFloat("LineHeight", LineHeight);
1425
            if (TextRenderType != c.TextRenderType)
1426
                writer.WriteValue("TextRenderType", TextRenderType);
1427
            if (ParagraphOffset != c.ParagraphOffset)
1428
                writer.WriteFloat("ParagraphOffset", ParagraphOffset);
1429
            if (ForceJustify != c.ForceJustify)
1430
                writer.WriteBool("ForceJustify", ForceJustify);
1431
            if (MergeMode != c.MergeMode)
1432
                writer.WriteValue("MergeMode", MergeMode);
1433
            if (writer.SerializeTo != SerializeTo.Preview)
1434
            {
1435
                if (Style != c.Style)
1436
                    writer.WriteStr("Style", Style);
1437
                if (Highlight.Count > 0)
1438
                    writer.Write(Highlight);
1439
            }
1440

1441
            if (ParagraphFormat.FirstLineIndent != 0)
1442
                writer.WriteFloat("ParagraphFormat.FirstLineIndent", ParagraphFormat.FirstLineIndent);
1443
            if (ParagraphFormat.LineSpacing > 0)
1444
                writer.WriteFloat("ParagraphFormat.LineSpacing", ParagraphFormat.LineSpacing);
1445
            if (ParagraphFormat.LineSpacingType != LineSpacingType.Single)
1446
                writer.WriteValue("ParagraphFormat.LineSpacingType", ParagraphFormat.LineSpacingType);
1447
            if (ParagraphFormat.SkipFirstLineIndent)
1448
                writer.WriteBool("ParagraphFormat.SkipFirstLineIndent", ParagraphFormat.SkipFirstLineIndent);
1449

1450
            StringBuilder sb = null;
1451

1452
            if (InlineImageCache != null && writer.BlobStore != null && HasHtmlTags == true)
1453
                foreach (InlineImageCache.CacheItem item in InlineImageCache.AllItems())
1454
                {
1455

1456
                    if (item.Src.StartsWith("data:")) continue;
1457
                    if (sb == null)
1458
                        sb = new StringBuilder();
1459
                    sb.Append(writer.BlobStore.AddOrUpdate(item.Stream, item.Src))
1460
                      .Append(',');
1461
                }
1462
            if (sb != null)
1463
            {
1464
                sb.Length--;
1465
                writer.WriteStr("InlineImageCacheIndexes", sb.ToString());
1466
            }
1467
        }
1468

1469

1470
        /// <inheritdoc/>
1471
        public override void Deserialize(FRReader reader)
1472
        {
1473
            base.Deserialize(reader);
1474
            TextFill.Deserialize(reader, "TextFill");
1475
            if (reader.BlobStore != null)
1476
            {
1477
                string indexes = reader.ReadStr("InlineImageCacheIndexes");
1478
                if (indexes != "null" && !String.IsNullOrEmpty(indexes))
1479
                {
1480
                    string[] arr = indexes.Split(',');
1481
                    foreach (string index in arr)
1482
                    {
1483
                        int val = 0;
1484
                        if (Int32.TryParse(index, out val))
1485
                        {
1486
                            if (val >= 0 && val < reader.BlobStore.Count)
1487
                            {
1488
                                InlineImageCache.CacheItem it = new InlineImageCache.CacheItem();
1489
                                it.Set(reader.BlobStore.Get(val));
1490
                                InlineImageCache.Set(reader.BlobStore.GetSource(val), it);
1491
                            }
1492
                        }
1493
                    }
1494
                }
1495
            }
1496
            switch (reader.DeserializeFrom)
1497
            {
1498
                case SerializeTo.Undo:
1499
                case SerializeTo.Preview:
1500
                case SerializeTo.Clipboard:
1501
                    // skip
1502
                    break;
1503
                default:
1504
                    if (!reader.HasProperty("Font") && reader.ItemName != "inherited")
1505
                    {
1506
                        string creatorVersion = reader.Root.GetProp("ReportInfo.CreatorVersion");
1507
                        if (!String.IsNullOrEmpty(creatorVersion))
1508
                        {
1509
                            try
1510
                            {
1511
                                string[] versions = creatorVersion.Split('.');
1512
                                int major = 0;
1513
                                if (Int32.TryParse(versions[0], out major))
1514
                                {
1515
                                    if (major < 2016)
1516
                                    {
1517
                                        Font = new Font("Arial", 10);
1518
                                    }
1519
                                }
1520
                            }
1521
                            catch
1522
                            {
1523

1524
                            }
1525
                        }
1526
                    }
1527
                    break;
1528
            }
1529
        }
1530

1531
        public override void InitializeComponent()
1532
        {
1533
            base.InitializeComponent();
1534
            TextFill.InitializeComponent();
1535
        }
1536

1537
        public override void FinalizeComponent()
1538
        {
1539
            base.FinalizeComponent();
1540
            TextFill.FinalizeComponent();
1541
        }
1542

1543
        internal void ApplyCondition(HighlightCondition c)
1544
        {
1545
            if (c.ApplyBorder)
1546
                Border = c.Border.Clone();
1547
            if (c.ApplyFill)
1548
                Fill = c.Fill.Clone();
1549
            if (c.ApplyTextFill)
1550
                TextFill = c.TextFill.Clone();
1551
            if (c.ApplyFont)
1552
                Font = c.Font;
1553

1554
            Visible = c.Visible;
1555
        }
1556

1557
        #endregion
1558

1559
        #region Report Engine
1560
        /// <inheritdoc/>
1561
        public override string[] GetExpressions()
1562
        {
1563
            List<string> expressions = new List<string>();
1564
            expressions.AddRange(base.GetExpressions());
1565

1566
            if (AllowExpressions && !String.IsNullOrEmpty(Brackets))
1567
            {
1568
                string[] brackets = Brackets.Split(',');
1569
                // collect expressions found in the text
1570
                expressions.AddRange(CodeUtils.GetExpressions(Text, brackets[0], brackets[1]));
1571
            }
1572

1573
            // add highlight conditions
1574
            foreach (HighlightCondition condition in Highlight)
1575
            {
1576
                expressions.Add(condition.Expression);
1577
            }
1578

1579
            return expressions.ToArray();
1580
        }
1581

1582
        /// <inheritdoc/>
1583
        public override void SaveState()
1584
        {
1585
            base.SaveState();
1586
            savedText = Text;
1587
            savedTextFill = TextFill;
1588
            savedFont = Font;
1589
            savedFormat = Format;
1590

1591
        }
1592

1593
        /// <inheritdoc/>
1594
        public override void RestoreState()
1595
        {
1596
            base.RestoreState();
1597
            Text = savedText;
1598
            TextFill = savedTextFill;
1599
            Font = savedFont;
1600
            Format = savedFormat;
1601
        }
1602

1603
        /// <summary>
1604
        /// Calculates the object's width.
1605
        /// </summary>
1606
        /// <returns>The width, in pixels.</returns>
1607
        public float CalcWidth()
1608
        {
1609
            if (Angle == 90 || Angle == 270)
1610
                return InternalCalcHeight();
1611
            return InternalCalcWidth();
1612
        }
1613

1614
        /// <inheritdoc/>
1615
        public override float CalcHeight()
1616
        {
1617
            if (Angle == 90 || Angle == 270)
1618
                return InternalCalcWidth();
1619
            return InternalCalcHeight();
1620
        }
1621

1622
        /// <inheritdoc/>
1623
        public override void GetData()
1624
        {
1625
            base.GetData();
1626

1627
            // process expressions
1628
            if (AllowExpressions)
1629
            {
1630
                if (!String.IsNullOrEmpty(Brackets))
1631
                {
1632
                    string[] brackets = Brackets.Split(',');
1633
                    FindTextArgs args = new FindTextArgs();
1634
                    args.Text = new FastString(Text);
1635
                    args.OpenBracket = brackets[0];
1636
                    args.CloseBracket = brackets[1];
1637
                    int expressionIndex = 0;
1638
                    while (args.StartIndex < args.Text.Length)
1639
                    {
1640
                        string expression = CodeUtils.GetExpression(args, false);
1641
                        if (expression == null)
1642
                            break;
1643

1644
                        //if (!Report.IsCompileNeeded)
1645
                        //{
1646
                        //    expression = Text;
1647
                        //}
1648

1649
                        string formattedValue = CalcAndFormatExpression(expression, expressionIndex);
1650

1651
                        args.Text.Remove(args.StartIndex, args.EndIndex - args.StartIndex);
1652
                        args.Text.Insert(args.StartIndex, formattedValue);
1653

1654
                        args.StartIndex += formattedValue.Length;
1655
                        expressionIndex++;
1656
                    }
1657
                    Text = args.Text.ToString();
1658
                }
1659
            }
1660

1661
            // process highlight
1662
            Variant varValue = new Variant(Value);
1663
            foreach (HighlightCondition condition in Highlight)
1664
            {
1665
                try
1666
                {
1667
                    object val = Report.Calc(condition.Expression, varValue);
1668
                    if (val != null && (bool)val == true)
1669
                    {
1670
                        ApplyCondition(condition);
1671
                        break;
1672
                    }
1673
                }
1674
                catch (Exception e)
1675
                {
1676
                    throw new Exception(Name + ": " + Res.Get("Messages,ErrorInHighlightCondition") + ": " + condition.Expression, e.InnerException);
1677
                }
1678
            }
1679

1680
            // make paragraph offset
1681
            if (ParagraphOffset != 0)
1682
                Text = MakeParagraphOffset(Text);
1683
            // process AutoShrink
1684
            ProcessAutoShrink();
1685
        }
1686

1687
        /// <inheritdoc/>
1688
        public override bool Break(BreakableComponent breakTo)
1689
        {
1690
            switch (TextRenderType)
1691
            {
1692
                case TextRenderType.HtmlParagraph:
1693
                    bool endOnEnter;
1694
                    string breakTextHtml = BreakTextHtml(out endOnEnter);
1695
                    if (breakTextHtml != null && breakTo != null)
1696
                    {
1697
                        (breakTo as TextObject).Text = breakTextHtml;
1698
                        if (!endOnEnter)
1699
                            (breakTo as TextObject).ParagraphFormat.SkipFirstLineIndent = true;
1700
                    }
1701
                    return breakTextHtml != null;
1702
                default:
1703
                    string breakText = BreakText();
1704
                    if (breakText != null && breakTo != null)
1705
                        (breakTo as TextObject).Text = breakText;
1706
                    return breakText != null;
1707
            }
1708
        }
1709

1710
        internal IEnumerable<PictureObject> GetPictureFromHtmlText(AdvancedTextRenderer renderer)
1711
        {
1712
            if (renderer == null)
1713
            {
1714
                using (Bitmap b = new Bitmap(1, 1))
1715
                using (IGraphics g = new GdiGraphics(b))
1716
                {
1717
                    RectangleF textRect = new RectangleF(
1718
                      (AbsLeft + Padding.Left),
1719
                      (AbsTop + Padding.Top),
1720
                      (Width - Padding.Horizontal),
1721
                      (Height - Padding.Vertical));
1722
                    StringFormat format = GetStringFormat(Report.GraphicCache, StringFormatFlags.LineLimit);
1723
                    renderer = new AdvancedTextRenderer(Text, g, Font, Brushes.Black, Pens.Black,
1724
                        textRect, format, HorzAlign, VertAlign, LineHeight, Angle, FontWidthRatio,
1725
                        ForceJustify, Wysiwyg, HasHtmlTags, false, 1, 1,
1726
                        InlineImageCache);
1727
                    foreach (PictureObject obj in GetPictureFromHtmlText(renderer))
1728
                        yield return obj;
1729
                }
1730
            }
1731
            else
1732
            {
1733
                RectangleF textRect = renderer.DisplayRect;
1734
                foreach (AdvancedTextRenderer.Paragraph paragraph in renderer.Paragraphs)
1735
                    foreach (AdvancedTextRenderer.Line line in paragraph.Lines)
1736
                        foreach (AdvancedTextRenderer.Word word in line.Words)
1737
                            foreach (AdvancedTextRenderer.Run run in word.Runs)
1738
                                if (run is AdvancedTextRenderer.RunImage)
1739
                                {
1740
                                    AdvancedTextRenderer.RunImage runImage = run as AdvancedTextRenderer.RunImage;
1741
                                    PictureObject obj = new PictureObject();
1742

1743
                                    float left = runImage.Left - textRect.Left;
1744
                                    float top = runImage.Top - textRect.Top;
1745
                                    float width =
1746
                                      runImage.Left + runImage.Width > textRect.Right ?
1747
                                      textRect.Right - (left < 0 ? textRect.Left : runImage.Left) :
1748
                                      (
1749
                                        runImage.Left < textRect.Left ?
1750
                                        runImage.Left + runImage.Width - textRect.Left :
1751
                                        runImage.Width
1752
                                      );
1753
                                    float height =
1754
                                      runImage.Top + runImage.Height > textRect.Bottom ?
1755
                                      textRect.Bottom - (top < 0 ? textRect.Top : runImage.Top) :
1756
                                      (
1757
                                        runImage.Top < textRect.Top ?
1758
                                        runImage.Top + runImage.Height - textRect.Top :
1759
                                        runImage.Height
1760
                                      );
1761

1762

1763
                                    if (left < 0 || top < 0 || width < runImage.Width || height < runImage.Height)
1764
                                    {
1765
                                        Bitmap bmp = new Bitmap((int)width, (int)height);
1766
                                        using (Graphics g = Graphics.FromImage(bmp))
1767
                                        {
1768
                                            g.DrawImage(runImage.Image, new PointF(
1769
                                              left < 0 ? left : 0,
1770
                                              top < 0 ? top : 0
1771
                                              ));
1772
                                        }
1773
                                        obj.Image = bmp;
1774
                                        obj.Left = (left < 0 ? textRect.Left : runImage.Left) / renderer.Scale;
1775
                                        obj.Top = (top < 0 ? textRect.Top : runImage.Top) / renderer.Scale;
1776
                                        obj.Width = width / renderer.Scale;
1777
                                        obj.Height = height / renderer.Scale;
1778
                                        obj.SizeMode = PictureBoxSizeMode.StretchImage;
1779
                                    }
1780
                                    else
1781
                                    {
1782
                                        obj.Image = runImage.Image;
1783
                                        obj.Left = runImage.Left / renderer.Scale;
1784
                                        obj.Top = runImage.Top / renderer.Scale;
1785
                                        obj.Width = runImage.Width / renderer.Scale;
1786
                                        obj.Height = runImage.Height / renderer.Scale;
1787
                                        obj.SizeMode = PictureBoxSizeMode.StretchImage;
1788
                                    }
1789
                                    yield return obj;
1790
                                }
1791
            }
1792
        }
1793
        #endregion
1794

1795
        /// <summary>
1796
        /// Initializes a new instance of the <see cref="TextObject"/> class with default settings.
1797
        /// </summary>
1798
        public TextObject()
1799
        {
1800
            paragraphFormat = new ParagraphFormat();
1801
            wordWrap = true;
1802
            font = DrawUtils.DefaultReportFont;
1803
            textFill = new SolidFill(Color.Black);
1804
            textOutline = new TextOutline();
1805
            trimming = StringTrimming.None;
1806
            fontWidthRatio = 1;
1807
            tabWidth = 58;
1808
            tabPositions = new FloatCollection();
1809
            clip = true;
1810
            highlight = new ConditionCollection();
1811
            FlagSerializeStyle = false;
1812
            SetFlags(Flags.HasSmartTag, true);
1813
        }
1814
    }
1815
}

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.