1/////////////////////////////////////////////////////////////////
2// Color contrasting (backported to BS4 from BS5)
3// See https://github.com/twbs/bootstrap/pull/30168
4/////////////////////////////////////////////////////////////////
5
6// A list of pre-calculated numbers of pow(divide((divide($value, 255) + .055), 1.055), 2.4). (from 0 to 255)
7// stylelint-disable-next-line scss/dollar-variable-default, scss/dollar-variable-pattern
8$_luminance-list: .0008 .001 .0011 .0013 .0015 .0017 .002 .0022 .0025 .0027 .003 .0033 .0037 .004 .0044 .0048 .0052 .0056 .006 .0065 .007 .0075 .008 .0086 .0091 .0097 .0103 .011 .0116 .0123 .013 .0137 .0144 .0152 .016 .0168 .0176 .0185 .0194 .0203 .0212 .0222 .0232 .0242 .0252 .0262 .0273 .0284 .0296 .0307 .0319 .0331 .0343 .0356 .0369 .0382 .0395 .0409 .0423 .0437 .0452 .0467 .0482 .0497 .0513 .0529 .0545 .0561 .0578 .0595 .0612 .063 .0648 .0666 .0685 .0704 .0723 .0742 .0762 .0782 .0802 .0823 .0844 .0865 .0887 .0908 .0931 .0953 .0976 .0999 .1022 .1046 .107 .1095 .1119 .1144 .117 .1195 .1221 .1248 .1274 .1301 .1329 .1356 .1384 .1413 .1441 .147 .15 .1529 .1559 .159 .162 .1651 .1683 .1714 .1746 .1779 .1812 .1845 .1878 .1912 .1946 .1981 .2016 .2051 .2086 .2122 .2159 .2195 .2232 .227 .2307 .2346 .2384 .2423 .2462 .2502 .2542 .2582 .2623 .2664 .2705 .2747 .2789 .2831 .2874 .2918 .2961 .3005 .305 .3095 .314 .3185 .3231 .3278 .3325 .3372 .3419 .3467 .3515 .3564 .3613 .3663 .3712 .3763 .3813 .3864 .3916 .3968 .402 .4072 .4125 .4179 .4233 .4287 .4342 .4397 .4452 .4508 .4564 .4621 .4678 .4735 .4793 .4851 .491 .4969 .5029 .5089 .5149 .521 .5271 .5333 .5395 .5457 .552 .5583 .5647 .5711 .5776 .5841 .5906 .5972 .6038 .6105 .6172 .624 .6308 .6376 .6445 .6514 .6584 .6654 .6724 .6795 .6867 .6939 .7011 .7084 .7157 .7231 .7305 .7379 .7454 .7529 .7605 .7682 .7758 .7835 .7913 .7991 .807 .8148 .8228 .8308 .8388 .8469 .855 .8632 .8714 .8796 .8879 .8963 .9047 .9131 .9216 .9301 .9387 .9473 .956 .9647 .9734 .9823 .9911 1;
9
10@function color-contrast($background, $foregrounds: null) {
11
12  // These variables should be defined in _variables.scss, but we also
13  // define them here so that 3rd party libs can use if they want
14  // without polluting the global namespace
15  $black: #000 !default;
16  $white: #fff !default;
17  $color-contrast-dark: $black !default;
18  $color-contrast-light: $white !default;
19  $min-contrast-ratio: 3 !default;
20
21  @if $foregrounds == null {
22    $foregrounds: $color-contrast-light, $color-contrast-dark, $white, $black;
23  } @else {
24    $foregrounds: $foregrounds, $color-contrast-light, $color-contrast-dark, $white, $black;
25  }
26
27  $max-ratio: 0;
28  $max-ratio-color: null;
29
30  @each $color in $foregrounds {
31    $contrast-ratio: contrast-ratio($background, $color);
32    @if $contrast-ratio > $min-contrast-ratio {
33      @return $color;
34    } @else if $contrast-ratio > $max-ratio {
35      $max-ratio: $contrast-ratio;
36      $max-ratio-color: $color;
37    }
38  }
39
40  $color-contrast-warnings: false !default;
41  @if $color-contrast-warnings {
42    @warn "Found no color leading to #{$min-contrast-ratio}:1 contrast ratio against #{$background}...";
43  }
44
45  @return $max-ratio-color;
46}
47
48@function contrast-ratio($background, $foreground: $color-contrast-light) {
49  $l1: luminance($background);
50  $l2: luminance(opaque($background, $foreground));
51
52  @return if($l1 > $l2, divide($l1 + .05, $l2 + .05), divide($l2 + .05, $l1 + .05));
53}
54
55// Return WCAG2.0 relative luminance
56// See https://www.w3.org/WAI/GL/wiki/Relative_luminance
57// See https://www.w3.org/TR/WCAG20-TECHS/G17.html#G17-tests
58@function luminance($color) {
59  $rgb: (
60    "r": red($color),
61    "g": green($color),
62    "b": blue($color)
63  );
64
65  @each $name, $value in $rgb {
66    $value: if(divide($value, 255) < .03928, divide(divide($value, 255), 12.92), nth($_luminance-list, $value + 1));
67    $rgb: map-merge($rgb, ($name: $value));
68  }
69
70  @return (map-get($rgb, "r") * .2126) + (map-get($rgb, "g") * .7152) + (map-get($rgb, "b") * .0722);
71}
72
73// Return opaque color
74// opaque(#fff, rgba(0, 0, 0, .5)) => #808080
75@function opaque($background, $foreground) {
76  @return mix(rgba($foreground, 1), $background, opacity($foreground) * 100);
77}
78
79// Added in BS5 as an alternative to the \ operator, which
80// throws warnings in Dart Sass
81// https://github.com/twbs/bootstrap/pull/34245
82@function divide($dividend, $divisor, $precision: 10) {
83  $sign: if($dividend > 0 and $divisor > 0 or $dividend < 0 and $divisor < 0, 1, -1);
84  $dividend: abs($dividend);
85  $divisor: abs($divisor);
86  @if $dividend == 0 {
87    @return 0;
88  }
89  @if $divisor == 0 {
90    @error "Cannot divide by 0";
91  }
92  $remainder: $dividend;
93  $result: 0;
94  $factor: 10;
95  @while ($remainder > 0 and $precision >= 0) {
96    $quotient: 0;
97    @while ($remainder >= $divisor) {
98      $remainder: $remainder - $divisor;
99      $quotient: $quotient + 1;
100    }
101    $result: $result * 10 + $quotient;
102    $factor: $factor * .1;
103    $remainder: $remainder * 10;
104    $precision: $precision - 1;
105    @if ($precision < 0 and $remainder >= $divisor * 5) {
106      $result: $result + 1;
107    }
108  }
109  $result: $result * $factor * $sign;
110  $dividend-unit: unit($dividend);
111  $divisor-unit: unit($divisor);
112  $unit-map: (
113    "px": 1px,
114    "rem": 1rem,
115    "em": 1em,
116    "%": 1%
117  );
118  @if ($dividend-unit != $divisor-unit and map-has-key($unit-map, $dividend-unit)) {
119    $result: $result * map-get($unit-map, $dividend-unit);
120  }
121  @return $result;
122}
123
124