// Decompiled with JetBrains decompiler // Type: Microsoft.Iris.ViewItems.Text // Assembly: UIX, Version=4.8.0.0, Culture=neutral, PublicKeyToken=ddd0da4d3e678217 // MVID: A56C6C9D-B7F6-46A9-8BDE-B3D9B8D60B11 // Assembly location: C:\Program Files\Zune\UIX.dll using Microsoft.Iris.Drawing; using Microsoft.Iris.InputHandlers; using Microsoft.Iris.Layout; using Microsoft.Iris.Layouts; using Microsoft.Iris.Markup; using Microsoft.Iris.OS; using Microsoft.Iris.Render; using Microsoft.Iris.Render.Extensions; using Microsoft.Iris.RenderAPI.Drawing; using Microsoft.Iris.Session; using Microsoft.Iris.UI; using System; using System.Collections; using System.Collections.Generic; using System.Text; namespace Microsoft.Iris.ViewItems { internal class Text : ViewItem, ILayout { private const float c_scaleEpsilon = 0.01f; private const float c_lineSpacingDefault = 0.0f; private const float c_characterSpacingDefault = 0.0f; private const bool c_enableKerningDefault = false; private uint _bits; private TextFlow _flow; private float _lastLineExtentLeft; private float _lastLineExtentRight; private Size _textSize; private Size _slotSize; private int _lineAlignmentOffset; private string _content; private Font _font; private Color _textColor; private Color _textHighlightColor; private Color _backHighlightColor; private char _passwordChar; private float _scale; private LineAlignment _lineAlignment; private float _fadeSize; private int _maxLines; private int _lastVisibleRun; private TextBounds _boundsType; private bool _disableIme; private TextStyle _textStyle; private IDictionary _namedStyles; private RichText _richTextRasterizer; private TextEditingHandler _externalEditingHandler; private string _parsedContent; private ArrayList _parsedContentMarkedRanges; private ArrayList _fragments; private TextFlowRenderingHelper _renderingHelper; private static Font s_defaultFont = new Font("Arial", 24f); private static RichText s_sharedOversampledRasterizer; private static RichText s_sharedNonOversampledRasterizer; private static SimpleText s_sharedSimpleTextRasterizer; private static bool s_simpleTextMeasureAvailable; private Vector _recentScaleChanges; private float _lineSpacing; private float _characterSpacing; private bool _enableKerning; private static char[] s_whitespaceChars = new char[3] { ' ', '\r', '\n' }; public Text() { this.Layout = this; this._font = s_defaultFont; this._textColor = Color.Black; this._textHighlightColor = Color.White; this._backHighlightColor = Color.Black; this._scale = 1f; this._fadeSize = 32f; this._maxLines = int.MaxValue; this._passwordChar = '•'; this._lineAlignment = LineAlignment.Near; this._richTextRasterizer = SharedNonOversampledRasterizer; this._renderingHelper = new TextFlowRenderingHelper(); this.ContributesToWidth = true; this.TextFitsWidth = true; this.TextFitsHeight = true; this.SetClipped(false); this.MarkScaleDirty(); if (s_simpleTextMeasureAvailable) return; this.ClearBit(Bits.FastMeasurePossible); this.SetBit(Bits.FastMeasureValid); } public Text(UIClass ownerUI) : this() { } protected override void OnDispose() { this.DisposeFlow(); this.UnregisterFragmentUsage(); base.OnDispose(); } private void DisposeFlow() { if (this._flow == null) return; this._flow.Dispose(this); this._flow = null; } public static void Initialize() { } public static void Uninitialize() { if (s_sharedOversampledRasterizer != null) { s_sharedOversampledRasterizer.Dispose(); s_sharedOversampledRasterizer = null; } if (s_sharedNonOversampledRasterizer != null) { s_sharedNonOversampledRasterizer.Dispose(); s_sharedNonOversampledRasterizer = null; } if (s_sharedSimpleTextRasterizer == null) return; s_sharedSimpleTextRasterizer.Dispose(); s_sharedSimpleTextRasterizer = null; } private static SimpleText SharedSimpleTextRasterizer { get { if (s_sharedSimpleTextRasterizer == null) s_sharedSimpleTextRasterizer = new SimpleText(); return s_sharedSimpleTextRasterizer; } } private static RichText SharedOversampledRasterizer { get { if (s_sharedOversampledRasterizer == null) { s_sharedOversampledRasterizer = new RichText(true); s_sharedOversampledRasterizer.Oversample = true; s_simpleTextMeasureAvailable = NativeApi.SpSimpleTextIsAvailable(); } return s_sharedOversampledRasterizer; } } private static RichText SharedNonOversampledRasterizer { get { if (s_sharedNonOversampledRasterizer == null) { s_sharedNonOversampledRasterizer = new RichText(true); s_simpleTextMeasureAvailable = NativeApi.SpSimpleTextIsAvailable(); } return s_sharedNonOversampledRasterizer; } } public string Content { get => this._content; set { if (!(this._content != value)) return; if (value != null && value.Length > 3) { this._content = value.TrimEnd(s_whitespaceChars); char ch1 = value[value.Length - 1]; char ch2 = value[value.Length - 2]; if (ch1 == ' ' && ch2 != ' ') this._content += (string)(object)ch1; } else this._content = value; this._parsedContent = null; this._parsedContentMarkedRanges = null; this.OnDisplayedContentChange(); this.FireNotification(NotificationID.Content); } } public void MarkScaleDirty() => this.SetBit(Bits.ScaleDirty); private bool InMeasure { get => this.GetBit(Bits.InMeasure); set => this.SetBit(Bits.InMeasure, value); } public void OnDisplayedContentChange() { if (this.InMeasure) return; this.MarkTextLayoutInvalid(); this.MarkPaintInvalid(); this.ForceContentChange(); } public Font Font { get => this._font; set { if (this._font == value) return; this._font = value; this.MarkPaintInvalid(); this.MarkTextLayoutInvalid(); this.ForceContentChange(); this.FireNotification(NotificationID.Font); } } public Color Color { get => this._textColor; set { if (!(this._textColor != value)) return; this._textColor = value; if (this.KeepFlowAlive) { this.MarkPaintInvalid(); } else { this.MarkLayoutInvalid(); if (this.HasEverPainted) this.KeepFlowAlive = true; } this.FireNotification(NotificationID.Color); } } public Color HighlightColor { get => this._backHighlightColor; set { if (!(this._backHighlightColor != value)) return; this._backHighlightColor = value; this.MarkPaintInvalid(); this.FireNotification(NotificationID.HighlightColor); } } public Color TextHighlightColor { get => this._textHighlightColor; set { if (!(this.TextHighlightColor != value)) return; this._textHighlightColor = value; this.MarkPaintInvalid(); this.FireNotification(NotificationID.TextHighlightColor); } } public TextSharpness TextSharpness { get => !this._richTextRasterizer.Oversample ? TextSharpness.Sharp : TextSharpness.Soft; set { if (this.TextSharpness == value) return; bool flag = false; switch (value) { case TextSharpness.Sharp: flag = false; break; case TextSharpness.Soft: flag = true; break; } if (this._richTextRasterizer == s_sharedNonOversampledRasterizer && flag) this._richTextRasterizer = SharedOversampledRasterizer; else if (this._richTextRasterizer == s_sharedOversampledRasterizer && !flag) this._richTextRasterizer = SharedNonOversampledRasterizer; else this._richTextRasterizer.Oversample = flag; this.MarkTextLayoutInvalid(); this.ForceContentChange(); this.FireNotification(NotificationID.TextSharpness); } } public bool WordWrap { get => this.GetBit(Bits.WordWrap); set { if (this.WordWrap == value) return; this.SetBit(Bits.WordWrap, value); if (value) this.KeepFlowAlive = true; this.MarkPaintInvalid(); this.MarkTextLayoutInvalid(); this.UpdateWordWrapForExternalRasterizer(); this.FireNotification(NotificationID.WordWrap); } } public bool UsePasswordMask { get => this.GetBit(Bits.PasswordMasked); set { if (this.UsePasswordMask == value) return; this.SetBit(Bits.PasswordMasked, value); this.MarkPaintInvalid(); this.MarkTextLayoutInvalid(); this.FireNotification(NotificationID.UsePasswordMask); } } public char PasswordMask { get => this._passwordChar; set { if (_passwordChar == value) return; this._passwordChar = value; if (this.UsePasswordMask) { this.MarkPaintInvalid(); this.MarkTextLayoutInvalid(); } this.FireNotification(NotificationID.PasswordMask); } } public int MaximumLines { get => this._maxLines; set { if (this._maxLines == value) return; this._maxLines = value; this.MarkPaintInvalid(); this.MarkTextLayoutInvalid(); this.FireNotification(NotificationID.MaximumLines); } } public LineAlignment LineAlignment { get => this._lineAlignment; set { if (this._lineAlignment == value) return; this._lineAlignment = value; this.MarkPaintInvalid(); this.MarkTextLayoutInvalid(); this.FireNotification(NotificationID.LineAlignment); } } public float LineSpacing { get => !this.GetBit(Bits.LineSpacingSet) ? 0.0f : this._lineSpacing; set { if (LineSpacing == (double)value) return; this._lineSpacing = value; this.SetBit(Bits.LineSpacingSet); this.MarkPaintInvalid(); this.MarkTextLayoutInvalid(); this.FireNotification(NotificationID.LineSpacing); } } public float CharacterSpacing { get => !this.GetBit(Bits.CharacterSpacingSet) ? 0.0f : this._characterSpacing; set { if (CharacterSpacing == (double)value) return; this._characterSpacing = value; this.SetBit(Bits.CharacterSpacingSet); this.MarkPaintInvalid(); this.MarkTextLayoutInvalid(); this.FireNotification(NotificationID.CharacterSpacing); } } public bool EnableKerning { get => this.GetBit(Bits.EnableKerningSet) && this._enableKerning; set { if (this.EnableKerning == value) return; this._enableKerning = value; this.SetBit(Bits.EnableKerningSet); this.MarkPaintInvalid(); this.MarkTextLayoutInvalid(); this.FireNotification(NotificationID.EnableKerning); } } public float FadeSize { get => this._fadeSize; set { if (_fadeSize == (double)value) return; this._fadeSize = value; this.InvalidateGradients(); this.FireNotification(NotificationID.FadeSize); } } public TextStyle Style { get => this._textStyle; set { if (this._textStyle == value) return; this._textStyle = value; this.MarkPaintInvalid(); this.MarkTextLayoutInvalid(); this.ForceContentChange(); this.FireNotification(NotificationID.Style); } } public IDictionary NamedStyles { get => this._namedStyles; set { if (this._namedStyles == value) return; this._namedStyles = value; this.MarkPaintInvalid(); this.MarkTextLayoutInvalid(); this.ForceContentChange(); this.FireNotification(NotificationID.NamedStyles); } } public IList Fragments => _fragments; public bool DisableIme { get => this._disableIme; set { if (this._disableIme == value) return; this._disableIme = value; this.FireNotification(NotificationID.DisableIme); } } public Rectangle LastLineBounds => this._flow != null ? this._flow.GetLastLineBounds(this._lineAlignmentOffset) : new Rectangle(this._textSize); public int NumberOfLines { get { if (this._flow == null) return 1; return this._flow.Count < 1 ? 0 : this._flow[this._flow.Count - 1].Line; } } public int NumberOfVisibleLines { get { if (this._flow == null) return 1; return this._flow.FirstFitRunOnFinalLine == null ? 0 : this._flow.FirstFitRunOnFinalLine.Line; } } public bool ContributesToWidth { get => this.GetBit(Bits.ContributesToWidth); set { if (this.ContributesToWidth == value) return; this.SetBit(Bits.ContributesToWidth, value); this.FireNotification(NotificationID.ContributesToWidth); this.MarkLayoutInvalid(); } } public TextBounds BoundsType { get => this._boundsType; set { if (this._boundsType == value) return; this._boundsType = value; this.MarkLayoutInvalid(); this.FireNotification(NotificationID.BoundsType); } } public bool Clipped => this.GetBit(Bits.Clipped); private void SetClipped(bool value) { if (this.GetBit(Bits.Clipped) == value) return; this.SetBit(Bits.Clipped, value); this.FireNotification(NotificationID.Clipped); } public RichText ExternalRasterizer { set { if (this._richTextRasterizer == value) return; bool oversample = this._richTextRasterizer.Oversample; this._richTextRasterizer = value; if (value != null) { this._richTextRasterizer.Oversample = oversample; this.MarkScaleDirty(); } else this._richTextRasterizer = !oversample ? SharedNonOversampledRasterizer : SharedOversampledRasterizer; this.MarkTextLayoutInvalid(); } } public TextEditingHandler ExternalEditingHandler { set { if (this._externalEditingHandler == value) return; this._externalEditingHandler = value; this.UpdateWordWrapForExternalRasterizer(); } } private void UpdateWordWrapForExternalRasterizer() { if (this._externalEditingHandler == null) return; this._externalEditingHandler.WordWrap = this.WordWrap; } public ItemAlignment DefaultChildAlignment => ItemAlignment.Default; public bool IsViewDependent(ViewItem node) => this.GetBit(Bits.ViewDependent); public void GetInitialChildrenRequests(out int more) => more = 0; Size ILayout.Measure(ILayoutNode layoutNode, Size constraint) { Size zero = Size.Zero; this.InMeasure = true; LineAlignment alignment = RichText.ReverseAlignment(this._lineAlignment, this.UISession.IsRtl); if (!this.TextLayoutInvalid && this._flow != null && (!this.WordWrap && alignment == LineAlignment.Near) && (this.TextFitsWidth && constraint.Width >= this._textSize.Width && (this.TextFitsHeight && constraint.Height >= this._textSize.Height))) { Size size = Size.Min(this._textSize, constraint); this.InMeasure = false; return size; } int boundingWidth = constraint.Width; if (!this.ContributesToWidth) { boundingWidth = 16777215; layoutNode.LayoutContributesToWidth = false; } this.MeasureText(boundingWidth, constraint.Height, alignment); if (alignment != LineAlignment.Near && this._flow.Bounds.Width < boundingWidth && this._flow.Bounds.Height >= 0) this.MeasureText(this._flow.Bounds.Width, this._flow.Bounds.Height, alignment); bool flag1 = false; bool flag2 = false; if (this._flow.Count > 0) { Size naturalSize = this.GetNaturalSize(); flag1 = naturalSize.Width > boundingWidth; flag2 = naturalSize.Height > constraint.Height; } int x = 0; int y = 0; if (this._flow.Bounds.Left < 0) x = -this._flow.Bounds.Left; if (this._flow.Bounds.Top < 0) y = -this._flow.Bounds.Top; Point point1 = new Point(x, y); this.ClipToHeight = false; int num1 = -1; int num2 = 0; int val1_1 = 0; int val1_2 = 0; int num3 = this.MaximumLines; if (num3 == 0) num3 = int.MaxValue; int index; for (index = 0; index < this._flow.Count; ++index) { TextRun run = this._flow[index]; if (run.Line > num3) { flag2 = true; break; } if (this.BoundsType != TextBounds.Full) { if (run.Line != num1) { num2 += val1_1 + val1_2; val1_1 = 0; val1_2 = 0; num1 = run.Line; } Point offsetPoint = point1; offsetPoint.Y -= num2; if ((this.BoundsType & TextBounds.AlignToAscender) != TextBounds.Full) { val1_1 = Math.Max(val1_1, run.AscenderInset); offsetPoint.Y -= run.AscenderInset; } if ((this.BoundsType & TextBounds.AlignToBaseline) != TextBounds.Full) val1_2 = Math.Max(val1_2, run.BaselineInset); run.ApplyOffset(offsetPoint); } int num4 = (this.BoundsType & TextBounds.AlignToBaseline) != TextBounds.Full ? run.BaselineInset : 0; if (run.LayoutBounds.Bottom - num4 > constraint.Height) { if (run.Line == 1) this.ClipToHeight = true; else break; } this._flow.AddFit(run); } this._lastVisibleRun = index - 1; this.TextFitsWidth = this.WordWrap || !flag1; this.TextFitsHeight = !flag2; if (!this.TextFitsHeight && this._flow.HasVisibleRuns) { this._lastLineExtentLeft = _flow.FirstFitRunOnFinalLine.LayoutBounds.Left; this._lastLineExtentRight = _flow.LastFitRun.LayoutBounds.Right; } else this._lastLineExtentLeft = this._lastLineExtentRight = 0.0f; this.InvalidateGradients(); if (this.UpdateFragmentsAfterLayout) ((ViewItem)layoutNode).MarkLayoutOutputDirty(true); Point point2 = new Point(this._flow.Bounds.Location.X + point1.X, this._flow.Bounds.Location.Y + point1.Y); this._textSize = new Size(this._flow.Bounds.Width + point2.X, this._flow.FitBounds.Height + point2.Y - (val1_1 + val1_2)); Size constraint1 = Size.Min(this._textSize, constraint); DefaultLayout.Measure(layoutNode, constraint1); this.FireNotification(NotificationID.LastLineBounds); this.InMeasure = false; return constraint1; } void ILayout.Arrange(ILayoutNode layoutNode, LayoutSlot slot) { this._slotSize = slot.Bounds; if (!this.ContributesToWidth) this.TextFitsWidth = this._textSize.Width <= slot.Bounds.Width; this._lineAlignmentOffset = 0; if (this.TextFitsWidth) { if (this.LineAlignment == LineAlignment.Center) this._lineAlignmentOffset = (this._slotSize.Width - this._textSize.Width) / 2; else if (this.LineAlignment == LineAlignment.Far) this._lineAlignmentOffset = this._slotSize.Width - this._textSize.Width; } bool flag1 = false; if (this._flow != null) { Rectangle view = slot.View; Size size = view.Size; bool flag2 = this._textSize.Width > size.Width || this._textSize.Height > size.Height; flag1 = ((flag1 ? 1 : 0) | (!this.KeepFlowAlive ? 0 : (flag2 ? 1 : 0))) != 0; this._flow.ResetVisibleTracking(); if (flag1) { bool flag3 = false; for (int index = 0; index <= this._lastVisibleRun; ++index) { TextRun textRun = this._flow[index]; bool flag4 = !textRun.LayoutBounds.IsEmpty && textRun.LayoutBounds.IntersectsWith(view); if (!flag3 && textRun.Visible != flag4) { this.MarkPaintInvalid(); this.UpdateFragmentsAfterLayout = true; flag3 = true; } if (flag4) this._flow.AddVisible(index); else textRun.Visible = false; } } else { for (int index = 0; index <= this._lastVisibleRun; ++index) { TextRun textRun = this._flow[index]; if (!textRun.LayoutBounds.IsEmpty) { if (!textRun.Visible) this.MarkPaintInvalid(); this._flow.AddVisible(index); } } } } this.KeepFlowAlive |= flag1; this.SetBit(Bits.ViewDependent, flag1); DefaultLayout.Arrange(layoutNode, slot); } private Size GetNaturalSize() { if (!this.FastMeasurePossible) return this._richTextRasterizer.GetNaturalBounds(); return this._flow.Count == 1 ? this._flow[0].NaturalExtent : Size.Zero; } private void MeasureText(int boundingWidth, int boundingHeight, LineAlignment alignment) { if (this.FastMeasurePossible) this.DoFastMeasure(boundingWidth, boundingHeight, alignment); else this.DoRichEditMeasure(boundingWidth, boundingHeight, alignment); } private void DoFastMeasure(int boundingWidth, int boundingHeight, LineAlignment alignment) { TextStyle effectiveTextStyle = this.GetEffectiveTextStyle(); Size constraint = new Size(boundingWidth, boundingHeight); this.DisposeFlow(); this._flow = SharedSimpleTextRasterizer.Measure(this._content, alignment, effectiveTextStyle, constraint); this._flow.DeclareOwner(this); } private void DoRichEditMeasure(int boundingWidth, int boundingHeight, LineAlignment alignment) { TextMeasureParams measureParams = new TextMeasureParams(); measureParams.Initialize(); float width = Math.Min(boundingWidth, 4095f); float height = Math.Min(boundingHeight, 8191f); measureParams.SetConstraint(new SizeF(width, height)); TextStyle effectiveTextStyle = this.GetEffectiveTextStyle(); string empty = string.Empty; string content; if (!this.UsedForEditing) { content = this.Content; if (this._namedStyles != null) { if (this._parsedContent == null && content != null) { this._parsedContentMarkedRanges = new ArrayList(); this._parsedContent = ParseMarkedUpText(content, this._parsedContentMarkedRanges); } content = this._parsedContent; } measureParams.SetWordWrap(this.WordWrap); } else content = this._richTextRasterizer.SimpleContent; measureParams.SetEditMode(this.UsedForEditing); if (this.UsePasswordMask) measureParams.SetPasswordChar(this._passwordChar); measureParams.SetFormat(alignment, effectiveTextStyle); if ((this._boundsType & TextBounds.TrimLeftSideBearing) != TextBounds.Full && this._lineAlignment == LineAlignment.Near) measureParams.TrimLeftSideBearing(); if (!this.UsedForEditing || this.GetBit(Bits.ScaleDirty)) { this.ClearBit(Bits.ScaleDirty); measureParams.SetScale(this._scale); } if (this._parsedContent != null) this.ApplyContentFormatting(ref measureParams); this.DisposeFlow(); this._flow = this._richTextRasterizer.Measure(content, ref measureParams); measureParams.Dispose(); this._flow.DeclareOwner(this); this.UpdateFragmentsAfterLayout = true; } private bool FastMeasurePossible { get { if (!this.GetBit(Bits.FastMeasureValid)) { bool flag = this.UsingSharedRasterizer && !this.WordWrap && (this._namedStyles == null && _scale == 1.0) && (this.TextSharpness == TextSharpness.Sharp && !this.UsePasswordMask) && !this.Zone.Session.IsRtl; if (flag) flag = SharedSimpleTextRasterizer.CanMeasure(this.Content, this.GetEffectiveTextStyle()); this.SetBit(Bits.FastMeasurePossible, flag); this.SetBit(Bits.FastMeasureValid); } return this.GetBit(Bits.FastMeasurePossible); } } internal TextStyle GetEffectiveTextStyle() { TextStyle textStyle = new TextStyle(); Font font = this._font ?? s_defaultFont; textStyle.FontFace = font.FontName; textStyle.FontSize = font.FontSize; if (font.AltFontSize != (double)font.FontSize) textStyle.AltFontSize = font.AltFontSize; if ((font.FontStyle & FontStyles.Bold) != FontStyles.None) textStyle.Bold = true; if ((font.FontStyle & FontStyles.Italic) != FontStyles.None) textStyle.Italic = true; if ((font.FontStyle & FontStyles.Underline) != FontStyles.None) textStyle.Underline = true; textStyle.Color = this._textColor; if (this.GetBit(Bits.LineSpacingSet)) textStyle.LineSpacing = this.LineSpacing; if (this.GetBit(Bits.CharacterSpacingSet)) textStyle.CharacterSpacing = this.CharacterSpacing; if (this.GetBit(Bits.EnableKerningSet)) textStyle.EnableKerning = this.EnableKerning; if (this._textStyle != null) textStyle.Add(this._textStyle); return textStyle; } protected override void OnLayoutComplete(ViewItem sender) { ArrayList arrayList = null; if (this.UpdateFragmentsAfterLayout) { if (this._namedStyles != null) arrayList = this.AnnotateFragments(); bool flag = false; if (this._fragments != null || arrayList != null) flag = this.TextLayoutInvalid || !AreFragmentListsEquivalent(_fragments, arrayList); if (flag) { this.UnregisterFragmentUsage(); this._fragments = arrayList; this.RegisterFragmentUsage(); this.FireNotification(NotificationID.Fragments); } else if (this._fragments != null) { for (int index = 0; index < this._fragments.Count; ++index) ((TextFragment)this._fragments[index]).NotifyPaintInvalid(); } this.ResetMarkedRanges(); this.UpdateFragmentsAfterLayout = false; } this.SetClipped(!this.TextFitsWidth || !this.TextFitsHeight); this.TextLayoutInvalid = false; base.OnLayoutComplete(sender); } private static bool AreFragmentListsEquivalent(IList lhsFragments, IList rhsFragments) { int num1 = lhsFragments != null ? lhsFragments.Count : 0; int num2 = rhsFragments != null ? rhsFragments.Count : 0; if (num1 != num2) return false; for (int index = 0; index < num1; ++index) { if (!((TextFragment)lhsFragments[index]).IsLayoutEquivalentTo((TextFragment)rhsFragments[index])) return false; } return true; } private void ApplyContentFormatting(ref TextMeasureParams measureParams) { if (this._parsedContentMarkedRanges == null || this._namedStyles == null) return; if (!this.UsingSharedRasterizer) { ErrorManager.ReportError("Text: Complex formatting unsupported on text that is editable"); } else { measureParams.AllocateFormattedRanges(this._parsedContentMarkedRanges.Count, this._namedStyles.Count); TextStyle[] array = new TextStyle[this._namedStyles.Count]; int index1 = 0; foreach (TextStyle style in _namedStyles.Values) { measureParams.SetFormattedRangeStyle(index1, style); array[index1] = style; ++index1; } TextMeasureParams.FormattedRange[] formattedRanges = measureParams.FormattedRanges; for (int index2 = 0; index2 < this._parsedContentMarkedRanges.Count; ++index2) { Microsoft.Iris.ViewItems.Text.MarkedRange contentMarkedRange = (Microsoft.Iris.ViewItems.Text.MarkedRange)this._parsedContentMarkedRanges[index2]; if (this._namedStyles.Contains(contentMarkedRange.tagName)) { TextStyle namedStyle = this._namedStyles[contentMarkedRange.tagName] as TextStyle; contentMarkedRange.cachedStyle = namedStyle; if (namedStyle != null) { formattedRanges[index2].FirstCharacter = contentMarkedRange.firstCharacter; formattedRanges[index2].LastCharacter = contentMarkedRange.lastCharacter; formattedRanges[index2].Color = contentMarkedRange.RangeIDAsColor; formattedRanges[index2].StyleIndex = Array.IndexOf(array, namedStyle); } } else contentMarkedRange.cachedStyle = null; } } } private ArrayList AnnotateFragments() { ArrayList arrayList = null; if (this._parsedContentMarkedRanges != null && this._flow != null) { for (int firstVisibleIndex = this._flow.FirstVisibleIndex; firstVisibleIndex <= this._flow.LastVisibleIndex; ++firstVisibleIndex) { TextRun textRun = this._flow[firstVisibleIndex]; textRun.IsFragment = false; if (textRun.RunColor.A != byte.MaxValue) { Microsoft.Iris.ViewItems.Text.MarkedRange markedRange = null; for (int index = 0; index < this._parsedContentMarkedRanges.Count; ++index) { Microsoft.Iris.ViewItems.Text.MarkedRange contentMarkedRange = (Microsoft.Iris.ViewItems.Text.MarkedRange)this._parsedContentMarkedRanges[index]; if (contentMarkedRange.RangeIDAsColor == textRun.RunColor) { textRun.OverrideColor = contentMarkedRange.GetEffectiveColor(Color.Transparent); markedRange = contentMarkedRange; break; } } if (markedRange != null && markedRange.IsInFragment) { textRun.IsFragment = true; if (markedRange.fragment == null) { markedRange.fragment = new TextFragment(markedRange.tagName, markedRange.attributes, this); if (arrayList == null) arrayList = new ArrayList(); arrayList.Add(markedRange.fragment); } markedRange.fragment.InternalRuns.Add(new TextRunData(textRun, this.IsOnLastLine(textRun), this, this._lineAlignmentOffset)); } } } } return arrayList; } private void RegisterFragmentUsage() { if (this._fragments == null) return; foreach (TextFragment fragment in this._fragments) { if (fragment.Runs != null) { foreach (TextRunData run in fragment.Runs) run.Run.RegisterUsage(this); } } } private void UnregisterFragmentUsage() { if (this._fragments == null) return; foreach (TextFragment fragment in this._fragments) { if (fragment.Runs != null) { foreach (TextRunData run in fragment.Runs) run.Run.UnregisterUsage(this); } } this._fragments = null; } private void ResetMarkedRanges() { if (this._parsedContentMarkedRanges == null) return; for (int index = 0; index < this._parsedContentMarkedRanges.Count; ++index) ((Microsoft.Iris.ViewItems.Text.MarkedRange)this._parsedContentMarkedRanges[index]).fragment = null; } private static string ParseMarkedUpText(string content, ArrayList markedRanges) { StringBuilder stringBuilder = new StringBuilder(); ArrayList arrayList = new ArrayList(); uint num = 0; try { using (NativeXmlReader nativeXmlReader = new NativeXmlReader(content, true)) { Microsoft.Iris.ViewItems.Text.MarkedRange markedRange1 = null; NativeXmlNodeType nodeType; while (nativeXmlReader.Read(out nodeType)) { switch (nodeType) { case NativeXmlNodeType.Element: if (!nativeXmlReader.IsEmptyElement) { string name = nativeXmlReader.Name; Microsoft.Iris.ViewItems.Text.MarkedRange markedRange2 = new Microsoft.Iris.ViewItems.Text.MarkedRange(); markedRange2.tagName = name; markedRange2.firstCharacter = stringBuilder.Length; markedRange2.lastCharacter = int.MaxValue; markedRange2.rangeID = ++num; arrayList.Add(markedRange2); markedRanges.Add(markedRange2); markedRange2.parentRange = markedRange1; markedRange1 = markedRange2; while (nativeXmlReader.ReadAttribute()) { if (markedRange1.attributes == null) markedRange1.attributes = new Dictionary(); markedRange1.attributes[nativeXmlReader.Name] = nativeXmlReader.Value; } continue; } continue; case NativeXmlNodeType.Text: case NativeXmlNodeType.CDATA: case NativeXmlNodeType.Whitespace: string str = nativeXmlReader.Value; if (str.IndexOf("\r\n", StringComparison.Ordinal) >= 0) str = str.Replace("\r\n", "\r"); stringBuilder.Append(str); continue; case NativeXmlNodeType.EndElement: string name1 = nativeXmlReader.Name; for (int index = arrayList.Count - 1; index >= 0; --index) { Microsoft.Iris.ViewItems.Text.MarkedRange markedRange2 = (Microsoft.Iris.ViewItems.Text.MarkedRange)arrayList[index]; markedRange2.lastCharacter = stringBuilder.Length; arrayList.RemoveAt(index); if (markedRange2.tagName == name1) break; } if (markedRange1 != null) { markedRange1 = markedRange1.parentRange; continue; } continue; default: continue; } } } } catch (NativeXmlException ex) { markedRanges.Clear(); stringBuilder = null; } if (stringBuilder == null) return content; return stringBuilder.ToString(); } public void CreateFadeGradientsHelper( ref IGradient gradientClipLeftRight, ref IGradient gradientMultiLine) { bool flag1 = true; if (this.TextFitsWidth && this.TextFitsHeight) flag1 = false; float fadeSize = this.FadeSize; if (!flag1 || fadeSize <= 0.0) return; if (!this.WordWrap) { if (this.TextFitsWidth) return; float num = 0.0f; float flPosition = 0.0f; LineAlignment lineAlignment = this.LineAlignment; if (lineAlignment == LineAlignment.Center) { flPosition = num = fadeSize; } else { bool flag2 = lineAlignment == LineAlignment.Near; if (this.UISession.IsRtl) flag2 = !flag2; if (flag2) num = fadeSize; else flPosition = fadeSize; } IGradient gradient = this.UISession.RenderSession.CreateGradient(this); gradient.Orientation = Orientation.Horizontal; if (flPosition > 0.0) { gradient.AddValue(-1f, 0.0f, RelativeSpace.Min); gradient.AddValue(flPosition, 1f, RelativeSpace.Min); } if (num > 0.0) { gradient.AddValue(_slotSize.Width - num, 1f, RelativeSpace.Min); gradient.AddValue(this._slotSize.Width + 1, 0.0f, RelativeSpace.Min); } gradientClipLeftRight = gradient; } else { if (this.TextFitsHeight) return; float flPosition1 = 0.0f; float flPosition2 = 0.0f; if (!this.UISession.IsRtl) { if (this._flow.LastFitRun != null) { flPosition2 = _flow.LastFitRun.LayoutBounds.Width; flPosition1 = flPosition2 - fadeSize; } } else { flPosition2 = 0.0f; flPosition1 = flPosition2 + fadeSize; } IGradient gradient = this.UISession.RenderSession.CreateGradient(this); gradient.ColorMask = new ColorF(byte.MaxValue, 0, 0, 0); gradient.Orientation = Orientation.Horizontal; gradient.AddValue(flPosition1, 1f, RelativeSpace.Min); gradient.AddValue(flPosition2, 0.0f, RelativeSpace.Min); gradientMultiLine = gradient; } } private bool UsingSharedRasterizer => !this._richTextRasterizer.HasCallbacks; private bool UsedForEditing => this._externalEditingHandler != null; private void ResetCachedScaleState() { this.IgnoreEffectiveScaleChanges = false; this._recentScaleChanges = null; } private void CreateVisuals(IVisualContainer topVisual, IRenderSession renderSession) { VisualOrder nOrder = VisualOrder.First; IGradient gradientClipLeftRight = null; IGradient gradientMultiLine = null; this.CreateFadeGradientsHelper(ref gradientClipLeftRight, ref gradientMultiLine); TextRun textRun = this.UISession.IsRtl ? this._flow.FirstFitRunOnFinalLine : this._flow.LastFitRun; for (int firstVisibleIndex = this._flow.FirstVisibleIndex; firstVisibleIndex <= this._flow.LastVisibleIndex; ++firstVisibleIndex) { TextRun run = this._flow[firstVisibleIndex]; if (run.Visible && !run.IsFragment) { Color effectiveColor = this.GetEffectiveColor(run); IImage imageForRun = GetImageForRun(this.UISession, run, effectiveColor); if (imageForRun != null) { float x = run.RenderBounds.Left + _lineAlignmentOffset; if (run.Highlighted) { RectangleF lineBound = (RectangleF)this._flow.LineBounds[run.Line - 1]; ISprite sprite = renderSession.CreateSprite(this, this); sprite.Effect = EffectManager.CreateColorFillEffect(this, this._backHighlightColor); sprite.Effect.UnregisterUsage(this); sprite.Position = new Vector3(x, lineBound.Top, 0.0f); sprite.Size = new Vector2(run.RenderBounds.Width, lineBound.Height); topVisual.AddChild(sprite, null, nOrder); sprite.UnregisterUsage(this); run.HighlightSprite = sprite; } ISprite sprite1 = renderSession.CreateSprite(this, this); sprite1.Effect = EffectClass.CreateImageRenderEffectWithFallback(this.Effect, this, imageForRun); sprite1.Effect.UnregisterUsage(this); sprite1.Position = new Vector3(x, run.RenderBounds.Top, 0.0f); sprite1.Size = new Vector2(run.RenderBounds.Width, run.RenderBounds.Height); if (gradientMultiLine != null && run == textRun) sprite1.AddGradient(gradientMultiLine); topVisual.AddChild(sprite1, null, nOrder); sprite1.UnregisterUsage(this); run.TextSprite = sprite1; } } } topVisual.RemoveAllGradients(); if (gradientClipLeftRight != null) topVisual.AddGradient(gradientClipLeftRight); gradientClipLeftRight?.UnregisterUsage(this); gradientMultiLine?.UnregisterUsage(this); } private Color GetEffectiveColor(TextRun run) { Color color = this._textColor; if (run.Highlighted) color = this._textHighlightColor; else if (run.OverrideColor != Color.Transparent) color = run.OverrideColor; else if (run.Link && this._externalEditingHandler != null && this._externalEditingHandler.LinkColor != Color.Transparent) color = this._externalEditingHandler.LinkColor; else if (this._textStyle != null && this._textStyle.HasColor) color = this._textStyle.Color; return color; } protected override void DisposeAllContent() { base.DisposeAllContent(); this.DisposeContent(true); } protected virtual void DisposeContent(bool removeFromTree) { if (removeFromTree) this.VisualContainer.RemoveAllChildren(); this.Effect?.DoneWithRenderEffects(this); if (this._flow == null) return; this._flow.ClearSprites(); } protected override void OnPaint(bool visible) { this.DisposeAllContent(); base.OnPaint(visible); this.ResetCachedScaleState(); if (this._flow == null) { if (this._content == null && this.UsingSharedRasterizer) return; this.MarkTextLayoutInvalid(); } else { this.CreateVisuals(this.VisualContainer, this.UISession.RenderSession); if (!this.KeepFlowAlive) this.DisposeFlow(); this.HasEverPainted = true; } } private bool IsOnLastLine(TextRun run) => this._flow.IsOnLastLine(run); private void InvalidateGradients() { this._renderingHelper.InvalidateGradients(); this.MarkPaintInvalid(); } protected override void OnEffectiveScaleChange() { float y = this.ComputeEffectiveScale().Y; if (!this.ScaleDifferenceIsGreaterThanThreshold(y, this._scale)) return; Vector vector = this._recentScaleChanges; if (!this.IgnoreEffectiveScaleChanges && vector != null) { foreach (float newScale in vector) { if (!this.ScaleDifferenceIsGreaterThanThreshold(y, newScale)) { this.IgnoreEffectiveScaleChanges = true; break; } } } if (this.IgnoreEffectiveScaleChanges) return; if (vector == null) vector = new Vector(4); vector.Add(y); this._recentScaleChanges = vector; this.MarkTextLayoutInvalid(); this._scale = y; this.MarkScaleDirty(); } private bool ScaleDifferenceIsGreaterThanThreshold(float oldScale, float newScale) => Math.Abs(oldScale - newScale) > 0.00999999977648258; private void MarkTextLayoutInvalid() { this.TextLayoutInvalid = true; if (s_simpleTextMeasureAvailable) this.ClearBit(Bits.FastMeasureValid); this.DisposeFlow(); this.MarkLayoutInvalid(); } internal static IImage GetImageForRun(UISession session, TextRun run, Color textColor) { if (string.IsNullOrEmpty(run.Content)) return null; string str = "aa"; bool flag = false; RichTextInfoKey richTextInfoKey = new RichTextInfoKey(run, str, flag, textColor); ImageCache instance = TextImageCache.Instance; ImageCacheItem imageCacheItem = instance.Lookup(richTextInfoKey); if (imageCacheItem == null) { imageCacheItem = new TextImageItem(session.RenderSession, run, str, flag, textColor); instance.Add(richTextInfoKey, imageCacheItem); } return imageCacheItem.RenderImage; } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(base.ToString()); if (this._content != null) { stringBuilder.Append(" (Content=\""); stringBuilder.Append(this._content); stringBuilder.Append("\")"); } return stringBuilder.ToString(); } private bool TextFitsWidth { get => this.GetBit(Bits.TextFitsWidth); set => this.SetBit(Bits.TextFitsWidth, value); } private bool TextFitsHeight { get => this.GetBit(Bits.TextFitsHeight); set => this.SetBit(Bits.TextFitsHeight, value); } private bool ClipToHeight { get => this.GetBit(Bits.ClipToHeight); set => this.SetBit(Bits.ClipToHeight, value); } private bool KeepFlowAlive { get => this.GetBit(Bits.KeepFlowAlive); set => this.SetBit(Bits.KeepFlowAlive, value); } private bool HasEverPainted { get => this.GetBit(Bits.HasEverPainted); set => this.SetBit(Bits.HasEverPainted, value); } private bool TextLayoutInvalid { get => this.GetBit(Bits.TextLayoutInvalid); set => this.SetBit(Bits.TextLayoutInvalid, value); } private bool UpdateFragmentsAfterLayout { get => this.GetBit(Bits.UpdateFragmentsAfterLayout); set => this.SetBit(Bits.UpdateFragmentsAfterLayout, value); } private bool IgnoreEffectiveScaleChanges { get => this.GetBit(Bits.IgnoreEffectiveScaleChanges); set => this.SetBit(Bits.IgnoreEffectiveScaleChanges, value); } private bool GetBit(Microsoft.Iris.ViewItems.Text.Bits lookupBit) => ((Microsoft.Iris.ViewItems.Text.Bits)this._bits & lookupBit) != 0; private void SetBit(Microsoft.Iris.ViewItems.Text.Bits changeBit, bool value) => this._bits = value ? (uint)((Microsoft.Iris.ViewItems.Text.Bits)this._bits | changeBit) : (uint)((Microsoft.Iris.ViewItems.Text.Bits)this._bits & ~changeBit); private void SetBit(Microsoft.Iris.ViewItems.Text.Bits changeBit) { Microsoft.Iris.ViewItems.Text text = this; text._bits = (uint)((Microsoft.Iris.ViewItems.Text.Bits)text._bits | changeBit); } private void ClearBit(Microsoft.Iris.ViewItems.Text.Bits changeBit) { Microsoft.Iris.ViewItems.Text text = this; text._bits = (uint)((Microsoft.Iris.ViewItems.Text.Bits)text._bits & ~changeBit); } private class MarkedRange { public string tagName; public int firstCharacter; public int lastCharacter; public uint rangeID; public Dictionary attributes; public Microsoft.Iris.ViewItems.Text.MarkedRange parentRange; public TextStyle cachedStyle; public TextFragment fragment; private static uint s_rangeIDIndicator = 1073741824; public Color RangeIDAsColor => new Color(s_rangeIDIndicator | this.rangeID); public Color GetEffectiveColor(Color defaultColor) { if (this.cachedStyle != null && this.cachedStyle.HasColor) return this.cachedStyle.Color; return this.parentRange != null ? this.parentRange.GetEffectiveColor(defaultColor) : defaultColor; } public bool IsInFragment { get { bool flag = false; for (Microsoft.Iris.ViewItems.Text.MarkedRange markedRange = this; markedRange != null; markedRange = markedRange.parentRange) { TextStyle cachedStyle = markedRange.cachedStyle; if (cachedStyle != null && cachedStyle.Fragment) { flag = true; break; } } return flag; } } } private new enum Bits : uint { TextFitsWidth = 1, TextFitsHeight = 2, ClipToHeight = 4, WordWrap = 8, PasswordMasked = 16, // 0x00000010 KeepFlowAlive = 32, // 0x00000020 TextLayoutInvalid = 64, // 0x00000040 UpdateFragmentsAfterLayout = 128, // 0x00000080 IgnoreEffectiveScaleChanges = 256, // 0x00000100 Clipped = 512, // 0x00000200 InMeasure = 1024, // 0x00000400 FastMeasureValid = 2048, // 0x00000800 FastMeasurePossible = 4096, // 0x00001000 ContributesToWidth = 8192, // 0x00002000 ScaleDirty = 16384, // 0x00004000 HasEverPainted = 32768, // 0x00008000 LineSpacingSet = 65536, // 0x00010000 CharacterSpacingSet = 131072, // 0x00020000 EnableKerningSet = 262144, // 0x00040000 ViewDependent = 524288, // 0x00080000 } } }