Browse Source

Merge branch 'master' into uri-type-provider-mono-fix

pull/2231/head
Steven Kirk 7 years ago
committed by GitHub
parent
commit
ff6d890f76
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      .ncrunch/Avalonia.Desktop.v3.ncrunchproject
  2. 5
      .ncrunch/Avalonia.net461.v3.ncrunchproject
  3. 1
      Avalonia.v3.ncrunchsolution
  4. 9
      samples/ControlCatalog/Pages/DropDownPage.xaml
  5. 3
      samples/ControlCatalog/Pages/DropDownPage.xaml.cs
  6. 21
      src/Avalonia.Animation/AnimationInstance`1.cs
  7. 6
      src/Avalonia.OpenGL/EglContext.cs
  8. 17
      src/Avalonia.OpenGL/EglDisplay.cs
  9. 21
      src/Avalonia.OpenGL/EglErrors.cs
  10. 7
      src/Avalonia.OpenGL/EglInterface.cs
  11. 3
      src/Avalonia.OpenGL/GlConsts.cs
  12. 15
      src/Avalonia.OpenGL/GlErrors.cs
  13. 5
      src/Avalonia.OpenGL/GlInterface.cs
  14. 30
      src/Avalonia.OpenGL/OpenGlException.cs
  15. 18
      src/Avalonia.Styling/Styling/TypeNameAndClassSelector.cs
  16. 7
      src/Avalonia.Visuals/Media/FontFamily.cs
  17. 5
      src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs
  18. 2
      src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
  19. 13
      src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
  20. 2
      src/Windows/Avalonia.Direct2D1/Media/Direct2D1FontCollectionCache.cs
  21. 54
      tests/Avalonia.Animation.UnitTests/AnimationIterationTests.cs
  22. 38
      tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs
  23. 2
      tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs
  24. 2
      tests/Avalonia.Visuals.UnitTests/VisualTree/MockRenderInterface.cs

5
.ncrunch/Avalonia.Desktop.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

5
.ncrunch/Avalonia.net461.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

1
Avalonia.v3.ncrunchsolution

@ -2,6 +2,7 @@
<Settings>
<AdditionalFilesToIncludeForSolution>
<Value>tests\TestFiles\**.*</Value>
<Value>src\Avalonia.Build.Tasks\bin\Debug\netstandard2.0\Avalonia.Build.Tasks.dll</Value>
</AdditionalFilesToIncludeForSolution>
<AllowParallelTestExecution>True</AllowParallelTestExecution>
<ProjectConfigStoragePathRelativeToSolutionDir>.ncrunch</ProjectConfigStoragePathRelativeToSolutionDir>

9
samples/ControlCatalog/Pages/DropDownPage.xaml

@ -27,6 +27,15 @@
<TextBox Text="TextBox"/>
</DropDownItem>
</DropDown>
<DropDown x:Name="fontDropDown" SelectedIndex="0">
<DropDown.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" FontFamily="{Binding}" />
</DataTemplate>
</DropDown.ItemTemplate>
</DropDown>
</StackPanel>
</StackPanel>

3
samples/ControlCatalog/Pages/DropDownPage.xaml.cs

@ -13,6 +13,9 @@ namespace ControlCatalog.Pages
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
var fontDropDown = this.Find<DropDown>("fontDropDown");
fontDropDown.Items = Avalonia.Media.FontFamily.SystemFontFamilies;
fontDropDown.SelectedIndex = 0;
}
}
}

21
src/Avalonia.Animation/AnimationInstance`1.cs

