Proper clips from parent object creation, they are now processed at a later stage

This commit is contained in:
DataHoarder 2022-01-07 21:03:35 +01:00
parent fa58baceda
commit 4e87f108e9
5 changed files with 77 additions and 58 deletions

17
src/ClippingFrame.php Normal file
View file

@ -0,0 +1,17 @@
<?php
namespace swf2ass;
class ClippingFrame extends ViewFrame {
private int $clipDepth;
public function __construct(int $objectId, int $clipDepth, ?DrawPathList $drawPathList) {
$this->clipDepth = $clipDepth;
parent::__construct($objectId, $drawPathList);
}
public function getClipDepth() : int{
return $this->clipDepth;
}
}

View file

@ -14,4 +14,18 @@ class ClippingViewLayout extends ViewLayout {
public function getClipDepth(): int {
return $this->clipDepth;
}
public function nextFrame(ActionList $actionList): ClippingFrame {
$frame = parent::nextFrame($actionList);
$clip = new ClippingFrame($frame->getObjectId(), $this->getClipDepth(), $frame->getDrawPathList());
foreach ($frame->getDepthMap() as $depth => $f){
$clip->addChild($depth, $f);
}
$clip->setColorTransform($frame->getColorTransform());
$clip->setMatrixTransform($frame->getMatrixTransform());
return $clip;
}
}

View file

@ -21,6 +21,10 @@ class RenderedObject {
$this->clip = $clip;
}
public function setClipPath(?ClipPath $path){
$this->clip = $path;
}
/**
* @return int[]
*/

View file

@ -7,8 +7,7 @@ class ViewFrame {
private int $objectId;
/** @var ViewFrame[] */
private array $depthMap = [];
/** @var ViewFrame[] */
private ?array $clipDepthMap = null;
private ?DrawPathList $drawPathList;
private ?ColorTransform $colorTransform = null;
@ -19,22 +18,14 @@ class ViewFrame {
$this->drawPathList = $drawPathList;
}
public function getDrawPathList() : ?DrawPathList{
return $this->drawPathList;
}
public function getObjectId(): int {
return $this->objectId;
}
public function setClipDepthMap(array $clipDepthMap) {
$this->clipDepthMap = $clipDepthMap;
//TODO: process this
}
/**
* @return ViewFrame[]|null
*/
public function getClipDepthMap(): ?array {
return $this->clipDepthMap;
}
public function addChild(int $depth, ViewFrame $frame) {
if ($this->drawPathList !== null) {
throw new \Exception();
@ -81,36 +72,50 @@ class ViewFrame {
$renderedFrame = new RenderedFrame();
$clipPath = null;
if ($this->clipDepthMap !== null) {
$colorIdentity = ColorTransform::identity();
$matrixIdentity = $parentMatrix;
foreach ($this->clipDepthMap as $clipDepth => $clipFrame) {
//TODO: detect rectangle clips?
//TODO: clip clips?
foreach ($clipFrame->render($clipDepth, $depthChain, $colorIdentity, $matrixIdentity)->getObjects() as $clipObject) {
$clipShape = new ClipPath();
foreach ($clipObject->drawPathList->commands as $p) {
if($p->style instanceof FillStyleRecord){ //Only clip with fills
$s = $p->commands->flatten();
if($s->getArea() > Constants::EPSILON){
$clipShape->addShape($s);
if ($this->drawPathList !== null) {
$renderedFrame->add(new RenderedObject($depthChain, $this->getObjectId(), $this->drawPathList, $colorTransform ?? ColorTransform::identity(), $matrixTransform ?? MatrixTransform::identity(), null));
} else {
/** @var ClippingFrame[] $clipMap */
$clipMap = [];
/** @var ClipPath $clipPaths */
$clipPaths = [];
foreach ($this->depthMap as $depth => $frame) { //Do not require ordering
if ($frame instanceof ClippingFrame) { //Process clips as they come
$clipMap[$depth] = $frame;
$clipPath = null;
foreach ($frame->render($depth, $depthChain, $colorTransform, $matrixTransform)->getObjects() as $clipObject) {
$clipShape = new ClipPath();
foreach ($clipObject->drawPathList->commands as $p) {
if ($p->style instanceof FillStyleRecord) { //Only clip with fills
$clipShape->addShape($p->commands);
}
}
if (count($clipShape->shapes) > 0) {
$clipShape = $clipShape->applyMatrixTransform($clipObject->matrixTransform);
$clipPath = $clipPath === null ? $clipShape : $clipShape->intersect($clipPath);
}
}
if(count($clipShape->shapes) > 0){
$clipShape = $clipShape->applyMatrixTransform($clipObject->matrixTransform);
$clipPath = $clipPath === null ? $clipShape : $clipShape->intersect($clipPath);
if ($clipPath !== null) {
$clipPaths[$depth] = $clipPath;
}
}
}
}
if ($this->drawPathList !== null) {
$renderedFrame->add(new RenderedObject($depthChain, $this->getObjectId(), $this->drawPathList, $colorTransform ?? ColorTransform::identity(), $matrixTransform ?? MatrixTransform::identity(), $clipPath));
} else {
foreach ($this->depthMap as $depth => $frame) {
if($frame instanceof ClippingFrame){ //Already processed
continue;
}
$clipPath = null;
foreach ($clipMap as $clipDepth => $clip) {
if ($clip->getClipDepth() > $depth and $clipDepth < $depth) {
$clipPath = $clipPath === null ? $clipPaths[$clipDepth] : $clipShape->intersect($clipPath);
}
}
$objects = $frame->render($depth, $depthChain, $colorTransform, $matrixTransform)->getObjects();
foreach ($objects as $object) {
if ($object->clip !== null and $clipPath !== null) {

View file

@ -117,33 +117,12 @@ class ViewLayout {
}
} else {
$frame = new ViewFrame($this->getObjectId(), null);
/** @var ClippingViewLayout[] $clipMap */
$clipMap = [];
/** @var ViewFrame[] $clipFrame */
$clipFrame = [];
ksort($this->depthMap);
foreach ($this->depthMap as $depth => $child) {
if ($child instanceof ClippingViewLayout) {
$clipMap[$depth] = $child;
$clipFrame[$depth] = $child->nextFrame($actionList);
} else {
/** @var ViewFrame[] $clips */
$clips = []; //TODO: make something else?
foreach ($clipMap as $clipDepth => $clip) {
//$targetDepth = $clip->getClipDepth() + $clipDepth;
if ($clip->getClipDepth() > $depth and $clipDepth < $depth) {
$clips[$clipDepth] = $clipFrame[$clipDepth];
}
}
$f = $child->nextFrame($actionList);
if (count($clips) > 0) {
$f->setClipDepthMap($clips);
}
$frame->addChild($depth, $f);
}
$f = $child->nextFrame($actionList);
$frame->addChild($depth, $f);
}
}