浏览代码

Added IImage interface.

`IImage` represents a base interface for raster and vector images. `IBitmap` now implements this interface and `DrawingContext` accepts this interface in `DrawImage`.

The interface defines a `Draw` method which introduces a level of indirection for drawing the image through the image itself.

Renamed `IDrawingContextImpl.DrawImage` to `DrawBitmap` as this only handles drawing bitmap images. `Bitmap` now calls this method directly on the platform implementation.
Steven Kirk 5 年之前
父节点
当前提交
a8e75384b7

+ 4 - 4
src/Avalonia.Visuals/Media/DrawingContext.cs

@@ -74,18 +74,18 @@ namespace Avalonia.Media
         public Matrix CurrentContainerTransform => _currentContainerTransform;
 
         /// <summary>
-        /// Draws a bitmap image.
+        /// Draws an image.
         /// </summary>
-        /// <param name="source">The bitmap image.</param>
+        /// <param name="source">The image.</param>
         /// <param name="opacity">The opacity to draw with.</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, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode = default)
         {
             Contract.Requires<ArgumentNullException>(source != null);
 
-            PlatformImpl.DrawImage(source.PlatformImpl, opacity, sourceRect, destRect, bitmapInterpolationMode);
+            source.Draw(this, opacity, sourceRect, destRect, bitmapInterpolationMode);
         }
 
         /// <summary>

+ 31 - 0
src/Avalonia.Visuals/Media/IImage.cs

@@ -0,0 +1,31 @@
+using Avalonia.Platform;
+using Avalonia.Visuals.Media.Imaging;
+
+namespace Avalonia.Media
+{
+    /// <summary>
+    /// Represents a raster or vector image.
+    /// </summary>
+    public interface IImage
+    {
+        /// <summary>
+        /// Gets the size of the image, in device independent pixels.
+        /// </summary>
+        Size Size { get; }
+
+        /// <summary>
+        /// Draws the image to a <see cref="DrawingContext"/>.
+        /// </summary>
+        /// <param name="context">The drawing context.</param>
+        /// <param name="opacity">The opacity to draw with.</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>
+        void Draw(
+            DrawingContext context,
+            double opacity,
+            Rect sourceRect,
+            Rect destRect,
+            BitmapInterpolationMode bitmapInterpolationMode);
+    }
+}

+ 21 - 0
src/Avalonia.Visuals/Media/Imaging/Bitmap.cs

@@ -5,6 +5,7 @@ using System;
 using System.IO;
 using Avalonia.Platform;
 using Avalonia.Utilities;
+using Avalonia.Visuals.Media.Imaging;
 
 namespace Avalonia.Media.Imaging
 {
@@ -94,9 +95,29 @@ namespace Avalonia.Media.Imaging
             PlatformImpl.Item.Save(fileName);
         }
 
+        /// <summary>
+        /// Saves the bitmap to a stream.
+        /// </summary>
+        /// <param name="stream">The stream.</param>
         public void Save(Stream stream)
         {
             PlatformImpl.Item.Save(stream);
         }
+
+        /// <inheritdoc/>
+        void IImage.Draw(
+            DrawingContext context,
+            double opacity,
+            Rect sourceRect,
+            Rect destRect,
+            BitmapInterpolationMode bitmapInterpolationMode)
+        {
+            context.PlatformImpl.DrawBitmap(
+                PlatformImpl,
+                opacity,
+                sourceRect,
+                destRect,
+                bitmapInterpolationMode);
+        }
     }
 }

+ 1 - 10
src/Avalonia.Visuals/Media/Imaging/IBitmap.cs

@@ -11,7 +11,7 @@ namespace Avalonia.Media.Imaging
     /// <summary>
     /// Represents a bitmap image.
     /// </summary>
