Skip to content

Commit bf7a1db

Browse files
Refactor GetDesiredSize and MapSourceAsync for improved aspect handling
1 parent b797ce8 commit bf7a1db

File tree

1 file changed

+58
-28
lines changed

1 file changed

+58
-28
lines changed

src/Core/src/Handlers/Image/ImageHandler.Windows.cs

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -60,39 +60,24 @@ protected override void RemoveContainer()
6060
/// <inheritdoc/>
6161
public override Graphics.Size GetDesiredSize(double widthConstraint, double heightConstraint)
6262
{
63-
// AspectFit + non-Fill alignment: cap Max* to intrinsic bitmap so alignment (Center/Start/End) works.
64-
// Only set once when Max* still Infinity and we have decoded size; else mirror VirtualView Maximum*.
65-
// Without this the Image measures to available space and alignment appears ignored.
63+
// Compute a possible size without mutating platform properties during measure.
64+
var possibleSize = base.GetDesiredSize(widthConstraint, heightConstraint);
65+
66+
// For AspectFit + non-Fill alignment, don't exceed intrinsic bitmap size so alignment works.
6667
if (VirtualView.Aspect == Aspect.AspectFit
6768
&& VirtualView.HorizontalLayoutAlignment != Primitives.LayoutAlignment.Fill
6869
&& VirtualView.VerticalLayoutAlignment != Primitives.LayoutAlignment.Fill)
6970
{
70-
// First (and only) chance to lock to intrinsic size.
71-
if (PlatformView.MaxWidth == double.PositiveInfinity
72-
&& PlatformView.MaxHeight == double.PositiveInfinity)
71+
var imageSize = GetImageSize();
72+
if (imageSize.Width > 0 && imageSize.Height > 0)
7373
{
74-
// Clamp to decoded pixel size if available.
75-
var imageSize = GetImageSize();
76-
77-
if (imageSize.Width != 0 && imageSize.Height != 0)
78-
{
79-
PlatformView.MaxWidth = imageSize.Width;
80-
PlatformView.MaxHeight = imageSize.Height;
81-
}
82-
}
83-
}
84-
else
85-
{
86-
// Other scenarios: honor user Maximum* values.
87-
if (VirtualView.MaximumHeight != PlatformView.MaxHeight
88-
|| VirtualView.MaximumWidth != PlatformView.MaxWidth)
89-
{
90-
PlatformView.MaxWidth = VirtualView.MaximumWidth;
91-
PlatformView.MaxHeight = VirtualView.MaximumHeight;
74+
return new Graphics.Size(
75+
Math.Min(possibleSize.Width, imageSize.Width),
76+
Math.Min(possibleSize.Height, imageSize.Height));
9277
}
9378
}
9479

95-
return base.GetDesiredSize(widthConstraint, heightConstraint);
80+
return possibleSize;
9681
}
9782

9883
/// <summary>
@@ -152,6 +137,9 @@ public static void MapAspect(IImageHandler handler, IImage image)
152137
{
153138
handler.UpdateValue(nameof(IViewHandler.ContainerView));
154139
handler.PlatformView?.UpdateAspect(image);
140+
// Aspect changes may affect whether we cap to intrinsic size
141+
if (handler is ImageHandler ih)
142+
ih.UpdatePlatformMaxConstraints();
155143
}
156144

157145
/// <summary>
@@ -175,15 +163,57 @@ public static void MapSource(IImageHandler handler, IImage image) =>
175163
/// </summary>
176164
/// <param name="handler">The associated handler.</param>
177165
/// <param name="image">The associated <see cref="Image"/> instance.</param>
178-
public static Task MapSourceAsync(IImageHandler handler, IImage image) =>
179-
handler.SourceLoader.UpdateImageSourceAsync();
166+
public static Task MapSourceAsync(IImageHandler handler, IImage image)
167+
{
168+
// Reset platform caps so we don't keep stale values between sources
169+
if (handler is ImageHandler ih && ih.PlatformView is not null)
170+
{
171+
ih.PlatformView.MaxWidth = double.PositiveInfinity;
172+
ih.PlatformView.MaxHeight = double.PositiveInfinity;
173+
}
174+
175+
return handler.SourceLoader.UpdateImageSourceAsync();
176+
}
180177

181178
void OnImageOpened(object sender, RoutedEventArgs e)
182179
{
183180
// Because this resolves from a task we should validate that the
184181
// handler hasn't been disconnected
185182
if (this.IsConnected())
183+
{
186184
UpdateValue(nameof(IImage.IsAnimationPlaying));
185+
// Apply platform constraints when the decoded size is available
186+
UpdatePlatformMaxConstraints();
187+
}
188+
}
189+
190+
/// <summary>
191+
/// Updates platform MaxWidth/MaxHeight based on current aspect/alignment and decoded image size.
192+
/// Avoids doing this during GetDesiredSize to prevent side effects across layout passes.
193+
/// </summary>
194+
private void UpdatePlatformMaxConstraints()
195+
{
196+
if (PlatformView is null || VirtualView is null)
197+
return;
198+
199+
bool isAspectFitNonFill = VirtualView.Aspect == Aspect.AspectFit
200+
&& VirtualView.HorizontalLayoutAlignment != Primitives.LayoutAlignment.Fill
201+
&& VirtualView.VerticalLayoutAlignment != Primitives.LayoutAlignment.Fill;
202+
203+
if (isAspectFitNonFill)
204+
{
205+
var sz = GetImageSize();
206+
if (sz.Width > 0 && sz.Height > 0)
207+
{
208+
PlatformView.MaxWidth = sz.Width;
209+
PlatformView.MaxHeight = sz.Height;
210+
return;
211+
}
212+
}
213+
214+
// Otherwise mirror the view's declared maximums
215+
PlatformView.MaxWidth = VirtualView.MaximumWidth;
216+
PlatformView.MaxHeight = VirtualView.MaximumHeight;
187217
}
188218

189219
private Graphics.Size GetImageSize()
@@ -195,7 +225,7 @@ private Graphics.Size GetImageSize()
195225
{
196226
return new Graphics.Size(bitmap.PixelWidth, bitmap.PixelHeight);
197227
}
198-
// If not available, set to zero
228+
// If not available, return zero
199229
}
200230
return Graphics.Size.Zero;
201231
}

0 commit comments

Comments
 (0)