imagettfbbox
(PHP 4, PHP 5, PHP 7)
imagettfbbox — 取得使用 TrueType 字体的文本的范围
说明
array imagettfbbox ( float $size , float $angle , string $fontfile , string
$text )
本函数计算并返回一个包围着 TrueType 文本范围的虚拟方框的像素大小。
size
像素单位的字体大小。
angle
text 将被度量的角度大小。
fontfile
TrueType 字体文件的文件名（可以是 URL）。根据 PHP 所使用的 GD 库版本，可能
尝试搜索那些不是以 '/' 开头的文件名并加上 '.ttf' 的后缀并搜索库定义的字体路
径。
text
要度量的字符串。
imagettfbbox() 返回一个含有 8 个单元的数组表示了文本外框的四个角：
0 左下角 X 位置
1 左下角 Y 位置
2 右下角 X 位置
3 右下角 Y 位置
4 右上角 X 位置
5 右上角 Y 位置
6 左上角 X 位置
7 左上角 Y 位置
这些点是相对于文本的而和角度无关，因此“左上角”指的是以水平方向看文字时其左上角
。
本函数同时需要 GD 库和 FreeType 库。
参见 imagettftext()。
User Contributed Notes 63 notes
===============================================================================
Please note that as imageTTFBbox and imageTTFText functions return an array of
coordinates which could be negative numbers care must be taken with height and
width calculations.
The rigth way to do that is to use the abs() function:
for an horizontal text:
$box = @imageTTFBbox($size,0,$font,$text);
$width = abs($box[4] - $box[0]);
$height = abs($box[5] - $box[1]);
Then to center your text at ($x,$y) position the code should be like that:
$x -= $width/2;
$y += $heigth/2;
imageTTFText($img,$size,0,$x,$y,$color,$font,$text);
this because (0,0) page origin is topleft page corner and (0,0) text origin is
lower-left readable text corner.
Hope this help.
===============================================================================
Very CLEAR version of func., with example....
abs($minX) - 1,
"top" => abs($minY) - 1,
"width" => $maxX - $minX,
"height" => $maxY - $minY,
"box" => $rect
);
}
// Example usage - gif image output
$text_string = "Hullo World";
$font_ttf = "./fonts/arial.ttf";
$font_size = 22;
$text_angle = 0;
$text_padding = 10; // Img padding - around text
$the_box = calculateTextBox($text_string, $font_ttf, $font_size,
$text_angle);
$imgWidth = $the_box["width"] + $text_padding;
$imgHeight = $the_box["height"] + $text_padding;
$image = imagecreate($imgWidth,$imgHeight);
imagefill($image, imagecolorallocate($image,200,200,200));
$color = imagecolorallocate($image,0,0,0);
imagettftext($image,
$font_size,
$text_angle,
$the_box["left"] + ($imgWidth / 2) - ($the_box["width"] / 2),
$the_box["top"] + ($imgHeight / 2) - ($the_box["height"] / 2),
$color,
$font_ttf,
$text_string);
header("Content-Type: image/gif");
imagegif($image);
imagedestroy($image);
?>
[ remember: No spaces before or after the tag, because of header()
call, you Roast! ]
===============================================================================
This is a function which reformats a text string into a text block of a given
width.
Usefull when you have a long single line string and want to fit it into a fixed
width but don't care about it's height
===============================================================================
It seems to be worth pointing out that the "points" unit GD2 is using
corresponds to 96 dpi, as defined in gd.h:
#define GD_RESOLUTION 96 /* pixels per inch */
So if you want to translate the bbox back to font points, you need to multiply
all coordinates by 72/96 = 3/4.
===============================================================================
I wrote a simple function that calculates the *exact* bounding box (single
pixel precision).
The function returns an associative array with these keys:
left, top: coordinates you will pass to imagettftext
width, height: dimension of the image you have to create
black => empty)
$rleft = $w4 = $width<<2;
$rright = 0;
$rbottom = 0;
$rtop = $h4 = $height<<2;
for( $x = 0; $x < $w4; $x++ )
for( $y = 0; $y < $h4; $y++ )
if( imagecolorat( $img, $x, $y ) ){
$rleft = min( $rleft, $x );
$rright = max( $rright, $x );
$rtop = min( $rtop, $y );
$rbottom = max( $rbottom, $y );
}
// destroy img and serve the result
imagedestroy( $img );
return array( "left" => $left - $rleft,
"top" => $top - $rtop,
"width" => $rright - $rleft + 1,
"height" => $rbottom - $rtop + 1 );
}
?>
===============================================================================
If you're looking for easy text alignment, you need to use the imagettfbbox()
command. When given the correct parameters, it will return the boundaries of
your to-be-made text field in an array, which will allow you to calculate the x
and y coordinate that you need to use for centering or aligning your text.
A horizontal centering example:
$tb would contain:
Array
(
[0] => 0 // lower left X coordinate
[1] => -1 // lower left Y coordinate
[2] => 198 // lower right X coordinate
[3] => -1 // lower right Y coordinate
[4] => 198 // upper right X coordinate
[5] => -20 // upper right Y coordinate
[6] => 0 // upper left X coordinate
[7] => -20 // upper left Y coordinate
)
For horizontal alignment, we need to substract the "text box's" width { $tb[2]
or $tb[4] } from the image's width and then substract by two.
Saying you have a 200px wide image, you could do something like this:
This'll give you perfect horizontal center alignment for your text, give or
take 1 pixel. Have fun!
===============================================================================
Please note that the 3rd argument is really a "path".
use instead something like this:
or
===============================================================================
The returned array order is like this:
-----------------------------
| X:4 Y:5 | X: Y:7 |
-----------------------------
| X:0 Y:1 | X:2 Y:3 |
-----------------------------
eg:
4 for the upper left X
5 for the upper left Y and so on.
===============================================================================
measure bg image size, wrap text to fit image width
===============================================================================
For mixed text drawing on image, height given by this function is useless and
leads to text's hip-hops over the baseline .
I will use just this:
===============================================================================
As many of you know, this function is bugged in several versions of PHP. It
should return the coordinates relative to the baseline of the font. So if your
text includes characters like g and p then the bounding box should extend below
zero on the Y axis, however it doesn't. This is a problem because imagettftext
() positions text using the baseline, so all your text will be misaligned.
My solution is to create an image of the desired font and font-size using all
ascii characters with imagettfbbox() and imagettftext(). The height of this
image is used as the height for the real image.
I then analyse the image to get the vertical offset of the text (the background
color should be $baseColor)
height(); $y++)
for($x = 0; $x < $this->width(); $x++)
if (imagecolorat($image, $x, $y) !== $baseColor)
return $y; }
?>
This offset can be used as the baseline for the font (for this font-size). You
can use a similar trick for the horizontal offset, but that changes depending
on the first character.
===============================================================================
I have been testing this function for a while now and have come up with many of
the same issues that other people have touched upon. Not being able to
calculate the width of the text correctly. Or if a solution is found then it
won't work with a hanging letter or a negative start letter like 'j'.
Like Ralph I also wanted to draw a box around some text and this would require
me being pixel perfect with the font. The trouble is I did not know which font
would be used or which size. This led me to come up with a solution which I am
sharing below.
= -1) {
$bbox['x'] = abs($bbox[0] + 1) * -1;
} else {
//$bbox['x'] = 0;
$bbox['x'] = abs($bbox[0] + 2);
}
//calculate actual text width
$bbox['width'] = abs($bbox[2] - $bbox[0]);
if($bbox[0] < -1) {
$bbox['width'] = abs($bbox[2]) + abs($bbox[0]) - 1;
}
//calculate y baseline
$bbox['y'] = abs($bbox[5] + 1);
//calculate actual text height
$bbox['height'] = abs($bbox[7]) - abs($bbox[1]);
if($bbox[3] > 0) {
$bbox['height'] = abs($bbox[7] - $bbox[1]) - 1;
}
return $bbox;
}
?>
The function above gives the correct x and y coordinates that the text should
be drawn from and also gives the actual image width and height. This has been
tested with various fonts and sizes ranging from 6 up to 144 points. Some of
the output will appear to be incorrect and have an extra pixel on the right,
using verdana at size 144 and outputting the character 'Q' for example. This
is not an error as this is part of the anti-aliasing of the font output.
Example Usage:
Return Values:
Array
(
[0] => -8
[1] => 40
[2] => 715
[3] => 40
[4] => 715
[5] => -177
[6] => -8
[7] => -177
[x] => 6
[width] => 722
[y] => 176
[height] => 216
)
Further notes can be found here along with images of the output of the function
http://mikeleigh.com/links/imagettfbbox
===============================================================================
Here is a function that lets you write a string with your own "font tracking"
level (the amount of pixels separating each character). It uses imagettfbbox
to determine the width of each character, so it doesn't discriminate against
the skinnier of characters. For this example, let $t = the amount of distance
in pixels you want to separate each character from its neighbors.
Be aware that it currently does not work for angles other than the 0 default (I
have no need for that).
===============================================================================
Finally managed to make a fixed version of imagettfbbox().
All angles returns correct values.
Except that imagettftext() returns different trackings (space between each
character) when rotating.
===============================================================================
a little something to replace in blackbart tip :
// start scanning (0=> black => empty)
$rleft = $w4 = $width<<2;
$rright = 0;
$rbottom = 0;
$rtop = $h4 = $height<<2;
for( $x = 0; $x < $w4; $x++ )
for( $y = 0; $y < $h4; $y++ )
if( imagecolorat( $img, $x, $y ) ){
$rleft = min( $rleft, $x );
$rright = max( $rright, $x );
$rtop = min( $rtop, $y );
$rbottom = max( $rbottom, $y );
}
with
// start scanning (0=> black => empty)
$break = false;
$rleft = $w4 = $width<<2;
$rright = 0;
$rbottom = 0;
$rtop = $h4 = $height<<2;
// scanning from left to right, breaking when a pixel is found, to scan from
the other side : avoid scanning all pixels !
for($x=0; $x<$w4; $x++){
for($y=0; $y<$h4; $y++)
if(imagecolorat($img,$x,$y)){
$rtop = min($rtop, $y); $rleft = min($rleft, $x);
$break = true; break;
}
if($break) break;
}
// scanning from right to left, breaking when a pixel is found
for($x=($w4-1); $x>$rleft; $x--){
for($y=0; $y<$h4; $y++)
if(imagecolorat($img,$x,$y)){
$rright = max($rright, $x); $rbottom = max($rbottom, $y);
$break = true; break;
}
if($break) break;
}
//... //
it may be even better to check if the picture is portrait or landscape, to
start the loops from left-right(landscape) or top-bottom (portrait)
===============================================================================
I found a simple solution that was working for me:
Here is the link with a examples:
http://www.tuxradar.com/practicalphp/11/2/6#null
===============================================================================
It should be noted that the bounding box coordinates returned by this function
are inaccurate - bug reports about this have been open for 5 years, so expect
this will likely never be fixed.
More information here:
https://gist.github.com/mindplay-dk/4429153
===============================================================================
Automatic line breaks: This simple function is able automatically create line
breaks if you want to write a text on an image. All you have to specify is a
maximum length.
===============================================================================
I could in no way reproduce this function's example if I was to use any
accented letter.
Replacing imagecreatetruecolor by imagecreate worked correctly with accents.
===============================================================================
I want to output a bounding box of a text as an image straightly. I did like
this:
";
$font = "./arial.ttf";
$size = "60";
$bbox = imagettfbbox($size, 0, $font, $text);
$width = abs($bbox[2] - $bbox[0]);
$height = abs($bbox[7] - $bbox[1]);
$image = imagecreatetruecolor($width, $height);
$bgcolor = imagecolorallocate($image, 255, 255, 255);
$color = imagecolorallocate($image, 0, 0, 0);
$x = $bbox[0] + ($width / 2) - ($bbox[4] / 2);
$y = $bbox[1] + ($height / 2) - ($bbox[5] / 2);
imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $bgcolor);
imagettftext($image, $size, 0, $x, $y, $color, $font, $text);
$last_pixel= imagecolorat($image, 0, 0);
for ($j = 0; $j < $height; $j++)
{
for ($i = 0; $i < $width; $i++)
{
if (isset($blank_left) && $i >= $blank_left)
{
break;
}
if (imagecolorat($image, $i, $j) !== $last_pixel)
{
if (!isset($blank_top))
{
$blank_top = $j;
}
$blank_left = $i;
break;
}
$last_pixel = imagecolorat($image, $i, $j);
}
}
$x -= $blank_left;
$y -= $blank_top;
imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $bgcolor);
imagettftext($image, $size, 0, $x, $y, $color, $font, $text);
header('Content-type: image/png');
imagepng($image);
imagedestroy($image);
?>
===============================================================================
If $fontfile is a Windows UNC path, it *must* start with //SERVER rather than \
\SERVER:
===============================================================================
My solution to below-baseline characters is to simply apply a smaller angle and
some padding when calculating your boundaries, so the function thinks your text
goes below baseline. For example:
===============================================================================
SIMPLE OVERLOADED FUNCTION: Adds TTF Center and Right Alignment to co ordintate
points.
Correctly demonstrates the use of the bouning box TTF function and the array of
coordinates that it returns.
After obtaining values and adjusting based on a set of values [L, C, R], it
uses simple math based of the length of the text to move it from the origin (x
= 0 )
===============================================================================
I was viewing the code for calculate the box of a text for a given font but I
do not found one that works fine with different angles from zero, so I have
made a function simpler than above:
abs($minX),
"top" => abs($minY),
"width" => $maxX - $minX,
"height" => $maxY - $minY,
"box" => $rect
);
}
?>
With this function you can center an angled string in any image:
===============================================================================
I worked out a script that allows the transfer of alphanumeric data to be
placed on an image. The HTML feature is img src and the php feature is
imagettftext. This simple code will increment from 1 to 3 on images.
code:
";
print "";
print "
";
}
?>
===============================================================================
To get the height for a line of text, I've found it useful to do:
I hope this helps. Before, I used the string "Tj", but that sometimes fell
short, especially for crazy fonts.
===============================================================================
the imagettfbbox and imagettftext quirks are:
1. imagettfbbox and imagettftext have the same return value and both of them
are wrong for angle not equal to zero.
2. imagettfbbox returns the correct bounding box when angle is zero.
3. the bounding box has a coordinate system that the x gets bigger from left to
right and y gets bigger from top to bottom.
4. the "base point" used in imagettftext is the origin in the bounding box
coordinate system.
5. when the angle is other than 0, it is actually rotated in the coordinate
system with respect to the base point. so if we know the bounding box
coordinate when angle is zero, we can get the new bounding box coordinate by
doing the rotation by math equations manually.
6. to have pixel level accuracy, we should also be aware of another thing.
suppose the axis is like this: |_|_|_|, the bounding box coordinate uses point
on the vertical line while image function uses point on the horizontal line, so
there is a 1 pixel difference you should take care of.
The following snippet creates minimal images containing a letter of different
font and rotation angle. This is especially useful in captcha scripts.
0 ) {
$tmp = $rect[6] * $cos + $rect[7] * $sin;
$bx = -1 - round( $tmp );
$imw = round( $rect[2] * $cos + $rect[3] * $sin - $tmp );
$tmp = $rect[5] * $cos - $rect[4] * $sin;
$by = -1 - round( $tmp );
$imh = round( $rect[1] * $cos - $rect[0] * $sin - $tmp );
} else {
$tmp = $rect[0] * $cos + $rect[1] * $sin;
$bx = -1 - round( $tmp );
$imw = round( $rect[4] * $cos + $rect[5] * $sin - $tmp );
$tmp = $rect[7] * $cos - $rect[6] * $sin;
$by = -1 - round( $tmp );
$imh = round( $rect[3] * $cos - $rect[2] * $sin - $tmp );
}
}
$im = imagecreatetruecolor( $imw, $imh );
imagefill( $im, 0, 0, imagecolorallocate( $im, 255, 0, 255 ) );
imagettftext( $im, $size, $angle, $bx, $by, imagecolorallocate( $im, 0, 0,
0 ), $font, $char );
imagegif( $im, trim( $font, './' ) . ord( $char ) . $angle . '.gif' );
imagedestroy( $im );
}
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
$angles = array( -30, -20, -10, 0, 10, 20, 30 );
$fonts = array( './latinwide.ttf', './verdana.ttf', './times.ttf', './
broadway.ttf' );
foreach( $angles as $angle )
foreach( $fonts as $font )
for( $i = 0; $i < strlen( $chars ); ++$i )
create_font_image( 100, $angle, $font, $chars[$i] );
?>
===============================================================================
I still got problems trying to rotate imagettftext using imagettfbbox.
It's position calculation is mostly wrong. So i tried to rotate ttftext with
IMAGEROTATE.
As a special the result is in black fontcolor and transparent background.
Hope it helps sombody (thanks for function convertBoundingBox, reading below)
function ImgText($text,$fontsize,$font,$angle){
$im = '';
if($text){
if(!$fontsize || $fontsize < 1) $fontsize = 12;
if(!$font) $font = "fonts/arial.ttf";
$bbox = imagettfbbox($fontsize, 0, $font, $text);
$size=convertBoundingBox($bbox);
$im = ImageCreatetruecolor($size['width'],$size['height']);
$white = ImageColorAllocate($im, 255, 255, 255);
$black = ImageColorAllocate($im, 0,0,0);
imagefill ($im, 0, 0, $white );
imagettftext($im, $fontsize, 0, $size['xOffset'], $size['yOffset'],
$black, $font, $text);
$im = imagerotate( $im,$angle, $white);
imagecolortransparent ($im,$white);
}else{
// No text
}
}
?>
===============================================================================
Apparently the bounding box returned by imagettftext and imagettfbbox is not
the same, and it appears as though imagettftext does a better job at
calculating the actual bounding box (maybe because it has to render every
character and it then finds out really everywhere it rendered).
So, you can create a dummy image render the text to it and get a better box.
Here is an example function:
If you use this a lot, it would be better to keep one dummy image instead of
continually creating and destroying images.
===============================================================================
Several comments show that the output of this function is often not what is
expected, especially when the text is rotated.
For those of you who'd like a visual representation of what is happening to the
bounding box as the text is rotated, take a look here:
http://ruquay.com/sandbox/imagettf/
===============================================================================
An improvement to the convertBoundingBox function. The previous function was
completely wrong. My confusion came from characters like "1" and "_" that are
rendered to the right or below the basepoint (in the font I'm using). I ended
up using mike at mikeleigh dot com's function with a fix for these characters,
and a "belowBasepoint" value.
= -1)
$xOffset = -abs($bbox[0] + 1);
else
$xOffset = abs($bbox[0] + 2);
$width = abs($bbox[2] - $bbox[0]);
if ($bbox[0] < -1) $width = abs($bbox[2]) + abs($bbox[0]) - 1;
$yOffset = abs($bbox[5] + 1);
if ($bbox[5] >= -1) $yOffset = -$yOffset; // Fixed characters below the
baseline.
$height = abs($bbox[7]) - abs($bbox[1]);
if ($bbox[3] > 0) $height = abs($bbox[7] - $bbox[1]) - 1;
return array(
'width' => $width,
'height' => $height,
'xOffset' => $xOffset, // Using xCoord + xOffset with imagettftext puts
the left most pixel of the text at xCoord.
'yOffset' => $yOffset, // Using yCoord + yOffset with imagettftext puts
the top most pixel of the text at yCoord.
'belowBasepoint' => max(0, $bbox[1])
);
}
?>
===============================================================================
It took me some time to make full use of imagettfbbox. Hopefully the following
function makes it much easier to use for others.
= -1)
$leftOfBasepoint = -abs($bbox[0] + 1);
else
$leftOfBasepoint = abs($bbox[0] + 2);
$rightOfBasepoint = abs($bbox[2] - $bbox[0]);
if ($bbox[0] < -1) $rightOfBasepoint = abs($bbox[2]) + abs($bbox[0]) - 1;
$aboveBasepoint = abs($bbox[5] + 1);
$height = abs($bbox[7]) - abs($bbox[1]);
if ($bbox[3] > 0) $height = abs($bbox[7] - $bbox[1]) - 1;
$width = $leftOfBasepoint + $rightOfBasepoint;
$belowBasepoint = $height - $aboveBasepoint;
return array(
'width' => $width,
'height' => $height,
'leftOfBasepoint' => $leftOfBasepoint,
'rightOfBasepoint' => $rightOfBasepoint,
'aboveBasepoint' => $aboveBasepoint,
'belowBasepoint' => $belowBasepoint
);
}
?>
Thanks goes to mike at mikeleigh dot com for providing the core of this
function.
Remember, the basepoint is the x, y coords you use to draw text with
imagettftext. A useful thing to do is take a string like...
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890
...and use the "aboveBasepoint" value for the height of your font. Now you can
draw lines and use "the height of your font * leading" as the distance between
lines of text, where leading is a number like 1.45 (for 45% leading).
===============================================================================
This script shows you side by side the difference between a font rendered at a
certain size and the same font rendered at some multiple of that size and then
scaled down by the same multiple. It seems to help small sizes and affects
large ones less. This script lets you see if it is worth implementing for your
situation. Included is the great "imagettfbboxextended" function by mike at
mikeleigh dot com below.
$size = 30;
$factor = 16;
$smallSize = imagettfbboxextended($size, 0, "fonts/MPlantin.ttf", "The quick
brown fox jumps over the lazy dog.");
$smallWidth = $smallSize['width'];
$smallHeight = $smallSize['height'];
$canvas = imagecreatetruecolor($smallWidth + 20, $smallHeight * 2 + 20);
imagefill($canvas, 0, 0, imagecolorallocate($canvas, 255, 255, 255));
imagettftext($canvas, $size, 0, 10 + $smallSize['x'], 10 + $smallSize['y'],
imagecolorallocate($canvas, 0, 0, 0), "fonts/MPlantin.ttf", "The quick brown
fox jumps over the lazy dog.");
$largeSize = imagettfbboxextended($size * $factor, 0, "fonts/MPlantin.ttf",
"The quick brown fox jumps over the lazy dog.");
$largeWidth = $largeSize['width'];
$largeHeight = $largeSize['height'];
$temp = imagecreatetruecolor($largeWidth, $largeHeight);
imagefill($temp, 0, 0, imagecolorallocate($canvas, 255, 255, 255));
imagettftext($temp, $size * $factor, 0, $largeSize['x'], $largeSize['y'],
imagecolorallocate($temp, 0, 0, 0), "fonts/MPlantin.ttf", "The quick brown fox
jumps over the lazy dog.");
imagecopyresampled($canvas, $temp, 10 + $smallSize['x'], 10 + $smallSize['y'] +
10, 0, 0, $smallWidth, $smallHeight, $largeWidth, $largeHeight);
imagepng($temp, "temp.png");
imagepng($canvas, "test.png");
function imagettfbboxextended($size, $angle, $fontfile, $text) {
/*this function extends imagettfbbox and includes within the returned array
the actual text width and height as well as the x and y coordinates the
text should be drawn from to render correctly. This currently only works
for an angle of zero and corrects the issue of hanging letters e.g. jpqg*/
$bbox = imagettfbbox($size, $angle, $fontfile, $text);
//calculate x baseline
if($bbox[0] >= -1) {
$bbox['x'] = abs($bbox[0] + 1) * -1;
} else {
//$bbox['x'] = 0;
$bbox['x'] = abs($bbox[0] + 2);
}
//calculate actual text width
$bbox['width'] = abs($bbox[2] - $bbox[0]);
if($bbox[0] < -1) {
$bbox['width'] = abs($bbox[2]) + abs($bbox[0]) - 1;
}
//calculate y baseline
$bbox['y'] = abs($bbox[5] + 1);
//calculate actual text height
$bbox['height'] = abs($bbox[7]) - abs($bbox[1]);
if($bbox[3] > 0) {
$bbox['height'] = abs($bbox[7] - $bbox[1]) - 1;
}
return $bbox;
}
===============================================================================
Ralph Bolton commented about the difference in calculating the bounding box
size vs. aligning text base line.
The workaround for this issue is to calculate the difference in height between
a character going below baseline and one above the baseline. This is likely
going to vary from font to font, so I'd suggest something like this:
This is not perfect yet. You should define a range of allowed characters that
can go below baseline, compare them to the ones actually found in your string
and use them instead of the string $test3 used in the example function above.
This should avoid problems with letters that go further below baseline than the
others (e.g. there could be a difference between 'g' and 'p')
===============================================================================
There's a bit of an annoyance with measuring font sizes and drawing boxes
around text. When fonts are measured using ImageTTFbbox, the correct vertical
height is returned. That is, the measurement of the phrase "Hanging" will be
from the top of the "H" to the bottom of the "g".
The problem is that functions like imageTTFtext align with the "line" of the
text - that is, in the phrase "Hanging", the alignment is below the "H", not
the bottom of the "g". That means that if you draw a rectangle behind your
text, it'll be incorrectly aligned because the hanging "g" will be outside the
box.
For example, this doesn't work as you might expect (because the "g" hangs below
the box):
It also seems that the rectangle in the above example is located 1 pixel to the
left of the text.
I haven't found a way to resolve this problem correctly. Instead, I have
enlarged the rectangle and then put the text into it. I don't think this will
work absolutely correctly for all fonts, so it's not exactly a perfect
solution. However, it's better than nothing! Here is a snippet of it:
===============================================================================
Warning:
james.logsdon's function has a few flaws in copying my own function. Though he
did a great job in making an overall nicer looking function it does have a few
flaws.
His function does not allow for long words (longer then the width) linebreaks
(harder then it looks) and has a non-pixel perfect location.
The problem with the imagettfbbox function is that different letters give a
different x/y top-left coordinate. At least it looks that way for the eye. I
'solved' this by putting a space in front of every line and then offset the
text by the width of that space.
So, although some things of my function seem useless they do serve an important
purpose.
===============================================================================
I've modified Nimja's function a little. It doesn't support line-breaks (didn't
need it in my script), but it's easy enough to add in.
$Width )
{
$Lines[] = trim ( $Line );
$Line = '';
}
$Line .= $Word . ' ';
}
$Lines[] = trim ( $Line );
$Dimensions = imagettfbbox ( $FontSize, 0, $Font, 'AJLMYabdfghjklpqry019`@$
^&*(,' );
$lineHeight = $Dimensions[1] - $Dimensions[5];
return array ( $lineHeight, $Lines, $lineHeight * count ( $Lines ) );
}
function imageWordWrap ( $Text, $Width, $Color, $X = 0, $Y = 0, $FontSize = 10,
$Font = './fonts/arial.ttf' )
{
$Data = $this->imageWordWrapBBox ( $Text, $Width, $FontSize, $Font );
foreach ( $Data[1] as $Key => $Line )
{
$locX = $X;
$locY = $Y + ( $Key * $Data[0] );
imagettftext ( $this->Image, $FontSize, 0, $locX, $locY, $Color, $Font,
$Line );
}
return $Data;
}
?>
===============================================================================
Neither Greg's or Henrik N's code worked for me.
I figured out that imagettfbbox gives the size (coordinates) of the whole
letter (ie. with the hang on 'g' or 'j'). So it was only a matter of finding
the correct index of coordinates in the array.
Note: This doesn't work on Times New Roman Italic's 'f' for some reason.
===============================================================================
Tried Greg's code below, but it didn't quite work for me. This did, however:
===============================================================================
Have a problem with imagettfbbox cutting off the hang of letters such as 'g' or
'j'??
After days trying to figure this thing out, I finally cracked it:
$size = imagettfbbox($s,0,$font,$text);
$dx=abs($size[0])+abs($size[2]);
$dy=abs($size[1])+abs($size[7]);
ImageTTFText($im, $s, 0, $dx-abs($size[0]), $dy-abs($size[1]), $black, $font,
$text);
The key is the abs commands - you must account for the negative numbers in the
original imagettfbbox, and if you have any, take them away from the location at
the end when the text is displayed:
you need to start the x and y at a (possibly) negative number, not 0,0 as I had
thought.
Hope that helps someone..
===============================================================================
My previous function had 2 bugs which are now fixed:
* Align is now pixel perfect, no longer dependant on the first character.
Solved by putting a space " " in front of every rendered line, making the
basepoint at the exact same place every time.
* X Y Coordinates are no longer the base-point, but the perfect top/left
coordinates. This made my life designing a LOT easier.
Features:
* Newline support! (both Windows and Linux)
* Paragraph support, no newlines are ignored, not even empty ones. So empty
lines are properly supported.
* True top/left x/y coordinates instead of TTF basepoint.(at least as close as
possible).
* Align function for Left, Center and Right
* Support for words that are longer then the supported width.
$width && !empty($line) ) { // check if it is too
big if the word was added, if so, then move on.
$dstLines[] = ' '.trim($line); //Add the line like it was
without spaces.
$line = '';
}
$line .= $word.' ';
}
$dstLines[] = ' '.trim($line); //Add the line when the line ends.
}
//Calculate lineheight by common characters.
$dimensions = imagettfbbox($textSize, 0, $font, "MXQJPmxqjp123"); //use a
custom string to get a fixed height.
$lineHeight = $dimensions[1] - $dimensions[5]; // get the heightof this
line
$align = strtolower(substr($align,0,1)); //Takes the first letter and
converts to lower string. Support for Left, left and l etc.
foreach ($dstLines as $nr => $line) {
if ($align != "l") {
$dimensions = imagettfbbox($textSize, 0, $font, $line);
$lineWidth = $dimensions[4] - $dimensions[0]; // get the length of
this line
if ($align == "r") { //If the align is Right
$locX = $x + $width - $lineWidth;
} else { //If the align is Center
$locX = $x + ($width/2) - ($lineWidth/2);
}
} else { //if the align is Left
$locX = $x;
}
$locY = $y + ($nr * $lineHeight);
//Print the line.
imagettftext($img, $textSize, 0, $locX, $locY, $color, $font, $line);
}
}
?>
===============================================================================
Another function for centered text string.
What it does: Generate a truecolor .png image of a text string. The image will
be just large enough encompass the text and a 2 px border and the text will be
centered in it.
It is called from any other page like so...
// Text with #&+"'\
<> will need to be escaped, but I've found spaces don't cause errors. I haven't
tested this with any other languages.
The following code is the file named linkImg.php
The file was not designed to have anything else here with it, and the open and
close php tags should the the very first and very last characters of the page
respectively, as outside whitespace can be a little evil sometimes.
Hope this helps someone!
-Patrick-
===============================================================================
I have revised my mb_wordwrap function to fix 2 major bugs: cannot handle line
break and infinite loop while handling very very long long long single byte
word.
$width || $sbs_line_width >=
$width) {
// If last word is alphanumeric, put it to next line rather then
cut it off
if ($single_byte_stack != "" && is_alphanumeric($this_char,
$single_byte_stack) && $sbs_line_width < $width) {
$stack_len = mb_strlen($single_byte_stack);
$this_line_strlen = $this_line_strlen - $stack_len + 1;
$pointer = $pointer - $stack_len + 1;
}
// Move the current line to result array and reset all counter
$result_lines[] = mb_substr($txt, $this_line_start,
$this_line_strlen-1);
if ($this_is_cr) { $pointer++; $this_is_cr=FALSE; }
if ($sbs_line_width >= $width) $sbs_line_width = 0;
$this_line_start = $pointer;
$this_line_strlen = 1;
$single_byte_stack = "";
} else {
if (!is_alphanumeric($this_char, $single_byte_stack)) {
$single_byte_stack = ""; // Clear stack if met multibyte
character and not line end
}
$this_line_strlen++;
$pointer++;
}
}
// Move remained word to result
$result_lines[] = mb_substr($txt, $this_line_start);
return $result_lines;
}
function is_alphanumeric($character, $stack) {
if (
(ord($character)>=48 && ord($character)<=57) ||
(ord($character)>=65 && ord($character)<=91) ||
(ord($character)>=97 && ord($character)<=123) ||
ord($character)==40 ||
ord($character)==60 ||
($stack=="" && (ord($character)==34 || ord($character)==39))
) return TRUE;
else return FALSE;
}
?>
===============================================================================
see http://php.rinet.ru/manual/ru/function.imagettftext.php#57416
function ByteCount($s) {
$has_mbstring = extension_loaded('mbstring') ||@dl
(PHP_SHLIB_PREFIX.'mbstring.'.PHP_SHLIB_SUFFIX);
$has_mb_shadow = (int) ini_get('mbstring.func_overload');
if ($has_mbstring && ($has_mb_shadow & 2) ) {
$size = mb_strlen($s,'latin1');
} else {
$size = strlen($s);
}
return $size;
}
function foxy_utf8_to_nce($s) {
$utf = "$s";
$max_count = 5; // flag-bits in $max_mark ( 1111 1000 == 5 times 1)
$max_mark = 248; // marker for a (theoretical ;-)) 5-byte-char and mask for a
4-byte-char;
$html = '';
$ByteCount = ByteCount($utf);
for($str_pos = 0; $str_pos < $ByteCount; $str_pos++) {
$old_chr = $utf{$str_pos};
$old_val = ord($old_chr);
$new_val = 0;
$utf8_marker = 0;
// skip non-utf-8-chars
if ($old_val > 127) {
$mark = $max_mark;
for ($byte_ctr = $max_count; $byte_ctr > 2; $byte_ctr--) {
// actual byte is utf-8-marker?
if (($old_val & $mark) == (($mark << 1) & 255)) {
$utf8_marker = $byte_ctr - 1;
break;
}
$mark = ($mark << 1) & 255;
}
}
// marker found: collect following bytes
if ($utf8_marker > 1 and isset($utf{$str_pos + 1})) {
$str_off = 0;
$new_val = $old_val & (127 >> $utf8_marker);
for($byte_ctr = $utf8_marker; $byte_ctr > 1; $byte_ctr--) {
// check if following chars are UTF8 additional data blocks
// UTF8 and ord() > 127
if( (ord($utf{$str_pos + 1}) & 192) == 128 ) {
$new_val = $new_val << 6;
$str_off++;
// no need for Addition, bitwise OR is sufficient
// 63: more UTF8-bytes; 0011 1111
$new_val = $new_val | ( ord( $utf{$str_pos + $str_off} ) & 63 );
}
// no UTF8, but ord() > 127
// nevertheless convert first char to NCE
else {
$new_val = $old_val;
}
}
// build NCE-Code
$html .= ''.$new_val.';';
// Skip additional UTF-8-Bytes
$str_pos = $str_pos + $str_off;
} else {
$html .= chr($old_val);
//$new_val = $old_val;
}
}
return $html;
}
===============================================================================
Most of functions shared here seems only work with western language and is not
suitable for multibyte characters (like Chinese). I have written a function
using mb_string functions to match the need of multibyte character word
wrapping.
I also added some machanism so that English word won't be cut off at the end of
line. Of couse you must use unicode string on GD.
function mb_wordwrap($txt,$font,$size,$width) {
$pointer = 0;
$this_line_start = 0;
$this_line_strlen = 1;
$single_byte_stack = "";
$result_lines = array();
while ($pointer <= mb_strlen($txt)) {
$this_char = mb_substr($txt,$pointer,1);
$tmp_line = mb_substr($txt, $this_line_start, $this_line_strlen);
$tmp_line_bbox = imagettfbbox($size,0,$font,$tmp_line);
$this_line_width = $tmp_line_bbox[2]-$tmp_line_bbox[0];
if ($this_line_width > $width) {
// If last word is alphanumeric, put it to next line rather then
cut it off
if ($single_byte_stack != "") {
$stack_len = mb_strlen($single_byte_stack);
$this_line_strlen -= $stack_len;
$pointer -= $stack_len;
}
$result_lines[] = mb_substr($txt, $this_line_start,
$this_line_strlen-1);
$this_line_start = $pointer;
$this_line_strlen = 1;
$single_byte_stack = "";
} else {
// Prevent to cut off english word at the end of line
// if this character is a alphanumeric character or open bracket,
put it into stack
if (
(ord($this_char)>=48 && ord($this_char)<=57) ||
(ord($this_char)>=65 && ord($this_char)<=91) ||
(ord($this_char)>=97 && ord($this_char)<=123) ||
ord($this_char)==40 ||
ord($this_char)==60 ||
($single_byte_stack=="" && (ord($this_char)==34 || ord
($this_char)==39))
) $single_byte_stack .= $this_char;
else $single_byte_stack = ""; // Clear stack if met multibyte
character and not line end
$this_line_strlen++;
$pointer++;
}
}
// Move remained word to result
$result_lines[] = mb_substr($txt, $this_line_start);
return $result_lines;
}
===============================================================================
TTF character charmap page
Could use some help in reading ttf file
so that unused rectangle chars are filtered out of the charmap
see
http://www.phpenabled.com/ttf_fontlist/
fontlist.php?font=Phones_NormalA.ttf
===============================================================================
I would like to post a small modification to the imageprintWordWrapped() posted
below also.
The following code causes each line to start with a space, which results in the
incorrect alignment of text:
$line .= ' '.$words[0]; // add the word to the current sentence
A (quick) fix for this problem:
$line .= ($line != '' ? ' ' : '').$words[0]; // add the word to the current
sentence
===============================================================================
I would modify the last function imageprintWordWrapped() posted below. When it
says:
// do the actual printing
$i = 0;
$i should be equal to 1, because if $top is greater than 0, the imagettftext()
call will not work for the first element in the $lines array ($top +
lineHeight*$i) == $top when $i=0!
imagettftext($image, $textSize, 0, $leftStart, $top + $lineHeight * $i, $color,
$font, $line);
$i++;
To sum up, replace
// do the actual printing
$i = 0;
with:
// do the actual printing
$i = 1;
Cheers,
Marcelo
===============================================================================
Just for the sake of consistency, I turned Miles' function into one that takes
a $right value rather than a $maxWidth value. This makes it like all the other
image* functions.
0) {
$dimensions = imagettfbbox($textSize, 0, $font, $line.' '.$words[0]);
$lineWidth = $dimensions[2] - $dimensions[0]; // get the length of this
line, if the word is to be included
if ($lineWidth > $maxWidth) { // if this makes the text wider that
anticipated
$lines[] = $line; // add the line to the others
$line = ''; // empty it (the word will be added outside the loop)
}
$line .= ' '.$words[0]; // add the word to the current sentence
$words = array_slice($words, 1); // remove the word from the array
}
if ($line != '') { $lines[] = $line; } // add the last line to the others,
if it isn't empty
$lineHeight = $dimensions[1] - $dimensions[7]; // the height of a single
line
$height = count($lines) * $lineHeight; // the height of all the lines total
// do the actual printing
$i = 0;
//print_R($widths);
foreach ($lines as $line) {
if($halign=="center") {
//figure out width of line
$dimensions = imagettfbbox($textSize, 0, $font, $line);
$lineWidth = $dimensions[2] - $dimensions[0];
//figure out where the center is.
$center=floor($maxWidth/2 + $left);
$leftStart=$center-$lineWidth/2;
} else if ($halign=="right") {
//figure out width of line
$dimensions = imagettfbbox($textSize, 0, $font, $line);
$lineWidth = $dimensions[2] - $dimensions[0];
$leftStart=$left+$maxWidth-$lineWidth;
} else {
$leftStart=$left;
}
imagettftext($image, $textSize, 0, $leftStart, $top + $lineHeight * $i,
$color, $font, $line);
$i++;
}
return $height;
}
?>
===============================================================================
Here is a slight modification to the function posted below that vegard posted
that allows for left, right or center alignment within the text boxes.
$halign has a default of left. center, and right can also be put in.
0) {
$dimensions = imagettfbbox($textSize, 0, $font, $line.' '.$words[0]);
$lineWidth = $dimensions[2] - $dimensions[0]; // get the length of this
line, if the word is to be included
if ($lineWidth > $maxWidth) { // if this makes the text wider that
anticipated
$lines[] = $line; // add the line to the others
$line = ''; // empty it (the word will be added outside the loop)
}
$line .= ' '.$words[0]; // add the word to the current sentence
$words = array_slice($words, 1); // remove the word from the array
}
if ($line != '') { $lines[] = $line; } // add the last line to the others,
if it isn't empty
$lineHeight = $dimensions[1] - $dimensions[7]; // the height of a single
line
$height = count($lines) * $lineHeight; // the height of all the lines total
// do the actual printing
$i = 0;
//print_R($widths);
foreach ($lines as $line) {
if($halign=="center") {
//figure out width of line
$dimensions = imagettfbbox($textSize, 0, $font, $line);
$lineWidth = $dimensions[2] - $dimensions[0];
//figure out where the center is.
$center=floor($maxWidth/2 + $left);
$leftStart=$center-$lineWidth/2;
} else if ($halign=="right") {
//figure out width of line
$dimensions = imagettfbbox($textSize, 0, $font, $line);
$lineWidth = $dimensions[2] - $dimensions[0];
$leftStart=$left+$maxWidth-$lineWidth;
} else {
$leftStart=$left;
}
imagettftext($image, $textSize, 0, $leftStart, $top + $lineHeight * $i,
$color, $font, $line);
$i++;
}
return $height;
}
?>
===============================================================================
according function by jtopland at hive dot no
08-Feb-2004 03:26
soukhinov at mail dot ru was right, the function doesn't work with 180 . By the
way it was a intresting way to trasform the angle to radian. Change the
calculation of the angle to the following: $angle = $angle/ 180 * pi();
The function to calc. the points is correct. Sorry to say this, but the cal. of
the height and width is incorrect. I used the version from LB (11-Feb-2004
08:55)
/**
* return width and height, offset [left, top] of a ttf character
* @param string $font : the font file
* @param string $text : the character
* @param int $size : the font size
* @param int $angle : the angle
* @access private
* @return array of the width and height, left and top.
**/
function _getCharacterSize($font, $text, $size, $angle)
{
// Get the boundingbox from imagettfbbox(), which is correct when
angle is 0
$bbox = imagettfbbox($size, 0, $font, $text);
// Rotate the boundingbox
$angle = $angle/ 180 * pi();
for ($i=0; $i<4; $i++)
{
$x = $bbox[$i * 2];
$y = $bbox[$i * 2 + 1];
$bbox[$i * 2] = cos($angle) * $x - sin($angle) * $y; // X
$bbox[$i * 2 + 1] = sin($angle) * $x + cos($angle) * $y; // Y
}
// Variables which tells the correct width and height
$bbox["left"] = 0- min($bbox[0],$bbox[2],$bbox[4],$bbox[6]);
$bbox["top"] = 0- min($bbox[1],$bbox[3],$bbox[5],$bbox[7]);
$bbox["width"] = max($bbox[0],$bbox[2],$bbox[4],$bbox[6]) - min($bbox
[0],$bbox[2],$bbox[4],$bbox[6]);
$bbox["height"] = max($bbox[1],$bbox[3],$bbox[5],$bbox[7]) - min($bbox
[1],$bbox[3],$bbox[5],$bbox[7]);
return $bbox;
}
===============================================================================
Pretty trivial, but still might save someone some trouble: on my system (Debian
Linux), the absolute path to the font file had to be specified. I tried it
relative to the current webpage and that did not work.
===============================================================================
Here is a function that wordwraps text you want to print, allows to specify
where the text should be printed, what the maximum width should be, and returns
the height used.
0) {
$dimensions = imagettfbbox($textSize, 0, $font, $line.'
'.$words[0]);
$lineWidth = $dimensions[2] - $dimensions[0]; // get
the length of this line, if the word is to be included
if ($lineWidth > $maxWidth) { // if this makes the text
wider that anticipated
$lines[] = $line; // add the line to the others
$line = ''; // empty it (the word will be added
outside the loop)
}
$line .= ' '.$words[0]; // add the word to the current
sentence
$words = array_slice($words, 1); // remove the word
from the array
}
if ($line != '') { $lines[] = $line; } // add the last line to
the others, if it isn't empty
$lineHeight = $dimensions[1] - $dimensions[7]; // the height of
a single line
$height = count($lines) * $lineHeight; // the height of all the
lines total
// do the actual printing
$i = 0;
foreach ($lines as $line) {
imagettftext($image, $textSize, 0, $left, $top +
$lineHeight * $i, $color, $font, $line);
$i++;
}
return $height;
}
?>
===============================================================================
I have tryed all of fixes
The David Eder's fix is the only working fix.
The "jtopland at hive dot no"s fix is good enough, but it not working with
angle = 180 degrees.
===============================================================================
Here is a function which moves the center of text's bounding
box to a given pivot point (px,py) and rotates text about
that point.
===============================================================================
I took Magicaltux's word wrap procedure and modified it in two ways. I changed
the order of processing so that the string plotting function is called only
once for each word instead of for every character. And I wrote the results to
a string scalar instead of a string array, with embedded breaks
at line
ends. It should run pretty fast. Mine breaks only on spaces, but hyphens
could easily be added.
I'm new to PHP so I apologize for my idiosyncratic formatting conventions.
function myWordWrap($txt,$font,$size,$width)
{
/*
word-wrapper. gets bounding box sizes for each word in a string, then
strings words together up to desired width. calls strpos and
imagettfbbox only once per word - so very fast.
this version reconcatenates the words with a
character where
the line break should be.
*/
$txt.=" "; // guaranteed to find end of line
$spaces=array();
$wids=array();
$i=0;
while(true)
{
$j=strpos(substr($txt,$i)," ");
if(!($j===false))
{
$spaces[]=$j+$i;
$bbox=imagettfbbox($size,0,$font,substr($txt,$i,$j+1));
$left=($bbox[0]>$bbox[6])?$bbox[6]:$bbox[0];
$right=($bbox[2]>$bbox[4])?$bbox[2]:$bbox[4];
$wids[]=$right-$left;
$i=$j+$i+1;
}
else break;
}
$lastspace=-1;
$cum=0;
$t2="";
for($i=0;$i0)&&($cum+$wids[$i])>$width)) // time for a line break
{
$t2.="
";
$cum=0;
$i--;
}
else
{
// we'll always get at least one word (even if too wide) thanks to
// ($cum>0) test above
$t2.=substr($txt,$lastspace+1,$spaces[$i]-$lastspace);
$cum+=$wids[$i];
$lastspace=$spaces[$i];
}
}
return $t2;
}
?>
===============================================================================
the oliver dot martin at onemail dot fixbbox function is just lacking a small
thing:
the coordonates for top and left have to be the opposite, because the
imagettftext x and y coordonates are calculated from the top left of the image
and set the bottom left of the first character.
The correct function is:
function fixbbox($bbox)
{
$tmp_bbox["left"] = min($bbox[0],$bbox[2],$bbox[4],$bbox[6]);
$tmp_bbox["top"] = min($bbox[1],$bbox[3],$bbox[5],$bbox[7]);
$tmp_bbox["width"] = max($bbox[0],$bbox[2],$bbox[4],$bbox[6]) -
min($bbox[0],$bbox[2],$bbox[4],$bbox[6]) + 1;
$tmp_bbox["height"] = max($bbox[1],$bbox[3],$bbox[5],$bbox[7]) - min($bbox
[1],$bbox[3],$bbox[5],$bbox[7]);
$tmp_bbox["left"] = 0 - $tmp_bbox["left"];
$tmp_bbox["top"] = 0 - $tmp_bbox["top"];
return $tmp_bbox;
}
And it works for any rotated text.
===============================================================================
As "oliver dot martin at onemail dot at" noted above, imagettfbbox() does not
work correctly in php 4.3.4. To remedy this, I've written a short function
that uses trig to calculate the bounding box from rotating a non-rotated piece
of text.
Hopefully, this comment will be obsolete soon, but for now, ...
function imagettfbbox_t($size, $angle, $fontfile, $text)
{
// compute size with a zero angle
$coords = imagettfbbox($size, 0, $fontfile, $text);
// convert angle to radians
$a = $angle * M_PI / 180;
// compute some usefull values
$ca = cos($a);
$sa = sin($a);
$ret = array();
// perform transformations
for($i = 0; $i < 7; $i += 2)
{
$ret[$i] = round($coords[$i] * $ca + $coords[$i+1] * $sa);
$ret[$i+1] = round($coords[$i+1] * $ca - $coords[$i] * $sa);
}
return $ret;
}
===============================================================================
The original fixbox function by doesn't
work when the text is rotated, as it assumes that the upper left corner of the
text is also the upper left corner of the bounding box. Same goes for the lower
right corner. Here is my corrected version of it:
function fixbbox($bbox)
{
$tmp_bbox["left"] = min($bbox[0],$bbox[2],$bbox[4],$bbox[6]);
$tmp_bbox["top"] = min($bbox[1],$bbox[3],$bbox[5],$bbox[7]);
$tmp_bbox["width"] = max($bbox[0],$bbox[2],$bbox[4],$bbox[6]) - min($bbox
[0],$bbox[2],$bbox[4],$bbox[6]);
$tmp_bbox["height"] = max($bbox[1],$bbox[3],$bbox[5],$bbox[7]) - min($bbox
[1],$bbox[3],$bbox[5],$bbox[7]);
return $tmp_bbox;
}
?>
However, be aware that this might not be very useful, as gd-2.0.8 introduces a
bug which renders the results of imagettfbbox() useless when the text is
rotated. This is still not fixed in the the php-4.3.4 bundled version (2.0.15
compatible).
===============================================================================
One use of this function is to do some WordWrap =p
I wrote a little function to make a basic wordwrap : it returns an array with
each line in a row.
You just have to display each row on a different line (calling many times
imagettftext) to get a good result.
The character ^ is assumed as a linebreak.
$bbox[6])?$bbox[6]:$bbox[0]; // determine most far
points
$right=($bbox[2]>$bbox[4])?$bbox[2]:$bbox[4]; // idem
$w=$right-$left; // get total width
if ($w>$width) {
if ($buf=='') return false; // FATAL: 1 letter is smallest than the
pixel width - avoid infinite loop
// we can assume that everything present in $buf currently is
inside our limits
// find a separator in string
$fp=false;
foreach($sep as $s) {
$p=strrpos($buf,$s);
if (($p!==false) and ($p>$fp)) $fp=$p;
}
if ($fp===false) {
// let's break here !
$res[]=$buf;
$buf='';
$i--; // dececrase $i to retry this letter
continue;
}
// $fp+1 -> we put the separator char at the end of the prev. line
=p
$res[]=substr($buf,0,$fp+1);
$buf=substr($buf,$fp+1);
$i--;
continue;
}
$buf.=$l;
}
if ($buf!='') $res[]=$buf;
return $res;
}
?>
===============================================================================
The array this function returns is very strange, at least, i think so... So i
created this function that 'fixes' the bounding box array into some
human-understandable format
===============================================================================
There seems to be a little confusion regarding the font coordinate system.
PHP's TTF functions will make more sense after you understand the principals of
font creation. This guy wrote a really good overview...
http://pfaedit.sourceforge.net/overview.html
===============================================================================
This is a completely rewritten function of "printWordWrapped" because it lacked
a few important features. First of all, it started too high with it's text,
which was easily fixed. And it has the annoying 'feature' of adding a space in
front of every line. Not ideal.
But secondly, and more importantly, it didn't support long words or linebreaks.
This is all fixed. And I rewrote it for cleaner code.
Please note that with the current code you could easily make a vertical align
as well if you wanted to. I have not done this myself since it did not fit my
own needs (and I'm slightly lazy)
Enjoy:
$width && !empty($line) ) { // check if it is too
big if the word was added, if so, then move on.
$dstLines[] = trim($line); //Add the line like it was without
spaces.
$line = '';
}
$line .= $word.' ';
}
$dstLines[] = trim($line); //Add the line when the line ends.
}
//Calculate lineheight by common characters.
$dimensions = imagettfbbox($textSize, 0, $font, "MXQJPmxqjp123"); //use a
custom string to get a fixed height.
$lineHeight = $dimensions[1] - $dimensions[5]; // get the heightof this
line
$align = strtolower(substr($align,0,1)); //Takes the first letter and
converts to lower string. Support for Left, left and l etc.
foreach ($dstLines as $nr => $line) {
if ($align != "l") {
$dimensions = imagettfbbox($textSize, 0, $font, $line);
$lineWidth = $dimensions[4] - $dimensions[0]; // get the length of
this line
if ($align == "r") { //If the align is Right
$locX = $x + $width - $lineWidth;
} else { //If the align is Center
$locX = $x + ($width/2) - ($lineWidth/2);
}
} else { //if the align is Left
$locX = $x;
}
$locY = $y + ($nr * $lineHeight);
//Print the line.
imagettftext($img, $textSize, 0, $locX, $locY, $color, $font, $line);
}
}
?>


