mirror of
https://github.com/Intervention/image.git
synced 2025-08-16 19:04:00 +02:00
Fix bug when centering non-latin characters (#1366)
This commit is contained in:
@@ -30,14 +30,16 @@ abstract class AbstractFontProcessor implements FontProcessorInterface
|
|||||||
|
|
||||||
$x = $pivot->x();
|
$x = $pivot->x();
|
||||||
$y = $font->hasFilename() ? $pivot->y() + $this->capHeight($font) : $pivot->y();
|
$y = $font->hasFilename() ? $pivot->y() + $this->capHeight($font) : $pivot->y();
|
||||||
$x_adjustment = 0;
|
$xAdjustment = 0;
|
||||||
|
|
||||||
|
// adjust line positions according to alignment
|
||||||
foreach ($lines as $line) {
|
foreach ($lines as $line) {
|
||||||
$line_width = $this->boxSize((string) $line, $font)->width();
|
$lineBoxSize = $this->boxSize((string) $line, $font);
|
||||||
$x_adjustment = $font->alignment() == 'left' ? 0 : $blockWidth - $line_width;
|
$lineWidth = $lineBoxSize->width() + $lineBoxSize->pivot()->x();
|
||||||
$x_adjustment = $font->alignment() == 'right' ? intval(round($x_adjustment)) : $x_adjustment;
|
$xAdjustment = $font->alignment() == 'left' ? 0 : $blockWidth - $lineWidth;
|
||||||
$x_adjustment = $font->alignment() == 'center' ? intval(round($x_adjustment / 2)) : $x_adjustment;
|
$xAdjustment = $font->alignment() == 'right' ? intval(round($xAdjustment)) : $xAdjustment;
|
||||||
$position = new Point($x + $x_adjustment, $y);
|
$xAdjustment = $font->alignment() == 'center' ? intval(round($xAdjustment / 2)) : $xAdjustment;
|
||||||
|
$position = new Point($x + $xAdjustment, $y);
|
||||||
$position->rotate($font->angle(), $pivot);
|
$position->rotate($font->angle(), $pivot);
|
||||||
$line->setPosition($position);
|
$line->setPosition($position);
|
||||||
$y += $leading;
|
$y += $leading;
|
||||||
|
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace Intervention\Image\Drivers\Gd;
|
namespace Intervention\Image\Drivers\Gd;
|
||||||
|
|
||||||
use Intervention\Image\Drivers\AbstractFontProcessor;
|
use Intervention\Image\Drivers\AbstractFontProcessor;
|
||||||
|
use Intervention\Image\Geometry\Point;
|
||||||
use Intervention\Image\Geometry\Rectangle;
|
use Intervention\Image\Geometry\Rectangle;
|
||||||
use Intervention\Image\Interfaces\FontInterface;
|
use Intervention\Image\Interfaces\FontInterface;
|
||||||
use Intervention\Image\Interfaces\SizeInterface;
|
use Intervention\Image\Interfaces\SizeInterface;
|
||||||
@@ -37,16 +38,17 @@ class FontProcessor extends AbstractFontProcessor
|
|||||||
|
|
||||||
// calculate box size from ttf font file with angle 0
|
// calculate box size from ttf font file with angle 0
|
||||||
$box = imageftbbox(
|
$box = imageftbbox(
|
||||||
$this->nativeFontSize($font),
|
size: $this->nativeFontSize($font),
|
||||||
0,
|
angle: 0,
|
||||||
$font->filename(),
|
font_filename: $font->filename(),
|
||||||
$text
|
string: $text
|
||||||
);
|
);
|
||||||
|
|
||||||
// build size from points
|
// build size from points
|
||||||
return new Rectangle(
|
return new Rectangle(
|
||||||
intval(abs($box[4] - $box[0])),
|
width: intval(abs($box[6] - $box[4])), // difference of upper-left-x and upper-right-x
|
||||||
intval(abs($box[5] - $box[1]))
|
height: intval(abs($box[7] - $box[1])), // difference if upper-left-y and lower-left-y
|
||||||
|
pivot: new Point($box[6], $box[7]), // position of upper-left corner
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,19 +19,63 @@ class AbstractFontProcessorTest extends BaseTestCase
|
|||||||
public function testTextBlock(): void
|
public function testTextBlock(): void
|
||||||
{
|
{
|
||||||
$text = 'AAAA BBBB CCCC';
|
$text = 'AAAA BBBB CCCC';
|
||||||
$font = (new Font($this->getTestResourcePath('test.ttf')))->setWrapWidth(20)->setSize(50);
|
$font = (new Font($this->getTestResourcePath('test.ttf')))
|
||||||
|
->setWrapWidth(20)
|
||||||
|
->setSize(50)
|
||||||
|
->setLineHeight(1.25)
|
||||||
|
->setAlignment('center');
|
||||||
|
|
||||||
$processor = Mockery::mock(AbstractFontProcessor::class)->makePartial();
|
$processor = Mockery::mock(AbstractFontProcessor::class)->makePartial();
|
||||||
$processor->shouldReceive('boxSize')->with('T', $font)->andReturn(new Rectangle(12, 6));
|
|
||||||
$processor->shouldReceive('boxSize')->with('Hy', $font)->andReturn(new Rectangle(24, 6));
|
$processor
|
||||||
$processor->shouldReceive('boxSize')->with('AAAA', $font)->andReturn(new Rectangle(24, 6));
|
->shouldReceive('boxSize')
|
||||||
$processor->shouldReceive('boxSize')->with('AAAA BBBB', $font)->andReturn(new Rectangle(24, 6));
|
->with('T', $font)
|
||||||
$processor->shouldReceive('boxSize')->with('BBBB', $font)->andReturn(new Rectangle(24, 6));
|
->andReturn(new Rectangle(12, 6));
|
||||||
$processor->shouldReceive('boxSize')->with('BBBB CCCC', $font)->andReturn(new Rectangle(24, 6));
|
$processor
|
||||||
$processor->shouldReceive('boxSize')->with('CCCC', $font)->andReturn(new Rectangle(24, 6));
|
->shouldReceive('boxSize')
|
||||||
$processor->shouldReceive('boxSize')->with($text, $font)->andReturn(new Rectangle(100, 25));
|
->with('Hy', $font)
|
||||||
|
->andReturn(new Rectangle(24, 6));
|
||||||
|
|
||||||
|
$processor
|
||||||
|
->shouldReceive('boxSize')
|
||||||
|
->with('AAAA', $font)
|
||||||
|
->andReturn(new Rectangle(24, 6, new Point(1000, 0)));
|
||||||
|
|
||||||
|
$processor
|
||||||
|
->shouldReceive('boxSize')
|
||||||
|
->with('AAAA BBBB', $font)
|
||||||
|
->andReturn(new Rectangle(24, 6));
|
||||||
|
|
||||||
|
$processor
|
||||||
|
->shouldReceive('boxSize')
|
||||||
|
->with('BBBB', $font)
|
||||||
|
->andReturn(new Rectangle(24, 6, new Point(2000, 0)));
|
||||||
|
|
||||||
|
$processor
|
||||||
|
->shouldReceive('boxSize')
|
||||||
|
->with('BBBB CCCC', $font)
|
||||||
|
->andReturn(new Rectangle(24, 6));
|
||||||
|
|
||||||
|
$processor
|
||||||
|
->shouldReceive('boxSize')
|
||||||
|
->with('CCCC', $font)
|
||||||
|
->andReturn(new Rectangle(24, 6, new Point(3000, 0)));
|
||||||
|
|
||||||
|
$processor
|
||||||
|
->shouldReceive('boxSize')
|
||||||
|
->with($text, $font)
|
||||||
|
->andReturn(new Rectangle(100, 25, new Point(10, 0)));
|
||||||
|
|
||||||
$block = $processor->textBlock($text, $font, new Point(0, 0));
|
$block = $processor->textBlock($text, $font, new Point(0, 0));
|
||||||
|
|
||||||
$this->assertInstanceOf(TextBlock::class, $block);
|
$this->assertInstanceOf(TextBlock::class, $block);
|
||||||
$this->assertEquals(3, $block->count());
|
$this->assertEquals(3, $block->count());
|
||||||
|
$this->assertEquals(-512, $block->getAtPosition(0)->position()->x());
|
||||||
|
$this->assertEquals(-16, $block->getAtPosition(0)->position()->y());
|
||||||
|
$this->assertEquals(-1012, $block->getAtPosition(1)->position()->x());
|
||||||
|
$this->assertEquals(-8, $block->getAtPosition(1)->position()->y());
|
||||||
|
$this->assertEquals(-1512, $block->getAtPosition(2)->position()->x());
|
||||||
|
$this->assertEquals(0, $block->getAtPosition(2)->position()->y());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNativeFontSize(): void
|
public function testNativeFontSize(): void
|
||||||
|
Reference in New Issue
Block a user