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 .tempart_sink import TempArtSink
|
||||||
from .fdart_sink import FdArtSink
|
from .fdart_sink import FdArtSink
|
||||||
from .icoart_sink import IcoArtSink
|
from .icoart_sink import IcoArtSink
|
||||||
|
from .msixart_sink import MsixArtSink
|
||||||
from .icnsart_sink import IcnsArtSink
|
from .icnsart_sink import IcnsArtSink
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
@@ -9,5 +10,6 @@ __all__ = [
|
|||||||
"TempArtSink",
|
"TempArtSink",
|
||||||
"FdArtSink",
|
"FdArtSink",
|
||||||
"IcoArtSink",
|
"IcoArtSink",
|
||||||
|
"MsixArtSink",
|
||||||
"IcnsArtSink"
|
"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 .tempart_source import TempArtSource
|
||||||
from .fdart_source import FdArtSource
|
from .fdart_source import FdArtSource
|
||||||
from .icoart_source import IcoArtSource
|
from .icoart_source import IcoArtSource
|
||||||
|
from .msixart_source import MsixArtSource
|
||||||
from .icnsart_source import IcnsArtSource
|
from .icnsart_source import IcnsArtSource
|
||||||
|
|
||||||
|
|
||||||
@@ -18,5 +19,6 @@ __all__ = [
|
|||||||
"TempArtSource",
|
"TempArtSource",
|
||||||
"FdArtSource",
|
"FdArtSource",
|
||||||
"IcoArtSource",
|
"IcoArtSource",
|
||||||
|
"MsixArtSource",
|
||||||
"IcnsArtSource",
|
"IcnsArtSource",
|
||||||
]
|
]
|
||||||
@@ -19,8 +19,8 @@ class IcnsArtSource(Source):
|
|||||||
def address(self) -> Address:
|
def address(self) -> Address:
|
||||||
return Address(AddressDomain.MacIcnsOutput, str(self.__kind), self.__name)
|
return Address(AddressDomain.MacIcnsOutput, str(self.__kind), self.__name)
|
||||||
|
|
||||||
def link_to(self, env: Environment, mac_sink: IcnsArtSink) -> None:
|
def link_to(self, env: Environment, icns_sink: IcnsArtSink) -> None:
|
||||||
sink_hint = mac_sink.push_hint()
|
sink_hint = icns_sink.push_hint()
|
||||||
LOGGER.info(
|
LOGGER.info(
|
||||||
'Duplicating macOS ICNS artifact from kind "%s" name "%s" to kind "%s" name "%s".',
|
'Duplicating macOS ICNS artifact from kind "%s" name "%s" to kind "%s" name "%s".',
|
||||||
self.__kind,
|
self.__kind,
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ class IcoArtSource(Source):
|
|||||||
def address(self) -> Address:
|
def address(self) -> Address:
|
||||||
return Address(AddressDomain.WinIcoOutput, str(self.__kind), self.__name)
|
return Address(AddressDomain.WinIcoOutput, str(self.__kind), self.__name)
|
||||||
|
|
||||||
def link_to(self, env: Environment, win_sink: IcoArtSink) -> None:
|
def link_to(self, env: Environment, ico_sink: IcoArtSink) -> None:
|
||||||
sink_hint = win_sink.push_hint()
|
sink_hint = ico_sink.push_hint()
|
||||||
LOGGER.info(
|
LOGGER.info(
|
||||||
'Duplicating Windows ICO artifact from kind "%s" name "%s" to kind "%s" name "%s".',
|
'Duplicating Windows ICO artifact from kind "%s" name "%s" to kind "%s" name "%s".',
|
||||||
self.__kind,
|
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:
|
def check_msix_scale(hw: int, scale: int) -> None:
|
||||||
"""
|
"""
|
||||||
Check whether given MSIX scale value is valid.
|
Check whether given MSIX scale value is valid.
|
||||||
@@ -32,7 +43,7 @@ def check_msix_scale(hw: int, scale: int) -> None:
|
|||||||
if scale <= 100:
|
if scale <= 100:
|
||||||
raise ValueError(f"Invalid scale value for MSIX icon variant: {scale}")
|
raise ValueError(f"Invalid scale value for MSIX icon variant: {scale}")
|
||||||
# the image scaled after this value must not exceed VART_HW
|
# 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:
|
if scaled_hw > VART_HW:
|
||||||
raise ValueError(f"Scale value is too large for MSIX icon variant: {scale}")
|
raise ValueError(f"Scale value is too large for MSIX icon variant: {scale}")
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user