// ------------------------------------------------------------------ // Fetch the next run at UIElment position. // // position - current position in the text array // dcp - current position in the text array // ------------------------------------------------------------------ private TextRun HandleInlineObject(StaticTextPointer position, int dcp) { Debug.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.EmbeddedElement, "TextPointer does not point to embedded object."); TextRun run = null; DependencyObject element = position.GetAdjacentElement(LogicalDirection.Forward) as DependencyObject; if (element is UIElement) { // TextRunProperties textProps = new TextProperties(element, position, true /* inline objects */, true /* get background */); // Create object run. run = new InlineObject(dcp, TextContainerHelper.EmbeddedObjectLength, (UIElement)element, textProps, _owner); } else { // If the embedded object is of an unknown type (not UIElement), // treat it as element edge. run = HandleElementEndEdge(position); } return(run); }
// ------------------------------------------------------------------ // // TextSource Implementation // // ------------------------------------------------------------------ #region TextSource Implementation // ------------------------------------------------------------------ // Get a text run at specified text source position. // ------------------------------------------------------------------ public override TextRun GetTextRun(int dcp) { TextRun run = null; StaticTextPointer position = _owner.TextContainer.CreateStaticPointerAtOffset(dcp); switch (position.GetPointerContext(LogicalDirection.Forward)) { case TextPointerContext.Text: run = HandleText(position); break; case TextPointerContext.ElementStart: run = HandleElementStartEdge(position); break; case TextPointerContext.ElementEnd: run = HandleElementEndEdge(position); break; case TextPointerContext.EmbeddedElement: run = HandleInlineObject(position, dcp); break; case TextPointerContext.None: run = new TextEndOfParagraph(_syntheticCharacterLength); break; } Debug.Assert(run != null, "TextRun has not been created."); Debug.Assert(run.Length > 0, "TextRun has to have positive length."); return(run); }
// ------------------------------------------------------------------ // // TextSource Implementation // // ------------------------------------------------------------------ #region TextSource Implementation /// <summary> /// Get a text run at specified text source position and return it. /// </summary> /// <param name="dcp"> /// dcp of position relative to start of line /// </param> internal override TextRun GetTextRun(int dcp) { TextRun run = null; ITextContainer textContainer = _paraClient.Paragraph.StructuralCache.TextContainer; StaticTextPointer position = textContainer.CreateStaticPointerAtOffset(_cpPara + dcp); switch (position.GetPointerContext(LogicalDirection.Forward)) { case TextPointerContext.Text: run = HandleText(position); break; case TextPointerContext.ElementStart: run = HandleElementStartEdge(position); break; case TextPointerContext.ElementEnd: run = HandleElementEndEdge(position); break; case TextPointerContext.EmbeddedElement: run = HandleEmbeddedObject(dcp, position); break; case TextPointerContext.None: run = new ParagraphBreakRun(_syntheticCharacterLength, PTS.FSFLRES.fsflrEndOfParagraph); break; } Invariant.Assert(run != null, "TextRun has not been created."); Invariant.Assert(run.Length > 0, "TextRun has to have positive length."); return(run); }
// Token: 0x0600688D RID: 26765 RVA: 0x001D7D74 File Offset: 0x001D5F74 protected TextRun HandleText(StaticTextPointer position) { Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text, "TextPointer does not point to characters."); DependencyObject target; if (position.Parent != null) { target = position.Parent; } else { target = this._paraClient.Paragraph.Element; } TextProperties textRunProperties = new TextProperties(target, position, false, true, this._paraClient.Paragraph.StructuralCache.TextFormatterHost.PixelsPerDip); StaticTextPointer position2 = position.TextContainer.Highlights.GetNextPropertyChangePosition(position, LogicalDirection.Forward); if (position.GetOffsetToPosition(position2) > 4096) { position2 = position.CreatePointer(4096); } char[] array = new char[position.GetOffsetToPosition(position2)]; int textInRun = position.GetTextInRun(LogicalDirection.Forward, array, 0, array.Length); return(new TextCharacters(array, 0, textInRun, textRunProperties)); }
// Token: 0x06004131 RID: 16689 RVA: 0x0012A0E0 File Offset: 0x001282E0 public override TextRun GetTextRun(int dcp) { TextRun textRun = null; StaticTextPointer position = this._owner.Host.TextContainer.CreateStaticPointerAtOffset(dcp); switch (position.GetPointerContext(LogicalDirection.Forward)) { case TextPointerContext.None: textRun = new TextEndOfParagraph(1); goto IL_5C; case TextPointerContext.Text: textRun = this.HandleText(position); goto IL_5C; } Invariant.Assert(false, "Unsupported position type."); IL_5C: Invariant.Assert(textRun != null, "TextRun has not been created."); Invariant.Assert(textRun.Length > 0, "TextRun has to have positive length."); if (textRun.Properties != null) { textRun.Properties.PixelsPerDip = base.PixelsPerDip; } return(textRun); }
// Token: 0x060065FF RID: 26111 RVA: 0x001CAA74 File Offset: 0x001C8C74 public override TextRun GetTextRun(int dcp) { TextRun textRun = null; StaticTextPointer position = this._owner.TextContainer.CreateStaticPointerAtOffset(dcp); switch (position.GetPointerContext(LogicalDirection.Forward)) { case TextPointerContext.None: textRun = new TextEndOfParagraph(Line._syntheticCharacterLength); break; case TextPointerContext.Text: textRun = this.HandleText(position); break; case TextPointerContext.EmbeddedElement: textRun = this.HandleInlineObject(position, dcp); break; case TextPointerContext.ElementStart: textRun = this.HandleElementStartEdge(position); break; case TextPointerContext.ElementEnd: textRun = this.HandleElementEndEdge(position); break; } if (textRun.Properties != null) { textRun.Properties.PixelsPerDip = base.PixelsPerDip; } return(textRun); }
/// <summary> /// Get a text run at specified text source position. /// </summary> public override TextRun GetTextRun(int dcp) { TextRun run = null; StaticTextPointer position = _owner.Host.TextContainer.CreateStaticPointerAtOffset(dcp); switch (position.GetPointerContext(LogicalDirection.Forward)) { case TextPointerContext.Text: run = HandleText(position); break; case TextPointerContext.None: run = new TextEndOfParagraph(_syntheticCharacterLength); break; case TextPointerContext.ElementStart: case TextPointerContext.ElementEnd: case TextPointerContext.EmbeddedElement: default: Invariant.Assert(false, "Unsupported position type."); break; } Invariant.Assert(run != null, "TextRun has not been created."); Invariant.Assert(run.Length > 0, "TextRun has to have positive length."); return(run); }
// Token: 0x06006890 RID: 26768 RVA: 0x001D80F4 File Offset: 0x001D62F4 protected TextRun HandleEmbeddedObject(int dcp, StaticTextPointer position) { Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.EmbeddedElement, "TextPointer does not point to embedded object."); DependencyObject dependencyObject = position.GetAdjacentElement(LogicalDirection.Forward) as DependencyObject; TextRun result; if (dependencyObject is UIElement) { TextRunProperties textProps = new TextProperties(dependencyObject, position, true, true, this._paraClient.Paragraph.StructuralCache.TextFormatterHost.PixelsPerDip); result = new InlineObjectRun(TextContainerHelper.EmbeddedObjectLength, (UIElement)dependencyObject, textProps, this._paraClient.Paragraph as TextParagraph); } else { result = new TextHidden(TextContainerHelper.EmbeddedObjectLength); } return(result); }
//------------------------------------------------------------------- // // Protected Methods // //------------------------------------------------------------------- #region Protected Methods /// <summary> /// Fetch the next run at text position. /// </summary> /// <param name="position"> /// Current position in text array /// </param> /// <returns></returns> protected TextRun HandleText(StaticTextPointer position) { DependencyObject element; StaticTextPointer endOfRunPosition; Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text, "TextPointer does not point to characters."); if (position.Parent != null) { element = position.Parent; } else { element = _paraClient.Paragraph.Element; } // Extract the aggregated properties into something that the textrun can use. // TextProperties textProps = new TextProperties(element, position, false /* inline objects */, true /* get background */, _paraClient.Paragraph.StructuralCache.TextFormatterHost.PixelsPerDip); // Calculate the end of the run by finding either: // a) the next intersection of highlight ranges, or // b) the natural end of this textrun endOfRunPosition = position.TextContainer.Highlights.GetNextPropertyChangePosition(position, LogicalDirection.Forward); // Clamp the text run at an arbitrary limit, so we don't make // an unbounded allocation. if (position.GetOffsetToPosition(endOfRunPosition) > 4096) { endOfRunPosition = position.CreatePointer(4096); } // Get character buffer for the text run. char[] textBuffer = new char[position.GetOffsetToPosition(endOfRunPosition)]; // Copy characters from text run into buffer. Note the actual number of characters copied, // which may be different than the buffer's length. Buffer length only specifies the maximum // number of characters int charactersCopied = position.GetTextInRun(LogicalDirection.Forward, textBuffer, 0, textBuffer.Length); // Create text run using the actual number of characters copied return(new TextCharacters(textBuffer, 0, charactersCopied, textProps)); }
/// <summary> /// Fetch the next run at element end edge position. /// ElementEndEdge; we can have 2 possibilities: /// (1) Close edge of element associated with the text paragraph, /// create synthetic LineBreak run to end the current line. /// (2) End of inline element, hide CloseEdge character and continue /// </summary> /// <param name="position"></param> /// Position in current text array protected TextRun HandleElementEndEdge(StaticTextPointer position) { Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd, "TextPointer does not point to element end edge."); TextRun run; if (position.Parent == _paraClient.Paragraph.Element) { // (1) Close edge of element associated with the text paragraph, // create synthetic LineBreak run to end the current line. run = new ParagraphBreakRun(_syntheticCharacterLength, PTS.FSFLRES.fsflrEndOfParagraph); } else { TextElement element = (TextElement)position.GetAdjacentElement(LogicalDirection.Forward); Debug.Assert(element != null, "Element should be here."); Inline inline = (Inline)element; DependencyObject parent = inline.Parent; FlowDirection parentFlowDirection = inline.FlowDirection; if (parent != null) { parentFlowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty); } if (inline.FlowDirection != parentFlowDirection) { run = new TextEndOfSegment(_elementEdgeCharacterLength); } else { TextDecorationCollection textDecorations = DynamicPropertyReader.GetTextDecorations(inline); if (textDecorations == null || textDecorations.Count == 0) { // (2) End of inline element, hide CloseEdge character and continue run = new TextHidden(_elementEdgeCharacterLength); } else { run = new TextEndOfSegment(_elementEdgeCharacterLength); } } } return(run); }
// ------------------------------------------------------------------ // Fetch the next run at element close edge position. // // position - current position in the text array // ------------------------------------------------------------------ private TextRun HandleElementEndEdge(StaticTextPointer position) { Debug.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd, "TextPointer does not point to element end edge."); TextRun run = null; TextElement element = (TextElement)position.GetAdjacentElement(LogicalDirection.Forward); Debug.Assert(element != null, "Element should be here."); Inline inline = element as Inline; if (inline == null) { run = new TextHidden(_elementEdgeCharacterLength); } else { DependencyObject parent = inline.Parent; FlowDirection parentFlowDirection = inline.FlowDirection; if (parent != null) { parentFlowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty); } if (inline.FlowDirection != parentFlowDirection) { run = new TextEndOfSegment(_elementEdgeCharacterLength); } else { TextDecorationCollection textDecorations = DynamicPropertyReader.GetTextDecorations(inline); if (textDecorations == null || textDecorations.Count == 0) { // (2) End of inline element, hide CloseEdge character and continue run = new TextHidden(_elementEdgeCharacterLength); } else { run = new TextEndOfSegment(_elementEdgeCharacterLength); } } } return(run); }
/// <summary> /// Fetch the next run at embedded object position. /// </summary> /// <param name="dcp"> /// Character offset of this run. /// </param> /// <param name="position"> /// Current position in the text array. /// </param> protected TextRun HandleEmbeddedObject(int dcp, StaticTextPointer position) { Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.EmbeddedElement, "TextPointer does not point to embedded object."); TextRun run = null; DependencyObject embeddedObject = position.GetAdjacentElement(LogicalDirection.Forward) as DependencyObject; if (embeddedObject is UIElement) { // Extract the aggregated properties into something that the textrun can use. TextRunProperties textProps = new TextProperties(embeddedObject, position, true /* inline objects */, true /* get background */); // Create inline object run. run = new InlineObjectRun(TextContainerHelper.EmbeddedObjectLength, (UIElement)embeddedObject, textProps, _paraClient.Paragraph as TextParagraph); } else { // If the embedded object is of an unknown type, treat it as hidden content. run = new TextHidden(TextContainerHelper.EmbeddedObjectLength); } return(run); }
// Token: 0x0600688F RID: 26767 RVA: 0x001D802C File Offset: 0x001D622C protected TextRun HandleElementEndEdge(StaticTextPointer position) { Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd, "TextPointer does not point to element end edge."); TextRun result; if (position.Parent == this._paraClient.Paragraph.Element) { result = new ParagraphBreakRun(LineBase._syntheticCharacterLength, PTS.FSFLRES.fsflrEndOfParagraph); } else { TextElement textElement = (TextElement)position.GetAdjacentElement(LogicalDirection.Forward); Inline inline = (Inline)textElement; DependencyObject parent = inline.Parent; FlowDirection flowDirection = inline.FlowDirection; if (parent != null) { flowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty); } if (inline.FlowDirection != flowDirection) { result = new TextEndOfSegment(LineBase._elementEdgeCharacterLength); } else { TextDecorationCollection textDecorations = DynamicPropertyReader.GetTextDecorations(inline); if (textDecorations == null || textDecorations.Count == 0) { result = new TextHidden(LineBase._elementEdgeCharacterLength); } else { result = new TextEndOfSegment(LineBase._elementEdgeCharacterLength); } } } return(result); }
// Token: 0x06006B36 RID: 27446 RVA: 0x001EF6F4 File Offset: 0x001ED8F4 internal override bool InvalidateStructure(int startPosition) { Invariant.Assert(base.ParagraphEndCharacterPosition >= startPosition); bool result = false; if (base.ParagraphStartCharacterPosition == startPosition) { result = true; AnchoredBlock anchoredBlock = null; if (this._attachedObjects != null && this._attachedObjects.Count > 0) { anchoredBlock = (AnchoredBlock)this._attachedObjects[0].Element; } if (anchoredBlock != null && startPosition == anchoredBlock.ElementStartOffset) { StaticTextPointer staticTextPointerFromCP = TextContainerHelper.GetStaticTextPointerFromCP(base.StructuralCache.TextContainer, startPosition); if (staticTextPointerFromCP.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart) { result = (anchoredBlock != staticTextPointerFromCP.GetAdjacentElement(LogicalDirection.Forward)); } } } this.InvalidateTextFormatCache(); if (this._attachedObjects != null) { for (int i = 0; i < this._attachedObjects.Count; i++) { BaseParagraph para = this._attachedObjects[i].Para; if (para.ParagraphEndCharacterPosition >= startPosition) { para.InvalidateStructure(startPosition); } } } return(result); }
/// <summary> /// Return next TextRun at element edge start position /// </summary> /// <param name="position"> /// Current position in text array /// </param> protected TextRun HandleElementStartEdge(StaticTextPointer position) { Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart, "TextPointer does not point to element start edge."); // In the future, handle visibility collapsed. TextRun run = null; TextElement element = (TextElement)position.GetAdjacentElement(LogicalDirection.Forward); Debug.Assert(element != null, "Cannot use ITextContainer that does not provide TextElement instances."); Invariant.Assert(!(element is Block), "We do not expect any Blocks inside Paragraphs"); // Treat figure and floaters as special hidden runs. if (element is Figure || element is Floater) { // Get the length of the element int cch = TextContainerHelper.GetElementLength(_paraClient.Paragraph.StructuralCache.TextContainer, element); // Create special hidden run. run = new FloatingRun(cch, element is Figure); if (element is Figure) { _hasFigures = true; } else { _hasFloaters = true; } } else if (element is LineBreak) { int cch = TextContainerHelper.GetElementLength(_paraClient.Paragraph.StructuralCache.TextContainer, element); run = new LineBreakRun(cch, PTS.FSFLRES.fsflrSoftBreak); } else if (element.IsEmpty) { // Empty TextElement should affect line metrics. // TextFormatter does not support this feature right now, so as workaround // TextRun with ZERO WIDTH SPACE is used. TextProperties textProps = new TextProperties(element, position, false /* inline objects */, true /* get background */, _paraClient.Paragraph.StructuralCache.TextFormatterHost.PixelsPerDip); char[] textBuffer = new char[_elementEdgeCharacterLength * 2]; // Assert that _elementEdgeCharacterLength is 1 before we use hard-coded indices Invariant.Assert(_elementEdgeCharacterLength == 1, "Expected value of _elementEdgeCharacterLength is 1"); textBuffer[0] = (char)0x200B; textBuffer[1] = (char)0x200B; run = new TextCharacters(textBuffer, 0, textBuffer.Length, textProps); } else { Inline inline = (Inline)element; DependencyObject parent = inline.Parent; FlowDirection inlineFlowDirection = inline.FlowDirection; FlowDirection parentFlowDirection = inlineFlowDirection; TextDecorationCollection inlineTextDecorations = DynamicPropertyReader.GetTextDecorations(inline); if (parent != null) { parentFlowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty); } if (inlineFlowDirection != parentFlowDirection) { // Inline's flow direction is different from its parent. Need to create new TextSpanModifier with flow direction if (inlineTextDecorations == null || inlineTextDecorations.Count == 0) { run = new TextSpanModifier( _elementEdgeCharacterLength, null, null, inlineFlowDirection ); } else { run = new TextSpanModifier( _elementEdgeCharacterLength, inlineTextDecorations, inline.Foreground, inlineFlowDirection ); } } else { if (inlineTextDecorations == null || inlineTextDecorations.Count == 0) { run = new TextHidden(_elementEdgeCharacterLength); } else { run = new TextSpanModifier( _elementEdgeCharacterLength, inlineTextDecorations, inline.Foreground ); } } } return(run); }
// Token: 0x0600688E RID: 26766 RVA: 0x001D7E38 File Offset: 0x001D6038 protected TextRun HandleElementStartEdge(StaticTextPointer position) { Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart, "TextPointer does not point to element start edge."); TextElement textElement = (TextElement)position.GetAdjacentElement(LogicalDirection.Forward); Invariant.Assert(!(textElement is Block), "We do not expect any Blocks inside Paragraphs"); TextRun result; if (textElement is Figure || textElement is Floater) { int elementLength = TextContainerHelper.GetElementLength(this._paraClient.Paragraph.StructuralCache.TextContainer, textElement); result = new FloatingRun(elementLength, textElement is Figure); if (textElement is Figure) { this._hasFigures = true; } else { this._hasFloaters = true; } } else if (textElement is LineBreak) { int elementLength2 = TextContainerHelper.GetElementLength(this._paraClient.Paragraph.StructuralCache.TextContainer, textElement); result = new LineBreakRun(elementLength2, PTS.FSFLRES.fsflrSoftBreak); } else if (textElement.IsEmpty) { TextProperties textRunProperties = new TextProperties(textElement, position, false, true, this._paraClient.Paragraph.StructuralCache.TextFormatterHost.PixelsPerDip); char[] array = new char[LineBase._elementEdgeCharacterLength * 2]; Invariant.Assert(LineBase._elementEdgeCharacterLength == 1, "Expected value of _elementEdgeCharacterLength is 1"); array[0] = ''; array[1] = ''; result = new TextCharacters(array, 0, array.Length, textRunProperties); } else { Inline inline = (Inline)textElement; DependencyObject parent = inline.Parent; FlowDirection flowDirection = inline.FlowDirection; FlowDirection flowDirection2 = flowDirection; TextDecorationCollection textDecorations = DynamicPropertyReader.GetTextDecorations(inline); if (parent != null) { flowDirection2 = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty); } if (flowDirection != flowDirection2) { if (textDecorations == null || textDecorations.Count == 0) { result = new TextSpanModifier(LineBase._elementEdgeCharacterLength, null, null, flowDirection); } else { result = new TextSpanModifier(LineBase._elementEdgeCharacterLength, textDecorations, inline.Foreground, flowDirection); } } else if (textDecorations == null || textDecorations.Count == 0) { result = new TextHidden(LineBase._elementEdgeCharacterLength); } else { result = new TextSpanModifier(LineBase._elementEdgeCharacterLength, textDecorations, inline.Foreground); } } return(result); }
// ------------------------------------------------------------------ // Fetch the next run at element open edge position. // // position - current position in the text array // ------------------------------------------------------------------ private TextRun HandleElementStartEdge(StaticTextPointer position) { Debug.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart, "TextPointer does not point to element start edge."); // TextRun run = null; TextElement element = (TextElement)position.GetAdjacentElement(LogicalDirection.Forward); Debug.Assert(element != null, "Cannot use ITextContainer that does not provide TextElement instances."); if (element is LineBreak) { run = new TextEndOfLine(_elementEdgeCharacterLength * 2); } else if (element.IsEmpty) { // Empty TextElement should affect line metrics. // TextFormatter does not support this feature right now, so as workaround // TextRun with ZERO WIDTH SPACE is used. TextRunProperties textProps = new TextProperties(element, position, false /* inline objects */, true /* get background */); char[] textBuffer = new char[_elementEdgeCharacterLength * 2]; textBuffer[0] = (char)0x200B; textBuffer[1] = (char)0x200B; run = new TextCharacters(textBuffer, 0, textBuffer.Length, textProps); } else { Inline inline = element as Inline; if (inline == null) { run = new TextHidden(_elementEdgeCharacterLength); } else { DependencyObject parent = inline.Parent; FlowDirection inlineFlowDirection = inline.FlowDirection; FlowDirection parentFlowDirection = inlineFlowDirection; if (parent != null) { parentFlowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty); } TextDecorationCollection inlineTextDecorations = DynamicPropertyReader.GetTextDecorations(inline); if (inlineFlowDirection != parentFlowDirection) { // Inline's flow direction is different from its parent. Need to create new TextSpanModifier with flow direction if (inlineTextDecorations == null || inlineTextDecorations.Count == 0) { run = new TextSpanModifier( _elementEdgeCharacterLength, null, null, inlineFlowDirection ); } else { run = new TextSpanModifier( _elementEdgeCharacterLength, inlineTextDecorations, inline.Foreground, inlineFlowDirection ); } } else { if (inlineTextDecorations == null || inlineTextDecorations.Count == 0) { run = new TextHidden(_elementEdgeCharacterLength); } else { run = new TextSpanModifier( _elementEdgeCharacterLength, inlineTextDecorations, inline.Foreground ); } } } } return(run); }