Example #1
0
 /**
  * @return string
  */
 public function toJSON()
 {
     $font = $this->document;
     $fontJSON = array('w' => (int) $font['horiz-adv-x'], 'face' => array(), 'glyphs' => array());
     $face = $font->xpath('font-face');
     if (empty($face)) {
         return null;
     }
     foreach ($face[0]->attributes() as $key => $val) {
         $fontJSON['face'][$key] = (string) $val;
     }
     foreach ($font->xpath('glyph') as $glyph) {
         if (!isset($glyph['unicode'])) {
             continue;
         }
         if (mb_strlen($glyph['unicode'], 'utf-8') > 1) {
             // it's a ligature, for now we'll just ignore it
             continue;
         }
         $data = array();
         if (isset($glyph['d'])) {
             $data['d'] = substr(VMLPath::fromSVG((string) $glyph['d']), 1, -2);
             // skip m and xe
         }
         if (isset($glyph['horiz-adv-x'])) {
             $data['w'] = (int) $glyph['horiz-adv-x'];
         }
         $fontJSON['glyphs'][(string) $glyph['unicode']] = $data;
     }
     return json_encode($fontJSON);
 }
Example #2
0
 /**
  * @return string
  */
 public function toJavaScript()
 {
     $font = $this->document;
     $fontJSON = array('w' => (int) $font['horiz-adv-x'], 'face' => array(), 'glyphs' => array(' ' => new stdClass()));
     $face = $font->xpath('font-face');
     if (empty($face)) {
         return null;
     }
     foreach ($face[0]->attributes() as $key => $val) {
         $fontJSON['face'][$key] = $this->getSanitizedFaceValue($key, (string) $val);
     }
     $nameIndex = array();
     $charIndex = array();
     foreach ($font->xpath('glyph') as $glyph) {
         if (!isset($glyph['unicode'])) {
             continue;
         }
         if (mb_strlen($glyph['unicode'], 'utf-8') > 1) {
             // it's a ligature, for now we'll just ignore it
             continue;
         }
         $data = new stdClass();
         if (isset($glyph['d'])) {
             $data->d = substr(VMLPath::fromSVG((string) $glyph['d']), 1, -2);
             // skip m and xe
         }
         if (isset($glyph['horiz-adv-x'])) {
             $data->w = (int) $glyph['horiz-adv-x'];
         }
         $char = (string) $glyph['unicode'];
         if (isset($glyph['glyph-name'])) {
             foreach (explode(',', (string) $glyph['glyph-name']) as $glyphName) {
                 $nameIndex[$glyphName] = $char;
                 $charIndex[$char] = $data;
             }
         }
         $fontJSON['glyphs'][$char] = $data;
     }
     $options = $this->container->getOptions();
     $emSize = (int) $fontJSON['face']['units-per-em'];
     // for some extremely weird reason FontForge sometimes pumps out
     // astronomical kerning values.
     // @todo figure out what's really wrong
     $kerningLimit = $emSize * 2;
     if ($options['kerning']) {
         foreach ($font->xpath('hkern') as $hkern) {
             $k = (int) $hkern['k'];
             if (abs($k) > $kerningLimit) {
                 continue;
             }
             $firstSet = array();
             $secondSet = array();
             if (isset($hkern['u1'])) {
                 $firstSet = self::getMatchingCharsFromUnicodeRange((string) $hkern['u1'], $charIndex);
             }
             if (isset($hkern['g1'])) {
                 $firstSet = array_merge($firstSet, self::getMatchingCharsFromGlyphNames((string) $hkern['g1'], $nameIndex));
             }
             if (isset($hkern['u2'])) {
                 $secondSet = self::getMatchingCharsFromUnicodeRange((string) $hkern['u2'], $charIndex);
             }
             if (isset($hkern['g2'])) {
                 $secondSet = array_merge($secondSet, self::getMatchingCharsFromGlyphNames((string) $hkern['g2'], $nameIndex));
             }
             if (!empty($secondSet)) {
                 foreach ($firstSet as $firstGlyph) {
                     foreach ($secondSet as $secondGlyph) {
                         $glyph = $fontJSON['glyphs'][$firstGlyph];
                         if (!isset($glyph->k)) {
                             $glyph->k = array();
                         }
                         $glyph->k[$secondGlyph] = $k;
                     }
                 }
             }
         }
     }
     $nbsp = utf8_encode(chr(0xa0));
     if (!isset($fontJSON['glyphs'][$nbsp]) && isset($fontJSON['glyphs'][' '])) {
         $fontJSON['glyphs'][$nbsp] = $fontJSON['glyphs'][' '];
     }
     return self::processFont($fontJSON, $options);
 }
