/// <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 void UpdateClip(IControl control, TransformedBounds bounds) { var clip = control.Clip as RectangleGeometry; if (clip == null) { clip = new RectangleGeometry { Transform = new MatrixTransform() }; control.Clip = clip; } clip.Rect = bounds.Bounds; }
public void Static_Render_Method_Does_Not_Update_TransformedBounds() { using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface)) { var target = new Border(); var expected = new TransformedBounds(new Rect(1, 2, 3, 4), new Rect(4, 5, 6, 7), Matrix.CreateRotation(0.8)); ((IVisual)target).TransformedBounds = expected; var renderTarget = Mock.Of <IRenderTarget>(x => x.CreateDrawingContext(It.IsAny <IVisualBrushRenderer>()) == Mock.Of <IDrawingContextImpl>()); ImmediateRenderer.Render(target, renderTarget); Assert.Equal(expected, target.TransformedBounds); } }
private void UpdateClip(IControl control, TransformedBounds bounds) { if (!(control.Clip is RectangleGeometry clip)) { clip = new RectangleGeometry(); control.Clip = clip; } var clipBounds = bounds.Bounds; if (bounds.Transform.HasInverse) { clipBounds = bounds.Clip.TransformToAABB(bounds.Transform.Invert()); } clip.Rect = clipBounds; }
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 { } var transformed = new TransformedBounds(new Rect(visual.Bounds.Size), clip, node.Transform); visual.TransformedBounds = 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 visual.TransformedBounds = 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); } }
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; #pragma warning disable CS0618 // Type or member is obsolete var clipToBoundsRadius = visual is IVisualWithRoundRectClip roundRectClip ? roundRectClip.ClipToBoundsRadius : default; #pragma warning restore CS0618 // Type or member is obsolete 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 = node != scene.Root ? Matrix.CreateTranslation(visual.Bounds.Position) : Matrix.Identity; 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 globalBounds = bounds.TransformToAABB(contextImpl.Transform); var clipBounds = clipToBounds ? globalBounds.Intersect(clip) : clip; forceRecurse = forceRecurse || node.ClipBounds != clipBounds || node.Opacity != opacity || node.Transform != contextImpl.Transform; node.Transform = contextImpl.Transform; node.ClipBounds = clipBounds; node.ClipToBounds = clipToBounds; node.LayoutBounds = globalBounds; node.ClipToBoundsRadius = clipToBoundsRadius; 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 { } var transformed = new TransformedBounds(new Rect(visual.Bounds.Size), clip, node.Transform); visual.TransformedBounds = transformed; if (forceRecurse) { var visualChildren = (IList <IVisual>)visual.VisualChildren; node.TryPreallocateChildren(visualChildren.Count); if (visualChildren.Count == 1) { var childNode = GetOrCreateChildNode(scene, visualChildren[0], node); Update(context, scene, (VisualNode)childNode, clip, forceRecurse); } else if (visualChildren.Count > 1) { var count = visualChildren.Count; var sortedChildren = new (IVisual visual, int index)[count];
private static Vector GetTranslate(TransformedBounds bounds) { return(new Vector(bounds.Transform.M31, bounds.Transform.M32)); }
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; // this should be calculated BEFORE renderTransform if (visual.HasMirrorTransform) { var mirrorMatrix = new Matrix(-1.0, 0.0, 0.0, 1.0, visual.Bounds.Width, 0); renderTransform *= mirrorMatrix; } if (visual.RenderTransform != null) { var origin = visual.RenderTransformOrigin.ToPixels(new Size(visual.Bounds.Width, visual.Bounds.Height)); var offset = Matrix.CreateTranslation(origin); var finalTransform = (-offset) * visual.RenderTransform.Value * (offset); renderTransform *= finalTransform; } m = renderTransform * m; if (clipToBounds) { if (visual.RenderTransform != null) { clipRect = new Rect(visual.Bounds.Size); } else { clipRect = clipRect.Intersect(new Rect(visual.Bounds.Size)); } } using (context.PushPostTransform(m)) using (context.PushOpacity(opacity)) using (clipToBounds #pragma warning disable CS0618 // Type or member is obsolete ? visual is IVisualWithRoundRectClip roundClipVisual ? context.PushClip(new RoundedRect(bounds, roundClipVisual.ClipToBoundsRadius)) : context.PushClip(bounds) : default(DrawingContext.PushedState)) #pragma warning restore CS0618// Type or member is obsolete 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 (_updateTransformedBounds) { visual.TransformedBounds = transformed; } foreach (var child in visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance)) { var childBounds = GetTransformedBounds(child); if (!child.ClipToBounds || clipRect.Intersects(childBounds)) { var childClipRect = child.RenderTransform == null ? clipRect.Translate(-childBounds.Position) : clipRect; Render(context, child, childClipRect); } else if (_updateTransformedBounds) { ClearTransformedBounds(child); } } } } if (!visual.IsVisible && _updateTransformedBounds) { ClearTransformedBounds(visual); } }
public bool Equals(TransformedBounds other) { return(Bounds == other.Bounds && Clip == other.Clip && Transform == other.Transform); }