An example of a process actor
The Process suite (processActor, processHand, processAlg) implements a
"do-nothing" process actor which accepts an input and copies it unchanged
to its output. As an example of a modifying message, it accepts one
parameter "ModIndex" which scales the amplitude of its output. It is
intended as a starting point for writing other process actors.
To use this process implementation (just to prove that it works, we suppose),
load process.so and create an actor of type ProcessActor.
ProcessActor messages
In addition to the messages understood by all generator actors, the ProcessActor understands the following messages:
- SetModIndex hActor x
- Set the default index of modulation for new instances
created by this actor to x.
- SetAllModIndex hActor x time
- Set the index of modulation of all children to x,
and set the default index for all future children.
If time is specified, children will modulate to the new
index over the specified duration. Default index is always
set immediately regardless of time.
ProcessActor handler messages
In addition to the messages understood by all handlers, the handler for
the ProcessActor understands the following messages:
- SetInput hSound hHandler
- Set the input to come from the handler hHandler.
- SetModIndex hSound x time
- Set the index of modulation to x. If
time is specified, move to the new index over the
specified duration.


Previous: -volatile
The word size value does not matter for checking standard-conforming programs that do not declare explicit precisions for non-character variables or store Hollerith data in variables. This setting also does not affect the default size of character variables, which is always 1 byte. Hollerith constants also are assumed to occupy 1 byte per character.
The word size is used to determine whether truncation occurs in assignment statements, and to catch precision mismatches in subprogram argument lists and common block lists. The exact warnings that are issued will depend on the status of other flags. Under both the -portability=mixed-size and the -nowordsize flag, any mixing of explicit with default precision objects (character expressions not included) is warned about. This applies to arithmetic expressions containing both types of objects, and to subprogram arguments and COMMON variables. Under control of the -truncation=demotion and promotion options, a warning is given for assignment of an expression to a shorter variable of the same type, or for promotion of a lower precision value to higher precision in an arithmetic expression or an assignment statement.
Giving a word size of 0, or equivalently, using -nowordsize means that no default value will be assumed. This is equivalent to specifying -portability=mixed-size. Use it to find cases of mixing default and explicit precision, for example to flag places where REAL*8 is treated as equivalent to DOUBLE PRECISION.
See also: -pointersize, -portability, -truncation.
Next: -wrap


