From: maxious Date: Sun, 25 Mar 2012 05:58:33 +0000 Subject: Add bubbletree X-Git-Url: https://maxious.lambdacomplex.org/git/?p=disclosr.git&a=commitdiff&h=4fad3e3a1bca4f5317bec66feff4ff6ae342d7ec --- Add bubbletree Former-commit-id: 8de5c676aaa98e0cae1a1da72e9cbae574963b68 --- --- a/.gitmodules +++ b/.gitmodules @@ -4,9 +4,6 @@ [submodule "couchdb/settee"] path = couchdb/settee url = https://github.com/inadarei/settee.git -[submodule "lib/springy"] - path = lib/springy - url = https://github.com/dhotson/springy.git [submodule "lib/php-diff"] path = lib/php-diff url = https://github.com/chrisboulton/php-diff.git @@ -19,4 +16,10 @@ [submodule "lib/phpquery"] path = lib/phpquery url = https://github.com/TobiaszCudnik/phpquery.git +[submodule "javascripts/sigma"] + path = javascripts/sigma + url = https://github.com/jacomyal/sigma.js.git +[submodule "javascripts/bubbletree"] + path = javascripts/bubbletree + url = https://github.com/okfn/bubbletree.git --- /dev/null +++ b/bubbletree.php @@ -1,1 +1,108 @@ + + + + + Minimal BubbleTree Demo + + + + + + + + + + + + + +
+
+
+ + + --- a/graph.php +++ b/graph.php @@ -6,36 +6,46 @@ $format = $_REQUEST['format']; } -function add_node($id, $label) { +function add_node($id, $label, $parent="") { global $format; if ($format == "html") { - echo "nodes[\"$id\"] = graph.newNode({label: \"$label\"});" . PHP_EOL; + // echo "nodes[\"$id\"] = graph.newNode({label: \"$label\"});" . PHP_EOL; } if ($format == "dot" && $label != "") { echo "$id [label=\"$label\"];". PHP_EOL; } + if ($format == "gexf") { + echo "":">") + ."" + ."". PHP_EOL; + } } function add_edge($from, $to, $color) { global $format; if ($format == "html") { - echo "graph.newEdge(nodes[\"$from\"], nodes['$to'], {color: '$color'});" . PHP_EOL; + // echo "graph.newEdge(nodes[\"$from\"], nodes['$to'], {color: '$color'});" . PHP_EOL; } if ($format == "dot") { echo "$from -> $to ".($color != ""? "[color=$color]":"").";". PHP_EOL; } + if ($format == "gexf") { + echo "". PHP_EOL; + } +} +if ($format == "gexf") { + //header('Content-Type: text/xml'); + header('Content-Type: application/gexf+xml'); +echo ' + + + Gexf.net + A hello world! file + + + '. PHP_EOL; } -if ($format == "html") { - ?> - - - - +
+ + + + + +
+
'. PHP_EOL; +} //include_footer(); ?> --- /dev/null +++ b/javascripts/bubbletree --- /dev/null +++ b/javascripts/sigma --- /dev/null +++ b/javascripts/sigma.min.js @@ -1,1 +1,63 @@ +/* sigmajs.org - an open-source light-weight JavaScript graph drawing library - Version: 0.1 - Author: Alexis Jacomy - License: MIT */ +var sigma={tools:{},classes:{},instances:{}}; +(function(){if(!Array.prototype.some)Array.prototype.some=function(i,n){var g=this.length;if("function"!=typeof i)throw new TypeError;for(var j=0;j";a+="

LOCAL :

";for(b in d.p.localProbes)a+="

"+b+" : "+d.p.localProbes[b]()+"

";d.p.dom.innerHTML= +a;return d}sigma.classes.Cascade.call(this);var d=this;this.instance=b;this.monitoring=!1;this.p={fps:40,dom:h,globalProbes:{"Time (ms)":sigma.chronos.getExecutionTime,Queue:sigma.chronos.getQueuedTasksCount,Tasks:sigma.chronos.getTasksCount,FPS:sigma.chronos.getFPS},localProbes:{"Nodes count":function(){return d.instance.graph.nodes.length},"Edges count":function(){return d.instance.graph.edges.length}}};this.activate=function(){if(!d.monitoring)d.monitoring=window.setInterval(e,1E3/d.p.fps);return d}; +this.desactivate=function(){if(d.monitoring)window.clearInterval(d.monitoring),d.monitoring=null,d.p.dom.innerHTML="";return d}}function j(b){function h(b){if(a.p.mouseEnabled&&(e(a.mouseX,a.mouseY,a.ratio*(0<(void 0!=b.wheelDelta&&b.wheelDelta||void 0!=b.detail&&-b.detail)?a.p.zoomMultiply:1/a.p.zoomMultiply)),a.p.blockScroll))b.preventDefault?b.preventDefault():b.returnValue=!1}function e(b,c,e){if(!a.isMouseDown&&(window.clearInterval(a.interpolationID),n=void 0!=e,i=a.stageX,j=b,k=a.stageY,l= +c,f=e||a.ratio,f=Math.min(Math.max(f,a.p.minRatio),a.p.maxRatio),u=a.p.directZooming?1-(n?a.p.zoomDelta:a.p.dragDelta):0,a.ratio!=f||a.stageX!=j||a.stageY!=l))d(),a.interpolationID=window.setInterval(d,50),a.dispatch("startinterpolate")}function d(){u+=n?a.p.zoomDelta:a.p.dragDelta;u=Math.min(u,1);var b=sigma.easing.quadratic.easeout(u),c=a.ratio;a.ratio=c*(1-b)+f*b;n?(a.stageX=j+(a.stageX-j)*a.ratio/c,a.stageY=l+(a.stageY-l)*a.ratio/c):(a.stageX=i*(1-b)+j*b,a.stageY=k*(1-b)+l*b);a.dispatch("interpolate"); +if(1<=u)window.clearInterval(a.interpolationID),b=a.ratio,n?(a.ratio=f,a.stageX=j+(a.stageX-j)*a.ratio/b,a.stageY=l+(a.stageY-l)*a.ratio/b):(a.stageX=j,a.stageY=l),a.dispatch("stopinterpolate")}sigma.classes.Cascade.call(this);sigma.classes.EventDispatcher.call(this);var a=this;this.p={minRatio:1,maxRatio:32,marginRatio:1,zoomDelta:0.1,dragDelta:0.3,zoomMultiply:2,directZooming:!1,blockScroll:!0,inertia:1.1,mouseEnabled:!0};var g=0,c=0,i=0,k=0,f=1,j=0,l=0,s=0,q=0,z=0,m=0,u=0,n=!1;this.stageY=this.stageX= +0;this.ratio=1;this.mouseY=this.mouseX=0;this.isMouseDown=!1;b.addEventListener("DOMMouseScroll",h,!0);b.addEventListener("mousewheel",h,!0);b.addEventListener("mousemove",function(b){a.mouseX=void 0!=b.offsetX&&b.offsetX||void 0!=b.layerX&&b.layerX||void 0!=b.clientX&&b.clientX;a.mouseY=void 0!=b.offsetY&&b.offsetY||void 0!=b.layerY&&b.layerY||void 0!=b.clientY&&b.clientY;if(a.isMouseDown){var d=a.mouseX-g+i,f=a.mouseY-c+k;if(d!=a.stageX||f!=a.stageY)q=s,m=z,s=d,z=f,a.stageX=d,a.stageY=f,a.dispatch("drag")}a.dispatch("move"); +b.preventDefault?b.preventDefault():b.returnValue=!1},!0);b.addEventListener("mousedown",function(b){if(a.p.mouseEnabled)a.isMouseDown=!0,a.dispatch("mousedown"),i=a.stageX,k=a.stageY,g=a.mouseX,c=a.mouseY,q=s=a.stageX,m=z=a.stageY,a.dispatch("startdrag"),b.preventDefault?b.preventDefault():b.returnValue=!1},!0);document.addEventListener("mouseup",function(b){if(a.p.mouseEnabled&&a.isMouseDown)a.isMouseDown=!1,a.dispatch("mouseup"),(i!=a.stageX||k!=a.stageY)&&e(a.stageX+a.p.inertia*(a.stageX-q),a.stageY+ +a.p.inertia*(a.stageY-m)),b.preventDefault?b.preventDefault():b.returnValue=!1},!0);this.checkBorders=function(){return a};this.interpolate=e}function m(b,h,e,d,a,g,c){function i(a){var b=d,c="fixed"==f.p.labelSize?f.p.defaultLabelSize:f.p.labelSizeRatio*a.displaySize;b.font=(f.p.hoverFontStyle||f.p.fontStyle||"")+" "+c+"px "+(f.p.hoverFont||f.p.font||"");b.fillStyle="node"==f.p.labelHoverBGColor?a.color||f.p.defaultNodeColor:f.p.defaultHoverLabelBGColor;b.beginPath();if(f.p.labelHoverShadow)b.shadowOffsetX= +0,b.shadowOffsetY=0,b.shadowBlur=4,b.shadowColor=f.p.labelHoverShadowColor;sigma.tools.drawRoundRect(b,Math.round(a.displayX-c/2-2),Math.round(a.displayY-c/2-2),Math.round(b.measureText(a.label).width+1.5*a.displaySize+c/2+4),Math.round(c+4),Math.round(c/2+2),"left");b.closePath();b.fill();b.shadowOffsetX=0;b.shadowOffsetY=0;b.shadowBlur=0;b.beginPath();b.fillStyle="node"==f.p.nodeBorderColor?a.color||f.p.defaultNodeColor:f.p.defaultNodeBorderColor;b.arc(Math.round(a.displayX),Math.round(a.displayY), +a.displaySize+f.p.borderSize,0,2*Math.PI,!0);b.closePath();b.fill();b.beginPath();b.fillStyle="node"==f.p.nodeHoverColor?a.color||f.p.defaultNodeColor:f.p.defaultNodeHoverColor;b.arc(Math.round(a.displayX),Math.round(a.displayY),a.displaySize,0,2*Math.PI,!0);b.closePath();b.fill();b.fillStyle="node"==f.p.labelHoverColor?a.color||f.p.defaultNodeColor:f.p.defaultLabelHoverColor;b.fillText(a.label,Math.round(a.displayX+1.5*a.displaySize),Math.round(a.displayY+c/2-3));return f}function k(a){if(isNaN(a.x)|| +isNaN(a.y))throw Error("A node's coordinate is not a number (id: "+a.id+")");return!a.hidden&&a.displayX+a.displaySize>-j/3&&a.displayX-a.displaySize<4*j/3&&a.displayY+a.displaySize>-l/3&&a.displayY-a.displaySize<4*l/3}sigma.classes.Cascade.call(this);var f=this;this.p={labelColor:"default",defaultLabelColor:"#000",labelHoverBGColor:"default",defaultHoverLabelBGColor:"#fff",labelHoverShadow:!0,labelHoverShadowColor:"#000",labelHoverColor:"default",defaultLabelHoverColor:"#000",labelActiveBGColor:"default", +defaultActiveLabelBGColor:"#fff",labelActiveShadow:!0,labelActiveShadowColor:"#000",labelActiveColor:"default",defaultLabelActiveColor:"#000",labelSize:"fixed",defaultLabelSize:12,labelSizeRatio:2,labelThreshold:6,font:"Arial",hoverFont:"",activeFont:"",fontStyle:"",hoverFontStyle:"",activeFontStyle:"",edgeColor:"source",defaultEdgeColor:"#aaa",defaultEdgeType:"line",defaultNodeColor:"#aaa",nodeHoverColor:"node",defaultNodeHoverColor:"#fff",nodeActiveColor:"node",defaultNodeActiveColor:"#fff",borderSize:0, +nodeBorderColor:"node",defaultNodeBorderColor:"#fff",edgesSpeed:200,nodesSpeed:200,labelsSpeed:200};var j=g,l=c;this.currentLabelIndex=this.currentNodeIndex=this.currentEdgeIndex=0;this.task_drawLabel=function(){for(var b=a.nodes.length,c=0;c++=f.p.labelThreshold){var k="fixed"==f.p.labelSize?f.p.defaultLabelSize:f.p.labelSizeRatio*d.displaySize;h.font= +f.p.fontStyle+k+"px "+f.p.font;h.fillStyle="node"==f.p.labelColor?d.color||f.p.defaultNodeColor:f.p.defaultLabelColor;h.fillText(d.label,Math.round(d.displayX+1.5*d.displaySize),Math.round(d.displayY+k/2-3))}}else f.currentLabelIndex++;return f.currentLabelIndex(b*=2)?0.5*b*b:-0.5*(--b*(b-2)-1)};sigma.tools.drawRoundRect=function(b,h,e,d,a,g,c){var g=g?g:0,i=c?c:[],i="string"==typeof i?i.split(" "):i,c=g&&(0<=i.indexOf("topleft")||0<=i.indexOf("top")||0<=i.indexOf("left")),j=g&&(0<=i.indexOf("topright")||0<=i.indexOf("top")||0<=i.indexOf("right")),f=g&&(0<=i.indexOf("bottomleft")||0<=i.indexOf("bottom")||0<=i.indexOf("left")),i=g&&(0<=i.indexOf("bottomright")|| +0<=i.indexOf("bottom")||0<=i.indexOf("right"));b.moveTo(h,e+g);c?b.arcTo(h,e,h+g,e,g):b.lineTo(h,e);j?(b.lineTo(h+d-g,e),b.arcTo(h+d,e,h+d,e+g,g)):b.lineTo(h+d,e);i?(b.lineTo(h+d,e+a-g),b.arcTo(h+d,e+a,h+d-g,e+a,g)):b.lineTo(h+d,e+a);f?(b.lineTo(h+g,e+a),b.arcTo(h,e+a,h,e+a-g,g)):b.lineTo(h,e+a);b.lineTo(h,e+g)};sigma.tools.getRGB=function(b,g){var b=b.toString(),e={r:0,g:0,b:0};if(3<=b.length&&"#"==b.charAt(0)){var d=b.length-1;6==d?e={r:parseInt(b.charAt(1)+b.charAt(2),16),g:parseInt(b.charAt(3)+ +b.charAt(4),16),b:parseInt(b.charAt(5)+b.charAt(5),16)}:3==d&&(e={r:parseInt(b.charAt(1)+b.charAt(1),16),g:parseInt(b.charAt(2)+b.charAt(2),16),b:parseInt(b.charAt(3)+b.charAt(3),16)})}g&&(e=[e.r,e.g,e.b]);return e};sigma.tools.rgbToHex=function(b,g,e){return sigma.tools.toHex(b)+sigma.tools.toHex(g)+sigma.tools.toHex(e)};sigma.tools.toHex=function(b){b=parseInt(b,10);if(isNaN(b))return"00";b=Math.max(0,Math.min(b,255));return"0123456789ABCDEF".charAt((b-b%16)/16)+"0123456789ABCDEF".charAt(b%16)}; +sigma.publicPrototype=p.prototype})(); --- /dev/null +++ b/lib/Color.php @@ -1,1 +1,502 @@ - + + * + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * + * @version $Id$ + * + */ +class Lux_Color +{ + /** + * + * Converts hexadecimal colors to RGB. + * + * @param string $hex Hexadecimal value. Accepts values with 3 or 6 numbers, + * with or without #, e.g., CCC, #CCC, CCCCCC or #CCCCCC. + * + * @return array RGB values: 0 => R, 1 => G, 2 => B + * + */ + public function hex2rgb($hex) + { + // Remove #. + if (strpos($hex, '#') === 0) { + $hex = substr($hex, 1); + } + + if (strlen($hex) == 3) { + $hex .= $hex; + } + + if (strlen($hex) != 6) { + return false; + } + + // Convert each tuple to decimal. + $r = hexdec(substr($hex, 0, 2)); + $g = hexdec(substr($hex, 2, 2)); + $b = hexdec(substr($hex, 4, 2)); + + return array($r, $g, $b); + } + + /** + * + * Converts hexadecimal colors to HSV. + * + * @param string $hex Hexadecimal value. Accepts values with 3 or 6 numbers, + * with or without #, e.g., CCC, #CCC, CCCCCC or #CCCCCC. + * + * @return array HSV values: 0 => H, 1 => S, 2 => V + * + */ + public function hex2hsv($hex) + { + return $this->rgb2hsv($this->hex2rgb($hex)); + } + + /** + * + * Converts hexadecimal colors to HSL. + * + * @param string $hex Hexadecimal value. Accepts values with 3 or 6 numbers, + * with or without #, e.g., CCC, #CCC, CCCCCC or #CCCCCC. + * + * @return array HSL values: 0 => H, 1 => S, 2 => L + * + */ + public function hex2hsl($hex) + { + return $this->rgb2hsl($this->hex2rgb($hex)); + } + + /** + * + * Converts RGB colors to hexadecimal. + * + * @param array $rgb RGB values: 0 => R, 1 => G, 2 => B + * + * @return string Hexadecimal value with six digits, e.g., CCCCCC. + * + */ + public function rgb2hex($rgb) + { + if(count($rgb) < 3) { + return false; + } + + list($r, $g, $b) = $rgb; + + // From php.net. + $r = 0x10000 * max(0, min(255, $r)); + $g = 0x100 * max(0, min(255, $g)); + $b = max(0, min(255, $b)); + + return strtoupper(str_pad(dechex($r + $g + $b), 6, 0, STR_PAD_LEFT)); + } + + /** + * + * Converts RGB to HSV. + * + * @param array $rgb RGB values: 0 => R, 1 => G, 2 => B + * + * @return array HSV values: 0 => H, 1 => S, 2 => V + * + */ + public function rgb2hsv($rgb) + { + // RGB values = 0 ÷ 255 + $var_R = ($rgb[0] / 255); + $var_G = ($rgb[1] / 255); + $var_B = ($rgb[2] / 255); + + // Min. value of RGB + $var_Min = min($var_R, $var_G, $var_B); + + // Max. value of RGB + $var_Max = max($var_R, $var_G, $var_B); + + // Delta RGB value + $del_Max = $var_Max - $var_Min; + + $V = $var_Max; + + // This is a gray, no chroma... + if ( $del_Max == 0 ) { + // HSV results = 0 ÷ 1 + $H = 0; + $S = 0; + } else { + // Chromatic data... + $S = $del_Max / $var_Max; + + $del_R = ((($var_Max - $var_R) / 6) + ($del_Max / 2)) / $del_Max; + $del_G = ((($var_Max - $var_G) / 6) + ($del_Max / 2)) / $del_Max; + $del_B = ((($var_Max - $var_B) / 6) + ($del_Max / 2)) / $del_Max; + + if ($var_R == $var_Max) { + $H = $del_B - $del_G; + } else if ($var_G == $var_Max) { + $H = (1 / 3) + $del_R - $del_B; + } else if ($var_B == $var_Max) { + $H = (2 / 3) + $del_G - $del_R; + } + + if ($H < 0) { + $H += 1; + } + if ($H > 1) { + $H -= 1; + } + } + + // Returns agnostic values. + // Range will depend on the application: e.g. $H*360, $S*100, $V*100. + return array($H, $S, $V); + } + + /** + * + * Converts RGB to HSL. + * + * @param array $rgb RGB values: 0 => R, 1 => G, 2 => B + * + * @return array HSL values: 0 => H, 1 => S, 2 => L + * + */ + public function rgb2hsl($rgb) + { + // Where RGB values = 0 ÷ 255. + $var_R = $rgb[0] / 255; + $var_G = $rgb[1] / 255; + $var_B = $rgb[2] / 255; + + // Min. value of RGB + $var_Min = min($var_R, $var_G, $var_B); + // Max. value of RGB + $var_Max = max($var_R, $var_G, $var_B); + // Delta RGB value + $del_Max = $var_Max - $var_Min; + + $L = ($var_Max + $var_Min) / 2; + + if ( $del_Max == 0 ) { + // This is a gray, no chroma... + // HSL results = 0 ÷ 1 + $H = 0; + $S = 0; + } else { + // Chromatic data... + if ($L < 0.5) { + $S = $del_Max / ($var_Max + $var_Min); + } else { + $S = $del_Max / ( 2 - $var_Max - $var_Min ); + } + + $del_R = ((($var_Max - $var_R) / 6) + ($del_Max / 2)) / $del_Max; + $del_G = ((($var_Max - $var_G) / 6) + ($del_Max / 2)) / $del_Max; + $del_B = ((($var_Max - $var_B) / 6) + ($del_Max / 2)) / $del_Max; + + if ($var_R == $var_Max) { + $H = $del_B - $del_G; + } else if ($var_G == $var_Max) { + $H = ( 1 / 3 ) + $del_R - $del_B; + } else if ($var_B == $var_Max) { + $H = ( 2 / 3 ) + $del_G - $del_R; + } + + if ($H < 0) { + $H += 1; + } + if ($H > 1) { + $H -= 1; + } + } + + return array($H, $S, $L); + } + + /** + * + * Converts HSV colors to hexadecimal. + * + * @param array $hsv HSV values: 0 => H, 1 => S, 2 => V + * + * @return string Hexadecimal value with six digits, e.g., CCCCCC. + * + */ + public function hsv2hex($hsv) + { + return $this->rgb2hex($this->hsv2rgb($hsv)); + } + + /** + * + * Converts HSV to RGB. + * + * @param array $hsv HSV values: 0 => H, 1 => S, 2 => V + * + * @return array RGB values: 0 => R, 1 => G, 2 => B + * + */ + public function hsv2rgb($hsv) + { + $H = $hsv[0]; + $S = $hsv[1]; + $V = $hsv[2]; + + // HSV values = 0 ÷ 1 + if ($S == 0) { + $R = $V * 255; + $G = $V * 255; + $B = $V * 255; + } else { + $var_h = $H * 6; + // H must be < 1 + if ( $var_h == 6 ) { + $var_h = 0; + } + // Or ... $var_i = floor( $var_h ) + $var_i = floor( $var_h ); + $var_1 = $V * ( 1 - $S ); + $var_2 = $V * ( 1 - $S * ( $var_h - $var_i ) ); + $var_3 = $V * ( 1 - $S * ( 1 - ( $var_h - $var_i ) ) ); + + switch($var_i) { + case 0: + $var_r = $V; + $var_g = $var_3; + $var_b = $var_1; + break; + case 1: + $var_r = $var_2; + $var_g = $V; + $var_b = $var_1; + break; + case 2: + $var_r = $var_1; + $var_g = $V; + $var_b = $var_3; + break; + case 3: + $var_r = $var_1; + $var_g = $var_2; + $var_b = $V; + break; + case 4: + $var_r = $var_3; + $var_g = $var_1; + $var_b = $V; + break; + default: + $var_r = $V; + $var_g = $var_1; + $var_b = $var_2; + } + + //RGB results = 0 ÷ 255 + $R = $var_r * 255; + $G = $var_g * 255; + $B = $var_b * 255; + } + + return array($R, $G, $B); + } + + /** + * + * Converts HSV colors to HSL. + * + * @param array $hsv HSV values: 0 => H, 1 => S, 2 => V + * + * @return array HSL values: 0 => H, 1 => S, 2 => L + * + */ + public function hsv2hsl($hsv) + { + return $this->rgb2hsl($this->hsv2rgb($hsv)); + } + + /** + * + * Converts hexadecimal colors to HSL. + * + * @param array $hsl HSL values: 0 => H, 1 => S, 2 => L + * + * @return string Hexadecimal value. Accepts values with 3 or 6 numbers, + * with or without #, e.g., CCC, #CCC, CCCCCC or #CCCCCC. + * + */ + public function hsl2hex($hsl) + { + return $this->rgb2hex($this->hsl2rgb($hsl)); + } + + /** + * + * Converts HSL to RGB. + * + * @param array $hsv HSL values: 0 => H, 1 => S, 2 => L + * + * @return array RGB values: 0 => R, 1 => G, 2 => B + * + */ + public function hsl2rgb($hsl) + { + list($H, $S, $L) = $hsl; + + if ($S == 0) { + // HSL values = 0 ÷ 1 + // RGB results = 0 ÷ 255 + $R = $L * 255; + $G = $L * 255; + $B = $L * 255; + } else { + if ($L < 0.5) { + $var_2 = $L * (1 + $S); + } else { + $var_2 = ($L + $S) - ($S * $L); + } + + $var_1 = 2 * $L - $var_2; + + $R = 255 * $this->_hue2rgb($var_1, $var_2, $H + (1 / 3)); + $G = 255 * $this->_hue2rgb($var_1, $var_2, $H); + $B = 255 * $this->_hue2rgb($var_1, $var_2, $H - (1 / 3)); + } + + return array($R, $G, $B); + } + + /** + * + * Support method for hsl2rgb(): converts hue ro RGB. + * + * @param + * + * @param + * + * @param + * + * @return int + * + */ + protected function _hue2rgb($v1, $v2, $vH) + { + if ($vH < 0) { + $vH += 1; + } + + if ($vH > 1) { + $vH -= 1; + } + + if ((6 * $vH) < 1) { + return ($v1 + ($v2 - $v1) * 6 * $vH); + } + + if ((2 * $vH) < 1) { + return $v2; + } + + if ((3 * $vH) < 2) { + return ($v1 + ($v2 - $v1) * (( 2 / 3) - $vH) * 6); + } + + return $v1; + } + + /** + * + * Converts hexadecimal colors to HSL. + * + * @param array $hsl HSL values: 0 => H, 1 => S, 2 => L + * + * @return array HSV values: 0 => H, 1 => S, 2 => V + * + */ + public function hsl2hsv($hsl) + { + return $this->rgb2hsv($this->hsl2rgb($hsl)); + } + + /** + * + * Updates HSV values. + * + * @param array $hsv HSV values: 0 => H, 1 => S, 2 => V + * + * @param array $values Values to update: 0 => value to add to H (0 to 360), + * 1 and 2 => values to multiply S and V (0 to 100). Example: + * + * {{{code:php + * // Update saturation to 80% in the provided HSV. + * $hsv = array(120, 0.75, 0.75); + * $new_hsv = $color->updateHsv($hsv, array(null, 80, null)); + * }}} + * + */ + public function updateHsv($hsv, $values) + { + if (isset($values[0])) { + $hsv[0] = max(0, min(360, ($hsv[0] + $values[0]))); + } + + if (isset($values[1])) { + $hsv[1] = max(0, min(1, ($hsv[1] * ($values[1] / 100)))); + } + + if (isset($values[2])) { + $hsv[2] = max(0, min(1, ($hsv[2] * ($values[2] / 100)))); + } + + return $hsv; + } + + /** + * + * Updates HSL values. + * + * @param array $hsl HSL values: 0 => H, 1 => S, 2 => L + * + * @param array $values Values to update: 0 => value to add to H (0 to 360), + * 1 and 2 => values to multiply S and V (0 to 100). Example: + * + * {{{code:php + * // Update saturation to 80% in the provided HSL. + * $hsl = array(120, 0.75, 0.75); + * $new_hsl = $color->updateHsl($hsl, array(null, 80, null)); + * }}} + * + */ + public function updateHsl($hsl, $values) + { + if (isset($values[0])) { + $hsl[0] = max(0, min(360, ($hsl[0] + $values[0]))); + } + + if (isset($values[1])) { + $hsl[1] = max(0, min(1, ($hsl[1] * ($values[1] / 100)))); + } + + if (isset($values[2])) { + $hsl[2] = max(0, min(1, ($hsl[2] * ($values[2] / 100)))); + } + + return $hsl; + } +} --- a/lib/springy +++ /dev/null