Skip to content

Instantly share code, notes, and snippets.

@SerafimArts
Last active March 26, 2023 05:58
Show Gist options
  • Save SerafimArts/01be7b01e9d1186fc7bf to your computer and use it in GitHub Desktop.
Save SerafimArts/01be7b01e9d1186fc7bf to your computer and use it in GitHub Desktop.
AI (Adobe Illustrator) Reader
<?php
namespace app\support\lib;
class Rect
{
protected $left;
protected $top;
protected $width;
protected $height;
public function __construct($left, $top, $width, $height)
{
$this->left = $left;
$this->top = $top;
$this->width = $width;
$this->height = $height;
}
public function getSize()
{
return (object)[
'width' => $this->width - $this->left,
'height' => $this->height - $this->top
];
}
public function __get($var)
{
if (isset($this->$var)) {
return $this->$var;
}
return null;
}
}
class Operation
{
/**
* @url http://partners.adobe.com/public/developer/en/illustrator/sdk/AI7FileFormat.pdf (page 56+)
*
* @TODO
* operation l
* operation L
* operation C
* operation V
* operation Y
*/
const OP_MOVE = 'm';
const OP_BEZIER = 'c';
const OP_BEZIER_SEGMENT_TO = 'v';
const OP_BEZIER_SEGMENT_FROM = 'y';
protected $type;
protected $points = [];
public function __construct($operation)
{
$points = explode(' ', $operation);
$this->type = array_pop($points);
foreach ($points as $point) {
$this->points[] = (double)$point;
}
}
}
class Layer
{
protected $operations = [];
protected $overlays = [];
public function __construct($points, $overlays)
{
$operations = explode(chr(13), $points);
foreach ($operations as $op) {
if (trim($op)) {
$this->operations[] = new Operation(trim($op));
}
}
preg_match_all('#\/([a-z]+)\s+((?:\/)?[a-z]+)\s*#isu', $overlays, $m);
for ($i=0; $i<count($m[0]); $i++) {
$this->overlays[$m[1][$i]] = $m[2][$i];
}
}
}
class Ai
{
protected $title;
protected $creator;
protected $path;
protected $layers;
public static function createFromFile($file)
{
return new static(file_get_contents($file));
}
public static function createFromSources($sources)
{
return new static($sources);
}
public function __construct($sources)
{
$this->title = $this->parse($sources, 'Title');
$this->creator = $this->parse($sources, 'Creator');
$this->path = $this->readSizes($sources);
$this->layers = $this->readLayers($sources);
}
public function getTitle()
{
return $this->title;
}
public function getCreator()
{
return $this->creator;
}
public function getPath()
{
return $this->path;
}
public function getLayers()
{
return $this->layers;
}
protected function readSizes($sources)
{
$box = explode(' ', $this->parse($sources, 'BoundingBox'));
return new Rect($box[0], $box[1], $box[2], $box[3]);
}
protected function readLayers($sources)
{
$result = [];
$pattern = '#%AI[0-9]+_Note:<<\s(.*?)\s>>\r1\sXR\s*(.*?)\s*n\r\*U#isu';
preg_match_all($pattern, $sources, $layers);
for ($i=0; $i<count($layers[0]); $i++) {
$result[] = new Layer($layers[2][$i], $layers[1][$i]);
}
return $result;
}
protected function parse($sources, $meta)
{
$pattern = '#%%' . $meta . ':(.*?)\r#isu';
preg_match_all($pattern, $sources, $m);
if (isset($m[1][0])) {
return trim($m[1][0]);
}
}
}
@SerafimArts
Copy link
Author

@reasecret just like without it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment