Skip to content

Commit e819e0c

Browse files
author
Jakub Caban
committed
Properly use font file and make positioning consistent with GD
1 parent 63c7785 commit e819e0c

File tree

2 files changed

+108
-48
lines changed

2 files changed

+108
-48
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
"require": {
1515
"php": "^7.1",
1616
"intervention/image": "^2.4",
17-
"jcupitt/vips": "^1.0"
17+
"jcupitt/vips": "^1.0",
18+
"phenx/php-font-lib": "^0.5.2"
1819
},
1920
"autoload": {
2021
"psr-4": {

src/Font.php

Lines changed: 106 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace Intervention\Image\Vips;
66

7+
use FontLib\Exception\FontNotFoundException;
8+
use FontLib\Font as FontReader;
79
use Intervention\Image\AbstractFont;
810
use Intervention\Image\Exception\RuntimeException;
911
use Intervention\Image\Image;
@@ -40,30 +42,90 @@ public function applyToImage(Image $image, $posx = 0, $posy = 0)
4042
]
4143
);
4244

45+
$angle = deg2rad($this->angle);
46+
$posy += $core->height * cos($angle);
47+
48+
$angle = -1 * ($this->angle % 365);
49+
switch ($angle) {
50+
case 0:
51+
break;
52+
53+
case 90:
54+
case -270:
55+
$core = $core->rot90();
56+
break;
57+
58+
case 180:
59+
case -180:
60+
$core = $core->rot180();
61+
break;
62+
63+
case -90:
64+
case 270:
65+
$core = $core->rot270();
66+
break;
67+
68+
default:
69+
$core = $core->rotate($angle, [
70+
'background' => [0],
71+
]);
72+
}
73+
4374
$align = is_null($this->align) ? 'left' : strtolower($this->align);
4475
$valign = is_null($this->valign) ? 'bottom' : strtolower($this->valign);
4576

46-
// corrections on y-position
47-
switch ($valign) {
48-
case 'center':
49-
case 'middle':
50-
$posx -= round($core->width / 2);
77+
$box = $this->getBoxSize();
78+
79+
$posy -= $core->height;
80+
// correction on position depending on v/h alignment
81+
switch ($align.'-'.$valign) {
82+
83+
case 'center-top':
84+
$posx -= round(($box[6] + $box[4])/2);
85+
$posy -= round(($box[7] + $box[5])/2);
5186
break;
5287

53-
case 'right':
54-
$posx -= $core->width;
88+
case 'right-top':
89+
$posx -= $box[4];
90+
$posy -= $box[5];
91+
break;
92+
93+
case 'left-top':
94+
$posx -= $box[6];
95+
$posy -= $box[7];
96+
break;
97+
98+
case 'center-center':
99+
case 'center-middle':
100+
$posx -= round(($box[0] + $box[4])/2);
101+
$posy -= round(($box[1] + $box[5])/2);
55102
break;
56-
}
57103

58-
// corrections on y-position
59-
switch ($align) {
60-
case 'center':
61-
case 'middle':
62-
$posy -= round($core->height / 2);
104+
case 'right-center':
105+
case 'right-middle':
106+
$posx -= round(($box[2] + $box[4])/2);
107+
$posy -= round(($box[3] + $box[5])/2);
63108
break;
64109

65-
case 'bottom':
66-
$posy -= $core->height;
110+
case 'left-center':
111+
case 'left-middle':
112+
$posx -= round(($box[0] + $box[6])/2);
113+
$posy -= round(($box[1] + $box[7])/2);
114+
break;
115+
116+
case 'center-bottom':
117+
$posx -= round(($box[0] + $box[2])/2);
118+
$posy -= round(($box[1] + $box[3])/2);
119+
break;
120+
121+
case 'right-bottom':
122+
$posx -= $box[2];
123+
$posy -= $box[3];
124+
break;
125+
126+
case 'left-bottom':
127+
$posx -= $box[0];
128+
$posy -= $box[1];
67129
break;
68130
}
69131

@@ -104,27 +166,50 @@ public function getBoxSize()
104166
$box['height'] = 0;
105167
} else {
106168
$core = $this->createTextImage();
107-
$box['width'] = $core->width;
108-
$box['height'] = $core->height;
169+
$box = [
170+
$core->xoffset,
171+
$core->height,
172+
$core->width+$core->xoffset,
173+
$core->height,
174+
$core->width+$core->xoffset,
175+
0,
176+
$core->xoffset,
177+
0
178+
];
179+
180+
if ($this->angle !== 0) {
181+
182+
$angle = deg2rad(360 - $this->angle);
183+
184+
for ($i=0; $i<4; $i++) {
185+
$x = $box[$i * 2];
186+
$y = $box[$i * 2 + 1];
187+
$box[$i * 2] = cos($angle) * $x - sin($angle) * $y;
188+
$box[$i * 2 + 1] = sin($angle) * $x + cos($angle) * $y;
189+
}
190+
}
191+
192+
$box['width'] = (int) abs($box[4] - $box[0]);
193+
$box['height'] = (int) abs($box[5] - $box[1]);
109194
}
110195

111196
return $box;
112197
}
113198

114199
/**
115200
* @return ImageCore
116-
* @throws Exception
201+
* @throws Exception|FontNotFoundException
117202
*/
118203
private function createTextImage()
119204
{
120205
if ($this->hasApplicableFontFile()) {
121-
$info = pathinfo($this->file);
122-
$font = basename($this->file, '.'.$info['extension']);
206+
$font = FontReader::load($this->file);
123207
} else {
124208
throw new RuntimeException(
125209
'Font file must be provided to apply text to image.'
126210
);
127211
}
212+
128213
$align_to_vips = [
129214
'left' => Align::LOW,
130215
'right' => Align::CENTRE,
@@ -133,38 +218,12 @@ private function createTextImage()
133218
$core = ImageCore::text(
134219
$this->text,
135220
[
136-
'font' => $font.' '.$this->size,
221+
'font' => $font->getFontFullName().' '.$this->size,
137222
'fontfile' => $this->file,
138223
'align' => $align_to_vips[$this->align ?: 'left'],
139224
]
140225
);
141226

142-
switch ($this->angle % 360) {
143-
case 0:
144-
break;
145-
146-
case 90:
147-
case -270:
148-
$core = $core->rot90();
149-
break;
150-
151-
case 180:
152-
case -180:
153-
$core = $core->rot180();
154-
break;
155-
156-
case -90:
157-
case 270:
158-
$core = $core->rot270();
159-
break;
160-
161-
default:
162-
$core = $core->similarity([
163-
'background' => [0],
164-
'angle' => $this->angle % 360,
165-
]);
166-
}
167-
168227
return $core;
169228
}
170229
}

0 commit comments

Comments
 (0)