$ErrorActionPreference = 'Stop' $root = "c:\Users\fdavalos\OneDrive - up.edu.mx\microtracking\MicrotrackingFer" function BE16($b, $o) { ($b[$o] -shl 8) + $b[$o+1] } function BE32($b, $o) { ($b[$o] -shl 24) + ($b[$o+1] -shl 16) + ($b[$o+2] -shl 8) + $b[$o+3] } function Get-NameTable($path) { $bytes = [IO.File]::ReadAllBytes($path) $out = [PSCustomObject]@{ File = (Split-Path $path -Leaf); Size = $bytes.Length; NumTables='?'; NameOff='?'; Count='?'; Records='?' ; Family='?'; Subfamily='?'; TyposFamily='?'; TyposSubfamily='?' } if ($bytes.Length -lt 16) { $out.NumTables = 'toosmall'; return $out } $num = BE16 $bytes 4 $out.NumTables = $num $off = 12 $nameOff = -1 if ($num -gt 64) { $num = 64 } for ($i=0; $i -lt $num; $i++) { if ([Text.Encoding]::ASCII.GetString($bytes, $off, 4) -eq 'name') { $nameOff = BE32 $bytes ($off+10) } $off += 16 } $out.NameOff = $nameOff if ($nameOff -lt 0) { $out.Count = 'none'; return $out } $count = BE16 $bytes ($nameOff+2) $strOff = BE16 $bytes ($nameOff+4) $base = $nameOff + $strOff $out.Count = $count $out.Records = "base=$base, strOff=$strOff, size=$($bytes.Length)" $res = @{} $roff = $nameOff + 6 $shown = @() for ($i=0; $i -lt $count; $i++) { if ($roff + 12 -gt $bytes.Length) { break } $pid_ = BE16 $bytes $roff $eid = BE16 $bytes ($roff+2) $lid = BE16 $bytes ($roff+4) $nid = BE16 $bytes ($roff+6) $len = BE16 $bytes ($roff+8) $soff = BE16 $bytes ($roff+10) if ($i -lt 12) { $shown += ("p=$pid_ e=$eid l=$lid n=$nid len=$len off=$soff") } if ($pid_ -eq 3 -and $lid -eq 0x0409 -and $len -gt 0 -and ($base+$soff+$len) -le $bytes.Length) { $s = [Text.Encoding]::Unicode.GetString($bytes, $base+$soff, $len) $key = switch ($nid) { 1 {'Family'} 2 {'Subfamily'} 16 {'TyposFamily'} 17 {'TyposSubfamily'} default { $null } } if ($key -and -not $res.ContainsKey($key)) { $res[$key] = $s } } $roff += 12 } $out.FirstRecords = ($shown -join ' | ') foreach ($k in $res.Keys) { if ($out.$k -eq '?') { $out.$k = $res[$k] } } $out } $otfDir = "$root\tools\fonts\lm\fonts\opentype\public\lm" Write-Output '=== [1] debug: first records of 4 key OTFs ===' @('lmroman10-regular.otf','lmroman10-italic.otf','lmroman10-bold.otf','lmmath.otf') | ForEach-Object { $p = Join-Path $otfDir $_ if (Test-Path $p) { Get-NameTable $p | Format-List | Out-String -Width 200 | Write-Output } else { Write-Output ("{0} : NOT PRESENT" -f $_) } } Write-Output '=== [2] all OTFs present (families) ===' Get-ChildItem $otfDir -Filter *.otf | ForEach-Object { $r = Get-NameTable $_.FullName "{0,-28} family='{1}' sub='{2}'" -f $_.Name, $r.Family, $r.Subfamily } | Group-Object | Sort-Object Name | ForEach-Object { "$($_.Name) (x$($_.Count))" } Write-Output '' '' Write-Output '=== [3] elsarticle / times font requirements in repo ===' Get-ChildItem $root -Include *.cls,*.sty -Recurse -ErrorAction SilentlyContinue | Where-Object { $_.Name -match 'elsarticle|times' } | Select-Object -ExpandProperty FullName Get-ChildItem $root -Include elsarticle*.cls -Recurse -ErrorAction SilentlyContinue | Select-String -Pattern 'rmdefault|sfdefault|ttdefault|mathfont|fontenc|usepackage' | Select-Object -First 30 @{n='Ref';e={$(Split-Path $_.Path -Leaf)+':'+$_.LineNumber}}, @{n='Text';e={$t=$_.Line.Trim(); if($t.Length -gt 100){$t.Substring(0,100)}else{$t}}} | Format-Table -AutoSize | Out-String -Width 190 | Write-Output Write-Output '=== [4] bundle/font top structure ===' Get-ChildItem (Join-Path $root 'tools\tectonic-src\bundle') -Depth 3 -ErrorAction SilentlyContinue | Select-Object @{n='Rel';e={$_.FullName.Substring($root.Length+1)}}, PSIsContainer, Length | Where-Object { -not $_.PSIsContainer -or ($_.Length -and $_.Length -gt 0) } | Select-Object -First 50 Rel, PSIsContainer, Length | Format-Table -AutoSize | Out-String -Width 180 | Write-Output function BE16($b, $o) { ($b[$o] -shl 8) + $b[$o+1] } function BE32($b, $o) { ($b[$o] -shl 24) + ($b[$o+1] -shl 16) + ($b[$o+2] -shl 8) + $b[$o+3] } Write-Output '=== [A] repo-wide: anything referencing texlive-fontconfig / FONTCONFIG (unique files) ===' Get-ChildItem $srcDir -Recurse -File | Select-String -Pattern 'texlive-fontconfig|FONTCONFIG' | Select-Object -ExpandProperty Path | Sort-Object -Unique | ForEach-Object { $_.Substring($srcDir.Length+1) } Write-Output '' Write-Output '=== [B] main src/: env manipulation (unique) ===' Get-ChildItem (Join-Path $srcDir 'src') -Recurse -Include *.rs -File | Select-String -Pattern 'remove_var|set_var|getenv|FONTCONFIG' | Select-Object -Unique @{n='Ref';e={$($_.Path.Substring($srcDir.Length+1)) + ':' + $_.LineNumber}}, @{n='Text';e={$t=$_.Line.Trim(); if($t.Length -gt 120){$t.Substring(0,120)}else{$t}}} | Format-Table -AutoSize | Out-String -Width 200 | Write-Output Write-Output '=== [C] tools/fonts: OTF/TTF count + first 25 ===' $fontsDir = Join-Path $root 'tools\fonts' $otfs = Get-ChildItem $fontsDir -Recurse -Include *.otf,*.ttf -File "Count: $($otfs.Count)" $otfs | Select-Object -First 25 @{n='Rel';e={$_.FullName.Substring($fontsDir.Length+1)}}, Length | Format-Table -AutoSize | Out-String -Width 200 | Write-Output Write-Output '=== [D] unique family / subfamily from OTF name tables ===' $rows = @() foreach ($f in $otfs) { $bytes = [IO.File]::ReadAllBytes($f.FullName) if ($bytes.Length -lt 16) { continue } $num = BE16 $bytes 4 $nameOff = -1 $off = 12 for ($i=0; $i -lt $num; $i++) { if ([Text.Encoding]::ASCII.GetString($bytes, $off, 4) -eq 'name') { $nameOff = BE32 $bytes ($off+10) } $off += 16 } if ($nameOff -lt 0) { continue } $count = BE16 $bytes ($nameOff+2) $base = $nameOff + (BE16 $bytes ($nameOff+4)) $res = @{} $roff = $nameOff + 6 for ($i=0; $i -lt $count; $i++) { $pid_ = BE16 $bytes $roff $lid = BE16 $bytes ($roff+4) $nid = BE16 $bytes ($roff+6) $len = BE16 $bytes ($roff+8) $soff = BE16 $bytes ($roff+10) $roff += 12 if ($pid_ -eq 3 -and $lid -eq 0x0409 -and $len -gt 0 -and $base+$soff+$len -le $bytes.Length) { $s = [Text.Encoding]::Unicode.GetString($bytes, $base+$soff, $len) $key = switch ($nid) { 1 {'family'} 2 {'subfamily'} 16 {'typosFamily'} 17 {'typosSubfamily'} default { $null } } if ($key -and -not $res.ContainsKey($key)) { $res[$key] = $s } } } if ($res.ContainsKey('family')) { $rows += [PSCustomObject]@{ Family = $res['family']; Subfamily = $res['subfamily']; TypoFamily = $res['typosFamily']; TypoSubfamily = $res['typosSubfamily'] } } } $rows | Group-Object { "$($_.Family) / $($_.Subfamily)" } | Select-Object @{n='Family';e={$_.Name}}, Count | Sort-Object Family | Format-Table -AutoSize | Out-String -Width 160 | Write-Output Write-Output '=== [E] fontconfig conf files inside the Tectonic bundle + their content ===' Get-ChildItem (Join-Path $srcDir 'bundle') -Recurse -Filter '*fontconfig*' -File | ForEach-Object { Write-Output ('---- ' + $_.FullName.Substring($srcDir.Length+1) + ' ----') Get-Content $_.FullName } Write-Output '' Write-Output '=== [F] bundle opentype font dirs (unique, first 40) ===' Get-ChildItem (Join-Path (Join-Path $srcDir 'bundle') 'font') -Recurse -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -match '^(opentype|otf)$' -or $_.Parent.Name -eq 'opentype' } | Select-Object -ExpandProperty FullName | Sort-Object -Unique | Select-Object -First 40