internal void ConstructVisualElements(ITextRunConstructionContext context, VisualLineElementGenerator[] generators) { foreach (VisualLineElementGenerator g in generators) { g.StartGeneration(context); } elements = new List<VisualLineElement>(); PerformVisualElementConstruction(generators); foreach (VisualLineElementGenerator g in generators) { g.FinishGeneration(); } this.Elements = elements.AsReadOnly(); CalculateOffsets(context.GlobalTextRunProperties); }
internal void ConstructVisualElements(ITextRunConstructionContext context, VisualLineElementGenerator[] generators) { foreach (VisualLineElementGenerator g in generators) { g.StartGeneration(context); } elements = new List<VisualLineElement>(); PerformVisualElementConstruction(generators); foreach (VisualLineElementGenerator g in generators) { g.FinishGeneration(); } // if (FirstDocumentLine.Length != 0) // elements.Add(new VisualLineText(FirstDocumentLine.Text, FirstDocumentLine.Length)); // //elements.Add(new VisualNewLine(VisualNewLine.NewLineType.Lf)); this.Elements = elements.AsReadOnly(); CalculateOffsets(context.GlobalTextRunProperties); }
void PerformVisualElementConstruction(VisualLineElementGenerator[] generators) { TextDocument document = this.Document; int offset = FirstDocumentLine.Offset; int currentLineEnd = offset + FirstDocumentLine.Length; LastDocumentLine = FirstDocumentLine; int askInterestOffset = 0; // 0 or 1 while (offset + askInterestOffset <= currentLineEnd) { int textPieceEndOffset = currentLineEnd; foreach (VisualLineElementGenerator g in generators) { g.cachedInterest = g.GetFirstInterestedOffset(offset + askInterestOffset); if (g.cachedInterest != -1) { if (g.cachedInterest < offset) throw new ArgumentOutOfRangeException(g.GetType().Name + ".GetFirstInterestedOffset", g.cachedInterest, "GetFirstInterestedOffset must not return an offset less than startOffset. Return -1 to signal no interest."); if (g.cachedInterest < textPieceEndOffset) textPieceEndOffset = g.cachedInterest; } } Debug.Assert(textPieceEndOffset >= offset); if (textPieceEndOffset > offset) { int textPieceLength = textPieceEndOffset - offset; elements.Add(new VisualLineText(this, textPieceLength)); offset = textPieceEndOffset; } // If no elements constructed / only zero-length elements constructed: // do not asking the generators again for the same location (would cause endless loop) askInterestOffset = 1; foreach (VisualLineElementGenerator g in generators) { if (g.cachedInterest == offset) { VisualLineElement element = g.ConstructElement(offset); if (element != null) { elements.Add(element); if (element.DocumentLength > 0) { // a non-zero-length element was constructed askInterestOffset = 0; offset += element.DocumentLength; if (offset > currentLineEnd) { DocumentLine newEndLine = document.GetLineByOffset(offset); if (newEndLine == this.LastDocumentLine) { throw new InvalidOperationException( "The VisualLineElementGenerator " + g.GetType().Name + " produced an element which ends within the line delimiter"); } currentLineEnd = newEndLine.Offset + newEndLine.Length; this.LastDocumentLine = newEndLine; } break; } } } } } }
internal void ConstructVisualElements(ITextRunConstructionContext context, VisualLineElementGenerator[] generators) { Debug.Assert(phase == LifetimePhase.Generating); foreach (VisualLineElementGenerator g in generators) { g.StartGeneration(context); } elements = new List<VisualLineElement>(); PerformVisualElementConstruction(generators); foreach (VisualLineElementGenerator g in generators) { g.FinishGeneration(); } var globalTextRunProperties = context.GlobalTextRunProperties; foreach (var element in elements) { element.SetTextRunProperties(new VisualLineElementTextRunProperties(globalTextRunProperties)); } this.Elements = elements.AsReadOnly(); CalculateOffsets(); phase = LifetimePhase.Transforming; }
public void AddVisualLineElementGenerator(VisualLineElementGenerator elementGenerator) { ElementGenerators.Add(elementGenerator); }
void PerformVisualElementConstruction(VisualLineElementGenerator[] generators) { TextDocument document = FirstDocumentLine.Document; int offset = FirstDocumentLine.Offset; int currentLineEnd = offset + FirstDocumentLine.Length; LastDocumentLine = FirstDocumentLine; int askInterestOffset = 0; // 0 or 1 while (offset + askInterestOffset <= currentLineEnd) { int textPieceEndOffset = currentLineEnd; foreach (VisualLineElementGenerator g in generators) { g.cachedInterest = g.GetFirstInterestedOffset(offset + askInterestOffset); if (g.cachedInterest != -1) { if (g.cachedInterest < offset) throw new ArgumentOutOfRangeException(g.GetType().Name + ".GetFirstInterestedOffset", g.cachedInterest, "GetFirstInterestedOffset must not return an offset less than startOffset. Return -1 to signal no interest."); if (g.cachedInterest < textPieceEndOffset) textPieceEndOffset = g.cachedInterest; } } Debug.Assert(textPieceEndOffset >= offset); if (textPieceEndOffset > offset) { int textPieceLength = textPieceEndOffset - offset; elements.Add(new VisualLineText(this, textPieceLength)); offset = textPieceEndOffset; } // if no elements constructed / only zero-length elements constructed: // prevent endless loop by asking the generators again for the same location askInterestOffset = 1; foreach (VisualLineElementGenerator g in generators) { if (g.cachedInterest == offset) { VisualLineElement element = g.ConstructElement(offset); if (element != null) { elements.Add(element); if (element.DocumentLength > 0) { // a non-zero-length element was constructed askInterestOffset = 0; offset += element.DocumentLength; if (offset > currentLineEnd) { LastDocumentLine = document.GetLineByOffset(offset); currentLineEnd = LastDocumentLine.Offset + LastDocumentLine.Length; } break; } } } } } }