diff --git a/appveyor.yml b/appveyor.yml index 8460abca1..670c1ca69 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -41,7 +41,6 @@ for: choco install ActivePerl choco install nasm choco install jom - choco install imagemagick.tool --version 7.0.11.13 choco install wixtoolset --version 3.11.2 Remove-Item -Path (Join-Path $Env:SystemDrive OpenSSL-Win32) -Recurse diff --git a/dist/msi/ConvertTo-Icon.ps1 b/dist/msi/ConvertTo-Icon.ps1 new file mode 100644 index 000000000..a66f25051 --- /dev/null +++ b/dist/msi/ConvertTo-Icon.ps1 @@ -0,0 +1,73 @@ +$ErrorActionPreference = 'Stop' + +# Adapted from: https://gist.github.com/darkfall/1656050 + +Add-Type -AssemblyName System.Drawing + +$outputFileName = $args[0] +$inputFileNames = $args[1..$args.Count] + +$inputImages = [System.Collections.ArrayList]@() + +foreach ($inputFileName in $inputFileNames) { + $resolvedInputFileName = $ExecutionContext.SessionState.Path.GetResolvedPSPathFromPSPath($inputFileName) + Write-Output "Input[$($inputImages.Count)]: $inputFileName ($resolvedInputFileName)" + + $inputBitmap = New-Object System.Drawing.Bitmap "$resolvedInputFileName" + if ($inputBitmap.Width -ne $inputBitmap.Height) { + throw "Input image is not square ($($inputBitmap.Width) != $($inputBitmap.Height))" + } + + $inputStream = New-Object System.IO.MemoryStream + $inputBitmap.Save($inputStream, [System.Drawing.Imaging.ImageFormat]::Png) + + $inputImage = @{ + Size = $inputBitmap.Width + Bytes = $inputStream.ToArray() + } + Write-Output " Size = $($inputImage.Size), Bytes = $($inputImage.Bytes.Count)" + + [void]$inputImages.Add($inputImage) + + $inputBitmap.Dispose() + $inputStream.Dispose() +} + +$resolvedOutputFileName = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($outputFileName) +Write-Output "Output: $outputFileName ($resolvedOutputFileName)" + +$outputFile = [System.IO.File]::Create($resolvedOutputFileName) + +$outputFileWriter = New-Object System.IO.BinaryWriter($outputFile) +$outputFileWriter.Write([short]0) # 0-1 reserved, 0 +$outputFileWriter.Write([short]1) # 2-3 image type, 1 = icon, 2 = cursor +$outputFileWriter.Write([short]$inputImages.Count) # 4-5 number of images + +$offset = 6 + (16 * $inputImages.Count) + +for ($i = 0; $i -lt $inputImages.Count; ++$i) { + $size = $inputImages[$i].Size + if ($size -eq 256) { + $size = 0 + } + + $outputFileWriter.Write([byte]$size) # 0 image width + $outputFileWriter.Write([byte]$size) # 1 image height + $outputFileWriter.Write([byte]0) # 2 number of colors + $outputFileWriter.Write([byte]0) # 3 reserved + $outputFileWriter.Write([short]0) # 4-5 color planes + $outputFileWriter.Write([short]32) # 6-7 bits per pixel + $outputFileWriter.Write([int]$inputImages[$i].Bytes.Count) # 8-11 size of image data + $outputFileWriter.Write([int]$offset) # 12-15 offset of image data + + $offset += $inputImages[$i].Bytes.Count +} + +for ($i = 0; $i -lt $inputImages.Count; ++$i) { + # write image data + # png data must contain the whole png data file + $outputFileWriter.Write($inputImages[$i].Bytes) +} + +$outputFileWriter.Flush() +$outputFile.Close() diff --git a/dist/msi/UtilityFunctions.cmake b/dist/msi/UtilityFunctions.cmake index a8122e3ab..28386c863 100644 --- a/dist/msi/UtilityFunctions.cmake +++ b/dist/msi/UtilityFunctions.cmake @@ -44,10 +44,22 @@ function(png2ico OUTPUT_FILE) set(OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_FILE}") endif() - add_custom_command( - OUTPUT "${OUTPUT_FILE}" - COMMAND magick convert ${ARGN} "${OUTPUT_FILE}" - DEPENDS ${ARGN}) + find_program(MAGICK_PROGRAM magick) + find_program(PWSH_PROGRAM pwsh powershell) + + if(MAGICK_PROGRAM) + add_custom_command( + OUTPUT "${OUTPUT_FILE}" + COMMAND "${MAGICK_PROGRAM}" convert ${ARGN} "${OUTPUT_FILE}" + DEPENDS ${ARGN}) + elseif(PWSH_PROGRAM) + add_custom_command( + OUTPUT "${OUTPUT_FILE}" + COMMAND "${PWSH_PROGRAM}" -Command "${CMAKE_CURRENT_LIST_DIR}/ConvertTo-Icon.ps1" "${OUTPUT_FILE}" ${ARGN} + DEPENDS ${ARGN}) + else() + message(FATAL_ERROR "Unable to convert PNGs to ICO (no suitable program found)") + endif() list(APPEND ${OUTPUT_VAR} "${OUTPUT_FILE}") set(${OUTPUT_VAR} "${${OUTPUT_VAR}}" PARENT_SCOPE)