From 9320430f330b8704657be2ce2c097652168f55a4 Mon Sep 17 00:00:00 2001 From: delucis Date: Sat, 1 Jan 2022 19:44:11 +0100 Subject: [PATCH] fix(mix): Fix algorithm directly instead of returning early Correctly handles the edge cases of bug #408. Based on the updated implementation in dart-sass: https://github.com/sass/dart-sass/blob/169178af6c6414d01bc66144b437701057ff3684/lib/src/functions/color.dart#L800-L838 --- src/mix.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/mix.ts b/src/mix.ts index 78c2112..b7a2fe4 100644 --- a/src/mix.ts +++ b/src/mix.ts @@ -5,9 +5,6 @@ import rgba from './rgba'; * Mixes two colors together. Taken from sass's implementation. */ function mix(color1: string, color2: string, weight: number): string { - if (weight <= 0) return rgba(...parseToRgba(color1)); - if (weight >= 1) return rgba(...parseToRgba(color2)); - const normalize = (n: number, index: number) => // 3rd index is alpha channel which is already normalized index === 3 ? n : n / 255; @@ -18,10 +15,12 @@ function mix(color1: string, color2: string, weight: number): string { // The formula is copied from the original Sass implementation: // http://sass-lang.com/documentation/Sass/Script/Functions.html#mix-instance_method const alphaDelta = a2 - a1; - const x = weight * 2 - 1; - const y = x * alphaDelta === -1 ? x : x + alphaDelta; - const z = 1 + x * alphaDelta; - const weight2 = (y / z + 1) / 2.0; + const normalizedWeight = weight * 2 - 1; + const combinedWeight = + normalizedWeight * alphaDelta === -1 + ? normalizedWeight + : normalizedWeight + alphaDelta / (1 + normalizedWeight * alphaDelta); + const weight2 = (combinedWeight + 1) / 2; const weight1 = 1 - weight2; const r = (r1 * weight1 + r2 * weight2) * 255;