Browse Source

Merge branch 'master' into skiagl

pull/1935/head
danwalmsley 8 years ago
committed by GitHub
parent
commit
909285305c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      src/Avalonia.Controls/Image.cs
  2. 8
      src/Avalonia.Controls/Presenters/ContentPresenter.cs
  3. 156
      src/Avalonia.Controls/Utils/BorderRenderHelper.cs
  4. 4
      src/Avalonia.Visuals/Media/PathMarkupParser.cs
  5. 2
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github
  6. 25
      tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs

1
src/Avalonia.Controls/Image.cs

@ -26,6 +26,7 @@ namespace Avalonia.Controls
static Image()
{
AffectsRender<Image>(SourceProperty, StretchProperty);
AffectsMeasure<Image>(SourceProperty, StretchProperty);
}
/// <summary>

8
src/Avalonia.Controls/Presenters/ContentPresenter.cs

@ -197,13 +197,6 @@ namespace Avalonia.Controls.Presenters
}
}
/// <inheritdoc/>
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
_dataTemplate = null;
}
/// <summary>
/// Updates the <see cref="Child"/> control based on the control's <see cref="Content"/>.
/// </summary>
@ -268,6 +261,7 @@ namespace Avalonia.Controls.Presenters
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnAttachedToLogicalTree(e);
_dataTemplate = null;
_createdChild = false;
InvalidateMeasure();
}

156
src/Avalonia.Controls/Utils/BorderRenderHelper.cs

