src.dualinventive.com/mtinfo/dist/webroot/main/include/graphics.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("", "&frac14;", "&frac12;", "&frac34;");
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 = "&frac12;";
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 = "&frac14;";
break;
case 2:
$frac = "&frac12;";
break;
case 3:
$frac = "&frac34;";
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 = "&frac14;";
break;
case 2:
$frac = "&frac12;";
break;
case 3:
$frac = "&frac34;";
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 . "&prime; " . $in . $frac . "&Prime;";
default:
return "";
}
}
?>