Skip to content

Commit

Permalink
Merge pull request #3378 from AvaloniaUI/feature/drawing-image
Browse files Browse the repository at this point in the history
Display Drawings in Image control
  • Loading branch information
grokys committed Jan 9, 2020
2 parents 08c9710 + a71b3ba commit 3d3ef68
Show file tree
Hide file tree
Showing 30 changed files with 270 additions and 120 deletions.
6 changes: 5 additions & 1 deletion samples/ControlCatalog/MainView.xaml
Expand Up @@ -32,7 +32,11 @@
<TabItem Header="DatePicker"><pages:DatePickerPage/></TabItem>
<TabItem Header="Drag+Drop"><pages:DragAndDropPage/></TabItem>
<TabItem Header="Expander"><pages:ExpanderPage/></TabItem>
<TabItem Header="Image"><pages:ImagePage/></TabItem>
<TabItem Header="Image"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<pages:ImagePage/>
</TabItem>
<TabItem Header="ItemsRepeater"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
Expand Down
85 changes: 46 additions & 39 deletions samples/ControlCatalog/Pages/ImagePage.xaml
@@ -1,45 +1,52 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ControlCatalog.Pages.ImagePage">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Image</TextBlock>
<TextBlock Classes="h2">Displays an image</TextBlock>

<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Spacing="16">
<StackPanel Orientation="Vertical">
<TextBlock>No Stretch</TextBlock>
<Image Source="/Assets/delicate-arch-896885_640.jpg"
Width="100" Height="200"
Stretch="None"/>
</StackPanel>

<StackPanel Orientation="Vertical">
<TextBlock>Fill</TextBlock>
<Image Source="/Assets/delicate-arch-896885_640.jpg"
Width="100" Height="200"
Stretch="Fill"/>
</StackPanel>
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Image</TextBlock>
<TextBlock Classes="h2">Displays an image</TextBlock>
</StackPanel>

<StackPanel Orientation="Vertical">
<TextBlock>Uniform</TextBlock>
<Image Source="/Assets/delicate-arch-896885_640.jpg"
Width="100" Height="200"
Stretch="Uniform"/>
</StackPanel>
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,*" Margin="64">

<DockPanel Grid.Column="0" Grid.Row="1" Margin="16">
<TextBlock DockPanel.Dock="Top" Classes="h3" Margin="0 8">Bitmap</TextBlock>
<ComboBox Name="bitmapStretch" DockPanel.Dock="Top" SelectedIndex="2" SelectionChanged="BitmapStretchChanged">
<ComboBoxItem>None</ComboBoxItem>
<ComboBoxItem>Fill</ComboBoxItem>
<ComboBoxItem>Uniform</ComboBoxItem>
<ComboBoxItem>UniformToFill</ComboBoxItem>
</ComboBox>
<Image Name="bitmapImage"
Source="/Assets/delicate-arch-896885_640.jpg"/>
</DockPanel>

<StackPanel Orientation="Vertical">
<TextBlock>UniformToFill</TextBlock>
<Image Source="/Assets/delicate-arch-896885_640.jpg"
Width="100" Height="200"
Stretch="UniformToFill"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical">
<TextBlock>Window Icon as an Image</TextBlock>
<Image Name="Icon" Width="100" Height="200" Stretch="None" />
</StackPanel>
</StackPanel>
<DockPanel Grid.Column="1" Grid.Row="1" Margin="16">
<TextBlock DockPanel.Dock="Top" Classes="h3" Margin="0 8">Drawing</TextBlock>
<ComboBox Name="drawingStretch" DockPanel.Dock="Top" SelectedIndex="2" SelectionChanged="DrawingStretchChanged">
<ComboBoxItem>None</ComboBoxItem>
<ComboBoxItem>Fill</ComboBoxItem>
<ComboBoxItem>Uniform</ComboBoxItem>
<ComboBoxItem>UniformToFill</ComboBoxItem>
</ComboBox>
<Image Name="drawingImage">
<Image.Source>
<DrawingImage>
<GeometryDrawing Brush="Red">
<PathGeometry>
<PathFigure StartPoint="0,0" IsClosed="True">
<QuadraticBezierSegment Point1="50,0" Point2="50,-50" />
<QuadraticBezierSegment Point1="100,-50" Point2="100,0" />
<LineSegment Point="50,0" />
<LineSegment Point="50,50" />
</PathFigure>
</PathGeometry>
</GeometryDrawing>
</DrawingImage>
</Image.Source>
</Image>
</DockPanel>
</Grid>

