package.xml 0000664 0001750 0001750 00000014232 11671375066 013777 0 ustar clockwerx clockwerx
*
* 'x' | This sets the top left coordinates (using x/y) or the center point
* 'y' | coordinates (using cx/cy) for your text box. The values from
* 'cx' | cx/cy will overwrite x/y.
* 'cy' |
*
* 'canvas' | You can set different values as a canvas:
* | - A gd image resource.
* | - An array with 'width' and 'height'.
* | - Nothing (the canvas will be measured after the real text size).
*
* 'antialias' | This is usually true. Set it to false to switch antialiasing off.
*
* 'width' | The width and height for your text box.
* 'height' |
*
* 'halign' | Alignment of your text inside the textbox. Use alignmnet constants to define
* 'valign' | vertical and horizontal alignment.
*
* 'angle' | The angle to rotate your text box.
*
* 'color' | An array of color values. Colors will be rotated in the mode you choose (linewise
* | or paragraphwise). Can be in the following formats:
* | - String representing HTML style hex couples (+ unusual alpha couple in the first place, optional).
* | - Array of int values using 'r', 'g', 'b' and optionally 'a' as keys.
*
* 'color_mode' | The color rotation mode for your color sets. Does only apply if you
* | defined multiple colors. Use 'line' or 'paragraph'.
*
* 'background_color' | defines the background color. NULL sets it transparent
* 'enable_alpha' | if alpha channel should be enabled. Automatically
* | enabled when background_color is set to NULL
*
* 'font_path' | Location of the font to use. The path only gives the directory path (ending with a /).
* 'font_file' | The fontfile is given in the 'font_file' option.
*
* 'font_size' | The font size to render text in (will be overwriten, if you use automeasurize).
*
* 'line_spacing' | Measure for the line spacing to use. Default is 0.5.
*
* 'min_font_size' | Automeasurize settings. Try to keep this area as small as possible to get better
* 'max_font_size' | performance.
*
* 'image_type' | The type of image (use image type constants). Is default set to PNG.
*
* 'dest_file' | The destination to (optionally) save your file.
*
*
* @access public
* @var array
* @see Image_Text::Image_Text(), Image_Text::set()
*/
var $options = array(
// orientation
'x' => 0,
'y' => 0,
// surface
'canvas' => null,
'antialias' => true,
// text clipping
'width' => 0,
'height' => 0,
// text alignment inside the clipping
'halign' => IMAGE_TEXT_ALIGN_LEFT,
'valign' => IMAGE_TEXT_ALIGN_TOP,
// angle to rotate the text clipping
'angle' => 0,
// color settings
'color' => array( '#000000' ),
'color_mode' => 'line',
'background_color' => '#000000',
'enable_alpha' => false,
// font settings
'font_path' => "./",
'font_file' => null,
'font_size' => 2,
'line_spacing' => 0.5,
// automasurizing settings
'min_font_size' => 1,
'max_font_size' => 100,
//max. lines to render
'max_lines' => 100,
// misc settings
'image_type' => IMAGETYPE_PNG,
'dest_file' => ''
);
/**
* Contains option names, which can cause re-initialization force.
*
* @var array
* @access private
*/
var $_reInits = array('width', 'height', 'canvas', 'angle', 'font_file', 'font_path', 'font_size');
/**
* The text you want to render.
*
* @access private
* @var string
*/
var $_text;
/**
* Resource ID of the image canvas.
*
* @access private
* @var ressource
*/
var $_img;
/**
* Tokens (each word).
*
* @access private
* @var array
*/
var $_tokens = array();
/**
* Fullpath to the font.
*
* @access private
* @var string
*/
var $_font;
/**
* Contains the bbox of each rendered lines.
*
* @access private
* @var array
*/
var $bbox = array();
/**
* Defines in which mode the canvas has be set.
*
* @access private
* @var array
*/
var $_mode = '';
/**
* Color indeces returned by imagecolorallocatealpha.
*
* @access public
* @var array
*/
var $colors = array();
/**
* Width and height of the (rendered) text.
*
* @access private
* @var array
*/
var $_realTextSize = array('width' => false, 'height' => false);
/**
* Measurized lines.
*
* @access private
* @var array
*/
var $_lines = false;
/**
* Fontsize for which the last measuring process was done.
*
* @access private
* @var array
*/
var $_measurizedSize = false;
/**
* Is the text object initialized?
*
* @access private
* @var bool
*/
var $_init = false;
/**
* Constructor
*
* Set the text and options. This initializes a new Image_Text object. You must set your text
* here. Optinally you can set all options here using the $options parameter. If you finished switching
* all options you have to call the init() method first befor doing anything further! See Image_Text::set()
* for further information.
*
* @param string $text Text to print.
* @param array $options Options.
* @access public
* @see Image_Text::set(), Image_Text::construct(), Image_Text::init()
*/
function Image_Text($text, $options = null)
{
$this->set('text', $text);
if (!empty($options)) {
$this->options = array_merge($this->options, $options);
}
}
/**
* Construct and initialize an Image_Text in one step.
* This method is called statically and creates plus initializes an Image_Text object.
* Beware: You will have to recall init() if you set an option afterwards manually.
*
* @param string $text Text to print.
* @param array $options Options.
* @access public
* @static
* @see Image_Text::set(), Image_Text::Image_Text(), Image_Text::init()
*/
function &construct ( $text, $options ) {
$itext = new Image_Text($text, $options);
$res = $itext->init();
if (PEAR::isError($res)) {
return $res;
}
return $itext;
}
/**
* Set options
*
* Set a single or multiple options. It may happen that you have to reinitialize the Image_Text
* object after changing options. For possible options, please take a look at the class options
* array!
*
*
* @param mixed $option A single option name or the options array.
* @param mixed $value Option value if $option is string.
* @return bool True on success, otherwise PEAR::Error.
* @access public
* @see Image_Text::Image_Text()
*/
function set($option, $value=null)
{
$reInits = array_flip($this->_reInits);
if (!is_array($option)) {
if (!isset($value)) {
return PEAR::raiseError('No value given.');
}
$option = array($option => $value);
}
foreach ($option as $opt => $val) {
switch ($opt) {
case 'color':
$this->setColors($val);
break;
case 'text':
if (is_array($val)) {
$this->_text = implode('\n', $val);
} else {
$this->_text = $val;
}
break;
default:
$this->options[$opt] = $val;
break;
}
if (isset($reInits[$opt])) {
$this->_init = false;
}
}
return true;
}
/**
* Set the color-set
*
* Using this method you can set multiple colors for your text.
* Use a simple numeric array to determine their order and give
* it to this function. Multiple colors will be
* cycled by the options specified 'color_mode' option. The given array
* will overwrite the existing color settings!
*
* The following colors syntaxes are understood by this method:
* - "#ffff00" hexadecimal format (HTML style), with and without #.
* - "#08ffff00" hexadecimal format (HTML style) with alpha channel (08), with and without #.
* - array with 'r','g','b' and (optionally) 'a' keys, using int values.
* - a GD color special color (tiled,...).
*
* A single color or an array of colors are allowed here.
*
* @param mixed $colors Single color or array of colors.
* @return bool True on success, otherwise PEAR::Error.
* @access public
* @see Image_Text::setColor(), Image_Text::set()
*/
function setColors($colors)
{
$i = 0;
if (is_array($colors) &&
(is_string($colors[0]) || is_array($colors[0]))
) {
foreach ($colors as $color) {
$res = $this->setColor($color,$i++);
if (PEAR::isError($res)) {
return $res;
}
}
} else {
return $this->setColor($colors, $i);
}
return true;
}
/**
* Set a color
*
* This method is used to set a color at a specific color ID inside the
* color cycle.
*
* The following colors syntaxes are understood by this method:
* - "#ffff00" hexadecimal format (HTML style), with and without #.
* - "#08ffff00" hexadecimal format (HTML style) with alpha channel (08), with and without #.
* - array with 'r','g','b' and (optionally) 'a' keys, using int values.
*
* @param mixed $color Color value.
* @param mixed $id ID (in the color array) to set color to.
* @return bool True on success, otherwise PEAR::Error.
* @access public
* @see Image_Text::setColors(), Image_Text::set()
*/
function setColor($color, $id=0)
{
if(is_array($color)) {
if (isset($color['r']) && isset($color['g']) && isset($color['b'])) {
$color['a'] = isset($color['a']) ? $color['a'] : 0;
$this->options['colors'][$id] = $color;
} else if (isset($color[0]) && isset($color[1]) && isset($color[2])) {
$color['r'] = $color[0];
$color['g'] = $color[1];
$color['b'] = $color[2];
$color['a'] = isset($color[3]) ? $color[3] : 0;
$this->options['colors'][$id] = $color;
} else {
return PEAR::raiseError('Use keys 1,2,3 (optionally) 4 or r,g,b and (optionally) a.');
}
} elseif (is_string($color)) {
$color = $this->_convertString2RGB($color);
if ($color) {
$this->options['color'][$id] = $color;
} else {
return PEAR::raiseError('Invalid color.');
}
}
if ($this->_img) {
$aaFactor = ($this->options['antialias']) ? 1 : -1;
if (function_exists('imagecolorallocatealpha') && isset($color['a'])) {
$this->colors[$id] = $aaFactor * imagecolorallocatealpha($this->_img,
$color['r'],$color['g'],$color['b'],$color['a']);
} else {
$this->colors[$id] = $aaFactor * imagecolorallocate($this->_img,
$color['r'],$color['g'],$color['b']);
}
if ($this->colors[$id] == 0 && $aaFactor == -1) {
// correction for black with antialiasing OFF
// since color cannot be negative zero
$this->colors[$id] = -256;
}
}
return true;
}
/**
* Initialiaze the Image_Text object.
*
* This method has to be called after setting the options for your Image_Text object.
* It initializes the canvas, normalizes some data and checks important options.
* Be shure to check the initialization after you switched some options. The
* set() method may force you to reinitialize the object.
*
* @access public
* @return bool True on success, otherwise PEAR::Error.
* @see Image_Text::set()
*/
function init()
{
// Does the fontfile exist and is readable?
// todo: with some versions of the GD-library it's also possible to leave font_path empty, add strip ".ttf" from
// the fontname; the fontfile will then be automatically searched for in library-defined directories
// however this does not yet work if at this point we check for the existance of the fontfile
$font_file = rtrim($this->options['font_path'], '/\\');
$font_file.= (OS_WINDOWS) ? '\\' : '/';
$font_file.= $this->options['font_file'];
$font_file = realpath($font_file);
if (empty($font_file)) {
return PEAR::raiseError('You must supply a font file.');
} elseif (!file_exists($font_file)) {
return PEAR::raiseError('Font file was not found.');
} elseif (!is_readable($font_file)) {
return PEAR::raiseError('Font file is not readable.');
} elseif (!@imagettfbbox(1, 1, $font_file, 1)) {
return PEAR::raiseError('Font file is not valid.');
}
$this->_font = $font_file;
// Is the font size to small?
if ($this->options['width'] < 1) {
return PEAR::raiseError('Width too small. Has to be > 1.');
}
// Check and create canvas
$image_canvas = false;
switch (true) {
case (empty($this->options['canvas'])):
// Create new image from width && height of the clipping
$this->_img = imagecreatetruecolor(
$this->options['width'], $this->options['height']);
if (!$this->_img) {
return PEAR::raiseError('Could not create image canvas.');
}
break;
case (is_resource($this->options['canvas']) &&
get_resource_type($this->options['canvas'])=='gd'):
// The canvas is an image resource
$image_canvas = true;
$this->_img = $this->options['canvas'];
break;
case (is_array($this->options['canvas']) &&
isset($this->options['canvas']['width']) &&
isset($this->options['canvas']['height'])):
// Canvas must be a width and height measure
$this->_img = imagecreatetruecolor(
$this->options['canvas']['width'],
$this->options['canvas']['height']
);
break;
case (is_array($this->options['canvas']) &&
isset($this->options['canvas']['size']) &&
($this->options['canvas']['size'] = 'auto')):
case (is_string($this->options['canvas']) &&
($this->options['canvas'] = 'auto')):
$this->_mode = 'auto';
break;
default:
return PEAR::raiseError('Could not create image canvas.');
}
if ($this->_img) {
$this->options['canvas'] = array();
$this->options['canvas']['width'] = imagesx($this->_img);
$this->options['canvas']['height'] = imagesy($this->_img);
}
if ($this->options['enable_alpha']) {
imagesavealpha($this->_img, true);
imagealphablending($this->_img, false);
}
if ($this->options['background_color'] === null) {
$this->options['enable_alpha'] = true;
imagesavealpha($this->_img, true);
imagealphablending($this->_img, false);
$colBg = imagecolorallocatealpha($this->_img, 255, 255, 255, 127);
} else {
$arBg = $this->_convertString2RGB($this->options['background_color']);
if ($arBg === false) {
return PEAR::raiseError('Background color is invalid.');
}
$colBg = imagecolorallocatealpha($this->_img, $arBg['r'], $arBg['g'], $arBg['b'], $arBg['a']);
}
if ($image_canvas === false) {
imagefilledrectangle(
$this->_img,
0, 0,
$this->options['canvas']['width'] - 1, $this->options['canvas']['height'] - 1,
$colBg
);
}
// Save and repair angle
$angle = $this->options['angle'];
while ($angle < 0) {
$angle += 360;
}
if ($angle > 359) {
$angle = $angle % 360;
}
$this->options['angle'] = $angle;
// Set the color values
$res = $this->setColors($this->options['color']);
if (PEAR::isError($res)) {
return $res;
}
$this->_lines = null;
// Initialization is complete
$this->_init = true;
return true;
}
/**
* Auto measurize text
*
* Automatically determines the greatest possible font size to
* fit the text into the text box. This method may be very resource
* intensive on your webserver. A good tweaking point are the $start
* and $end parameters, which specify the range of font sizes to search
* through. Anyway, the results should be cached if possible. You can
* optionally set $start and $end here as a parameter or the settings of
* the options array are used.
*
* @access public
* @param int $start Fontsize to start testing with.
* @param int $end Fontsize to end testing with.
* @return int Fontsize measured or PEAR::Error.
* @see Image_Text::measurize()
*/
function autoMeasurize($start=false, $end=false)
{
if (!$this->_init) {
return PEAR::raiseError('Not initialized. Call ->init() first!');
}
$start = (empty($start)) ? $this->options['min_font_size'] : $start;
$end = (empty($end)) ? $this->options['max_font_size'] : $end;
$res = false;
// Run through all possible font sizes until a measurize fails
// Not the optimal way. This can be tweaked!
for ($i = $start; $i <= $end; $i++) {
$this->options['font_size'] = $i;
$res = $this->measurize();
if ($res === false) {
if ($start == $i) {
$this->options['font_size'] = -1;
return PEAR::raiseError("No possible font size found");
}
$this->options['font_size'] -= 1;
$this->_measurizedSize = $this->options['font_size'];
break;
}
// Always the last couple of lines is stored here.
$this->_lines = $res;
}
return $this->options['font_size'];
}
/**
* Measurize text into the text box
*
* This method makes your text fit into the defined textbox by measurizing the
* lines for your given font-size. You can do this manually before rendering (or use
* even Image_Text::autoMeasurize()) or the renderer will do measurizing
* automatically.
*
* @access public
* @param bool $force Optionally, default is false, set true to force measurizing.
* @return array Array of measured lines or PEAR::Error.
* @see Image_Text::autoMeasurize()
*/
function measurize($force=false)
{
if (!$this->_init) {
return PEAR::raiseError('Not initialized. Call ->init() first!');
}
$this->_processText();
// Precaching options
$font = $this->_font;
$size = $this->options['font_size'];
$line_spacing = $this->options['line_spacing'];
$space = (1 + $this->options['line_spacing']) * $this->options['font_size'];
$max_lines = (int)$this->options['max_lines'];
if (($max_lines<1) && !$force) {
return false;
}
$block_width = $this->options['width'];
$block_height = $this->options['height'];
$colors_cnt = sizeof($this->colors);
$c = $this->colors[0];
$text_line = '';
$lines_cnt = 0;
$tokens_cnt = sizeof($this->_tokens);
$lines = array();
$text_height = 0;
$text_width = 0;
$i = 0;
$para_cnt = 0;
$beginning_of_line = true;
// Run through tokens and order them in lines
foreach($this->_tokens as $token) {
// Handle new paragraphs
if ($token=="\n") {
$bounds = imagettfbbox($size, 0, $font, $text_line);
if ((++$lines_cnt>=$max_lines) && !$force) {
return false;
}
if ($this->options['color_mode']=='paragraph') {
$c = $this->colors[$para_cnt%$colors_cnt];
$i++;
} else {
$c = $this->colors[$i++%$colors_cnt];
}
$lines[] = array(
'string' => $text_line,
'width' => $bounds[2]-$bounds[0],
'height' => $bounds[1]-$bounds[7],
'bottom_margin' => $bounds[1],
'left_margin' => $bounds[0],
'color' => $c
);
$text_width = max($text_width, ($bounds[2]-$bounds[0]));
$text_height += (int)$space;
if (($text_height > $block_height) && !$force) {
return false;
}
$para_cnt++;
$text_line = '';
$beginning_of_line = true;
continue;
}
// Usual lining up
if ($beginning_of_line) {
$text_line = '';
$text_line_next = $token;
$beginning_of_line = false;
} else {
$text_line_next = $text_line.' '.$token;
}
$bounds = imagettfbbox($size, 0, $font, $text_line_next);
$prev_width = isset($prev_width)?$width:0;
$width = $bounds[2]-$bounds[0];
// Handling of automatic new lines
if ($width>$block_width) {
if ((++$lines_cnt>=$max_lines) && !$force) {
return false;
}
if ($this->options['color_mode']=='line') {
$c = $this->colors[$i++%$colors_cnt];
} else {
$c = $this->colors[$para_cnt%$colors_cnt];
$i++;
}
$lines[] = array(
'string' => $text_line,
'width' => $prev_width,
'height' => $bounds[1]-$bounds[7],
'bottom_margin' => $bounds[1],
'left_margin' => $bounds[0],
'color' => $c
);
$text_width = max($text_width, ($bounds[2]-$bounds[0]));
$text_height += (int)$space;
if (($text_height > $block_height) && !$force) {
return false;
}
$text_line = $token;
$bounds = imagettfbbox($size, 0, $font, $text_line);
$width = $bounds[2]-$bounds[0];
$beginning_of_line = false;
} else {
$text_line = $text_line_next;
}
}
// Store remaining line
$bounds = imagettfbbox($size, 0, $font,$text_line);
if ($this->options['color_mode']=='line') {
$c = $this->colors[$i++%$colors_cnt];
} else {
$c = $this->colors[$para_cnt%$colors_cnt];
$i++;
}
$lines[] = array(
'string'=> $text_line,
'width' => $bounds[2]-$bounds[0],
'height'=> $bounds[1]-$bounds[7],
'bottom_margin' => $bounds[1],
'left_margin' => $bounds[0],
'color' => $c
);
// add last line height, but without the line-spacing
$text_height += $this->options['font_size'];
$text_width = max($text_width, ($bounds[2]-$bounds[0]));
if (($text_height > $block_height) && !$force) {
return false;
}
$this->_realTextSize = array('width' => $text_width, 'height' => $text_height);
$this->_measurizedSize = $this->options['font_size'];
return $lines;
}
/**
* Render the text in the canvas using the given options.
*
* This renders the measurized text or automatically measures it first. The $force parameter
* can be used to switch of measurizing problems (this may cause your text being rendered
* outside a given text box or destroy your image completely).
*
* @access public
* @param bool $force Optional, initially false, set true to silence measurize errors.
* @return bool True on success, otherwise PEAR::Error.
*/
function render($force=false)
{
if (!$this->_init) {
return PEAR::raiseError('Not initialized. Call ->init() first!');
}
if (!$this->_tokens) {
$this->_processText();
}
if (empty($this->_lines) || ($this->_measurizedSize != $this->options['font_size'])) {
$this->_lines = $this->measurize( $force );
}
$lines = $this->_lines;
if (PEAR::isError($this->_lines)) {
return $this->_lines;
}
if ($this->_mode === 'auto') {
$this->_img = imagecreatetruecolor(
$this->_realTextSize['width'],
$this->_realTextSize['height']
);
if (!$this->_img) {
return PEAR::raiseError('Could not create image cabvas.');
}
$this->_mode = '';
$this->setColors($this->_options['color']);
}
$block_width = $this->options['width'];
$block_height = $this->options['height'];
$max_lines = $this->options['max_lines'];
$angle = $this->options['angle'];
$radians = round(deg2rad($angle), 3);
$font = $this->_font;
$size = $this->options['font_size'];
$line_spacing = $this->options['line_spacing'];
$align = $this->options['halign'];
$im = $this->_img;
$offset = $this->_getOffset();
$start_x = $offset['x'];
$start_y = $offset['y'];
$end_x = $start_x + $block_width;
$end_y = $start_y + $block_height;
$sinR = sin($radians);
$cosR = cos($radians);
switch ($this->options['valign']) {
case IMAGE_TEXT_ALIGN_TOP:
$valign_space = 0;
break;
case IMAGE_TEXT_ALIGN_MIDDLE:
$valign_space = ($this->options['height'] - $this->_realTextSize['height']) / 2;
break;
case IMAGE_TEXT_ALIGN_BOTTOM:
$valign_space = $this->options['height'] - $this->_realTextSize['height'];
break;
default:
$valign_space = 0;
}
$space = (1 + $line_spacing) * $size;
// Adjustment of align + translation of top-left-corner to bottom-left-corner of first line
$new_posx = $start_x + ($sinR * ($valign_space + $size));
$new_posy = $start_y + ($cosR * ($valign_space + $size));
$lines_cnt = min($max_lines,sizeof($lines));
// Go thorugh lines for rendering
for($i=0; $i<$lines_cnt; $i++){
// Calc the new start X and Y (only for line>0)
// the distance between the line above is used
if($i > 0){
$new_posx += $sinR * $space;
$new_posy += $cosR * $space;
}
// Calc the position of the 1st letter. We can then get the left and bottom margins
// 'i' is really not the same than 'j' or 'g'.
$bottom_margin = $lines[$i]['bottom_margin'];
$left_margin = $lines[$i]['left_margin'];
$line_width = $lines[$i]['width'];
// Calc the position using the block width, the current line width and obviously
// the angle. That gives us the offset to slide the line.
switch($align) {
case IMAGE_TEXT_ALIGN_LEFT:
$hyp = 0;
break;
case IMAGE_TEXT_ALIGN_RIGHT:
$hyp = $block_width - $line_width - $left_margin;
break;
case IMAGE_TEXT_ALIGN_CENTER:
$hyp = ($block_width-$line_width)/2 - $left_margin;
break;
default:
$hyp = 0;
break;
}
$posx = $new_posx + $cosR * $hyp;
$posy = $new_posy - $sinR * $hyp;
$c = $lines[$i]['color'];
// Render textline
$bboxes[] = imagettftext ($im, $size, $angle, $posx, $posy, $c, $font, $lines[$i]['string']);
}
$this->bbox = $bboxes;
return true;
}
/**
* Return the image ressource.
*
* Get the image canvas.
*
* @access public
* @return resource Used image resource
*/
function &getImg()
{
return $this->_img;
}
/**
* Display the image (send it to the browser).
*
* This will output the image to the users browser. You can use the standard IMAGETYPE_*
* constants to determine which image type will be generated. Optionally you can save your
* image to a destination you set in the options.
*
* @param bool $save Save or not the image on printout.
* @param bool $free Free the image on exit.
* @return bool True on success, otherwise PEAR::Error.
* @access public
* @see Image_Text::save()
*/
function display($save=false, $free=false)
{
if (!headers_sent()) {
header("Content-type: " .image_type_to_mime_type($this->options['image_type']));
} else {
PEAR::raiseError('Header already sent.');
}
switch ($this->options['image_type']) {
case IMAGETYPE_PNG:
$imgout = 'imagepng';
break;
case IMAGETYPE_JPEG:
$imgout = 'imagejpeg';
break;
case IMAGETYPE_BMP:
$imgout = 'imagebmp';
break;
default:
return PEAR::raiseError('Unsupported image type.');
break;
}
if ($save) {
$imgout($this->_img);
$res = $this->save();
if (PEAR::isError($res)) {
return $res;
}
} else {
$imgout($this->_img);
}
if ($free) {
$res = imagedestroy($this->image);
if (!$res) {
PEAR::raiseError('Destroying image failed.');
}
}
return true;
}
/**
* Save image canvas.
*
* Saves the image to a given destination. You can leave out the destination file path,
* if you have the option for that set correctly. Saving is possible with the display()
* method, too.
*
* @param string $destFile The destination to save to (optional, uses options value else).
* @return bool True on success, otherwise PEAR::Error.
* @see Image_Text::display()
*/
function save($dest_file=false)
{
if (!$dest_file) {
$dest_file = $this->options['dest_file'];
}
if (!$dest_file) {
return PEAR::raiseError("Invalid desitination file.");
}
switch ($this->options['image_type']) {
case IMAGETYPE_PNG:
$imgout = 'imagepng';
break;
case IMAGETYPE_JPEG:
$imgout = 'imagejpeg';
break;
case IMAGETYPE_BMP:
$imgout = 'imagebmp';
break;
default:
return PEAR::raiseError('Unsupported image type.');
break;
}
$res = $imgout($this->_img, $dest_file);
if (!$res) {
PEAR::raiseError('Saving file failed.');
}
return true;
}
/**
* Get completely translated offset for text rendering.
*
* Get completely translated offset for text rendering. Important
* for usage of center coords and angles
*
* @access private
* @return array Array of x/y coordinates.
*/
function _getOffset()
{
// Presaving data
$width = $this->options['width'];
$height = $this->options['height'];
$angle = $this->options['angle'];
$x = $this->options['x'];
$y = $this->options['y'];
// Using center coordinates
if (!empty($this->options['cx']) && !empty($this->options['cy'])) {
$cx = $this->options['cx'];
$cy = $this->options['cy'];
// Calculation top left corner
$x = $cx - ($width / 2);
$y = $cy - ($height / 2);
// Calculating movement to keep the center point on himslf after rotation
if ($angle) {
$ang = deg2rad($angle);
// Vector from the top left cornern ponting to the middle point
$vA = array( ($cx - $x), ($cy - $y) );
// Matrix to rotate vector
// sinus and cosinus
$sin = round(sin($ang), 14);
$cos = round(cos($ang), 14);
// matrix
$mRot = array(
$cos, (-$sin),
$sin, $cos
);
// Multiply vector with matrix to get the rotated vector
// This results in the location of the center point after rotation
$vB = array (
($mRot[0] * $vA[0] + $mRot[2] * $vA[0]),
($mRot[1] * $vA[1] + $mRot[3] * $vA[1])
);
// To get the movement vector, we subtract the original middle
$vC = array (
($vA[0] - $vB[0]),
($vA[1] - $vB[1])
);
// Finally we move the top left corner coords there
$x += $vC[0];
$y += $vC[1];
}
}
return array ('x' => (int)round($x, 0), 'y' => (int)round($y, 0));
}
/**
* Convert a color to an array.
*
* The following colors syntax must be used:
* "#08ffff00" hexadecimal format with alpha channel (08)
* array with 'r','g','b','a'(optionnal) keys
* A GD color special color (tiled,...)
* Only one color is allowed
* If $id is given, the color index $id is used
*
* @param mixed $colors Array of colors.
* @param mixed $id Array of colors.
* @access private
*/
function _convertString2RGB($scolor)
{
if (preg_match(IMAGE_TEXT_REGEX_HTMLCOLOR, $scolor, $matches)) {
return array(
'r' => hexdec($matches[2]),
'g' => hexdec($matches[3]),
'b' => hexdec($matches[4]),
'a' => hexdec(!empty($matches[1])?$matches[1]:0),
);
}
return false;
}
/**
* Extract the tokens from the text.
*
* @access private
*/
function _processText()
{
if (!isset($this->_text)) {
return false;
}
$this->_tokens = array();
// Normalize linebreak to "\n"
$this->_text = preg_replace("[\r\n]", "\n", $this->_text);
// Get each paragraph
$paras = explode("\n",$this->_text);
// loop though the paragraphs
// and get each word (token)
foreach($paras as $para) {
$words = explode(' ',$para);
foreach($words as $word) {
$this->_tokens[] = $word;
}
// add a "\n" to mark the end of a paragraph
$this->_tokens[] = "\n";
}
// we do not need an end paragraph as the last token
array_pop($this->_tokens);
}
}
Image_Text-0.6.1/tests/imageisthesame.php 0000664 0001750 0001750 00000003744 11671375066 021216 0 ustar clockwerx clockwerx ($rgb1 >> 16) & 0xFF,
'g' => ($rgb1 >> 8) & 0xFF,
'b' => $rgb1 & 0xFF
);
$pix1 = imagecolorsforindex($i1, $rgb1);
$rgb2 = imagecolorat($i2, $x, $y);
$pix2 = array(
'r' => ($rgb2 >> 16) & 0xFF,
'g' => ($rgb2 >> 8) & 0xFF,
'b' => $rgb2 & 0xFF
);
$pix2 = imagecolorsforindex($i2, $rgb2);
//echo implode(',',$pix1) . ' - ' . implode(',',$pix2) . "\n";
if ($pix1 != $pix2) {
return false;
}
}
}
return true;
}//function imageisthesame($file1, $file2)
?> Image_Text-0.6.1/tests/imageisthesameTest.php 0000664 0001750 0001750 00000007335 11671375066 022056 0 ustar clockwerx clockwerx markTestSkipped("Requires the gd extension");
}
$this->dir = dirname(__FILE__) . '/testimages/';
}
/**
* Tears down the fixture, for example, close a network connection.
* This method is called after a test is executed.
*
* @access protected
*/
protected function tearDown() {
}
/**
*
*/
public function testSame() {
//same image
$this->assertTrue(imageisthesame(
$this->dir . '10x5-red.png',
$this->dir . '10x5-red.png'
));
//same image
$this->assertTrue(imageisthesame(
imagecreatefrompng($this->dir . '10x5-red.png'),
imagecreatefrompng($this->dir . '10x5-red.png')
));
}
public function testSize() {
//wrong size
$this->assertFalse(imageisthesame(
$this->dir . '10x5-red.png',
$this->dir . '5x10-red.png'
));
$this->assertFalse(imageisthesame(
imagecreatefrompng($this->dir . '10x5-red.png'),
imagecreatefrompng($this->dir . '5x10-red.png')
));
}
public function testWrongColor() {
//wrong color
$this->assertFalse(imageisthesame(
$this->dir . '10x5-red.png',
$this->dir . '10x5-white.png'
));
}
public function testIndexed() {
//same, but indexed
$this->assertTrue(imageisthesame(
$this->dir . '10x5-white.png',
$this->dir . '10x5-white-index.png'
));
//wrong color, but indexed
$this->assertFalse(imageisthesame(
$this->dir . '10x5-red.png',
$this->dir . '10x5-white-index.png'
));
}
public function testGreyscale() {
//same, but greyscale
$this->assertTrue(imageisthesame(
$this->dir . '10x5-white.png',
$this->dir . '10x5-white-grey.png'
));
//wrong color, greyscale
$this->assertFalse(imageisthesame(
$this->dir . '10x5-red.png',
$this->dir . '10x5-white-grey.png'
));
}
public function testImagetypes() {
//same color, different image type, one color
$this->assertTrue(imageisthesame(
$this->dir . '5x10-red-254.jpg',
$this->dir . '5x10-red-254.png'
));
//same color, different type, gradient
$this->assertTrue(imageisthesame(
$this->dir . '5x10-gradient.jpg',
$this->dir . '5x10-gradient.png'
));
}
}
// Call Image_TextTest::main() if this source file is executed directly.
if (PHPUnit_MAIN_METHOD == "imageisthesameTest::main") {
imageisthesameTest::main();
}
?>
Image_Text-0.6.1/tests/TextTest.php 0000664 0001750 0001750 00000017127 11671375066 020015 0 ustar clockwerx clockwerx markTestSkipped("Requires the gd extension");
}
$this->dir = dirname(__FILE__) . '/testimages/';
}
protected function initInstance($text)
{
$i = new Image_Text($text);
$i->set(array(
'font_path' => dirname(__FILE__) . '/',
'font_file' => 'Vera.ttf',
'font_size' => 12,
'canvas' => array('width'=> 200,'height'=> 100),
'width' => 200,
'height' => 200,
'color' => array('#FFFFFF')
));
return $i;
}
/**
* Tears down the fixture, for example, close a network connection.
* This method is called after a test is executed.
*
* @access protected
*/
protected function tearDown() {
}
/**
*
*/
public function testConstruct() {
return;
$i = $this->initInstance('test');
$this->assertSame('Image_Text', get_class($i));
$this->assertTrue($i->init());
$this->assertTrue($i->render());
$this->assertTrue(imageisthesame(
$this->dir . 'test-construct.png',
$i->getImg()
));
$i = $this->initInstance('text');
$this->assertSame('Image_Text', get_class($i));
$this->assertTrue($i->init());
$this->assertTrue($i->render());
$this->assertFalse(imageisthesame(
$this->dir . 'test-construct.png',
$i->getImg()
));
}
public function testBackgroundColor() {
//default background is black
$i = $this->initInstance('test');
$this->assertSame('Image_Text', get_class($i));
$this->assertTrue($i->init());
$this->assertTrue($i->render());
$this->assertTrue(imageisthesame(
$this->dir . 'test-construct.png',
$i->getImg()
));
//red background
$i = $this->initInstance('text');
$this->assertSame('Image_Text', get_class($i));
$i->set(array('background_color' => '#FF0000'));
$this->assertTrue($i->init());
$this->assertTrue($i->render());
$this->assertTrue(imageisthesame(
$this->dir . 'test-background-red.png',
$i->getImg()
));
//transparent background
$i = $this->initInstance('text');
$this->assertSame('Image_Text', get_class($i));
$i->set(array('background_color' => null));
$this->assertTrue($i->init());
$this->assertTrue($i->render());
$this->assertTrue(imageisthesame(
$this->dir . 'test-background-transparent.png',
$i->getImg()
));
}
/**
* @todo Implement testSet().
*/
public function testSet() {
// Remove the following line when you implement this test.
$this->markTestIncomplete(
"This test has not been implemented yet."
);
}
/**
* @todo Implement testSetColors().
*/
public function testSetColors() {
// Remove the following line when you implement this test.
$this->markTestIncomplete(
"This test has not been implemented yet."
);
}
/**
* @todo Implement testSetColor().
*/
public function testSetColor() {
// Remove the following line when you implement this test.
$this->markTestIncomplete(
"This test has not been implemented yet."
);
}
/**
* @todo Implement testInit().
*/
public function testInit() {
// Remove the following line when you implement this test.
$this->markTestIncomplete(
"This test has not been implemented yet."
);
}
/**
* @todo Implement testAutoMeasurize().
*/
public function testAutoMeasurize() {
// Remove the following line when you implement this test.
$this->markTestIncomplete(
"This test has not been implemented yet."
);
}
/**
* @todo Implement testMeasurize().
*/
public function testMeasurize() {
// Remove the following line when you implement this test.
$this->markTestIncomplete(
"This test has not been implemented yet."
);
}
/**
* @todo Implement testRender().
*/
public function testRender() {
// Remove the following line when you implement this test.
$this->markTestIncomplete(
"This test has not been implemented yet."
);
}
/**
* @todo Implement testGetImg().
*/
public function testGetImg() {
// Remove the following line when you implement this test.
$this->markTestIncomplete(
"This test has not been implemented yet."
);
}
/**
* @todo Implement testDisplay().
*/
public function testDisplay() {
// Remove the following line when you implement this test.
$this->markTestIncomplete(
"This test has not been implemented yet."
);
}
/**
* @todo Implement testSave().
*/
public function testSave() {
// Remove the following line when you implement this test.
$this->markTestIncomplete(
"This test has not been implemented yet."
);
}
/**
* @todo Implement test_getOffset().
*/
public function test_getOffset() {
// Remove the following line when you implement this test.
$this->markTestIncomplete(
"This test has not been implemented yet."
);
}
/**
*
*/
public function test_convertString2RGB() {
$this->assertEquals(
array('r'=> 255,'g'=> 255,'b'=> 255,'a'=> 0),
Image_Text::_convertString2RGB('#FFFFFF')
);
$this->assertEquals(
array('r'=> 255,'g'=> 255,'b'=> 255,'a'=> 0),
Image_Text::_convertString2RGB('#00FFFFFF')
);
$this->assertEquals(
array('r'=> 0,'g'=> 0,'b'=> 0,'a'=> 0),
Image_Text::_convertString2RGB('#000000')
);
$this->assertEquals(
array('r'=> 0,'g'=> 0,'b'=> 0,'a'=> 255),
Image_Text::_convertString2RGB('#FF000000')
);
}
/**
* @todo Implement test_processText().
*/
public function test_processText() {
// Remove the following line when you implement this test.
$this->markTestIncomplete(
"This test has not been implemented yet."
);
}
}
// Call Image_TextTest::main() if this source file is executed directly.
if (PHPUnit_MAIN_METHOD == "Image_TextTest::main") {
Image_TextTest::main();
}
?>
Image_Text-0.6.1/tests/Vera.ttf 0000664 0001750 0001750 00000200531 11671375066 017125 0 ustar clockwerx clockwerx OS/2_c p VPCLTъ^ 6cmap l Xcvt 9 fpgm &` gasp H glyftA &