示例#1
0
        /// <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);
                                    }
            }
        }
示例#2
0
        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);
            }
        }
示例#4
0
        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;
        }
示例#5
0
        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();
                            }
                        }
            }
        }
示例#6
0
        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);
            }
        }
示例#7
0
        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));
 }
示例#9
0
        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);
            }
        }
示例#10
0
 public bool Equals(TransformedBounds other)
 {
     return(Bounds == other.Bounds && Clip == other.Clip && Transform == other.Transform);
 }