edit
This commit is contained in:
499
XLAB2/tools/GenerateXlabAppIcon.ps1
Normal file
499
XLAB2/tools/GenerateXlabAppIcon.ps1
Normal file
@@ -0,0 +1,499 @@
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
|
||||
function New-RoundedRectPath {
|
||||
param(
|
||||
[System.Drawing.RectangleF] $Rect,
|
||||
[float] $Radius
|
||||
)
|
||||
|
||||
$diameter = $Radius * 2.0
|
||||
$path = New-Object System.Drawing.Drawing2D.GraphicsPath
|
||||
|
||||
if ($diameter -le 0.0) {
|
||||
$path.AddRectangle($Rect)
|
||||
return $path
|
||||
}
|
||||
|
||||
$path.AddArc($Rect.X, $Rect.Y, $diameter, $diameter, 180, 90)
|
||||
$path.AddArc($Rect.Right - $diameter, $Rect.Y, $diameter, $diameter, 270, 90)
|
||||
$path.AddArc($Rect.Right - $diameter, $Rect.Bottom - $diameter, $diameter, $diameter, 0, 90)
|
||||
$path.AddArc($Rect.X, $Rect.Bottom - $diameter, $diameter, $diameter, 90, 90)
|
||||
$path.CloseFigure()
|
||||
return $path
|
||||
}
|
||||
|
||||
function New-Color {
|
||||
param(
|
||||
[int] $A,
|
||||
[int] $R,
|
||||
[int] $G,
|
||||
[int] $B
|
||||
)
|
||||
|
||||
return [System.Drawing.Color]::FromArgb($A, $R, $G, $B)
|
||||
}
|
||||
|
||||
function Add-ShadowRoundedRect {
|
||||
param(
|
||||
[System.Drawing.Graphics] $Graphics,
|
||||
[System.Drawing.RectangleF] $Rect,
|
||||
[float] $Radius,
|
||||
[int] $Layers,
|
||||
[float] $OffsetX,
|
||||
[float] $OffsetY
|
||||
)
|
||||
|
||||
for ($layer = $Layers; $layer -ge 1; $layer--) {
|
||||
$inflate = [float]($layer * 2.2)
|
||||
$shadowRect = [System.Drawing.RectangleF]::new(
|
||||
$Rect.X + $OffsetX - ($inflate / 2.0),
|
||||
$Rect.Y + $OffsetY - ($inflate / 2.0),
|
||||
$Rect.Width + $inflate,
|
||||
$Rect.Height + $inflate)
|
||||
$shadowPath = New-RoundedRectPath -Rect $shadowRect -Radius ($Radius + ($inflate / 3.5))
|
||||
try {
|
||||
$alpha = [Math]::Min(80, [int](5 + ($layer * 2.8)))
|
||||
$brush = New-Object System.Drawing.SolidBrush (New-Color -A $alpha -R 0 -G 0 -B 0)
|
||||
try {
|
||||
$Graphics.FillPath($brush, $shadowPath)
|
||||
}
|
||||
finally {
|
||||
$brush.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$shadowPath.Dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Add-ShadowEllipse {
|
||||
param(
|
||||
[System.Drawing.Graphics] $Graphics,
|
||||
[System.Drawing.RectangleF] $Rect,
|
||||
[int] $Layers,
|
||||
[float] $OffsetX,
|
||||
[float] $OffsetY
|
||||
)
|
||||
|
||||
for ($layer = $Layers; $layer -ge 1; $layer--) {
|
||||
$inflate = [float]($layer * 1.8)
|
||||
$alpha = [Math]::Min(65, [int](4 + ($layer * 2.0)))
|
||||
$brush = New-Object System.Drawing.SolidBrush (New-Color -A $alpha -R 0 -G 0 -B 0)
|
||||
try {
|
||||
$Graphics.FillEllipse(
|
||||
$brush,
|
||||
$Rect.X + $OffsetX - ($inflate / 2.0),
|
||||
$Rect.Y + $OffsetY - ($inflate / 2.0),
|
||||
$Rect.Width + $inflate,
|
||||
$Rect.Height + $inflate)
|
||||
}
|
||||
finally {
|
||||
$brush.Dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Draw-Line {
|
||||
param(
|
||||
[System.Drawing.Graphics] $Graphics,
|
||||
[System.Drawing.Color] $Color,
|
||||
[float] $Width,
|
||||
[float] $X1,
|
||||
[float] $Y1,
|
||||
[float] $X2,
|
||||
[float] $Y2,
|
||||
[System.Drawing.Drawing2D.LineCap] $StartCap = [System.Drawing.Drawing2D.LineCap]::Round,
|
||||
[System.Drawing.Drawing2D.LineCap] $EndCap = [System.Drawing.Drawing2D.LineCap]::Round
|
||||
)
|
||||
|
||||
$pen = New-Object System.Drawing.Pen($Color, $Width)
|
||||
try {
|
||||
$pen.StartCap = $StartCap
|
||||
$pen.EndCap = $EndCap
|
||||
$Graphics.DrawLine($pen, $X1, $Y1, $X2, $Y2)
|
||||
}
|
||||
finally {
|
||||
$pen.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
function Save-MultiSizeIcon {
|
||||
param(
|
||||
[System.Drawing.Bitmap] $MasterBitmap,
|
||||
[string] $OutputPath,
|
||||
[int[]] $Sizes
|
||||
)
|
||||
|
||||
$tempFiles = New-Object System.Collections.Generic.List[string]
|
||||
try {
|
||||
foreach ($size in $Sizes) {
|
||||
$scaled = New-Object System.Drawing.Bitmap($size, $size)
|
||||
try {
|
||||
$graphics = [System.Drawing.Graphics]::FromImage($scaled)
|
||||
try {
|
||||
$graphics.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality
|
||||
$graphics.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
|
||||
$graphics.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality
|
||||
$graphics.CompositingQuality = [System.Drawing.Drawing2D.CompositingQuality]::HighQuality
|
||||
$graphics.Clear([System.Drawing.Color]::Transparent)
|
||||
$graphics.DrawImage($MasterBitmap, 0, 0, $size, $size)
|
||||
}
|
||||
finally {
|
||||
$graphics.Dispose()
|
||||
}
|
||||
|
||||
$tempFile = [System.IO.Path]::ChangeExtension([System.IO.Path]::GetTempFileName(), '.png')
|
||||
$scaled.Save($tempFile, [System.Drawing.Imaging.ImageFormat]::Png)
|
||||
$tempFiles.Add($tempFile)
|
||||
}
|
||||
finally {
|
||||
$scaled.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
$stream = [System.IO.File]::Create($OutputPath)
|
||||
try {
|
||||
$writer = New-Object System.IO.BinaryWriter($stream)
|
||||
try {
|
||||
$writer.Write([UInt16]0)
|
||||
$writer.Write([UInt16]1)
|
||||
$writer.Write([UInt16]$Sizes.Length)
|
||||
|
||||
$dataOffset = 6 + (16 * $Sizes.Length)
|
||||
$imageBlobs = @()
|
||||
for ($index = 0; $index -lt $Sizes.Length; $index++) {
|
||||
$size = $Sizes[$index]
|
||||
$pngBytes = [System.IO.File]::ReadAllBytes($tempFiles[$index])
|
||||
$imageBlobs += ,$pngBytes
|
||||
|
||||
$writer.Write([byte]($(if ($size -ge 256) { 0 } else { $size })))
|
||||
$writer.Write([byte]($(if ($size -ge 256) { 0 } else { $size })))
|
||||
$writer.Write([byte]0)
|
||||
$writer.Write([byte]0)
|
||||
$writer.Write([UInt16]1)
|
||||
$writer.Write([UInt16]32)
|
||||
$writer.Write([UInt32]$pngBytes.Length)
|
||||
$writer.Write([UInt32]$dataOffset)
|
||||
$dataOffset += $pngBytes.Length
|
||||
}
|
||||
|
||||
foreach ($blob in $imageBlobs) {
|
||||
$writer.Write($blob)
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$writer.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$stream.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
foreach ($tempFile in $tempFiles) {
|
||||
if ([System.IO.File]::Exists($tempFile)) {
|
||||
Remove-Item $tempFile -Force
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$root = Split-Path -Parent $PSScriptRoot
|
||||
$assetsDir = Join-Path $root 'Assets'
|
||||
$previewPath = Join-Path $assetsDir 'XlabAppIconPreview.png'
|
||||
$iconPath = Join-Path $assetsDir 'XlabApp.ico'
|
||||
|
||||
$size = 1024
|
||||
$bitmap = New-Object System.Drawing.Bitmap($size, $size)
|
||||
try {
|
||||
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
|
||||
try {
|
||||
$graphics.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias
|
||||
$graphics.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
|
||||
$graphics.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality
|
||||
$graphics.CompositingQuality = [System.Drawing.Drawing2D.CompositingQuality]::HighQuality
|
||||
$graphics.Clear([System.Drawing.Color]::Transparent)
|
||||
|
||||
$tileRect = [System.Drawing.RectangleF]::new(86, 86, 852, 852)
|
||||
$tileRadius = 194.0
|
||||
Add-ShadowRoundedRect -Graphics $graphics -Rect $tileRect -Radius $tileRadius -Layers 14 -OffsetX 8 -OffsetY 18
|
||||
|
||||
$tilePath = New-RoundedRectPath -Rect $tileRect -Radius $tileRadius
|
||||
try {
|
||||
$tileBrush = New-Object System.Drawing.Drawing2D.LinearGradientBrush(
|
||||
$tileRect,
|
||||
(New-Color -A 255 -R 12 -G 28 -B 52),
|
||||
(New-Color -A 255 -R 20 -G 96 -B 132),
|
||||
48.0)
|
||||
try {
|
||||
$graphics.FillPath($tileBrush, $tilePath)
|
||||
}
|
||||
finally {
|
||||
$tileBrush.Dispose()
|
||||
}
|
||||
|
||||
$glowEllipse = New-Object System.Drawing.Drawing2D.GraphicsPath
|
||||
try {
|
||||
$glowEllipse.AddEllipse([System.Drawing.RectangleF]::new(198, 154, 486, 350))
|
||||
$glowBrush = New-Object System.Drawing.Drawing2D.PathGradientBrush($glowEllipse)
|
||||
try {
|
||||
$glowBrush.CenterColor = New-Color -A 90 -R 255 -G 255 -B 255
|
||||
$glowBrush.SurroundColors = @((New-Color -A 0 -R 255 -G 255 -B 255))
|
||||
$graphics.FillPath($glowBrush, $glowEllipse)
|
||||
}
|
||||
finally {
|
||||
$glowBrush.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$glowEllipse.Dispose()
|
||||
}
|
||||
|
||||
$radialCore = New-Object System.Drawing.Drawing2D.GraphicsPath
|
||||
try {
|
||||
$radialCore.AddEllipse([System.Drawing.RectangleF]::new(232, 232, 560, 560))
|
||||
$radialBrush = New-Object System.Drawing.Drawing2D.PathGradientBrush($radialCore)
|
||||
try {
|
||||
$radialBrush.CenterColor = New-Color -A 64 -R 68 -G 226 -B 255
|
||||
$radialBrush.SurroundColors = @((New-Color -A 0 -R 68 -G 226 -B 255))
|
||||
$graphics.FillPath($radialBrush, $radialCore)
|
||||
}
|
||||
finally {
|
||||
$radialBrush.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$radialCore.Dispose()
|
||||
}
|
||||
|
||||
$rimPen = New-Object System.Drawing.Pen((New-Color -A 80 -R 98 -G 219 -B 255), 8.0)
|
||||
try {
|
||||
$graphics.DrawPath($rimPen, $tilePath)
|
||||
}
|
||||
finally {
|
||||
$rimPen.Dispose()
|
||||
}
|
||||
|
||||
$innerPath = New-RoundedRectPath -Rect ([System.Drawing.RectangleF]::new(116, 116, 792, 792)) -Radius 170.0
|
||||
try {
|
||||
$innerPen = New-Object System.Drawing.Pen((New-Color -A 42 -R 255 -G 255 -B 255), 3.0)
|
||||
try {
|
||||
$graphics.DrawPath($innerPen, $innerPath)
|
||||
}
|
||||
finally {
|
||||
$innerPen.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$innerPath.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$tilePath.Dispose()
|
||||
}
|
||||
|
||||
$orbitRect = [System.Drawing.RectangleF]::new(250, 252, 524, 524)
|
||||
$orbitShadowPen = New-Object System.Drawing.Pen((New-Color -A 42 -R 0 -G 0 -B 0), 18.0)
|
||||
try {
|
||||
$graphics.DrawEllipse($orbitShadowPen, 268, 272, 524, 524)
|
||||
}
|
||||
finally {
|
||||
$orbitShadowPen.Dispose()
|
||||
}
|
||||
|
||||
$orbitPen = New-Object System.Drawing.Pen((New-Color -A 76 -R 206 -G 241 -B 255), 14.0)
|
||||
try {
|
||||
$graphics.DrawEllipse($orbitPen, $orbitRect)
|
||||
}
|
||||
finally {
|
||||
$orbitPen.Dispose()
|
||||
}
|
||||
|
||||
$center = 512.0
|
||||
$bladeRect = [System.Drawing.RectangleF]::new(-64, -286, 128, 356)
|
||||
$bladeRadius = 64.0
|
||||
|
||||
$bladeDefinitions = @(
|
||||
@{ Angle = -18.0; Start = (New-Color -A 255 -R 88 -G 240 -B 255); End = (New-Color -A 255 -R 28 -G 144 -B 218); Highlight = (New-Color -A 120 -R 255 -G 255 -B 255) },
|
||||
@{ Angle = 102.0; Start = (New-Color -A 255 -R 109 -G 246 -B 198); End = (New-Color -A 255 -R 30 -G 179 -B 133); Highlight = (New-Color -A 110 -R 244 -G 255 -B 250) },
|
||||
@{ Angle = 222.0; Start = (New-Color -A 255 -R 255 -G 190 -B 98); End = (New-Color -A 255 -R 240 -G 120 -B 52); Highlight = (New-Color -A 100 -R 255 -G 242 -B 218) }
|
||||
)
|
||||
|
||||
foreach ($blade in $bladeDefinitions) {
|
||||
$shadowState = $graphics.Save()
|
||||
try {
|
||||
$graphics.TranslateTransform($center + 14.0, $center + 18.0)
|
||||
$graphics.RotateTransform([float]$blade.Angle)
|
||||
$shadowPath = New-RoundedRectPath -Rect $bladeRect -Radius $bladeRadius
|
||||
try {
|
||||
$shadowBrush = New-Object System.Drawing.SolidBrush (New-Color -A 72 -R 0 -G 0 -B 0)
|
||||
try {
|
||||
$graphics.FillPath($shadowBrush, $shadowPath)
|
||||
}
|
||||
finally {
|
||||
$shadowBrush.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$shadowPath.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$graphics.Restore($shadowState)
|
||||
}
|
||||
|
||||
$state = $graphics.Save()
|
||||
try {
|
||||
$graphics.TranslateTransform($center, $center)
|
||||
$graphics.RotateTransform([float]$blade.Angle)
|
||||
|
||||
$path = New-RoundedRectPath -Rect $bladeRect -Radius $bladeRadius
|
||||
try {
|
||||
$bladeBrush = New-Object System.Drawing.Drawing2D.LinearGradientBrush(
|
||||
$bladeRect,
|
||||
$blade.Start,
|
||||
$blade.End,
|
||||
90.0)
|
||||
try {
|
||||
$graphics.FillPath($bladeBrush, $path)
|
||||
}
|
||||
finally {
|
||||
$bladeBrush.Dispose()
|
||||
}
|
||||
|
||||
$shinePath = New-RoundedRectPath -Rect ([System.Drawing.RectangleF]::new(-44, -270, 34, 316)) -Radius 18.0
|
||||
try {
|
||||
$shineBrush = New-Object System.Drawing.Drawing2D.LinearGradientBrush(
|
||||
([System.Drawing.RectangleF]::new(-44, -270, 34, 316)),
|
||||
$blade.Highlight,
|
||||
(New-Color -A 0 -R 255 -G 255 -B 255),
|
||||
90.0)
|
||||
try {
|
||||
$graphics.FillPath($shineBrush, $shinePath)
|
||||
}
|
||||
finally {
|
||||
$shineBrush.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$shinePath.Dispose()
|
||||
}
|
||||
|
||||
$edgePen = New-Object System.Drawing.Pen((New-Color -A 86 -R 255 -G 255 -B 255), 4.0)
|
||||
try {
|
||||
$graphics.DrawPath($edgePen, $path)
|
||||
}
|
||||
finally {
|
||||
$edgePen.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$path.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$graphics.Restore($state)
|
||||
}
|
||||
}
|
||||
|
||||
$innerShadowBrush = New-Object System.Drawing.SolidBrush (New-Color -A 70 -R 0 -G 0 -B 0)
|
||||
try {
|
||||
$graphics.FillEllipse($innerShadowBrush, 404, 406, 216, 216)
|
||||
}
|
||||
finally {
|
||||
$innerShadowBrush.Dispose()
|
||||
}
|
||||
|
||||
$innerRingRect = [System.Drawing.RectangleF]::new(394, 392, 216, 216)
|
||||
$innerRingBrush = New-Object System.Drawing.Drawing2D.LinearGradientBrush(
|
||||
$innerRingRect,
|
||||
(New-Color -A 255 -R 250 -G 252 -B 255),
|
||||
(New-Color -A 255 -R 204 -G 214 -B 226),
|
||||
125.0)
|
||||
try {
|
||||
$graphics.FillEllipse($innerRingBrush, $innerRingRect)
|
||||
}
|
||||
finally {
|
||||
$innerRingBrush.Dispose()
|
||||
}
|
||||
|
||||
$innerCorePath = New-Object System.Drawing.Drawing2D.GraphicsPath
|
||||
try {
|
||||
$innerCorePath.AddEllipse([System.Drawing.RectangleF]::new(428, 426, 148, 148))
|
||||
$innerCoreBrush = New-Object System.Drawing.Drawing2D.PathGradientBrush($innerCorePath)
|
||||
try {
|
||||
$innerCoreBrush.CenterColor = New-Color -A 255 -R 14 -G 46 -B 82
|
||||
$innerCoreBrush.SurroundColors = @((New-Color -A 255 -R 25 -G 93 -B 138))
|
||||
$graphics.FillPath($innerCoreBrush, $innerCorePath)
|
||||
}
|
||||
finally {
|
||||
$innerCoreBrush.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$innerCorePath.Dispose()
|
||||
}
|
||||
|
||||
$coreGlowPath = New-Object System.Drawing.Drawing2D.GraphicsPath
|
||||
try {
|
||||
$coreGlowPath.AddEllipse([System.Drawing.RectangleF]::new(444, 442, 116, 116))
|
||||
$coreGlowBrush = New-Object System.Drawing.Drawing2D.PathGradientBrush($coreGlowPath)
|
||||
try {
|
||||
$coreGlowBrush.CenterColor = New-Color -A 255 -R 92 -G 227 -B 255
|
||||
$coreGlowBrush.SurroundColors = @((New-Color -A 0 -R 92 -G 227 -B 255))
|
||||
$graphics.FillPath($coreGlowBrush, $coreGlowPath)
|
||||
}
|
||||
finally {
|
||||
$coreGlowBrush.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$coreGlowPath.Dispose()
|
||||
}
|
||||
|
||||
$coreRingPen = New-Object System.Drawing.Pen((New-Color -A 112 -R 255 -G 255 -B 255), 6.0)
|
||||
try {
|
||||
$graphics.DrawEllipse($coreRingPen, $innerRingRect)
|
||||
}
|
||||
finally {
|
||||
$coreRingPen.Dispose()
|
||||
}
|
||||
|
||||
$sparkPath = New-Object System.Drawing.Drawing2D.GraphicsPath
|
||||
try {
|
||||
$sparkPath.AddEllipse([System.Drawing.RectangleF]::new(672, 248, 74, 74))
|
||||
$sparkBrush = New-Object System.Drawing.Drawing2D.PathGradientBrush($sparkPath)
|
||||
try {
|
||||
$sparkBrush.CenterColor = New-Color -A 190 -R 255 -G 255 -B 255
|
||||
$sparkBrush.SurroundColors = @((New-Color -A 0 -R 255 -G 255 -B 255))
|
||||
$graphics.FillPath($sparkBrush, $sparkPath)
|
||||
}
|
||||
finally {
|
||||
$sparkBrush.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$sparkPath.Dispose()
|
||||
}
|
||||
|
||||
Draw-Line -Graphics $graphics -Color (New-Color -A 86 -R 255 -G 255 -B 255) -Width 10.0 -X1 708.0 -Y1 216.0 -X2 708.0 -Y2 282.0
|
||||
Draw-Line -Graphics $graphics -Color (New-Color -A 86 -R 255 -G 255 -B 255) -Width 10.0 -X1 675.0 -Y1 249.0 -X2 741.0 -Y2 249.0
|
||||
|
||||
$bitmap.Save($previewPath, [System.Drawing.Imaging.ImageFormat]::Png)
|
||||
Save-MultiSizeIcon -MasterBitmap $bitmap -OutputPath $iconPath -Sizes @(16, 24, 32, 48, 64, 128, 256)
|
||||
}
|
||||
finally {
|
||||
$graphics.Dispose()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$bitmap.Dispose()
|
||||
}
|
||||
|
||||
Write-Host "Generated:"
|
||||
Write-Host " $previewPath"
|
||||
Write-Host " $iconPath"
|
||||
Reference in New Issue
Block a user