@ -19,6 +19,7 @@ namespace Avalonia.Animation
private ulong? _iterationCount;
private ulong _currentIteration;
private bool _gotFirstKFValue;
private bool _playbackReversed;
private FillMode _fillMode;
private PlaybackDirection _playbackDirection;
private Animator<T> _animator;
@ -160,9 +161,14 @@ namespace Avalonia.Animation
_currentIteration = (ulong)(opsTime / iterationTime);
// Stop animation when the current iteration is beyond the iteration count.
// Stop animation when the current iteration is beyond the iteration count
// and snap the last iteration value to exact values.
if ((_currentIteration + 1) > _iterationCount)
{
var easedTime = _easeFunc.Ease(_playbackReversed ? 0.0 : 1.0);
_lastInterpValue = _interpolator(easedTime, _neutralValue);
DoComplete();
}
if (playbackTime <= iterDuration)
{
@ -170,27 +176,26 @@ namespace Avalonia.Animation
var normalizedTime = playbackTime / iterDuration;
// Check if normalized time needs to be reversed according to PlaybackDirection
bool playbackReversed;
switch (_playbackDirection)
{
case PlaybackDirection.Normal:
playbackReversed = false;
_playbackReversed = false;
break;
case PlaybackDirection.Reverse:
playbackReversed = true;
_playbackReversed = true;
break;
case PlaybackDirection.Alternate:
playbackReversed = (_currentIteration % 2 == 0) ? false : true;
_playbackReversed = (_currentIteration % 2 == 0) ? false : true;
break;
case PlaybackDirection.AlternateReverse:
playbackReversed = (_currentIteration % 2 == 0) ? true : false;
_playbackReversed = (_currentIteration % 2 == 0) ? true : false;
break;
default:
throw new InvalidOperationException($"Animation direction value is unknown: {_playbackDirection}");
}
if (playbackReversed)
if (_playbackReversed)
normalizedTime = 1 - normalizedTime;
// Ease and interpolate

6
src/Avalonia.OpenGL/EglContext.cs

@ -31,14 +31,14 @@ namespace Avalonia.OpenGL
public void MakeCurrent()
{
if (!_egl.MakeCurrent(_disp.Handle, IntPtr.Zero, IntPtr.Zero, Context))
throw new OpenGlException("eglMakeCurrent failed");
throw OpenGlException.GetFormattedException("eglMakeCurrent", _egl);
}
public void MakeCurrent(EglSurface surface)
{
var surf = ((EglSurface)surface)?.DangerousGetHandle() ?? OffscreenSurface;
var surf = surface?.DangerousGetHandle() ?? OffscreenSurface;
if (!_egl.MakeCurrent(_disp.Handle, surf, surf, Context))
throw new OpenGlException("eglMakeCurrent failed");
throw OpenGlException.GetFormattedException("eglMakeCurrent", _egl);
}
}
}

17
src/Avalonia.OpenGL/EglDisplay.cs

