Files
LabDennis 1f4aaaec47 Fonts: finish Thai fallback delivery for desktop and web releases
Retain the complete reviewed change, including prior integration resolutions,
on current upstream.

#736: deliver Thai UI fonts in desktop and web releases

Use the merged craft-fonts input containing Noto Sans Thai across release,
FreeBSD and Nix builds. Retain the small Thai face in the wasm subset and
reject required release inputs that lack it. Exercise the reported Thai
folder name through all UI families and include original font licence texts
in Windows installers as well as portable packages.

Refs #736; completes delivery of the fallback added in #750.

Validation: UI tests, UI-only strict Clippy, 28 wasm checks, HEIF checks,
assets, layers, parity and formatting pass. All 21 unrelated workspace
failures reproduce with upstream Rust sources and the old font input;
existing Rust 1.95 metadata/engine Clippy findings remain unchanged.
2026-10-14 18:52:15 +02:00

215 lines
13 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!--
LightCraft MSI (WiX Toolset v5: `dotnet tool install -g wix`, plus the UI and Util extensions:
`wix extension add -g WixToolset.UI.wixext/5.0.2 WixToolset.Util.wixext/5.0.2`). Built by package.ps1:
wix build lightcraft.wxs -arch x64 -ext WixToolset.UI.wixext/5.0.2 -ext WixToolset.Util.wixext/5.0.2
-d Version=1.2.3 -d BinDir=... -d IconPath=... -d UiDialogBmp=... -d UiBannerBmp=... -o out.msi
Per-machine install into Program Files (or the folder chosen in the installer, or
`INSTALLFOLDER=...` on the msiexec command line; upgrades keep it), a Start Menu shortcut, `.pcraft` owned by LightCraft,
and LightCraft offered under "Open with" for PSD/PSB and the image formats it reads (without
taking over the user's default app for them).
-->
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Package
Name="LightCraft"
Manufacturer="Learning Machines LLC"
Version="$(var.Version)"
UpgradeCode="229BB552-5EFD-479A-BA86-8CB6D926390C"
Scope="perMachine"
Compressed="yes"
Language="1033">
<SummaryInformation Description="LightCraft photo library and raw developer" Manufacturer="Learning Machines LLC" />
<!-- Same-version upgrades let successive pre-releases of one X.Y.Z replace each other
(MSI versions are numeric, so 1.2.3-rc.1 and 1.2.3-rc.2 are both 1.2.3). -->
<MajorUpgrade AllowSameVersionUpgrades="yes"
DowngradeErrorMessage="A newer version of LightCraft is already installed." />
<MediaTemplate EmbedCab="yes" CompressionLevel="high" />
<Icon Id="LightcraftIcon.ico" SourceFile="$(var.IconPath)" />
<Property Id="ARPPRODUCTICON" Value="LightcraftIcon.ico" />
<Property Id="ARPURLINFOABOUT" Value="https://getartcraft.com/apps/lightcraft" />
<Property Id="ARPURLUPDATEINFO" Value="https://getartcraft.com/apps/lightcraft" />
<Property Id="ARPHELPLINK" Value="https://discord.gg/artcraft" />
<StandardDirectory Id="ProgramFiles6432Folder">
<Directory Id="INSTALLFOLDER" Name="LightCraft" />
</StandardDirectory>
<!-- The folder of the installed version (written by LightcraftApp), so an upgrade installs
where the user chose instead of moving back to Program Files (issue #399). Searched into
its own property: AppSearch would otherwise overwrite INSTALLFOLDER=... given to msiexec. -->
<Property Id="PREVIOUSINSTALLFOLDER">
<RegistrySearch Id="PreviousInstallFolder" Root="HKLM" Key="Software\LightCraft" Name="InstallFolder" Type="raw" />
</Property>
<SetProperty Id="INSTALLFOLDER" Value="[PREVIOUSINSTALLFOLDER]" After="AppSearch" Sequence="both"
Condition="PREVIOUSINSTALLFOLDER AND NOT INSTALLFOLDER" />
<!-- Older MSIs (including 0.5.0) only recorded the executable in App Paths. Type="file"
without a FileSearch returns its containing directory. Keep the searches separate so
the newer InstallFolder value and an explicit INSTALLFOLDER always take precedence. -->
<Property Id="LEGACYINSTALLFOLDER">
<RegistrySearch Id="LegacyInstallFolder" Root="HKLM"
Key="Software\Microsoft\Windows\CurrentVersion\App Paths\lightcraft.exe" Type="file" />
</Property>
<!-- That directory search doesn't check the executable exists, and when its unquoted path is
gone it falls back to the text before the first space: a deleted
"C:\Program Files\LightCraft\lightcraft.exe" yields "C:\". Only use the folder when this
search, which does require lightcraft.exe, finds it too. -->
<Property Id="LEGACYINSTALLEXE">
<RegistrySearch Id="LegacyInstallExe" Root="HKLM"
Key="Software\Microsoft\Windows\CurrentVersion\App Paths\lightcraft.exe" Type="file">
<FileSearch Id="LegacyInstallExeFile" Name="lightcraft.exe" />
</RegistrySearch>
</Property>
<SetProperty Id="INSTALLFOLDER" Action="SetInstallFolderFromAppPaths" Value="[LEGACYINSTALLFOLDER]"
After="SetINSTALLFOLDER" Sequence="both"
Condition="LEGACYINSTALLFOLDER AND LEGACYINSTALLEXE AND NOT PREVIOUSINSTALLFOLDER AND NOT INSTALLFOLDER" />
<StandardDirectory Id="ProgramMenuFolder" />
<Feature Id="Main" Title="LightCraft" Level="1">
<ComponentGroupRef Id="LightcraftFiles" />
</Feature>
<UIRef Id="LightcraftUI" />
</Package>
<!--
Interactive install UI: Welcome -> Destination Folder -> Ready to install -> progress ->
"Completed" (Finish), with a "Launch LightCraft" checkbox (checked by default). Destination
Folder (issue #399) shows Program Files\LightCraft, or the installed version's folder on an
upgrade; Change... browses, and a folder that can't be used (InvalidDirDlg) is refused before
anything is installed. Failure and cancellation end on WiX's standard FatalError / UserExit
dialogs instead of the completion page. Maintenance (running the MSI again, Repair/Remove from
Apps) uses the standard maintenance dialogs; every successful run — install, repair or
remove — then ends on the shared completion page, so a successful uninstall is confirmed
with a visible final dialog (issue #892; the page itself is issue #790's fix).
This is WixUI_InstallDir without its licence-acceptance page: LightCraft is MIT OR Apache-2.0,
which ask nothing of people who just install and run it, so a click-through EULA would only
add a step. Silent (/qn) and basic-UI (/passive, /qb) installs never show these dialogs, so
they are unaffected, and nothing is launched.
The dialogs, strings and error/cancel pages come from WixToolset.UI.wixext; the side and
banner bitmaps are plain panels generated by package.ps1 (no third-party artwork).
-->
<Fragment>
<WixVariable Id="WixUIDialogBmp" Value="$(var.UiDialogBmp)" />
<WixVariable Id="WixUIBannerBmp" Value="$(var.UiBannerBmp)" />
<Property Id="WIXUI_EXITDIALOGOPTIONALTEXT"
Value="LightCraft has been installed. You can start it at any time from the Start menu." />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Launch LightCraft" />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
<!-- "Launch LightCraft" on Finish. WixUnelevatedShellExec (Util extension) asks the desktop
shell (Explorer) to start the program, so it runs as the signed-in user at normal
integrity even when the installer UI itself is elevated (e.g. msiexec started from an
admin prompt); it never runs from the elevated/SYSTEM server side. It is a UI-only control
event, so silent and passive installs never run it. Return="ignore": a failed launch must
not turn a successful install into an error. -->
<Property Id="WixUnelevatedShellExecTarget" Value="[#LightcraftExe]" />
<CustomAction Id="LaunchLightcraft" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)"
DllEntry="WixUnelevatedShellExec" Execute="immediate" Impersonate="yes" Return="ignore" />
<UI Id="LightcraftUI">
<TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
<TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
<TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />
<Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
<DialogRef Id="ErrorDlg" />
<DialogRef Id="FatalError" />
<DialogRef Id="FilesInUse" />
<DialogRef Id="MsiRMFilesInUse" />
<DialogRef Id="PrepareDlg" />
<DialogRef Id="ProgressDlg" />
<DialogRef Id="ResumeDlg" />
<DialogRef Id="UserExit" />
<DialogRef Id="WelcomeDlg" />
<DialogRef Id="InstallDirDlg" />
<DialogRef Id="BrowseDlg" />
<DialogRef Id="InvalidDirDlg" />
<DialogRef Id="DiskCostDlg" />
<!-- Referenced by the Publish events below but never pulled in on its own: without this
ref the MSI ships without a completion page, so a successful install or remove ends
silently (issues #790, #892). The UI extension's fragment shows it on exit=success,
which covers Remove from Apps & features too. -->
<DialogRef Id="ExitDialog" />
<DialogRef Id="VerifyReadyDlg" />
<DialogRef Id="MaintenanceWelcomeDlg" />
<DialogRef Id="MaintenanceTypeDlg" />
<!-- The folder InstallDirDlg edits. -->
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
<!-- First install / upgrade: Welcome -> Destination Folder -> Ready to install. A patch skips
the folder (it can't move an installed product). -->
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg" Condition="NOT Installed" />
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Condition="Installed AND PATCH" />
<!-- Destination Folder, as in WixUI_InstallDir: Next sets the folder, validates it (WiX's
WixUIValidatePath) and refuses one that can't be used; Change... opens the folder browser,
whose OK validates too. -->
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" />
<Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1" />
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="WixUIValidatePath_$(sys.BUILDARCHSHORT)" Order="2"
Condition="NOT WIXUI_DONTVALIDATEPATH" />
<Publish Dialog="InstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3"
Condition="NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID&lt;&gt;&quot;1&quot;" />
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="4"
Condition="WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID=&quot;1&quot;" />
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1" />
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2" />
<Publish Dialog="BrowseDlg" Control="OK" Event="DoAction" Value="WixUIValidatePath_$(sys.BUILDARCHSHORT)" Order="3"
Condition="NOT WIXUI_DONTVALIDATEPATH" />
<Publish Dialog="BrowseDlg" Control="OK" Event="SpawnDialog" Value="InvalidDirDlg" Order="4"
Condition="NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID&lt;&gt;&quot;1&quot;" />
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="InstallDirDlg" Order="1"
Condition="NOT Installed" />
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="3"
Condition="Installed AND PATCH" />
<!-- Maintenance: Welcome -> Repair / Remove -> Ready. -->
<Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg" />
<Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg" />
<Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg" />
<Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg" />
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2"
Condition="Installed AND NOT PATCH" />
<!-- Completion page: optionally launch, then close. -->
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="LaunchLightcraft" Order="1"
Condition="WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 AND NOT Installed" />
<Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999" />
<!-- One feature, nothing to change: no "Change" in Apps & features. -->
<Property Id="ARPNOMODIFY" Value="1" />
</UI>
<UIRef Id="WixUI_Common" />
</Fragment>
<Fragment>
<ComponentGroup Id="LightcraftFiles" Directory="INSTALLFOLDER">
<Component Id="LightcraftApp" Guid="8A1D3A39-F7C1-47B1-97AE-40C80BF82F4A">
<File Id="LightcraftExe" Source="$(var.BinDir)\lightcraft.exe" KeyPath="yes">
<Shortcut Id="StartMenuShortcut" Directory="ProgramMenuFolder" Name="LightCraft"
Description="LightCraft photo library and raw developer" WorkingDirectory="INSTALLFOLDER" Advertise="yes"
Icon="LightcraftIcon.ico" IconIndex="0" />
</File>
<RegistryValue Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\App Paths\lightcraft.exe" Value="[#LightcraftExe]" Type="string" />
<RegistryValue Root="HKLM" Key="Software\LightCraft" Name="InstallFolder" Value="[INSTALLFOLDER]" Type="string" />
</Component>
<Component Id="LightcraftCli">
<File Id="LightcraftCliExe" Source="$(var.BinDir)\lightcraft-cli.exe" KeyPath="yes" />
</Component>
<Component Id="LightcraftFontLicences">
<File Id="LightcraftFontLicencesFile" Source="$(var.BinDir)\FONT-LICENCES.txt" KeyPath="yes" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>