Browse Source

Merge branch 'master' into devtools-layout-ux

pull/5926/head
Dariusz Komosiński 5 years ago
committed by GitHub
parent
commit
c03260b488
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      samples/RenderDemo/Pages/AnimationsPage.xaml
  2. 65
      samples/RenderDemo/Pages/TransitionsPage.xaml
  3. 10
      src/Avalonia.Animation/Transitions/DoubleTransition.cs
  4. 7
      src/Avalonia.Animation/Transitions/FloatTransition.cs
  5. 7
      src/Avalonia.Animation/Transitions/IntegerTransition.cs
  6. 6
      src/Avalonia.Controls.DataGrid/DataGrid.cs
  7. 3
      src/Avalonia.Controls/ApiCompatBaseline.txt
  8. 11
      src/Avalonia.Controls/Viewbox.cs
  9. 22
      src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
  10. 39
      src/Avalonia.Styling/Controls/Classes.cs
  11. 10
      src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs
  12. 23
      src/Avalonia.Visuals/Animation/Transitions/BoxShadowsTransition.cs
  13. 21
      src/Avalonia.Visuals/Animation/Transitions/CornerRadiusTransition.cs
  14. 10
      src/Avalonia.Visuals/Animation/Transitions/PointTransition.cs
  15. 10
      src/Avalonia.Visuals/Animation/Transitions/SizeTransition.cs
  16. 10
      src/Avalonia.Visuals/Animation/Transitions/ThicknessTransition.cs
  17. 10
      src/Avalonia.Visuals/Animation/Transitions/VectorTransition.cs
  18. 5
      src/Avalonia.Visuals/ApiCompatBaseline.txt
  19. 45
      src/Avalonia.Visuals/Media/Imaging/WriteableBitmap.cs
  20. 32
      src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs
  21. 25
      src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
  22. 65
      src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs
  23. 22
      src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
  24. 17
      src/Windows/Avalonia.Direct2D1/Media/Imaging/WriteableWicBitmapImpl.cs
  25. 22
      tests/Avalonia.Benchmarks/NullRenderingPlatform.cs
  26. 22
      tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs
  27. 22
      tests/Avalonia.Visuals.UnitTests/VisualTree/MockRenderInterface.cs

7
samples/RenderDemo/Pages/AnimationsPage.xaml

@ -1,7 +1,8 @@
<UserControl <UserControl
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="RenderDemo.Pages.AnimationsPage"> x:Class="RenderDemo.Pages.AnimationsPage"
MaxWidth="600">
<UserControl.Styles> <UserControl.Styles>
<Styles> <Styles>
<Styles.Resources> <Styles.Resources>
@ -167,8 +168,8 @@
<StackPanel.Clock> <StackPanel.Clock>
<Clock /> <Clock />
</StackPanel.Clock> </StackPanel.Clock>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"> <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Spacing="20">
<TextBlock VerticalAlignment="Center">Hover to activate Transform Keyframe Animations.</TextBlock> <TextBlock VerticalAlignment="Center">Hover to activate Keyframe Animations.</TextBlock>
<Button Content="{Binding PlayStateText}" Command="{Binding TogglePlayState}" Click="ToggleClock" /> <Button Content="{Binding PlayStateText}" Command="{Binding TogglePlayState}" Click="ToggleClock" />
</StackPanel> </StackPanel>
<WrapPanel ClipToBounds="False"> <WrapPanel ClipToBounds="False">

65
samples/RenderDemo/Pages/TransitionsPage.xaml

@ -1,7 +1,8 @@
<UserControl <UserControl
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="RenderDemo.Pages.TransitionsPage"> x:Class="RenderDemo.Pages.TransitionsPage"
MaxWidth="600">
<UserControl.Styles> <UserControl.Styles>
<Styles> <Styles>
<Styles.Resources> <Styles.Resources>
@ -90,6 +91,56 @@
<Setter Property="RenderTransform" Value="none" /> <Setter Property="RenderTransform" Value="none" />
</Style> </Style>
<Style Selector="Border.Rect7">
<Setter Property="Transitions">
<Transitions>
<DoubleTransition Property="Height" Duration="0:0:0.5" />
</Transitions>
</Setter>
</Style>
<Style Selector="Border.Rect7:pointerover">
<Setter Property="Height" Value="50" />
</Style>
<Style Selector="Border.Rect8">
<Setter Property="Transitions">
<Transitions>
<CornerRadiusTransition Property="CornerRadius" Duration="0:0:0.5" />
</Transitions>
</Setter>
</Style>
<Style Selector="Border.Rect8:pointerover">
<Setter Property="CornerRadius" Value="50" />
</Style>
<Style Selector="Border.Rect9">
<Setter Property="Transitions">
<Transitions>
<ThicknessTransition Property="Padding" Duration="0:0:0.5" />
</Transitions>
</Setter>
</Style>
<Style Selector="Border.Rect9:pointerover">
<Setter Property="Padding" Value="10" />
</Style>
<Style Selector="Border.Shadow">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BoxShadow" Value="inset 0 0 0 2 Red, -15 -15 Green"/>
<Setter Property="Transitions">
<Transitions>
<BoxShadowsTransition Property="BoxShadow" Duration="0:0:0.5" />
</Transitions>
</Setter>
</Style>
<Style Selector="Border.Shadow:pointerover">
<Setter Property="BoxShadow" Value="inset 30 30 20 30 Green, 20 40 20 10 Red"/>
</Style>
</Styles> </Styles>
</UserControl.Styles> </UserControl.Styles>
@ -98,8 +149,8 @@
<StackPanel.Clock> <StackPanel.Clock>
<Clock /> <Clock />
</StackPanel.Clock> </StackPanel.Clock>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"> <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Spacing="20">
<TextBlock VerticalAlignment="Center">Hover to activate Transform Keyframe Animations.</TextBlock> <TextBlock VerticalAlignment="Center">Hover to activate Transitions.</TextBlock>
<Button Content="{Binding PlayStateText}" Command="{Binding TogglePlayState}" Click="ToggleClock" /> <Button Content="{Binding PlayStateText}" Command="{Binding TogglePlayState}" Click="ToggleClock" />
</StackPanel> </StackPanel>
<WrapPanel ClipToBounds="False"> <WrapPanel ClipToBounds="False">
@ -109,6 +160,12 @@
<Border Classes="Test Rect4" Background="Navy"/> <Border Classes="Test Rect4" Background="Navy"/>
<Border Classes="Test Rect5" Background="SeaGreen"/> <Border Classes="Test Rect5" Background="SeaGreen"/>
<Border Classes="Test Rect6" Background="Orange"/> <Border Classes="Test Rect6" Background="Orange"/>
<Border Classes="Test Rect7" Background="Gold"/>
<Border Classes="Test Rect8" Background="Gray" />
<Border Classes="Test Rect9" Background="Red" />
<Border Classes="Test Shadow" CornerRadius="10" Child="{x:Null}" />
<Border Classes="Test Shadow" CornerRadius="0 30 60 0" Child="{x:Null}" />
</WrapPanel> </WrapPanel>
</StackPanel> </StackPanel>
</Grid> </Grid>

