1
0
mirror of https://github.com/Intervention/image.git synced 2025-08-27 15:50:09 +02:00

Geometry refactoring

This commit is contained in:
Oliver Vogel
2021-11-07 11:37:42 +00:00
parent 304d158fb0
commit 9ac8e765c2
4 changed files with 119 additions and 59 deletions

View File

@@ -11,7 +11,7 @@ class Resizer
* *
* @var SizeInterface * @var SizeInterface
*/ */
protected $size; protected $original;
/** /**
* Target size * Target size
@@ -20,20 +20,20 @@ class Resizer
*/ */
protected $target; protected $target;
public function __construct(SizeInterface $size) /**
* Create new instance
*
* @param SizeInterface $size
*/
public function __construct(SizeInterface $original)
{ {
$this->size = $size; $this->original = $original;
$this->target = new Size(0, 0); $this->target = new Size(0, 0);
} }
public static function fromSize(SizeInterface $size): self protected function copyOriginal(): SizeInterface
{ {
return new self($size); return new Size($this->original->getWidth(), $this->original->getHeight());
}
public function getSize(): SizeInterface
{
return $this->size;
} }
protected function hasTargetWidth(): bool protected function hasTargetWidth(): bool
@@ -81,14 +81,32 @@ class Resizer
public function setTargetSize(SizeInterface $size): self public function setTargetSize(SizeInterface $size): self
{ {
$this->target = $size; $this->target = new Size($size->getWidth(), $size->getHeight());
return $this; return $this;
} }
protected function getProportionalWidth(): int
{
if (! $this->hasTargetHeight()) {
return $this->original->getWidth();
}
return (int) round($this->target->getHeight() * $this->original->getAspectRatio());
}
protected function getProportionalHeight(): int
{
if (! $this->hasTargetWidth()) {
return $this->original->getHeight();
}
return (int) round($this->target->getWidth() / $this->original->getAspectRatio());
}
public function resize(): SizeInterface public function resize(): SizeInterface
{ {
$resized = clone $this->size; $resized = $this->copyOriginal();
if ($this->hasTargetWidth()) { if ($this->hasTargetWidth()) {
$resized->setWidth($this->target->getWidth()); $resized->setWidth($this->target->getWidth());
@@ -103,92 +121,82 @@ class Resizer
public function resizeDown(): SizeInterface public function resizeDown(): SizeInterface
{ {
$resized = $this->copyOriginal();
if ($this->hasTargetWidth()) { if ($this->hasTargetWidth()) {
$this->target->setWidth( $resized->setWidth(
min($this->target->getWidth(), $this->size->getWidth()) min($this->target->getWidth(), $this->original->getWidth())
); );
} }
if ($this->hasTargetHeight()) { if ($this->hasTargetHeight()) {
$this->target->setHeight( $resized->setHeight(
min($this->target->getHeight(), $this->size->getHeight()) min($this->target->getHeight(), $this->original->getHeight())
); );
} }
return $this->resize(); return $resized;
} }
public function scale(): SizeInterface public function scale(): SizeInterface
{ {
$resized = $this->copyOriginal();
if ($this->hasTargetWidth() && $this->hasTargetHeight()) { if ($this->hasTargetWidth() && $this->hasTargetHeight()) {
$this->target->setWidth(min( $resized->setWidth(min(
$this->getProportionalWidth(), $this->getProportionalWidth(),
$this->target->getWidth() $this->target->getWidth()
)); ));
$this->target->setHeight(min( $resized->setHeight(min(
$this->getProportionalHeight(), $this->getProportionalHeight(),
$this->target->getHeight() $this->target->getHeight()
)); ));
} elseif ($this->hasTargetWidth()) { } elseif ($this->hasTargetWidth()) {
$this->target->setHeight($this->getProportionalHeight()); $resized->setWidth($this->target->getWidth());
$resized->setHeight($this->getProportionalHeight());
} elseif ($this->hasTargetHeight()) { } elseif ($this->hasTargetHeight()) {
$this->target->setWidth($this->getProportionalWidth()); $resized->setWidth($this->getProportionalWidth());
$resized->setHeight($this->target->getHeight());
} }
return $this->resize(); return $resized;
} }
public function scaleDown(): SizeInterface public function scaleDown(): SizeInterface
{ {
$resized = $this->copyOriginal();
if ($this->hasTargetWidth() && $this->hasTargetHeight()) { if ($this->hasTargetWidth() && $this->hasTargetHeight()) {
$this->target->setWidth(min( $resized->setWidth(min(
$this->getProportionalWidth(), $this->getProportionalWidth(),
$this->target->getWidth(), $this->target->getWidth(),
$this->size->getWidth() $this->original->getWidth()
)); ));
$this->target->setHeight(min( $resized->setHeight(min(
$this->getProportionalHeight(), $this->getProportionalHeight(),
$this->target->getHeight(), $this->target->getHeight(),
$this->size->getHeight() $this->original->getHeight()
)); ));
} elseif ($this->hasTargetWidth()) { } elseif ($this->hasTargetWidth()) {
$this->target->setWidth(min( $resized->setWidth(min(
$this->target->getWidth(), $this->target->getWidth(),
$this->size->getWidth() $this->original->getWidth()
)); ));
$this->target->setHeight(min( $resized->setHeight(min(
$this->getProportionalHeight(), $this->getProportionalHeight(),
$this->size->getHeight() $this->original->getHeight()
)); ));
} elseif ($this->hasTargetHeight()) { } elseif ($this->hasTargetHeight()) {
$this->target->setWidth(min( $resized->setWidth(min(
$this->getProportionalWidth(), $this->getProportionalWidth(),
$this->size->getWidth() $this->original->getWidth()
)); ));
$this->target->setHeight(min( $resized->setHeight(min(
$this->target->getHeight(), $this->target->getHeight(),
$this->size->getHeight() $this->original->getHeight()
)); ));
} }
return $this->resize(); return $resized;
}
protected function getProportionalWidth(): int
{
if (! $this->hasTargetHeight()) {
return $this->size->getWidth();
}
return (int) round($this->target->getHeight() * $this->size->getAspectRatio());
}
protected function getProportionalHeight(): int
{
if (! $this->hasTargetWidth()) {
return $this->size->getHeight();
}
return (int) round($this->target->getWidth() / $this->size->getAspectRatio());
} }
} }

View File

@@ -38,6 +38,13 @@ class Size implements SizeInterface
return $this->pivot; return $this->pivot;
} }
public function setPivot(PointInterface $pivot): self
{
$this->pivot = $pivot;
return $this;
}
public function setWidth(int $width): SizeInterface public function setWidth(int $width): SizeInterface
{ {
$this->width = $width; $this->width = $width;

View File

@@ -8,6 +8,13 @@ use PHPUnit\Framework\TestCase;
class ResizerTest extends TestCase class ResizerTest extends TestCase
{ {
public function testConstructor(): void
{
$size = new Size(300, 200);
$resizer = new Resizer($size);
$this->assertInstanceOf(Resizer::class, $resizer);
}
public function testSetTargetSizeByArray() public function testSetTargetSizeByArray()
{ {
$resizer = new Resizer(new Size(300, 200)); $resizer = new Resizer(new Size(300, 200));
@@ -63,22 +70,16 @@ class ResizerTest extends TestCase
$resizer = new Resizer($size); $resizer = new Resizer($size);
$resizer->width(150); $resizer->width(150);
$result = $resizer->resize(); $result = $resizer->resize();
$original = $resizer->getSize();
$this->assertEquals(150, $result->getWidth()); $this->assertEquals(150, $result->getWidth());
$this->assertEquals(200, $result->getHeight()); $this->assertEquals(200, $result->getHeight());
$this->assertEquals(300, $original->getWidth());
$this->assertEquals(200, $original->getHeight());
$size = new Size(300, 200); $size = new Size(300, 200);
$resizer = new Resizer($size); $resizer = new Resizer($size);
$resizer->width(20); $resizer->width(20);
$resizer->height(10); $resizer->height(10);
$result = $resizer->resize(); $result = $resizer->resize();
$original = $resizer->getSize();
$this->assertEquals(20, $result->getWidth()); $this->assertEquals(20, $result->getWidth());
$this->assertEquals(10, $result->getHeight()); $this->assertEquals(10, $result->getHeight());
$this->assertEquals(300, $original->getWidth());
$this->assertEquals(200, $original->getHeight());
} }
public function testResizeDown() public function testResizeDown()
@@ -367,4 +368,5 @@ class ResizerTest extends TestCase
$this->assertEquals(13, $result->getWidth()); $this->assertEquals(13, $result->getWidth());
$this->assertEquals(10, $result->getHeight()); $this->assertEquals(10, $result->getHeight());
} }
} }

