swf2ass/src/ClipPath.php

102 lines
3 KiB
PHP

<?php
namespace swf2ass;
use MartinezRueda\Algorithm;
use MartinezRueda\Polygon;
class ClipPath {
/** @var Shape[] */
public array $shapes;
/**
* @param Shape[] $shapes
*/
public function __construct(array $shapes = []){
$this->shapes = $shapes;
}
public function getShape() : Shape{
$shape = new Shape();
foreach ($this->shapes as $s){
$shape = $shape->merge($s);
}
return $shape;
}
public function addShape(Shape $shape){
$this->shapes[] = $shape;
}
/**
* Calculates the intersection between two ClipPath.
* Shapes part of the clips need to be flat (or they will be flattened)
*
* @param ClipPath $other
* @return ClipPath
*/
public function intersect(ClipPath $other) : ClipPath{
try{
return self::fromPolygon((new Algorithm())->getIntersection($this->toPolygon(), $other->toPolygon()));
}catch (\Exception $e){
var_dump($this);
var_dump($other);
echo $e;
$self = $this->getShape()->flatten();
$other = $other->getShape()->flatten();
var_dump((new Shape($self->getRecords()))->getArea());
var_dump((new \swf2ass\ass\drawTag(new Shape($self->getRecords()), 1))->encode(new \swf2ass\ass\ASSEventTime(1, 1, 1)));
var_dump((new Shape($other->getRecords()))->getArea());
var_dump((new \swf2ass\ass\drawTag(new Shape($other->getRecords()), 1))->encode(new \swf2ass\ass\ASSEventTime(1, 1, 1)));
return $this; //TODO: fix this breakage, some clips being overlapping shapes????
}
}
private function toPolygon() : Polygon{
$contours = [];
foreach ($this->shapes as $shape){
$contours[] = array_map(function (Vector2 $point){return $point->toArray();}, $shape->toPoints());
}
return new Polygon($contours);
}
private static function fromPolygon(Polygon $p) : ClipPath{
$result = $p->toArray();
$clipPath = new ClipPath();
if(count($result) === 0){ //Nothing!
return $clipPath;
}
foreach ($result as $contour){
$shape = new Shape();
$start = $pos = new Vector2(...reset($contour));
while (($p = next($contour)) !== false){
$point = new Vector2(...$p);
$shape->addRecord(new LineRecord($point, $pos));
$pos = $point;
}
//if($shape->getArea() > Constants::EPSILON){ //TODO
$shape->addRecord(new LineRecord($start, $pos)); //Close shape
$clipPath->addShape($shape);
//}
}
return $clipPath;
}
public function applyMatrixTransform(MatrixTransform $transform, bool $applyTranslation = true) : ClipPath{
$shapes = [];
foreach ($this->shapes as $shape){
$shapes[] = $transform->applyToShape($shape, $applyTranslation);
}
return new ClipPath($shapes);
}
}