Example #3
0
 /**
  * @param string $path
  * @return VMLPath
  */
 public static function fromSVG($path)
 {
     $vml = new VMLPath();
     $matches = array();
     if (!preg_match_all('/([a-zA-Z])([0-9. \\-,]*)/', $path, $matches, PREG_SET_ORDER)) {
         return $vml;
     }
     $at = (object) array('x' => 0, 'y' => 0);
     $cp = (object) array('x' => 0, 'y' => 0);
     $previous = null;
     $zm = false;
     for (; $set = current($matches); next($matches)) {
         list($cmd, $coords) = array($set[1], array_map('floatval', preg_split('/(?:,|\\s+)/', trim($set[2]))));
         switch ($cmd) {
             case 'z':
             case 'Z':
                 if (strcasecmp($previous, 'm') === 0) {
                     $vml->pop();
                 }
                 if ($zm) {
                     $vml->pop();
                 }
                 $vml->closePath();
                 break;
             case 'M':
                 if (strcasecmp($previous, 'm') === 0) {
                     $vml->pop();
                 }
                 $vml->moveTo($at->x = $coords[0], $at->y = $coords[1]);
                 break;
             case 'L':
                 $vml->lineTo($at->x = $coords[0], $at->y = $coords[1]);
                 break;
             case 'l':
                 $vml->lineTo($at->x += $coords[0], $at->y += $coords[1]);
                 break;
             case 'H':
                 $vml->lineTo($at->x = $coords[0], $at->y);
                 break;
             case 'h':
                 $vml->lineTo($at->x += $coords[0], $at->y);
                 break;
             case 'V':
                 $vml->lineTo($at->x, $at->y = $coords[0]);
                 break;
             case 'v':
                 $vml->lineTo($at->x, $at->y += $coords[0]);
                 break;
             case 'C':
                 $vml->bezierCurveTo($coords[0], $coords[1], $cp->x = $coords[2], $cp->y = $coords[3], $at->x = $coords[4], $at->y = $coords[5]);
                 break;
             case 'c':
                 $vml->bezierCurveTo($at->x + $coords[0], $at->y + $coords[1], $cp->x = $at->x + $coords[2], $cp->y = $at->y + $coords[3], $at->x += $coords[4], $at->y += $coords[5]);
                 break;
             case 'S':
                 if (!$previous || !preg_match('/^[CcSs]$/', $previous)) {
                     $cp->x = $at->x;
                     $cp->y = $at->y;
                 }
                 $vml->bezierCurveTo($at->x + ($at->x - $cp->x), $at->y + ($at->y - $cp->y), $cp->x = $coords[0], $cp->y = $coords[1], $at->x = $coords[2], $at->y = $coords[3]);
                 break;
             case 's':
                 if (!$previous || !preg_match('/^[CcSs]$/', $previous)) {
                     $cp->x = $at->x;
                     $cp->y = $at->y;
                 }
                 $vml->bezierCurveTo($at->x + ($at->x - $cp->x), $at->y + ($at->y - $cp->y), $cp->x = $at->x + $coords[0], $cp->y = $at->y + $coords[1], $at->x += $coords[2], $at->y += $coords[3]);
                 break;
             case 'Q':
                 $vml->quadraticCurveTo($cp->x = $coords[0], $cp->y = $coords[1], $at->x = $coords[2], $at->y = $coords[3]);
                 break;
             case 'q':
                 $vml->quadraticCurveTo($cp->x = $at->x + $coords[0], $cp->y = $at->y + $coords[1], $at->x += $coords[2], $at->y += $coords[3]);
                 break;
             case 'T':
                 if (!$previous || !preg_match('/^[QqTt]$/', $previous)) {
                     $cp->x = $at->x;
                     $cp->y = $at->y;
                 }
                 $vml->quadraticCurveTo($cp->x = $at->x + ($at->x - $cp->x), $cp->y = $at->y + ($at->y - $cp->y), $at->x = $coords[0], $at->y = $coords[1]);
                 break;
             case 't':
                 if (!$previous || !preg_match('/^[QqTt]$/', $previous)) {
                     $cp->x = $at->x;
                     $cp->y = $at->y;
                 }
                 $vml->quadraticCurveTo($cp->x = $at->x + ($at->x - $cp->x), $cp->y = $at->y + ($at->y - $cp->y), $at->x += $coords[0], $at->y += $coords[1]);
                 break;
             case 'A':
             case 'a':
                 break;
         }
         $zm = strcasecmp($cmd, 'm') === 0 && strcasecmp($previous, 'z') === 0;
         $previous = $cmd;
     }
     $vml->endPath();
     return $vml;
 }
