feat: add MSIX artifact sink and source
This commit is contained in:
1 parent
e2c15f7145
commit
9e41900596
7 files changed
+209
-5
No files matched your search
@@ -2,6 +2,7 @@ from .common import Sink
|
||||
from .tempart_sink import TempArtSink
|
||||
from .fdart_sink import FdArtSink
|
||||
from .icoart_sink import IcoArtSink
|
||||
from .msixart_sink import MsixArtSink
|
||||
from .icnsart_sink import IcnsArtSink
|
||||
|
||||
__all__ = [
|
||||
@@ -9,5 +10,6 @@ __all__ = [
|
||||
"TempArtSink",
|
||||
"FdArtSink",
|
||||
"IcoArtSink",
|
||||
"MsixArtSink",
|
||||
"IcnsArtSink"
|
||||
]
|
||||
@@ -0,0 +1,105 @@
|
||||
from dataclasses import dataclass
|
||||
from .common import Sink
|
||||
from ..address import Address, AddressDomain
|
||||
from ..environment import Environment
|
||||
from ..utils import (
|
||||
Artifact,
|
||||
MsixCategory,
|
||||
MsixAppLogoKind,
|
||||
MsixAppPlatedKind,
|
||||
resolve_msix_scale,
|
||||
check_vart,
|
||||
)
|
||||
from ...lowlevel import artio, artrdr
|
||||
from ...logger import HIGHLEVEL_LOGGER as LOGGER
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class MsixArtSinkHint:
|
||||
kind: MsixCategory
|
||||
name: str
|
||||
|
||||
|
||||
class MsixArtSink(Sink):
|
||||
__kind: MsixCategory
|
||||
__name: str
|
||||
|
||||
def __init__(self, kind: MsixCategory, name: str) -> None:
|
||||
self.__kind = kind
|
||||
self.__name = name
|
||||
|
||||
@property
|
||||
def address(self) -> Address:
|
||||
return Address(AddressDomain.WinMsixOutput, str(self.__kind), self.__name)
|
||||
|
||||
def push(self, env: Environment, art: Artifact) -> None:
|
||||
LOGGER.info(
|
||||
'Saving Windows MSIX artifact with kind "%s" and name "%s".',
|
||||
self.__kind,
|
||||
self.__name,
|
||||
)
|
||||
check_vart(art)
|
||||
|
||||
# different category need entirely different push strategies
|
||||
match self.__kind:
|
||||
case MsixCategory.Application:
|
||||
self.__push_app(env, art)
|
||||
case MsixCategory.Extension:
|
||||
self.__push_ext(env, art)
|
||||
case _:
|
||||
raise ValueError(f"Unknown MSIX category: {self.__kind}")
|
||||
|
||||
def __push_app(self, env: Environment, art: Artifact) -> None:
|
||||
# push by sub-kind
|
||||
for kind in MsixAppLogoKind:
|
||||
size = kind.to_size()
|
||||
|
||||
# push no suffix variant
|
||||
# TODO: We currently brutely assume all artifacts are squared.
|
||||
# This premise may be broken when meeting with wide tile logo and etc.
|
||||
# But currently we doesn't support them.
|
||||
# So these code need to be changed in future.
|
||||
hw = size[0]
|
||||
(thumbnail,) = artrdr.render_thumbnail(art, (hw,))
|
||||
dst = env.msix_app_output_artifact(kind, None, None, None, self.__name)
|
||||
artio.save_artifact(thumbnail, dst)
|
||||
|
||||
# push scale variants
|
||||
hws = tuple(resolve_msix_scale(hw, scale) for scale in env.prologue.msix_scales)
|
||||
for scale, thumbnail in zip(
|
||||
env.prologue.msix_scales, artrdr.render_thumbnail(art, hws)
|
||||
):
|
||||
dst = env.msix_app_output_artifact(kind, scale, None, None, self.__name)
|
||||
artio.save_artifact(thumbnail, dst)
|
||||
|
||||
# push special variants for Square44x44
|
||||
if kind == MsixAppLogoKind.Square44x44:
|
||||
for targetsize, thumbnail in zip(
|
||||
env.prologue.msix_app44_targetsizes,
|
||||
artrdr.render_thumbnail(art, env.prologue.msix_app44_targetsizes),
|
||||
):
|
||||
for plated in MsixAppPlatedKind:
|
||||
dst = env.msix_app_output_artifact(
|
||||
kind, None, targetsize, plated, self.__name
|
||||
)
|
||||
artio.save_artifact(thumbnail, dst)
|
||||
|
||||
def __push_ext(self, env: Environment, art: Artifact) -> None:
|
||||
# push default with 44x44 size
|
||||
# TODO: These hardcode code is also shitty
|
||||
# It should be improved like ``MsixAppLogoKind`.to_size()`
|
||||
hw = 44
|
||||
(thumbnail,) = artrdr.render_thumbnail(art, (hw,))
|
||||
dst = env.msix_ext_output_artifact(None, self.__name)
|
||||
artio.save_artifact(thumbnail, dst)
|
||||
|
||||
# push targetsize variants
|
||||
for targetsize, thumbnail in zip(
|
||||
env.prologue.msix_ext_targetsizes,
|
||||
artrdr.render_thumbnail(art, env.prologue.msix_ext_targetsizes),
|
||||
):
|
||||
dst = env.msix_ext_output_artifact(targetsize, self.__name)
|
||||
artio.save_artifact(thumbnail, dst)
|
||||
|
||||
def push_hint(self) -> MsixArtSinkHint:
|
||||
return MsixArtSinkHint(self.__kind, self.__name)
|
||||
@@ -6,6 +6,7 @@ from .blender_source import BlenderSource
|
||||
from .tempart_source import TempArtSource
|
||||
from .fdart_source import FdArtSource
|
||||
from .icoart_source import IcoArtSource
|
||||
from .msixart_source import MsixArtSource
|
||||
from .icnsart_source import IcnsArtSource
|
||||
|
||||
|
||||
@@ -18,5 +19,6 @@ __all__ = [
|
||||
"TempArtSource",
|
||||
"FdArtSource",
|
||||
"IcoArtSource",
|
||||
"MsixArtSource",
|
||||
"IcnsArtSource",
|
||||
]
|
||||
@@ -19,8 +19,8 @@ class IcnsArtSource(Source):
|
||||
def address(self) -> Address:
|
||||
return Address(AddressDomain.MacIcnsOutput, str(self.__kind), self.__name)
|
||||
|
||||
def link_to(self, env: Environment, mac_sink: IcnsArtSink) -> None:
|
||||
sink_hint = mac_sink.push_hint()
|
||||
def link_to(self, env: Environment, icns_sink: IcnsArtSink) -> None:
|
||||
sink_hint = icns_sink.push_hint()
|
||||
LOGGER.info(
|
||||
'Duplicating macOS ICNS artifact from kind "%s" name "%s" to kind "%s" name "%s".',
|
||||
self.__kind,
|
||||
|
||||
@@ -19,8 +19,8 @@ class IcoArtSource(Source):
|
||||
def address(self) -> Address:
|
||||
return Address(AddressDomain.WinIcoOutput, str(self.__kind), self.__name)
|
||||
|
||||
def link_to(self, env: Environment, win_sink: IcoArtSink) -> None:
|
||||
sink_hint = win_sink.push_hint()
|
||||
def link_to(self, env: Environment, ico_sink: IcoArtSink) -> None:
|
||||
sink_hint = ico_sink.push_hint()
|
||||
LOGGER.info(
|
||||
'Duplicating Windows ICO artifact from kind "%s" name "%s" to kind "%s" name "%s".',
|
||||
self.__kind,
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
from .common import Source
|
||||
from ..address import Address, AddressDomain
|
||||
from ..environment import Environment
|
||||
from ..sink.msixart_sink import MsixArtSink, MsixArtSinkHint
|
||||
from ..utils import MsixCategory, MsixAppLogoKind, MsixAppPlatedKind
|
||||
from ...lowlevel import artio
|
||||
from ...logger import HIGHLEVEL_LOGGER as LOGGER
|
||||
|
||||
|
||||
class MsixArtSource(Source):
|
||||
__kind: MsixCategory
|
||||
__name: str
|
||||
|
||||
def __init__(self, kind: MsixCategory, name: str) -> None:
|
||||
self.__kind = kind
|
||||
self.__name = name
|
||||
|
||||
@property
|
||||
def address(self) -> Address:
|
||||
return Address(AddressDomain.WinMsixOutput, str(self.__kind), self.__name)
|
||||
|
||||
def link_to(self, env: Environment, msix_sink: MsixArtSink) -> None:
|
||||
sink_hint = msix_sink.push_hint()
|
||||
LOGGER.info(
|
||||
'Duplicating Windows MSIX artifact from kind "%s" name "%s" to kind "%s" name "%s".',
|
||||
self.__kind,
|
||||
self.__name,
|
||||
sink_hint.kind,
|
||||
sink_hint.name,
|
||||
)
|
||||
|
||||
# different category need entirely different link strategies
|
||||
match self.__kind:
|
||||
case MsixCategory.Application:
|
||||
self.__link_to_app(env, sink_hint)
|
||||
case MsixCategory.Extension:
|
||||
self.__link_to_ext(env, sink_hint)
|
||||
case _:
|
||||
raise ValueError(f"Unknown MSIX category: {self.__kind}")
|
||||
|
||||
def __link_to_app(self, env: Environment, sink_hint: MsixArtSinkHint) -> None:
|
||||
# link by sub-kind
|
||||
for kind in MsixAppLogoKind:
|
||||
# link no suffix variant
|
||||
artio.link_artifact(
|
||||
env.msix_app_output_artifact(kind, None, None, None, self.__name),
|
||||
env.msix_app_output_artifact(kind, None, None, None, sink_hint.name),
|
||||
)
|
||||
|
||||
# link scale variants
|
||||
for scale in env.prologue.msix_scales:
|
||||
artio.link_artifact(
|
||||
env.msix_app_output_artifact(kind, scale, None, None, self.__name),
|
||||
env.msix_app_output_artifact(
|
||||
kind, scale, None, None, sink_hint.name
|
||||
),
|
||||
)
|
||||
|
||||
# link special variants for Square44x44
|
||||
if kind == MsixAppLogoKind.Square44x44:
|
||||
for targetsize in env.prologue.msix_app44_targetsizes:
|
||||
for plated in MsixAppPlatedKind:
|
||||
artio.link_artifact(
|
||||
env.msix_app_output_artifact(
|
||||
kind, None, targetsize, plated, self.__name
|
||||
),
|
||||
env.msix_app_output_artifact(
|
||||
kind, None, targetsize, plated, sink_hint.name
|
||||
),
|
||||
)
|
||||
|
||||
def __link_to_ext(self, env: Environment, sink_hint: MsixArtSinkHint) -> None:
|
||||
# link default
|
||||
artio.link_artifact(
|
||||
env.msix_ext_output_artifact(None, self.__name),
|
||||
env.msix_ext_output_artifact(None, sink_hint.name),
|
||||
)
|
||||
|
||||
# link targetsize variants
|
||||
for targetsize in env.prologue.msix_ext_targetsizes:
|
||||
artio.link_artifact(
|
||||
env.msix_ext_output_artifact(targetsize, self.__name),
|
||||
env.msix_ext_output_artifact(targetsize, sink_hint.name),
|
||||
)
|
||||
@@ -20,6 +20,17 @@ def check_fd_hw(hw: int) -> None:
|
||||
)
|
||||
|
||||
|
||||
def resolve_msix_scale(hw: int, scale: int) -> int:
|
||||
"""
|
||||
Resolve given MSIX scale value with original width/height.
|
||||
|
||||
:param hw: The height or width before scale for resolving.
|
||||
:param scale: The scale value for resolving.
|
||||
:returns: The height/width after applying scale value.
|
||||
"""
|
||||
return hw * scale // 100
|
||||
|
||||
|
||||
def check_msix_scale(hw: int, scale: int) -> None:
|
||||
"""
|
||||
Check whether given MSIX scale value is valid.
|
||||
@@ -32,7 +43,7 @@ def check_msix_scale(hw: int, scale: int) -> None:
|
||||
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
|
||||
scaled_hw = resolve_msix_scale(hw, scale)
|
||||
if scaled_hw > VART_HW:
|
||||
raise ValueError(f"Scale value is too large for MSIX icon variant: {scale}")
|
||||
|
||||
|
||||
Reference in new issue
Block a user