From 8de5cf96907c6718646672c3fc7e08811f9f5e93 Mon Sep 17 00:00:00 2001 From: Hikaru Y Date: Thu, 16 Nov 2023 09:30:54 +0900 Subject: [PATCH] Fix misalignment of IO masks in Qt5 when image is vertically long (#2829) * Revert "Fix I/O not showing in Qt5" This reverts commit c478689e5a04e8b92989a6f9902e59722db4d4ec. * Fix misalignment of IO masks in Qt5 when image is vertically long Also, as in Qt6, constrain the IO image to fit in the viewport. --- qt/aqt/theme.py | 6 ++--- ts/image-occlusion/review.ts | 45 +++++++++++++++++++++++++++++++++++- ts/reviewer/reviewer.scss | 4 ---- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/qt/aqt/theme.py b/qt/aqt/theme.py index 498941f44..6acd5463d 100644 --- a/qt/aqt/theme.py +++ b/qt/aqt/theme.py @@ -177,10 +177,8 @@ class ThemeManager: classes.append("reduce-motion") if not aqt.mw.pm.minimalist_mode(): classes.append("fancy") - if qtmajor == 5: - classes.append("qt5") - if qtminor < 15: - classes.append("no-blur") + if qtmajor == 5 and qtminor < 15: + classes.append("no-blur") return " ".join(classes) def body_classes_for_card_ord( diff --git a/ts/image-occlusion/review.ts b/ts/image-occlusion/review.ts index 603e4c04d..7d42119de 100644 --- a/ts/image-occlusion/review.ts +++ b/ts/image-occlusion/review.ts @@ -74,6 +74,43 @@ async function waitForImage(): Promise { }); } +/** + * Calculate the size of the container that will fit in the viewport while having + * the same aspect ratio as the image. This is a workaround for Qt5 WebEngine not + * supporting the `aspect-ratio` CSS property. + */ +function calculateContainerSize( + container: HTMLDivElement, + img: HTMLImageElement, +): { width: number; height: number } { + const compStyle = getComputedStyle(container); + + const compMaxWidth = parseFloat(compStyle.getPropertyValue("max-width")); + const vw = container.parentElement!.clientWidth; + // respect 'max-width' if it is set narrower than the viewport + const maxWidth = Number.isNaN(compMaxWidth) || compMaxWidth > vw ? vw : compMaxWidth; + + // see ./review.scss + const defaultMaxHeight = document.documentElement.clientHeight * 0.95 - 40; + const compMaxHeight = parseFloat(compStyle.getPropertyValue("max-height")); + let maxHeight: number; + // If 'max-height' is set to 'unset' or 'initial' and the image is taller than + // the default max height, the container height is up to the image height. + if (Number.isNaN(compMaxHeight)) { + maxHeight = Math.max(img.naturalHeight, defaultMaxHeight); + } else if (compMaxHeight < defaultMaxHeight) { + maxHeight = compMaxHeight; + } else { + maxHeight = Math.max(defaultMaxHeight, Math.min(img.naturalHeight, compMaxHeight)); + } + + const ratio = Math.min( + maxWidth / img.naturalWidth, + maxHeight / img.naturalHeight, + ); + return { width: img.naturalWidth * ratio, height: img.naturalHeight * ratio }; +} + function setupImageOcclusionInner(setupOptions?: SetupImageOcclusionOptions): void { const canvas = document.querySelector( "#image-occlusion-canvas", @@ -94,7 +131,13 @@ function setupImageOcclusionInner(setupOptions?: SetupImageOcclusionOptions): vo } // Enforce aspect ratio of image - container.style.aspectRatio = `${image.naturalWidth / image.naturalHeight}`; + if (CSS.supports("aspect-ratio: 1")) { + container.style.aspectRatio = `${image.naturalWidth / image.naturalHeight}`; + } else { + const containerSize = calculateContainerSize(container, image); + container.style.width = `${containerSize.width}px`; + container.style.height = `${containerSize.height}px`; + } const size = optimumPixelSizeForCanvas( { width: image.naturalWidth, height: image.naturalHeight }, diff --git a/ts/reviewer/reviewer.scss b/ts/reviewer/reviewer.scss index 12ae087b1..1c5d6a7d4 100644 --- a/ts/reviewer/reviewer.scss +++ b/ts/reviewer/reviewer.scss @@ -129,7 +129,3 @@ button { .nightMode img.drawing { filter: unquote("invert(1) hue-rotate(180deg)"); } - -.qt5 #image-occlusion-container img { - position: relative; -}