diff --git a/tools/render-refs.ps1 b/tools/render-refs.ps1 new file mode 100644 index 0000000..41fe9a1 --- /dev/null +++ b/tools/render-refs.ps1 @@ -0,0 +1,51 @@ +param( + [string]$OutDir = "tools/out" +) + +$ErrorActionPreference = "Stop" + +$candidates = @( + "${env:ProgramFiles(x86)}\Microsoft\Edge\Application\msedge.exe", + "$env:ProgramFiles\Microsoft\Edge\Application\msedge.exe", + "${env:ProgramFiles}\Google\Chrome\Application\chrome.exe", + "${env:ProgramFiles(x86)}\Google\Chrome\Application\chrome.exe" +) +$browser = $candidates | Where-Object { Test-Path $_ } | Select-Object -First 1 +if (-not $browser) { + Write-Error "msedge.exe / chrome.exe not found in standard locations" + exit 1 +} + +New-Item -ItemType Directory -Force -Path $OutDir | Out-Null + +$refs = @( + @{ Html = "refs/dark.html"; Png = "ref-dark.png" }, + @{ Html = "refs/light.html"; Png = "ref-light.png" } +) + +foreach ($ref in $refs) { + $outAbs = [System.IO.Path]::GetFullPath((Join-Path $OutDir $ref.Png)) + $uri = ([System.Uri]([System.IO.Path]::GetFullPath($ref.Html))).AbsoluteUri + + foreach ($mode in @("--headless=new", "--headless")) { + $args = @( + $mode, + "--disable-gpu", + "--hide-scrollbars", + "--no-first-run", + "--user-data-dir=$env:TEMP\bp-headless-profile", + "--window-size=488,800", + "--screenshot=`"$outAbs`"", + $uri + ) + Start-Process -FilePath $browser -ArgumentList $args -Wait | Out-Null + if (Test-Path $outAbs) { break } + } + + if (Test-Path $outAbs) { + Write-Host "OK $($ref.Png)" + } else { + Write-Error "failed to render $($ref.Html)" + exit 1 + } +} diff --git a/tools/run-and-shot.ps1 b/tools/run-and-shot.ps1 new file mode 100644 index 0000000..88486d0 --- /dev/null +++ b/tools/run-and-shot.ps1 @@ -0,0 +1,27 @@ +param( + [string]$Out = "tools/out/app.png", + [switch]$NoBuild +) + +$ErrorActionPreference = "Stop" + +if (-not $NoBuild) { + cargo build + if ($LASTEXITCODE -ne 0) { exit 1 } +} + +$exe = Join-Path $PWD "target\debug\bropicker.exe" +if (-not (Test-Path $exe)) { + Write-Error "bropicker.exe not found, build first" + exit 1 +} + +$proc = Start-Process -FilePath $exe -WorkingDirectory $PWD -PassThru +Start-Sleep -Milliseconds 1800 + +& "$PSScriptRoot\shot.ps1" -ProcId $proc.Id -Out $Out +$shotOk = ($LASTEXITCODE -eq 0) + +Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue + +if (-not $shotOk) { exit 1 } diff --git a/tools/shot.ps1 b/tools/shot.ps1 new file mode 100644 index 0000000..6c1f0d2 --- /dev/null +++ b/tools/shot.ps1 @@ -0,0 +1,71 @@ +param( + [string]$ProcName = "bropicker", + [int]$ProcId = 0, + [string]$Out = "tools/out/app.png" +) + +$ErrorActionPreference = "Stop" + +Add-Type @" +using System; +using System.Runtime.InteropServices; +public class BpWin { + public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); + [DllImport("user32.dll")] public static extern bool SetProcessDPIAware(); + [DllImport("user32.dll")] public static extern bool EnumWindows(EnumWindowsProc cb, IntPtr lParam); + [DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint pid); + [DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr hWnd); + [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT rect); + [StructLayout(LayoutKind.Sequential)] + public struct RECT { public int Left; public int Top; public int Right; public int Bottom; } +} +"@ + +[BpWin]::SetProcessDPIAware() | Out-Null + +if ($ProcId -eq 0) { + $proc = Get-Process -Name $ProcName -ErrorAction Stop | Select-Object -First 1 + $ProcId = $proc.Id +} + +$found = [IntPtr]::Zero +$callback = [BpWin+EnumWindowsProc]{ + param($hWnd, $lParam) + $winPid = 0 + [BpWin]::GetWindowThreadProcessId($hWnd, [ref]$winPid) | Out-Null + if ($winPid -eq $ProcId -and [BpWin]::IsWindowVisible($hWnd)) { + $script:found = $hWnd + return $false + } + return $true +} +[BpWin]::EnumWindows($callback, [IntPtr]::Zero) | Out-Null + +if ($found -eq [IntPtr]::Zero) { + Write-Error "visible window for process $ProcId not found" + exit 1 +} + +$rect = New-Object BpWin+RECT +[BpWin]::GetWindowRect($found, [ref]$rect) | Out-Null +$w = $rect.Right - $rect.Left +$h = $rect.Bottom - $rect.Top + +if ($w -le 0 -or $h -le 0) { + Write-Error "invalid window size ${w}x${h}" + exit 1 +} + +Add-Type -AssemblyName System.Drawing +$bmp = New-Object System.Drawing.Bitmap($w, $h) +$g = [System.Drawing.Graphics]::FromImage($bmp) +$g.CopyFromScreen($rect.Left, $rect.Top, 0, 0, (New-Object System.Drawing.Size($w, $h))) +$g.Dispose() + +$outDir = Split-Path -Parent (Join-Path $PWD $Out) +New-Item -ItemType Directory -Force -Path $outDir | Out-Null +$outAbs = [System.IO.Path]::GetFullPath((Join-Path $PWD $Out)) +$bmp.Save($outAbs, [System.Drawing.Imaging.ImageFormat]::Png) +$bmp.Dispose() + +Write-Host "OK $OutAbs (${w}x${h})"