1
0
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:
Oliver Vogel
2022-07-04 19:11:25 +02:00
parent 6a4a7bfa8f
commit b7371cf9fb
5 changed files with 54 additions and 115 deletions

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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.');

View File

@@ -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());
}
}