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

Implement FontWriter Modifier

This commit is contained in:
Oliver Vogel
2022-06-23 12:04:04 +02:00
parent afec510ad0
commit 7abf23edbb
10 changed files with 942 additions and 54 deletions

View File

@@ -3,6 +3,8 @@
namespace Intervention\Image\Drivers\Gd; namespace Intervention\Image\Drivers\Gd;
use Intervention\Image\Drivers\Abstract\AbstractFont; use Intervention\Image\Drivers\Abstract\AbstractFont;
use Intervention\Image\Geometry\Point;
use Intervention\Image\Geometry\Polygon;
use Intervention\Image\Geometry\Size; use Intervention\Image\Geometry\Size;
class Font extends AbstractFont class Font extends AbstractFont
@@ -15,9 +17,9 @@ class Font extends AbstractFont
/** /**
* Calculate size of bounding box of current text * Calculate size of bounding box of current text
* *
* @return Size * @return Polygon
*/ */
public function getBoxSize(): Size public function getBoxSize(): Polygon
{ {
if (!$this->hasFilename()) { if (!$this->hasFilename()) {
// calculate box size from gd font // calculate box size from gd font
@@ -27,18 +29,26 @@ class Font extends AbstractFont
$box->setWidth($chars * $this->getGdFontWidth()); $box->setWidth($chars * $this->getGdFontWidth());
$box->setHeight($this->getGdFontHeight()); $box->setHeight($this->getGdFontHeight());
} }
return $box; return $box->toPolygon();
} }
// calculate box size from font file // calculate box size from font file with angle 0
$box = imageftbbox( $box = imageftbbox(
$this->getSize(), $this->getSize(),
$this->getAngle(), 0,
$this->getFilename(), $this->getFilename(),
$this->getText() $this->getText()
); );
return new Size(abs($box[0] - $box[2]), abs($box[1] - $box[7])); // build polygon from points
$polygon = new Polygon();
$polygon->addPoint(new Point($box[6], $box[7]));
$polygon->addPoint(new Point($box[4], $box[5]));
$polygon->addPoint(new Point($box[2], $box[3]));
$polygon->addPoint(new Point($box[0], $box[1]));
return $polygon;
} }
public function getGdFont(): int public function getGdFont(): int

View File