10
src/Avalonia.Animation/Transitions/DoubleTransition.cs

@ -1,6 +1,8 @@
using System; using System;
using System.Reactive.Linq; using System.Reactive.Linq;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
/// <summary> /// <summary>
@ -8,15 +10,13 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
public class DoubleTransition : Transition<double> public class DoubleTransition : Transition<double>
{ {
private static readonly DoubleAnimator s_animator = new DoubleAnimator();
/// <inheritdocs/> /// <inheritdocs/>
public override IObservable<double> DoTransition(IObservable<double> progress, double oldValue, double newValue) public override IObservable<double> DoTransition(IObservable<double> progress, double oldValue, double newValue)
{ {
return progress return progress
.Select(p => .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue));
{
var f = Easing.Ease(p);
return ((newValue - oldValue) * f) + oldValue;
});
} }
} }
} }

7
src/Avalonia.Animation/Transitions/FloatTransition.cs

@ -1,6 +1,8 @@
using System; using System;
using System.Reactive.Linq; using System.Reactive.Linq;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
/// <summary> /// <summary>
@ -8,12 +10,13 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
public class FloatTransition : Transition<float> public class FloatTransition : Transition<float>
{ {
private static readonly FloatAnimator s_animator = new FloatAnimator();
/// <inheritdocs/> /// <inheritdocs/>
public override IObservable<float> DoTransition(IObservable<double> progress, float oldValue, float newValue) public override IObservable<float> DoTransition(IObservable<double> progress, float oldValue, float newValue)
{ {
var delta = newValue - oldValue;
return progress return progress
.Select(p => (float)Easing.Ease(p) * delta + oldValue); .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue));
} }
} }
} }

7
src/Avalonia.Animation/Transitions/IntegerTransition.cs

@ -1,6 +1,8 @@
using System; using System;
using System.Reactive.Linq; using System.Reactive.Linq;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
/// <summary> /// <summary>
@ -8,12 +10,13 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
public class IntegerTransition : Transition<int> public class IntegerTransition : Transition<int>
{ {
private static readonly Int32Animator s_animator = new Int32Animator();
/// <inheritdocs/> /// <inheritdocs/>
public override IObservable<int> DoTransition(IObservable<double> progress, int oldValue, int newValue) public override IObservable<int> DoTransition(IObservable<double> progress, int oldValue, int newValue)
{ {
var delta = newValue - oldValue;
return progress return progress
.Select(p => (int)(Easing.Ease(p) * delta + oldValue)); .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue));
} }
} }
} }

6
src/Avalonia.Controls.DataGrid/DataGrid.cs

@ -535,7 +535,8 @@ namespace Avalonia.Controls
AvaloniaProperty.RegisterDirect<DataGrid, int>( AvaloniaProperty.RegisterDirect<DataGrid, int>(
nameof(SelectedIndex), nameof(SelectedIndex),
o => o.SelectedIndex, o => o.SelectedIndex,
(o, v) => o.SelectedIndex = v); (o, v) => o.SelectedIndex = v,
defaultBindingMode: BindingMode.TwoWay);
/// <summary> /// <summary>
/// Gets or sets the index of the current selection. /// Gets or sets the index of the current selection.
@ -553,7 +554,8 @@ namespace Avalonia.Controls
AvaloniaProperty.RegisterDirect<DataGrid, object>( AvaloniaProperty.RegisterDirect<DataGrid, object>(
nameof(SelectedItem), nameof(SelectedItem),
o => o.SelectedItem, o => o.SelectedItem,
(o, v) => o.SelectedItem = v); (o, v) => o.SelectedItem = v,
defaultBindingMode: BindingMode.TwoWay);
/// <summary> /// <summary>
/// Gets or sets the data item corresponding to the selected row. /// Gets or sets the data item corresponding to the selected row.

