protected override Size ArrangeOverride(Size finalSize) { if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) { this.Log().Debug(Panel.ToString() + $" arranging with finalSize={finalSize}"); } //If we are given a non-zero size to draw into, set the target dimensions to load the image with accordingly ImageControl.SetTargetImageSize(finalSize); if (this.Log().IsEnabled(LogLevel.Warning)) { if (ImageControl._openedImage != null) { var renderedSize = finalSize.LogicalToPhysicalPixels(); var loadedSize = ImageControl.SourceImageSize.LogicalToPhysicalPixels(); if (((renderedSize.Width + 512) < loadedSize.Width || (renderedSize.Height + 512) < loadedSize.Height) && ImageControl.Source.UseTargetSize) { this.Log().Warn("The image was opened with a size of {0} and is displayed using a size of only {1}. Try optimizing the image size by using a smaller source or not using Stretch.Uniform or using fixed Width and Height." .InvariantCultureFormat(loadedSize, renderedSize)); } } } return(finalSize); }
protected override Size MeasureOverride(Size availableSize) { if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) { this.Log().Debug(Panel.ToString() + $" measuring with availableSize={availableSize}"); } ImageControl.SetTargetImageSize(availableSize); var size = InnerMeasureOverride(availableSize); return(size); }
protected override Size MeasureOverride(Size availableSize) { Size sourceSize = ImageControl.SourceImageSize; var hasKnownWidth = ImageControl.HasKnownWidth(availableSize.Width); var hasKnownHeight = ImageControl.HasKnownHeight(availableSize.Height); ImageControl._hasFiniteBounds = hasKnownWidth && hasKnownHeight; // If one dimension is known and the other isn't, we need to consider uniformity based on the dimension we know. // Example: Horizontal=Stretch, Vertical=Top, Stretch=Uniform, SourceWidth=200, SourceHeight=100 (AspectRatio=2) // This Image is Inside a StackPanel (infinite height and width=300). // When being measured, the height can be calculated using the aspect ratio of the source image and the available width. // That means the Measure should return // height = (KnownWidth=300) / (AspectRatio=2) = 150 // ...and not height = (SourceHeight=100) = 100 if (hasKnownWidth ^ hasKnownHeight) { var aspectRatio = sourceSize.Width / sourceSize.Height; var desiredSize = new Size(); if (hasKnownWidth) { var knownWidth = ImageControl.GetKnownWidth(availableSize.Width, sourceSize.Width); desiredSize.Width = knownWidth; switch (ImageControl.Stretch) { case Stretch.Uniform: // If sourceSize is empty, aspect ratio is undefined so we return 0. // Since apsect ratio can have a lot of decimal, iOS ceils Image size to 0.5 if it's not a precise size (like 111.111111111) // so the desiredSize will never match the actual size causing an infinite measuring and can freeze the app desiredSize.Height = sourceSize == default(Size) ? 0 : Math.Ceiling((knownWidth / aspectRatio) * 2) / 2; break; case Stretch.None: desiredSize.Height = sourceSize.Height; break; case Stretch.Fill: case Stretch.UniformToFill: desiredSize.Height = double.IsInfinity(availableSize.Height) ? sourceSize.Height : availableSize.Height; break; } if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) { this.Log().Debug(Panel.ToString() + $" measuring with knownWidth={knownWidth} with availableSize={availableSize}, returning desiredSize={desiredSize}"); } return(desiredSize); } else if (hasKnownHeight) { var knownHeight = ImageControl.GetKnownHeight(availableSize.Height, sourceSize.Height); desiredSize.Height = knownHeight; switch (ImageControl.Stretch) { case Stretch.Uniform: //If sourceSize is empty, aspect ratio is undefined so we return 0 // Since apsect ratio can have a lot of decimal, iOS ceils Image size to 0.5 if it's not a precise size (like 111.111111111) // so the desiredSize will never match the actual size causing an infinite measuring and can freeze the app desiredSize.Width = sourceSize == default(Size) ? 0 : Math.Ceiling(knownHeight * aspectRatio * 2) / 2; break; case Stretch.None: desiredSize.Width = sourceSize.Width; break; case Stretch.Fill: case Stretch.UniformToFill: desiredSize.Width = double.IsInfinity(availableSize.Width) ? sourceSize.Width : availableSize.Width; break; } if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) { this.Log().Debug(Panel.ToString() + $" measuring with knownHeight={knownHeight} with availableSize={availableSize}, returning desiredSize={desiredSize}"); } return(desiredSize); } } if (sourceSize.Width > availableSize.Width || sourceSize.Height > availableSize.Height || (hasKnownWidth && hasKnownHeight)) { var knownWidth = ImageControl.GetKnownWidth(availableSize.Width, sourceSize.Width); var knownHeight = ImageControl.GetKnownHeight(availableSize.Height, sourceSize.Height); var knownSize = new Size(knownWidth, knownHeight); switch (ImageControl.Stretch) { case Stretch.Uniform: var desiredSize = new Size(); var aspectRatio = sourceSize.Width / sourceSize.Height; // Since apsect ratio can have a lot of decimal, iOS ceils Image size to 0.5 if it's not a precise size (like 111.111111111) // so the desiredSize will never match the actual size causing an infinite measuring and can freeze the app desiredSize.Width = Math.Min(knownWidth, Math.Ceiling(knownHeight * aspectRatio * 2) / 2); desiredSize.Height = Math.Min(knownHeight, Math.Ceiling(knownWidth / aspectRatio * 2) / 2); if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) { this.Log().Debug(Panel.ToString() + $" measuring with knownSize={knownSize} and Stretch.Uniform with availableSize={availableSize}, returning desiredSize={desiredSize}"); } return(desiredSize); //TODO: #11103 - For futur needs, for an Image with no specified size, need to implement Stretching: UniformToFill, Fill, None //case Stretch.UniformToFill: //case Stretch.Fill: //case Stretch.None: //return sourceSize; } } if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) { this.Log().Debug(Panel.ToString() + $" measuring with availableSize={availableSize}, returning sourceSize={sourceSize}"); } return(sourceSize); }