diff options
| author | kj_sh604 | 2026-03-02 20:43:40 -0500 |
|---|---|---|
| committer | kj_sh604 | 2026-03-02 20:43:40 -0500 |
| commit | fd01077b3f163cbe05be2cfeacdc45d3d060b8a5 (patch) | |
| tree | 6767192c49dfb3f8bb76ebed43ea5a9b479d121d /src | |
| parent | 1ba021a80cd8ea93efe0994f728c3a25450491f6 (diff) | |
fix: usage of italics for some font options
Diffstat (limited to 'src')
| -rw-r--r-- | src/fonts.php | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/src/fonts.php b/src/fonts.php index 1959f51..6d7912b 100644 --- a/src/fonts.php +++ b/src/fonts.php | |||
| @@ -4,31 +4,59 @@ | |||
| 4 | header('Content-Type: application/json'); | 4 | header('Content-Type: application/json'); |
| 5 | header('Cache-Control: public, max-age=3600'); | 5 | header('Cache-Control: public, max-age=3600'); |
| 6 | 6 | ||
| 7 | $output = shell_exec('fc-list --format="%{family}|%{file}\n" 2>/dev/null'); | 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 | } | ||
| 8 | if (!$output) { | 19 | if (!$output) { |
| 9 | echo json_encode([]); | 20 | echo json_encode([]); |
| 10 | exit; | 21 | exit; |
| 11 | } | 22 | } |
| 12 | 23 | ||
| 13 | $lines = array_filter(explode("\n", trim($output))); | 24 | $lines = array_filter(explode("\n", trim($output))); |
| 14 | $fonts = []; | 25 | $best = []; // family => ['file' => ..., 'score' => ...] |
| 15 | $seen = []; | 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 | }; | ||
| 16 | 35 | ||
| 17 | foreach ($lines as $line) { | 36 | foreach ($lines as $line) { |
| 18 | $parts = explode('|', $line, 2); | 37 | $parts = explode('|', $line, 3); |
| 19 | if (count($parts) < 2) continue; | 38 | if (count($parts) < 3) continue; |
| 20 | 39 | ||
| 21 | /* take first family name (some entries are comma-separated) */ | 40 | /* take first family name (some entries are comma-separated) */ |
| 22 | $families = explode(',', $parts[0]); | 41 | $families = explode(',', $parts[0]); |
| 23 | $family = trim($families[0]); | 42 | $family = trim($families[0]); |
| 24 | 43 | ||
| 25 | if (empty($family) || isset($seen[$family])) continue; | 44 | if (empty($family)) continue; |
| 26 | 45 | ||
| 27 | $file = trim($parts[1]); | 46 | $style = trim(explode(',', $parts[1])[0]); |
| 47 | $file = trim($parts[2]); | ||
| 28 | if (!file_exists($file)) continue; | 48 | if (!file_exists($file)) continue; |
| 29 | 49 | ||
| 30 | $seen[$family] = true; | 50 | $score = $style_score($style); |
| 31 | 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']; | ||
| 32 | $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION)); | 60 | $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION)); |
| 33 | $format = match ($ext) { | 61 | $format = match ($ext) { |
| 34 | 'ttf' => 'truetype', | 62 | 'ttf' => 'truetype', |
