swf2ass/src/ViewFrame.php

136 lines
4.8 KiB
PHP

<?php
namespace swf2ass;
class ViewFrame {
private int $objectId;
/** @var ViewFrame[] */
private array $depthMap = [];
private ?DrawPathList $drawPathList;
private ?ColorTransform $colorTransform = null;
private ?MatrixTransform $matrixTransform = null;
public function __construct(int $objectId, ?DrawPathList $drawPathList) {
$this->objectId = $objectId;
$this->drawPathList = $drawPathList;
}
public function getDrawPathList() : ?DrawPathList{
return $this->drawPathList;
}
public function getObjectId(): int {
return $this->objectId;
}
public function addChild(int $depth, ViewFrame $frame) {
if ($this->drawPathList !== null) {
throw new \Exception();
}
$this->depthMap[$depth] = $frame;
}
/**
* @return ViewFrame[]
*/
public function getDepthMap(): array {
return $this->depthMap;
}
public function setColorTransform(?ColorTransform $transform) {
$this->colorTransform = $transform;
}
public function setMatrixTransform(?MatrixTransform $transform) {
$this->matrixTransform = $transform;
}
public function getColorTransform(): ?ColorTransform {
return $this->colorTransform;
}
public function getMatrixTransform(): ?MatrixTransform {
return $this->matrixTransform;
}
public function render(int $baseDepth, array $depthChain, ?ColorTransform $parentColor, ?MatrixTransform $parentMatrix): RenderedFrame {
$depthChain[] = $baseDepth;
$matrixTransform = $parentMatrix;
if($this->matrixTransform !== null){
$matrixTransform = $parentMatrix !== null ? $this->matrixTransform->multiply($parentMatrix) : $this->matrixTransform;
}
$colorTransform = $parentColor;
if($this->colorTransform !== null){
$colorTransform = $parentColor !== null ? $parentColor->combine($this->colorTransform) : $this->colorTransform;
}
$renderedFrame = new RenderedFrame();
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 TODO: is this correct?
$clipShape->addShape($p->commands);
}
}
if (count($clipShape->shapes) > 0) {
$clipShape = $clipShape->applyMatrixTransform($clipObject->matrixTransform);
$clipPath = $clipPath === null ? $clipShape : $clipShape->intersect($clipPath);
}
}
if ($clipPath !== null) {
$clipPaths[$depth] = $clipPath;
}else{
unset($clipMap[$depth]); //TODO: ????
}
}
}
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) {
$object->clip = $object->clip->intersect($clipPath);
} else if ($clipPath !== null) {
$object->clip = $clipPath;
}
$renderedFrame->add($object);
}
}
}
return $renderedFrame;
}
}