140 lines
4.5 KiB
PHP
140 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace swf2ass;
|
|
|
|
|
|
class MatrixTransform {
|
|
private const IDENTITY = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
|
|
|
|
private Matrix2D $matrix;
|
|
|
|
public function __construct(?Vector2 $scale, ?Vector2 $rotateSkew, ?Vector2 $translation) {
|
|
$matrix = self::IDENTITY;
|
|
|
|
if ($scale !== null) {
|
|
$matrix[0][0] = $scale->x;
|
|
$matrix[1][1] = $scale->y;
|
|
}
|
|
if ($rotateSkew !== null) {
|
|
$matrix[1][0] = $rotateSkew->x;
|
|
$matrix[0][1] = $rotateSkew->y;
|
|
}
|
|
if ($translation !== null) {
|
|
$matrix[2][0] = $translation->x;
|
|
$matrix[2][1] = $translation->y;
|
|
}
|
|
$this->matrix = Matrix2D::from2DArray($matrix);
|
|
}
|
|
|
|
public static function identity(): MatrixTransform {
|
|
return new MatrixTransform(new Vector2(1, 1), new Vector2(0, 0), new Vector2(0, 0));
|
|
}
|
|
|
|
public function combine(MatrixTransform $other): MatrixTransform {
|
|
$result = clone $this;
|
|
$result->matrix = $this->matrix->product($other->matrix);
|
|
return $result;
|
|
}
|
|
|
|
public function getScaleX() {
|
|
return $this->matrix->get(new Vector2(0, 0));
|
|
}
|
|
|
|
public function getScaleY() {
|
|
return $this->matrix->get(new Vector2(1, 1));
|
|
}
|
|
|
|
public function getScale(): Vector2 {
|
|
return new Vector2($this->getScaleX(), $this->getScaleY());
|
|
}
|
|
|
|
public function getRotateSkewX() {
|
|
return $this->matrix->get(new Vector2(0, 1));
|
|
}
|
|
|
|
public function getRotateSkewY() {
|
|
return $this->matrix->get(new Vector2(1, 0));
|
|
}
|
|
|
|
public function getRotateSkew(): Vector2 {
|
|
return new Vector2($this->getRotateSkewX(), $this->getRotateSkewY());
|
|
}
|
|
|
|
public function getTranslationX() {
|
|
return $this->matrix->get(new Vector2(0, 2));
|
|
}
|
|
|
|
public function getTranslationY() {
|
|
return $this->matrix->get(new Vector2(1, 2));
|
|
}
|
|
|
|
public function getTranslation(): Vector2 {
|
|
return new Vector2($this->getTranslationX(), $this->getTranslationY());
|
|
}
|
|
|
|
public function applyToVector(Vector2 $vector): Vector2 {
|
|
$result = Matrix2D::from2DArray([[$vector->x, $vector->y, 1]])->product($this->matrix);
|
|
return new Vector2($result->get(new Vector2(0, 0)), $result->get(new Vector2(1, 0)));
|
|
/*
|
|
return
|
|
$vector->vectorMultiply($this->getScale()) //scale
|
|
->add($vector->vectorMultiply($this->getRotateSkew())->invert()) //skew
|
|
->add($this->getTranslation()); //translate
|
|
*/
|
|
}
|
|
|
|
public function applyToShape(Shape $shape): Shape {
|
|
$newShape = new Shape();
|
|
foreach ($shape->edges as $edge) {
|
|
$newShape->edges[] = $edge->applyMatrixTransform($this);
|
|
}
|
|
|
|
return $newShape;
|
|
}
|
|
|
|
public function applyToStyleContainer(StyleContainer $styles): StyleContainer {
|
|
if ($this->scale !== null) {
|
|
|
|
if ($this->scale->x < 0) {
|
|
$styles->fry = 180;
|
|
}
|
|
$styles->fscx = round(abs($this->scale->x) * 100, 2);
|
|
|
|
if ($this->scale->y < 0) {
|
|
$styles->frx = 180;
|
|
}
|
|
$styles->fscy = round(abs($this->scale->y) * 100, 2);
|
|
|
|
} else {
|
|
$styles->fry = null;
|
|
$styles->fscx = null;
|
|
$styles->frx = null;
|
|
$styles->fscy = null;
|
|
}
|
|
|
|
if ($this->skew !== null) {
|
|
$styles->fax = round($this->skew->x, 4);
|
|
$styles->fay = round($this->skew->y, 4);
|
|
} else {
|
|
$styles->fax = null;
|
|
$styles->fay = null;
|
|
}
|
|
|
|
if ($this->translation !== null) {
|
|
$styles->pos = ($styles->pos ?? new Vector2(0, 0))->add($this->translation);
|
|
} else {
|
|
$styles->pos = null;
|
|
}
|
|
|
|
return $styles;
|
|
}
|
|
|
|
public function equals(MatrixTransform $other, $epsilon = Constants::EPSILON): bool {
|
|
return $this->matrix->equals($other->matrix, $epsilon);
|
|
}
|
|
|
|
static function fromXML(\DOMElement $element): MatrixTransform {
|
|
return new MatrixTransform($element->hasAttribute("scaleX") ? new Vector2(floatval($element->getAttribute("scaleX")), floatval($element->getAttribute("scaleY"))) : null, $element->hasAttribute("skewX") ? new Vector2(floatval($element->getAttribute("skewX")), floatval($element->getAttribute("skewY"))) : null, $element->hasAttribute("transX") ? new Vector2(intval($element->getAttribute("transX")), intval($element->getAttribute("transY"))) : null,);
|
|
}
|
|
|
|
} |