[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Builtin functions 5 * 6 * @package Less 7 * @subpackage function 8 * @see http://lesscss.org/functions/ 9 */ 10 class Less_Functions{ 11 12 public $env; 13 public $currentFileInfo; 14 15 function __construct($env, $currentFileInfo = null ){ 16 $this->env = $env; 17 $this->currentFileInfo = $currentFileInfo; 18 } 19 20 21 /** 22 * @param string $op 23 */ 24 static public function operate( $op, $a, $b ){ 25 switch ($op) { 26 case '+': return $a + $b; 27 case '-': return $a - $b; 28 case '*': return $a * $b; 29 case '/': return $a / $b; 30 } 31 } 32 33 static public function clamp($val, $max = 1){ 34 return min( max($val, 0), $max); 35 } 36 37 static function fround( $value ){ 38 39 if( $value === 0 ){ 40 return $value; 41 } 42 43 if( Less_Parser::$options['numPrecision'] ){ 44 $p = pow(10, Less_Parser::$options['numPrecision']); 45 return round( $value * $p) / $p; 46 } 47 return $value; 48 } 49 50 static public function number($n){ 51 52 if ($n instanceof Less_Tree_Dimension) { 53 return floatval( $n->unit->is('%') ? $n->value / 100 : $n->value); 54 } else if (is_numeric($n)) { 55 return $n; 56 } else { 57 throw new Less_Exception_Compiler("color functions take numbers as parameters"); 58 } 59 } 60 61 static public function scaled($n, $size = 255 ){ 62 if( $n instanceof Less_Tree_Dimension && $n->unit->is('%') ){ 63 return (float)$n->value * $size / 100; 64 } else { 65 return Less_Functions::number($n); 66 } 67 } 68 69 public function rgb ($r, $g, $b){ 70 return $this->rgba($r, $g, $b, 1.0); 71 } 72 73 public function rgba($r, $g, $b, $a){ 74 $rgb = array($r, $g, $b); 75 $rgb = array_map(array('Less_Functions','scaled'),$rgb); 76 77 $a = self::number($a); 78 return new Less_Tree_Color($rgb, $a); 79 } 80 81 public function hsl($h, $s, $l){ 82 return $this->hsla($h, $s, $l, 1.0); 83 } 84 85 public function hsla($h, $s, $l, $a){ 86 87 $h = fmod(self::number($h), 360) / 360; // Classic % operator will change float to int 88 $s = self::clamp(self::number($s)); 89 $l = self::clamp(self::number($l)); 90 $a = self::clamp(self::number($a)); 91 92 $m2 = $l <= 0.5 ? $l * ($s + 1) : $l + $s - $l * $s; 93 94 $m1 = $l * 2 - $m2; 95 96 return $this->rgba( self::hsla_hue($h + 1/3, $m1, $m2) * 255, 97 self::hsla_hue($h, $m1, $m2) * 255, 98 self::hsla_hue($h - 1/3, $m1, $m2) * 255, 99 $a); 100 } 101 102 /** 103 * @param double $h 104 */ 105 function hsla_hue($h, $m1, $m2){ 106 $h = $h < 0 ? $h + 1 : ($h > 1 ? $h - 1 : $h); 107 if ($h * 6 < 1) return $m1 + ($m2 - $m1) * $h * 6; 108 else if ($h * 2 < 1) return $m2; 109 else if ($h * 3 < 2) return $m1 + ($m2 - $m1) * (2/3 - $h) * 6; 110 else return $m1; 111 } 112 113 public function hsv($h, $s, $v) { 114 return $this->hsva($h, $s, $v, 1.0); 115 } 116 117 /** 118 * @param double $a 119 */ 120 public function hsva($h, $s, $v, $a) { 121 $h = ((Less_Functions::number($h) % 360) / 360 ) * 360; 122 $s = Less_Functions::number($s); 123 $v = Less_Functions::number($v); 124 $a = Less_Functions::number($a); 125 126 $i = floor(($h / 60) % 6); 127 $f = ($h / 60) - $i; 128 129 $vs = array( $v, 130 $v * (1 - $s), 131 $v * (1 - $f * $s), 132 $v * (1 - (1 - $f) * $s)); 133 134 $perm = array(array(0, 3, 1), 135 array(2, 0, 1), 136 array(1, 0, 3), 137 array(1, 2, 0), 138 array(3, 1, 0), 139 array(0, 1, 2)); 140 141 return $this->rgba($vs[$perm[$i][0]] * 255, 142 $vs[$perm[$i][1]] * 255, 143 $vs[$perm[$i][2]] * 255, 144 $a); 145 } 146 147 public function hue($color){ 148 $c = $color->toHSL(); 149 return new Less_Tree_Dimension(Less_Parser::round($c['h'])); 150 } 151 152 public function saturation($color){ 153 $c = $color->toHSL(); 154 return new Less_Tree_Dimension(Less_Parser::round($c['s'] * 100), '%'); 155 } 156 157 public function lightness($color){ 158 $c = $color->toHSL(); 159 return new Less_Tree_Dimension(Less_Parser::round($c['l'] * 100), '%'); 160 } 161 162 public function hsvhue( $color ){ 163 $hsv = $color->toHSV(); 164 return new Less_Tree_Dimension( Less_Parser::round($hsv['h']) ); 165 } 166 167 168 public function hsvsaturation( $color ){ 169 $hsv = $color->toHSV(); 170 return new Less_Tree_Dimension( Less_Parser::round($hsv['s'] * 100), '%' ); 171 } 172 173 public function hsvvalue( $color ){ 174 $hsv = $color->toHSV(); 175 return new Less_Tree_Dimension( Less_Parser::round($hsv['v'] * 100), '%' ); 176 } 177 178 public function red($color) { 179 return new Less_Tree_Dimension( $color->rgb[0] ); 180 } 181 182 public function green($color) { 183 return new Less_Tree_Dimension( $color->rgb[1] ); 184 } 185 186 public function blue($color) { 187 return new Less_Tree_Dimension( $color->rgb[2] ); 188 } 189 190 public function alpha($color){ 191 $c = $color->toHSL(); 192 return new Less_Tree_Dimension($c['a']); 193 } 194 195 public function luma ($color) { 196 return new Less_Tree_Dimension(Less_Parser::round( $color->luma() * $color->alpha * 100), '%'); 197 } 198 199 public function luminance( $color ){ 200 $luminance = 201 (0.2126 * $color->rgb[0] / 255) 202 + (0.7152 * $color->rgb[1] / 255) 203 + (0.0722 * $color->rgb[2] / 255); 204 205 return new Less_Tree_Dimension(Less_Parser::round( $luminance * $color->alpha * 100), '%'); 206 } 207 208 public function saturate($color, $amount = null){ 209 // filter: saturate(3.2); 210 // should be kept as is, so check for color 211 if( !property_exists($color,'rgb') ){ 212 return null; 213 } 214 $hsl = $color->toHSL(); 215 216 $hsl['s'] += $amount->value / 100; 217 $hsl['s'] = self::clamp($hsl['s']); 218 219 return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']); 220 } 221 222 /** 223 * @param Less_Tree_Dimension $amount 224 */ 225 public function desaturate($color, $amount){ 226 $hsl = $color->toHSL(); 227 228 $hsl['s'] -= $amount->value / 100; 229 $hsl['s'] = self::clamp($hsl['s']); 230 231 return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']); 232 } 233 234 235 236 public function lighten($color, $amount){ 237 $hsl = $color->toHSL(); 238 239 $hsl['l'] += $amount->value / 100; 240 $hsl['l'] = self::clamp($hsl['l']); 241 242 return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']); 243 } 244 245 public function darken($color, $amount){ 246 247 if( $color instanceof Less_Tree_Color ){ 248 $hsl = $color->toHSL(); 249 $hsl['l'] -= $amount->value / 100; 250 $hsl['l'] = self::clamp($hsl['l']); 251 252 return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']); 253 } 254 255 Less_Functions::Expected('color',$color); 256 } 257 258 public function fadein($color, $amount){ 259 $hsl = $color->toHSL(); 260 $hsl['a'] += $amount->value / 100; 261 $hsl['a'] = self::clamp($hsl['a']); 262 return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']); 263 } 264 265 public function fadeout($color, $amount){ 266 $hsl = $color->toHSL(); 267 $hsl['a'] -= $amount->value / 100; 268 $hsl['a'] = self::clamp($hsl['a']); 269 return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']); 270 } 271 272 public function fade($color, $amount){ 273 $hsl = $color->toHSL(); 274 275 $hsl['a'] = $amount->value / 100; 276 $hsl['a'] = self::clamp($hsl['a']); 277 return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']); 278 } 279 280 281 282 public function spin($color, $amount){ 283 $hsl = $color->toHSL(); 284 $hue = fmod($hsl['h'] + $amount->value, 360); 285 286 $hsl['h'] = $hue < 0 ? 360 + $hue : $hue; 287 288 return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']); 289 } 290 291 // 292 // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein 293 // http://sass-lang.com 294 // 295 296 /** 297 * @param Less_Tree_Color $color1 298 */ 299 public function mix($color1, $color2, $weight = null){ 300 if (!$weight) { 301 $weight = new Less_Tree_Dimension('50', '%'); 302 } 303 304 $p = $weight->value / 100.0; 305 $w = $p * 2 - 1; 306 $hsl1 = $color1->toHSL(); 307 $hsl2 = $color2->toHSL(); 308 $a = $hsl1['a'] - $hsl2['a']; 309 310 $w1 = (((($w * $a) == -1) ? $w : ($w + $a) / (1 + $w * $a)) + 1) / 2; 311 $w2 = 1 - $w1; 312 313 $rgb = array($color1->rgb[0] * $w1 + $color2->rgb[0] * $w2, 314 $color1->rgb[1] * $w1 + $color2->rgb[1] * $w2, 315 $color1->rgb[2] * $w1 + $color2->rgb[2] * $w2); 316 317 $alpha = $color1->alpha * $p + $color2->alpha * (1 - $p); 318 319 return new Less_Tree_Color($rgb, $alpha); 320 } 321 322 public function greyscale($color){ 323 return $this->desaturate($color, new Less_Tree_Dimension(100)); 324 } 325 326 327 public function contrast( $color, $dark = null, $light = null, $threshold = null){ 328 // filter: contrast(3.2); 329 // should be kept as is, so check for color 330 if( !property_exists($color,'rgb') ){ 331 return null; 332 } 333 if( !$light ){ 334 $light = $this->rgba(255, 255, 255, 1.0); 335 } 336 if( !$dark ){ 337 $dark = $this->rgba(0, 0, 0, 1.0); 338 } 339 //Figure out which is actually light and dark! 340 if( $dark->luma() > $light->luma() ){ 341 $t = $light; 342 $light = $dark; 343 $dark = $t; 344 } 345 if( !$threshold ){ 346 $threshold = 0.43; 347 } else { 348 $threshold = Less_Functions::number($threshold); 349 } 350 351 if( $color->luma() < $threshold ){ 352 return $light; 353 } else { 354 return $dark; 355 } 356 } 357 358 public function e ($str){ 359 if( is_string($str) ){ 360 return new Less_Tree_Anonymous($str); 361 } 362 return new Less_Tree_Anonymous($str instanceof Less_Tree_JavaScript ? $str->expression : $str->value); 363 } 364 365 public function escape ($str){ 366 367 $revert = array('%21'=>'!', '%2A'=>'*', '%27'=>"'",'%3F'=>'?','%26'=>'&','%2C'=>',','%2F'=>'/','%40'=>'@','%2B'=>'+','%24'=>'$'); 368 369 return new Less_Tree_Anonymous(strtr(rawurlencode($str->value), $revert)); 370 } 371 372 373 /** 374 * todo: This function will need some additional work to make it work the same as less.js 375 * 376 */ 377 public function replace( $string, $pattern, $replacement, $flags = null ){ 378 $result = $string->value; 379 380 $expr = '/'.str_replace('/','\\/',$pattern->value).'/'; 381 if( $flags && $flags->value){ 382 $expr .= self::replace_flags($flags->value); 383 } 384 385 $result = preg_replace($expr,$replacement->value,$result); 386 387 388 if( property_exists($string,'quote') ){ 389 return new Less_Tree_Quoted( $string->quote, $result, $string->escaped); 390 } 391 return new Less_Tree_Quoted( '', $result ); 392 } 393 394 public static function replace_flags($flags){ 395 $flags = str_split($flags,1); 396 $new_flags = ''; 397 398 foreach($flags as $flag){ 399 switch($flag){ 400 case 'e': 401 case 'g': 402 break; 403 404 default: 405 $new_flags .= $flag; 406 break; 407 } 408 } 409 410 return $new_flags; 411 } 412 413 public function _percent(){ 414 $string = func_get_arg(0); 415 416 $args = func_get_args(); 417 array_shift($args); 418 $result = $string->value; 419 420 foreach($args as $arg){ 421 if( preg_match('/%[sda]/i',$result, $token) ){ 422 $token = $token[0]; 423 $value = stristr($token, 's') ? $arg->value : $arg->toCSS(); 424 $value = preg_match('/[A-Z]$/', $token) ? urlencode($value) : $value; 425 $result = preg_replace('/%[sda]/i',$value, $result, 1); 426 } 427 } 428 $result = str_replace('%%', '%', $result); 429 430 return new Less_Tree_Quoted( $string->quote , $result, $string->escaped); 431 } 432 433 public function unit( $val, $unit = null) { 434 if( !($val instanceof Less_Tree_Dimension) ){ 435 throw new Less_Exception_Compiler('The first argument to unit must be a number' . ($val instanceof Less_Tree_Operation ? '. Have you forgotten parenthesis?' : '.') ); 436 } 437 438 if( $unit ){ 439 if( $unit instanceof Less_Tree_Keyword ){ 440 $unit = $unit->value; 441 } else { 442 $unit = $unit->toCSS(); 443 } 444 } else { 445 $unit = ""; 446 } 447 return new Less_Tree_Dimension($val->value, $unit ); 448 } 449 450 public function convert($val, $unit){ 451 return $val->convertTo($unit->value); 452 } 453 454 public function round($n, $f = false) { 455 456 $fraction = 0; 457 if( $f !== false ){ 458 $fraction = $f->value; 459 } 460 461 return $this->_math('Less_Parser::round',null, $n, $fraction); 462 } 463 464 public function pi(){ 465 return new Less_Tree_Dimension(M_PI); 466 } 467 468 public function mod($a, $b) { 469 return new Less_Tree_Dimension( $a->value % $b->value, $a->unit); 470 } 471 472 473 474 public function pow($x, $y) { 475 if( is_numeric($x) && is_numeric($y) ){ 476 $x = new Less_Tree_Dimension($x); 477 $y = new Less_Tree_Dimension($y); 478 }elseif( !($x instanceof Less_Tree_Dimension) || !($y instanceof Less_Tree_Dimension) ){ 479 throw new Less_Exception_Compiler('Arguments must be numbers'); 480 } 481 482 return new Less_Tree_Dimension( pow($x->value, $y->value), $x->unit ); 483 } 484 485 // var mathFunctions = [{name:"ce ... 486 public function ceil( $n ){ return $this->_math('ceil', null, $n); } 487 public function floor( $n ){ return $this->_math('floor', null, $n); } 488 public function sqrt( $n ){ return $this->_math('sqrt', null, $n); } 489 public function abs( $n ){ return $this->_math('abs', null, $n); } 490 491 public function tan( $n ){ return $this->_math('tan', '', $n); } 492 public function sin( $n ){ return $this->_math('sin', '', $n); } 493 public function cos( $n ){ return $this->_math('cos', '', $n); } 494 495 public function atan( $n ){ return $this->_math('atan', 'rad', $n); } 496 public function asin( $n ){ return $this->_math('asin', 'rad', $n); } 497 public function acos( $n ){ return $this->_math('acos', 'rad', $n); } 498 499 private function _math() { 500 $args = func_get_args(); 501 $fn = array_shift($args); 502 $unit = array_shift($args); 503 504 if ($args[0] instanceof Less_Tree_Dimension) { 505 506 if( $unit === null ){ 507 $unit = $args[0]->unit; 508 }else{ 509 $args[0] = $args[0]->unify(); 510 } 511 $args[0] = (float)$args[0]->value; 512 return new Less_Tree_Dimension( call_user_func_array($fn, $args), $unit); 513 } else if (is_numeric($args[0])) { 514 return call_user_func_array($fn,$args); 515 } else { 516 throw new Less_Exception_Compiler("math functions take numbers as parameters"); 517 } 518 } 519 520 /** 521 * @param boolean $isMin 522 */ 523 function _minmax( $isMin, $args ){ 524 525 $arg_count = count($args); 526 527 if( $arg_count < 1 ){ 528 throw new Less_Exception_Compiler( 'one or more arguments required'); 529 } 530 531 $j = null; 532 $unitClone = null; 533 $unitStatic = null; 534 535 536 $order = array(); // elems only contains original argument values. 537 $values = array(); // key is the unit.toString() for unified tree.Dimension values, 538 // value is the index into the order array. 539 540 541 for( $i = 0; $i < $arg_count; $i++ ){ 542 $current = $args[$i]; 543 if( !($current instanceof Less_Tree_Dimension) ){ 544 if( is_array($args[$i]->value) ){ 545 $args[] = $args[$i]->value; 546 } 547 continue; 548 } 549 550 if( $current->unit->toString() === '' && !$unitClone ){ 551 $temp = new Less_Tree_Dimension($current->value, $unitClone); 552 $currentUnified = $temp->unify(); 553 }else{ 554 $currentUnified = $current->unify(); 555 } 556 557 if( $currentUnified->unit->toString() === "" && !$unitStatic ){ 558 $unit = $unitStatic; 559 }else{ 560 $unit = $currentUnified->unit->toString(); 561 } 562 563 if( $unit !== '' && !$unitStatic || $unit !== '' && $order[0]->unify()->unit->toString() === "" ){ 564 $unitStatic = $unit; 565 } 566 567 if( $unit != '' && !$unitClone ){ 568 $unitClone = $current->unit->toString(); 569 } 570 571 if( isset($values['']) && $unit !== '' && $unit === $unitStatic ){ 572 $j = $values['']; 573 }elseif( isset($values[$unit]) ){ 574 $j = $values[$unit]; 575 }else{ 576 577 if( $unitStatic && $unit !== $unitStatic ){ 578 throw new Less_Exception_Compiler( 'incompatible types'); 579 } 580 $values[$unit] = count($order); 581 $order[] = $current; 582 continue; 583 } 584 585 586 if( $order[$j]->unit->toString() === "" && $unitClone ){ 587 $temp = new Less_Tree_Dimension( $order[$j]->value, $unitClone); 588 $referenceUnified = $temp->unifiy(); 589 }else{ 590 $referenceUnified = $order[$j]->unify(); 591 } 592 if( ($isMin && $currentUnified->value < $referenceUnified->value) || (!$isMin && $currentUnified->value > $referenceUnified->value) ){ 593 $order[$j] = $current; 594 } 595 } 596 597 if( count($order) == 1 ){ 598 return $order[0]; 599 } 600 $args = array(); 601 foreach($order as $a){ 602 $args[] = $a->toCSS($this->env); 603 } 604 return new Less_Tree_Anonymous( ($isMin?'min(':'max(') . implode(Less_Environment::$_outputMap[','],$args).')'); 605 } 606 607 public function min(){ 608 $args = func_get_args(); 609 return $this->_minmax( true, $args ); 610 } 611 612 public function max(){ 613 $args = func_get_args(); 614 return $this->_minmax( false, $args ); 615 } 616 617 public function getunit($n){ 618 return new Less_Tree_Anonymous($n->unit); 619 } 620 621 public function argb($color) { 622 return new Less_Tree_Anonymous($color->toARGB()); 623 } 624 625 public function percentage($n) { 626 return new Less_Tree_Dimension($n->value * 100, '%'); 627 } 628 629 public function color($n) { 630 631 if( $n instanceof Less_Tree_Quoted ){ 632 $colorCandidate = $n->value; 633 $returnColor = Less_Tree_Color::fromKeyword($colorCandidate); 634 if( $returnColor ){ 635 return $returnColor; 636 } 637 if( preg_match('/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/',$colorCandidate) ){ 638 return new Less_Tree_Color(substr($colorCandidate, 1)); 639 } 640 throw new Less_Exception_Compiler("argument must be a color keyword or 3/6 digit hex e.g. #FFF"); 641 } else { 642 throw new Less_Exception_Compiler("argument must be a string"); 643 } 644 } 645 646 647 public function iscolor($n) { 648 return $this->_isa($n, 'Less_Tree_Color'); 649 } 650 651 public function isnumber($n) { 652 return $this->_isa($n, 'Less_Tree_Dimension'); 653 } 654 655 public function isstring($n) { 656 return $this->_isa($n, 'Less_Tree_Quoted'); 657 } 658 659 public function iskeyword($n) { 660 return $this->_isa($n, 'Less_Tree_Keyword'); 661 } 662 663 public function isurl($n) { 664 return $this->_isa($n, 'Less_Tree_Url'); 665 } 666 667 public function ispixel($n) { 668 return $this->isunit($n, 'px'); 669 } 670 671 public function ispercentage($n) { 672 return $this->isunit($n, '%'); 673 } 674 675 public function isem($n) { 676 return $this->isunit($n, 'em'); 677 } 678 679 /** 680 * @param string $unit 681 */ 682 public function isunit( $n, $unit ){ 683 return ($n instanceof Less_Tree_Dimension) && $n->unit->is( ( property_exists($unit,'value') ? $unit->value : $unit) ) ? new Less_Tree_Keyword('true') : new Less_Tree_Keyword('false'); 684 } 685 686 /** 687 * @param string $type 688 */ 689 private function _isa($n, $type) { 690 return is_a($n, $type) ? new Less_Tree_Keyword('true') : new Less_Tree_Keyword('false'); 691 } 692 693 public function tint($color, $amount) { 694 return $this->mix( $this->rgb(255,255,255), $color, $amount); 695 } 696 697 public function shade($color, $amount) { 698 return $this->mix($this->rgb(0, 0, 0), $color, $amount); 699 } 700 701 public function extract($values, $index ){ 702 $index = (int)$index->value - 1; // (1-based index) 703 // handle non-array values as an array of length 1 704 // return 'undefined' if index is invalid 705 if( property_exists($values,'value') && is_array($values->value) ){ 706 if( isset($values->value[$index]) ){ 707 return $values->value[$index]; 708 } 709 return null; 710 711 }elseif( (int)$index === 0 ){ 712 return $values; 713 } 714 715 return null; 716 } 717 718 function length($values){ 719 $n = (property_exists($values,'value') && is_array($values->value)) ? count($values->value) : 1; 720 return new Less_Tree_Dimension($n); 721 } 722 723 function datauri($mimetypeNode, $filePathNode = null ) { 724 725 $filePath = ( $filePathNode ? $filePathNode->value : null ); 726 $mimetype = $mimetypeNode->value; 727 728 $args = 2; 729 if( !$filePath ){ 730 $filePath = $mimetype; 731 $args = 1; 732 } 733 734 $filePath = str_replace('\\','/',$filePath); 735 if( Less_Environment::isPathRelative($filePath) ){ 736 737 if( Less_Parser::$options['relativeUrls'] ){ 738 $temp = $this->currentFileInfo['currentDirectory']; 739 } else { 740 $temp = $this->currentFileInfo['entryPath']; 741 } 742 743 if( !empty($temp) ){ 744 $filePath = Less_Environment::normalizePath(rtrim($temp,'/').'/'.$filePath); 745 } 746 747 } 748 749 750 // detect the mimetype if not given 751 if( $args < 2 ){ 752 753 /* incomplete 754 $mime = require('mime'); 755 mimetype = mime.lookup(path); 756 757 // use base 64 unless it's an ASCII or UTF-8 format 758 var charset = mime.charsets.lookup(mimetype); 759 useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0; 760 if (useBase64) mimetype += ';base64'; 761 */ 762 763 $mimetype = Less_Mime::lookup($filePath); 764 765 $charset = Less_Mime::charsets_lookup($mimetype); 766 $useBase64 = !in_array($charset,array('US-ASCII', 'UTF-8')); 767 if( $useBase64 ){ $mimetype .= ';base64'; } 768 769 }else{ 770 $useBase64 = preg_match('/;base64$/',$mimetype); 771 } 772 773 774 if( file_exists($filePath) ){ 775 $buf = @file_get_contents($filePath); 776 }else{ 777 $buf = false; 778 } 779 780 781 // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded 782 // and the --ieCompat flag is enabled, return a normal url() instead. 783 $DATA_URI_MAX_KB = 32; 784 $fileSizeInKB = round( strlen($buf) / 1024 ); 785 if( $fileSizeInKB >= $DATA_URI_MAX_KB ){ 786 $url = new Less_Tree_Url( ($filePathNode ? $filePathNode : $mimetypeNode), $this->currentFileInfo); 787 return $url->compile($this); 788 } 789 790 if( $buf ){ 791 $buf = $useBase64 ? base64_encode($buf) : rawurlencode($buf); 792 $filePath = '"data:' . $mimetype . ',' . $buf . '"'; 793 } 794 795 return new Less_Tree_Url( new Less_Tree_Anonymous($filePath) ); 796 } 797 798 //svg-gradient 799 function svggradient( $direction ){ 800 801 $throw_message = 'svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]'; 802 $arguments = func_get_args(); 803 804 if( count($arguments) < 3 ){ 805 throw new Less_Exception_Compiler( $throw_message ); 806 } 807 808 $stops = array_slice($arguments,1); 809 $gradientType = 'linear'; 810 $rectangleDimension = 'x="0" y="0" width="1" height="1"'; 811 $useBase64 = true; 812 $directionValue = $direction->toCSS(); 813 814 815 switch( $directionValue ){ 816 case "to bottom": 817 $gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"'; 818 break; 819 case "to right": 820 $gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"'; 821 break; 822 case "to bottom right": 823 $gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"'; 824 break; 825 case "to top right": 826 $gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"'; 827 break; 828 case "ellipse": 829 case "ellipse at center": 830 $gradientType = "radial"; 831 $gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"'; 832 $rectangleDimension = 'x="-50" y="-50" width="101" height="101"'; 833 break; 834 default: 835 throw new Less_Exception_Compiler( "svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'" ); 836 } 837 838 $returner = '<?xml version="1.0" ?>' . 839 '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">' . 840 '<' . $gradientType . 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' . $gradientDirectionSvg . '>'; 841 842 for( $i = 0; $i < count($stops); $i++ ){ 843 if( is_object($stops[$i]) && property_exists($stops[$i],'value') ){ 844 $color = $stops[$i]->value[0]; 845 $position = $stops[$i]->value[1]; 846 }else{ 847 $color = $stops[$i]; 848 $position = null; 849 } 850 851 if( !($color instanceof Less_Tree_Color) || (!(($i === 0 || $i+1 === count($stops)) && $position === null) && !($position instanceof Less_Tree_Dimension)) ){ 852 throw new Less_Exception_Compiler( $throw_message ); 853 } 854 if( $position ){ 855 $positionValue = $position->toCSS(); 856 }elseif( $i === 0 ){ 857 $positionValue = '0%'; 858 }else{ 859 $positionValue = '100%'; 860 } 861 $alpha = $color->alpha; 862 $returner .= '<stop offset="' . $positionValue . '" stop-color="' . $color->toRGB() . '"' . ($alpha < 1 ? ' stop-opacity="' . $alpha . '"' : '') . '/>'; 863 } 864 865 $returner .= '</' . $gradientType . 'Gradient><rect ' . $rectangleDimension . ' fill="url(#gradient)" /></svg>'; 866 867 868 if( $useBase64 ){ 869 $returner = "'data:image/svg+xml;base64,".base64_encode($returner)."'"; 870 }else{ 871 $returner = "'data:image/svg+xml,".$returner."'"; 872 } 873 874 return new Less_Tree_URL( new Less_Tree_Anonymous( $returner ) ); 875 } 876 877 878 /** 879 * @param string $type 880 */ 881 private static function Expected( $type, $arg ){ 882 883 $debug = debug_backtrace(); 884 array_shift($debug); 885 $last = array_shift($debug); 886 $last = array_intersect_key($last,array('function'=>'','class'=>'','line'=>'')); 887 888 $message = 'Object of type '.get_class($arg).' passed to darken function. Expecting `'.$type.'`. '.$arg->toCSS().'. '.print_r($last,true); 889 throw new Less_Exception_Compiler($message); 890 891 } 892 893 /** 894 * Php version of javascript's `encodeURIComponent` function 895 * 896 * @param string $string The string to encode 897 * @return string The encoded string 898 */ 899 public static function encodeURIComponent($string){ 900 $revert = array('%21' => '!', '%2A' => '*', '%27' => "'", '%28' => '(', '%29' => ')'); 901 return strtr(rawurlencode($string), $revert); 902 } 903 904 905 // Color Blending 906 // ref: http://www.w3.org/TR/compositing-1 907 908 public function colorBlend( $mode, $color1, $color2 ){ 909 $ab = $color1->alpha; // backdrop 910 $as = $color2->alpha; // source 911 $r = array(); // result 912 913 $ar = $as + $ab * (1 - $as); 914 for( $i = 0; $i < 3; $i++ ){ 915 $cb = $color1->rgb[$i] / 255; 916 $cs = $color2->rgb[$i] / 255; 917 $cr = call_user_func( $mode, $cb, $cs ); 918 if( $ar ){ 919 $cr = ($as * $cs + $ab * ($cb - $as * ($cb + $cs - $cr))) / $ar; 920 } 921 $r[$i] = $cr * 255; 922 } 923 924 return new Less_Tree_Color($r, $ar); 925 } 926 927 public function multiply($color1, $color2 ){ 928 return $this->colorBlend( array($this,'colorBlendMultiply'), $color1, $color2 ); 929 } 930 931 private function colorBlendMultiply($cb, $cs){ 932 return $cb * $cs; 933 } 934 935 public function screen($color1, $color2 ){ 936 return $this->colorBlend( array($this,'colorBlendScreen'), $color1, $color2 ); 937 } 938 939 private function colorBlendScreen( $cb, $cs){ 940 return $cb + $cs - $cb * $cs; 941 } 942 943 public function overlay($color1, $color2){ 944 return $this->colorBlend( array($this,'colorBlendOverlay'), $color1, $color2 ); 945 } 946 947 private function colorBlendOverlay($cb, $cs ){ 948 $cb *= 2; 949 return ($cb <= 1) 950 ? $this->colorBlendMultiply($cb, $cs) 951 : $this->colorBlendScreen($cb - 1, $cs); 952 } 953 954 public function softlight($color1, $color2){ 955 return $this->colorBlend( array($this,'colorBlendSoftlight'), $color1, $color2 ); 956 } 957 958 private function colorBlendSoftlight($cb, $cs ){ 959 $d = 1; 960 $e = $cb; 961 if( $cs > 0.5 ){ 962 $e = 1; 963 $d = ($cb > 0.25) ? sqrt($cb) 964 : ((16 * $cb - 12) * $cb + 4) * $cb; 965 } 966 return $cb - (1 - 2 * $cs) * $e * ($d - $cb); 967 } 968 969 public function hardlight($color1, $color2){ 970 return $this->colorBlend( array($this,'colorBlendHardlight'), $color1, $color2 ); 971 } 972 973 private function colorBlendHardlight( $cb, $cs ){ 974 return $this->colorBlendOverlay($cs, $cb); 975 } 976 977 public function difference($color1, $color2) { 978 return $this->colorBlend( array($this,'colorBlendDifference'), $color1, $color2 ); 979 } 980 981 private function colorBlendDifference( $cb, $cs ){ 982 return abs($cb - $cs); 983 } 984 985 public function exclusion( $color1, $color2 ){ 986 return $this->colorBlend( array($this,'colorBlendExclusion'), $color1, $color2 ); 987 } 988 989 private function colorBlendExclusion( $cb, $cs ){ 990 return $cb + $cs - 2 * $cb * $cs; 991 } 992 993 public function average($color1, $color2){ 994 return $this->colorBlend( array($this,'colorBlendAverage'), $color1, $color2 ); 995 } 996 997 // non-w3c functions: 998 function colorBlendAverage($cb, $cs ){ 999 return ($cb + $cs) / 2; 1000 } 1001 1002 public function negation($color1, $color2 ){ 1003 return $this->colorBlend( array($this,'colorBlendNegation'), $color1, $color2 ); 1004 } 1005 1006 function colorBlendNegation($cb, $cs){ 1007 return 1 - abs($cb + $cs - 1); 1008 } 1009 1010 // ~ End of Color Blending 1011 1012 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |