Browse Source

Merge branch 'master' into Remove-GTKebab

pull/1174/head
Nikita Tsukanov 9 years ago
committed by GitHub
parent
commit
e58b83a259
  1. 6
      src/Avalonia.Visuals/Media/GradientBrush.cs
  2. 2
      src/Avalonia.Visuals/Media/IGradientBrush.cs
  3. 4
      src/Avalonia.Visuals/Media/Immutable/ImmutableGradientBrush.cs
  4. 2
      src/Avalonia.Visuals/Media/Immutable/ImmutableLinearGradientBrush.cs
  5. 2
      src/Avalonia.Visuals/Media/Immutable/ImmutableRadialGradientBrush.cs
  6. 63
      src/Avalonia.Visuals/Media/PathMarkupParser.cs
  7. 5
      src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs
  8. 5
      src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs
  9. 6
      src/Windows/Avalonia.Win32/WindowImpl.cs
  10. 1
      tests/Avalonia.RenderTests/Avalonia.RenderTests.projitems
  11. 53
      tests/Avalonia.RenderTests/SVGPathTests.cs
  12. BIN
      tests/TestFiles/Cairo/SVGPath/SVGPath.expected.png
  13. BIN
      tests/TestFiles/Direct2D1/SVGPath/SVGPath.expected.png
  14. BIN
      tests/TestFiles/Skia/SVGPath/SVGPath.expected.png

6
src/Avalonia.Visuals/Media/GradientBrush.cs

@ -21,8 +21,8 @@ namespace Avalonia.Media
/// <summary>
/// Defines the <see cref="GradientStops"/> property.
/// </summary>
public static readonly StyledProperty<IReadOnlyList<GradientStop>> GradientStopsProperty =
AvaloniaProperty.Register<GradientBrush, IReadOnlyList<GradientStop>>(nameof(Opacity));
public static readonly StyledProperty<IList<GradientStop>> GradientStopsProperty =
AvaloniaProperty.Register<GradientBrush, IList<GradientStop>>(nameof(Opacity));
/// <summary>
/// Initializes a new instance of the <see cref="GradientBrush"/> class.
@ -46,7 +46,7 @@ namespace Avalonia.Media
/// Gets or sets the brush's gradient stops.
/// </summary>
[Content]
public IReadOnlyList<GradientStop> GradientStops
public IList<GradientStop> GradientStops
{
get { return GetValue(GradientStopsProperty); }
set { SetValue(GradientStopsProperty, value); }

2
src/Avalonia.Visuals/Media/IGradientBrush.cs

@ -10,7 +10,7 @@ namespace Avalonia.Media
/// <summary>
/// Gets the brush's gradient stops.
/// </summary>
IReadOnlyList<GradientStop> GradientStops { get; }
IList<GradientStop> GradientStops { get; }
/// <summary>
/// Gets the brush's spread method that defines how to draw a gradient that doesn't fill

4
src/Avalonia.Visuals/Media/Immutable/ImmutableGradientBrush.cs

@ -16,7 +16,7 @@ namespace Avalonia.Media.Immutable
/// <param name="opacity">The opacity of the brush.</param>
/// <param name="spreadMethod">The spread method.</param>
protected ImmutableGradientBrush(
IReadOnlyList<GradientStop> gradientStops,
IList<GradientStop> gradientStops,
double opacity,
GradientSpreadMethod spreadMethod)
{
@ -36,7 +36,7 @@ namespace Avalonia.Media.Immutable
}
/// <inheritdoc/>
public IReadOnlyList<GradientStop> GradientStops { get; }
public IList<GradientStop> GradientStops { get; }
/// <inheritdoc/>
public double Opacity { get; }

2
src/Avalonia.Visuals/Media/Immutable/ImmutableLinearGradientBrush.cs

@ -20,7 +20,7 @@ namespace Avalonia.Media.Immutable
/// <param name="startPoint">The start point for the gradient.</param>
/// <param name="endPoint">The end point for the gradient.</param>
public ImmutableLinearGradientBrush(
IReadOnlyList<GradientStop> gradientStops,
IList<GradientStop> gradientStops,
double opacity = 1,
GradientSpreadMethod spreadMethod = GradientSpreadMethod.Pad,
RelativePoint? startPoint = null,

2
src/Avalonia.Visuals/Media/Immutable/ImmutableRadialGradientBrush.cs

@ -22,7 +22,7 @@ namespace Avalonia.Media.Immutable
/// The horizontal and vertical radius of the outermost circle of the radial gradient.
/// </param>
public ImmutableRadialGradientBrush(
IReadOnlyList<GradientStop> gradientStops,
IList<GradientStop> gradientStops,
double opacity = 1,
GradientSpreadMethod spreadMethod = GradientSpreadMethod.Pad,
RelativePoint? center = null,

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

@ -21,7 +21,10 @@ namespace Avalonia.Media
{ 'L', Command.Line },
{ 'H', Command.HorizontalLine },
{ 'V', Command.VerticalLine },
{ 'Q', Command.QuadraticBezierCurve },
{ 'T', Command.SmoothQuadraticBezierCurve },
{ 'C', Command.CubicBezierCurve },
{ 'S', Command.SmoothCubicBezierCurve },
{ 'A', Command.Arc },
{ 'Z', Command.Close },
};
@ -55,6 +58,9 @@ namespace Avalonia.Media
HorizontalLine,
VerticalLine,
CubicBezierCurve,
QuadraticBezierCurve,
SmoothCubicBezierCurve,
SmoothQuadraticBezierCurve,
Arc,
Close,
}
@ -71,7 +77,8 @@ namespace Avalonia.Media
{
Command command = Command.None;
Point point = new Point();
bool relative = false;
bool relative = false;
Point? previousControlPoint = null;
while (ReadCommand(reader, ref command, ref relative))
{
@ -79,6 +86,7 @@ namespace Avalonia.Media
{
case Command.FillRule:
_context.SetFillRule(ReadFillRule(reader));
previousControlPoint = null;
break;
case Command.Move:
@ -90,11 +98,13 @@ namespace Avalonia.Media
point = ReadPoint(reader, point, relative);
_context.BeginFigure(point, true);
openFigure = true;
previousControlPoint = null;
break;
case Command.Line:
point = ReadPoint(reader, point, relative);
_context.LineTo(point);
previousControlPoint = null;
break;
case Command.HorizontalLine:
@ -108,6 +118,7 @@ namespace Avalonia.Media
}
_context.LineTo(point);
previousControlPoint = null;
break;
case Command.VerticalLine:
@ -121,18 +132,57 @@ namespace Avalonia.Media
}
_context.LineTo(point);
previousControlPoint = null;
break;
case Command.QuadraticBezierCurve:
{
Point handle = ReadPoint(reader, point, relative);
previousControlPoint = handle;
ReadSeparator(reader);
point = ReadPoint(reader, point, relative);
_context.QuadraticBezierTo(handle, point);
break;
}
case Command.SmoothQuadraticBezierCurve:
{
Point end = ReadPoint(reader, point, relative);
if(previousControlPoint != null)
previousControlPoint = MirrorControlPoint((Point)previousControlPoint, point);
_context.QuadraticBezierTo(previousControlPoint ?? point, end);
point = end;
break;
}
case Command.CubicBezierCurve:
{
Point point1 = ReadPoint(reader, point, relative);
ReadSeparator(reader);
Point point2 = ReadPoint(reader, point, relative);
previousControlPoint = point2;
ReadSeparator(reader);
point = ReadPoint(reader, point, relative);
_context.CubicBezierTo(point1, point2, point);
break;
}
case Command.SmoothCubicBezierCurve:
{
Point point2 = ReadPoint(reader, point, relative);
ReadSeparator(reader);
Point end = ReadPoint(reader, point, relative);
if(previousControlPoint != null)
previousControlPoint = MirrorControlPoint((Point)previousControlPoint, point);
_context.CubicBezierTo(previousControlPoint ?? point, point2, end);
previousControlPoint = point2;
point = end;
break;
}
case Command.Arc:
{
@ -147,12 +197,14 @@ namespace Avalonia.Media
point = ReadPoint(reader, point, relative);
_context.ArcTo(point, size, rotationAngle, isLargeArc, sweepDirection);
previousControlPoint = null;
break;
}
case Command.Close:
_context.EndFigure(true);
openFigure = false;
previousControlPoint = null;
break;
default:
@ -167,6 +219,12 @@ namespace Avalonia.Media
}
}
private Point MirrorControlPoint(Point controlPoint, Point center)
{
Point dir = (controlPoint - center);
return center + -dir;
}
private static bool ReadCommand(
StringReader reader,
ref Command command,
@ -243,6 +301,9 @@ namespace Avalonia.Media
(c == 'E' && !readExponent) ||
char.IsDigit(c))
{
if (b.Length != 0 && !readExponent && c == '-')
break;
b.Append(c);
reader.Read();

5
src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs

@ -342,7 +342,10 @@ namespace Avalonia.Gtk3
Native.GtkWindowResize(GtkWidget, (int)value.Width, (int)value.Height);
}
public IScreenImpl Screen { get; } = new ScreenImpl();
public IScreenImpl Screen
{
get;
} = new ScreenImpl();
public Point Position
{

5
src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs

@ -153,7 +153,10 @@ namespace Avalonia.MonoMac
Position = pos;
}
public IScreenImpl Screen { get; } = new ScreenImpl();
public IScreenImpl Screen
{
get;
} = new ScreenImpl();
public override Point PointToClient(Point point)
{

6
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -103,7 +103,11 @@ namespace Avalonia.Win32
}
}
public IScreenImpl Screen => new ScreenImpl();
public IScreenImpl Screen
{
get;
} = new ScreenImpl();
public IRenderer CreateRenderer(IRenderRoot root)
{

1
tests/Avalonia.RenderTests/Avalonia.RenderTests.projitems

@ -14,6 +14,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Media\RadialGradientBrushTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Media\BitmapTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)OpacityMaskTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SVGPathTests.cs" />
<Compile Include="Media\FormattedTextImplTests.cs" />
<Compile Include="Controls\ImageTests.cs" />
<Compile Include="Controls\BorderTests.cs" />

53
tests/Avalonia.RenderTests/SVGPathTests.cs

@ -0,0 +1,53 @@
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Media;
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;
using System.Threading.Tasks;
#if AVALONIA_CAIRO
namespace Avalonia.Cairo.RenderTests
#elif AVALONIA_SKIA
namespace Avalonia.Skia.RenderTests
#else
namespace Avalonia.Direct2D1.RenderTests
#endif
{
public class SVGPathTests : TestBase
{
public SVGPathTests()
:base("SVGPath")
{
}
[Fact]
public async Task SVGPath()
{
var target = new Canvas
{
Background = Brushes.Yellow,
Width = 76,
Height = 76,
Children = new Avalonia.Controls.Controls
{
new Path
{
Width = 32,
Height = 40,
[Canvas.LeftProperty] = 23,
[Canvas.TopProperty] = 18,
Stretch = Stretch.Fill,
Fill = Brushes.Black,
//Coffee Maker by Becris from the Noun Project
Data = StreamGeometry.Parse("M5,51v4c0,1.654,1.346,3,3,3h7v3c0,0.552,0.447,1,1,1h8c0.553,0,1-0.448,1-1v-3h18v3c0,0.552,0.447,1,1,1h8 c0.553,0,1-0.448,1-1v-3c2.757,0,5-2.243,5-5V13V7c0-2.757-2.243-5-5-5H11C8.243,2,6,4.243,6,7v2c0,2.757,2.243,5,5,5h1.743 l-2.717,11.775c-0.068,0.297,0.002,0.609,0.192,0.848C10.407,26.861,10.695,27,11,27h4c0.431,0,0.812-0.275,0.948-0.684L18.721,18 h1.499l1.811,7.243C22.142,25.688,22.541,26,23,26h12c0.459,0,0.858-0.312,0.97-0.757L37.78,18h6.658l-3.235,29.11 C41.147,47.618,40.72,48,40.21,48h-4.167c0.873-1.159,1.203-2.622,0.897-4.047L35,34.895v-2.481l2.707-2.707 c0.286-0.286,0.372-0.716,0.217-1.09C37.77,28.244,37.404,28,37,28H22c-0.553,0-1,0.448-1,1v0.719l-2.758-0.689 c-0.443-0.111-0.906,0.094-1.123,0.496l-7,13l1.762,0.948l6.631-12.315L21,31.781v3.115l-1.94,9.057 c-0.306,1.426,0.025,2.889,0.897,4.048H8C6.346,48,5,49.346,5,51z M23,60h-6v-2h6V60z M51,60h-6v-2h6V60z M8,9V7 c0-1.654,1.346-3,3-3h42c1.654,0,3,1.346,3,3v5H46H14h-3C9.346,12,8,10.654,8,9z M34.219,24H23.781l-1.5-6h13.438L34.219,24z M44.66,16H37H21h-3c-0.431,0-0.812,0.275-0.948,0.684L14.279,25h-2.022l2.539-11h30.087l-0.185,1.662L44.66,16z M43.191,47.331 L46.896,14H56v39c0,1.654-1.346,3-3,3h-1h-8H24h-8H8c-0.552,0-1-0.449-1-1v-4c0-0.551,0.448-1,1-1h15.948h8.104h8.158 C41.741,50,43.022,48.853,43.191,47.331z M23,30h11.586l-1.293,1.293C33.105,31.48,33,31.735,33,32v2H23V30z M21.614,46.886 c-0.571-0.708-0.79-1.624-0.6-2.514L22.809,36h10.383l1.794,8.372c0.19,0.89-0.028,1.806-0.6,2.514 C33.813,47.594,32.963,48,32.052,48h-8.104C23.037,48,22.187,47.594,21.614,46.886z")
}
}
};
await RenderToFile(target);
CompareImages();
}
}
}

BIN
tests/TestFiles/Cairo/SVGPath/SVGPath.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
tests/TestFiles/Direct2D1/SVGPath/SVGPath.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
tests/TestFiles/Skia/SVGPath/SVGPath.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Loading…
Cancel
Save