nsCSSColorUtils.cpp (5384B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* functions that manipulate colors */ 8 9 #include "nsCSSColorUtils.h" 10 11 #include <math.h> 12 13 #include "nsDebug.h" 14 15 // Weird color computing code stolen from winfe which was stolen 16 // from the xfe which was written originally by Eric Bina. So there. 17 18 #define RED_LUMINOSITY 299 19 #define GREEN_LUMINOSITY 587 20 #define BLUE_LUMINOSITY 114 21 #define INTENSITY_FACTOR 25 22 #define LUMINOSITY_FACTOR 75 23 24 void NS_GetSpecial3DColors(nscolor aResult[2], nscolor aBorderColor) { 25 const float kDarkerScale = 2.0f / 3.0f; 26 27 uint8_t r = NS_GET_R(aBorderColor); 28 uint8_t g = NS_GET_G(aBorderColor); 29 uint8_t b = NS_GET_B(aBorderColor); 30 uint8_t a = NS_GET_A(aBorderColor); 31 if (r == 0 && g == 0 && b == 0) { 32 // 0.3 * black 33 aResult[0] = NS_RGBA(76, 76, 76, a); 34 // 0.7 * black 35 aResult[1] = NS_RGBA(178, 178, 178, a); 36 return; 37 } 38 39 aResult[0] = NS_RGBA(uint8_t(r * kDarkerScale), uint8_t(g * kDarkerScale), 40 uint8_t(b * kDarkerScale), a); 41 aResult[1] = aBorderColor; 42 } 43 44 int NS_GetBrightness(uint8_t aRed, uint8_t aGreen, uint8_t aBlue) { 45 uint8_t intensity = (aRed + aGreen + aBlue) / 3; 46 47 uint8_t luminosity = NS_GetLuminosity(NS_RGB(aRed, aGreen, aBlue)) / 1000; 48 49 return ((intensity * INTENSITY_FACTOR) + (luminosity * LUMINOSITY_FACTOR)) / 50 100; 51 } 52 53 int32_t NS_GetLuminosity(nscolor aColor) { 54 // When aColor is not opaque, the perceived luminosity will depend 55 // on what color(s) aColor is ultimately drawn on top of, which we 56 // do not know. 57 NS_ASSERTION(NS_GET_A(aColor) == 255, 58 "impossible to compute luminosity of a non-opaque color"); 59 60 return (NS_GET_R(aColor) * RED_LUMINOSITY + 61 NS_GET_G(aColor) * GREEN_LUMINOSITY + 62 NS_GET_B(aColor) * BLUE_LUMINOSITY); 63 } 64 65 // Function to convert RGB color space into the HSV colorspace 66 // Hue is the primary color defined from 0 to 359 degrees 67 // Saturation is defined from 0 to 255. The higher the number.. the deeper 68 // the color Value is the brightness of the color. 0 is black, 255 is white. 69 void NS_RGB2HSV(nscolor aColor, uint16_t& aHue, uint16_t& aSat, 70 uint16_t& aValue, uint8_t& aAlpha) { 71 uint8_t r, g, b; 72 int16_t delta, min, max, r1, b1, g1; 73 float hue; 74 75 r = NS_GET_R(aColor); 76 g = NS_GET_G(aColor); 77 b = NS_GET_B(aColor); 78 79 if (r > g) { 80 max = r; 81 min = g; 82 } else { 83 max = g; 84 min = r; 85 } 86 87 if (b > max) { 88 max = b; 89 } 90 if (b < min) { 91 min = b; 92 } 93 94 // value or brightness will always be the max of all the colors(RGB) 95 aValue = max; 96 delta = max - min; 97 aSat = (max != 0) ? ((delta * 255) / max) : 0; 98 r1 = r; 99 b1 = b; 100 g1 = g; 101 102 if (aSat == 0) { 103 hue = 1000; 104 } else { 105 if (r == max) { 106 hue = (float)(g1 - b1) / (float)delta; 107 } else if (g1 == max) { 108 hue = 2.0f + (float)(b1 - r1) / (float)delta; 109 } else { 110 hue = 4.0f + (float)(r1 - g1) / (float)delta; 111 } 112 } 113 114 if (hue < 999) { 115 hue *= 60; 116 if (hue < 0) { 117 hue += 360; 118 } 119 } else { 120 hue = 0; 121 } 122 123 aHue = (uint16_t)hue; 124 125 aAlpha = NS_GET_A(aColor); 126 } 127 128 // Function to convert HSV color space into the RGB colorspace 129 // Hue is the primary color defined from 0 to 359 degrees 130 // Saturation is defined from 0 to 255. The higher the number.. the deeper 131 // the color Value is the brightness of the color. 0 is black, 255 is white. 132 void NS_HSV2RGB(nscolor& aColor, uint16_t aHue, uint16_t aSat, uint16_t aValue, 133 uint8_t aAlpha) { 134 uint16_t r = 0, g = 0, b = 0; 135 uint16_t i, p, q, t; 136 double h, f, percent; 137 138 if (aSat == 0) { 139 // achromatic color, no hue is defined 140 r = aValue; 141 g = aValue; 142 b = aValue; 143 } else { 144 // hue in in degrees around the color wheel defined from 145 // 0 to 360 degrees. 146 if (aHue >= 360) { 147 aHue = 0; 148 } 149 150 // we break the color wheel into 6 areas.. these 151 // areas define how the saturation and value define the color. 152 // reds behave differently than the blues 153 h = (double)aHue / 60.0; 154 i = (uint16_t)floor(h); 155 f = h - (double)i; 156 percent = ((double)aValue / 157 255.0); // this needs to be a value from 0 to 1, so a percentage 158 // can be calculated of the saturation. 159 p = (uint16_t)(percent * (255 - aSat)); 160 q = (uint16_t)(percent * (255 - (aSat * f))); 161 t = (uint16_t)(percent * (255 - (aSat * (1.0 - f)))); 162 163 // i is guaranteed to never be larger than 5. 164 switch (i) { 165 case 0: 166 r = aValue; 167 g = t; 168 b = p; 169 break; 170 case 1: 171 r = q; 172 g = aValue; 173 b = p; 174 break; 175 case 2: 176 r = p; 177 g = aValue; 178 b = t; 179 break; 180 case 3: 181 r = p; 182 g = q; 183 b = aValue; 184 break; 185 case 4: 186 r = t; 187 g = p; 188 b = aValue; 189 break; 190 case 5: 191 r = aValue; 192 g = p; 193 b = q; 194 break; 195 } 196 } 197 aColor = NS_RGBA(r, g, b, aAlpha); 198 } 199 200 #undef RED_LUMINOSITY 201 #undef GREEN_LUMINOSITY 202 #undef BLUE_LUMINOSITY 203 #undef INTENSITY_FACTOR 204 #undef LUMINOSITY_FACTOR