From 8af6d8b0d921501d7df4731e0774e7b3ab7e5724 Mon Sep 17 00:00:00 2001 From: Anton Komarev Date: Fri, 13 Oct 2023 22:39:19 +0300 Subject: [PATCH] Separate FontSvg to classes --- composer.json | 6 + src/Parser/SimpleXmlSvgFontFileParser.php | 136 ++++++++++++++++++++++ src/Parser/XmlReaderSvgFontFileParser.php | 34 ++++-- test/Unit/SvgFontTest.php | 4 +- 4 files changed, 167 insertions(+), 13 deletions(-) create mode 100644 src/Parser/SimpleXmlSvgFontFileParser.php diff --git a/composer.json b/composer.json index e24dd1f..91ef2d1 100644 --- a/composer.json +++ b/composer.json @@ -32,8 +32,14 @@ "cybercog/php-unicode": "dev-master" }, "require-dev": { + "ext-simplexml": "*", + "ext-xmlreader": "*", "phpunit/phpunit": "^9.0|^10.0" }, + "suggest": { + "ext-simplexml": "*", + "ext-xmlreader": "*" + }, "repositories": [ { "type": "git", diff --git a/src/Parser/SimpleXmlSvgFontFileParser.php b/src/Parser/SimpleXmlSvgFontFileParser.php new file mode 100644 index 0000000..d24360c --- /dev/null +++ b/src/Parser/SimpleXmlSvgFontFileParser.php @@ -0,0 +1,136 @@ +getName() === self::ELEMENT_NAME_DEFS) { + foreach ($xmlRootElement as $def) { + if ($def->getName() === self::ELEMENT_NAME_FONT) { + $fonts[] = $this->initFont($def); + } + } + } + } + + return new SvgFontFileCollection($fonts); + } + + private function initFont( + \SimpleXMLElement $fontElement + ): Font { + $fontId = strval($fontElement[self::ATTRIBUTE_ID]); + $defaultHorizontalAdvance = intval($fontElement[self::ATTRIBUTE_HORIZ_ADV_X]); + $glyphs = []; + + foreach ($fontElement as $fontChildElement) { + switch ($fontChildElement->getName()) { + case self::ELEMENT_NAME_FONT_FACE: + $fontFace = $this->initFontFace($fontChildElement); + break; + case self::ELEMENT_NAME_MISSING_GLYPH: + $missingGlyph = $this->initMissingGlyph($fontChildElement); + break; + case self::ELEMENT_NAME_GLYPH: + $character = strval($fontChildElement[self::ATTRIBUTE_UNICODE]); + + if ($character !== '') { + $codePointDecimal = CodePoint::ofCharacter($character)->toDecimal(); + $glyphs[$codePointDecimal] = $this->initGlyph($fontChildElement); + } + break; + } + } + + return new Font( + $fontId, + $defaultHorizontalAdvance, + $fontFace, + $missingGlyph, + $glyphs + ); + } + + private function initFontFace( + \SimpleXMLElement $fontFaceElement + ): FontFace { + $unitsPerEm = intval($fontFaceElement[self::ATTRIBUTE_UNITS_PER_EM]); + + if ($unitsPerEm === 0) { + $unitsPerEm = 1000; + } + + return new FontFace( + $unitsPerEm, + ); + } + + private function initGlyph( + \SimpleXMLElement $glyphElement + ): Glyph { + $name = strval($glyphElement[self::ATTRIBUTE_GLYPH_NAME]); + + if ($name === '') { + $name = null; + } + + $glyphHorizontalAdvance = intval($glyphElement[self::ATTRIBUTE_HORIZ_ADV_X]); + + if ($glyphHorizontalAdvance === 0) { + $glyphHorizontalAdvance = null; + } + + //$glyph->pathData = $xml->getAttribute('d'); + + return new Glyph( + $name, + $glyphHorizontalAdvance, + ); + } + + private function initMissingGlyph( + \SimpleXMLElement $missingGlyphElement + ): MissingGlyph { + $horizontalAdvance = intval($missingGlyphElement[self::ATTRIBUTE_HORIZ_ADV_X]); + + if ($horizontalAdvance === 0) { + $horizontalAdvance = null; + } + + return new MissingGlyph( + $horizontalAdvance, + ); + } +} diff --git a/src/Parser/XmlReaderSvgFontFileParser.php b/src/Parser/XmlReaderSvgFontFileParser.php index 300e6cb..de5f0bf 100644 --- a/src/Parser/XmlReaderSvgFontFileParser.php +++ b/src/Parser/XmlReaderSvgFontFileParser.php @@ -35,9 +35,29 @@ public function parseFile( $xml = new XMLReader(); $xml->open($filePath); - $glyphs = []; + $fonts = []; while ($xml->read()) { + if ($xml->name === self::ELEMENT_NAME_FONT) { + if ($xml->nodeType === XMLReader::ELEMENT) { + $fontId = null; + $defaultHorizontalAdvance = null; + $fontFace = null; + $missingGlyph = null; + $glyphs = []; + } + + if ($xml->nodeType === XMLReader::END_ELEMENT) { + $fonts[] = new Font( + $fontId, + $defaultHorizontalAdvance, + $fontFace, + $missingGlyph, + $glyphs + ); + } + } + if ($xml->nodeType !== XMLReader::ELEMENT) { continue; } @@ -66,18 +86,10 @@ public function parseFile( } } - $font = new Font( - $fontId, - $defaultHorizontalAdvance, - $fontFace, - $missingGlyph, - $glyphs, - ); + $xml->close(); return new SvgFontFileCollection( - [ - $font, - ] + $fonts, ); } diff --git a/test/Unit/SvgFontTest.php b/test/Unit/SvgFontTest.php index 7291759..586cde6 100644 --- a/test/Unit/SvgFontTest.php +++ b/test/Unit/SvgFontTest.php @@ -5,7 +5,7 @@ namespace Test\Unit\Cog\SvgFont; use Cog\SvgFont\Font; -use Cog\SvgFont\Parser\XmlReaderSvgFontFileParser; +use Cog\SvgFont\Parser\SimpleXmlSvgFontFileParser; use Cog\Unicode\CodePoint; use PHPUnit\Framework\TestCase; @@ -55,7 +55,7 @@ protected function getFontById( throw new \DomainException("Unknown test case font id `$fontId`"); } - return (new XmlReaderSvgFontFileParser()) + return (new SimpleXmlSvgFontFileParser()) ->parseFile(__DIR__ . '/../resource/' . $fontFileName) ->getById($fontId); }