-    public interface IBitmap : IDisposable
+    public interface IBitmap : IImage, IDisposable
     {
         /// <summary>
         /// Gets the dots per inch (DPI) of the image.
@@ -32,15 +32,6 @@ namespace Avalonia.Media.Imaging
         /// </summary>
         IRef<IBitmapImpl> PlatformImpl { get; }
 
-        /// <summary>
-        /// Gets the size of the image, in device independent pixels.
-        /// </summary>
-        /// <remarks>
-        /// Note that Skia does not currently support reading the DPI of an image so this value
-        /// will equal <see cref="PixelSize"/> on Skia.
-        /// </remarks>
-        Size Size { get; }
-
         /// <summary>
         /// Saves the bitmap to a file.
         /// </summary>

+ 2 - 2
src/Avalonia.Visuals/Platform/IDrawingContextImpl.cs

@@ -33,7 +33,7 @@ namespace Avalonia.Platform
         /// <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>
-        void DrawImage(IRef<IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode = BitmapInterpolationMode.Default);
+        void DrawBitmap(IRef<IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode = BitmapInterpolationMode.Default);
 
         /// <summary>
         /// Draws a bitmap image.
@@ -42,7 +42,7 @@ namespace Avalonia.Platform
         /// <param name="opacityMask">The opacity mask to draw with.</param>
         /// <param name="opacityMaskRect">The destination rect for the opacity mask.</param>
         /// <param name="destRect">The rect in the output to draw to.</param>
-        void DrawImage(IRef<IBitmapImpl> source, IBrush opacityMask, Rect opacityMaskRect, Rect destRect);
+        void DrawBitmap(IRef<IBitmapImpl> source, IBrush opacityMask, Rect opacityMaskRect, Rect destRect);
 
         /// <summary>
         /// Draws a line.

+ 3 - 3
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@@ -469,11 +469,11 @@ namespace Avalonia.Rendering
 
                 if (layer.OpacityMask == null)
                 {
-                    context.DrawImage(bitmap, layer.Opacity, sourceRect, clientRect);
+                    context.DrawBitmap(bitmap, layer.Opacity, sourceRect, clientRect);
                 }
                 else
                 {
-                    context.DrawImage(bitmap, layer.OpacityMask, layer.OpacityMaskRect, sourceRect);
+                    context.DrawBitmap(bitmap, layer.OpacityMask, layer.OpacityMaskRect, sourceRect);
                 }
 
                 if (layer.GeometryClip != null)
@@ -485,7 +485,7 @@ namespace Avalonia.Rendering
             if (_overlay != null)
             {
                 var sourceRect = new Rect(0, 0, _overlay.Item.PixelSize.Width, _overlay.Item.PixelSize.Height);
-                context.DrawImage(_overlay, 0.5, sourceRect, clientRect);
+                context.DrawBitmap(_overlay, 0.5, sourceRect, clientRect);
             }
 
             if (DrawFps)

+ 2 - 2
src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs

@@ -115,7 +115,7 @@ namespace Avalonia.Rendering.SceneGraph
         }
 
         /// <inheritdoc/>
-        public void DrawImage(IRef<IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode)
+        public void DrawBitmap(IRef<IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode)
         {
             var next = NextDrawAs<ImageNode>();
 
@@ -130,7 +130,7 @@ namespace Avalonia.Rendering.SceneGraph
         }
 
         /// <inheritdoc/>
-        public void DrawImage(IRef<IBitmapImpl> source, IBrush opacityMask, Rect opacityMaskRect, Rect sourceRect)
+        public void DrawBitmap(IRef<IBitmapImpl> source, IBrush opacityMask, Rect opacityMaskRect, Rect sourceRect)
         {
             // This method is currently only used to composite layers so shouldn't be called here.
             throw new NotSupportedException();

+ 1 - 1
src/Avalonia.Visuals/Rendering/SceneGraph/ImageNode.cs

@@ -100,7 +100,7 @@ namespace Avalonia.Rendering.SceneGraph
         public override void Render(IDrawingContextImpl context)
         {
             context.Transform = Transform;
-            context.DrawImage(Source, Opacity, SourceRect, DestRect, BitmapInterpolationMode);
+            context.DrawBitmap(Source, Opacity, SourceRect, DestRect, BitmapInterpolationMode);
         }
 
         /// <inheritdoc/>

+ 1 - 1
src/Avalonia.X11/X11IconLoader.cs

@@ -59,7 +59,7 @@ namespace Avalonia.X11
             }
             using(var rt = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>().CreateRenderTarget(new[]{this}))
             using (var ctx = rt.CreateDrawingContext(null))
-                ctx.DrawImage(bitmap.PlatformImpl, 1, new Rect(bitmap.Size),
+                ctx.DrawBitmap(bitmap.PlatformImpl, 1, new Rect(bitmap.Size),
                     new Rect(0, 0, _width, _height));
             Data = new UIntPtr[_width * _height + 2];
             Data[0] = new UIntPtr((uint)_width);

+ 4 - 4
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@@ -110,7 +110,7 @@ namespace Avalonia.Skia
         }
 
         /// <inheritdoc />
-        public void DrawImage(IRef<IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode)
+        public void DrawBitmap(IRef<IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode)
         {
             var drawableImage = (IDrawableBitmapImpl)source.Item;
             var s = sourceRect.ToSKRect();
@@ -146,10 +146,10 @@ namespace Avalonia.Skia
         }
 
         /// <inheritdoc />
