| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- using System.Runtime.InteropServices;
- namespace PicView.Core.Calculations;
- public static class ImageSizeCalculationHelper
- {
- /// <summary>
- /// Returns the interface size of the titlebar based on OS
- /// </summary>
- public static double GetInterfaceSize()
- {
- // TODO: find a more elegant solution
- return RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? 165 : 230;
- }
- public static ImageSize GetImageSize(double width,
- double height,
- double monitorWidth,
- double monitorHeight,
- double monitorMinWidth,
- double monitorMinHeight,
- double interfaceSize,
- double rotationAngle,
- double padding,
- double dpiScaling,
- double uiTopSize,
- double uiBottomSize,
- double galleryHeight,
- double containerWidth,
- double containerHeight)
- {
- if (width <= 0 || height <= 0 || rotationAngle > 360 || rotationAngle < 0)
- {
- return new ImageSize(0, 0, 0, 0, 0, 0, 0, 0);
- }
- double aspectRatio;
- double maxWidth, maxHeight;
- var margin = 0d;
- var fullscreen = Settings.WindowProperties.Fullscreen ||
- Settings.WindowProperties.Maximized;
-
- var borderSpaceHeight = fullscreen ? 0 : uiTopSize + uiBottomSize + galleryHeight;
- var borderSpaceWidth = fullscreen ? 0 : padding;
- var workAreaWidth = monitorWidth - borderSpaceWidth;
- var workAreaHeight = monitorHeight - borderSpaceHeight;
- if (Settings.Zoom.ScrollEnabled)
- {
- workAreaWidth -= SizeDefaults.ScrollbarSize * dpiScaling;
- containerWidth -= SizeDefaults.ScrollbarSize * dpiScaling;
- maxWidth = workAreaWidth - padding;
- maxHeight = height;
- }
- else if (Settings.WindowProperties.AutoFit)
- {
- maxWidth = Settings.ImageScaling.StretchImage
- ? workAreaWidth - padding
- : Math.Min(workAreaWidth - padding, width);
-
- maxHeight = Settings.ImageScaling.StretchImage
- ? workAreaHeight - padding
- : Math.Min(workAreaHeight - padding, height);
- }
- else
- {
- maxWidth = Settings.ImageScaling.StretchImage
- ? containerWidth
- : Math.Min(containerWidth, width);
- maxHeight = Settings.ImageScaling.StretchImage
- ? containerHeight - galleryHeight
- : Math.Min(containerHeight - galleryHeight, height);
- }
- if (Settings.Gallery.IsBottomGalleryShown)
- {
- if (!Settings.UIProperties.ShowInterface)
- {
- if (Settings.Gallery.ShowBottomGalleryInHiddenUI)
- {
- margin = galleryHeight > 0 ? galleryHeight : 0;
- }
- else
- {
- margin = 0;
- }
- }
- else
- {
- margin = galleryHeight > 0 ? galleryHeight : 0;
- }
- }
- // aspect ratio calculation
- switch (rotationAngle)
- {
- case 0:
- case 180:
- aspectRatio = Math.Min(maxWidth / width, maxHeight / height);
- break;
- case 90:
- case 270:
- aspectRatio = Math.Min(maxWidth / height, maxHeight / width);
- break;
- default:
- var rotationRadians = rotationAngle * Math.PI / 180;
- var newWidth = Math.Abs(width * Math.Cos(rotationRadians)) +
- Math.Abs(height * Math.Sin(rotationRadians));
- var newHeight = Math.Abs(width * Math.Sin(rotationRadians)) +
- Math.Abs(height * Math.Cos(rotationRadians));
- aspectRatio = Math.Min(maxWidth / newWidth, maxHeight / newHeight);
- break;
- }
- // Fit image by aspect ratio calculation
- // and update values
- double scrollWidth, scrollHeight, xWidth, xHeight;
- if (Settings.Zoom.ScrollEnabled)
- {
- if (Settings.WindowProperties.AutoFit)
- {
- xWidth = maxWidth - SizeDefaults.ScrollbarSize - 10;
- xHeight = maxWidth * height / width;
- scrollWidth = maxWidth;
- scrollHeight = containerHeight - padding - 8;
- }
- else
- {
- scrollWidth = containerWidth + SizeDefaults.ScrollbarSize;
- scrollHeight = containerHeight;
- xWidth = containerWidth - SizeDefaults.ScrollbarSize + 10;
- xHeight = height / width * xWidth;
- }
- }
- else
- {
- scrollWidth = double.NaN;
- scrollHeight = double.NaN;
- xWidth = width * aspectRatio;
- xHeight = height * aspectRatio;
- }
- var titleMaxWidth = GetTitleMaxWidth(rotationAngle, xWidth, xHeight, monitorMinWidth, monitorMinHeight,
- interfaceSize, containerWidth);
- return new ImageSize(xWidth, xHeight, 0, scrollWidth, scrollHeight, titleMaxWidth, margin, aspectRatio);
- }
- public static ImageSize GetImageSize(double width,
- double height,
- double secondaryWidth,
- double secondaryHeight,
- double monitorWidth,
- double monitorHeight,
- double monitorMinWidth,
- double monitorMinHeight,
- double interfaceSize,
- double rotationAngle,
- double padding,
- double dpiScaling,
- double uiTopSize,
- double uiBottomSize,
- double galleryHeight,
- double containerWidth,
- double containerHeight)
- {
- if (width <= 0 || height <= 0 || secondaryWidth <= 0 || secondaryHeight <= 0 || rotationAngle > 360 ||
- rotationAngle < 0)
- {
- return new ImageSize(0, 0, 0, 0, 0, 0, 0, 0);
- }
- // Get sizes for both images
- var firstSize = GetImageSize(width, height, monitorWidth, monitorHeight, monitorMinWidth, monitorMinHeight,
- interfaceSize, rotationAngle, padding, dpiScaling, uiTopSize, uiBottomSize, galleryHeight,
- containerWidth,
- containerHeight);
- var secondSize = GetImageSize(secondaryWidth, secondaryHeight, monitorWidth, monitorHeight, monitorMinWidth,
- monitorMinHeight, interfaceSize, rotationAngle, padding, dpiScaling, uiTopSize, uiBottomSize,
- galleryHeight,
- containerWidth, containerHeight);
- // Determine maximum height for both images
- var xHeight = Math.Max(firstSize.Height, secondSize.Height);
- // Recalculate the widths to maintain the aspect ratio with the new maximum height
- var xWidth1 = firstSize.Width / firstSize.Height * xHeight;
- var xWidth2 = secondSize.Width / secondSize.Height * xHeight;
- // Combined width of both images
- var combinedWidth = xWidth1 + xWidth2;
- if (Settings.WindowProperties.AutoFit)
- {
- var widthPadding = Settings.ImageScaling.StretchImage ? 4 : padding;
- var availableWidth = monitorWidth - widthPadding;
- var availableHeight = monitorHeight - (widthPadding + uiBottomSize + uiTopSize);
- if (rotationAngle is 0 or 180)
- {
- // If combined width exceeds available width, scale both images down proportionally
- if (combinedWidth > availableWidth)
- {
- var scaleFactor = availableWidth / combinedWidth;
- xWidth1 *= scaleFactor;
- xWidth2 *= scaleFactor;
- xHeight *= scaleFactor;
- combinedWidth = xWidth1 + xWidth2;
- }
- }
- else
- {
- if (combinedWidth > availableHeight)
- {
- var scaleFactor = availableHeight / combinedWidth;
- xWidth1 *= scaleFactor;
- xWidth2 *= scaleFactor;
- xHeight *= scaleFactor;
-
- combinedWidth = xWidth1 + xWidth2;
- }
- }
- }
- else
- {
- if (rotationAngle is 0 or 180)
- {
- if (combinedWidth > containerWidth)
- {
- var scaleFactor = containerWidth / combinedWidth;
- xWidth1 *= scaleFactor;
- xWidth2 *= scaleFactor;
- xHeight *= scaleFactor;
- combinedWidth = xWidth1 + xWidth2;
- }
- }
- else
- {
- if (combinedWidth > containerHeight)
- {
- var scaleFactor = containerHeight / combinedWidth;
- xWidth1 *= scaleFactor;
- xWidth2 *= scaleFactor;
- xHeight *= scaleFactor;
-
- combinedWidth = xWidth1 + xWidth2;
- }
- }
- }
- double scrollWidth, scrollHeight;
- if (Settings.Zoom.ScrollEnabled)
- {
- if (Settings.WindowProperties.AutoFit)
- {
- combinedWidth -= SizeDefaults.ScrollbarSize;
- scrollWidth = combinedWidth + SizeDefaults.ScrollbarSize + 8;
- var fullscreen = Settings.WindowProperties.Fullscreen ||
- Settings.WindowProperties.Maximized;
- var borderSpaceHeight = fullscreen ? 0 : uiTopSize + uiBottomSize + galleryHeight;
- var workAreaHeight = monitorHeight * dpiScaling - borderSpaceHeight;
- scrollHeight = Settings.ImageScaling.StretchImage
- ? workAreaHeight
- : workAreaHeight - padding;
- }
- else
- {
- combinedWidth -= SizeDefaults.ScrollbarSize + 8;
- scrollWidth = double.NaN;
- scrollHeight = double.NaN;
- }
- }
- else
- {
- scrollWidth = double.NaN;
- scrollHeight = double.NaN;
- }
- var titleMaxWidth = GetTitleMaxWidth(rotationAngle, combinedWidth, xHeight, monitorMinWidth,
- monitorMinHeight, interfaceSize, containerWidth);
- var margin = firstSize.Height > secondSize.Height ? firstSize.Margin : secondSize.Margin;
- return new ImageSize(combinedWidth, xHeight, xWidth2, scrollWidth, scrollHeight, titleMaxWidth, margin,
- firstSize.AspectRatio);
- }
- public static double GetTitleMaxWidth(double rotationAngle, double width, double height, double monitorMinWidth,
- double monitorMinHeight, double interfaceSize, double containerWidth)
- {
- double titleMaxWidth;
- var maximized = Settings.WindowProperties.Fullscreen ||
- Settings.WindowProperties.Maximized;
- if (Settings.WindowProperties.AutoFit && !maximized)
- {
- switch (rotationAngle)
- {
- case 0 or 180:
- titleMaxWidth = Math.Max(width, monitorMinWidth);
- break;
- case 90 or 270:
- titleMaxWidth = Math.Max(height, monitorMinHeight);
- break;
- default:
- {
- var rotationRadians = rotationAngle * Math.PI / 180;
- var newWidth = Math.Abs(width * Math.Cos(rotationRadians)) +
- Math.Abs(height * Math.Sin(rotationRadians));
- titleMaxWidth = Math.Max(newWidth, monitorMinWidth);
- break;
- }
- }
- titleMaxWidth = titleMaxWidth - interfaceSize < interfaceSize
- ? interfaceSize
- : titleMaxWidth - interfaceSize;
- if (Settings.Zoom.ScrollEnabled)
- {
- titleMaxWidth += SizeDefaults.ScrollbarSize + 10;
- }
- }
- else
- {
- // Fix title width to window size
- titleMaxWidth = containerWidth - interfaceSize <= 0 ? 0 : containerWidth - interfaceSize;
- }
- return titleMaxWidth;
- }
- public readonly struct ImageSize(
- double width,
- double height,
- double secondaryWidth,
- double scrollViewerWidth,
- double scrollViewerHeight,
- double titleMaxWidth,
- double margin,
- double aspectRatio)
- {
- public double TitleMaxWidth { get; } = titleMaxWidth;
- public double Width { get; } = width;
- public double Height { get; } = height;
- public double ScrollViewerWidth { get; } = scrollViewerWidth;
- public double ScrollViewerHeight { get; } = scrollViewerHeight;
- public double SecondaryWidth { get; } = secondaryWidth;
- public double Margin { get; } = margin;
- public double AspectRatio { get; } = aspectRatio;
- }
- }
|