diff --git a/src/assemblicon/highlevel/environment.py b/src/assemblicon/highlevel/environment.py index 57a9d3b..e25c88b 100644 --- a/src/assemblicon/highlevel/environment.py +++ b/src/assemblicon/highlevel/environment.py @@ -27,9 +27,26 @@ class Prologue(LowPrologue): fd_thumbnail_hws: tuple[int, ...] """ The collection of sizes of generated FreeDesktop icons. - Each size must be greater than zero and lower or equal to ``VART_HW``. + Each size must be greater than zero and lower than or equal to ``VART_HW``. Due to icon is a square rectangle, the height and width are same. """ + msix_scales: tuple[int, ...] + """ + The collection of scale values of generated MSIX icon variants. + Each size must be greater than 100 (100 percent) and, when applied to the + largest MSIX application logo, yield a scaled image whose length and width + are less than or equal to ``VART_HW``. + """ + msix_app44_targetsizes: tuple[int, ...] + """ + The collection of targetsize values of generated MSIX application 44x44 icon variants. + Each size must be greater than zero and lower than or equal to ``VART_HW``. + """ + msix_ext_targetsizes: tuple[int, ...] + """ + The collection of targetsize values of generated MSIX file association icon variants. + Each size must be greater than zero and lower than or equal to ``VART_HW``. + """ temp_dir_initializer: Callable[[Path], None] | None """ The extra initializer for user temporary directory. @@ -42,6 +59,17 @@ class Prologue(LowPrologue): for hw in self.fd_thumbnail_hws: check_fd_hw(hw) + # use maximum height/width for checking + max_msix_hw = MsixAppLogoKind.max_hw() + for scale in self.msix_scales: + check_msix_scale(max_msix_hw, scale) + + for targetsize in self.msix_app44_targetsizes: + check_msix_targetsize(targetsize) + + for targetsize in self.msix_ext_targetsizes: + check_msix_targetsize(targetsize) + _TEMP_USER_DIR: str = "user" _TEMP_LIB_DIR: str = "assemblicon" @@ -313,7 +341,7 @@ class Environment(Generic[P]): # build file name part if scale is not None: - check_msix_scale(scale) + check_msix_scale(max(kind.to_size()), scale) filename = f"{name}.{kind}.scale-{scale}.png" elif targetsize is not None: check_msix_targetsize(targetsize) diff --git a/src/assemblicon/highlevel/utils.py b/src/assemblicon/highlevel/utils.py index 8c8b820..933de83 100644 --- a/src/assemblicon/highlevel/utils.py +++ b/src/assemblicon/highlevel/utils.py @@ -15,20 +15,33 @@ def check_vart(art: Artifact) -> None: def check_fd_hw(hw: int) -> None: if hw <= 0 or hw > VART_HW: raise ValueError( - f"Invalid FreeDesktop icon thumbnail size. " + "Invalid FreeDesktop icon thumbnail size. " f"Expect > 0 and <= {VART_HW}, got {hw}." ) -def check_msix_scale(scale: int) -> None: +def check_msix_scale(hw: int, scale: int) -> None: + """ + Check whether given MSIX scale value is valid. + + :param hw: The height or width before scale for checking. + :param scale: The scale value for checking. + :raises ValueError: Given scale value is invalid. + """ + # scale must be > 100 (100 percent) if scale <= 100: raise ValueError(f"Invalid scale value for MSIX icon variant: {scale}") + # the image scaled after this value must not exceed VART_HW + scaled_hw = hw * scale // 100 + if scaled_hw > VART_HW: + raise ValueError(f"Scale value is too large for MSIX icon variant: {scale}") def check_msix_targetsize(targetsize: int) -> None: - if targetsize <= 0: + if targetsize <= 0 or targetsize > VART_HW: raise ValueError( - f"Invalid targetsize value for MSIX icon variant: {targetsize}" + "Invalid targetsize value for MSIX icon variant. " + f"Expect > 0 and <= {VART_HW}, got {targetsize}." ) @@ -70,6 +83,24 @@ class MsixAppLogoKind(enum.StrEnum): Square150x150 = "Square150x150Logo" """The 150x150 icon used for medium tile.""" + def to_size(self) -> tuple[int, int]: + match self: + case MsixAppLogoKind.StoreLogo: + return (50, 50) + case MsixAppLogoKind.Square44x44: + return (44, 44) + case MsixAppLogoKind.Square150x150: + return (150, 150) + case _: + raise ValueError(f"Unknown app logo kind: {self}") + + @staticmethod + def max_hw() -> int: + hw = 0 + for kind in MsixAppLogoKind: + hw = max(hw, max(kind.to_size())) + return hw + class MsixAppPlatedKind(enum.StrEnum): Plated = "plated" @@ -85,5 +116,22 @@ class IcnsCategory(enum.StrEnum): """Icons for file extensions""" +# fmt: off DEFAULT_FD_THUMBNAIL_HWS: tuple[int, ...] = (16, 32, 48, 64, 128, 256, 512) +# fmt: on """The default collection of sizes for generating FreeDesktop icons.""" + +# fmt: off +DEFAULT_MSIX_SCALES: tuple[int, ...] = (125, 150, 200, 400) +# fmt: on +"""The default collection of ``scale`` for generating MSIX variants.""" + +# fmt: off +DEFAULT_MSIX_APP44_TARGETSIZES: tuple[int, ...] = (16, 20, 24, 30, 32, 36, 40, 48, 60, 64, 72, 80, 96, 256) +# fmt: on +"""The default collection of ``targetsize`` for generating MSIX 44x44Logo variants.""" + +# fmt: off +DEFAULT_MSIX_EXT_TARGETSIZES: tuple[int, ...] = (16, 24, 32, 48, 256) +# fmt: on +"""The default collection of ``targetsize`` for generating MSIX file association logo variants."""