</DockPanel>
</UserControl>
39 changes: 20 additions & 19 deletions samples/ControlCatalog/Pages/ImagePage.xaml.cs
@@ -1,40 +1,41 @@
using System.IO;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Media.Imaging;
using Avalonia.Media;

namespace ControlCatalog.Pages
{
public class ImagePage : UserControl
{
private Image iconImage;
private readonly Image _bitmapImage;
private readonly Image _drawingImage;

public ImagePage()
{
this.InitializeComponent();
InitializeComponent();
_bitmapImage = this.FindControl<Image>("bitmapImage");
_drawingImage = this.FindControl<Image>("drawingImage");
}

private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
iconImage = this.Get<Image>("Icon");
}

protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
public void BitmapStretchChanged(object sender, SelectionChangedEventArgs e)
{
if (_bitmapImage != null)
{
var comboxBox = (ComboBox)sender;
_bitmapImage.Stretch = (Stretch)comboxBox.SelectedIndex;
}
}

public void DrawingStretchChanged(object sender, SelectionChangedEventArgs e)
{
base.OnAttachedToVisualTree(e);
if (iconImage.Source == null)
if (_drawingImage != null)
{
var windowRoot = e.Root as Window;
if (windowRoot != null)
{
using (var stream = new MemoryStream())
{
windowRoot.Icon.Save(stream);
stream.Seek(0, SeekOrigin.Begin);
iconImage.Source = new Bitmap(stream);
}
}
var comboxBox = (ComboBox)sender;
_drawingImage.Stretch = (Stretch)comboxBox.SelectedIndex;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion samples/RenderDemo/Pages/RenderTargetBitmapPage.cs
Expand Up @@ -39,7 +39,7 @@ public override void Render(DrawingContext context)
ctx.FillRectangle(Brushes.Fuchsia, new Rect(50, 50, 100, 100));
}

context.DrawImage(_bitmap, 1,
context.DrawImage(_bitmap,
new Rect(0, 0, 200, 200),
new Rect(0, 0, 200, 200));
Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Background);
Expand Down
4 changes: 3 additions & 1 deletion src/Avalonia.Controls/DrawingPresenter.cs
@@ -1,9 +1,11 @@
using Avalonia.Controls.Shapes;
using System;
using Avalonia.Controls.Shapes;
using Avalonia.Media;
using Avalonia.Metadata;

namespace Avalonia.Controls
{
[Obsolete("Use Image control with DrawingImage source")]
public class DrawingPresenter : Control
{
static DrawingPresenter()
Expand Down
17 changes: 8 additions & 9 deletions src/Avalonia.Controls/Image.cs
Expand Up @@ -14,8 +14,8 @@ public class Image : Control
/// <summary>
/// Defines the <see cref="Source"/> property.
/// </summary>
public static readonly StyledProperty<IBitmap> SourceProperty =
AvaloniaProperty.Register<Image, IBitmap>(nameof(Source));
public static readonly StyledProperty<IImage> SourceProperty =
AvaloniaProperty.Register<Image, IImage>(nameof(Source));

/// <summary>
/// Defines the <see cref="Stretch"/> property.
Expand All @@ -38,9 +38,9 @@ static Image()
}

/// <summary>
/// Gets or sets the bitmap image that will be displayed.
/// Gets or sets the image that will be displayed.
/// </summary>
public IBitmap Source
public IImage Source
{
get { return GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
Expand Down Expand Up @@ -75,7 +75,7 @@ public override void Render(DrawingContext context)
if (source != null)
{
Rect viewPort = new Rect(Bounds.Size);
Size sourceSize = new Size(source.PixelSize.Width, source.PixelSize.Height);
Size sourceSize = source.Size;
Vector scale = Stretch.CalculateScaling(Bounds.Size, sourceSize, StretchDirection);
Size scaledSize = sourceSize * scale;
Rect destRect = viewPort
Expand All @@ -86,7 +86,7 @@ public override void Render(DrawingContext context)

var interpolationMode = RenderOptions.GetBitmapInterpolationMode(this);

context.DrawImage(source, 1, sourceRect, destRect, interpolationMode);
context.DrawImage(source, sourceRect, destRect, interpolationMode);
}
}

Expand All @@ -102,8 +102,7 @@ protected override Size MeasureOverride(Size availableSize)

if (source != null)
{
var sourceSize = new Size(source.PixelSize.Width, source.PixelSize.Height);
result = Stretch.CalculateSize(availableSize, sourceSize, StretchDirection);
result = Stretch.CalculateSize(availableSize, source.Size, StretchDirection);
}

return result;
Expand All @@ -116,7 +115,7 @@ protected override Size ArrangeOverride(Size finalSize)

if (source != null)
{
var sourceSize = new Size(source.PixelSize.Width, source.PixelSize.Height);
var sourceSize = source.Size;
var result = Stretch.CalculateSize(finalSize, sourceSize);
return result;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Avalonia.Controls/Remote/RemoteWidget.cs
Expand Up @@ -83,7 +83,7 @@ public override void Render(DrawingContext context)
Marshal.Copy(_lastFrame.Data, y * _lastFrame.Stride,
new IntPtr(l.Address.ToInt64() + l.RowBytes * y), lineLen);
}
context.DrawImage(_bitmap, 1, new Rect(0, 0, _bitmap.PixelSize.Width, _bitmap.PixelSize.Height),
context.DrawImage(_bitmap, new Rect(0, 0, _bitmap.PixelSize.Width, _bitmap.PixelSize.Height),
new Rect(Bounds.Size));
}
base.Render(context);
Expand Down
6 changes: 4 additions & 2 deletions src/Avalonia.Visuals/Media/Drawing.cs
@@ -1,9 +1,11 @@
namespace Avalonia.Media
using Avalonia.Platform;

namespace Avalonia.Media
{
public abstract class Drawing : AvaloniaObject
{
public abstract void Draw(DrawingContext context);

public abstract Rect GetBounds();
}
}
}
21 changes: 16 additions & 5 deletions src/Avalonia.Visuals/Media/DrawingContext.cs
Expand Up @@ -74,18 +74,29 @@ private set
public Matrix CurrentContainerTransform => _currentContainerTransform;

/// <summary>
/// Draws a bitmap image.
/// Draws an image.
/// </summary>
/// <param name="source">The bitmap image.</param>
/// <param name="opacity">The opacity to draw with.</param>
/// <param name="source">The image.</param>
/// <param name="rect">The rect in the output to draw to.</param>
public void DrawImage(IImage source, Rect rect)
{
Contract.Requires<ArgumentNullException>(source != null);

DrawImage(source, new Rect(source.Size), rect);
}

/// <summary>
/// Draws an image.
/// </summary>
/// <param name="source">The image.</param>
/// <param name="sourceRect">The rect in the image to draw.</param>
/// <param name="destRect">The rect in the output to draw to.</param>
/// <param name="bitmapInterpolationMode">The bitmap interpolation mode.</param>
public void DrawImage(IBitmap source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode = default)
public void DrawImage(IImage source, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode = default)
{
Contract.Requires<ArgumentNullException>(source != null);

PlatformImpl.DrawImage(source.PlatformImpl, opacity, sourceRect, destRect, bitmapInterpolationMode);
source.Draw(this, sourceRect, destRect, bitmapInterpolationMode);
}

/// <summary>
Expand Down
3 changes: 2 additions & 1 deletion src/Avalonia.Visuals/Media/DrawingGroup.cs
@@ -1,5 +1,6 @@
using Avalonia.Collections;
using Avalonia.Metadata;
using Avalonia.Platform;

namespace Avalonia.Media
{
Expand Down Expand Up @@ -55,4 +56,4 @@ public override Rect GetBounds()
return rect;
}
}
}
}

0 comments on commit 3d3ef68

Please sign in to comment.