diff --git a/src/Elements/TextElement.php b/src/Elements/TextElement.php index 510bcb4..5a7d3e0 100644 --- a/src/Elements/TextElement.php +++ b/src/Elements/TextElement.php @@ -7,52 +7,6 @@ use NoccyLabs\GdLabel\Element; class TextElement extends Element { - private static $fontCache = []; - - private static function findFont($font, $style='regular') - { - if (count(self::$fontCache)==0) { - self::updateFonts(); - } - - $font = strtolower($font); - - if (array_key_exists($font, self::$fontCache)) { - $info = self::$fontCache[$font]; - if (!$style) { - return $info; - } - if (array_key_exists($style, $info)) { - return $info[$style]; - } - return false; - } - return false; - } - - private static function updateFonts() - { - exec("fc-list", $output, $ret); - if ($ret != 0) { - fprintf(STDERR, "%s\n", join("\n",$output)); - return; - } - foreach ($output as $line) { - $seg = explode(":", $line); - $file = $seg[0]; - $name = strtolower(trim(preg_replace("/[^A-Za-z0-9 ]/", '', $seg[1]))); - $style = strtolower(str_replace("style=","",$seg[2])); - $style = explode(",",$style); - $style = reset($style); - - if (!array_key_exists($name, self::$fontCache)) { - self::$fontCache[$name] = []; - } - self::$fontCache[$name][$style] = $file; - } - - } - protected function draw($gd, int $x, int $y, int $width, int $height, array $params) { if (($bound = $this->getProp("bind-value"))) { @@ -62,8 +16,9 @@ class TextElement extends Element } $fontName = $this->getProp("font")?:"liberation sans"; + $fontStyle = $this->getProp("font-style")?:"regular"; + $font = \NoccyLabs\GdLabel\FontRegistry::getInstance()->findFont($fontName, $fontStyle); - $font = self::findFont($fontName); if (!$font) { return; } diff --git a/src/FontRegistry.php b/src/FontRegistry.php new file mode 100644 index 0000000..d3c106d --- /dev/null +++ b/src/FontRegistry.php @@ -0,0 +1,113 @@ +load(); + } + return self::$instance; + } + + public function load(string $lang='en') + { + exec("fc-list -v", $out, $ret); + $meta = []; $curr = []; + foreach ($out as $line) { + if (trim($line)) { + $curr[] = $line; + } else { + $meta[] = $curr; + $curr = []; + } + } + + foreach ($meta as $font) { + $this->parseMeta($font, $lang); + } + } + + private function parseMeta(array $meta, string $lang) + { + $coll = []; + foreach ($meta as $line) { + if (9 != ord($line[0]) or strpos($line,": ") === false or ctype_digit($line[1])) { + continue; + } + list ($key, $values) = explode(": ", substr($line, 1), 2); + if (preg_match('/.+lang$/', $key)) { + $base = substr($key, 0, -4); + $baseMeta = $coll[$base]; + $vals = str_getcsv($baseMeta, ' ', '"'); + $langs = str_getcsv($values, ' ', '"'); + $keep = []; + while (count($langs)>0) { + $l = $this->parseValue(array_shift($langs)); + $v = $this->parseValue(array_shift($vals)); + if ($l == $lang) { + $keep[] = $v; + } + } + $coll[$base] = $keep; + } else { + $coll[$key] = $values; + } + } + foreach ($coll as $key=>$values) { + if (is_array($values)) { + continue; + } + $coll[$key] = $this->parseValue($values); + } + $langs = explode("|", $coll['lang']); + if (!in_array($lang, $langs)) { + return; + } + $this->fonts[] = (object)$coll; + } + + private function parseValue($value) + { + if (substr($value, -3, 3) == "(s)") { + $value = substr($value, 0, -3); + if ($value && $value[0] == '"') { + $value = substr($value, 1, strpos($value, '"', 2)-1); + } + } + if (substr($value, -3, 3) == "(i)") { + $value = intval($value); + } + return $value; + } + + public function findFont($family, $styles='regular') + { + $styles = explode(" ",$styles); + foreach ($this->fonts as $font) { + $families = array_map("strtolower", (array)$font->family); + if (!in_array(strtolower($family), $families)) { + continue; + } + $fontStyles = array_map("strtolower", $font->style); + foreach ($styles as $style) { + if (!in_array($style, $fontStyles)) { + continue(2); + } + } + if (count(array_diff($fontStyles, $styles))>0) { + continue; + } + return $font->file; + } + } + +}