-        public void DrawImage(IRef<IBitmapImpl> source, IBrush opacityMask, Rect opacityMaskRect, Rect destRect)
+        public void DrawBitmap(IRef<IBitmapImpl> source, IBrush opacityMask, Rect opacityMaskRect, Rect destRect)
         {
             PushOpacityMask(opacityMask, opacityMaskRect);
-            DrawImage(source, 1, new Rect(0, 0, source.Item.PixelSize.Width, source.Item.PixelSize.Height), destRect, BitmapInterpolationMode.Default);
+            DrawBitmap(source, 1, new Rect(0, 0, source.Item.PixelSize.Width, source.Item.PixelSize.Height), destRect, BitmapInterpolationMode.Default);
             PopOpacityMask();
         }
 
@@ -437,7 +437,7 @@ namespace Avalonia.Skia
                 context.Clear(Colors.Transparent);
                 context.PushClip(calc.IntermediateClip);
                 context.Transform = calc.IntermediateTransform;
-                context.DrawImage(
+                context.DrawBitmap(
                     RefCountable.CreateUnownedNotClonable(tileBrushImage),
                     1,
                     sourceRect,

+ 2 - 2
src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs

@@ -109,7 +109,7 @@ namespace Avalonia.Direct2D1.Media
         /// <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(IRef<IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode)
+        public void DrawBitmap(IRef<IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode)
         {
             using (var d2d = ((BitmapImpl)source.Item).GetDirect2DBitmap(_deviceContext))
             {
@@ -149,7 +149,7 @@ namespace Avalonia.Direct2D1.Media
         /// <param name="opacityMask">The opacity mask to draw with.</param>
         /// <param name="opacityMaskRect">The destination rect for the opacity mask.</param>
         /// <param name="destRect">The rect in the output to draw to.</param>
-        public void DrawImage(IRef<IBitmapImpl> source, IBrush opacityMask, Rect opacityMaskRect, Rect destRect)
+        public void DrawBitmap(IRef<IBitmapImpl> source, IBrush opacityMask, Rect opacityMaskRect, Rect destRect)
         {
             using (var d2dSource = ((BitmapImpl)source.Item).GetDirect2DBitmap(_deviceContext))
             using (var sourceBrush = new BitmapBrush(_deviceContext, d2dSource.Value))

+ 1 - 1
src/Windows/Avalonia.Direct2D1/Media/ImageBrushImpl.cs

@@ -107,7 +107,7 @@ namespace Avalonia.Direct2D1.Media
                 context.PushClip(calc.IntermediateClip);
                 context.Transform = calc.IntermediateTransform;
                 
-                context.DrawImage(RefCountable.CreateUnownedNotClonable(bitmap), 1, rect, rect, _bitmapInterpolationMode);
+                context.DrawBitmap(RefCountable.CreateUnownedNotClonable(bitmap), 1, rect, rect, _bitmapInterpolationMode);
                 context.PopClip();
             }
 

+ 1 - 1
src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs

@@ -58,7 +58,7 @@ namespace Avalonia.Direct2D1.Media.Imaging
             {
                 using (var dc = wic.CreateDrawingContext(null))
                 {
-                    dc.DrawImage(
+                    dc.DrawBitmap(
                         RefCountable.CreateUnownedNotClonable(this),
                         1,
                         new Rect(PixelSize.ToSizeWithDpi(Dpi.X)),

+ 1 - 1
tests/Avalonia.RenderTests/Media/BitmapTests.cs

@@ -94,7 +94,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media
                     ctx.DrawRectangle(Brushes.Pink, null, new Rect(0, 20, 100, 10));
 
                     var rc = new Rect(0, 0, 60, 60);
-                    ctx.DrawImage(bmp.PlatformImpl, 1, rc, rc);
+                    ctx.DrawBitmap(bmp.PlatformImpl, 1, rc, rc);
                 }
                 rtb.Save(System.IO.Path.Combine(OutputPath, testName + ".out.png"));
             }

+ 1 - 1
tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs

@@ -670,7 +670,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
             var context = Mock.Get(target.RenderTarget.CreateDrawingContext(null));
             var borderLayer = target.Layers[border].Bitmap;
 
-            context.Verify(x => x.DrawImage(borderLayer, 0.5, It.IsAny<Rect>(), It.IsAny<Rect>(), BitmapInterpolationMode.Default));
+            context.Verify(x => x.DrawBitmap(borderLayer, 0.5, It.IsAny<Rect>(), It.IsAny<Rect>(), BitmapInterpolationMode.Default));
         }
 
         [Fact]