diff options
Diffstat (limited to 'src/fonts.php')
| -rw-r--r-- | src/fonts.php | 77 |
1 files changed, 0 insertions, 77 deletions
diff --git a/src/fonts.php b/src/fonts.php deleted file mode 100644 index 6d7912b..0000000 --- a/src/fonts.php +++ /dev/null | |||
| @@ -1,77 +0,0 @@ | |||
| 1 | <?php | ||
| 2 | // fonts.php — LIST server-side fonts via fontconfig | ||
| 3 | |||
| 4 | header('Content-Type: application/json'); | ||
| 5 | header('Cache-Control: public, max-age=3600'); | ||
| 6 | |||
| 7 | /* get list of installed fonts using fc-list */ | ||
| 8 | $cmd = ['fc-list', '--format=%{family}|%{style}|%{file}\n']; | ||
| 9 | $desc = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']]; | ||
| 10 | $proc = proc_open($cmd, $desc, $pipes); | ||
| 11 | |||
| 12 | $output = ''; | ||
| 13 | if (is_resource($proc)) { | ||
| 14 | $output = stream_get_contents($pipes[1]); | ||
| 15 | fclose($pipes[1]); | ||
| 16 | fclose($pipes[2]); | ||
| 17 | proc_close($proc); | ||
| 18 | } | ||
| 19 | if (!$output) { | ||
| 20 | echo json_encode([]); | ||
| 21 | exit; | ||
| 22 | } | ||
| 23 | |||
| 24 | $lines = array_filter(explode("\n", trim($output))); | ||
| 25 | $best = []; // family => ['file' => ..., 'score' => ...] | ||
| 26 | |||
| 27 | /* lower score = higher priority */ | ||
| 28 | $style_score = static function (string $style): int { | ||
| 29 | $s = strtolower(trim($style)); | ||
| 30 | if ($s === 'regular' || $s === 'roman' || $s === 'book' || $s === 'text') return 0; | ||
| 31 | if ($s === 'bold') return 1; | ||
| 32 | if (str_contains($s, 'italic') || str_contains($s, 'oblique')) return 2; | ||
| 33 | return 3; | ||
| 34 | }; | ||
| 35 | |||
| 36 | foreach ($lines as $line) { | ||
| 37 | $parts = explode('|', $line, 3); | ||
| 38 | if (count($parts) < 3) continue; | ||
| 39 | |||
| 40 | /* take first family name (some entries are comma-separated) */ | ||
| 41 | $families = explode(',', $parts[0]); | ||
| 42 | $family = trim($families[0]); | ||
| 43 | |||
| 44 | if (empty($family)) continue; | ||
| 45 | |||
| 46 | $style = trim(explode(',', $parts[1])[0]); | ||
| 47 | $file = trim($parts[2]); | ||
| 48 | if (!file_exists($file)) continue; | ||
| 49 | |||
| 50 | $score = $style_score($style); | ||
| 51 | |||
| 52 | if (!isset($best[$family]) || $score < $best[$family]['score']) { | ||
| 53 | $best[$family] = ['file' => $file, 'score' => $score]; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | $fonts = []; | ||
| 58 | foreach ($best as $family => $entry) { | ||
| 59 | $file = $entry['file']; | ||
| 60 | $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION)); | ||
| 61 | $format = match ($ext) { | ||
| 62 | 'ttf' => 'truetype', | ||
| 63 | 'otf' => 'opentype', | ||
| 64 | 'woff' => 'woff', | ||
| 65 | 'woff2' => 'woff2', | ||
| 66 | default => 'truetype', | ||
| 67 | }; | ||
| 68 | |||
| 69 | $fonts[] = [ | ||
| 70 | 'family' => $family, | ||
| 71 | 'file' => base64_encode($file), | ||
| 72 | 'format' => $format, | ||
| 73 | ]; | ||
| 74 | } | ||
| 75 | |||
| 76 | usort($fonts, fn($a, $b) => strcasecmp($a['family'], $b['family'])); | ||
| 77 | echo json_encode($fonts); | ||