Example #4
0
 /**
  * @param XMLReader $reader
  * @return SVGFont
  */
 public function readFrom(XMLReader $reader)
 {
     $currentGlyphs = array(' ' => new stdClass());
     $currentFace = array('font-family' => '', 'font-weight' => '', 'font-stretch' => '', 'font-style' => 'normal', 'units-per-em' => '', 'panose-1' => '', 'ascent' => '', 'descent' => '', 'bbox' => '', 'underline-thickness' => '', 'underline-position' => '', 'unicode-range' => '');
     $nameIndex = array();
     $charIndex = array();
     do {
         if ($reader->nodeType == XMLReader::END_ELEMENT) {
             if ($reader->name === 'font') {
                 break;
             }
             continue;
         }
         if ($reader->nodeType != XMLReader::ELEMENT) {
             continue;
         }
         switch ($reader->name) {
             case 'font':
                 if (isset($this->id)) {
                     // shouldn't happen but hey, who knows
                     break 2;
                 }
                 $this->id = $reader->getAttribute('id');
                 $this->horizAdvX = (int) $reader->getAttribute('horiz-adv-x');
                 break;
             case 'font-face':
                 foreach ($currentFace as $key => $defaultValue) {
                     $actualValue = $this->sanitizeFaceValue($key, $reader->getAttribute($key));
                     $currentFace[$key] = $actualValue == null ? $defaultValue : $actualValue;
                 }
                 break;
             case 'glyph':
                 $glyphChar = $reader->getAttribute('unicode');
                 if (empty($glyphChar) && $glyphChar !== '0') {
                     break;
                 }
                 if (mb_strlen($glyphChar, 'utf-8') > 1) {
                     // it's a ligature, for now we'll just ignore it
                     break;
                 }
                 $glyphData = new stdClass();
                 $glyphName = $reader->getAttribute('glyph-name');
                 $glyphPath = $reader->getAttribute('d');
                 $glyphHorizAdvX = $reader->getAttribute('horiz-adv-x');
                 if ($glyphPath != null) {
                     $glyphData->d = substr(VMLPath::fromSVG($glyphPath), 1, -2);
                     // skip m and xe
                 }
                 if ($glyphHorizAdvX != null) {
                     $glyphData->w = (int) $glyphHorizAdvX;
                 }
                 if ($glyphName != null) {
                     foreach (explode(',', $glyphName) as $glyphNameAlt) {
                         $nameIndex[$glyphNameAlt] = $glyphChar;
                         $charIndex[$glyphChar] = $glyphData;
                     }
                 }
                 $currentGlyphs[$glyphChar] = $glyphData;
                 break;
             case 'hkern':
                 if (empty($this->options['kerning'])) {
                     break;
                 }
                 $kernK = (int) $reader->getAttribute('k');
                 $kernU1 = $reader->getAttribute('u1');
                 $kernG1 = $reader->getAttribute('g1');
                 $kernU2 = $reader->getAttribute('u2');
                 $kernG2 = $reader->getAttribute('g2');
                 $firstSet = array();
                 $secondSet = array();
                 if ($kernU1 != null) {
                     $firstSet = self::getMatchingCharsFromUnicodeRange($kernU1, $charIndex);
                 }
                 if ($kernG1 != null) {
                     $firstSet = array_merge($firstSet, self::getMatchingCharsFromGlyphNames($kernG1, $nameIndex));
                 }
                 if ($kernU2 != null) {
                     $secondSet = self::getMatchingCharsFromUnicodeRange($kernU2, $charIndex);
                 }
                 if ($kernG2 != null) {
                     $secondSet = array_merge($secondSet, self::getMatchingCharsFromGlyphNames($kernG2, $nameIndex));
                 }
                 if (!empty($secondSet)) {
                     foreach ($firstSet as $firstGlyph) {
                         foreach ($secondSet as $secondGlyph) {
                             $glyph = $currentGlyphs[$firstGlyph];
                             if (!isset($glyph->k)) {
                                 $glyph->k = array();
                             }
                             $glyph->k[$secondGlyph] = $kernK;
                         }
                     }
                 }
                 break;
         }
     } while ($reader->read());
     $nbsp = utf8_encode(chr(0xa0));
     if (!isset($currentGlyphs[$nbsp]) && isset($currentGlyphs[' '])) {
         $currentGlyphs[$nbsp] = $currentGlyphs[' '];
     }
     $this->face = $currentFace;
     $this->glyphs = $currentGlyphs;
     return $this;
 }