diff --git a/src/Perspex.SceneGraph/Media/DrawingContext.cs b/src/Perspex.SceneGraph/Media/DrawingContext.cs index 32edc8d8fa..a191cb1fce 100644 --- a/src/Perspex.SceneGraph/Media/DrawingContext.cs +++ b/src/Perspex.SceneGraph/Media/DrawingContext.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -12,15 +13,42 @@ namespace Perspex.Media private readonly IDrawingContextImpl _impl; private int _currentLevel; + private Stack _transformContainers = new Stack(); + + struct TransformContainer + { + public Matrix LocalTransform; + public Matrix ContainerTransform; + + public TransformContainer(Matrix localTransform, Matrix containerTransform) + { + LocalTransform = localTransform; + ContainerTransform = containerTransform; + } + } + public DrawingContext(IDrawingContextImpl impl) { _impl = impl; } + + private Matrix _currentTransform = Matrix.Identity; + /// /// Gets the current transform of the drawing context. /// - public Matrix CurrentTransform => _impl.Transform; + public Matrix CurrentTransform + { + get { return _currentTransform; } + private set + { + _currentTransform = value; + _impl.Transform = _currentTransform*_currentContainerTransform; + } + } + + private Matrix _currentContainerTransform = Matrix.Identity; /// /// Draws a bitmap image. @@ -87,7 +115,8 @@ namespace Perspex.Media None, Matrix, Opacity, - Clip + Clip, + MatrixContainer } public PushedState(DrawingContext context, PushedStateType type, Matrix matrix = default(Matrix)) @@ -107,15 +136,18 @@ namespace Perspex.Media throw new InvalidOperationException("Wrong Push/Pop state order"); _context._currentLevel--; if (_type == PushedStateType.Matrix) - _context._impl.Transform = _matrix; + _context.CurrentTransform = _matrix; else if(_type == PushedStateType.Clip) _context._impl.PopClip(); - else if(_type == PushedStateType.Opacity) _context._impl.PopOpacity(); + else if (_type == PushedStateType.MatrixContainer) + { + var cont = _context._transformContainers.Pop(); + _context._currentContainerTransform = cont.ContainerTransform; + _context.CurrentTransform = cont.LocalTransform; + } } - - } @@ -155,10 +187,20 @@ namespace Perspex.Media PushedState PushSetTransform(Matrix matrix) { var oldMatrix = CurrentTransform; - _impl.Transform = matrix; + CurrentTransform = matrix; + return new PushedState(this, PushedState.PushedStateType.Matrix, oldMatrix); } + + public PushedState PushTransformContainer() + { + _transformContainers.Push(new TransformContainer(CurrentTransform, _currentContainerTransform)); + _currentContainerTransform = CurrentTransform*_currentContainerTransform; + _currentTransform = Matrix.Identity; + return new PushedState(this, PushedState.PushedStateType.MatrixContainer); + } + public void Dispose() => _impl.Dispose(); } } diff --git a/src/Perspex.SceneGraph/Rendering/RendererBase.cs b/src/Perspex.SceneGraph/Rendering/RendererBase.cs index 88601e7ef8..7a7db8f842 100644 --- a/src/Perspex.SceneGraph/Rendering/RendererBase.cs +++ b/src/Perspex.SceneGraph/Rendering/RendererBase.cs @@ -52,10 +52,10 @@ namespace Perspex.Rendering } m = renderTransform*m; - - using (context.PushPreTransform(m)) + using (context.PushPostTransform(m)) using (context.PushOpacity(opacity)) using (visual.ClipToBounds ? context.PushClip(new Rect(visual.Bounds.Size)) : default(DrawingContext.PushedState)) + using (context.PushTransformContainer()) { visual.Render(context); foreach (var child in visual.VisualChildren.OrderBy(x => x.ZIndex))