View File

@@ -143,4 +143,47 @@ class SizeTest extends TestCase
$this->assertInstanceOf(Size::class, $result); $this->assertInstanceOf(Size::class, $result);
} }
public function testRelativePosition(): void
{
$container = new Size(800, 600);
$input = new Size(200, 100);
$container->align('top-left');
$input->align('top-left');
$pos = $container->relativePosition($input);
$this->assertEquals(0, $pos->getX());
$this->assertEquals(0, $pos->getY());
$container = new Size(800, 600);
$input = new Size(200, 100);
$container->align('center');
$input->align('top-left');
$pos = $container->relativePosition($input);
$this->assertEquals(400, $pos->getX());
$this->assertEquals(300, $pos->getY());
$container = new Size(800, 600);
$input = new Size(200, 100);
$container->align('bottom-right');
$input->align('top-right');
$pos = $container->relativePosition($input);
$this->assertEquals(600, $pos->getX());
$this->assertEquals(600, $pos->getY());
$container = new Size(800, 600);
$input = new Size(200, 100);
$container->align('center');
$input->align('center');
$pos = $container->relativePosition($input);
$this->assertEquals(300, $pos->getX());
$this->assertEquals(250, $pos->getY());
$container = new Size(100, 200);
$input = new Size(100, 100);
$container->align('center');
$input->align('center');
$pos = $container->relativePosition($input);
$this->assertEquals(0, $pos->getX());
$this->assertEquals(50, $pos->getY());
}
} }