@ -88,24 +88,82 @@ namespace Avalonia.Controls.Utils
}
else
{
var borderThickness = borders.Left;
var cornerRadius = (float)radii.TopLeft;
var rect = new Rect(size);
var borderThickness = borders.Top;
var top = borderThickness * 0.5;
var cornerRadius = (float)Math.Max(0, radii.TopLeft - borderThickness - top);
if (background != null)
{
context.FillRectangle(background, rect.Deflate(borders), cornerRadius);
var topLeft = new Point(borders.Left, borders.Top);
var bottomRight = new Point(size.Width - borders.Right, size.Height - borders.Bottom);
var innerRect = new Rect(topLeft, bottomRight);
context.FillRectangle(background, innerRect, cornerRadius);
}
if (borderBrush != null && borderThickness > 0)
{
context.DrawRectangle(new Pen(borderBrush, borderThickness), rect.Deflate(borderThickness), cornerRadius);
var topLeft = new Point(top, top);
var bottomRight = new Point(size.Width - top, size.Height - top);
var outerRect = new Rect(topLeft, bottomRight);
context.DrawRectangle(new Pen(borderBrush, borderThickness), outerRect, (float)radii.TopLeft);
}
}
}
private static void CreateGeometry(StreamGeometryContext context, Rect boundRect, BorderGeometryKeypoints keypoints)
{
context.BeginFigure(keypoints.TopLeft, true);
// Top
context.LineTo(keypoints.TopRight);
// TopRight corner
var radiusX = boundRect.TopRight.X - keypoints.TopRight.X;
var radiusY = keypoints.RightTop.Y - boundRect.TopRight.Y;
if (radiusX != 0 || radiusY != 0)
{
context.ArcTo(keypoints.RightTop, new Size(radiusY, radiusY), 0, false, SweepDirection.Clockwise);
}
// Right
context.LineTo(keypoints.RightBottom);
// BottomRight corner
radiusX = boundRect.BottomRight.X - keypoints.BottomRight.X;
radiusY = boundRect.BottomRight.Y - keypoints.RightBottom.Y;
if (radiusX != 0 || radiusY != 0)
{
context.ArcTo(keypoints.BottomRight, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise);
}
// Bottom
context.LineTo(keypoints.BottomLeft);
// BottomLeft corner
radiusX = keypoints.BottomLeft.X - boundRect.BottomLeft.X;
radiusY = boundRect.BottomLeft.Y - keypoints.LeftBottom.Y;
if (radiusX != 0 || radiusY != 0)
{
context.ArcTo(keypoints.LeftBottom, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise);
}
// Left
context.LineTo(keypoints.LeftTop);
// TopLeft corner
radiusX = keypoints.TopLeft.X - boundRect.TopLeft.X;
radiusY = keypoints.LeftTop.Y - boundRect.TopLeft.Y;
if (radiusX != 0 || radiusY != 0)
{
context.ArcTo(keypoints.TopLeft, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise);
}
context.EndFigure(true);
}
private class BorderGeometryKeypoints
{
{
internal BorderGeometryKeypoints(Rect boundRect, Thickness borderThickness, CornerRadius cornerRadius, bool inner)
{
var left = 0.5 * borderThickness.Left;
@ -135,25 +193,24 @@ namespace Avalonia.Controls.Utils
}
else
{
leftTopY = cornerRadius.TopLeft + top + boundRect.TopLeft.Y;
topLeftX = cornerRadius.TopLeft + left + boundRect.TopLeft.X;
topLeftX = cornerRadius.TopLeft + left + boundRect.TopLeft.X;
topRightX = boundRect.Width - (cornerRadius.TopRight + right) + boundRect.TopLeft.X;
rightTopY = cornerRadius.TopRight + top + boundRect.TopLeft.Y;
rightTopY = cornerRadius.TopRight + top + boundRect.TopLeft.Y;
rightBottomY = boundRect.Height - (cornerRadius.BottomRight + bottom) + boundRect.TopLeft.Y;
bottomRightX = boundRect.Width - (cornerRadius.BottomRight + right) + boundRect.TopLeft.X;
bottomLeftX = cornerRadius.BottomLeft + left + boundRect.TopLeft.X;
bottomRightX = boundRect.Width - (cornerRadius.BottomRight + right) + boundRect.TopLeft.X;
bottomLeftX = cornerRadius.BottomLeft + left + boundRect.TopLeft.X;
leftBottomY = boundRect.Height - (cornerRadius.BottomLeft + bottom) + boundRect.TopLeft.Y;
}
}
var leftTopX = boundRect.TopLeft.X;
var topLeftY = boundRect.TopLeft.Y;
var leftTopX = boundRect.TopLeft.X;
var topLeftY = boundRect.TopLeft.Y;
var topRightY = boundRect.TopLeft.Y;
var rightTopX = boundRect.Width + boundRect.TopLeft.X;
var rightBottomX = boundRect.Width + boundRect.TopLeft.X;
var bottomRightY = boundRect.Height + boundRect.TopLeft.Y;
var rightTopX = boundRect.Width + boundRect.TopLeft.X;
var rightBottomX = boundRect.Width + boundRect.TopLeft.X;
var bottomRightY = boundRect.Height + boundRect.TopLeft.Y;
var bottomLeftY = boundRect.Height + boundRect.TopLeft.Y;
var leftBottomX = boundRect.TopLeft.X;
var leftBottomX = boundRect.TopLeft.X;
LeftTop = new Point(leftTopX, leftTopY);
TopLeft = new Point(topLeftX, topLeftY);
@ -164,7 +221,7 @@ namespace Avalonia.Controls.Utils
BottomLeft = new Point(bottomLeftX, bottomLeftY);
LeftBottom = new Point(leftBottomX, leftBottomY);
//Fix overlap
// Fix overlap
if (TopLeft.X > TopRight.X)
{
var scaledX = topLeftX / (topLeftX + topRightX) * boundRect.Width;
@ -194,66 +251,21 @@ namespace Avalonia.Controls.Utils
}
}
internal Point LeftTop { get; private set; }
internal Point TopLeft { get; private set; }
internal Point TopRight { get; private set; }
internal Point RightTop { get; private set; }
internal Point RightBottom { get; private set; }
internal Point BottomRight { get; private set; }
internal Point BottomLeft { get; private set; }
internal Point LeftBottom { get; private set; }
}
internal Point LeftTop { get; }
private static void CreateGeometry(StreamGeometryContext context, Rect boundRect, BorderGeometryKeypoints keypoints)
{
context.BeginFigure(keypoints.TopLeft, true);
internal Point TopLeft { get; }
//Top
context.LineTo(keypoints.TopRight);
internal Point TopRight { get; }
//TopRight corner
var radiusX = boundRect.TopRight.X - keypoints.TopRight.X;
var radiusY = keypoints.RightTop.Y - boundRect.TopRight.Y;
if (radiusX != 0 || radiusY != 0)
{
context.ArcTo(keypoints.RightTop, new Size(radiusY, radiusY), 0, false, SweepDirection.Clockwise);
}
internal Point RightTop { get; }
//Right
context.LineTo(keypoints.RightBottom);
internal Point RightBottom { get; }
//BottomRight corner
radiusX = boundRect.BottomRight.X - keypoints.BottomRight.X;
radiusY = boundRect.BottomRight.Y - keypoints.RightBottom.Y;
if (radiusX != 0 || radiusY != 0)
{
context.ArcTo(keypoints.BottomRight, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise);
}
//Bottom
context.LineTo(keypoints.BottomLeft);
//BottomLeft corner
radiusX = keypoints.BottomLeft.X - boundRect.BottomLeft.X;
radiusY = boundRect.BottomLeft.Y - keypoints.LeftBottom.Y;
if (radiusX != 0 || radiusY != 0)
{
context.ArcTo(keypoints.LeftBottom, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise);
}
internal Point BottomRight { get; }
//Left
context.LineTo(keypoints.LeftTop);
//TopLeft corner
radiusX = keypoints.TopLeft.X - boundRect.TopLeft.X;
radiusY = keypoints.LeftTop.Y - boundRect.TopLeft.Y;
if (radiusX != 0 || radiusY != 0)
{
context.ArcTo(keypoints.TopLeft, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise);
}
internal Point BottomLeft { get; }
context.EndFigure(true);
internal Point LeftBottom { get; }
}
}
}

