Browse Source

Merge branch 'master' into platform-options

Steven Kirk 6 years ago
parent
commit
92a279c2d2

+ 1 - 1
src/Avalonia.Controls/Presenters/TextPresenter.cs

@@ -275,7 +275,7 @@ namespace Avalonia.Controls.Presenters
                     Typeface = new Typeface(FontFamily, FontSize, FontStyle, FontWeight),
                     TextAlignment = TextAlignment,
                     Constraint = availableSize,
-                }.Measure();
+                }.Bounds.Size;
             }
         }
 

+ 1 - 1
src/Avalonia.Controls/TextBlock.cs

@@ -396,7 +396,7 @@ namespace Avalonia.Controls
                     FormattedText.Constraint = Size.Infinity;
                 }
 
-                return FormattedText.Measure();
+                return FormattedText.Bounds.Size;
             }
 
             return new Size();

+ 0 - 3
src/Avalonia.Controls/UserControl.cs

@@ -27,9 +27,6 @@ namespace Avalonia.Controls
             remove { _nameScope.Unregistered -= value; }
         }
 
-        /// <inheritdoc/>
-        Type IStyleable.StyleKey => typeof(UserControl);
-
         /// <inheritdoc/>
         void INameScope.Register(string name, object element)
         {

+ 1 - 1
src/Avalonia.Themes.Default/UserControl.xaml

@@ -1,4 +1,4 @@
-<Style xmlns="https://github.com/avaloniaui" Selector="UserControl">
+<Style xmlns="https://github.com/avaloniaui" Selector=":is(UserControl)">
   <Setter Property="Template">
     <ControlTemplate>
       <ContentPresenter Name="PART_ContentPresenter"

+ 6 - 9
src/Avalonia.Visuals/Media/FormattedText.cs

@@ -37,6 +37,12 @@ namespace Avalonia.Media
             _platform = platform;
         }
 
+        /// <summary>
+        /// Gets the bounds of the text within the <see cref="Constraint"/>.
+        /// </summary>
+        /// <returns>The bounds of the text.</returns>
+        public Rect Bounds => PlatformImpl.Bounds;
+
         /// <summary>
         /// Gets or sets the constraint of the text.
         /// </summary>
@@ -158,15 +164,6 @@ namespace Avalonia.Media
             return PlatformImpl.HitTestTextRange(index, length);
         }
 
-        /// <summary>
-        /// Gets the size of the text, taking <see cref="Constraint"/> into account.
-        /// </summary>
-        /// <returns>The bounds box of the text.</returns>
-        public Size Measure()
-        {
-            return PlatformImpl.Size;
-        }
-
         private void Set<T>(ref T field, T value)
         {
             field = value;

+ 3 - 2
src/Avalonia.Visuals/Platform/IFormattedTextImpl.cs

@@ -1,6 +1,7 @@
 // Copyright (c) The Avalonia Project. All rights reserved.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
+using System;
 using System.Collections.Generic;
 using Avalonia.Media;
 
@@ -17,9 +18,9 @@ namespace Avalonia.Platform
         Size Constraint { get; }
 
         /// <summary>
-        /// The measured size of the text.
+        /// The measured bounds of the text.
         /// </summary>
-        Size Size { get; }
+        Rect Bounds{ get; }
 
         /// <summary>
         /// Gets the text.

+ 1 - 1
src/Avalonia.Visuals/Rendering/RendererBase.cs

@@ -45,7 +45,7 @@ namespace Avalonia.Rendering
                 _fpsText.Text = string.Format("FPS: {0:000}", _fps);
             }
 
-            var size = _fpsText.Measure();
+            var size = _fpsText.Bounds.Size;
             var rect = new Rect(clientRect.Right - size.Width, 0, size.Width, size.Height);
 
             context.Transform = Matrix.Identity;

+ 1 - 1
src/Avalonia.Visuals/Rendering/SceneGraph/TextNode.cs

@@ -27,7 +27,7 @@ namespace Avalonia.Rendering.SceneGraph
             Point origin,
             IFormattedTextImpl text,
             IDictionary<IVisual, Scene> childScenes = null)
-            : base(new Rect(origin, text.Size), transform, null)
+            : base(text.Bounds.Translate(origin), transform, null)
         {
             Transform = transform;
             Foreground = foreground?.ToImmutable();

+ 36 - 0
src/Avalonia.Visuals/VisualTree/TransformedBounds.cs

@@ -50,5 +50,41 @@ namespace Avalonia.VisualTree
                 return Bounds.Contains(point);
             }
         }
+
+        public bool Equals(TransformedBounds other)
+        {
+            return Bounds == other.Bounds && Clip == other.Clip && Transform == other.Transform;
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (obj is null)
+            {
+                return false;
+            }
+
+            return obj is TransformedBounds other && Equals(other);
+        }
+
+        public override int GetHashCode()
+        {
+            unchecked
+            {
+                var hashCode = Bounds.GetHashCode();
+                hashCode = (hashCode * 397) ^ Clip.GetHashCode();
+                hashCode = (hashCode * 397) ^ Transform.GetHashCode();
+                return hashCode;
+            }
+        }
+
+        public static bool operator ==(TransformedBounds left, TransformedBounds right)
+        {
+            return left.Equals(right);
+        }
+
+        public static bool operator !=(TransformedBounds left, TransformedBounds right)
+        {
+            return !left.Equals(right);
+        }
     }
 }