@@ -19,13 +19,12 @@ class TextWriter implements ModifierInterface
public function apply(ImageInterface $image): ImageInterface public function apply(ImageInterface $image): ImageInterface
{ {
$position = $this->getAlignedPosition(); $position = $this->getAlignedPosition();
foreach ($image as $frame) { foreach ($image as $frame) {
if ($this->font->hasFilename()) { if ($this->font->hasFilename()) {
imagettftext( imagettftext(
$frame->getCore(), $frame->getCore(),
$this->font->getSize(), $this->font->getSize(),
$this->font->getAngle(), $this->font->getAngle() * (-1),
$position->getX(), $position->getX(),
$position->getY(), $position->getY(),
$this->font->getColor()->toInt(), $this->font->getColor()->toInt(),
@@ -47,34 +46,18 @@ class TextWriter implements ModifierInterface
return $image; return $image;
} }
protected function getAlignedPosition(): Point public function getAlignedPosition(): Point
{ {
$position = $this->position; $poly = $this->font->getBoxSize();
$box = $this->font->getBoxSize(); $poly->setPivotPoint($this->position);
// adjust x pos $poly->align($this->font->getAlign());
switch ($this->font->getAlign()) { $poly->valign($this->font->getValign());
case 'center':
$position->setX($position->getX() - round($box->getWidth() / 2));
break;
case 'right': if ($this->font->getAngle() != 0) {
$position->setX($position->getX() - $box->getWidth()); $poly->rotate($this->font->getAngle());
break;
} }
// adjust y pos return $poly->last();
switch ($this->font->getValign()) {
case 'top':
$position->setY($position->getY() + $box->getHeight());
break;
case 'middle':
case 'center':
$position->setY($position->getY() + round($box->getHeight() / 2));
break;
}
return $position;
} }
} }

View File

@@ -6,6 +6,7 @@ use Imagick;
use ImagickDraw; use ImagickDraw;
use Intervention\Image\Drivers\Abstract\AbstractFont; use Intervention\Image\Drivers\Abstract\AbstractFont;
use Intervention\Image\Exceptions\FontException; use Intervention\Image\Exceptions\FontException;
use Intervention\Image\Geometry\Polygon;
use Intervention\Image\Geometry\Size; use Intervention\Image\Geometry\Size;
class Font extends AbstractFont class Font extends AbstractFont
@@ -13,7 +14,7 @@ class Font extends AbstractFont
public function toImagickDraw(): ImagickDraw public function toImagickDraw(): ImagickDraw
{ {
if (!$this->hasFilename()) { if (!$this->hasFilename()) {
throw new FontException('No font file.'); throw new FontException('No font file specified.');
} }
$draw = new ImagickDraw(); $draw = new ImagickDraw();
@@ -50,14 +51,13 @@ class Font extends AbstractFont
/** /**
* Calculate box size of current font * Calculate box size of current font
* *
* @return Size * @return Polygon
*/ */
public function getBoxSize(): Size public function getBoxSize(): Polygon
{ {
$foo = null;
// no text - no box size // no text - no box size
if (mb_strlen($this->getText()) === 0) { if (mb_strlen($this->getText()) === 0) {
return new Size(0, 0); return (new Size(0, 0))->toPolygon();
} }
$dimensions = (new Imagick())->queryFontMetrics( $dimensions = (new Imagick())->queryFontMetrics(
@@ -65,9 +65,9 @@ class Font extends AbstractFont
$this->getText() $this->getText()
); );
return new Size( return (new Size(
intval(abs($dimensions['textWidth'])), intval(round(abs($dimensions['boundingBox']['x1'] - $dimensions['boundingBox']['x2']))),
intval(abs($dimensions['textHeight'])) intval(round(abs($dimensions['boundingBox']['y1'] - $dimensions['boundingBox']['y2']))),
); ))->toPolygon();
} }
} }

View File

@@ -18,15 +18,13 @@ class TextWriter implements ModifierInterface
public function apply(ImageInterface $image): ImageInterface public function apply(ImageInterface $image): ImageInterface
{ {
$draw = $this->font->toImagickDraw();
$position = $this->getAlignedPosition(); $position = $this->getAlignedPosition();
foreach ($image as $frame) { foreach ($image as $frame) {
$frame->getCore()->annotateImage( $frame->getCore()->annotateImage(
$draw, $this->font->toImagickDraw(),
$position->getX(), $position->getX(),
$position->getY(), $position->getY(),
$this->font->getAngle(), $this->font->getAngle() * (-1),
$this->font->getText() $this->font->getText()
); );
} }
@@ -42,12 +40,12 @@ class TextWriter implements ModifierInterface
// adjust y pos // adjust y pos
switch ($this->font->getValign()) { switch ($this->font->getValign()) {
case 'top': case 'top':
$position->setY($position->getY() + $box->getHeight()); $position->setY($position->getY() + $box->height());
break; break;
case 'middle': case 'middle':
case 'center': case 'center':
$position->setY($position->getY() + round($box->getHeight() / 2)); $position->setY(intval($position->getY() + round($box->height() / 2)));
break; break;
} }

View File

@@ -58,7 +58,7 @@ class Point implements PointInterface
/** /**
* Move X coordinate * Move X coordinate
* *
* @param integer $x * @param integer $value
*/ */
public function moveX(int $value): self public function moveX(int $value): self
{ {
@@ -70,7 +70,7 @@ class Point implements PointInterface
/** /**
* Move Y coordinate * Move Y coordinate
* *
* @param integer $y * @param integer $value
*/ */
public function moveY(int $value): self public function moveY(int $value): self
{ {
@@ -79,6 +79,11 @@ class Point implements PointInterface
return $this; return $this;
} }
public function move(int $x, int $y): self
{
return $this->moveX($x)->moveY($y);
}
/** /**
* Sets both X and Y coordinate * Sets both X and Y coordinate
* *
@@ -107,8 +112,8 @@ class Point implements PointInterface
$cos = round(cos(deg2rad($angle)), 6); $cos = round(cos(deg2rad($angle)), 6);
return $this->setPosition( return $this->setPosition(
$cos * ($this->x - $pivot->x) - $sin * ($this->y - $pivot->y) + $pivot->x, intval($cos * ($this->x - $pivot->x) - $sin * ($this->y - $pivot->y) + $pivot->x),
$sin * ($this->x - $pivot->x) + $cos * ($this->y - $pivot->y) + $pivot->y intval($sin * ($this->x - $pivot->x) + $cos * ($this->y - $pivot->y) + $pivot->y)
); );
} }
} }

455
src/Geometry/Polygon.php Normal file
View File

@@ -0,0 +1,455 @@
<?php
namespace Intervention\Image\Geometry;
use ArrayAccess;
use Countable;
class Polygon implements Countable, ArrayAccess
{
public function __construct(
protected array $points = [],
protected ?Point $pivot = null
) {
$this->pivot = $pivot ? $pivot : new Point();
}
/**
* Return current pivot point
*
* @return Point
*/
public function getPivotPoint(): Point
{
return $this->pivot;
}
/**
* Change pivot point to given point
*
* @param Point $pivot
* @return Polygon
*/
public function setPivotPoint(Point $pivot): self
{
$this->pivot = $pivot;
return $this;
}
/**
* Return first point of polygon
*
* @return ?Point
*/
public function first(): ?Point
{
if ($point = reset($this->points)) {
return $point;
}
return null;
}
/**
* Return last point of polygon
*
* @return ?Point
*/
public function last(): ?Point
{
if ($point = end($this->points)) {
return $point;
}
return null;
}
/**
* Return polygon's point count
*
* @return int
*/
public function count(): int
{
return count($this->points);
}
/**
* Determine if point exists at given offset
*
* @param mixed $offset
* @return bool
*/
public function offsetExists($offset): bool
{
return array_key_exists($offset, $this->points);
}
/**
* Return point at given offset
*
* @param mixed $offset
* @return Point
*/
public function offsetGet($offset)
{
return $this->points[$offset];
}
/**
* Set point at given offset
*
* @param mixed $offset
* @param Point $value
* @return void
*/
public function offsetSet($offset, $value): void
{
$this->points[$offset] = $value;
}
/**
* Unset offset at given offset
*
* @param mixed $offset
* @return void
*/
public function offsetUnset($offset): void
{
unset($this->points[$offset]);
}
/**
* Add given point to polygon
*
* @param Point $point
* @return Polygon
*/
public function addPoint(Point $point): self
{
$this->points[] = $point;
return $this;
}
/**
* Calculate total horizontal span of polygon
*
* @return int
*/
public function width(): int
{
return abs($this->getMostLeftPoint()->getX() - $this->getMostRightPoint()->getX());
}
/**
* Calculate total vertical span of polygon
*
* @return int
*/
public function height(): int
{
return abs($this->getMostBottomPoint()->getY() - $this->getMostTopPoint()->getY());
}
/**
* Return most left point of all points in polygon
*
* @return Point
*/
public function getMostLeftPoint(): Point
{
$points = [];
foreach ($this->points as $point) {
$points[] = $point;
}
usort($points, function ($a, $b) {
if ($a->getX() === $b->getX()) {
return 0;
}
return ($a->getX() < $b->getX()) ? -1 : 1;
});
return $points[0];
}
/**
* Return most right point in polygon
*
* @return Point
*/
public function getMostRightPoint(): Point
{
$points = [];
foreach ($this->points as $point) {
$points[] = $point;
}
usort($points, function ($a, $b) {
if ($a->getX() === $b->getX()) {
return 0;
}
return ($a->getX() > $b->getX()) ? -1 : 1;
});
return $points[0];
}
/**
* Return most top point in polygon
*
* @return Point
*/
public function getMostTopPoint(): Point
{
$points = [];
foreach ($this->points as $point) {
$points[] = $point;
}
usort($points, function ($a, $b) {
if ($a->getY() === $b->getY()) {
return 0;
}
return ($a->getY() > $b->getY()) ? -1 : 1;
});
return $points[0];
}
/**
* Return most bottom point in polygon
*
* @return Point
*/
public function getMostBottomPoint(): Point
{
$points = [];
foreach ($this->points as $point) {
$points[] = $point;
}
usort($points, function ($a, $b) {
if ($a->getY() === $b->getY()) {
return 0;
}
return ($a->getY() < $b->getY()) ? -1 : 1;
});
return $points[0];
}
/**
* Create and return point in absolute center of the polygon
*
* @return Point
*/
public function getCenterPoint(): Point
{
return new Point(
$this->getMostRightPoint()->getX() - (intval(round($this->width() / 2))),
$this->getMostTopPoint()->getY() - (intval(round($this->height() / 2)))
);
}
/**
* Align pivot point to given horizontal position
*
* @param string $position
* @return Polygon
*/
public function alignPivot(string $position): self
{
switch (strtolower($position)) {
case 'center':
$this->pivot->setX(
intval(($this->getMostRightPoint()->getX() + $this->getMostLeftPoint()->getX()) / 2)
);
break;
case 'right':
$this->pivot->setX(
$this->getMostRightPoint()->getX()
);
break;
case 'left':
$this->pivot->setX(
$this->getMostLeftPoint()->getX()
);
break;
}
return $this;
}
/**
* Align pivot point to given vertical position
*
* @param string $position
* @return Polygon
*/
public function valignPivot(string $position): self
{
switch (strtolower($position)) {
case 'center':
case 'middle':
$this->pivot->setY(
intval(($this->getMostTopPoint()->getY() + $this->getMostBottomPoint()->getY()) / 2)
);
break;
case 'top':
$this->pivot->setY(
$this->getMostTopPoint()->getY()
);
break;
case 'bottom':
$this->pivot->setY(
$this->getMostBottomPoint()->getY()
);
break;
}
return $this;
}
/**
* Align all points of polygon horizontally to given position around pivot point
*
* @param string $position
* @return Polygon
*/
public function align(string $position): self
{
switch (strtolower($position)) {
case 'center':
case 'middle':
$diff = ($this->getCenterPoint()->getX() - $this->pivot->getX());
break;
case 'right':
$diff = ($this->getMostRightPoint()->getX() - $this->pivot->getX());
break;
default:
case 'left':
$diff = ($this->getMostLeftPoint()->getX() - $this->pivot->getX());
break;
}
foreach ($this->points as $point) {
$point->setX($point->getX() - $diff);
}
return $this;
}
/**
* Align all points of polygon vertically to given position around pivot point
*
* @param string $position
* @return Polygon
*/
public function valign(string $position): self
{
switch (strtolower($position)) {
case 'center':
case 'middle':
$diff = ($this->getCenterPoint()->getY() - $this->pivot->getY());
break;
case 'top':
$diff = ($this->getMostTopPoint()->getY() - $this->pivot->getY()) - $this->height();
break;
default:
case 'bottom':
$diff = ($this->getMostBottomPoint()->getY() - $this->pivot->getY()) + $this->height();
break;
}
foreach ($this->points as $point) {
$point->setY($point->getY() - $diff);
}
return $this;
}
/**
* Rotate points of polygon around pivot point with given angle
*
* @param float $angle
* @return Polygon
*/
public function rotate(float $angle): self
{
$sin = sin(deg2rad($angle));
$cos = cos(deg2rad($angle));
foreach ($this->points as $point) {
// translate point to pivot
$point->setX($point->getX() - $this->pivot->getX());
$point->setY($point->getY() - $this->pivot->getY());
// rotate point
$x = $point->getX() * $cos - $point->getY() * $sin;
$y = $point->getX() * $sin + $point->getY() * $cos;
// translate point back
$point->setX($x + $this->pivot->getX());
$point->setY($y + $this->pivot->getY());
}
return $this;
}
/**
* Move all points by given amount on the x-axis
*
* @param int $amount
* @return Polygon
*/
public function movePointsX(int $amount): self
{
foreach ($this->points as $point) {
$point->moveX($amount);
}
return $this;
}
/**
* Move all points by given amount on the y-axis
*
* @param int $amount
* @return Polygon
*/
public function movePointsY(int $amount): self
{
foreach ($this->points as $point) {
$point->moveY($amount);
}
return $this;
}
/**
* Return array of all x/y values of all points of polygon
*
* @return array
*/
public function toArray(): array
{
$coordinates = [];
foreach ($this->points as $point) {
$coordinates[] = $point->getX();
$coordinates[] = $point->getY();
}
return $coordinates;
}
}

View File

@@ -209,6 +209,30 @@ class Size implements SizeInterface
return new Point($x, $y); return new Point($x, $y);
} }
public function toPolygon(): Polygon
{
$polygon = new Polygon([
$this->pivot // top/left
], $this->pivot);
// top/right
$polygon->addPoint(
new Point($this->pivot->getX() + $this->getWidth(), $this->pivot->getY())
);
// bottom/right
$polygon->addPoint(
new Point($this->pivot->getX() + $this->getWidth(), $this->pivot->getY() - $this->getHeight())
);
// bottom/left
$polygon->addPoint(
new Point($this->pivot->getX(), $this->pivot->getY() - $this->getHeight())
);
return $polygon;
}
protected function getResizer(?int $width = null, ?int $height = null): Resizer protected function getResizer(?int $width = null, ?int $height = null): Resizer
{ {
return new Resizer($width, $height); return new Resizer($width, $height);

View File

@@ -2,7 +2,7 @@
namespace Intervention\Image\Interfaces; namespace Intervention\Image\Interfaces;
use Intervention\Image\Geometry\Size; use Intervention\Image\Geometry\Polygon;
use Intervention\Image\Interfaces\ColorInterface; use Intervention\Image\Interfaces\ColorInterface;
interface FontInterface interface FontInterface
@@ -19,5 +19,5 @@ interface FontInterface
public function hasFilename(): bool; public function hasFilename(): bool;
public function align(string $align): self; public function align(string $align): self;
public function getAlign(): string; public function getAlign(): string;
public function getBoxSize(): Size; public function getBoxSize(): Polygon;
} }

View File

@@ -0,0 +1,397 @@
<?php
namespace Intervention\Image\Tests\Geometry;
use Intervention\Image\Geometry\{Point, Polygon};
use Intervention\Image\Tests\TestCase;
/**
* @covers \Intervention\Image\Geometry\Polygon
*/
class PolygonTest extends TestCase
{
public function testConstructor(): void
{
$poly = new Polygon([]);
$this->assertInstanceOf(Polygon::class, $poly);
$this->assertEquals(0, $poly->count());
}
public function testCount(): void
{
$poly = new Polygon([new Point(), new Point()]);
$this->assertEquals(2, $poly->count());
}
public function testArrayAccess(): void
{
$poly = new Polygon([new Point(), new Point()]);
$this->assertInstanceOf(Point::class, $poly[0]);
$this->assertInstanceOf(Point::class, $poly[1]);
}
public function testAddPoint(): void
{
$poly = new Polygon([new Point(), new Point()]);
$this->assertEquals(2, $poly->count());
$result = $poly->addPoint(new Point());
$this->assertEquals(3, $poly->count());
$this->assertInstanceOf(Polygon::class, $result);
}
public function testGetCenterPoint(): void
{
$poly = new Polygon([
new Point(0, 0),
new Point(20, 0),
new Point(20, -20),
new Point(0, -20),
]);
$result = $poly->getCenterPoint();
$this->assertEquals(10, $result->getX());
$this->assertEquals(-10, $result->getY());
$poly = new Polygon([
new Point(0, 0),
new Point(300, 0),
new Point(300, -200),
new Point(0, -200),
], new Point(0, 0));
$result = $poly->getCenterPoint();
$this->assertEquals(150, $result->getX());
$this->assertEquals(-100, $result->getY());
}
public function testWidth(): void
{
$poly = new Polygon([
new Point(12, 45),
new Point(-23, -49),
new Point(3, 566),
]);
$this->assertEquals($poly->width(), 35);
}
public function testHeight(): void
{
$poly = new Polygon([
new Point(12, 45),
new Point(-23, -49),
new Point(3, 566),
]);
$this->assertEquals(615, $poly->height());
$poly = new Polygon([
new Point(250, 207),
new Point(473, 207),
new Point(473, 250),
new Point(250, 250),
], new Point(250, 250));
$this->assertEquals(43, $poly->height());
}
public function testFirst(): void
{
$poly = new Polygon([
new Point(12, 45),
new Point(-23, -49),
new Point(3, 566),
]);
$this->assertEquals(12, $poly->first()->getX());
$this->assertEquals(45, $poly->first()->getY());
}
public function testLast(): void
{
$poly = new Polygon([
new Point(12, 45),
new Point(-23, -49),
new Point(3, 566),
]);
$this->assertEquals(3, $poly->last()->getX());
$this->assertEquals(566, $poly->last()->getY());
}
public function testGetPivotPoint(): void
{
$poly = new Polygon();
$this->assertInstanceOf(Point::class, $poly->getPivotPoint());
}
public function testAlignPivot(): void
{
$poly = new Polygon([
new Point(12, 45),
new Point(-24, -49),
new Point(3, 566),
]);
$this->assertEquals(0, $poly->getPivotPoint()->getX());
$this->assertEquals(0, $poly->getPivotPoint()->getY());
$result = $poly->alignPivot('center');
$this->assertInstanceOf(Polygon::class, $result);
$this->assertEquals(-6, $result->getPivotPoint()->getX());
$this->assertEquals(0, $result->getPivotPoint()->getY());
}
public function testValignPivot(): void
{
$poly = new Polygon([
new Point(12, 45),
new Point(-24, -50),
new Point(3, 566),
]);
$this->assertEquals(0, $poly->getPivotPoint()->getX());
$this->assertEquals(0, $poly->getPivotPoint()->getY());
$result = $poly->valignPivot('middle');
$this->assertInstanceOf(Polygon::class, $result);
$this->assertEquals(0, $result->getPivotPoint()->getX());
$this->assertEquals(258, $result->getPivotPoint()->getY());
}
public function testGetMostLeftPoint(): void
{
$poly = new Polygon([
new Point(0, 0),
new Point(300, 0),
new Point(300, -200),
new Point(-32, -200),
], new Point(0, 0));
$result = $poly->getMostLeftPoint();
$this->assertEquals(-32, $result->getX());
$this->assertEquals(-200, $result->getY());
}
public function testGetMostRightPoint(): void
{
$poly = new Polygon([
new Point(0, 0),
new Point(350, 0),
new Point(300, -200),
new Point(-32, -200),
], new Point(0, 0));
$result = $poly->getMostRightPoint();
$this->assertEquals(350, $result->getX());
$this->assertEquals(0, $result->getY());
}
public function testGetMostTopPoint(): void
{
$poly = new Polygon([
new Point(0, 100),
new Point(350, 0),
new Point(300, -200),
new Point(-32, 200),
], new Point(0, 0));
$result = $poly->getMostTopPoint();
$this->assertEquals(-32, $result->getX());
$this->assertEquals(200, $result->getY());
}
public function testGetMostBottomPoint(): void
{
$poly = new Polygon([
new Point(0, 100),
new Point(350, 0),
new Point(300, -200),
new Point(-32, 200),
], new Point(0, 0));
$result = $poly->getMostBottomPoint();
$this->assertEquals(300, $result->getX());
$this->assertEquals(-200, $result->getY());
}
public function testAlignCenter(): void
{
$poly = new Polygon([
new Point(0, 0),
new Point(300, 0),
new Point(300, -200),
new Point(0, -200),
], new Point(0, 0));
$result = $poly->align('center');
$this->assertInstanceOf(Polygon::class, $result);
$this->assertEquals(-150, $result[0]->getX());
$this->assertEquals(0, $result[0]->getY());
$this->assertEquals(150, $result[1]->getX());
$this->assertEquals(0, $result[1]->getY());
$this->assertEquals(150, $result[2]->getX());
$this->assertEquals(-200, $result[2]->getY());
$this->assertEquals(-150, $result[3]->getX());
$this->assertEquals(-200, $result[3]->getY());
$poly = new Polygon([
new Point(0, 0),
new Point(300, 0),
new Point(300, -200),
new Point(0, -200),
], new Point(-1000, -1000));
$result = $poly->align('center');
$this->assertInstanceOf(Polygon::class, $result);
$this->assertEquals(-1150, $result[0]->getX());
$this->assertEquals(0, $result[0]->getY());
$this->assertEquals(-850, $result[1]->getX());
$this->assertEquals(0, $result[1]->getY());
$this->assertEquals(-850, $result[2]->getX());
$this->assertEquals(-200, $result[2]->getY());
$this->assertEquals(-1150, $result[3]->getX());
$this->assertEquals(-200, $result[3]->getY());
}
public function testAlignLeft(): void
{
$poly = new Polygon([
new Point(0, 0),
new Point(300, 0),
new Point(300, -200),
new Point(0, -200),
], new Point(100, 100));
$result = $poly->align('left');
$this->assertInstanceOf(Polygon::class, $result);
$this->assertEquals(100, $result[0]->getX());
$this->assertEquals(0, $result[0]->getY());
$this->assertEquals(400, $result[1]->getX());
$this->assertEquals(0, $result[1]->getY());
$this->assertEquals(400, $result[2]->getX());
$this->assertEquals(-200, $result[2]->getY());
$this->assertEquals(100, $result[3]->getX());
$this->assertEquals(-200, $result[3]->getY());
$poly = new Polygon([
new Point(0, 0),
new Point(300, 0),
new Point(300, -200),
new Point(0, -200),
], new Point(-1000, -1000));
$result = $poly->align('left');
$this->assertInstanceOf(Polygon::class, $result);
$this->assertEquals(-1000, $result[0]->getX());
$this->assertEquals(0, $result[0]->getY());
$this->assertEquals(-700, $result[1]->getX());
$this->assertEquals(0, $result[1]->getY());
$this->assertEquals(-700, $result[2]->getX());
$this->assertEquals(-200, $result[2]->getY());
$this->assertEquals(-1000, $result[3]->getX());
$this->assertEquals(-200, $result[3]->getY());
}
public function testAlignRight(): void
{
$poly = new Polygon([
new Point(0, 0),
new Point(300, 0),
new Point(300, -200),
new Point(0, -200),
], new Point(100, 100));
$result = $poly->align('right');
$this->assertInstanceOf(Polygon::class, $result);
$this->assertEquals(-200, $result[0]->getX());
$this->assertEquals(0, $result[0]->getY());
$this->assertEquals(100, $result[1]->getX());
$this->assertEquals(0, $result[1]->getY());
$this->assertEquals(100, $result[2]->getX());
$this->assertEquals(-200, $result[2]->getY());
$this->assertEquals(-200, $result[3]->getX());
$this->assertEquals(-200, $result[3]->getY());
$poly = new Polygon([
new Point(0, 0),
new Point(300, 0),
new Point(300, -200),
new Point(0, -200),
], new Point(-1000, -1000));
$result = $poly->align('right');
$this->assertInstanceOf(Polygon::class, $result);
$this->assertEquals(-1300, $result[0]->getX());
$this->assertEquals(0, $result[0]->getY());
$this->assertEquals(-1000, $result[1]->getX());
$this->assertEquals(0, $result[1]->getY());
$this->assertEquals(-1000, $result[2]->getX());
$this->assertEquals(-200, $result[2]->getY());
$this->assertEquals(-1300, $result[3]->getX());
$this->assertEquals(-200, $result[3]->getY());
}
public function testValignMiddle(): void
{
$poly = new Polygon([
new Point(-21, -22),
new Point(91, -135),
new Point(113, -113),
new Point(0, 0),
], new Point(250, 250));
$result = $poly->valign('middle');
$this->assertInstanceOf(Polygon::class, $result);
$this->assertEquals(-21, $result[0]->getX());
$this->assertEquals(296, $result[0]->getY());
$this->assertEquals(91, $result[1]->getX());
$this->assertEquals(183, $result[1]->getY());
$this->assertEquals(113, $result[2]->getX());
$this->assertEquals(205, $result[2]->getY());
$this->assertEquals(0, $result[3]->getX());
$this->assertEquals(318, $result[3]->getY());
}
public function testRotate(): void
{
$poly = new Polygon([
new Point(0, 0),
new Point(50, 0),
new Point(50, -50),
new Point(0, -50),
]);
$result = $poly->rotate(45);
$this->assertInstanceOf(Polygon::class, $result);
$this->assertEquals(0, $result[0]->getX());
$this->assertEquals(0, $result[0]->getY());
$this->assertEquals(35, $result[1]->getX());
$this->assertEquals(35, $result[1]->getY());
$this->assertEquals(70, $result[2]->getX());
$this->assertEquals(0, $result[2]->getY());
$this->assertEquals(35, $result[3]->getX());
$this->assertEquals(-35, $result[3]->getY());
}
public function testToArray(): void
{
$poly = new Polygon([
new Point(0, 0),
new Point(50, 0),
new Point(50, -50),
new Point(0, -50),
]);
$this->assertEquals([0, 0, 50, 0, 50, -50, 0, -50], $poly->toArray());
}
}

View File

@@ -2,7 +2,7 @@
namespace Intervention\Image\Tests\Geometry; namespace Intervention\Image\Tests\Geometry;
use Intervention\Image\Geometry\{Point, Size,}; use Intervention\Image\Geometry\{Point, Polygon, Size,};
use Intervention\Image\Tests\TestCase; use Intervention\Image\Tests\TestCase;
/** /**
@@ -254,6 +254,22 @@ class SizeTest extends TestCase
$this->assertEquals(50, $pos->getY()); $this->assertEquals(50, $pos->getY());
} }
public function testToPolygon(): void
{
$size = new Size(300, 200);
$poly = $size->toPolygon();
$this->assertInstanceOf(Polygon::class, $poly);
$this->assertCount(4, $poly);
$this->assertEquals(0, $poly[0]->getX());
$this->assertEquals(0, $poly[0]->getY());
$this->assertEquals(300, $poly[1]->getX());
$this->assertEquals(0, $poly[1]->getY());
$this->assertEquals(300, $poly[2]->getX());
$this->assertEquals(-200, $poly[2]->getY());
$this->assertEquals(0, $poly[3]->getX());
$this->assertEquals(-200, $poly[3]->getY());
}
public function testResize(): void public function testResize(): void
{ {
$size = new Size(300, 200); $size = new Size(300, 200);