Skip to content

Commit

Permalink
Separate FontSvg to classes
Browse files Browse the repository at this point in the history
  • Loading branch information
antonkomarev committed Oct 13, 2023
1 parent 773afba commit 8af6d8b
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 13 deletions.
6 changes: 6 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
136 changes: 136 additions & 0 deletions src/Parser/SimpleXmlSvgFontFileParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<?php

declare(strict_types=1);

namespace Cog\SvgFont\Parser;

use Cog\SvgFont\Font;
use Cog\SvgFont\FontFace;
use Cog\SvgFont\Glyph;
use Cog\SvgFont\MissingGlyph;
use Cog\SvgFont\SvgFontFileCollection;
use Cog\Unicode\CodePoint;

final class SimpleXmlSvgFontFileParser implements
SvgFontFileParser
{
private const ATTRIBUTE_ID = 'id';
private const ATTRIBUTE_HORIZ_ADV_X = 'horiz-adv-x';
private const ATTRIBUTE_UNITS_PER_EM = 'units-per-em';
private const ATTRIBUTE_UNICODE = 'unicode';
private const ATTRIBUTE_GLYPH_NAME = 'glyph-name';

private const ELEMENT_NAME_DEFS = 'defs';
private const ELEMENT_NAME_FONT = 'font';
private const ELEMENT_NAME_FONT_FACE = 'font-face';
private const ELEMENT_NAME_MISSING_GLYPH = 'missing-glyph';
private const ELEMENT_NAME_GLYPH = 'glyph';

/**
* @inheritDoc
*/
public function parseFile(string $filePath): SvgFontFileCollection
{
$xml = simplexml_load_file($filePath);

$fonts = [];

foreach ($xml as $xmlRootElement) {
if ($xmlRootElement->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,
);
}
}
34 changes: 23 additions & 11 deletions src/Parser/XmlReaderSvgFontFileParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -66,18 +86,10 @@ public function parseFile(
}
}

$font = new Font(
$fontId,
$defaultHorizontalAdvance,
$fontFace,
$missingGlyph,
$glyphs,
);
$xml->close();

return new SvgFontFileCollection(
[
$font,
]
$fonts,
);
}

Expand Down
4 changes: 2 additions & 2 deletions test/Unit/SvgFontTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
}
Expand Down

0 comments on commit 8af6d8b

Please sign in to comment.