We make it easy for you to search for a recipe within your dietary
restricitons, intolerances, or even with whats already in your fridge!
Don't forget the most important part, the MOVIE! Pick
whatever genre you're in the mood for and we'll help you decide what
to watch tonight!


Username
First Name
Last Name
Original size
Thumbnail
Date registered
Total Number of Entries
Email
Twitter
Facebook
Reminders
+ Add new reminder
We’ll help you remember to write in your journal by sending you an email reminder.
Daily @ 08:00
Biographical Info
Share a little biographical information to fill out your profile.
Old Password
New Password
Verify Password


Things to do: Task Label Task Description Make JSON data JSON obj file with team info and schedule info.


SNPs linkage associated OpenUrl allele adaptation alleles loblolly Fst populations genomic selection CrossRef variables genetic climate population Figure frequency Table environmental climatic maps &; species associations pine using SNP Information local natural group analysis map clusters different groups recombination S). located location loci showing Science genome high (Supporting Web distribution individual results small west genes number pairwise principal structure variation Moisture Molecular components effect gene minor significant used Torre adaptive consensus east frequencies large markers pine. Eckert Genetics, Neale Pinus architecture center package physical shifts showed studies suggest suggested variables. Annual FREE Text diversity higher low moderate new populations, variables, Abstract Population Principal cluster eastern increased moisture multiple presence range species. Deficit Ecology, PC, addition, annotation based data differentiation individuals levels model neutral nucleotide smaller taeda values (scaffold Degree-days Genomic Hancock Martinez-Garcia SNPs, Supporting Whitlock clustering identified outlier polygenic species’ study, trait western Climate Evolution, Figures Pritchard Results Temperature aridity association changes co-association component correction disequilibrium distributed environment flow functional geographic groups. increase known major mapping observed position previously regions species, subtle suggesting temperature (p-value Climatic Corre Download GEA Genetic Kremer, LFMM LOD Lotterhos, Mississippi PCA Precipitation View Wang average base common comparing constructed environments humidity implemented included involved maf map. obtained pedigree reference related response result shown standing tested testing), them. tree ultra-dense variable Arabidopsis Biology Consensus Frichot Gonzalez-Martinez Index Linkage Lotterhos Pairwise Plant Qtl SNPs. Schmidtling, Variables Westbrook Yeaman Yeaman, Yoder adapted co-located combinations consistent contribution decreased differentiated distributions divergence estimated genetics genome-wide genomes growth highest important longitude mainly module network newly occurred populations. position), putatively seasonality study test thaliana traits widely widespread winter (AHM) (BIO), (DD_), (LG) (PAS), (cM), AX-, American Average Biology, Construction D). DNA Genetics Heat Ingvarsson Local Map Nelson Open OutFLANK Picea Review Science, Teskey Zhang adaptation. addition analysis. approach conifers considered correlations data-hide-link-title=""> data-icon-position="" dataset, deficit detect did dissect ecological effects evaluated evaluating expression factors fastStructure figure flow, genotyping groups, gymnosperms highly hitchhiking id), increasing index largely latent length locations main markers. mean-squared molecular numbers occurring p-value pairs plots potential precipitation present pressures qtl radiation rapidly recent region represent resulting river scaffold scores selected side) signature significantly sizes, snow sweeps tab whole-genome wide