@ -1,5 +1,4 @@
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Avalonia.Platform.Interop;
using static Avalonia.OpenGL.EglConsts;
@ -34,11 +33,11 @@ namespace Avalonia.OpenGL
if (_display == IntPtr.Zero)
_display = _egl.GetDisplay(IntPtr.Zero);
if(_display == IntPtr.Zero)
throw new OpenGlException("eglGetDisplay failed");
if (_display == IntPtr.Zero)
throw OpenGlException.GetFormattedException("eglGetDisplay", _egl);
if (!_egl.Initialize(_display, out var major, out var minor))
throw new OpenGlException("eglInitialize failed");
throw OpenGlException.GetFormattedException("eglInitialize", _egl);
foreach (var cfg in new[]
{
@ -113,7 +112,7 @@ namespace Avalonia.OpenGL
var shareCtx = (EglContext)share;
var ctx = _egl.CreateContext(_display, _config, shareCtx?.Context ?? IntPtr.Zero, _contextAttributes);
if (ctx == IntPtr.Zero)
throw new OpenGlException("eglCreateContext failed");
throw OpenGlException.GetFormattedException("eglCreateContext", _egl);
var surf = _egl.CreatePBufferSurface(_display, _config, new[]
{
EGL_WIDTH, 1,
@ -121,7 +120,7 @@ namespace Avalonia.OpenGL
EGL_NONE
});
if (surf == IntPtr.Zero)
throw new OpenGlException("eglCreatePbufferSurface failed");
throw OpenGlException.GetFormattedException("eglCreatePBufferSurface", _egl);
var rv = new EglContext(this, _egl, ctx, surf);
rv.MakeCurrent(null);
return rv;
@ -130,14 +129,14 @@ namespace Avalonia.OpenGL
public void ClearContext()
{
if (!_egl.MakeCurrent(_display, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero))
throw new OpenGlException("eglMakeCurrent failed");
throw OpenGlException.GetFormattedException("eglMakeCurrent", _egl);
}
public EglSurface CreateWindowSurface(IntPtr window)
{
var s = _egl.CreateWindowSurface(_display, _config, window, new[] {EGL_NONE, EGL_NONE});
if (s == IntPtr.Zero)
throw new OpenGlException("eglCreateWindowSurface failed");
throw OpenGlException.GetFormattedException("eglCreateWindowSurface", _egl);
return new EglSurface(this, _egl, s);
}

21
src/Avalonia.OpenGL/EglErrors.cs

@ -0,0 +1,21 @@
namespace Avalonia.OpenGL
{
public enum EglErrors
{
EGL_SUCCESS = EglConsts.EGL_SUCCESS,
EGL_NOT_INITIALIZED = EglConsts.EGL_NOT_INITIALIZED,
EGL_BAD_ACCESS = EglConsts.EGL_BAD_ACCESS,
EGL_BAD_ALLOC = EglConsts.EGL_BAD_ALLOC,
EGL_BAD_ATTRIBUTE = EglConsts.EGL_BAD_ATTRIBUTE,
EGL_BAD_CONTEXT = EglConsts.EGL_BAD_CONTEXT,
EGL_BAD_CONFIG = EglConsts.EGL_BAD_CONFIG,
EGL_BAD_CURRENT_SURFACE = EglConsts.EGL_BAD_CURRENT_SURFACE,
EGL_BAD_DISPLAY = EglConsts.EGL_BAD_DISPLAY,
EGL_BAD_SURFACE = EglConsts.EGL_BAD_SURFACE,
EGL_BAD_MATCH = EglConsts.EGL_BAD_MATCH,
EGL_BAD_PARAMETER = EglConsts.EGL_BAD_PARAMETER,
EGL_BAD_NATIVE_PIXMAP = EglConsts.EGL_BAD_NATIVE_PIXMAP,
EGL_BAD_NATIVE_WINDOW = EglConsts.EGL_BAD_NATIVE_WINDOW,
EGL_CONTEXT_LOST = EglConsts.EGL_CONTEXT_LOST
}
}

7
src/Avalonia.OpenGL/EglInterface.cs

@ -1,7 +1,6 @@
using System;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
using static Avalonia.OpenGL.EglConsts;
namespace Avalonia.OpenGL
{
@ -32,8 +31,12 @@ namespace Avalonia.OpenGL
var lib = dyn.LoadLibrary(library);
return (s, o) => dyn.GetProcAddress(lib, s, o);
}
// ReSharper disable UnassignedGetOnlyAutoProperty
public delegate int EglGetError();
[EntryPoint("eglGetError")]
public EglGetError GetError { get; }
public delegate IntPtr EglGetDisplay(IntPtr nativeDisplay);
[EntryPoint("eglGetDisplay")]
public EglGetDisplay GetDisplay { get; }

3
src/Avalonia.OpenGL/GlConsts.cs

@ -456,12 +456,15 @@ namespace Avalonia.OpenGL
public const int GL_RENDERER = 0x1F01;
public const int GL_VERSION = 0x1F02;
public const int GL_EXTENSIONS = 0x1F03;
public const int GL_NO_ERROR = 0;
public const int GL_INVALID_ENUM = 0x0500;
public const int GL_INVALID_VALUE = 0x0501;
public const int GL_INVALID_OPERATION = 0x0502;
public const int GL_STACK_OVERFLOW = 0x0503;
public const int GL_STACK_UNDERFLOW = 0x0504;
public const int GL_OUT_OF_MEMORY = 0x0505;
public const int GL_INVALID_FRAMEBUFFER_OPERATION = 0x0506;
public const int GL_CONTEXT_LOST = 0x0507;
public const int GL_CURRENT_BIT = 0x00000001;
public const int GL_POINT_BIT = 0x00000002;
public const int GL_LINE_BIT = 0x00000004;

15
src/Avalonia.OpenGL/GlErrors.cs

@ -0,0 +1,15 @@
namespace Avalonia.OpenGL
{
public enum GlErrors
{
GL_NO_ERROR = GlConsts.GL_NO_ERROR,
GL_INVALID_ENUM = GlConsts.GL_INVALID_ENUM,
GL_INVALID_VALUE = GlConsts.GL_INVALID_VALUE,
GL_INVALID_OPERATION = GlConsts.GL_INVALID_OPERATION,
GL_INVALID_FRAMEBUFFER_OPERATION = GlConsts.GL_INVALID_FRAMEBUFFER_OPERATION,
GL_STACK_OVERFLOW = GlConsts.GL_STACK_OVERFLOW,
GL_STACK_UNDERFLOW = GlConsts.GL_STACK_UNDERFLOW,
GL_OUT_OF_MEMORY = GlConsts.GL_OUT_OF_MEMORY,
GL_CONTEXT_LOST = GlConsts.GL_CONTEXT_LOST
}
}

5
src/Avalonia.OpenGL/GlInterface.cs

@ -19,7 +19,10 @@ namespace Avalonia.OpenGL
public T GetProcAddress<T>(string proc) => Marshal.GetDelegateForFunctionPointer<T>(GetProcAddress(proc));
// ReSharper disable UnassignedGetOnlyAutoProperty
public delegate int GlGetError();
[EntryPoint("glGetError")]
public GlGetError GetError { get; }
public delegate void GlClearStencil(int s);
[EntryPoint("glClearStencil")]
public GlClearStencil ClearStencil { get; }

30
src/Avalonia.OpenGL/OpenGlException.cs

@ -4,9 +4,39 @@ namespace Avalonia.OpenGL
{
public class OpenGlException : Exception
{
public int? ErrorCode { get; private set; }
public OpenGlException(string message) : base(message)
{
}
private OpenGlException(string message, int errorCode) : base(message)
{
ErrorCode = errorCode;
}
public static OpenGlException GetFormattedException(string funcName, EglInterface egl)
{
return GetFormattedException(typeof(EglErrors), funcName, egl.GetError());
}
public static OpenGlException GetFormattedException(string funcName, GlInterface gl)
{
return GetFormattedException(typeof(GlErrors), funcName, gl.GetError());
}
private static OpenGlException GetFormattedException(Type consts, string funcName, int errorCode)
{
try
{
string errorName = Enum.GetName(consts, errorCode);
return new OpenGlException(
$"{funcName} failed with error {errorName} (0x{errorCode.ToString("X")})", errorCode);
}
catch (ArgumentException)
{
return new OpenGlException($"{funcName} failed with error 0x{errorCode.ToString("X")}", errorCode);
}
}
}
}

18
src/Avalonia.Styling/Styling/TypeNameAndClassSelector.cs

@ -116,11 +116,9 @@ namespace Avalonia.Styling
}
}
if (Name != null)
if (Name != null && control.Name != Name)
{
return control.Name == Name ?
SelectorMatch.AlwaysThisInstance :
SelectorMatch.NeverThisInstance;
return SelectorMatch.NeverThisInstance;
}
if (_classes.IsValueCreated && _classes.Value.Count > 0)
@ -130,17 +128,13 @@ namespace Avalonia.Styling
var observable = new ClassObserver(control.Classes, _classes.Value);
return new SelectorMatch(observable);
}
else
else if (!Matches(control.Classes))
{
return Matches(control.Classes) ?
SelectorMatch.AlwaysThisInstance :
SelectorMatch.NeverThisInstance;
return SelectorMatch.NeverThisInstance;
}
}
else
{
return SelectorMatch.AlwaysThisType;
}
return Name == null ? SelectorMatch.AlwaysThisType : SelectorMatch.AlwaysThisInstance;
}
protected override Selector MovePrevious() => _previous;

