Files

61 lines
3.3 KiB
PowerShell

$ErrorActionPreference = 'Stop'
# Big-endian readers. NOTE: must cast to [int] first - [byte] -shl wraps in PS 5.1.
function R16([byte[]]$b, [int]$p) { return [int]($b[$p]) -shl 8 -bor [int]$b[$p+1] }
function R32([byte[]]$b, [int]$p) { return ([int]$b[$p] -shl 24) -bor ([int]$b[$p+1] -shl 16) -bor ([int]$b[$p+2] -shl 8) -bor [int]$b[$p+3] }
# Correct OTF/TTF name-table parser (table-record offset field is at +8)
function Get-FontNames([string]$path) {
$bytes = [IO.File]::ReadAllBytes($path)
# header: major(2) minor(2) numTables(2) searchedNum(2) rangeShift(2) = 12 bytes
$numTables = R16 $bytes 4
$pos = 12
$nameOff = -1
for ($i = 0; $i -lt $numTables; $i++) {
$rec = $pos + $i * 16
$tag = [Text.Encoding]::ASCII.GetString($bytes, $rec, 4)
if ($tag -eq 'name') { $nameOff = R32 $bytes ($rec + 8) }
}
if ($nameOff -lt 0) { Write-Output ((Split-Path $path -Leaf) + " : NO name TABLE"); return }
$base = $nameOff
$count = R16 $bytes ($base + 2)
# stringOffset: spec says 32-bit, but some builds (incl. some LM releases) store 16-bit.
# A valid value must point at/after the end of the record block (base + 6 + count*12).
$recordsEnd = 6 + $count * 12
$strOff32 = R32 $bytes ($base + 4)
if ($strOff32 -ge $recordsEnd -and ($base + $strOff32) -le $bytes.Length) { $strOff = $strOff32 } else { $strOff = R16 $bytes ($base + 4) }
$strBase = $base + $strOff
$res = @{}
$macRes = @{}
for ($i = 0; $i -lt $count; $i++) {
$r = $base + 6 + $i * 12
$plat = R16 $bytes $r
$lang = R16 $bytes ($r + 4)
$id = R16 $bytes ($r + 6)
$len = R16 $bytes ($r + 8)
$off = R16 $bytes ($r + 10)
if ($len -eq 0 -or ($strBase + $off + $len) -gt $bytes.Length) { continue }
$bytes2 = New-Object byte[] $len
[Array]::Copy($bytes, $strBase + $off, $bytes2, 0, $len)
if ($plat -eq 3 -and $lang -eq 0x0409) {
if (-not $res.ContainsKey("n$id")) { $res["n$id"] = [Text.Encoding]::Unicode.GetString($bytes2) }
} elseif ($plat -eq 1) {
if (-not $macRes.ContainsKey("n$id")) { $macRes["n$id"] = [Text.Encoding]::ASCII.GetString($bytes2) }
}
}
$pick = { param($id) if ($res.ContainsKey("n$id")) { $res["n$id"] } elseif ($macRes.ContainsKey("n$id")) { $macRes["n$id"] } else { '' } }
$fam = & $pick 16; if (-not $fam) { $fam = & $pick 1 }
$sub = & $pick 17; if (-not $sub) { $sub = & $pick 2 }
Write-Output ("{0,-28} family = {1} | subfamily = {2}" -f (Split-Path $path -Leaf), $fam, $sub)
}
$lmDir = "c:\Users\fdavalos\OneDrive - up.edu.mx\microtracking\MicrotrackingFer\tools\fonts\lm\fonts\opentype\public\lm"
Write-Output '=== Local LM samples (family used by fontconfig) ==='
foreach ($f in @('lmroman10-regular.otf','lmsans10-regular.otf','lmmono10-regular.otf','lmmonolt10-regular.otf')) {
$p = Join-Path $lmDir $f
if (Test-Path $p) { Get-FontNames $p } else { Write-Output "$f : MISSING" }
}
Write-Output ''
Write-Output '=== Windows fonts (ptm / phv candidates) ==='
foreach ($f in @('times.ttf','timesbd.ttf','timesi.ttf','timesbi.ttf','arial.ttf','arialbd.ttf','ariali.ttf','arialbi.ttf')) {
$p = Join-Path $env:windir "Fonts\$f"
if (Test-Path $p) { Get-FontNames $p } else { Write-Output "$f : MISSING" }
}