From 3f05ced59cdc6eef31590d90b2eac05872706937 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 4 Sep 2011 18:15:38 +0200 Subject: [PATCH] Use DrawingVisual for rendering a VisualLine. This seems to improve AvalonEdit rendering performance a lot in some scenarios. --- .../Rendering/TextLayer.cs | 34 +++++++++++++++++-- .../Rendering/TextView.cs | 14 ++++---- .../Rendering/VisualLine.cs | 30 ++++++++++++++++ 3 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextLayer.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextLayer.cs index e2b06e337b..469884669b 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextLayer.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextLayer.cs @@ -33,10 +33,38 @@ namespace ICSharpCode.AvalonEdit.Rendering { } - protected override void OnRender(DrawingContext drawingContext) + List visuals = new List(); + + internal void SetVisualLines(ICollection visualLines) + { + foreach (VisualLineDrawingVisual v in visuals) { + if (v.VisualLine.IsDisposed) + RemoveVisualChild(v); + } + visuals.Clear(); + foreach (VisualLine newLine in visualLines) { + VisualLineDrawingVisual v = newLine.Render(); + if (!v.IsAdded) { + AddVisualChild(v); + v.IsAdded = true; + } + visuals.Add(v); + } + InvalidateArrange(); + } + + protected override int VisualChildrenCount { + get { return visuals.Count; } + } + + protected override Visual GetVisualChild(int index) + { + return visuals[index]; + } + + protected override void ArrangeCore(Rect finalRect) { - base.OnRender(drawingContext); - textView.RenderTextLayer(drawingContext); + textView.ArrangeTextLayer(visuals); } } } diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs index 68483921bb..8f6b72339b 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs @@ -833,7 +833,6 @@ namespace ICSharpCode.AvalonEdit.Rendering MeasureInlineObjects(); InvalidateVisual(); // = InvalidateArrange+InvalidateRender - textLayer.InvalidateVisual(); double maxWidth; if (document == null) { @@ -862,6 +861,8 @@ namespace ICSharpCode.AvalonEdit.Rendering } } + textLayer.SetVisualLines(visibleVisualLines); + SetScrollData(availableSize, new Size(maxWidth, heightTreeHeight), scrollOffset); @@ -1153,14 +1154,13 @@ namespace ICSharpCode.AvalonEdit.Rendering } } - internal void RenderTextLayer(DrawingContext drawingContext) + internal void ArrangeTextLayer(IList visuals) { Point pos = new Point(-scrollOffset.X, -clippedPixelsOnTop); - foreach (VisualLine visualLine in allVisualLines) { - foreach (TextLine textLine in visualLine.TextLines) { - textLine.Draw(drawingContext, pos, InvertAxes.None); - pos.Y += textLine.Height; - } + foreach (VisualLineDrawingVisual visual in visuals) { + visual.Transform = new TranslateTransform(pos.X, pos.Y); + visual.Transform.Freeze(); + pos.Y += visual.Height; } } #endregion diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs index 53b606521f..4d8ef56fc8 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs @@ -1,6 +1,7 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +using System.Windows.Media; using ICSharpCode.AvalonEdit.Utils; using System; using System.Collections.Generic; @@ -424,5 +425,34 @@ namespace ICSharpCode.AvalonEdit.Rendering { return true; } + + VisualLineDrawingVisual visual; + + internal VisualLineDrawingVisual Render() + { + if (visual == null) + visual = new VisualLineDrawingVisual(this); + return visual; + } + } + + sealed class VisualLineDrawingVisual : DrawingVisual + { + public readonly VisualLine VisualLine; + public readonly double Height; + internal bool IsAdded; + + public VisualLineDrawingVisual(VisualLine visualLine) + { + this.VisualLine = visualLine; + var drawingContext = RenderOpen(); + double pos = 0; + foreach (TextLine textLine in visualLine.TextLines) { + textLine.Draw(drawingContext, new Point(0, pos), InvertAxes.None); + pos += textLine.Height; + } + this.Height = pos; + drawingContext.Close(); + } } }