// ----------------------------------------------------------------------- // // Copyright 2015 MIT Licence. See licence.md for more information. // // ----------------------------------------------------------------------- namespace Perspex.Controls { using System; using Perspex.Media; using Perspex.Media.Imaging; /// /// Displays a image. /// public class Image : Control { /// /// Defines the property. /// public static readonly PerspexProperty SourceProperty = PerspexProperty.Register(nameof(Source)); /// /// Defines the property. /// public static readonly PerspexProperty StretchProperty = PerspexProperty.Register(nameof(Stretch), Stretch.Uniform); /// /// Gets or sets the bitmap image that will be displayed. /// public Bitmap Source { get { return this.GetValue(SourceProperty); } set { this.SetValue(SourceProperty, value); } } /// /// Gets or sets a value controlling how the image will be stretched. /// public Stretch Stretch { get { return (Stretch)this.GetValue(StretchProperty); } set { this.SetValue(StretchProperty, value); } } /// /// Renders the control. /// /// The drawing context. public override void Render(IDrawingContext context) { Bitmap source = this.Source; if (source != null) { Rect viewPort = new Rect(this.Bounds.Size); Size sourceSize = new Size(source.PixelWidth, source.PixelHeight); Vector scale = CalculateScaling(this.Bounds.Size, sourceSize, this.Stretch); Size scaledSize = sourceSize * scale; Rect destRect = viewPort .CenterIn(new Rect(scaledSize)) .Intersect(viewPort); Rect sourceRect = new Rect(sourceSize) .CenterIn(new Rect(destRect.Size / scale)); context.DrawImage(source, 1, sourceRect, destRect); } } /// /// Measures the control. /// /// The available size. /// The desired size of the control. protected override Size MeasureOverride(Size availableSize) { double width = 0; double height = 0; Vector scale = new Vector(); if (this.Source != null) { width = this.Source.PixelWidth; height = this.Source.PixelHeight; if (this.Width > 0) { availableSize = new Size(this.Width, availableSize.Height); } if (this.Height > 0) { availableSize = new Size(availableSize.Width, this.Height); } scale = CalculateScaling(availableSize, new Size(width, height), this.Stretch); } return new Size(width * scale.X, height * scale.Y); } /// /// Calculates the scaling for the image. /// /// The size available to display the image. /// The pxiel size of the image. /// The stretch mode of the control. /// A vector with the X and Y scaling factors. private static Vector CalculateScaling(Size availableSize, Size imageSize, Stretch stretch) { double scaleX = 1; double scaleY = 1; if (stretch != Stretch.None) { scaleX = availableSize.Width / imageSize.Width; scaleY = availableSize.Height / imageSize.Height; switch (stretch) { case Stretch.Uniform: scaleX = scaleY = Math.Min(scaleX, scaleY); break; case Stretch.UniformToFill: scaleX = scaleY = Math.Max(scaleX, scaleY); break; } } return new Vector(scaleX, scaleY); } } }