4
src/Avalonia.Visuals/Media/PathMarkupParser.cs

@ -107,7 +107,7 @@ namespace Avalonia.Media
{
if(!ReadCommand(ref span, out var command, out var relative))
{
return;
break;
}
bool initialCommand = true;
@ -565,4 +565,4 @@ namespace Avalonia.Media
return true;
}
}
}
}

2
src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github

@ -1 +1 @@
Subproject commit 8abbe09592668efb573ac4d5548ba2d7e464ba78
Subproject commit 8e4700d4b24935ed5400e5e0d6fce96b5b4a317a

25
tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs

@ -9,6 +9,8 @@ namespace Avalonia.Visuals.UnitTests.Media
{
using System.Globalization;
using System.IO;
using Avalonia.Platform;
using Moq;
public class PathMarkupParserTests
{
@ -18,7 +20,7 @@ namespace Avalonia.Visuals.UnitTests.Media
var pathGeometry = new PathGeometry();
using (var context = new PathGeometryContext(pathGeometry))
using (var parser = new PathMarkupParser(context))
{
{
parser.Parse("M10 10");
var figure = pathGeometry.Figures[0];
@ -202,6 +204,25 @@ namespace Avalonia.Visuals.UnitTests.Media
}
}
[Theory]
[InlineData("M0 0L10 10")]
[InlineData("M0 0L10 10z")]
[InlineData("M0 0L10 10 \n ")]
[InlineData("M0 0L10 10z \n ")]
[InlineData("M0 0L10 10 ")]
[InlineData("M0 0L10 10z ")]
public void Should_AlwaysEndFigure(string pathData)
{
var context = new Mock<IGeometryContext>();
using (var parser = new PathMarkupParser(context.Object))
{
parser.Parse(pathData);
}
context.Verify(v => v.EndFigure(It.IsAny<bool>()), Times.AtLeastOnce());
}
[Theory]
[InlineData("0 0")]
[InlineData("j")]
@ -215,4 +236,4 @@ namespace Avalonia.Visuals.UnitTests.Media
}
}
}
}
}

Loading…
Cancel
Save