3
src/Avalonia.Controls/ApiCompatBaseline.txt

@ -4,10 +4,11 @@ InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalon
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.IMenuItem.StaysOpenOnClick.set(System.Boolean)' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.IMenuItem.StaysOpenOnClick.set(System.Boolean)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.INativeMenuExporterEventsImplBridge.RaiseClosed()' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.INativeMenuExporterEventsImplBridge.RaiseClosed()' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.INativeMenuExporterEventsImplBridge.RaiseOpening()' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.INativeMenuExporterEventsImplBridge.RaiseOpening()' is present in the implementation but not in the contract.
MembersMustExist : Member 'public Avalonia.AvaloniaProperty<Avalonia.Media.Stretch> Avalonia.AvaloniaProperty<Avalonia.Media.Stretch> Avalonia.Controls.Viewbox.StretchProperty' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.AvaloniaProperty Avalonia.AvaloniaProperty Avalonia.Controls.Notifications.NotificationCard.CloseOnClickProperty' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.AvaloniaProperty Avalonia.AvaloniaProperty Avalonia.Controls.Notifications.NotificationCard.CloseOnClickProperty' does not exist in the implementation but it does exist in the contract.
EnumValuesMustMatch : Enum value 'Avalonia.Platform.ExtendClientAreaChromeHints Avalonia.Platform.ExtendClientAreaChromeHints.Default' is (System.Int32)2 in the implementation but (System.Int32)1 in the contract. EnumValuesMustMatch : Enum value 'Avalonia.Platform.ExtendClientAreaChromeHints Avalonia.Platform.ExtendClientAreaChromeHints.Default' is (System.Int32)2 in the implementation but (System.Int32)1 in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.ICursorImpl)' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.ICursorImpl)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.IPlatformHandle)' is present in the contract but not in the implementation. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.IPlatformHandle)' is present in the contract but not in the implementation.
MembersMustExist : Member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract.
Total Issues: 11 Total Issues: 12

11
src/Avalonia.Controls/Viewbox.cs

