430 lines
13 KiB
PHP
430 lines
13 KiB
PHP
<?php
|
|
|
|
/*
|
|
** include/graphics.php
|
|
**
|
|
** Additional graphics functions
|
|
**
|
|
** Jack Weeland, 24 July 2007
|
|
*/
|
|
|
|
//
|
|
// Definitions
|
|
//
|
|
define("ALH_LEFT", 0x0001);
|
|
define("ALH_RIGHT", 0x0002);
|
|
define("ALH_CENTER", 0x0004);
|
|
define("ALV_TOP", 0x0010);
|
|
define("ALV_BOTTOM", 0x0020);
|
|
define("ALV_MIDDLE", 0x0040);
|
|
define("AL_DEFAULT", ALH_LEFT | ALV_TOP);
|
|
define("AL_CENTERED", ALH_CENTER | ALV_MIDDLE);
|
|
|
|
//
|
|
// Functions
|
|
//
|
|
|
|
function imagestringalign($im, $font, $x, $y, $string, $color, $align = AL_DEFAULT)
|
|
{
|
|
$lines = explode("\n", $string);
|
|
$h_line = imagefontheight($font);
|
|
if( $align & ALV_MIDDLE )
|
|
$y -= ($h_line * count($lines)) >> 1;
|
|
else if( $align & ALV_BOTTOM )
|
|
$y -= $h_line * count($lines);
|
|
|
|
foreach( $lines as $line )
|
|
{
|
|
if( $align & ALH_CENTER )
|
|
$w = (imagefontwidth($font) * strlen($line)) >> 1;
|
|
else if( $align & ALH_RIGHT )
|
|
$w = imagefontwidth($font) * strlen($line);
|
|
else
|
|
$w = 0;
|
|
imagestring($im, $font, $x - $w, $y, $line, $color);
|
|
|
|
$y += $h_line;
|
|
}
|
|
}
|
|
|
|
function imagestringupalign($im, $font, $x, $y, $string, $color, $align = AL_DEFAULT)
|
|
{
|
|
$lines = explode("\n", $string);
|
|
$h_line = imagefontheight($font);
|
|
if( $align & ALH_CENTER )
|
|
$x -= ($h_line * count($lines)) >> 1;
|
|
else if( $align & ALH_RIGHT )
|
|
$x -= $h_line * count($lines);
|
|
|
|
foreach( $lines as $line )
|
|
{
|
|
if( $align & ALV_MIDDLE )
|
|
$h = (imagefontwidth($font) * strlen($line)) >> 1;
|
|
else if( $align & ALV_TOP )
|
|
$h = imagefontwidth($font) * strlen($line);
|
|
else
|
|
$h = 0;
|
|
imagestringup($im, $font, $x, $y + $h, $line, $color);
|
|
|
|
$x += $h_line;
|
|
}
|
|
}
|
|
|
|
function imagestringborderalign($im, $font, $x, $y, $string, $color, $bgcolor, $align = AL_DEFAULT)
|
|
{
|
|
imagestringalign($im, $font, $x - 1, $y - 1, $string, $bgcolor, $align);
|
|
imagestringalign($im, $font, $x , $y - 1, $string, $bgcolor, $align);
|
|
imagestringalign($im, $font, $x + 1, $y - 1, $string, $bgcolor, $align);
|
|
imagestringalign($im, $font, $x - 1, $y , $string, $bgcolor, $align);
|
|
imagestringalign($im, $font, $x + 1, $y , $string, $bgcolor, $align);
|
|
imagestringalign($im, $font, $x - 1, $y + 1, $string, $bgcolor, $align);
|
|
imagestringalign($im, $font, $x , $y + 1, $string, $bgcolor, $align);
|
|
imagestringalign($im, $font, $x + 1, $y + 1, $string, $bgcolor, $align);
|
|
imagestringalign($im, $font, $x , $y , $string, $color, $align);
|
|
}
|
|
|
|
function imagestringupborderalign($im, $font, $x, $y, $string, $color, $bgcolor, $align = AL_DEFAULT)
|
|
{
|
|
imagestringupalign($im, $font, $x - 1, $y - 1, $string, $bgcolor, $align);
|
|
imagestringupalign($im, $font, $x , $y - 1, $string, $bgcolor, $align);
|
|
imagestringupalign($im, $font, $x + 1, $y - 1, $string, $bgcolor, $align);
|
|
imagestringupalign($im, $font, $x - 1, $y , $string, $bgcolor, $align);
|
|
imagestringupalign($im, $font, $x + 1, $y , $string, $bgcolor, $align);
|
|
imagestringupalign($im, $font, $x - 1, $y + 1, $string, $bgcolor, $align);
|
|
imagestringupalign($im, $font, $x , $y + 1, $string, $bgcolor, $align);
|
|
imagestringupalign($im, $font, $x + 1, $y + 1, $string, $bgcolor, $align);
|
|
imagestringupalign($im, $font, $x , $y , $string, $color, $align);
|
|
}
|
|
|
|
// Draw a symbol (currently only a redimentary implementation)
|
|
function imagesymbol($im, $x, $y, $w, $h, $what, $state, $color, $align = AL_DEFAULT)
|
|
{
|
|
// determine image size
|
|
switch( $what ) {
|
|
case 'relais':
|
|
$width = 20;
|
|
$height = 10;
|
|
break;
|
|
default:
|
|
error_log("imagesymbol(): symbol \"" . $what . "\" not implemented.");
|
|
return FALSE;
|
|
}
|
|
|
|
// create drawing canvas with transparent background
|
|
$symbol = imagecreate($width, $height);
|
|
if( function_exists("imageantialias") )
|
|
imageantialias($im, true);
|
|
$bgcolor = imagecolorallocatealpha($symbol, 255, 255, 255, 127);
|
|
imagefill($symbol, 0, 0, $bgcolor);
|
|
|
|
// set colors
|
|
if( is_array($color) ) {
|
|
for( $i = 0; $i < count($colors); $i++ ) {
|
|
$rgba = imagecolorsforindex($im, $color[$i]);
|
|
$color[$i] = imagecolorallocatealpha($symbol, $rgba['red'], $rgba['green'], $rgba['blue'], $rgba['alpha']);
|
|
}
|
|
}
|
|
else {
|
|
$rgba = imagecolorsforindex($im, $color);
|
|
$color = imagecolorallocatealpha($symbol, $rgba['red'], $rgba['green'], $rgba['blue'], $rgba['alpha']);
|
|
}
|
|
|
|
// draw symbol
|
|
switch( $what ) {
|
|
case 'relais':
|
|
// circle
|
|
imageline($symbol, 0, 8, 0, 6, $color);
|
|
imageline($symbol, 1, 9, 3, 9, $color);
|
|
imageline($symbol, 4, 8, 4, 6, $color);
|
|
imageline($symbol, 3, 5, 1, 5, $color);
|
|
// circle
|
|
imageline($symbol, 15, 8, 15, 6, $color);
|
|
imageline($symbol, 16, 9, 18, 9, $color);
|
|
imageline($symbol, 19, 8, 19, 6, $color);
|
|
imageline($symbol, 18, 5, 16, 5, $color);
|
|
if( $state == 0 ) {
|
|
// open
|
|
imageline($symbol, 2, 4, 16, 0, $color);
|
|
}
|
|
else {
|
|
// closed
|
|
imageline($symbol, 2, 4, 18, 4, $color);
|
|
}
|
|
break;
|
|
}
|
|
|
|
// destination size set?
|
|
if( $w <= 0 ) $w = $width;
|
|
if( $h <= 0 ) $h = $height;
|
|
// adjust x and y for alignment
|
|
if( $align & ALH_CENTER )
|
|
$x -= ($w >> 1);
|
|
else if( $align & ALH_RIGHT)
|
|
$x -= $w;
|
|
if( $align & ALV_MIDDLE )
|
|
$y -= ($h >> 1);
|
|
else if( $align & ALV_TOP )
|
|
$y -= $h;
|
|
|
|
imagecopyresampled($im, $symbol, $x, $y, 0, 0, $w, $h, imagesx($symbol), imagesy($symbol));
|
|
imagedestroy($symbol);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Allocate a color defined by a string
|
|
// Parameters:
|
|
// $im - image resource
|
|
// $color - string specifying the color:
|
|
// - by name
|
|
// - #rgb (r, g and b as hex digits)
|
|
// - #rrggbb (rr, gg, and bb as hex digits)
|
|
// - rgb(r,g,b) (r, g and b as decimal numbers 0..255 or a percentage 0%..100%)
|
|
// - rgba(r,g,b,a) (r, g and b as above, a between 0.0 and 1.0)
|
|
// - (r,g,b) or (r,g,b,a) (r, g, b and a as floating point number in the range 0.0 to 1.0)
|
|
// $alpha - alpha value between 0.0 (transparent) and 1.0 (opaque)
|
|
// alpha value is overridden when it is specified in the color string
|
|
function imagecolorstringalpha($im, $color, $alpha)
|
|
{
|
|
$matches; // for 'preg_match()'
|
|
|
|
if( preg_match('/#[0-9A-F]{6}/', $color) ){
|
|
$rgb['red'] = intval(substr($color, 1, 2), 16);
|
|
$rgb['green'] = intval(substr($color, 3, 2), 16);
|
|
$rgb['blue'] = intval(substr($color, 5, 2), 16);
|
|
}
|
|
else if( preg_match('/#[0-9A-F]{3}/', $color) ){
|
|
$rgb['red'] =
|
|
(intval(substr($color, 1, 1), 16) << 4) +
|
|
(intval(substr($color, 1, 1), 16) );
|
|
$rgb['green'] =
|
|
(intval(substr($color, 2, 1), 16) << 4) +
|
|
(intval(substr($color, 2, 1), 16) );
|
|
$rgb['blue'] =
|
|
(intval(substr($color, 3, 1), 16) << 4) +
|
|
(intval(substr($color, 3, 1), 16) );
|
|
}
|
|
else if( preg_match('/rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/i', $color, $matches) ) {
|
|
// RGB tuple, with r,g,b between 0 and 255
|
|
$rgb['red'] = intval($matches[1], 10);
|
|
$rgb['green'] = intval($matches[2], 10);
|
|
$rgb['blue'] = intval($matches[3], 10);
|
|
}
|
|
else if( preg_match('/rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i', $color, $matches) ) {
|
|
// percentage, 0 to 100%
|
|
$rgb['red'] = floatval($matches[1]) * 2.55;
|
|
$rgb['green'] = floatval($matches[2]) * 2.55;
|
|
$rgb['blue'] = floatval($matches[3]) * 2.55;
|
|
}
|
|
else if( preg_match('/rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+|\d*\.\d+)\s*\)/i', $color, $matches) ) {
|
|
// RGB tuple with alpha, with r,g,b between 0 and 255 and alpha between 0.0 and 1.0
|
|
$rgb['red'] = intval($matches[1], 10);
|
|
$rgb['green'] = intval($matches[2], 10);
|
|
$rgb['blue'] = intval($matches[3], 10);
|
|
$alpha = floatval($matches[4]) * 255.0;
|
|
}
|
|
else if( preg_match('/rgba\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+|\d*\.\d+)\s*\)/i', $color, $matches) ) {
|
|
// percentage, 0 to 100%, with r,g,b between 0 and 255 and alpha between 0.0 and 1.0
|
|
$rgb['red'] = floatval($matches[1]) * 2.55;
|
|
$rgb['green'] = floatval($matches[2]) * 2.55;
|
|
$rgb['blue'] = floatval($matches[3]) * 2.55;
|
|
$alpha = floatval($matches[4]);
|
|
}
|
|
else if( preg_match('/\(\s*(\d+|\d*\.\d+)\s*,\s*(\d+|\d*\.\d+)\s*,\s*(\d+|\d*\.\d+)(\s*,\s*(\d+|\d*\.\d+))?\s*\)/i', $color, $matches) ) {
|
|
// RGB tuple with r,g,b and alpha between 0.0 and 1.0
|
|
$rgb['red'] = floatval($matches[1]) * 255.0;
|
|
$rgb['green'] = floatval($matches[2]) * 255.0;
|
|
$rgb['blue'] = floatval($matches[3]) * 255.0;
|
|
if( isset($matches[5]) ) $alpha = floatval($matches[5]);
|
|
}
|
|
else {
|
|
// standard color, section 4.3.6 of http://www.w3.org/TR/CSS2
|
|
$stdcolors = array(
|
|
'maroon' => array('red' => 0x80, 'green' => 0x00, 'blue' => 0x00 ),
|
|
'red' => array('red' => 0xFF, 'green' => 0x00, 'blue' => 0x00 ),
|
|
'orange' => array('red' => 0xFF, 'green' => 0xA5, 'blue' => 0x00 ),
|
|
'yellow' => array('red' => 0xFF, 'green' => 0xFF, 'blue' => 0x00 ),
|
|
'olive' => array('red' => 0x80, 'green' => 0x80, 'blue' => 0x00 ),
|
|
'purple' => array('red' => 0x80, 'green' => 0x00, 'blue' => 0x80 ),
|
|
'fuchsia' => array('red' => 0xFF, 'green' => 0x00, 'blue' => 0xFF ),
|
|
'white' => array('red' => 0xFF, 'green' => 0xFF, 'blue' => 0xFF ),
|
|
'lime' => array('red' => 0x00, 'green' => 0xFF, 'blue' => 0x00 ),
|
|
'green' => array('red' => 0x00, 'green' => 0x80, 'blue' => 0x00 ),
|
|
'navy' => array('red' => 0x00, 'green' => 0x00, 'blue' => 0x80 ),
|
|
'blue' => array('red' => 0x00, 'green' => 0x00, 'blue' => 0xFF ),
|
|
'aqua' => array('red' => 0x00, 'green' => 0xFF, 'blue' => 0xFF ),
|
|
'teal' => array('red' => 0x00, 'green' => 0x80, 'blue' => 0x80 ),
|
|
'black' => array('red' => 0x00, 'green' => 0x00, 'blue' => 0x00 ),
|
|
'silver' => array('red' => 0xC0, 'green' => 0xC0, 'blue' => 0xC0 ),
|
|
'gray' => array('red' => 0x80, 'green' => 0x80, 'blue' => 0x80 )
|
|
);
|
|
$rgb = $stdcolors[$color];
|
|
}
|
|
|
|
// default to black
|
|
if( !isset($rgb) )
|
|
$rgb = array('red' => 0, 'green' => 0, 'blue' => 0);
|
|
|
|
// convert $alpha from 0..255 to 127..0 (for the GD library, '0' means opaque whereas
|
|
// for alpha channels, '1' means opaque)
|
|
$alpha = (1.0 - $alpha) * 127;
|
|
|
|
return imagecolorallocatealpha($im, $rgb['red'], $rgb['green'], $rgb['blue'], $alpha);
|
|
}
|
|
|
|
function imagecolorstring($im, $color)
|
|
{
|
|
return imagecolorstringalpha($im, $color, 1.0);
|
|
}
|
|
|
|
//
|
|
// Miscellaneous functions
|
|
//
|
|
|
|
// Format a number
|
|
// Parameters:
|
|
// $val - value to format
|
|
// $div_factor - optional scaling factor, or '1' when not used
|
|
// $decimals - digits following the decimal point, or the string "frac" for 1/2, 1/4, 3/4
|
|
// Returns:
|
|
// Formatted $val (as a string)
|
|
function format_number($val, $div_factor, $decimals)
|
|
{
|
|
if( $decimals == "frac" ) {
|
|
$int_val = (int)($val / $div_factor);
|
|
$frac = round((($val / $div_factor) - $int_val) * 4);
|
|
$frac_str = array("", "¼", "½", "¾");
|
|
return sprintf("%u%s", $int_val, $frac_str[$frac]);
|
|
}
|
|
else {
|
|
if( $decimals < 0 ) {
|
|
// negative: decimals are printed only when non-zero
|
|
// 1.0 -> 1
|
|
// 1.5 -> 1.5
|
|
$decimals = -$decimals;
|
|
$print_dec = false;
|
|
}
|
|
else $print_dec = true;
|
|
$rnd_val = $div_factor >> 1;
|
|
$dec_div = 1;
|
|
$padding = 0;
|
|
for( $i = 0; $i < $decimals; $i++ ) {
|
|
$dec_div *= 10;
|
|
$padding++;
|
|
}
|
|
$int_val = (int)(($val + (int)($rnd_val / $dec_div)) / $div_factor);
|
|
$rem_val = round(($val - ($int_val * $div_factor)) / $div_factor * $dec_div);
|
|
if( $decimals == 0 || (!$print_dec && $rem_val == 0) )
|
|
return sprintf("%u", $int_val);
|
|
else {
|
|
global $_I18N;
|
|
$i18n_info = $_I18N['info'];
|
|
return sprintf("%u%s%0" . $padding . "u", $int_val, $i18n_info['decimal_point'], $rem_val);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Rounding functions
|
|
function round_down($var, $step)
|
|
{
|
|
return $var - ($var % $step);
|
|
}
|
|
|
|
function round_up($var, $step)
|
|
{
|
|
if( $var % $step == 0 ) return $var;
|
|
else return $var - ($var % $step) + $step;
|
|
}
|
|
|
|
// Convert grams/meters to lbs/feet etc
|
|
// Parameters:
|
|
// $val - value in ISO units
|
|
// $unit - the unit (string)
|
|
// "kg", "g" -> lbs, oz
|
|
// "m", "cm", "mm" -> feet, inches
|
|
// Returns:
|
|
// Imperial value as a string, with "lbs" etc inserted
|
|
function iso2imp($val, $unit)
|
|
{
|
|
switch( $unit )
|
|
{
|
|
case "kg":
|
|
$val *= 1000;
|
|
case "g":
|
|
$g2lbs = 453.59237;
|
|
$lbs = (int)($val / $g2lbs);
|
|
if( $val < (20 * $g2lbs) ) {
|
|
$oz2 = (int)round(($val - $lbs * $g2lbs) * 32 / $g2lbs);
|
|
if( ($oz2 & 1) == 1 ) $frac = "½";
|
|
else $frac = "";
|
|
if( $oz2 == 1 ) $oz = "";
|
|
else {
|
|
$oz = $oz2 >> 1;
|
|
if( $oz == 16 ) {
|
|
$oz = 0;
|
|
$lbs++;
|
|
}
|
|
}
|
|
return "" . $lbs . " lbs. " . $oz . $frac . " oz.";
|
|
}
|
|
else {
|
|
$lbs2 = (int)round(($val - $lbs * $g2lbs) * 4 / $g2lbs);
|
|
switch( $lbs2 ) {
|
|
case 1:
|
|
$frac = "¼";
|
|
break;
|
|
case 2:
|
|
$frac = "½";
|
|
break;
|
|
case 3:
|
|
$frac = "¾";
|
|
break;
|
|
case 4:
|
|
$lbs++;
|
|
default:
|
|
$frac = "";
|
|
break;
|
|
}
|
|
return "" . $lbs . $frac . " lbs.";
|
|
}
|
|
case "mm":
|
|
$val /= 10;
|
|
case "cm":
|
|
$val /= 100;
|
|
case "m":
|
|
$m2ft = 0.9144 / 3;
|
|
$ft = (int)($val / $m2ft);
|
|
if( $val < (3 * $m2ft) )
|
|
$in2 = (int)round(($val - $ft * $m2ft) * 48 / $m2ft);
|
|
else
|
|
$in2 = (int)round(($val - $ft * $m2ft) * 24 / $m2ft) << 1;
|
|
switch( ($in2 & 3) ) {
|
|
case 0:
|
|
$frac = "";
|
|
break;
|
|
case 1:
|
|
$frac = "¼";
|
|
break;
|
|
case 2:
|
|
$frac = "½";
|
|
break;
|
|
case 3:
|
|
$frac = "¾";
|
|
break;
|
|
}
|
|
if( $in2 > 0 && $in2 < 4 ) $in = "";
|
|
else {
|
|
$in = $in2 >> 2;
|
|
if( $in == 12 ) {
|
|
$in = 0;
|
|
$ft++;
|
|
}
|
|
}
|
|
//error_log(implode(",", array($val, $unit, $m2ft, $in2, $in, $frac)));
|
|
return "" . $ft . "′ " . $in . $frac . "″";
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
?>
|