Asserts that the value of a literal is within the expected range
/** * Adjusts the colour * @param SassColour the colour to adjust * @param SassNumber the amount to adust by * @param boolean whether the amount is a proportion of the current value or * the total range * @param string the attribute to adjust * @param boolean whether to decrease (false) or increase (true) the value of the attribute * @param float minimum value the amount can be * @param float maximum value the amount can bemixed * @param string amount units */ private static function adjust($colour, $amount, $ofCurrent, $attribute, $op, $min, $max, $units = '') { SassLiteral::assertType($colour, 'SassColour'); SassLiteral::assertType($amount, 'SassNumber'); SassLiteral::assertInRange($amount, $min, $max, $units); if (!is_bool($ofCurrent)) { SassLiteral::assertType($ofCurrent, 'SassBoolean'); $ofCurrent = $ofCurrent->value; } $amount = $amount->value * ($attribute === 'alpha' && $ofCurrent && $units === '' ? 100 : 1); return $colour->with(array($attribute => self::inRange($ofCurrent ? $colour->{$attribute} * (1 + $amount * ($op === self::INCREASE ? 1 : -1) / 100) : $colour->{$attribute} + $amount * ($op === self::INCREASE ? 1 : -1), $min, $max))); }
/** * Mixes two colours together. * Takes the average of each of the RGB components, optionally weighted by the * given percentage. The opacity of the colours is also considered when * weighting the components. * The weight specifies the amount of the first colour that should be included * in the returned colour. The default, 50%, means that half the first colour * and half the second colour should be used. 25% means that a quarter of the * first colour and three quarters of the second colour should be used. * For example: * mix(#f00, #00f) => #7f007f * mix(#f00, #00f, 25%) => #3f00bf * mix(rgba(255, 0, 0, 0.5), #00f) => rgba(63, 0, 191, 0.75) * * @param SassColour The first colour * @param SassColour The second colour * @param float Percentage of the first colour to use * @return new SassColour The mixed colour * @throws SassScriptFunctionException If $colour1 or $colour2 is * not a colour */ public static function mix($colour1, $colour2, $weight = '50%') { if (is_object($weight)) { $weight = new SassNumber($weight); } SassLiteral::assertType($colour1, 'SassColour'); SassLiteral::assertType($colour2, 'SassColour'); SassLiteral::assertType($weight, 'SassNumber'); SassLiteral::assertInRange($weight, 0, 100, '%'); /* * This algorithm factors in both the user-provided weight * and the difference between the alpha values of the two colours * to decide how to perform the weighted average of the two RGB values. * * It works by first normalizing both parameters to be within [-1, 1], * where 1 indicates "only use colour1", -1 indicates "only use colour 0", * and all values in between indicated a proportionately weighted average. * * Once we have the normalized variables w and a, * we apply the formula (w + a)/(1 + w*a) * to get the combined weight (in [-1, 1]) of colour1. * This formula has two especially nice properties: * * * When either w or a are -1 or 1, the combined weight is also that number * (cases where w * a == -1 are undefined, and handled as a special case). * * * When a is 0, the combined weight is w, and vice versa * * Finally, the weight of colour1 is renormalized to be within [0, 1] * and the weight of colour2 is given by 1 minus the weight of colour1. */ $p = $weight->value / 100; $w = $p * 2 - 1; $a = $colour1->alpha - $colour2->alpha; $w1 = (($w * $a == -1 ? $w : ($w + $a) / (1 + $w * $a)) + 1) / 2; $w2 = 1 - $w1; $rgb1 = $colour1->getRgb(); $rgb2 = $colour2->getRgb(); $rgba = array(); foreach ($rgb1 as $key => $value) { $rgba[$key] = floor($value * $w1 + $rgb2[$key] * $w2); } // foreach $rgba[] = floor($colour1->alpha * $p + $colour2->alpha * (1 - $p)); return new SassColour($rgba); }