@ -11,9 +11,8 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Defines the <see cref="Stretch"/> property. /// Defines the <see cref="Stretch"/> property.
/// </summary> /// </summary>
public static readonly AvaloniaProperty<Stretch> StretchProperty = public static readonly StyledProperty<Stretch> StretchProperty =
AvaloniaProperty.RegisterDirect<Viewbox, Stretch>(nameof(Stretch), AvaloniaProperty.Register<Image, Stretch>(nameof(Stretch), Stretch.Uniform);
v => v.Stretch, (c, v) => c.Stretch = v, Stretch.Uniform);
/// <summary> /// <summary>
/// Defines the <see cref="StretchDirection"/> property. /// Defines the <see cref="StretchDirection"/> property.
@ -21,8 +20,6 @@ namespace Avalonia.Controls
public static readonly StyledProperty<StretchDirection> StretchDirectionProperty = public static readonly StyledProperty<StretchDirection> StretchDirectionProperty =
AvaloniaProperty.Register<Viewbox, StretchDirection>(nameof(StretchDirection), StretchDirection.Both); AvaloniaProperty.Register<Viewbox, StretchDirection>(nameof(StretchDirection), StretchDirection.Both);
private Stretch _stretch = Stretch.Uniform;
static Viewbox() static Viewbox()
{ {
ClipToBoundsProperty.OverrideDefaultValue<Viewbox>(true); ClipToBoundsProperty.OverrideDefaultValue<Viewbox>(true);
@ -35,8 +32,8 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
public Stretch Stretch public Stretch Stretch
{ {
get => _stretch; get => GetValue(StretchProperty);
set => SetAndRaise(StretchProperty, ref _stretch, value); set => SetValue(StretchProperty, value);
} }
/// <summary> /// <summary>

22
src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs

@ -70,6 +70,28 @@ namespace Avalonia.Headless
return new HeadlessBitmapStub(new Size(1, 1), new Vector(96, 96)); return new HeadlessBitmapStub(new Size(1, 1), new Vector(96, 96));
} }
public IWriteableBitmapImpl LoadWriteableBitmapToWidth(Stream stream, int width,
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{
return new HeadlessBitmapStub(new Size(1, 1), new Vector(96, 96));
}
public IWriteableBitmapImpl LoadWriteableBitmapToHeight(Stream stream, int height,
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{
return new HeadlessBitmapStub(new Size(1, 1), new Vector(96, 96));
}
public IWriteableBitmapImpl LoadWriteableBitmap(string fileName)
{
return new HeadlessBitmapStub(new Size(1, 1), new Vector(96, 96));
}
public IWriteableBitmapImpl LoadWriteableBitmap(Stream stream)
{
return new HeadlessBitmapStub(new Size(1, 1), new Vector(96, 96));
}
public IBitmapImpl LoadBitmap(PixelFormat format, AlphaFormat alphaFormat, IntPtr data, PixelSize size, Vector dpi, int stride) public IBitmapImpl LoadBitmap(PixelFormat format, AlphaFormat alphaFormat, IntPtr data, PixelSize size, Vector dpi, int stride)
{ {
return new HeadlessBitmapStub(new Size(1, 1), new Vector(96, 96)); return new HeadlessBitmapStub(new Size(1, 1), new Vector(96, 96));

39
src/Avalonia.Styling/Controls/Classes.cs

@ -2,6 +2,8 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Avalonia.Collections; using Avalonia.Collections;
#nullable enable
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
/// <summary> /// <summary>
@ -90,7 +92,7 @@ namespace Avalonia.Controls
} }
/// <summary> /// <summary>
/// Remvoes all non-pseudoclasses from the collection. /// Removes all non-pseudoclasses from the collection.
/// </summary> /// </summary>
public override void Clear() public override void Clear()
{ {
@ -135,7 +137,7 @@ namespace Avalonia.Controls
/// </remarks> /// </remarks>
public override void InsertRange(int index, IEnumerable<string> names) public override void InsertRange(int index, IEnumerable<string> names)
{ {
var c = new List<string>(); List<string>? toInsert = null;
foreach (var name in names) foreach (var name in names)
{ {
@ -143,11 +145,16 @@ namespace Avalonia.Controls
if (!Contains(name)) if (!Contains(name))
{ {
c.Add(name); toInsert ??= new List<string>();
toInsert.Add(name);
} }
} }
base.InsertRange(index, c); if (toInsert != null)
{
base.InsertRange(index, toInsert);
}
} }
/// <summary> /// <summary>
@ -176,19 +183,21 @@ namespace Avalonia.Controls
/// </remarks> /// </remarks>
public override void RemoveAll(IEnumerable<string> names) public override void RemoveAll(IEnumerable<string> names)
{ {
var c = new List<string>(); List<string>? toRemove = null;
foreach (var name in names) foreach (var name in names)
{ {
ThrowIfPseudoclass(name, "removed"); ThrowIfPseudoclass(name, "removed");
if (Contains(name)) toRemove ??= new List<string>();
{
c.Add(name); toRemove.Add(name);
}
} }
base.RemoveAll(c); if (toRemove != null)
{
base.RemoveAll(toRemove);
}
} }
/// <summary> /// <summary>
@ -223,7 +232,7 @@ namespace Avalonia.Controls
/// <param name="source">The new contents of the collection.</param> /// <param name="source">The new contents of the collection.</param>
public void Replace(IList<string> source) public void Replace(IList<string> source)
{ {
var toRemove = new List<string>(); List<string>? toRemove = null;
foreach (var name in source) foreach (var name in source)
{ {
@ -234,11 +243,17 @@ namespace Avalonia.Controls
{ {
if (!name.StartsWith(":")) if (!name.StartsWith(":"))
{ {
toRemove ??= new List<string>();
toRemove.Add(name); toRemove.Add(name);
} }
} }
base.RemoveAll(toRemove); if (toRemove != null)
{
base.RemoveAll(toRemove);
}
base.AddRange(source); base.AddRange(source);
} }

10
src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs

@ -12,6 +12,11 @@ namespace Avalonia.Animation.Animators
{ {
public override ISolidColorBrush Interpolate(double progress, ISolidColorBrush oldValue, ISolidColorBrush newValue) public override ISolidColorBrush Interpolate(double progress, ISolidColorBrush oldValue, ISolidColorBrush newValue)
{ {
if (oldValue is null || newValue is null)
{
return oldValue;
}
return new ImmutableSolidColorBrush(ColorAnimator.InterpolateCore(progress, oldValue.Color, newValue.Color)); return new ImmutableSolidColorBrush(ColorAnimator.InterpolateCore(progress, oldValue.Color, newValue.Color));
} }
@ -26,6 +31,11 @@ namespace Avalonia.Animation.Animators
{ {
public override SolidColorBrush Interpolate(double progress, SolidColorBrush oldValue, SolidColorBrush newValue) public override SolidColorBrush Interpolate(double progress, SolidColorBrush oldValue, SolidColorBrush newValue)
{ {
if (oldValue is null || newValue is null)
{
return oldValue;
}
return new SolidColorBrush(ColorAnimator.InterpolateCore(progress, oldValue.Color, newValue.Color)); return new SolidColorBrush(ColorAnimator.InterpolateCore(progress, oldValue.Color, newValue.Color));
} }
} }

23
src/Avalonia.Visuals/Animation/Transitions/BoxShadowsTransition.cs

@ -0,0 +1,23 @@
using System;
using System.Reactive.Linq;
using Avalonia.Animation.Animators;
using Avalonia.Media;
namespace Avalonia.Animation
{
/// <summary>
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="BoxShadows"/> type.
/// </summary>
public class BoxShadowsTransition : Transition<BoxShadows>
{
private static readonly BoxShadowsAnimator s_animator = new BoxShadowsAnimator();
/// <inheritdocs/>
public override IObservable<BoxShadows> DoTransition(IObservable<double> progress, BoxShadows oldValue, BoxShadows newValue)
{
return progress
.Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue));
}
}
}

21
src/Avalonia.Visuals/Animation/Transitions/CornerRadiusTransition.cs

@ -1,6 +1,8 @@
using System; using System;
using System.Reactive.Linq; using System.Reactive.Linq;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
/// <summary> /// <summary>
@ -8,26 +10,13 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
public class CornerRadiusTransition : Transition<CornerRadius> public class CornerRadiusTransition : Transition<CornerRadius>
{ {
private static readonly CornerRadiusAnimator s_animator = new CornerRadiusAnimator();
/// <inheritdocs/> /// <inheritdocs/>
public override IObservable<CornerRadius> DoTransition(IObservable<double> progress, CornerRadius oldValue, CornerRadius newValue) public override IObservable<CornerRadius> DoTransition(IObservable<double> progress, CornerRadius oldValue, CornerRadius newValue)
{ {
return progress return progress
.Select(p => .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue));
{
var f = Easing.Ease(p);
var deltaTL = newValue.TopLeft - oldValue.TopLeft;
var deltaTR = newValue.TopRight - oldValue.TopRight;
var deltaBR = newValue.BottomRight - oldValue.BottomRight;
var deltaBL = newValue.BottomLeft - oldValue.BottomLeft;
var nTL = f * deltaTL + oldValue.TopLeft;
var nTR = f * deltaTR + oldValue.TopRight;
var nBR = f * deltaBR + oldValue.BottomRight;
var nBL = f * deltaBL + oldValue.BottomLeft;
return new CornerRadius(nTL, nTR, nBR, nBL);
});
} }
} }
} }

10
src/Avalonia.Visuals/Animation/Transitions/PointTransition.cs

@ -1,6 +1,8 @@
using System; using System;
using System.Reactive.Linq; using System.Reactive.Linq;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
/// <summary> /// <summary>
@ -8,15 +10,13 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
public class PointTransition : Transition<Point> public class PointTransition : Transition<Point>
{ {
private static readonly PointAnimator s_animator = new PointAnimator();
/// <inheritdocs/> /// <inheritdocs/>
public override IObservable<Point> DoTransition(IObservable<double> progress, Point oldValue, Point newValue) public override IObservable<Point> DoTransition(IObservable<double> progress, Point oldValue, Point newValue)
{ {
return progress return progress
.Select(p => .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue));
{
var f = Easing.Ease(p);
return ((newValue - oldValue) * f) + oldValue;
});
} }
} }
} }

