| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- <?php
- namespace Intervention\Image\Gd;
- use Intervention\Image\Image;
- class Font extends \Intervention\Image\AbstractFont
- {
- /**
- * Get font size in points
- *
- * @return integer
- */
- protected function getPointSize()
- {
- return intval(ceil($this->size * 0.75));
- }
- /**
- * Filter function to access internal integer font values
- *
- * @return integer
- */
- private function getInternalFont()
- {
- $internalfont = is_null($this->file) ? 1 : $this->file;
- $internalfont = is_numeric($internalfont) ? $internalfont : false;
- if ( ! in_array($internalfont, array(1, 2, 3, 4, 5))) {
- throw new \Intervention\Image\Exception\NotSupportedException(
- sprintf('Internal GD font (%s) not available. Use only 1-5.', $internalfont)
- );
- }
- return intval($internalfont);
- }
- /**
- * Get width of an internal font character
- *
- * @return integer
- */
- private function getInternalFontWidth()
- {
- return $this->getInternalFont() + 4;
- }
- /**
- * Get height of an internal font character
- *
- * @return integer
- */
- private function getInternalFontHeight()
- {
- switch ($this->getInternalFont()) {
- case 1:
- return 8;
- case 2:
- return 14;
- case 3:
- return 14;
- case 4:
- return 16;
- case 5:
- return 16;
- }
- }
- /**
- * Calculates bounding box of current font setting
- *
- * @return Array
- */
- public function getBoxSize()
- {
- $box = array();
- if ($this->hasApplicableFontFile()) {
- // get bounding box with angle 0
- $box = imagettfbbox($this->getPointSize(), 0, $this->file, $this->text);
- // rotate points manually
- if ($this->angle != 0) {
- $angle = pi() * 2 - $this->angle * pi() * 2 / 360;
- for ($i=0; $i<4; $i++) {
- $x = $box[$i * 2];
- $y = $box[$i * 2 + 1];
- $box[$i * 2] = cos($angle) * $x - sin($angle) * $y;
- $box[$i * 2 + 1] = sin($angle) * $x + cos($angle) * $y;
- }
- }
- $box['width'] = intval(abs($box[4] - $box[0]));
- $box['height'] = intval(abs($box[5] - $box[1]));
- } else {
- // get current internal font size
- $width = $this->getInternalFontWidth();
- $height = $this->getInternalFontHeight();
- if (strlen($this->text) == 0) {
- // no text -> no boxsize
- $box['width'] = 0;
- $box['height'] = 0;
- } else {
- // calculate boxsize
- $box['width'] = strlen($this->text) * $width;
- $box['height'] = $height;
- }
- }
- return $box;
- }
- /**
- * Draws font to given image at given position
- *
- * @param Image $image
- * @param integer $posx
- * @param integer $posy
- * @return void
- */
- public function applyToImage(Image $image, $posx = 0, $posy = 0)
- {
- // parse text color
- $color = new Color($this->color);
- if ($this->hasApplicableFontFile()) {
- if ($this->angle != 0 || is_string($this->align) || is_string($this->valign)) {
- $box = $this->getBoxSize();
- $align = is_null($this->align) ? 'left' : strtolower($this->align);
- $valign = is_null($this->valign) ? 'bottom' : strtolower($this->valign);
- // correction on position depending on v/h alignment
- switch ($align.'-'.$valign) {
- case 'center-top':
- $posx = $posx - round(($box[6]+$box[4])/2);
- $posy = $posy - round(($box[7]+$box[5])/2);
- break;
- case 'right-top':
- $posx = $posx - $box[4];
- $posy = $posy - $box[5];
- break;
- case 'left-top':
- $posx = $posx - $box[6];
- $posy = $posy - $box[7];
- break;
- case 'center-center':
- case 'center-middle':
- $posx = $posx - round(($box[0]+$box[4])/2);
- $posy = $posy - round(($box[1]+$box[5])/2);
- break;
- case 'right-center':
- case 'right-middle':
- $posx = $posx - round(($box[2]+$box[4])/2);
- $posy = $posy - round(($box[3]+$box[5])/2);
- break;
- case 'left-center':
- case 'left-middle':
- $posx = $posx - round(($box[0]+$box[6])/2);
- $posy = $posy - round(($box[1]+$box[7])/2);
- break;
- case 'center-bottom':
- $posx = $posx - round(($box[0]+$box[2])/2);
- $posy = $posy - round(($box[1]+$box[3])/2);
- break;
- case 'right-bottom':
- $posx = $posx - $box[2];
- $posy = $posy - $box[3];
- break;
- case 'left-bottom':
- $posx = $posx - $box[0];
- $posy = $posy - $box[1];
- break;
- }
- }
- // enable alphablending for imagettftext
- imagealphablending($image->getCore(), true);
- // draw ttf text
- imagettftext($image->getCore(), $this->getPointSize(), $this->angle, $posx, $posy, $color->getInt(), $this->file, $this->text);
- } else {
- // get box size
- $box = $this->getBoxSize();
- $width = $box['width'];
- $height = $box['height'];
- // internal font specific position corrections
- if ($this->getInternalFont() == 1) {
- $top_correction = 1;
- $bottom_correction = 2;
- } elseif ($this->getInternalFont() == 3) {
- $top_correction = 2;
- $bottom_correction = 4;
- } else {
- $top_correction = 3;
- $bottom_correction = 4;
- }
- // x-position corrections for horizontal alignment
- switch (strtolower($this->align)) {
- case 'center':
- $posx = ceil($posx - ($width / 2));
- break;
- case 'right':
- $posx = ceil($posx - $width) + 1;
- break;
- }
- // y-position corrections for vertical alignment
- switch (strtolower($this->valign)) {
- case 'center':
- case 'middle':
- $posy = ceil($posy - ($height / 2));
- break;
- case 'top':
- $posy = ceil($posy - $top_correction);
- break;
- default:
- case 'bottom':
- $posy = round($posy - $height + $bottom_correction);
- break;
- }
- // draw text
- imagestring($image->getCore(), $this->getInternalFont(), $posx, $posy, $this->text, $color->getInt());
- }
- }
- }
|