mirror of
https://github.com/Intervention/image.git
synced 2025-08-01 11:30:16 +02:00
Implement multiline TextWriter for Imagick driver
This commit is contained in:
@@ -2,13 +2,9 @@
|
||||
|
||||
namespace Intervention\Image\Drivers\Abstract;
|
||||
|
||||
use Intervention\Image\Geometry\Point;
|
||||
use Intervention\Image\Geometry\Polygon;
|
||||
use Intervention\Image\Geometry\Size;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\FontInterface;
|
||||
use Intervention\Image\Traits\CanHandleInput;
|
||||
use Intervention\Image\Typography\TextBlock;
|
||||
|
||||
abstract class AbstractFont implements FontInterface
|
||||
{
|
||||
@@ -117,4 +113,19 @@ abstract class AbstractFont implements FontInterface
|
||||
{
|
||||
return $this->lineHeight;
|
||||
}
|
||||
|
||||
public function leadingInPixels(): int
|
||||
{
|
||||
return intval(round($this->fontSizeInPixels() * $this->getLineHeight()));
|
||||
}
|
||||
|
||||
public function capHeight(): int
|
||||
{
|
||||
return $this->getBoxSize('T')->height();
|
||||
}
|
||||
|
||||
public function fontSizeInPixels(): int
|
||||
{
|
||||
return $this->getBoxSize('Hy')->height();
|
||||
}
|
||||
}
|
||||
|
@@ -84,19 +84,4 @@ class Font extends AbstractFont
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
public function capHeight(): int
|
||||
{
|
||||
return $this->getBoxSize('T')->height();
|
||||
}
|
||||
|
||||
public function leadingInPixels(): int
|
||||
{
|
||||
return intval(round($this->fontSizeInPixels() * $this->getLineHeight()));
|
||||
}
|
||||
|
||||
public function fontSizeInPixels(): int
|
||||
{
|
||||
return $this->getBoxSize('Hy')->height();
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ class Font extends AbstractFont
|
||||
$draw->setFont($this->getFilename());
|
||||
$draw->setFontSize($this->getSize());
|
||||
$draw->setFillColor($this->getColor()->getPixel());
|
||||
$draw->setTextAlignment($this->getImagickAlign());
|
||||
$draw->setTextAlignment(Imagick::ALIGN_LEFT);
|
||||
|
||||
return $draw;
|
||||
}
|
||||
@@ -40,24 +40,6 @@ class Font extends AbstractFont
|
||||
return $color;
|
||||
}
|
||||
|
||||
public function getAngle(): float
|
||||
{
|
||||
return parent::getAngle() * (-1);
|
||||
}
|
||||
|
||||
public function getImagickAlign(): int
|
||||
{
|
||||
switch (strtolower($this->getAlign())) {
|
||||
case 'center':
|
||||
return Imagick::ALIGN_CENTER;
|
||||
|
||||
case 'right':
|
||||
return Imagick::ALIGN_RIGHT;
|
||||
}
|
||||
|
||||
return Imagick::ALIGN_LEFT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate box size of current font
|
||||
*
|
||||
@@ -70,14 +52,14 @@ class Font extends AbstractFont
|
||||
return (new Size(0, 0))->toPolygon();
|
||||
}
|
||||
|
||||
$dimensions = (new Imagick())->queryFontMetrics(
|
||||
$this->toImagickDraw(),
|
||||
$text
|
||||
);
|
||||
$draw = $this->toImagickDraw();
|
||||
$draw->setStrokeAntialias(true);
|
||||
$draw->setTextAntialias(true);
|
||||
$dimensions = (new Imagick())->queryFontMetrics($draw, $text);
|
||||
|
||||
return (new Size(
|
||||
intval(round(abs($dimensions['boundingBox']['x1'] - $dimensions['boundingBox']['x2']))),
|
||||
intval(round(abs($dimensions['boundingBox']['y1'] - $dimensions['boundingBox']['y2']))),
|
||||
intval(round($dimensions['textWidth'])),
|
||||
intval(round($dimensions['textHeight'])),
|
||||
))->toPolygon();
|
||||
}
|
||||
}
|
||||
|
@@ -5,48 +5,50 @@ namespace Intervention\Image\Drivers\Imagick\Modifiers;
|
||||
use Intervention\Image\Drivers\Abstract\AbstractTextWriter;
|
||||
use Intervention\Image\Drivers\Imagick\Font;
|
||||
use Intervention\Image\Exceptions\FontException;
|
||||
use Intervention\Image\Geometry\Point;
|
||||
use Intervention\Image\Interfaces\FontInterface;
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
|
||||
class TextWriter extends AbstractTextWriter
|
||||
{
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
$position = $this->getAlignedPosition();
|
||||
$lines = $this->getAlignedTextBlock();
|
||||
foreach ($image as $frame) {
|
||||
$frame->getCore()->annotateImage(
|
||||
$this->getFont()->toImagickDraw(),
|
||||
$position->getX(),
|
||||
$position->getY(),
|
||||
$this->getFont()->getAngle() * (-1),
|
||||
$this->text
|
||||
);
|
||||
foreach ($lines as $line) {
|
||||
$frame->getCore()->annotateImage(
|
||||
$this->getFont()->toImagickDraw(),
|
||||
$line->getPosition()->getX(),
|
||||
$line->getPosition()->getY(),
|
||||
$this->getFont()->getAngle(),
|
||||
$line
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
protected function getAlignedPosition(): Point
|
||||
{
|
||||
$position = $this->position;
|
||||
$box = $this->getFont()->getBoxSize($this->text);
|
||||
// protected function getAlignedPosition(): Point
|
||||
// {
|
||||
// $position = $this->position;
|
||||
// $box = $this->getFont()->getBoxSize($this->text);
|
||||
//
|
||||
// // adjust y pos
|
||||
// switch ($this->getFont()->getValign()) {
|
||||
// case 'top':
|
||||
// $position->setY($position->getY() + $box->height());
|
||||
// break;
|
||||
//
|
||||
// case 'middle':
|
||||
// case 'center':
|
||||
// $position->setY(intval($position->getY() + round($box->height() / 2)));
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// return $position;
|
||||
// }
|
||||
|
||||
// adjust y pos
|
||||
switch ($this->getFont()->getValign()) {
|
||||
case 'top':
|
||||
$position->setY($position->getY() + $box->height());
|
||||
break;
|
||||
|
||||
case 'middle':
|
||||
case 'center':
|
||||
$position->setY(intval($position->getY() + round($box->height() / 2)));
|
||||
break;
|
||||
}
|
||||
|
||||
return $position;
|
||||
}
|
||||
|
||||
private function getFont(): Font
|
||||
protected function getFont(): FontInterface
|
||||
{
|
||||
if (!is_a($this->font, Font::class)) {
|
||||
throw new FontException('Font is not compatible to current driver.');
|
||||
|
@@ -2,12 +2,9 @@
|
||||
|
||||
namespace Intervention\Image\Tests\Typography;
|
||||
|
||||
use Intervention\Image\Geometry\Point;
|
||||
use Intervention\Image\Tests\TestCase;
|
||||
use Intervention\Image\Typography\TextBlock;
|
||||
use Intervention\Image\Drivers\Abstract\AbstractFont;
|
||||
use Intervention\Image\Geometry\Point;
|
||||
use Intervention\Image\Geometry\Polygon;
|
||||
use Mockery;
|
||||
|
||||
class TextBlockTest extends TestCase
|
||||
{
|
||||
@@ -40,42 +37,4 @@ class TextBlockTest extends TestCase
|
||||
$this->assertEquals('FooBar', $block->getLine(1));
|
||||
$this->assertEquals('bar', $block->getLine(2));
|
||||
}
|
||||
|
||||
public function testAlignByFont(): void
|
||||
{
|
||||
$font = Mockery::mock(AbstractFont::class)
|
||||
->shouldAllowMockingProtectedMethods()
|
||||
->makePartial();
|
||||
|
||||
$font->shouldReceive('getBoxSize')->andReturn(
|
||||
new Polygon([
|
||||
new Point(-1, -29),
|
||||
new Point(141, -29),
|
||||
new Point(141, 98),
|
||||
new Point(-1, 98),
|
||||
])
|
||||
);
|
||||
|
||||
// $font->shouldReceive('capHeight')->andReturn(22);
|
||||
|
||||
$font->shouldReceive('leadingInPixels')->andReturn(74);
|
||||
$font->angle(45);
|
||||
|
||||
$block = $this->getTestBlock(); // before
|
||||
$this->assertEquals(0, $block->getLine(0)->getPosition()->getX());
|
||||
$this->assertEquals(0, $block->getLine(0)->getPosition()->getY());
|
||||
$this->assertEquals(0, $block->getLine(1)->getPosition()->getX());
|
||||
$this->assertEquals(0, $block->getLine(1)->getPosition()->getY());
|
||||
$this->assertEquals(0, $block->getLine(2)->getPosition()->getX());
|
||||
$this->assertEquals(0, $block->getLine(2)->getPosition()->getY());
|
||||
|
||||
$result = $block->alignByFont($font); // after
|
||||
$this->assertInstanceOf(TextBlock::class, $result);
|
||||
$this->assertEquals(0, $block->getLine(0)->getPosition()->getX());
|
||||
$this->assertEquals(0, $block->getLine(0)->getPosition()->getY());
|
||||
$this->assertEquals(-52, $block->getLine(1)->getPosition()->getX());
|
||||
$this->assertEquals(52, $block->getLine(1)->getPosition()->getY());
|
||||
$this->assertEquals(-104, $block->getLine(2)->getPosition()->getX());
|
||||
$this->assertEquals(104, $block->getLine(2)->getPosition()->getY());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user