10
src/Avalonia.Visuals/Animation/Transitions/SizeTransition.cs

@ -1,6 +1,8 @@
using System; using System;
using System.Reactive.Linq; using System.Reactive.Linq;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
/// <summary> /// <summary>
@ -8,15 +10,13 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
public class SizeTransition : Transition<Size> public class SizeTransition : Transition<Size>
{ {
private static readonly SizeAnimator s_animator = new SizeAnimator();
/// <inheritdocs/> /// <inheritdocs/>
public override IObservable<Size> DoTransition(IObservable<double> progress, Size oldValue, Size newValue) public override IObservable<Size> DoTransition(IObservable<double> progress, Size oldValue, Size newValue)
{ {
return progress return progress
.Select(p => .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue));
{
var f = Easing.Ease(p);
return ((newValue - oldValue) * f) + oldValue;
});
} }
} }
} }

10
src/Avalonia.Visuals/Animation/Transitions/ThicknessTransition.cs

@ -1,6 +1,8 @@
using System; using System;
using System.Reactive.Linq; using System.Reactive.Linq;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
/// <summary> /// <summary>
@ -8,15 +10,13 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
public class ThicknessTransition : Transition<Thickness> public class ThicknessTransition : Transition<Thickness>
{ {
private static readonly ThicknessAnimator s_animator = new ThicknessAnimator();
/// <inheritdocs/> /// <inheritdocs/>
public override IObservable<Thickness> DoTransition(IObservable<double> progress, Thickness oldValue, Thickness newValue) public override IObservable<Thickness> DoTransition(IObservable<double> progress, Thickness oldValue, Thickness newValue)
{ {
return progress return progress
.Select(p => .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue));
{
var f = Easing.Ease(p);
return ((newValue - oldValue) * f) + oldValue;
});
} }
} }
} }

10
src/Avalonia.Visuals/Animation/Transitions/VectorTransition.cs

@ -1,6 +1,8 @@
using System; using System;
using System.Reactive.Linq; using System.Reactive.Linq;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
/// <summary> /// <summary>
@ -8,15 +10,13 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
public class VectorTransition : Transition<Vector> public class VectorTransition : Transition<Vector>
{ {
private static readonly VectorAnimator s_animator = new VectorAnimator();
/// <inheritdocs/> /// <inheritdocs/>
public override IObservable<Vector> DoTransition(IObservable<double> progress, Vector oldValue, Vector newValue) public override IObservable<Vector> DoTransition(IObservable<double> progress, Vector oldValue, Vector newValue)
{ {
return progress return progress
.Select(p => .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue));
{
var f = Easing.Ease(p);
return ((newValue - oldValue) * f) + oldValue;
});
} }
} }
} }

5
src/Avalonia.Visuals/ApiCompatBaseline.txt

