/**
  * generate a font from a directory containing svg files (one file per glyph)
  * by naming convention the file name can specify which character should be mapped to the glyph
  * - my-icon.png       => creates a glyph with the name 'my-icon' mapped to a character in the Unicode Private Use Area
  * - my-icon-x263a.png => creates a glyph with the name 'my-icon' mapped to the unicode character U+263A "☺"
  *
  * @param  string  $path              SVG path definition (consider the font coordinate system has an inverted y axis)
  * @param  array   $fontOptions       font options for the Font object
  * @param  boolean $renameSourceFiles if true, files without mapping information will be renamed
  * @return static                     this
  */
 public function generateFromDir($path, $fontOptions = array(), $renameSourceFiles = false)
 {
     $this->font = new Font($fontOptions);
     $this->mapping = array();
     $fontOptions = $this->font->getOptions();
     $files = scandir($path);
     foreach ($files as $fileName) {
         if (strtolower(substr($fileName, -4)) === '.svg') {
             if (preg_match('(^(.*)-x([0-9a-f]{2,6})\\.svg$)i', $fileName, $matches)) {
                 $iconName = strtolower($matches[1]);
                 $iconCode = static::hexToUnicode(strtolower($matches[2]));
                 if (isset($this->mapping[$iconCode])) {
                     throw new \Exception('Duplicate glyph ' . $iconCode . ' ' . $iconName);
                 }
                 $this->mapping[$iconCode] = array('path' => $path . DIRECTORY_SEPARATOR . $fileName, 'name' => $iconName);
             }
         }
     }
     foreach ($files as $fileName) {
         if (strtolower(substr($fileName, -4)) === '.svg') {
             if (!preg_match('(^(.*)-x([0-9a-f]{2,6})\\.svg$)i', $fileName)) {
                 $iconName = strtolower(substr($fileName, 0, -4));
                 $code = hexdec('e001');
                 while (isset($this->mapping[static::hexToUnicode(dechex($code))])) {
                     $code++;
                 }
                 if ($renameSourceFiles) {
                     if (!rename($path . DIRECTORY_SEPARATOR . $fileName, $path . DIRECTORY_SEPARATOR . $iconName . '-x' . dechex($code) . '.svg')) {
                         throw new \Exception('unable to rename "' . $path . DIRECTORY_SEPARATOR . $fileName . '"');
                     }
                     $fileName = $iconName . '-x' . dechex($code) . '.svg';
                 }
                 $this->mapping[static::hexToUnicode(dechex($code))] = array('path' => $path . DIRECTORY_SEPARATOR . $fileName, 'name' => $iconName);
             }
         }
     }
     foreach ($this->mapping as $code => $icon) {
         try {
             $iconDoc = new Document(file_get_contents($icon['path']));
             $viewBox = $iconDoc->getViewBox();
             $this->font->addGlyph($code, $iconDoc->getPath($fontOptions['units-per-em'] / $viewBox['height'], null, 'vertical', true, 0, $fontOptions['descent']), $icon['name'], round($viewBox['width'] * $fontOptions['units-per-em'] / $viewBox['height']));
         } catch (\Exception $e) {
             throw new \Exception(basename($icon['path']) . ': ' . $e->getMessage());
         }
     }
     return $this;
 }