I'm a 17 year old high school student with a 3.8 GPA and aspirations to attend IU, IUPUI, or Purdue. I can speak four lanuages: English, Spanish, Japanese, and code.
I've taken intro courses into coding. I have experience with HTML, CSS, JavaScript, jQuery, and Python. I'm in the Nextech Catapult internship and have references from companies such as SalesForce and ElevenFifty. You can reach me at my github or click the contact page.
I have no previous job experience but I have completed many extra curricular activities and hours of community service. I am a former member of Upward Bound and Purdue Bound. I'm a member of the Arsenal Technical Marching Band and the Arsenal Tech Technicians (Show Choir). I'm a good public speaker/presenter. I volunteer in my church and I help the FFA (Future Farmers of America) every summer at the Marion County Fair and help them garden at my school.


{{ property.property_name }}
Starting from ₹{{ property.best_price }}/Day
When you need a space for your posse to gather around, big spaces are not fit for your needs. When a group of people want to learn and share ideas, a small space is more appropriate.
Here we are, with spaces that are just right for you ext gathering. At the right prices and the right amount of room, have a delightful time with your clique.


âˆ’ bat sequences (.) viral â€". viruses (tissue pool) sequence [], []. identified analysis bats species contig related RNA virus samples PCR Phylogenetic genome reads Virol: specimens indicated number rotavirus used new read various family {border-style data protein contigs including px;} species, tissue #ffffff;} based diversity vertebrate different endogenous human presence tree viruses, (Table Dis: Infect corresponding mammalian However, Identification Myotis amino-acid polymerase aa) diverse genus obtained partial phylogenetic Emerg detected known large nt) region sequencing specimen taxonomic (A) (Fig. (almost BLASTn Pipistrellus bar disease encoding gene longest novel pooled previously shown (B) (specimen BLASTx DNA Figure [L] alignment bats. nucleotide previous proportion recently relevant species. Bats French Gen []â€"[], additional black bootstrap generated insectivorous lungs pipistrellus respectively. specific study translated values viruses. zoonotic Clin Male RNA-dependent Schematic amplified animal animals branch clarity contact families gammaretrovirus humans indicates length length, main midpoint-rooted nodes. only. performed produced purposes px; representation represented respiratory scale sequences. {font-family â‰¥% (GenBank (named B). Br, Common Hand Illumina Microbiol: Number Viral aa, available bornavirus collected demonstrated detection families, font-size group guano harbor host humans. infecting infection li, major manipulation metagenomic nairovirus pipistrelle plant pol positions potential products rabies results sample selected sequence. sequences, studies total version viromes virus, (> (PDF) (in Bat Borna Click HTS In: LINK Mean PCR/Sanger []â€"[]. acute adenovirus amplification analyses analyzed approximate assembly asterisk. bar, bats, bornavirus-related closely confirmed dashed described distribution double; editors. family, file. fruit genomic given high-throughput insect lung members organs picobirnaviruses position present reservoir retrovirus; role sample, segment shown). transmission using value van virome virus. virus; (nt) DM, Detection European Fields GenBank Howley Knipe PM, Velvet Virology. Wilkins. Williams [RdRp] addition analysis, analysis. associated b). bacteriophages bars basis bioinformatics bold bold, border-color border-width characterization concerning dead differences emerging findings groups high identification identity insects kit levels liver matching mystacinus natural novo particular, population porcine quality reads, reflect remaining report reported retrovirus rotaviruses samples, sequenced short solid; strain study, unassembled unassigned veterinary {font-style {font-weight (%) (Myotis (Pipistrellus (data Ahun Analysis BLAST Bunyaviridae, CLC Dugbe HB. Indeed, Isolation Mammalian MartellaV, Metagenomic Novel ORF Philadelphia: Reference Rhinolophus Rotavirus Sequence Sers UniProt Veterinary Virus [L]d accession accounting animals. b), bats: best biological brain capacity close comparison confirming considered courier; date died direct displayed double-stranded ed. em; epidemiological evidence extraction followed following genera. genetic genetically genomes global health humans, isolated low matched mosaic nairoviruses non nt, order origin particularly primers provided pt;} red). removal reveals searches segments severe showed similar similarity single spread step type virus-related â€"


SHOPI
SHOP
Home
(current)
shop
blog
Previous
Next
Default sorting
Show 12
Previous
1
2
3
Next
addidas new hammer sole for sports person
$75.00
buy
addidas new hammer sole for sports person
$92.50
buy
addidas new hammer sole for sports person
$165.90
buy
addidas new hammer sole for sports person
$75.00
buy
addidas new hammer sole for sports person
$92.50
buy
addidas new hammer sole for sport person
$165.90
buy