@ -64,3 +64,8 @@ InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.IGl
InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.IGlyphRunImpl Avalonia.Platform.IPlatformRenderInterface.CreateGlyphRun(Avalonia.Media.GlyphRun, System.Double)' is present in the contract but not in the implementation. InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.IGlyphRunImpl Avalonia.Platform.IPlatformRenderInterface.CreateGlyphRun(Avalonia.Media.GlyphRun, System.Double)' is present in the contract but not in the implementation.
MembersMustExist : Member 'public Avalonia.Platform.IGlyphRunImpl Avalonia.Platform.IPlatformRenderInterface.CreateGlyphRun(Avalonia.Media.GlyphRun, System.Double)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.Platform.IGlyphRunImpl Avalonia.Platform.IPlatformRenderInterface.CreateGlyphRun(Avalonia.Media.GlyphRun, System.Double)' does not exist in the implementation but it does exist in the contract.
Total Issues: 64 Total Issues: 64
InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.IWriteableBitmapImpl Avalonia.Platform.IPlatformRenderInterface.LoadWriteableBitmap(System.IO.Stream)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.IWriteableBitmapImpl Avalonia.Platform.IPlatformRenderInterface.LoadWriteableBitmap(System.String)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.IWriteableBitmapImpl Avalonia.Platform.IPlatformRenderInterface.LoadWriteableBitmapToHeight(System.IO.Stream, System.Int32, Avalonia.Visuals.Media.Imaging.BitmapInterpolationMode)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.IWriteableBitmapImpl Avalonia.Platform.IPlatformRenderInterface.LoadWriteableBitmapToWidth(System.IO.Stream, System.Int32, Avalonia.Visuals.Media.Imaging.BitmapInterpolationMode)' is present in the implementation but not in the contract.
Total Issues: 11

45
src/Avalonia.Visuals/Media/Imaging/WriteableBitmap.cs

