private static void ClearTransformedBounds(IVisual visual) { foreach (var e in visual.GetSelfAndVisualDescendents()) { BoundsTracker.SetTransformedBounds((Visual)visual, null); } }
private static void Deindex(Scene scene, VisualNode node) { scene.Remove(node); node.SubTreeUpdated = true; scene.Layers[node.LayerRoot].Dirty.Add(node.Bounds); if (node.Visual is Visual v) { BoundsTracker.SetTransformedBounds(v, null); } foreach (VisualNode child in node.Children) { var geometry = child as IDrawOperation; if (child is VisualNode visual) { Deindex(scene, visual); } } if (node.LayerRoot == node.Visual && node.Visual != scene.Root.Visual) { scene.Layers.Remove(node.LayerRoot); } }
/// <summary> /// Renders the specified visual. /// </summary> /// <param name="visual">The visual to render.</param> /// <param name="context">The drawing context.</param> /// <param name="clipRect"> /// The current clip rect, in coordinates relative to <paramref name="visual"/>. /// </param> private static void Render(this DrawingContext context, IVisual visual, Rect clipRect) { var opacity = visual.Opacity; var clipToBounds = visual.ClipToBounds; var bounds = new Rect(visual.Bounds.Size); if (visual.IsVisible && opacity > 0) { var m = Matrix.CreateTranslation(visual.Bounds.Position); var renderTransform = Matrix.Identity; if (visual.RenderTransform != null) { var origin = visual.RenderTransformOrigin.ToPixels(new Size(visual.Bounds.Width, visual.Bounds.Height)); var offset = Matrix.CreateTranslation(origin); renderTransform = (-offset) * visual.RenderTransform.Value * (offset); } m = renderTransform * m; if (clipToBounds) { clipRect = clipRect.Intersect(new Rect(visual.Bounds.Size)); } using (context.PushPostTransform(m)) using (context.PushOpacity(opacity)) using (clipToBounds ? context.PushClip(bounds) : default(DrawingContext.PushedState)) using (visual.Clip != null ? context.PushGeometryClip(visual.Clip) : default(DrawingContext.PushedState)) using (visual.OpacityMask != null ? context.PushOpacityMask(visual.OpacityMask, bounds) : default(DrawingContext.PushedState)) using (context.PushTransformContainer()) { visual.Render(context); var transformed = new TransformedBounds(bounds, new Rect(), context.CurrentContainerTransform); if (visual is Visual) { BoundsTracker.SetTransformedBounds((Visual)visual, transformed); } var lst = GetSortedVisualList(visual.VisualChildren); foreach (var child in lst) { var childBounds = GetTransformedBounds(child); if (!child.ClipToBounds || clipRect.Intersects(childBounds)) { var childClipRect = clipRect.Translate(-childBounds.Position); context.Render(child, childClipRect); } } ReturnListToPool(lst); } } }
private static void Update(DrawingContext context, Scene scene, VisualNode node, Rect clip, bool forceRecurse) { var visual = node.Visual; var opacity = visual.Opacity; var clipToBounds = visual.ClipToBounds; var bounds = new Rect(visual.Bounds.Size); var contextImpl = (DeferredDrawingContextImpl)context.PlatformImpl; contextImpl.Layers.Find(node.LayerRoot)?.Dirty.Add(node.Bounds); if (visual.IsVisible) { var m = Matrix.CreateTranslation(visual.Bounds.Position); var renderTransform = Matrix.Identity; if (visual.RenderTransform != null) { var origin = visual.RenderTransformOrigin.ToPixels(new Size(visual.Bounds.Width, visual.Bounds.Height)); var offset = Matrix.CreateTranslation(origin); renderTransform = (-offset) * visual.RenderTransform.Value * (offset); } m = renderTransform * m; using (contextImpl.BeginUpdate(node)) using (context.PushPostTransform(m)) using (context.PushTransformContainer()) { var clipBounds = bounds.TransformToAABB(contextImpl.Transform).Intersect(clip); forceRecurse = forceRecurse || node.Transform != contextImpl.Transform || node.ClipBounds != clipBounds; node.Transform = contextImpl.Transform; node.ClipBounds = clipBounds; node.ClipToBounds = clipToBounds; node.GeometryClip = visual.Clip?.PlatformImpl; node.Opacity = opacity; // TODO: Check equality between node.OpacityMask and visual.OpacityMask before assigning. node.OpacityMask = visual.OpacityMask?.ToImmutable(); if (ShouldStartLayer(visual)) { if (node.LayerRoot != visual) { MakeLayer(scene, node); } else { UpdateLayer(node, scene.Layers[node.LayerRoot]); } } else if (node.LayerRoot == node.Visual && node.Parent != null) { ClearLayer(scene, node); } if (node.ClipToBounds) { clip = clip.Intersect(node.ClipBounds); } try { visual.Render(context); } catch { } if (visual is Visual) { var transformed = new TransformedBounds(new Rect(visual.Bounds.Size), clip, node.Transform); BoundsTracker.SetTransformedBounds((Visual)visual, transformed); } if (forceRecurse) { foreach (var child in visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance)) { var childNode = scene.FindNode(child) ?? CreateNode(scene, child, node); Update(context, scene, (VisualNode)childNode, clip, forceRecurse); } node.SubTreeUpdated = true; contextImpl.TrimChildren(); } } } }
private void Render(DrawingContext context, IVisual visual, Rect clipRect) { var opacity = visual.Opacity; var clipToBounds = visual.ClipToBounds; var bounds = new Rect(visual.Bounds.Size); if (visual.IsVisible && opacity > 0) { var m = Matrix.CreateTranslation(visual.Bounds.Position); var renderTransform = Matrix.Identity; if (visual.RenderTransform != null) { var origin = visual.RenderTransformOrigin.ToPixels(new Size(visual.Bounds.Width, visual.Bounds.Height)); var offset = Matrix.CreateTranslation(origin); renderTransform = (-offset) * visual.RenderTransform.Value * (offset); } m = renderTransform * m; if (clipToBounds) { clipRect = clipRect.Intersect(new Rect(visual.Bounds.Size)); } using (context.PushPostTransform(m)) using (context.PushOpacity(opacity)) using (clipToBounds ? context.PushClip(bounds) : default(DrawingContext.PushedState)) using (visual.Clip != null ? context.PushGeometryClip(visual.Clip) : default(DrawingContext.PushedState)) using (visual.OpacityMask != null ? context.PushOpacityMask(visual.OpacityMask, bounds) : default(DrawingContext.PushedState)) using (context.PushTransformContainer()) { visual.Render(context); #pragma warning disable 0618 var transformed = new TransformedBounds(bounds, new Rect(), context.CurrentContainerTransform); #pragma warning restore 0618 if (visual is Visual) { BoundsTracker.SetTransformedBounds((Visual)visual, transformed); } foreach (var child in visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance)) { var childBounds = GetTransformedBounds(child); if (!child.ClipToBounds || clipRect.Intersects(childBounds)) { var childClipRect = clipRect.Translate(-childBounds.Position); Render(context, child, childClipRect); } else { ClearTransformedBounds(child); } } } } if (!visual.IsVisible) { ClearTransformedBounds(visual); } }