+ 1 - 1
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@@ -218,7 +218,7 @@ namespace Avalonia.Skia
         /// <inheritdoc />
         public void DrawText(IBrush foreground, Point origin, IFormattedTextImpl text)
         {
-            using (var paint = CreatePaint(foreground, text.Size))
+            using (var paint = CreatePaint(foreground, text.Bounds.Size))
             {
                 var textImpl = (FormattedTextImpl) text;
                 textImpl.Draw(this, Canvas, origin.ToSKPoint(), paint, _canTextUseLcdRendering);

+ 20 - 6
src/Skia/Avalonia.Skia/FormattedTextImpl.cs

@@ -89,7 +89,7 @@ namespace Avalonia.Skia
 
         public Size Constraint => _constraint;
 
-        public Size Size => _size;
+        public Rect Bounds => _bounds;
 
         public IEnumerable<FormattedTextLine> GetLines()
         {
@@ -135,7 +135,7 @@ namespace Avalonia.Skia
                 };
             }
 
-            bool end = point.X > _size.Width || point.Y > _lines.Sum(l => l.Height);
+            bool end = point.X > _bounds.Width || point.Y > _lines.Sum(l => l.Height);
 
             return new TextHitTestResult()
             {
@@ -323,7 +323,7 @@ namespace Avalonia.Skia
         private Size _constraint = new Size(double.PositiveInfinity, double.PositiveInfinity);
         private float _lineHeight = 0;
         private float _lineOffset = 0;
-        private Size _size;
+        private Rect _bounds;
         private List<AvaloniaFormattedTextLine> _skiaLines;
 
         private static void ApplyWrapperTo(ref SKPaint current, DrawingContextImpl.PaintWrapper wrapper,
@@ -639,12 +639,26 @@ namespace Avalonia.Skia
             if (_skiaLines.Count == 0)
             {
                 _lines.Add(new FormattedTextLine(0, _lineHeight));
-                _size = new Size(0, _lineHeight);
+                _bounds = new Rect(0, 0, 0, _lineHeight);
             }
             else
             {
                 var lastLine = _skiaLines[_skiaLines.Count - 1];
-                _size = new Size(maxX, lastLine.Top + lastLine.Height);
+                _bounds = new Rect(0, 0, maxX, lastLine.Top + lastLine.Height);
+
+                switch (_paint.TextAlign)
+                {
+                    case SKTextAlign.Center:
+                        _bounds = new Rect(Constraint).CenterRect(_bounds);
+                        break;
+                    case SKTextAlign.Right:
+                        _bounds = new Rect(
+                            Constraint.Width - _bounds.Width,
+                            0,
+                            _bounds.Width,
+                            _bounds.Height);
+                        break;
+                }
             }
         }
 
@@ -660,7 +674,7 @@ namespace Avalonia.Skia
             {
                 double width = Constraint.Width > 0 && !double.IsPositiveInfinity(Constraint.Width) ?
                                 Constraint.Width :
-                                _size.Width;
+                                _bounds.Width;
 
                 switch (align)
                 {

+ 1 - 1
src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs

@@ -274,7 +274,7 @@ namespace Avalonia.Direct2D1.Media
             {
                 var impl = (FormattedTextImpl)text;
 
-                using (var brush = CreateBrush(foreground, impl.Size))
+                using (var brush = CreateBrush(foreground, impl.Bounds.Size))
                 using (var renderer = new AvaloniaTextRenderer(this, _deviceContext, brush.PlatformBrush))
                 {
                     if (brush.PlatformBrush != null)

+ 8 - 4
src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs

@@ -45,12 +45,12 @@ namespace Avalonia.Direct2D1.Media
                 }
             }
 
-            Size = Measure();
+            Bounds = Measure();
         }
 
         public Size Constraint => new Size(TextLayout.MaxWidth, TextLayout.MaxHeight);
 
-        public Size Size { get; }
+        public Rect Bounds { get; }
 
         public string Text { get; }
 
@@ -104,7 +104,7 @@ namespace Avalonia.Direct2D1.Media
             }
         }
 
-        private Size Measure()
+        private Rect Measure()
         {
             var metrics = TextLayout.Metrics;
 
@@ -115,7 +115,11 @@ namespace Avalonia.Direct2D1.Media
                 width = metrics.Width;
             }
 
-            return new Size(width, TextLayout.Metrics.Height);
+            return new Rect(
+                TextLayout.Metrics.Left,
+                TextLayout.Metrics.Top,
+                width,
+                TextLayout.Metrics.Height);
         }
     }
 }

+ 1 - 1
tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs

@@ -146,7 +146,7 @@ namespace Avalonia.Layout.UnitTests
 
             public string Text { get; }
 
-            public Size Size => new Size();
+            public Rect Bounds => Rect.Empty;
 
             public void Dispose()
             {

+ 2 - 2
tests/Avalonia.RenderTests/Media/FormattedTextImplTests.cs

@@ -100,7 +100,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media
         public void Should_Measure_String_Correctly(string input, double fontSize, double expWidth, double expHeight)
         {
             var fmt = Create(input, fontSize);
-            var size = fmt.Size;
+            var size = fmt.Bounds.Size;
 
             Assert.Equal(expWidth, size.Width, 2);
             Assert.Equal(expHeight, size.Height, 2);
@@ -265,4 +265,4 @@ namespace Avalonia.Direct2D1.RenderTests.Media
             }
         }
     }
-}
+}

+ 25 - 0
tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/TextNodeTests.cs

@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Avalonia.Platform;
+using Avalonia.Rendering.SceneGraph;
+using Moq;
+using Xunit;
+
+namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
+{
+    public class TextNodeTests
+    {
+        [Fact]
+        public void Bounds_Should_Be_Offset_By_Origin()
+        {
+            var target = new TextNode(
+                Matrix.Identity,
+                null,
+                new Point(10, 10),
+                Mock.Of<IFormattedTextImpl>(x => x.Bounds == new Rect(5, 5, 50, 50)));
+
+            Assert.Equal(new Rect(15, 15, 50, 50), target.Bounds);
+        }
+    }
+}