123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- <?php
- /**
- * Dimension
- *
- * @package Less
- * @subpackage tree
- */
- class Less_Tree_Dimension extends Less_Tree {
- public $value;
- public $unit;
- public $type = 'Dimension';
- public function __construct( $value, $unit = null ) {
- $this->value = floatval( $value );
- if ( $unit && ( $unit instanceof Less_Tree_Unit ) ) {
- $this->unit = $unit;
- } elseif ( $unit ) {
- $this->unit = new Less_Tree_Unit( array( $unit ) );
- } else {
- $this->unit = new Less_Tree_Unit();
- }
- }
- public function accept( $visitor ) {
- $this->unit = $visitor->visitObj( $this->unit );
- }
- public function compile() {
- return $this;
- }
- public function toColor() {
- return new Less_Tree_Color( array( $this->value, $this->value, $this->value ) );
- }
- /**
- * @see Less_Tree::genCSS
- */
- public function genCSS( $output ) {
- if ( Less_Parser::$options['strictUnits'] && !$this->unit->isSingular() ) {
- throw new Less_Exception_Compiler( "Multiple units in dimension. Correct the units or use the unit function. Bad unit: ".$this->unit->toString() );
- }
- $value = Less_Functions::fround( $this->value );
- $strValue = (string)$value;
- if ( $value !== 0 && $value < 0.000001 && $value > -0.000001 ) {
- // would be output 1e-6 etc.
- $strValue = number_format( $strValue, 10 );
- $strValue = preg_replace( '/\.?0+$/', '', $strValue );
- }
- if ( Less_Parser::$options['compress'] ) {
- // Zero values doesn't need a unit
- if ( $value === 0 && $this->unit->isLength() ) {
- $output->add( $strValue );
- return $strValue;
- }
- // Float values doesn't need a leading zero
- if ( $value > 0 && $value < 1 && $strValue[0] === '0' ) {
- $strValue = substr( $strValue, 1 );
- }
- }
- $output->add( $strValue );
- $this->unit->genCSS( $output );
- }
- public function __toString() {
- return $this->toCSS();
- }
- // In an operation between two Dimensions,
- // we default to the first Dimension's unit,
- // so `1px + 2em` will yield `3px`.
- /**
- * @param string $op
- */
- public function operate( $op, $other ) {
- $value = Less_Functions::operate( $op, $this->value, $other->value );
- $unit = clone $this->unit;
- if ( $op === '+' || $op === '-' ) {
- if ( !$unit->numerator && !$unit->denominator ) {
- $unit->numerator = $other->unit->numerator;
- $unit->denominator = $other->unit->denominator;
- } elseif ( !$other->unit->numerator && !$other->unit->denominator ) {
- // do nothing
- } else {
- $other = $other->convertTo( $this->unit->usedUnits() );
- if ( Less_Parser::$options['strictUnits'] && $other->unit->toString() !== $unit->toCSS() ) {
- throw new Less_Exception_Compiler( "Incompatible units. Change the units or use the unit function. Bad units: '" . $unit->toString() . "' and " . $other->unit->toString() . "'." );
- }
- $value = Less_Functions::operate( $op, $this->value, $other->value );
- }
- } elseif ( $op === '*' ) {
- $unit->numerator = array_merge( $unit->numerator, $other->unit->numerator );
- $unit->denominator = array_merge( $unit->denominator, $other->unit->denominator );
- sort( $unit->numerator );
- sort( $unit->denominator );
- $unit->cancel();
- } elseif ( $op === '/' ) {
- $unit->numerator = array_merge( $unit->numerator, $other->unit->denominator );
- $unit->denominator = array_merge( $unit->denominator, $other->unit->numerator );
- sort( $unit->numerator );
- sort( $unit->denominator );
- $unit->cancel();
- }
- return new Less_Tree_Dimension( $value, $unit );
- }
- public function compare( $other ) {
- if ( $other instanceof Less_Tree_Dimension ) {
- if ( $this->unit->isEmpty() || $other->unit->isEmpty() ) {
- $a = $this;
- $b = $other;
- } else {
- $a = $this->unify();
- $b = $other->unify();
- if ( $a->unit->compare( $b->unit ) !== 0 ) {
- return -1;
- }
- }
- $aValue = $a->value;
- $bValue = $b->value;
- if ( $bValue > $aValue ) {
- return -1;
- } elseif ( $bValue < $aValue ) {
- return 1;
- } else {
- return 0;
- }
- } else {
- return -1;
- }
- }
- public function unify() {
- return $this->convertTo( array( 'length' => 'px', 'duration' => 's', 'angle' => 'rad' ) );
- }
- public function convertTo( $conversions ) {
- $value = $this->value;
- $unit = clone $this->unit;
- if ( is_string( $conversions ) ) {
- $derivedConversions = array();
- foreach ( Less_Tree_UnitConversions::$groups as $i ) {
- if ( isset( Less_Tree_UnitConversions::${$i}[$conversions] ) ) {
- $derivedConversions = array( $i => $conversions );
- }
- }
- $conversions = $derivedConversions;
- }
- foreach ( $conversions as $groupName => $targetUnit ) {
- $group = Less_Tree_UnitConversions::${$groupName};
- // numerator
- foreach ( $unit->numerator as $i => $atomicUnit ) {
- $atomicUnit = $unit->numerator[$i];
- if ( !isset( $group[$atomicUnit] ) ) {
- continue;
- }
- $value = $value * ( $group[$atomicUnit] / $group[$targetUnit] );
- $unit->numerator[$i] = $targetUnit;
- }
- // denominator
- foreach ( $unit->denominator as $i => $atomicUnit ) {
- $atomicUnit = $unit->denominator[$i];
- if ( !isset( $group[$atomicUnit] ) ) {
- continue;
- }
- $value = $value / ( $group[$atomicUnit] / $group[$targetUnit] );
- $unit->denominator[$i] = $targetUnit;
- }
- }
- $unit->cancel();
- return new Less_Tree_Dimension( $value, $unit );
- }
- }
|