FastReport
1815 строк · 66.7 Кб
1using System;2using System.Text;3using System.Collections.Generic;4using System.Drawing;5using System.Drawing.Text;6using System.Drawing.Drawing2D;7using System.ComponentModel;8using FastReport.Utils;9using FastReport.Format;10using FastReport.Code;11using System.Windows.Forms;12using System.Drawing.Design;13
14namespace FastReport15{
16/// <summary>17/// Specifies the horizontal alignment of a text in the TextObject object.18/// </summary>19public enum HorzAlign20{21/// <summary>22/// Specifies that text is aligned in the left of the layout rectangle.23/// </summary>24Left,25
26/// <summary>27/// Specifies that text is aligned in the center of the layout rectangle.28/// </summary>29Center,30
31/// <summary>32/// Specifies that text is aligned in the right of the layout rectangle.33/// </summary>34Right,35
36/// <summary>37/// Specifies that text is aligned in the left and right sides of the layout rectangle.38/// </summary>39Justify
40}41
42/// <summary>43/// Specifies the vertical alignment of a text in the TextObject object.44/// </summary>45public enum VertAlign46{47/// <summary>48/// Specifies that text is aligned in the top of the layout rectangle.49/// </summary>50Top,51
52/// <summary>53/// Specifies that text is aligned in the center of the layout rectangle.54/// </summary>55Center,56
57/// <summary>58/// Specifies that text is aligned in the bottom of the layout rectangle.59/// </summary>60Bottom
61}62
63/// <summary>64/// The type of text renderer65/// </summary>66public enum TextRenderType67{68/// <summary>69/// The default render70/// </summary>71Default,72/// <summary>73/// Render with some html tags and stable logic74/// </summary>75HtmlTags,76/// <summary>77/// Render with img tags, span etc. Experimental and unstable logic78/// </summary>79HtmlParagraph,80/// <summary>81/// Renders a text in a simplest way. For internal use only.82/// </summary>83Inline
84}85
86/// <summary>87/// The format of paragraph88/// </summary>89[TypeConverter(typeof(TypeConverters.FRExpandableObjectConverter))]90public class ParagraphFormat91{92private float firstLineIndent;93private float lineSpacing;94private LineSpacingType lineSpacingType;95private 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")]103public float FirstLineIndent104{105get { return firstLineIndent; }106set { firstLineIndent = value; }107}108
109/// <summary>110/// The distance between lines, not effect if value less then 0111/// </summary>112[Browsable(true)]113[DefaultValue(0f)]114[TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]115public float LineSpacing116{117get { return lineSpacing; }118set { if (value >= 0) lineSpacing = value; }119}120
121/// <summary>122/// The spacing type for distance between line calculation123/// </summary>124[Browsable(true)]125[DefaultValue(LineSpacingType.Single)]126public LineSpacingType LineSpacingType127{128get { return lineSpacingType; }129set { lineSpacingType = value; }130}131
132/// <summary>133/// The value for a multiplication line height for adding spacing134/// </summary>135[Browsable(true)]136[DefaultValue(0f)]137public float LineSpacingMultiple138{139get { return lineSpacing / 100f; }140set { if (value >= 0) lineSpacing = value * 100f; }141}142
143/// <summary>144/// Skip the line indent in the first paragraph, for broken paragraphs145/// </summary>146[Browsable(false)]147[DefaultValue(false)]148public bool SkipFirstLineIndent149{150get { return skipFirstLineIndent; }151set { skipFirstLineIndent = value; }152}153
154/// <summary>155/// clone with new scale;156/// </summary>157/// <param name="scale"></param>158/// <returns></returns>159internal ParagraphFormat MultipleScale(float scale)160{161ParagraphFormat clone = new ParagraphFormat();162clone.lineSpacingType = lineSpacingType;163if (LineSpacingType == LineSpacingType.Multiple)164clone.lineSpacing = lineSpacing;165else166clone.lineSpacing = lineSpacing * scale;167clone.firstLineIndent = firstLineIndent * scale;168clone.skipFirstLineIndent = skipFirstLineIndent;169return clone;170}171
172internal void Assign(ParagraphFormat p)173{174lineSpacingType = p.lineSpacingType;175lineSpacing = p.lineSpacing;176firstLineIndent = p.firstLineIndent;177skipFirstLineIndent = p.skipFirstLineIndent;178}179
180public override bool Equals(object obj)181{182ParagraphFormat format = obj as ParagraphFormat;183return format != null &&184firstLineIndent == format.firstLineIndent &&185lineSpacing == format.lineSpacing &&186lineSpacingType == format.lineSpacingType &&187skipFirstLineIndent == format.skipFirstLineIndent;188}189
190public override int GetHashCode()191{192unchecked193{194int hashCode = -1051315095;195hashCode = hashCode * -1521134295 + firstLineIndent.GetHashCode();196hashCode = hashCode * -1521134295 + lineSpacing.GetHashCode();197hashCode = hashCode * -1521134295 + lineSpacingType.GetHashCode();198hashCode = hashCode * -1521134295 + skipFirstLineIndent.GetHashCode();199return hashCode;200}201}202}203
204/// <summary>205/// The spacing type between lines206/// </summary>207public enum LineSpacingType208{209/// <summary>210/// Single spacing, not effect from LineSpacing211/// </summary>212Single,213/// <summary>214/// Minimal spacing in exactly size215/// </summary>216AtLeast,217/// <summary>218/// The specific distance between the lines, for some exports, does not work if the distance value is too small.219/// </summary>220Exactly,221/// <summary>222/// The calculated distance between lines, for some exports, does not work if the distance value is too small.223/// </summary>224Multiple
225}226
227/// <summary>228/// Specifies the behavior of the <b>AutoShrink</b> feature of <b>TextObject</b>.229/// </summary>230public enum AutoShrinkMode231{232/// <summary>233/// AutoShrink is disabled.234/// </summary>235None,236
237/// <summary>238/// AutoShrink decreases the <b>Font.Size</b> property of the <b>TextObject</b>.239/// </summary>240FontSize,241
242/// <summary>243/// AutoShrink decreases the <b>FontWidthRatio</b> property of the <b>TextObject</b>.244/// </summary>245FontWidth
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]253public enum MergeMode254{255/// <summary>256/// Merge is disabled.257/// </summary>258None = 0,259
260/// <summary>261/// Allows horizontal merging.262/// </summary>263Horizontal = 1,264
265/// <summary>266/// Allows vertical merging.267/// </summary>268Vertical = 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 report277/// is running, all expressions are calculated and replaced with actual values, so the text278/// would be "Today is 01.01.2008".279/// <para/>The symbols used to find expressions in a text are set in the280/// <see cref="TextObjectBase.Brackets">Brackets</see> property. You also may disable expressions281/// using the <see cref="TextObjectBase.AllowExpressions">AllowExpressions</see> property.282/// <para/>To format an expression value, use the <see cref="Format"/> property.283/// </remarks>284public partial class TextObject : TextObjectBase285{286#region Fields287private MergeMode mergeMode;288private bool autoWidth;289private HorzAlign horzAlign;290private VertAlign vertAlign;291private int angle;292private bool rightToLeft;293private bool wordWrap;294private bool underlines;295private Font font;296private FillBase textFill;297private TextOutline textOutline;298private StringTrimming trimming;299private float fontWidthRatio;300private float firstTabOffset;301private float tabWidth;302private FloatCollection tabPositions;303private bool clip;304private ConditionCollection highlight;305private bool wysiwyg;306private float lineHeight;307private bool forceJustify;308private TextRenderType textRenderType;309private AutoShrinkMode autoShrink;310private float autoShrinkMinSize;311private float paragraphOffset;312private FillBase savedTextFill;313private Font savedFont;314private string savedText;315private FormatBase savedFormat;316private InlineImageCache inlineImageCache;317private ParagraphFormat paragraphFormat;318#endregion319
320#region Properties321
322/// <summary>323/// Gets or sets a paragraph format for a new html rendering type, not for others rendering324/// </summary>325[Category("Appearance")]326public ParagraphFormat ParagraphFormat327{328get { return paragraphFormat; }329set { 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")]337public bool AutoWidth338{339get { return autoWidth; }340set { autoWidth = value; }341}342
343/// <summary>344/// Gets or sets a value that indicates whether the font size should shrink to345/// 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")]352public AutoShrinkMode AutoShrink353{354get { return autoShrink; }355set { 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 to364/// <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")]369public float AutoShrinkMinSize370{371get { return autoShrinkMinSize; }372set { 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")]380public HorzAlign HorzAlign381{382get { return horzAlign; }383set { 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")]391public VertAlign VertAlign392{393get { return vertAlign; }394set { 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))]403public int Angle404{405get { return angle; }406set { 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")]414public bool RightToLeft415{416get { return rightToLeft; }417set { 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")]425public bool WordWrap426{427get { return wordWrap; }428set { 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")]436public bool Underlines437{438get { return underlines; }439set { underlines = value; }440}441
442/// <summary>443/// Gets or sets the font settings for this object.444/// </summary>445[Category("Appearance")]446public Font Font447{448get { return font; }449set450{451font = value;452if (!String.IsNullOrEmpty(Style))453Style = "";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>461public FloatCollection TabPositions462{463get { return tabPositions; }464set465{466if (value == null)467tabPositions.Clear();468else469tabPositions = 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))]485public FillBase TextFill486{487get { return textFill; }488set489{490if (value == null)491throw new ArgumentNullException("TextFill");492textFill = value;493if (!String.IsNullOrEmpty(Style))494Style = "";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))]503public TextOutline TextOutline504{505get { return textOutline; }506set507{508if (value == null)509throw new ArgumentNullException("TextOutline");510textOutline = value;511if (!String.IsNullOrEmpty(Style))512Style = "";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 is521/// equivalent to: <code>textObject1.TextFill = new SolidFill(color);</code>522/// </remarks>523[Browsable(false)]524public Color TextColor525{526get { return TextFill is SolidFill ? (TextFill as SolidFill).Color : Color.Black; }527set { 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")]535public StringTrimming Trimming536{537get { return trimming; }538set { 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")]550public float FontWidthRatio551{552get { return fontWidthRatio; }553set554{555if (value > 0)556fontWidthRatio = value;557else558fontWidthRatio = 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")]567public float LineHeight568{569get { return lineHeight; }570set { 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")]579public float FirstTabOffset580{581get { return firstTabOffset; }582set { 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")]590public float TabWidth591{592get { return tabWidth; }593set { 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")]601public bool Clip602{603get { return clip; }604set { 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 object612/// depending on some condition(s). For example, you may highlight negative values displayed by613/// 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 < 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))]625public ConditionCollection Highlight626{627get { 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")]635public bool Wysiwyg636{637get { return wysiwyg; }638set { wysiwyg = value; }639}640
641/// <summary>642/// Forces justify for the last text line.643/// </summary>644[Browsable(false)]645public bool ForceJustify646{647get { return forceJustify; }648set { 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: <b>, <i>, <u>,656/// <strike>, <sub>, <sup>, </b>, </i>, </u>,657/// </strike>, </sub>, </sup>,658/// <font color=&...&>, </font>. Font size cannot659/// 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")]665public bool HtmlTags666{667get668{669return HasHtmlTags;670}671set { 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)]681public bool HasHtmlTags682{683get684{685switch (textRenderType)686{687case TextRenderType.HtmlTags:688case TextRenderType.HtmlParagraph:689return true;690default:691return false;692}693}694}695
696/// <summary>697/// The type of text render698/// </summary>699/// /// <remarks>700/// The following html tags can be used in the object's text: <b>, <i>, <u>,701/// <strike>, <sub>, <sup>, </b>, </i>, </u>,702/// </strike>, </sub>, </sup>,703/// <font color=&...&>, </font>. Font size cannot704/// be changed due to limitations in the rendering engine.705/// </remarks>706[DefaultValue(TextRenderType.Default)]707[Category("Behavior")]708public TextRenderType TextRenderType709{710get { return textRenderType; }711set { 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")]720public float ParagraphOffset721{722get { return paragraphOffset; }723set { paragraphOffset = value; }724}725
726internal bool IsAdvancedRendererNeeded727{728get { return HorzAlign == HorzAlign.Justify || Wysiwyg || LineHeight != 0 || HasHtmlTags; }729}730
731/// <summary>732/// Cache for inline images733/// </summary>734[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]735public InlineImageCache InlineImageCache736{737get738{739if (inlineImageCache == null)740inlineImageCache = new InlineImageCache();741return 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))]751public MergeMode MergeMode752{753get { return mergeMode; }754set { mergeMode = value; }755}756#endregion757
758#region Private Methods759private void DrawUnderlines(FRPaintEventArgs e)760{761if (!Underlines || Angle != 0)762return;763
764IGraphics g = e.Graphics;765float lineHeight = LineHeight == 0 ? Font.GetHeight() * DrawUtils.ScreenDpiFX : LineHeight;766lineHeight *= e.ScaleY;767float curY = AbsTop * e.ScaleY + lineHeight + 1;768Pen pen = e.Cache.GetPen(Border.Color, Border.Width * e.ScaleY, DashStyle.Solid);769while (curY < AbsBottom * e.ScaleY)770{771g.DrawLine(pen, AbsLeft * e.ScaleX, curY, AbsRight * e.ScaleY, curY);772curY += lineHeight;773}774}775
776private SizeF CalcSize()777{778Report report = Report;779if (String.IsNullOrEmpty(Text) || report == null)780return new SizeF(0, 0);781
782Font font = report.GraphicCache.GetFont(Font.FontFamily, Font.Size * 96f / DrawUtils.ScreenDpi, Font.Style);783float width = 0;784if (WordWrap)785{786if (Angle == 90 || Angle == 270)787width = Height - Padding.Vertical;788else789width = Width - Padding.Horizontal;790}791
792IGraphics g = report.MeasureGraphics;793IGraphicsState state = g.Save();794try795{796if (report.TextQuality != TextQuality.Default)797g.TextRenderingHint = report.GetTextQuality();798if (TextRenderType == TextRenderType.HtmlParagraph)799{800if (width == 0)801width = 100000;802
803using (HtmlTextRenderer htmlRenderer = GetHtmlTextRenderer(g, new RectangleF(0, 0, width, 100000), 1, 1))804{805float height = htmlRenderer.CalcHeight();806width = htmlRenderer.CalcWidth();807
808width += Padding.Horizontal + 1;809height += Padding.Vertical + 1;810
811return new SizeF(width, height);812}813}814#if CROSSPLATFORM && !SKIA815// in FR.Core we use AdvancedTextRenderer only if needed (IsAdvancedRendererNeeded) or if it's not Windows816if (IsAdvancedRendererNeeded || !Config.IsWindows)817#else818if (IsAdvancedRendererNeeded)819#endif820{821if (width == 0)822width = 100000;823AdvancedTextRenderer renderer = new AdvancedTextRenderer(Text, g, font, Brushes.Black, Pens.Black,824new RectangleF(0, 0, width, 100000), GetStringFormat(report.GraphicCache, 0),825HorzAlign, VertAlign, LineHeight, Angle, FontWidthRatio, false, Wysiwyg, HasHtmlTags, false, 96f / DrawUtils.ScreenDpi,82696f / DrawUtils.ScreenDpi, InlineImageCache);827float height = renderer.CalcHeight();828width = renderer.CalcWidth();829
830width += Padding.Horizontal + 1;831height += Padding.Vertical + 1;832return new SizeF(width, height);833}834else835{836if (FontWidthRatio != 1)837width /= FontWidthRatio;838SizeF size = g.MeasureString(Text, font, new SizeF(width, 100000));839size.Width += Padding.Horizontal + 1;840size.Height += Padding.Vertical + 1;841return size;842}843}844finally845{846g.Restore(state);847}848}849
850private float InternalCalcWidth()851{852bool saveWordWrap = WordWrap;853WordWrap = false;854float result = 0;855
856try857{858SizeF size = CalcSize();859result = size.Width;860}861finally862{863WordWrap = saveWordWrap;864}865
866return result;867}868
869private float InternalCalcHeight()870{871return CalcSize().Height;872}873
874private string BreakTextHtml(out bool endOnEnter)875{876endOnEnter = false;877ForceJustify = false;878if (String.IsNullOrEmpty(Text))879return "";880string result = null;881Report report = Report;882if (report == null)883return "";884
885
886StringFormat format = GetStringFormat(report.GraphicCache, StringFormatFlags.LineLimit);887RectangleF textRect = new RectangleF(0, 0, Width - Padding.Horizontal, Height - Padding.Vertical);888
889if (textRect.Height <= 0)890return result;891
892int charactersFitted;893IGraphics g = report.MeasureGraphics;894IGraphicsState state = g.Save();895
896if (report.TextQuality != TextQuality.Default)897g.TextRenderingHint = report.GetTextQuality();898
899try900{901using (HtmlTextRenderer htmlRenderer = GetHtmlTextRenderer(g, 1, 1, textRect, format))902{903htmlRenderer.CalcHeight(out charactersFitted);904if (charactersFitted == 0)905return null;906
907Text = HtmlTextRenderer.BreakHtml(Text, charactersFitted, out result, out endOnEnter);908
909if (HorzAlign == HorzAlign.Justify && !endOnEnter && result != "")910{911if (Text.EndsWith(" "))912Text = Text.TrimEnd(' ');913ForceJustify = true;914}915}916}917finally918{919g.Restore(state);920}921
922return result;923}924
925private string BreakText()926{927ForceJustify = false;928if (String.IsNullOrEmpty(Text))929return "";930
931string result = null;932Report report = Report;933if (report == null)934return "";935
936Font font = report.GraphicCache.GetFont(Font.FontFamily, Font.Size * 96f / DrawUtils.ScreenDpi, Font.Style);937StringFormat format = GetStringFormat(report.GraphicCache, StringFormatFlags.LineLimit);938RectangleF textRect = new RectangleF(0, 0, Width - Padding.Horizontal, Height - Padding.Vertical);939if (textRect.Height < 0)940return null;941
942int charactersFitted;943int linesFilled;944
945IGraphics g = report.MeasureGraphics;946IGraphicsState state = g.Save();947try948{949if (report.TextQuality != TextQuality.Default)950g.TextRenderingHint = report.GetTextQuality();951
952AdvancedTextRenderer.StyleDescriptor htmlStyle = null;953
954if (IsAdvancedRendererNeeded)955{956AdvancedTextRenderer renderer = new AdvancedTextRenderer(Text, g, font, Brushes.Black, Pens.Black,957textRect, format, HorzAlign, VertAlign, LineHeight, Angle, FontWidthRatio, false, Wysiwyg, HasHtmlTags, false, 96f / DrawUtils.ScreenDpi,95896f / DrawUtils.ScreenDpi, InlineImageCache);959renderer.CalcHeight(out charactersFitted, out htmlStyle);960
961if (charactersFitted == 0)962linesFilled = 0;963else964linesFilled = 2;965}966else967{968g.MeasureString(Text, font, textRect.Size, format, out charactersFitted, out linesFilled);969}970
971
972if (linesFilled == 0)973return null;974if (linesFilled == 1)975{976// check if there is enough space for one line977float lineHeight = g.MeasureString("Wg", font).Height;978if (textRect.Height < lineHeight)979return null;980}981
982if (charactersFitted < Text.Length)983result = Text.Substring(charactersFitted);984else985result = "";986
987Text = Text.Substring(0, charactersFitted);988
989
990if (HorzAlign == HorzAlign.Justify && !Text.EndsWith("\n") && result != "")991{992if (Text.EndsWith(" "))993Text = Text.Substring(0, Text.Length - 1);994ForceJustify = true;995}996if (HasHtmlTags && htmlStyle != null && result != "")997result = htmlStyle.ToString() + result;998}999finally1000{1001g.Restore(state);1002}1003
1004return result;1005}1006
1007private void ProcessAutoShrink()1008{1009if (TextRenderType == TextRenderType.HtmlParagraph)1010return;1011if (String.IsNullOrEmpty(Text))1012return;1013
1014if (AutoShrink == AutoShrinkMode.FontSize)1015{1016while (CalcWidth() > Width - 1 && Font.Size > AutoShrinkMinSize && Font.Size > 1)1017{1018Font = new Font(Font.FontFamily, Font.Size - 1, Font.Style);1019}1020}1021else if (AutoShrink == AutoShrinkMode.FontWidth)1022{1023FontWidthRatio = 1;1024float ratio = Converter.DecreasePrecision((Width - 1) / CalcWidth(), 2) - 0.01f;1025if (ratio < 1)1026FontWidthRatio = Math.Max(ratio, AutoShrinkMinSize);1027}1028}1029
1030private string MakeParagraphOffset(string text)1031{1032// fixed issue 28231033FirstTabOffset = ParagraphOffset;1034string[] lines = text.Split('\n');1035for (int i = 0; i < lines.Length; i++)1036{1037if (!lines[i].StartsWith("\t"))1038lines[i] = "\t" + lines[i];1039}1040return String.Join("\n", lines);1041}1042
1043
1044#endregion1045
1046#region Protected Methods1047/// <inheritdoc/>1048protected override void DeserializeSubItems(FRReader reader)1049{1050if (String.Compare(reader.ItemName, "Highlight", true) == 0)1051reader.Read(Highlight);1052else1053base.DeserializeSubItems(reader);1054}1055#endregion1056
1057#region Public Methods1058/// <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>1064public StringFormat GetStringFormat(GraphicCache cache, StringFormatFlags flags)1065{1066return GetStringFormat(cache, flags, 1);1067}1068
1069internal StringFormat GetStringFormat(GraphicCache cache, StringFormatFlags flags, float scale)1070{1071StringAlignment align = StringAlignment.Near;1072if (HorzAlign == HorzAlign.Center)1073align = StringAlignment.Center;1074else if (HorzAlign == HorzAlign.Right)1075align = StringAlignment.Far;1076
1077StringAlignment lineAlign = StringAlignment.Near;1078if (VertAlign == VertAlign.Center)1079lineAlign = StringAlignment.Center;1080else if (VertAlign == VertAlign.Bottom)1081lineAlign = StringAlignment.Far;1082
1083if (RightToLeft)1084flags |= StringFormatFlags.DirectionRightToLeft;1085if (!WordWrap)1086flags |= StringFormatFlags.NoWrap;1087if (!Clip)1088flags |= StringFormatFlags.NoClip;1089if (TabPositions.Count > 0)1090{1091FloatCollection tabPositions = new FloatCollection();1092foreach (var i in TabPositions)1093tabPositions.Add((float)i * scale);1094return cache.GetStringFormat(align, lineAlign, Trimming, flags, firstTabOffset * scale, tabPositions,109548 * scale);1096}1097return cache.GetStringFormat(align, lineAlign, Trimming, flags, firstTabOffset * scale, tabWidth * scale);1098}1099
1100/// <inheritdoc/>1101public override void Assign(Base source)1102{1103base.Assign(source);1104
1105TextObject src = source as TextObject;1106AutoWidth = src.AutoWidth;1107HorzAlign = src.HorzAlign;1108VertAlign = src.VertAlign;1109Angle = src.Angle;1110RightToLeft = src.RightToLeft;1111WordWrap = src.WordWrap;1112Underlines = src.Underlines;1113Font = src.Font;1114TextFill = src.TextFill.Clone();1115TextOutline.Assign(src.TextOutline);1116Trimming = src.Trimming;1117FontWidthRatio = src.FontWidthRatio;1118FirstTabOffset = src.FirstTabOffset;1119TabWidth = src.TabWidth;1120TabPositions.Assign(src.TabPositions);1121Clip = src.Clip;1122Highlight.Assign(src.Highlight);1123Wysiwyg = src.Wysiwyg;1124LineHeight = src.LineHeight;1125TextRenderType = src.TextRenderType;1126AutoShrink = src.AutoShrink;1127AutoShrinkMinSize = src.AutoShrinkMinSize;1128ParagraphOffset = src.ParagraphOffset;1129inlineImageCache = src.inlineImageCache;1130paragraphFormat.Assign(src.paragraphFormat);1131MergeMode = 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>1140public HtmlTextRenderer GetHtmlTextRenderer(float scale, float fontScale)1141{1142return GetHtmlTextRenderer(Report.MeasureGraphics, scale, fontScale);1143}1144
1145internal HtmlTextRenderer GetHtmlTextRenderer(IGraphics g, float scale, float fontScale)1146{1147StringFormat format = GetStringFormat(Report.GraphicCache, 0, scale);1148RectangleF textRect = new RectangleF(1149(AbsLeft + Padding.Left) * scale,1150(AbsTop + Padding.Top) * scale,1151(Width - Padding.Horizontal) * scale,1152(Height - Padding.Vertical) * scale);1153return GetHtmlTextRenderer(g, scale, fontScale, textRect, format);1154
1155}1156
1157internal HtmlTextRenderer GetHtmlTextRenderer(IGraphics g, RectangleF textRect, float scale, float fontScale)1158{1159StringFormat format = GetStringFormat(Report.GraphicCache, 0, fontScale);1160return GetHtmlTextRenderer(g, scale, fontScale, textRect, format);1161}1162
1163internal HtmlTextRenderer GetHtmlTextRenderer(IGraphics g, float scale, float fontScale, RectangleF textRect, StringFormat format)1164{1165return GetHtmlTextRenderer(Text, g, fontScale, scale, fontScale, textRect, format, false);1166}1167
1168internal HtmlTextRenderer GetHtmlTextRenderer(string text, IGraphics g, float formatScale, float scale, float fontScale,1169RectangleF textRect, StringFormat format, bool isPrinting)1170{1171#if true1172HtmlTextRenderer.RendererContext context;1173context.angle = angle;1174context.widthRatio = FontWidthRatio;1175context.text = text;1176context.g = g;1177context.font = font.FontFamily;1178context.size = font.Size;1179context.style = font.Style; // no keep1180context.color = TextColor; // no keep1181context.underlineColor = textOutline.Color;1182context.rect = textRect;1183context.underlines = Underlines;1184context.format = format; // no keep1185context.horzAlign = horzAlign;1186context.vertAlign = vertAlign;1187context.paragraphFormat = ParagraphFormat.MultipleScale(formatScale);1188context.forceJustify = ForceJustify;1189context.scale = scale * 96f / DrawUtils.ScreenDpi;1190context.fontScale = fontScale * 96f / DrawUtils.ScreenDpi;1191context.cache = InlineImageCache;1192context.isPrinting = isPrinting;1193context.isDifferentTabPositions = TabPositions.Count > 0;1194context.keepLastLineSpace = false;1195return new HtmlTextRenderer(context);1196#else1197bool isDifferentTabPositions = TabPositions.Count > 0;1198return new HtmlTextRenderer(text, g, font.FontFamily, font.Size, font.Style, TextColor,1199textOutline.Color, textRect, Underlines,1200format, horzAlign, vertAlign, ParagraphFormat.MultipleScale(formatScale), ForceJustify,1201scale * 96f / DrawUtils.ScreenDpi, fontScale * 96f / DrawUtils.ScreenDpi, InlineImageCache,1202isPrinting, isDifferentTabPositions);1203#endif1204}1205
1206/// <summary>1207/// Draws a text.1208/// </summary>1209/// <param name="e">Paint event data.</param>1210public void DrawText(FRPaintEventArgs e)1211{1212string text = GetDisplayText();1213if (!String.IsNullOrEmpty(text))1214{1215IGraphics g = e.Graphics;1216RectangleF 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
1222if (ParagraphOffset != 0 && IsDesigning)1223text = MakeParagraphOffset(text);1224StringFormat format = GetStringFormat(e.Cache, 0, e.ScaleX);1225
1226Font font = e.Cache.GetFont(Font.FontFamily,1227IsPrinting ? Font.Size : Font.Size * e.ScaleX * 96f / DrawUtils.ScreenDpi,1228Font.Style);1229
1230Brush textBrush = null;1231if (TextFill is SolidFill)1232textBrush = e.Cache.GetBrush((TextFill as SolidFill).Color);1233else1234textBrush = TextFill.CreateBrush(textRect, e.ScaleX, e.ScaleY);1235
1236Pen outlinePen = null;1237if (textOutline.Enabled)1238outlinePen = e.Cache.GetPen(textOutline.Color, textOutline.Width * e.ScaleX, textOutline.Style);1239
1240Report report = Report;1241if (report != null && report.TextQuality != TextQuality.Default)1242g.TextRenderingHint = report.GetTextQuality();1243
1244if (textRect.Width > 0 && textRect.Height > 0)1245{1246switch (TextRenderType)1247{1248case TextRenderType.Inline:1249g.DrawString(text, font, textBrush, textRect.X, textRect.Y, StringFormat.GenericTypographic);1250break;1251case TextRenderType.HtmlParagraph:1252try1253{1254using (HtmlTextRenderer htmlRenderer = GetHtmlTextRenderer(text, e.Graphics, e.ScaleX,1255IsPrinting ? 1 : e.ScaleX, IsPrinting ? 1 / (96f / DrawUtils.ScreenDpi) : e.ScaleX, textRect, format, IsPrinting))1256{1257htmlRenderer.Draw();1258}1259}1260catch1261{1262textBrush.Dispose();1263textBrush = null;1264}1265break;1266default:1267if (IsAdvancedRendererNeeded)1268{1269// use advanced rendering1270AdvancedTextRenderer advancedRenderer = new AdvancedTextRenderer(text, g, font, textBrush,1271outlinePen, textRect, format, HorzAlign, VertAlign, LineHeight * e.ScaleY, Angle,1272FontWidthRatio, ForceJustify, Wysiwyg, HasHtmlTags, false,1273e.ScaleX * 96f / DrawUtils.ScreenDpi,1274IsPrinting ? 1 : e.ScaleX * 96f / DrawUtils.ScreenDpi, InlineImageCache, IsPrinting);1275advancedRenderer.Draw();1276}1277else1278{1279// use simple rendering1280if (Angle == 0 && FontWidthRatio == 1)1281{1282if (outlinePen == null)1283{1284if (WordWrap)1285format.Trimming = StringTrimming.Word;1286
1287g.DrawString(text, font, textBrush, textRect, format);1288}1289else1290{1291GraphicsPath path = new GraphicsPath();1292path.AddString(text, font.FontFamily, Convert.ToInt32(font.Style),1293g.DpiY * font.Size / 72, textRect, format);1294
1295IGraphicsState state = g.Save();1296g.SetClip(textRect);1297//g.FillPath(textBrush, path);1298
1299//regime for text output with drawbehind1300if (TextOutline.DrawBehind)1301{1302g.DrawPath(outlinePen, path);1303g.FillPath(textBrush, path);1304}1305else //without. default1306{1307g.FillAndDrawPath(outlinePen, textBrush, path);1308}1309g.Restore(state);1310
1311}1312}1313else1314StandardTextRenderer.Draw(text, g, font, textBrush, outlinePen, textRect, format, Angle,1315FontWidthRatio);1316
1317}1318DrawUnderlines(e);1319break;1320}1321
1322}1323if (!(TextFill is SolidFill))1324{1325textBrush.Dispose();1326}1327}1328}1329
1330
1331/// <inheritdoc/>1332public override void Draw(FRPaintEventArgs e)1333{1334base.Draw(e);1335DrawText(e);1336DrawMarkers(e);1337Border.Draw(e, new RectangleF(AbsLeft, AbsTop, Width, Height));1338DrawDesign(e);1339}1340
1341/// <inheritdoc/>1342public override void ApplyStyle(Style style)1343{1344if (style.ApplyTextFill)1345TextFill = style.TextFill.Clone();1346if (style.ApplyFont)1347Font = style.Font;1348base.ApplyStyle(style);1349}1350
1351/// <inheritdoc/>1352public override void SaveStyle()1353{1354base.SaveStyle();1355savedTextFill = TextFill;1356savedFont = Font;1357}1358
1359/// <inheritdoc/>1360public override void RestoreStyle()1361{1362base.RestoreStyle();1363TextFill = savedTextFill;1364Font = savedFont;1365}1366
1367/// <inheritdoc/>1368public override void Serialize(FRWriter writer)1369{1370if (writer.SerializeTo == SerializeTo.Preview && AutoWidth)1371{1372WordWrap = false;1373float width = CalcSize().Width;1374if ((Anchor & AnchorStyles.Right) != 0 || HorzAlign == HorzAlign.Right)1375Left = Right - width;1376if (HorzAlign == HorzAlign.Center)1377Left += Width / 2 - width / 2;1378Width = width;1379}1380TextObject c = writer.DiffObject as TextObject;1381base.Serialize(writer);1382
1383if (c == null)1384return; // RichObject here1385
1386if (AutoWidth != c.AutoWidth)1387writer.WriteBool("AutoWidth", AutoWidth);1388if (AutoShrink != c.AutoShrink)1389writer.WriteValue("AutoShrink", AutoShrink);1390if (FloatDiff(AutoShrinkMinSize, c.AutoShrinkMinSize))1391writer.WriteFloat("AutoShrinkMinSize", AutoShrinkMinSize);1392if (HorzAlign != c.HorzAlign)1393writer.WriteValue("HorzAlign", HorzAlign);1394if (VertAlign != c.VertAlign)1395writer.WriteValue("VertAlign", VertAlign);1396if (Angle != c.Angle)1397writer.WriteInt("Angle", Angle);1398if (RightToLeft != c.RightToLeft)1399writer.WriteBool("RightToLeft", RightToLeft);1400if (WordWrap != c.WordWrap)1401writer.WriteBool("WordWrap", WordWrap);1402if (Underlines != c.Underlines)1403writer.WriteBool("Underlines", Underlines);1404if ((writer.SerializeTo != SerializeTo.Preview || !Font.Equals(c.Font)) && writer.ItemName != "inherited")1405writer.WriteValue("Font", Font);1406TextFill.Serialize(writer, "TextFill", c.TextFill);1407if (TextOutline != null)1408TextOutline.Serialize(writer, "TextOutline", c.TextOutline);1409if (Trimming != c.Trimming)1410writer.WriteValue("Trimming", Trimming);1411if (FontWidthRatio != c.FontWidthRatio)1412writer.WriteFloat("FontWidthRatio", FontWidthRatio);1413if (FirstTabOffset != c.FirstTabOffset)1414writer.WriteFloat("FirstTabOffset", FirstTabOffset);1415if (TabWidth != c.TabWidth)1416writer.WriteFloat("TabWidth", TabWidth);1417if (TabPositions.Count > 0)1418writer.WriteValue("TabPositions", TabPositions);1419if (Clip != c.Clip)1420writer.WriteBool("Clip", Clip);1421if (Wysiwyg != c.Wysiwyg)1422writer.WriteBool("Wysiwyg", Wysiwyg);1423if (LineHeight != c.LineHeight)1424writer.WriteFloat("LineHeight", LineHeight);1425if (TextRenderType != c.TextRenderType)1426writer.WriteValue("TextRenderType", TextRenderType);1427if (ParagraphOffset != c.ParagraphOffset)1428writer.WriteFloat("ParagraphOffset", ParagraphOffset);1429if (ForceJustify != c.ForceJustify)1430writer.WriteBool("ForceJustify", ForceJustify);1431if (MergeMode != c.MergeMode)1432writer.WriteValue("MergeMode", MergeMode);1433if (writer.SerializeTo != SerializeTo.Preview)1434{1435if (Style != c.Style)1436writer.WriteStr("Style", Style);1437if (Highlight.Count > 0)1438writer.Write(Highlight);1439}1440
1441if (ParagraphFormat.FirstLineIndent != 0)1442writer.WriteFloat("ParagraphFormat.FirstLineIndent", ParagraphFormat.FirstLineIndent);1443if (ParagraphFormat.LineSpacing > 0)1444writer.WriteFloat("ParagraphFormat.LineSpacing", ParagraphFormat.LineSpacing);1445if (ParagraphFormat.LineSpacingType != LineSpacingType.Single)1446writer.WriteValue("ParagraphFormat.LineSpacingType", ParagraphFormat.LineSpacingType);1447if (ParagraphFormat.SkipFirstLineIndent)1448writer.WriteBool("ParagraphFormat.SkipFirstLineIndent", ParagraphFormat.SkipFirstLineIndent);1449
1450StringBuilder sb = null;1451
1452if (InlineImageCache != null && writer.BlobStore != null && HasHtmlTags == true)1453foreach (InlineImageCache.CacheItem item in InlineImageCache.AllItems())1454{1455
1456if (item.Src.StartsWith("data:")) continue;1457if (sb == null)1458sb = new StringBuilder();1459sb.Append(writer.BlobStore.AddOrUpdate(item.Stream, item.Src))1460.Append(',');1461}1462if (sb != null)1463{1464sb.Length--;1465writer.WriteStr("InlineImageCacheIndexes", sb.ToString());1466}1467}1468
1469
1470/// <inheritdoc/>1471public override void Deserialize(FRReader reader)1472{1473base.Deserialize(reader);1474TextFill.Deserialize(reader, "TextFill");1475if (reader.BlobStore != null)1476{1477string indexes = reader.ReadStr("InlineImageCacheIndexes");1478if (indexes != "null" && !String.IsNullOrEmpty(indexes))1479{1480string[] arr = indexes.Split(',');1481foreach (string index in arr)1482{1483int val = 0;1484if (Int32.TryParse(index, out val))1485{1486if (val >= 0 && val < reader.BlobStore.Count)1487{1488InlineImageCache.CacheItem it = new InlineImageCache.CacheItem();1489it.Set(reader.BlobStore.Get(val));1490InlineImageCache.Set(reader.BlobStore.GetSource(val), it);1491}1492}1493}1494}1495}1496switch (reader.DeserializeFrom)1497{1498case SerializeTo.Undo:1499case SerializeTo.Preview:1500case SerializeTo.Clipboard:1501// skip1502break;1503default:1504if (!reader.HasProperty("Font") && reader.ItemName != "inherited")1505{1506string creatorVersion = reader.Root.GetProp("ReportInfo.CreatorVersion");1507if (!String.IsNullOrEmpty(creatorVersion))1508{1509try1510{1511string[] versions = creatorVersion.Split('.');1512int major = 0;1513if (Int32.TryParse(versions[0], out major))1514{1515if (major < 2016)1516{1517Font = new Font("Arial", 10);1518}1519}1520}1521catch1522{1523
1524}1525}1526}1527break;1528}1529}1530
1531public override void InitializeComponent()1532{1533base.InitializeComponent();1534TextFill.InitializeComponent();1535}1536
1537public override void FinalizeComponent()1538{1539base.FinalizeComponent();1540TextFill.FinalizeComponent();1541}1542
1543internal void ApplyCondition(HighlightCondition c)1544{1545if (c.ApplyBorder)1546Border = c.Border.Clone();1547if (c.ApplyFill)1548Fill = c.Fill.Clone();1549if (c.ApplyTextFill)1550TextFill = c.TextFill.Clone();1551if (c.ApplyFont)1552Font = c.Font;1553
1554Visible = c.Visible;1555}1556
1557#endregion1558
1559#region Report Engine1560/// <inheritdoc/>1561public override string[] GetExpressions()1562{1563List<string> expressions = new List<string>();1564expressions.AddRange(base.GetExpressions());1565
1566if (AllowExpressions && !String.IsNullOrEmpty(Brackets))1567{1568string[] brackets = Brackets.Split(',');1569// collect expressions found in the text1570expressions.AddRange(CodeUtils.GetExpressions(Text, brackets[0], brackets[1]));1571}1572
1573// add highlight conditions1574foreach (HighlightCondition condition in Highlight)1575{1576expressions.Add(condition.Expression);1577}1578
1579return expressions.ToArray();1580}1581
1582/// <inheritdoc/>1583public override void SaveState()1584{1585base.SaveState();1586savedText = Text;1587savedTextFill = TextFill;1588savedFont = Font;1589savedFormat = Format;1590
1591}1592
1593/// <inheritdoc/>1594public override void RestoreState()1595{1596base.RestoreState();1597Text = savedText;1598TextFill = savedTextFill;1599Font = savedFont;1600Format = savedFormat;1601}1602
1603/// <summary>1604/// Calculates the object's width.1605/// </summary>1606/// <returns>The width, in pixels.</returns>1607public float CalcWidth()1608{1609if (Angle == 90 || Angle == 270)1610return InternalCalcHeight();1611return InternalCalcWidth();1612}1613
1614/// <inheritdoc/>1615public override float CalcHeight()1616{1617if (Angle == 90 || Angle == 270)1618return InternalCalcWidth();1619return InternalCalcHeight();1620}1621
1622/// <inheritdoc/>1623public override void GetData()1624{1625base.GetData();1626
1627// process expressions1628if (AllowExpressions)1629{1630if (!String.IsNullOrEmpty(Brackets))1631{1632string[] brackets = Brackets.Split(',');1633FindTextArgs args = new FindTextArgs();1634args.Text = new FastString(Text);1635args.OpenBracket = brackets[0];1636args.CloseBracket = brackets[1];1637int expressionIndex = 0;1638while (args.StartIndex < args.Text.Length)1639{1640string expression = CodeUtils.GetExpression(args, false);1641if (expression == null)1642break;1643
1644//if (!Report.IsCompileNeeded)1645//{1646// expression = Text;1647//}1648
1649string formattedValue = CalcAndFormatExpression(expression, expressionIndex);1650
1651args.Text.Remove(args.StartIndex, args.EndIndex - args.StartIndex);1652args.Text.Insert(args.StartIndex, formattedValue);1653
1654args.StartIndex += formattedValue.Length;1655expressionIndex++;1656}1657Text = args.Text.ToString();1658}1659}1660
1661// process highlight1662Variant varValue = new Variant(Value);1663foreach (HighlightCondition condition in Highlight)1664{1665try1666{1667object val = Report.Calc(condition.Expression, varValue);1668if (val != null && (bool)val == true)1669{1670ApplyCondition(condition);1671break;1672}1673}1674catch (Exception e)1675{1676throw new Exception(Name + ": " + Res.Get("Messages,ErrorInHighlightCondition") + ": " + condition.Expression, e.InnerException);1677}1678}1679
1680// make paragraph offset1681if (ParagraphOffset != 0)1682Text = MakeParagraphOffset(Text);1683// process AutoShrink1684ProcessAutoShrink();1685}1686
1687/// <inheritdoc/>1688public override bool Break(BreakableComponent breakTo)1689{1690switch (TextRenderType)1691{1692case TextRenderType.HtmlParagraph:1693bool endOnEnter;1694string breakTextHtml = BreakTextHtml(out endOnEnter);1695if (breakTextHtml != null && breakTo != null)1696{1697(breakTo as TextObject).Text = breakTextHtml;1698if (!endOnEnter)1699(breakTo as TextObject).ParagraphFormat.SkipFirstLineIndent = true;1700}1701return breakTextHtml != null;1702default:1703string breakText = BreakText();1704if (breakText != null && breakTo != null)1705(breakTo as TextObject).Text = breakText;1706return breakText != null;1707}1708}1709
1710internal IEnumerable<PictureObject> GetPictureFromHtmlText(AdvancedTextRenderer renderer)1711{1712if (renderer == null)1713{1714using (Bitmap b = new Bitmap(1, 1))1715using (IGraphics g = new GdiGraphics(b))1716{1717RectangleF textRect = new RectangleF(1718(AbsLeft + Padding.Left),1719(AbsTop + Padding.Top),1720(Width - Padding.Horizontal),1721(Height - Padding.Vertical));1722StringFormat format = GetStringFormat(Report.GraphicCache, StringFormatFlags.LineLimit);1723renderer = new AdvancedTextRenderer(Text, g, Font, Brushes.Black, Pens.Black,1724textRect, format, HorzAlign, VertAlign, LineHeight, Angle, FontWidthRatio,1725ForceJustify, Wysiwyg, HasHtmlTags, false, 1, 1,1726InlineImageCache);1727foreach (PictureObject obj in GetPictureFromHtmlText(renderer))1728yield return obj;1729}1730}1731else1732{1733RectangleF textRect = renderer.DisplayRect;1734foreach (AdvancedTextRenderer.Paragraph paragraph in renderer.Paragraphs)1735foreach (AdvancedTextRenderer.Line line in paragraph.Lines)1736foreach (AdvancedTextRenderer.Word word in line.Words)1737foreach (AdvancedTextRenderer.Run run in word.Runs)1738if (run is AdvancedTextRenderer.RunImage)1739{1740AdvancedTextRenderer.RunImage runImage = run as AdvancedTextRenderer.RunImage;1741PictureObject obj = new PictureObject();1742
1743float left = runImage.Left - textRect.Left;1744float top = runImage.Top - textRect.Top;1745float width =1746runImage.Left + runImage.Width > textRect.Right ?1747textRect.Right - (left < 0 ? textRect.Left : runImage.Left) :1748(1749runImage.Left < textRect.Left ?1750runImage.Left + runImage.Width - textRect.Left :1751runImage.Width1752);1753float height =1754runImage.Top + runImage.Height > textRect.Bottom ?1755textRect.Bottom - (top < 0 ? textRect.Top : runImage.Top) :1756(1757runImage.Top < textRect.Top ?1758runImage.Top + runImage.Height - textRect.Top :1759runImage.Height1760);1761
1762
1763if (left < 0 || top < 0 || width < runImage.Width || height < runImage.Height)1764{1765Bitmap bmp = new Bitmap((int)width, (int)height);1766using (Graphics g = Graphics.FromImage(bmp))1767{1768g.DrawImage(runImage.Image, new PointF(1769left < 0 ? left : 0,1770top < 0 ? top : 01771));1772}1773obj.Image = bmp;1774obj.Left = (left < 0 ? textRect.Left : runImage.Left) / renderer.Scale;1775obj.Top = (top < 0 ? textRect.Top : runImage.Top) / renderer.Scale;1776obj.Width = width / renderer.Scale;1777obj.Height = height / renderer.Scale;1778obj.SizeMode = PictureBoxSizeMode.StretchImage;1779}1780else1781{1782obj.Image = runImage.Image;1783obj.Left = runImage.Left / renderer.Scale;1784obj.Top = runImage.Top / renderer.Scale;1785obj.Width = runImage.Width / renderer.Scale;1786obj.Height = runImage.Height / renderer.Scale;1787obj.SizeMode = PictureBoxSizeMode.StretchImage;1788}1789yield return obj;1790}1791}1792}1793#endregion1794
1795/// <summary>1796/// Initializes a new instance of the <see cref="TextObject"/> class with default settings.1797/// </summary>1798public TextObject()1799{1800paragraphFormat = new ParagraphFormat();1801wordWrap = true;1802font = DrawUtils.DefaultReportFont;1803textFill = new SolidFill(Color.Black);1804textOutline = new TextOutline();1805trimming = StringTrimming.None;1806fontWidthRatio = 1;1807tabWidth = 58;1808tabPositions = new FloatCollection();1809clip = true;1810highlight = new ConditionCollection();1811FlagSerializeStyle = false;1812SetFlags(Flags.HasSmartTag, true);1813}1814}1815}