@ -1,5 +1,8 @@
using System; using System;
using System.IO;
using System.Threading.Tasks;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Visuals.Media.Imaging;
namespace Avalonia.Media.Imaging namespace Avalonia.Media.Imaging
{ {
@ -34,8 +37,50 @@ namespace Avalonia.Media.Imaging
{ {
} }
private WriteableBitmap(IWriteableBitmapImpl impl) : base(impl)
{
}
public ILockedFramebuffer Lock() => ((IWriteableBitmapImpl) PlatformImpl.Item).Lock(); public ILockedFramebuffer Lock() => ((IWriteableBitmapImpl) PlatformImpl.Item).Lock();
public static WriteableBitmap Decode(Stream stream)
{
var ri = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>();
return new WriteableBitmap(ri.LoadWriteableBitmap(stream));
}
/// <summary>
/// Loads a WriteableBitmap from a stream and decodes at the desired width. Aspect ratio is maintained.
/// This is more efficient than loading and then resizing.
/// </summary>
/// <param name="stream">The stream to read the bitmap from. This can be any supported image format.</param>
/// <param name="width">The desired width of the resulting bitmap.</param>
/// <param name="interpolationMode">The <see cref="BitmapInterpolationMode"/> to use should any scaling be required.</param>
/// <returns>An instance of the <see cref="WriteableBitmap"/> class.</returns>
public new static WriteableBitmap DecodeToWidth(Stream stream, int width, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{
var ri = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>();
return new WriteableBitmap(ri.LoadWriteableBitmapToWidth(stream, width, interpolationMode));
}
/// <summary>
/// Loads a Bitmap from a stream and decodes at the desired height. Aspect ratio is maintained.
/// This is more efficient than loading and then resizing.
/// </summary>
/// <param name="stream">The stream to read the bitmap from. This can be any supported image format.</param>
/// <param name="height">The desired height of the resulting bitmap.</param>
/// <param name="interpolationMode">The <see cref="BitmapInterpolationMode"/> to use should any scaling be required.</param>
/// <returns>An instance of the <see cref="WriteableBitmap"/> class.</returns>
public new static WriteableBitmap DecodeToHeight(Stream stream, int height, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{
var ri = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>();
return new WriteableBitmap(ri.LoadWriteableBitmapToHeight(stream, height, interpolationMode));
}
private static IBitmapImpl CreatePlatformImpl(PixelSize size, in Vector dpi, PixelFormat? format, AlphaFormat? alphaFormat) private static IBitmapImpl CreatePlatformImpl(PixelSize size, in Vector dpi, PixelFormat? format, AlphaFormat? alphaFormat)
{ {
var ri = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>(); var ri = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>();

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

@ -100,6 +100,38 @@ namespace Avalonia.Platform
/// <returns>An <see cref="IBitmapImpl"/>.</returns> /// <returns>An <see cref="IBitmapImpl"/>.</returns>
IBitmapImpl LoadBitmap(Stream stream); IBitmapImpl LoadBitmap(Stream stream);
/// <summary>
/// Loads a WriteableBitmap implementation from a stream to a specified width maintaining aspect ratio.
/// </summary>
/// <param name="stream">The stream to read the bitmap from.</param>
/// <param name="width">The desired width of the resulting bitmap.</param>
/// <param name="interpolationMode">The <see cref="BitmapInterpolationMode"/> to use should resizing be required.</param>
/// <returns>An <see cref="IWriteableBitmapImpl"/>.</returns>
IWriteableBitmapImpl LoadWriteableBitmapToWidth(Stream stream, int width, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality);
/// <summary>
/// Loads a WriteableBitmap implementation from a stream to a specified height maintaining aspect ratio.
/// </summary>
/// <param name="stream">The stream to read the bitmap from.</param>
/// <param name="height">The desired height of the resulting bitmap.</param>
/// <param name="interpolationMode">The <see cref="BitmapInterpolationMode"/> to use should resizing be required.</param>
/// <returns>An <see cref="IBitmapImpl"/>.</returns>
IWriteableBitmapImpl LoadWriteableBitmapToHeight(Stream stream, int height, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality);
/// <summary>
/// Loads a WriteableBitmap implementation from a file.
/// </summary>
/// <param name="fileName">The filename of the bitmap.</param>
/// <returns>An <see cref="IBitmapImpl"/>.</returns>
IWriteableBitmapImpl LoadWriteableBitmap(string fileName);
/// <summary>
/// Loads a WriteableBitmap implementation from a file.
/// </summary>
/// <param name="stream">The stream to read the bitmap from.</param>
/// <returns>An <see cref="IBitmapImpl"/>.</returns>
IWriteableBitmapImpl LoadWriteableBitmap(Stream stream);
/// <summary> /// <summary>
/// Loads a bitmap implementation from a stream to a specified width maintaining aspect ratio. /// Loads a bitmap implementation from a stream to a specified width maintaining aspect ratio.
/// </summary> /// </summary>

25
src/Skia/Avalonia.Skia/PlatformRenderInterface.cs

@ -77,6 +77,31 @@ namespace Avalonia.Skia
return new ImmutableBitmap(stream); return new ImmutableBitmap(stream);
} }
public IWriteableBitmapImpl LoadWriteableBitmapToWidth(Stream stream, int width,
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{
return new WriteableBitmapImpl(stream, width, true, interpolationMode);
}
public IWriteableBitmapImpl LoadWriteableBitmapToHeight(Stream stream, int height,
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{
return new WriteableBitmapImpl(stream, height, false, interpolationMode);
}
public IWriteableBitmapImpl LoadWriteableBitmap(string fileName)
{
using (var stream = File.OpenRead(fileName))
{
return LoadWriteableBitmap(stream);
}
}
public IWriteableBitmapImpl LoadWriteableBitmap(Stream stream)
{
return new WriteableBitmapImpl(stream);
}
/// <inheritdoc /> /// <inheritdoc />
public IBitmapImpl LoadBitmap(PixelFormat format, AlphaFormat alphaFormat, IntPtr data, PixelSize size, Vector dpi, int stride) public IBitmapImpl LoadBitmap(PixelFormat format, AlphaFormat alphaFormat, IntPtr data, PixelSize size, Vector dpi, int stride)
{ {

65
src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs

@ -1,8 +1,10 @@
using System; using System;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using Avalonia.Media.Imaging;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Skia.Helpers; using Avalonia.Skia.Helpers;
using Avalonia.Visuals.Media.Imaging;
using SkiaSharp; using SkiaSharp;
namespace Avalonia.Skia namespace Avalonia.Skia
@ -15,7 +17,70 @@ namespace Avalonia.Skia
private static readonly SKBitmapReleaseDelegate s_releaseDelegate = ReleaseProc; private static readonly SKBitmapReleaseDelegate s_releaseDelegate = ReleaseProc;
private readonly SKBitmap _bitmap; private readonly SKBitmap _bitmap;
private readonly object _lock = new object(); private readonly object _lock = new object();
/// <summary>
/// Create a WriteableBitmap from given stream.
/// </summary>
/// <param name="stream">Stream containing encoded data.</param>
public WriteableBitmapImpl(Stream stream)
{
using (var skiaStream = new SKManagedStream(stream))
{
_bitmap = SKBitmap.Decode(skiaStream);
if (_bitmap == null)
{
throw new ArgumentException("Unable to load bitmap from provided data");
}
PixelSize = new PixelSize(_bitmap.Width, _bitmap.Height);
Dpi = SkiaPlatform.DefaultDpi;
}
}
public WriteableBitmapImpl(Stream stream, int decodeSize, bool horizontal, BitmapInterpolationMode interpolationMode)
{
using (var skStream = new SKManagedStream(stream))
using (var codec = SKCodec.Create(skStream))
{
var info = codec.Info;
// get the scale that is nearest to what we want (eg: jpg returned 512)
var supportedScale = codec.GetScaledDimensions(horizontal ? ((float)decodeSize / info.Width) : ((float)decodeSize / info.Height));
// decode the bitmap at the nearest size
var nearest = new SKImageInfo(supportedScale.Width, supportedScale.Height);
var bmp = SKBitmap.Decode(codec, nearest);
// now scale that to the size that we want
var realScale = horizontal ? ((double)info.Height / info.Width) : ((double)info.Width / info.Height);
SKImageInfo desired;
if (horizontal)
{
desired = new SKImageInfo(decodeSize, (int)(realScale * decodeSize));
}
else
{
desired = new SKImageInfo((int)(realScale * decodeSize), decodeSize);
}
if (bmp.Width != desired.Width || bmp.Height != desired.Height)
{
var scaledBmp = bmp.Resize(desired, interpolationMode.ToSKFilterQuality());
bmp.Dispose();
bmp = scaledBmp;
}
_bitmap = bmp;
PixelSize = new PixelSize(bmp.Width, bmp.Height);
Dpi = SkiaPlatform.DefaultDpi;
}
}
/// <summary> /// <summary>
/// Create new writeable bitmap. /// Create new writeable bitmap.
/// </summary> /// </summary>

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

@ -188,6 +188,28 @@ namespace Avalonia.Direct2D1
return new WicBitmapImpl(stream); return new WicBitmapImpl(stream);
} }
public IWriteableBitmapImpl LoadWriteableBitmapToWidth(Stream stream, int width,
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{
return new WriteableWicBitmapImpl(stream, width, true, interpolationMode);
}
public IWriteableBitmapImpl LoadWriteableBitmapToHeight(Stream stream, int height,
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{
return new WriteableWicBitmapImpl(stream, height, false, interpolationMode);
}
public IWriteableBitmapImpl LoadWriteableBitmap(string fileName)
{
return new WriteableWicBitmapImpl(fileName);
}
public IWriteableBitmapImpl LoadWriteableBitmap(Stream stream)
{
return new WriteableWicBitmapImpl(stream);
}
/// <inheritdoc /> /// <inheritdoc />
public IBitmapImpl LoadBitmapToWidth(Stream stream, int width, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) public IBitmapImpl LoadBitmapToWidth(Stream stream, int width, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{ {

17
src/Windows/Avalonia.Direct2D1/Media/Imaging/WriteableWicBitmapImpl.cs

@ -1,4 +1,5 @@
using System; using System;
using System.IO;
using Avalonia.Platform; using Avalonia.Platform;
using SharpDX.WIC; using SharpDX.WIC;
using PixelFormat = Avalonia.Platform.PixelFormat; using PixelFormat = Avalonia.Platform.PixelFormat;
@ -7,11 +8,27 @@ namespace Avalonia.Direct2D1.Media.Imaging
{ {
class WriteableWicBitmapImpl : WicBitmapImpl, IWriteableBitmapImpl class WriteableWicBitmapImpl : WicBitmapImpl, IWriteableBitmapImpl
{ {
public WriteableWicBitmapImpl(Stream stream, int decodeSize, bool horizontal,
Avalonia.Visuals.Media.Imaging.BitmapInterpolationMode interpolationMode)
: base(stream, decodeSize, horizontal, interpolationMode)
{
}
public WriteableWicBitmapImpl(PixelSize size, Vector dpi, PixelFormat? pixelFormat, AlphaFormat? alphaFormat) public WriteableWicBitmapImpl(PixelSize size, Vector dpi, PixelFormat? pixelFormat, AlphaFormat? alphaFormat)
: base(size, dpi, pixelFormat, alphaFormat) : base(size, dpi, pixelFormat, alphaFormat)
{ {
} }
public WriteableWicBitmapImpl(Stream stream)
: base(stream)
{
}
public WriteableWicBitmapImpl(string fileName)
: base(fileName)
{
}
class LockedBitmap : ILockedFramebuffer class LockedBitmap : ILockedFramebuffer
{ {
private readonly WriteableWicBitmapImpl _parent; private readonly WriteableWicBitmapImpl _parent;

22
tests/Avalonia.Benchmarks/NullRenderingPlatform.cs

@ -61,6 +61,28 @@ namespace Avalonia.Benchmarks
throw new NotImplementedException(); throw new NotImplementedException();
} }
public IWriteableBitmapImpl LoadWriteableBitmapToWidth(Stream stream, int width,
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{
throw new NotImplementedException();
}
public IWriteableBitmapImpl LoadWriteableBitmapToHeight(Stream stream, int height,
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{
throw new NotImplementedException();
}
public IWriteableBitmapImpl LoadWriteableBitmap(string fileName)
{
throw new NotImplementedException();
}
public IWriteableBitmapImpl LoadWriteableBitmap(Stream stream)
{
throw new NotImplementedException();
}
public IBitmapImpl LoadBitmap(PixelFormat format, AlphaFormat alphaFormat, IntPtr data, PixelSize size, Vector dpi, int stride) public IBitmapImpl LoadBitmap(PixelFormat format, AlphaFormat alphaFormat, IntPtr data, PixelSize size, Vector dpi, int stride)
{ {
throw new NotImplementedException(); throw new NotImplementedException();

22
tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs

@ -66,6 +66,28 @@ namespace Avalonia.UnitTests
return Mock.Of<IBitmapImpl>(); return Mock.Of<IBitmapImpl>();
} }
public IWriteableBitmapImpl LoadWriteableBitmapToWidth(Stream stream, int width,
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{
throw new NotImplementedException();
}
public IWriteableBitmapImpl LoadWriteableBitmapToHeight(Stream stream, int height,
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{
throw new NotImplementedException();
}
public IWriteableBitmapImpl LoadWriteableBitmap(string fileName)
{
throw new NotImplementedException();
}
public IWriteableBitmapImpl LoadWriteableBitmap(Stream stream)
{
throw new NotImplementedException();
}
public IBitmapImpl LoadBitmap(string fileName) public IBitmapImpl LoadBitmap(string fileName)
{ {
return Mock.Of<IBitmapImpl>(); return Mock.Of<IBitmapImpl>();

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

@ -42,6 +42,28 @@ namespace Avalonia.Visuals.UnitTests.VisualTree
throw new NotImplementedException(); throw new NotImplementedException();
} }
public IWriteableBitmapImpl LoadWriteableBitmapToWidth(Stream stream, int width,
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{
throw new NotImplementedException();
}
public IWriteableBitmapImpl LoadWriteableBitmapToHeight(Stream stream, int height,
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{
throw new NotImplementedException();
}
public IWriteableBitmapImpl LoadWriteableBitmap(string fileName)
{
throw new NotImplementedException();
}
public IWriteableBitmapImpl LoadWriteableBitmap(Stream stream)
{
throw new NotImplementedException();
}
public IBitmapImpl LoadBitmap(string fileName) public IBitmapImpl LoadBitmap(string fileName)
{ {
throw new NotImplementedException(); throw new NotImplementedException();

Loading…
Cancel
Save