first commit
This commit is contained in:
110
vendor/phenx/php-font-lib/src/FontLib/Glyph/Outline.php
vendored
Normal file
110
vendor/phenx/php-font-lib/src/FontLib/Glyph/Outline.php
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/PhenX/php-font-lib
|
||||
* @author Fabien Ménager <fabien.menager@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||
* @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
|
||||
*/
|
||||
namespace FontLib\Glyph;
|
||||
|
||||
use FontLib\Table\Type\glyf;
|
||||
use FontLib\TrueType\File;
|
||||
use FontLib\BinaryStream;
|
||||
|
||||
/**
|
||||
* `glyf` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class Outline extends BinaryStream {
|
||||
/**
|
||||
* @var \FontLib\Table\Type\glyf
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
protected $offset;
|
||||
protected $size;
|
||||
|
||||
// Data
|
||||
public $numberOfContours;
|
||||
public $xMin;
|
||||
public $yMin;
|
||||
public $xMax;
|
||||
public $yMax;
|
||||
|
||||
public $raw;
|
||||
|
||||
/**
|
||||
* @param glyf $table
|
||||
* @param $offset
|
||||
* @param $size
|
||||
*
|
||||
* @return Outline
|
||||
*/
|
||||
static function init(glyf $table, $offset, $size, BinaryStream $font) {
|
||||
$font->seek($offset);
|
||||
|
||||
if ($font->readInt16() > -1) {
|
||||
/** @var OutlineSimple $glyph */
|
||||
$glyph = new OutlineSimple($table, $offset, $size);
|
||||
}
|
||||
else {
|
||||
/** @var OutlineComposite $glyph */
|
||||
$glyph = new OutlineComposite($table, $offset, $size);
|
||||
}
|
||||
|
||||
$glyph->parse($font);
|
||||
|
||||
return $glyph;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return File
|
||||
*/
|
||||
function getFont() {
|
||||
return $this->table->getFont();
|
||||
}
|
||||
|
||||
function __construct(glyf $table, $offset = null, $size = null) {
|
||||
$this->table = $table;
|
||||
$this->offset = $offset;
|
||||
$this->size = $size;
|
||||
}
|
||||
|
||||
function parse(BinaryStream $font) {
|
||||
$font->seek($this->offset);
|
||||
|
||||
if (!$this->size) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->raw = $font->read($this->size);
|
||||
}
|
||||
|
||||
function parseData() {
|
||||
$font = $this->getFont();
|
||||
$font->seek($this->offset);
|
||||
|
||||
$this->numberOfContours = $font->readInt16();
|
||||
$this->xMin = $font->readFWord();
|
||||
$this->yMin = $font->readFWord();
|
||||
$this->xMax = $font->readFWord();
|
||||
$this->yMax = $font->readFWord();
|
||||
}
|
||||
|
||||
function encode() {
|
||||
$font = $this->getFont();
|
||||
|
||||
return $font->write($this->raw, strlen($this->raw));
|
||||
}
|
||||
|
||||
function getSVGContours() {
|
||||
// Inherit
|
||||
}
|
||||
|
||||
function getGlyphIDs() {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
31
vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineComponent.php
vendored
Normal file
31
vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineComponent.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/PhenX/php-font-lib
|
||||
* @author Fabien Ménager <fabien.menager@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||
* @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
|
||||
*/
|
||||
|
||||
namespace FontLib\Glyph;
|
||||
/**
|
||||
* Glyph outline component
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class OutlineComponent {
|
||||
public $flags;
|
||||
public $glyphIndex;
|
||||
public $a, $b, $c, $d, $e, $f;
|
||||
public $point_compound;
|
||||
public $point_component;
|
||||
public $instructions;
|
||||
|
||||
function getMatrix() {
|
||||
return array(
|
||||
$this->a, $this->b,
|
||||
$this->c, $this->d,
|
||||
$this->e, $this->f,
|
||||
);
|
||||
}
|
||||
}
|
||||
242
vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineComposite.php
vendored
Normal file
242
vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineComposite.php
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/PhenX/php-font-lib
|
||||
* @author Fabien Ménager <fabien.menager@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||
* @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
|
||||
*/
|
||||
|
||||
namespace FontLib\Glyph;
|
||||
|
||||
/**
|
||||
* Composite glyph outline
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class OutlineComposite extends Outline {
|
||||
const ARG_1_AND_2_ARE_WORDS = 0x0001;
|
||||
const ARGS_ARE_XY_VALUES = 0x0002;
|
||||
const ROUND_XY_TO_GRID = 0x0004;
|
||||
const WE_HAVE_A_SCALE = 0x0008;
|
||||
const MORE_COMPONENTS = 0x0020;
|
||||
const WE_HAVE_AN_X_AND_Y_SCALE = 0x0040;
|
||||
const WE_HAVE_A_TWO_BY_TWO = 0x0080;
|
||||
const WE_HAVE_INSTRUCTIONS = 0x0100;
|
||||
const USE_MY_METRICS = 0x0200;
|
||||
const OVERLAP_COMPOUND = 0x0400;
|
||||
|
||||
/**
|
||||
* @var OutlineComponent[]
|
||||
*/
|
||||
public $components = array();
|
||||
|
||||
function getGlyphIDs() {
|
||||
if (empty($this->components)) {
|
||||
$this->parseData();
|
||||
}
|
||||
|
||||
$glyphIDs = array();
|
||||
foreach ($this->components as $_component) {
|
||||
$glyphIDs[] = $_component->glyphIndex;
|
||||
|
||||
$_glyph = $this->table->data[$_component->glyphIndex];
|
||||
|
||||
if ($_glyph !== $this) {
|
||||
$glyphIDs = array_merge($glyphIDs, $_glyph->getGlyphIDs());
|
||||
}
|
||||
}
|
||||
|
||||
return $glyphIDs;
|
||||
}
|
||||
|
||||
/*function parse() {
|
||||
//$this->parseData();
|
||||
}*/
|
||||
|
||||
function parseData() {
|
||||
parent::parseData();
|
||||
|
||||
$font = $this->getFont();
|
||||
|
||||
do {
|
||||
$flags = $font->readUInt16();
|
||||
$glyphIndex = $font->readUInt16();
|
||||
|
||||
$a = 1.0;
|
||||
$b = 0.0;
|
||||
$c = 0.0;
|
||||
$d = 1.0;
|
||||
$e = 0.0;
|
||||
$f = 0.0;
|
||||
|
||||
$point_compound = null;
|
||||
$point_component = null;
|
||||
|
||||
$instructions = null;
|
||||
|
||||
if ($flags & self::ARG_1_AND_2_ARE_WORDS) {
|
||||
if ($flags & self::ARGS_ARE_XY_VALUES) {
|
||||
$e = $font->readInt16();
|
||||
$f = $font->readInt16();
|
||||
}
|
||||
else {
|
||||
$point_compound = $font->readUInt16();
|
||||
$point_component = $font->readUInt16();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($flags & self::ARGS_ARE_XY_VALUES) {
|
||||
$e = $font->readInt8();
|
||||
$f = $font->readInt8();
|
||||
}
|
||||
else {
|
||||
$point_compound = $font->readUInt8();
|
||||
$point_component = $font->readUInt8();
|
||||
}
|
||||
}
|
||||
|
||||
if ($flags & self::WE_HAVE_A_SCALE) {
|
||||
$a = $d = $font->readInt16();
|
||||
}
|
||||
elseif ($flags & self::WE_HAVE_AN_X_AND_Y_SCALE) {
|
||||
$a = $font->readInt16();
|
||||
$d = $font->readInt16();
|
||||
}
|
||||
elseif ($flags & self::WE_HAVE_A_TWO_BY_TWO) {
|
||||
$a = $font->readInt16();
|
||||
$b = $font->readInt16();
|
||||
$c = $font->readInt16();
|
||||
$d = $font->readInt16();
|
||||
}
|
||||
|
||||
//if ($flags & self::WE_HAVE_INSTRUCTIONS) {
|
||||
//
|
||||
//}
|
||||
|
||||
$component = new OutlineComponent();
|
||||
$component->flags = $flags;
|
||||
$component->glyphIndex = $glyphIndex;
|
||||
$component->a = $a;
|
||||
$component->b = $b;
|
||||
$component->c = $c;
|
||||
$component->d = $d;
|
||||
$component->e = $e;
|
||||
$component->f = $f;
|
||||
$component->point_compound = $point_compound;
|
||||
$component->point_component = $point_component;
|
||||
$component->instructions = $instructions;
|
||||
|
||||
$this->components[] = $component;
|
||||
} while ($flags & self::MORE_COMPONENTS);
|
||||
}
|
||||
|
||||
function encode() {
|
||||
$font = $this->getFont();
|
||||
|
||||
$gids = $font->getSubset();
|
||||
|
||||
$size = $font->writeInt16(-1);
|
||||
$size += $font->writeFWord($this->xMin);
|
||||
$size += $font->writeFWord($this->yMin);
|
||||
$size += $font->writeFWord($this->xMax);
|
||||
$size += $font->writeFWord($this->yMax);
|
||||
|
||||
foreach ($this->components as $_i => $_component) {
|
||||
$flags = 0;
|
||||
if ($_component->point_component === null && $_component->point_compound === null) {
|
||||
$flags |= self::ARGS_ARE_XY_VALUES;
|
||||
|
||||
if (abs($_component->e) > 0x7F || abs($_component->f) > 0x7F) {
|
||||
$flags |= self::ARG_1_AND_2_ARE_WORDS;
|
||||
}
|
||||
}
|
||||
elseif ($_component->point_component > 0xFF || $_component->point_compound > 0xFF) {
|
||||
$flags |= self::ARG_1_AND_2_ARE_WORDS;
|
||||
}
|
||||
|
||||
if ($_component->b == 0 && $_component->c == 0) {
|
||||
if ($_component->a == $_component->d) {
|
||||
if ($_component->a != 1.0) {
|
||||
$flags |= self::WE_HAVE_A_SCALE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$flags |= self::WE_HAVE_AN_X_AND_Y_SCALE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$flags |= self::WE_HAVE_A_TWO_BY_TWO;
|
||||
}
|
||||
|
||||
if ($_i < count($this->components) - 1) {
|
||||
$flags |= self::MORE_COMPONENTS;
|
||||
}
|
||||
|
||||
$size += $font->writeUInt16($flags);
|
||||
|
||||
$new_gid = array_search($_component->glyphIndex, $gids);
|
||||
$size += $font->writeUInt16($new_gid);
|
||||
|
||||
if ($flags & self::ARG_1_AND_2_ARE_WORDS) {
|
||||
if ($flags & self::ARGS_ARE_XY_VALUES) {
|
||||
$size += $font->writeInt16($_component->e);
|
||||
$size += $font->writeInt16($_component->f);
|
||||
}
|
||||
else {
|
||||
$size += $font->writeUInt16($_component->point_compound);
|
||||
$size += $font->writeUInt16($_component->point_component);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($flags & self::ARGS_ARE_XY_VALUES) {
|
||||
$size += $font->writeInt8($_component->e);
|
||||
$size += $font->writeInt8($_component->f);
|
||||
}
|
||||
else {
|
||||
$size += $font->writeUInt8($_component->point_compound);
|
||||
$size += $font->writeUInt8($_component->point_component);
|
||||
}
|
||||
}
|
||||
|
||||
if ($flags & self::WE_HAVE_A_SCALE) {
|
||||
$size += $font->writeInt16($_component->a);
|
||||
}
|
||||
elseif ($flags & self::WE_HAVE_AN_X_AND_Y_SCALE) {
|
||||
$size += $font->writeInt16($_component->a);
|
||||
$size += $font->writeInt16($_component->d);
|
||||
}
|
||||
elseif ($flags & self::WE_HAVE_A_TWO_BY_TWO) {
|
||||
$size += $font->writeInt16($_component->a);
|
||||
$size += $font->writeInt16($_component->b);
|
||||
$size += $font->writeInt16($_component->c);
|
||||
$size += $font->writeInt16($_component->d);
|
||||
}
|
||||
}
|
||||
|
||||
return $size;
|
||||
}
|
||||
|
||||
public function getSVGContours() {
|
||||
$contours = array();
|
||||
|
||||
/** @var \FontLib\Table\Type\glyf $glyph_data */
|
||||
$glyph_data = $this->getFont()->getTableObject("glyf");
|
||||
|
||||
/** @var Outline[] $glyphs */
|
||||
$glyphs = $glyph_data->data;
|
||||
|
||||
foreach ($this->components as $component) {
|
||||
$_glyph = $glyphs[$component->glyphIndex];
|
||||
|
||||
if ($_glyph !== $this) {
|
||||
$contours[] = array(
|
||||
"contours" => $_glyph->getSVGContours(),
|
||||
"transform" => $component->getMatrix(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $contours;
|
||||
}
|
||||
}
|
||||
335
vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineSimple.php
vendored
Normal file
335
vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineSimple.php
vendored
Normal file
@@ -0,0 +1,335 @@
|
||||
<?php
|
||||
/**
|
||||
* @package php-font-lib
|
||||
* @link https://github.com/PhenX/php-font-lib
|
||||
* @author Fabien Ménager <fabien.menager@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||
* @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
|
||||
*/
|
||||
|
||||
namespace FontLib\Glyph;
|
||||
|
||||
/**
|
||||
* `glyf` font table.
|
||||
*
|
||||
* @package php-font-lib
|
||||
*/
|
||||
class OutlineSimple extends Outline {
|
||||
const ON_CURVE = 0x01;
|
||||
const X_SHORT_VECTOR = 0x02;
|
||||
const Y_SHORT_VECTOR = 0x04;
|
||||
const REPEAT = 0x08;
|
||||
const THIS_X_IS_SAME = 0x10;
|
||||
const THIS_Y_IS_SAME = 0x20;
|
||||
|
||||
public $instructions;
|
||||
public $points;
|
||||
|
||||
function parseData() {
|
||||
parent::parseData();
|
||||
|
||||
if (!$this->size) {
|
||||
return;
|
||||
}
|
||||
|
||||
$font = $this->getFont();
|
||||
|
||||
$noc = $this->numberOfContours;
|
||||
|
||||
if ($noc == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$endPtsOfContours = $font->r(array(self::uint16, $noc));
|
||||
|
||||
$instructionLength = $font->readUInt16();
|
||||
$this->instructions = $font->r(array(self::uint8, $instructionLength));
|
||||
|
||||
$count = $endPtsOfContours[$noc - 1] + 1;
|
||||
|
||||
// Flags
|
||||
$flags = array();
|
||||
for ($index = 0; $index < $count; $index++) {
|
||||
$flags[$index] = $font->readUInt8();
|
||||
|
||||
if ($flags[$index] & self::REPEAT) {
|
||||
$repeats = $font->readUInt8();
|
||||
|
||||
for ($i = 1; $i <= $repeats; $i++) {
|
||||
$flags[$index + $i] = $flags[$index];
|
||||
}
|
||||
|
||||
$index += $repeats;
|
||||
}
|
||||
}
|
||||
|
||||
$points = array();
|
||||
foreach ($flags as $i => $flag) {
|
||||
$points[$i]["onCurve"] = $flag & self::ON_CURVE;
|
||||
$points[$i]["endOfContour"] = in_array($i, $endPtsOfContours);
|
||||
}
|
||||
|
||||
// X Coords
|
||||
$x = 0;
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$flag = $flags[$i];
|
||||
|
||||
if ($flag & self::THIS_X_IS_SAME) {
|
||||
if ($flag & self::X_SHORT_VECTOR) {
|
||||
$x += $font->readUInt8();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($flag & self::X_SHORT_VECTOR) {
|
||||
$x -= $font->readUInt8();
|
||||
}
|
||||
else {
|
||||
$x += $font->readInt16();
|
||||
}
|
||||
}
|
||||
|
||||
$points[$i]["x"] = $x;
|
||||
}
|
||||
|
||||
// Y Coords
|
||||
$y = 0;
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$flag = $flags[$i];
|
||||
|
||||
if ($flag & self::THIS_Y_IS_SAME) {
|
||||
if ($flag & self::Y_SHORT_VECTOR) {
|
||||
$y += $font->readUInt8();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($flag & self::Y_SHORT_VECTOR) {
|
||||
$y -= $font->readUInt8();
|
||||
}
|
||||
else {
|
||||
$y += $font->readInt16();
|
||||
}
|
||||
}
|
||||
|
||||
$points[$i]["y"] = $y;
|
||||
}
|
||||
|
||||
$this->points = $points;
|
||||
}
|
||||
|
||||
public function splitSVGPath($path) {
|
||||
preg_match_all('/([a-z])|(-?\d+(?:\.\d+)?)/i', $path, $matches, PREG_PATTERN_ORDER);
|
||||
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
public function makePoints($path) {
|
||||
$path = $this->splitSVGPath($path);
|
||||
$l = count($path);
|
||||
$i = 0;
|
||||
|
||||
$points = array();
|
||||
|
||||
while ($i < $l) {
|
||||
switch ($path[$i]) {
|
||||
// moveTo
|
||||
case "M":
|
||||
$points[] = array(
|
||||
"onCurve" => true,
|
||||
"x" => $path[++$i],
|
||||
"y" => $path[++$i],
|
||||
"endOfContour" => false,
|
||||
);
|
||||
break;
|
||||
|
||||
// lineTo
|
||||
case "L":
|
||||
$points[] = array(
|
||||
"onCurve" => true,
|
||||
"x" => $path[++$i],
|
||||
"y" => $path[++$i],
|
||||
"endOfContour" => false,
|
||||
);
|
||||
break;
|
||||
|
||||
// quadraticCurveTo
|
||||
case "Q":
|
||||
$points[] = array(
|
||||
"onCurve" => false,
|
||||
"x" => $path[++$i],
|
||||
"y" => $path[++$i],
|
||||
"endOfContour" => false,
|
||||
);
|
||||
$points[] = array(
|
||||
"onCurve" => true,
|
||||
"x" => $path[++$i],
|
||||
"y" => $path[++$i],
|
||||
"endOfContour" => false,
|
||||
);
|
||||
break;
|
||||
|
||||
// closePath
|
||||
/** @noinspection PhpMissingBreakStatementInspection */
|
||||
case "z":
|
||||
$points[count($points) - 1]["endOfContour"] = true;
|
||||
|
||||
default:
|
||||
$i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $points;
|
||||
}
|
||||
|
||||
function encode() {
|
||||
if (empty($this->points)) {
|
||||
return parent::encode();
|
||||
}
|
||||
|
||||
return $this->size = $this->encodePoints($this->points);
|
||||
}
|
||||
|
||||
public function encodePoints($points) {
|
||||
$endPtsOfContours = array();
|
||||
$flags = array();
|
||||
$coords_x = array();
|
||||
$coords_y = array();
|
||||
|
||||
$last_x = 0;
|
||||
$last_y = 0;
|
||||
$xMin = $yMin = 0xFFFF;
|
||||
$xMax = $yMax = -0xFFFF;
|
||||
foreach ($points as $i => $point) {
|
||||
$flag = 0;
|
||||
if ($point["onCurve"]) {
|
||||
$flag |= self::ON_CURVE;
|
||||
}
|
||||
|
||||
if ($point["endOfContour"]) {
|
||||
$endPtsOfContours[] = $i;
|
||||
}
|
||||
|
||||
// Simplified, we could do some optimizations
|
||||
if ($point["x"] == $last_x) {
|
||||
$flag |= self::THIS_X_IS_SAME;
|
||||
}
|
||||
else {
|
||||
$x = intval($point["x"]);
|
||||
$xMin = min($x, $xMin);
|
||||
$xMax = max($x, $xMax);
|
||||
$coords_x[] = $x - $last_x; // int16
|
||||
}
|
||||
|
||||
// Simplified, we could do some optimizations
|
||||
if ($point["y"] == $last_y) {
|
||||
$flag |= self::THIS_Y_IS_SAME;
|
||||
}
|
||||
else {
|
||||
$y = intval($point["y"]);
|
||||
$yMin = min($y, $yMin);
|
||||
$yMax = max($y, $yMax);
|
||||
$coords_y[] = $y - $last_y; // int16
|
||||
}
|
||||
|
||||
$flags[] = $flag;
|
||||
$last_x = $point["x"];
|
||||
$last_y = $point["y"];
|
||||
}
|
||||
|
||||
$font = $this->getFont();
|
||||
|
||||
$l = 0;
|
||||
$l += $font->writeInt16(count($endPtsOfContours)); // endPtsOfContours
|
||||
$l += $font->writeFWord(isset($this->xMin) ? $this->xMin : $xMin); // xMin
|
||||
$l += $font->writeFWord(isset($this->yMin) ? $this->yMin : $yMin); // yMin
|
||||
$l += $font->writeFWord(isset($this->xMax) ? $this->xMax : $xMax); // xMax
|
||||
$l += $font->writeFWord(isset($this->yMax) ? $this->yMax : $yMax); // yMax
|
||||
|
||||
// Simple glyf
|
||||
$l += $font->w(array(self::uint16, count($endPtsOfContours)), $endPtsOfContours); // endPtsOfContours
|
||||
$l += $font->writeUInt16(0); // instructionLength
|
||||
$l += $font->w(array(self::uint8, count($flags)), $flags); // flags
|
||||
$l += $font->w(array(self::int16, count($coords_x)), $coords_x); // xCoordinates
|
||||
$l += $font->w(array(self::int16, count($coords_y)), $coords_y); // yCoordinates
|
||||
return $l;
|
||||
}
|
||||
|
||||
public function getSVGContours($points = null) {
|
||||
$path = "";
|
||||
|
||||
if (!$points) {
|
||||
if (empty($this->points)) {
|
||||
$this->parseData();
|
||||
}
|
||||
|
||||
$points = $this->points;
|
||||
}
|
||||
|
||||
$length = count($points);
|
||||
$firstIndex = 0;
|
||||
$count = 0;
|
||||
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$count++;
|
||||
|
||||
if ($points[$i]["endOfContour"]) {
|
||||
$path .= $this->getSVGPath($points, $firstIndex, $count);
|
||||
$firstIndex = $i + 1;
|
||||
$count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
protected function getSVGPath($points, $startIndex, $count) {
|
||||
$offset = 0;
|
||||
$path = "";
|
||||
|
||||
while ($offset < $count) {
|
||||
$point = $points[$startIndex + $offset % $count];
|
||||
$point_p1 = $points[$startIndex + ($offset + 1) % $count];
|
||||
|
||||
if ($offset == 0) {
|
||||
$path .= "M{$point['x']},{$point['y']} ";
|
||||
}
|
||||
|
||||
if ($point["onCurve"]) {
|
||||
if ($point_p1["onCurve"]) {
|
||||
$path .= "L{$point_p1['x']},{$point_p1['y']} ";
|
||||
$offset++;
|
||||
}
|
||||
else {
|
||||
$point_p2 = $points[$startIndex + ($offset + 2) % $count];
|
||||
|
||||
if ($point_p2["onCurve"]) {
|
||||
$path .= "Q{$point_p1['x']},{$point_p1['y']},{$point_p2['x']},{$point_p2['y']} ";
|
||||
}
|
||||
else {
|
||||
$path .= "Q{$point_p1['x']},{$point_p1['y']}," . $this->midValue($point_p1['x'], $point_p2['x']) . "," . $this->midValue($point_p1['y'], $point_p2['y']) . " ";
|
||||
}
|
||||
|
||||
$offset += 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($point_p1["onCurve"]) {
|
||||
$path .= "Q{$point['x']},{$point['y']},{$point_p1['x']},{$point_p1['y']} ";
|
||||
}
|
||||
else {
|
||||
$path .= "Q{$point['x']},{$point['y']}," . $this->midValue($point['x'], $point_p1['x']) . "," . $this->midValue($point['y'], $point_p1['y']) . " ";
|
||||
}
|
||||
|
||||
$offset++;
|
||||
}
|
||||
}
|
||||
|
||||
$path .= "z ";
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
function midValue($a, $b) {
|
||||
return $a + ($b - $a) / 2;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user