From 85c0193d725c11de14fb57ed577fc7c7ea0814e4 Mon Sep 17 00:00:00 2001 From: Anton Komarev Date: Wed, 11 Oct 2023 18:55:24 +0300 Subject: [PATCH] Fix badge rendering without GD --- src/BadgeImageRendererService.php | 8 +- src/DejaVuSans-webfont.svg | 146 ++++++++++++++++++++++++++++++ src/SvgFont.php | 125 +++++++++++++++++++++++++ src/SvgTextSizeCalculator.php | 41 +++++++++ src/TextUnicodeConverter.php | 42 +++++++++ 5 files changed, 358 insertions(+), 4 deletions(-) create mode 100644 src/DejaVuSans-webfont.svg create mode 100644 src/SvgFont.php create mode 100644 src/SvgTextSizeCalculator.php create mode 100644 src/TextUnicodeConverter.php diff --git a/src/BadgeImageRendererService.php b/src/BadgeImageRendererService.php index f4ad326..2cdf8fb 100644 --- a/src/BadgeImageRendererService.php +++ b/src/BadgeImageRendererService.php @@ -27,10 +27,10 @@ final class BadgeImageRendererService public function __construct() { $this->poser = new Poser([ - new SvgPlasticRender(), - new SvgFlatRender(), - new SvgFlatSquareRender(), - new SvgForTheBadgeRenderer(), + new SvgPlasticRender(new SvgTextSizeCalculator()), + new SvgFlatRender(new SvgTextSizeCalculator()), + new SvgFlatSquareRender(new SvgTextSizeCalculator()), + new SvgForTheBadgeRenderer(null, new SvgTextSizeCalculator()), ]); } diff --git a/src/DejaVuSans-webfont.svg b/src/DejaVuSans-webfont.svg new file mode 100644 index 0000000..84589ef --- /dev/null +++ b/src/DejaVuSans-webfont.svg @@ -0,0 +1,146 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Copyright c 2003 by Bitstream Inc All Rights ReservedCopyright c 2006 by Tavmjong Bah All Rights ReservedDejaVu changes are in public domain +Foundry : DejaVu fonts team +Foundry URL : httpdejavusourceforgenet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/SvgFont.php b/src/SvgFont.php new file mode 100644 index 0000000..ae60b29 --- /dev/null +++ b/src/SvgFont.php @@ -0,0 +1,125 @@ +glyphs = $glyphs; + $this->unitsPerEm = $unitsPerEm; + $this->glyphSpacingAdvX = $glyphSpacingAdvX; + $this->missingGlyphAdvX = $missingGlyphAdvX; + } + + /** + * Takes path to SVG font (local path) and processes its XML + * to get path representation of every character and additional + * font parameters. + */ + public static function fromFile( + string $filePath + ): self { + $xml = new XMLReader(); + $xml->open($filePath); + + $glyphs = []; + $defaultHorizAdvX = 0; + $unitsPerEm = 0; + $glyphSpacingHorizAdvX = 0; + $missingGlyphHorizAdvX = 0; + + while ($xml->read()) { + if ($xml->nodeType !== XMLReader::ELEMENT) { + continue; + } + + if ($xml->name === 'font') { + $defaultHorizAdvX = intval($xml->getAttribute('horiz-adv-x')); + } + + if ($xml->name === 'font-face') { + $unitsPerEm = intval($xml->getAttribute('units-per-em')); + } + + if ($xml->name === 'missing-glyph') { + $missingGlyphHorizAdvX = intval($xml->getAttribute('horiz-adv-x')); + } + + if ($xml->name === 'glyph') { + $unicode = $xml->getAttribute('unicode'); + + if (isset($unicode)) { + $codePoints = TextUnicodeConverter::convertTextToCodePoints($unicode); + + if (isset($codePoints[0])) { + $codePoint = $codePoints[0]; + + $glyphs[$codePoint] = new \stdClass(); + $glyphHorizAdvX = $xml->getAttribute('horiz-adv-x'); + + if (empty($glyphHorizAdvX)) { + $glyphs[$codePoint]->horizAdvX = $defaultHorizAdvX; + } else { + $glyphs[$codePoint]->horizAdvX = intval($glyphHorizAdvX); + } + + $glyphs[$codePoint]->d = $xml->getAttribute('d'); + + if ($codePoint === self::UNICODE_CODE_POINT_M_LOWERCASE) { + $glyphSpacingHorizAdvX = $glyphs[$codePoint]->horizAdvX; + } + } + } + } + } + + return new self( + $glyphs, + $unitsPerEm, + $glyphSpacingHorizAdvX, + $missingGlyphHorizAdvX, + ); + } + + public function computeWidth( + int $codePoint, + int $size, + float $glyphSpacing = 0.0 + ): float { + $size = $size / $this->unitsPerEm; + + $glyphAdvX = $this->getGlyphAdvX($codePoint); + + $glyphWidth = $glyphAdvX * $size; + $glyphSpacingWidth = $this->glyphSpacingAdvX * $glyphSpacing * $size; + + return $glyphWidth + $glyphSpacingWidth; + } + + private function getGlyphAdvX( + int $codePoint + ): int { + return isset($this->glyphs[$codePoint]) + ? $this->glyphs[$codePoint]->horizAdvX + : $this->missingGlyphAdvX; + } +} diff --git a/src/SvgTextSizeCalculator.php b/src/SvgTextSizeCalculator.php new file mode 100644 index 0000000..dd75e64 --- /dev/null +++ b/src/SvgTextSizeCalculator.php @@ -0,0 +1,41 @@ +computeWidth($unicodeCodePoint, $size); + } + + $width = max($width, $lineWidth); + + return \round($width + self::SHIELD_PADDING, 1); + } +} diff --git a/src/TextUnicodeConverter.php b/src/TextUnicodeConverter.php new file mode 100644 index 0000000..e7b20e0 --- /dev/null +++ b/src/TextUnicodeConverter.php @@ -0,0 +1,42 @@ +