Skip to content

Commit 9fe7980

Browse files
authored
Fix bug when centering non-latin characters (#1366)
1 parent ed6ddf4 commit 9fe7980

File tree

3 files changed

+69
-21
lines changed

3 files changed

+69
-21
lines changed

src/Drivers/AbstractFontProcessor.php

+8-6
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,16 @@ public function textBlock(string $text, FontInterface $font, PointInterface $pos
3030

3131
$x = $pivot->x();
3232
$y = $font->hasFilename() ? $pivot->y() + $this->capHeight($font) : $pivot->y();
33-
$x_adjustment = 0;
33+
$xAdjustment = 0;
3434

35+
// adjust line positions according to alignment
3536
foreach ($lines as $line) {
36-
$line_width = $this->boxSize((string) $line, $font)->width();
37-
$x_adjustment = $font->alignment() == 'left' ? 0 : $blockWidth - $line_width;
38-
$x_adjustment = $font->alignment() == 'right' ? intval(round($x_adjustment)) : $x_adjustment;
39-
$x_adjustment = $font->alignment() == 'center' ? intval(round($x_adjustment / 2)) : $x_adjustment;
40-
$position = new Point($x + $x_adjustment, $y);
37+
$lineBoxSize = $this->boxSize((string) $line, $font);
38+
$lineWidth = $lineBoxSize->width() + $lineBoxSize->pivot()->x();
39+
$xAdjustment = $font->alignment() == 'left' ? 0 : $blockWidth - $lineWidth;
40+
$xAdjustment = $font->alignment() == 'right' ? intval(round($xAdjustment)) : $xAdjustment;
41+
$xAdjustment = $font->alignment() == 'center' ? intval(round($xAdjustment / 2)) : $xAdjustment;
42+
$position = new Point($x + $xAdjustment, $y);
4143
$position->rotate($font->angle(), $pivot);
4244
$line->setPosition($position);
4345
$y += $leading;

src/Drivers/Gd/FontProcessor.php

+8-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Intervention\Image\Drivers\Gd;
66

77
use Intervention\Image\Drivers\AbstractFontProcessor;
8+
use Intervention\Image\Geometry\Point;
89
use Intervention\Image\Geometry\Rectangle;
910
use Intervention\Image\Interfaces\FontInterface;
1011
use Intervention\Image\Interfaces\SizeInterface;
@@ -37,16 +38,17 @@ public function boxSize(string $text, FontInterface $font): SizeInterface
3738

3839
// calculate box size from ttf font file with angle 0
3940
$box = imageftbbox(
40-
$this->nativeFontSize($font),
41-
0,
42-
$font->filename(),
43-
$text
41+
size: $this->nativeFontSize($font),
42+
angle: 0,
43+
font_filename: $font->filename(),
44+
string: $text
4445
);
4546

4647
// build size from points
4748
return new Rectangle(
48-
intval(abs($box[4] - $box[0])),
49-
intval(abs($box[5] - $box[1]))
49+
width: intval(abs($box[6] - $box[4])), // difference of upper-left-x and upper-right-x
50+
height: intval(abs($box[7] - $box[1])), // difference if upper-left-y and lower-left-y
51+
pivot: new Point($box[6], $box[7]), // position of upper-left corner
5052
);
5153
}
5254

tests/Unit/Drivers/AbstractFontProcessorTest.php

+53-9
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,63 @@ class AbstractFontProcessorTest extends BaseTestCase
1919
public function testTextBlock(): void
2020
{
2121
$text = 'AAAA BBBB CCCC';
22-
$font = (new Font($this->getTestResourcePath('test.ttf')))->setWrapWidth(20)->setSize(50);
22+
$font = (new Font($this->getTestResourcePath('test.ttf')))
23+
->setWrapWidth(20)
24+
->setSize(50)
25+
->setLineHeight(1.25)
26+
->setAlignment('center');
27+
2328
$processor = Mockery::mock(AbstractFontProcessor::class)->makePartial();
24-
$processor->shouldReceive('boxSize')->with('T', $font)->andReturn(new Rectangle(12, 6));
25-
$processor->shouldReceive('boxSize')->with('Hy', $font)->andReturn(new Rectangle(24, 6));
26-
$processor->shouldReceive('boxSize')->with('AAAA', $font)->andReturn(new Rectangle(24, 6));
27-
$processor->shouldReceive('boxSize')->with('AAAA BBBB', $font)->andReturn(new Rectangle(24, 6));
28-
$processor->shouldReceive('boxSize')->with('BBBB', $font)->andReturn(new Rectangle(24, 6));
29-
$processor->shouldReceive('boxSize')->with('BBBB CCCC', $font)->andReturn(new Rectangle(24, 6));
30-
$processor->shouldReceive('boxSize')->with('CCCC', $font)->andReturn(new Rectangle(24, 6));
31-
$processor->shouldReceive('boxSize')->with($text, $font)->andReturn(new Rectangle(100, 25));
29+
30+
$processor
31+
->shouldReceive('boxSize')
32+
->with('T', $font)
33+
->andReturn(new Rectangle(12, 6));
34+
$processor
35+
->shouldReceive('boxSize')
36+
->with('Hy', $font)
37+
->andReturn(new Rectangle(24, 6));
38+
39+
$processor
40+
->shouldReceive('boxSize')
41+
->with('AAAA', $font)
42+
->andReturn(new Rectangle(24, 6, new Point(1000, 0)));
43+
44+
$processor
45+
->shouldReceive('boxSize')
46+
->with('AAAA BBBB', $font)
47+
->andReturn(new Rectangle(24, 6));
48+
49+
$processor
50+
->shouldReceive('boxSize')
51+
->with('BBBB', $font)
52+
->andReturn(new Rectangle(24, 6, new Point(2000, 0)));
53+
54+
$processor
55+
->shouldReceive('boxSize')
56+
->with('BBBB CCCC', $font)
57+
->andReturn(new Rectangle(24, 6));
58+
59+
$processor
60+
->shouldReceive('boxSize')
61+
->with('CCCC', $font)
62+
->andReturn(new Rectangle(24, 6, new Point(3000, 0)));
63+
64+
$processor
65+
->shouldReceive('boxSize')
66+
->with($text, $font)
67+
->andReturn(new Rectangle(100, 25, new Point(10, 0)));
68+
3269
$block = $processor->textBlock($text, $font, new Point(0, 0));
70+
3371
$this->assertInstanceOf(TextBlock::class, $block);
3472
$this->assertEquals(3, $block->count());
73+
$this->assertEquals(-512, $block->getAtPosition(0)->position()->x());
74+
$this->assertEquals(-16, $block->getAtPosition(0)->position()->y());
75+
$this->assertEquals(-1012, $block->getAtPosition(1)->position()->x());
76+
$this->assertEquals(-8, $block->getAtPosition(1)->position()->y());
77+
$this->assertEquals(-1512, $block->getAtPosition(2)->position()->x());
78+
$this->assertEquals(0, $block->getAtPosition(2)->position()->y());
3579
}
3680

3781
public function testNativeFontSize(): void

0 commit comments

Comments
 (0)