7
src/Avalonia.Visuals/Media/FontFamily.cs

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia.Media.Fonts;
using Avalonia.Platform;
namespace Avalonia.Media
{
@ -51,6 +52,12 @@ namespace Avalonia.Media
/// </summary>
public static FontFamily Default => new FontFamily(String.Empty);
/// <summary>
/// Represents all font families in the system. This can be an expensive call depending on platform implementation.
/// </summary>
public static IEnumerable<FontFamily> SystemFontFamilies =>
AvaloniaLocator.Current.GetService<IPlatformRenderInterface>().InstalledFontNames.Select(name => new FontFamily(name));
/// <summary>
/// Gets the primary family name of the font family.
/// </summary>

5
src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs

@ -13,6 +13,11 @@ namespace Avalonia.Platform
/// </summary>
public interface IPlatformRenderInterface
{
/// <summary>
/// Get all installed fonts in the system
/// </summary>
IEnumerable<string> InstalledFontNames { get; }
/// <summary>
/// Creates a formatted text implementation.
/// </summary>

2
src/Skia/Avalonia.Skia/PlatformRenderInterface.cs

@ -19,6 +19,8 @@ namespace Avalonia.Skia
{
private GRContext GrContext { get; }
public IEnumerable<string> InstalledFontNames => SKFontManager.Default.FontFamilies;
public PlatformRenderInterface()
{
var gl = AvaloniaLocator.Current.GetService<IWindowingPlatformGlFeature>();

13
src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs

@ -41,6 +41,19 @@ namespace Avalonia.Direct2D1
public static SharpDX.DXGI.Device1 DxgiDevice { get; private set; }
public IEnumerable<string> InstalledFontNames
{
get
{
var cache = Direct2D1FontCollectionCache.s_installedFontCollection;
var length = cache.FontFamilyCount;
for (int i = 0; i < length; i++)
{
var names = cache.GetFontFamily(i).FamilyNames;
yield return names.GetString(0);
}
}
}
private static readonly object s_initLock = new object();
private static bool s_initialized = false;

2
src/Windows/Avalonia.Direct2D1/Media/Direct2D1FontCollectionCache.cs

@ -7,7 +7,7 @@ namespace Avalonia.Direct2D1.Media
internal static class Direct2D1FontCollectionCache
{
private static readonly ConcurrentDictionary<FontFamilyKey, SharpDX.DirectWrite.FontCollection> s_cachedCollections;
private static readonly SharpDX.DirectWrite.FontCollection s_installedFontCollection;
internal static readonly SharpDX.DirectWrite.FontCollection s_installedFontCollection;
static Direct2D1FontCollectionCache()
{

54
tests/Avalonia.Animation.UnitTests/AnimationIterationTests.cs

@ -8,6 +8,7 @@ using Avalonia.Styling;
using Avalonia.UnitTests;
using Avalonia.Data;
using Xunit;
using Avalonia.Animation.Easings;
namespace Avalonia.Animation.UnitTests
{
@ -73,5 +74,58 @@ namespace Avalonia.Animation.UnitTests
Assert.True(animationRun.Status == TaskStatus.RanToCompletion);
Assert.Equal(border.Width, 100d);
}
[Fact]
public void Check_FillModes_Start_and_End_Values_if_Retained()
{
var keyframe1 = new KeyFrame()
{
Setters =
{
new Setter(Border.WidthProperty, 0d),
},
Cue = new Cue(0.0d)
};
var keyframe2 = new KeyFrame()
{
Setters =
{
new Setter(Border.WidthProperty, 300d),
},
Cue = new Cue(1.0d)
};
var animation = new Animation()
{
Duration = TimeSpan.FromSeconds(0.05d),
Delay = TimeSpan.FromSeconds(0.05d),
Easing = new SineEaseInOut(),
FillMode = FillMode.Both,
Children =
{
keyframe1,
keyframe2
}
};
var border = new Border()
{
Height = 100d,
Width = 100d,
};
var clock = new TestClock();
var animationRun = animation.RunAsync(border, clock);
clock.Step(TimeSpan.FromSeconds(0d));
Assert.Equal(border.Width, 0d);
clock.Step(TimeSpan.FromSeconds(0.050d));
Assert.Equal(border.Width, 0d);
clock.Step(TimeSpan.FromSeconds(0.100d));
Assert.Equal(border.Width, 300d);
}
}
}

38
tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs

@ -85,6 +85,44 @@ namespace Avalonia.Styling.UnitTests
Assert.Equal(SelectorMatchResult.NeverThisType, match.Result);
}
[Fact]
public void Named_Class_Template_Child_Of_Control()
{
var template = new FuncControlTemplate(parent =>
{
return new Border
{
Name = "border",
};
});
var control = new Button
{
Template = template,
};
control.ApplyTemplate();
var selector = default(Selector)
.OfType<Button>()
.Template()
.Name("border")
.Class("foo");
var border = (Border)((IVisual)control).VisualChildren.Single();
var values = new List<bool>();
var match = selector.Match(border);
Assert.Equal(SelectorMatchResult.Sometimes, match.Result);
match.Activator.Subscribe(x => values.Add(x));
Assert.Equal(new[] { false }, values);
border.Classes.AddRange(new[] { "foo" });
Assert.Equal(new[] { false, true }, values);
border.Classes.Remove("foo");
Assert.Equal(new[] { false, true, false }, values);
}
[Fact]
public void TargetType_OfType()
{

2
tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs

@ -9,6 +9,8 @@ namespace Avalonia.UnitTests
{
public class MockPlatformRenderInterface : IPlatformRenderInterface
{
public IEnumerable<string> InstalledFontNames => new string[0];
public IFormattedTextImpl CreateFormattedText(
string text,
Typeface typeface,

2
tests/Avalonia.Visuals.UnitTests/VisualTree/MockRenderInterface.cs

@ -8,6 +8,8 @@ namespace Avalonia.Visuals.UnitTests.VisualTree
{
class MockRenderInterface : IPlatformRenderInterface
{
public IEnumerable<string> InstalledFontNames => new string[0];
public IFormattedTextImpl CreateFormattedText(
string text,
Typeface typeface,

Loading…
Cancel
Save