function _color_shift

Same name in other branches
  1. 7.x modules/color/color.module \_color_shift()
  2. 9 core/modules/color/color.module \_color_shift()

Shifts a given color, using a reference pair and a target blend color.

Note: this function is significantly different from the JS version, as it is written to match the blended images perfectly.

Constraint: if (ref2 == target + (ref1 - target) * delta) for some fraction delta then (return == target + (given - target) * delta).

Loose constraint: Preserve relative positions in saturation and luminance space.

1 call to _color_shift()
_color_rewrite_stylesheet in core/modules/color/color.module
Rewrites the stylesheet to match the colors in the palette.

File

core/modules/color/color.module, line 694

Code

function _color_shift($given, $ref1, $ref2, $target) {
    // We assume that ref2 is a blend of ref1 and target and find
    // delta based on the length of the difference vectors.
    // delta = 1 - |ref2 - ref1| / |white - ref1|
    $target = _color_unpack($target, TRUE);
    $ref1 = _color_unpack($ref1, TRUE);
    $ref2 = _color_unpack($ref2, TRUE);
    $numerator = 0;
    $denominator = 0;
    for ($i = 0; $i < 3; ++$i) {
        $numerator += ($ref2[$i] - $ref1[$i]) * ($ref2[$i] - $ref1[$i]);
        $denominator += ($target[$i] - $ref1[$i]) * ($target[$i] - $ref1[$i]);
    }
    $delta = $denominator > 0 ? 1 - sqrt($numerator / $denominator) : 0;
    // Calculate the color that ref2 would be if the assumption was true.
    for ($i = 0; $i < 3; ++$i) {
        $ref3[$i] = $target[$i] + ($ref1[$i] - $target[$i]) * $delta;
    }
    // If the assumption is not true, there is a difference between ref2 and ref3.
    // We measure this in HSL space. Notation: x' = hsl(x).
    $ref2 = _color_rgb2hsl($ref2);
    $ref3 = _color_rgb2hsl($ref3);
    for ($i = 0; $i < 3; ++$i) {
        $shift[$i] = $ref2[$i] - $ref3[$i];
    }
    // Take the given color, and blend it towards the target.
    $given = _color_unpack($given, TRUE);
    for ($i = 0; $i < 3; ++$i) {
        $result[$i] = $target[$i] + ($given[$i] - $target[$i]) * $delta;
    }
    // Finally, we apply the extra shift in HSL space.
    // Note: if ref2 is a pure blend of ref1 and target, then |shift| = 0.
    $result = _color_rgb2hsl($result);
    for ($i = 0; $i < 3; ++$i) {
        $result[$i] = min(1, max(0, $result[$i] + $shift[$i]));
    }
    $result = _color_hsl2rgb($result);
    // Return hex color.
    return _color_pack($result, TRUE);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.