2017-10-27 20:33:53 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2002-09-05 22:18:40 +04:00
|
|
|
|
2006-03-30 09:56:38 +04:00
|
|
|
/* functions that manipulate colors */
|
|
|
|
|
2002-09-05 22:18:40 +04:00
|
|
|
#include "nsCSSColorUtils.h"
|
2008-09-19 21:06:46 +04:00
|
|
|
#include "nsDebug.h"
|
2002-09-05 22:18:40 +04:00
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
// Weird color computing code stolen from winfe which was stolen
|
|
|
|
// from the xfe which was written originally by Eric Bina. So there.
|
|
|
|
|
2005-04-04 14:40:48 +04:00
|
|
|
#define RED_LUMINOSITY 299
|
|
|
|
#define GREEN_LUMINOSITY 587
|
|
|
|
#define BLUE_LUMINOSITY 114
|
2002-09-05 22:18:40 +04:00
|
|
|
#define INTENSITY_FACTOR 25
|
|
|
|
#define LUMINOSITY_FACTOR 75
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2018-09-22 08:18:34 +03:00
|
|
|
void NS_GetSpecial3DColors(nscolor aResult[2], nscolor aBorderColor) {
|
2018-09-27 13:43:42 +03:00
|
|
|
const float kDarkerScale = 2.0f / 3.0f;
|
2002-09-05 22:18:40 +04:00
|
|
|
|
2018-09-22 08:18:34 +03:00
|
|
|
uint8_t r = NS_GET_R(aBorderColor);
|
|
|
|
uint8_t g = NS_GET_G(aBorderColor);
|
|
|
|
uint8_t b = NS_GET_B(aBorderColor);
|
2012-08-22 19:56:38 +04:00
|
|
|
uint8_t a = NS_GET_A(aBorderColor);
|
2018-09-22 08:18:34 +03:00
|
|
|
if (r == 0 && g == 0 && b == 0) {
|
|
|
|
// 0.3 * black
|
|
|
|
aResult[0] = NS_RGBA(76, 76, 76, a);
|
|
|
|
// 0.7 * black
|
|
|
|
aResult[1] = NS_RGBA(178, 178, 178, a);
|
|
|
|
return;
|
2002-09-05 22:18:40 +04:00
|
|
|
}
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2018-09-22 08:18:34 +03:00
|
|
|
aResult[0] = NS_RGBA(uint8_t(r * kDarkerScale), uint8_t(g * kDarkerScale),
|
|
|
|
uint8_t(b * kDarkerScale), a);
|
|
|
|
aResult[1] = aBorderColor;
|
2002-09-05 22:18:40 +04:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int NS_GetBrightness(uint8_t aRed, uint8_t aGreen, uint8_t aBlue) {
|
|
|
|
uint8_t intensity = (aRed + aGreen + aBlue) / 3;
|
2002-09-05 22:18:40 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint8_t luminosity = NS_GetLuminosity(NS_RGB(aRed, aGreen, aBlue)) / 1000;
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2002-09-05 22:18:40 +04:00
|
|
|
return ((intensity * INTENSITY_FACTOR) + (luminosity * LUMINOSITY_FACTOR)) /
|
|
|
|
100;
|
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t NS_GetLuminosity(nscolor aColor) {
|
2008-09-19 21:06:46 +04:00
|
|
|
// When aColor is not opaque, the perceived luminosity will depend
|
|
|
|
// on what color(s) aColor is ultimately drawn on top of, which we
|
|
|
|
// do not know.
|
|
|
|
NS_ASSERTION(NS_GET_A(aColor) == 255,
|
|
|
|
"impossible to compute luminosity of a non-opaque color");
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2005-04-04 14:40:48 +04:00
|
|
|
return (NS_GET_R(aColor) * RED_LUMINOSITY +
|
|
|
|
NS_GET_G(aColor) * GREEN_LUMINOSITY +
|
|
|
|
NS_GET_B(aColor) * BLUE_LUMINOSITY);
|
|
|
|
}
|
|
|
|
|
2002-09-05 22:18:40 +04:00
|
|
|
// Function to convert RGB color space into the HSV colorspace
|
|
|
|
// Hue is the primary color defined from 0 to 359 degrees
|
2008-10-28 05:05:38 +03:00
|
|
|
// Saturation is defined from 0 to 255. The higher the number.. the deeper
|
|
|
|
// the color Value is the brightness of the color. 0 is black, 255 is white.
|
2019-05-01 11:47:10 +03:00
|
|
|
void NS_RGB2HSV(nscolor aColor, uint16_t& aHue, uint16_t& aSat,
|
|
|
|
uint16_t& aValue, uint8_t& aAlpha) {
|
2012-08-22 19:56:38 +04:00
|
|
|
uint8_t r, g, b;
|
|
|
|
int16_t delta, min, max, r1, b1, g1;
|
2008-10-28 05:05:38 +03:00
|
|
|
float hue;
|
2002-09-05 22:18:40 +04:00
|
|
|
|
|
|
|
r = NS_GET_R(aColor);
|
|
|
|
g = NS_GET_G(aColor);
|
|
|
|
b = NS_GET_B(aColor);
|
|
|
|
|
|
|
|
if (r > g) {
|
|
|
|
max = r;
|
|
|
|
min = g;
|
|
|
|
} else {
|
|
|
|
max = g;
|
|
|
|
min = r;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b > max) {
|
|
|
|
max = b;
|
|
|
|
}
|
|
|
|
if (b < min) {
|
|
|
|
min = b;
|
|
|
|
}
|
|
|
|
|
|
|
|
// value or brightness will always be the max of all the colors(RGB)
|
2017-07-06 15:00:35 +03:00
|
|
|
aValue = max;
|
2002-09-05 22:18:40 +04:00
|
|
|
delta = max - min;
|
|
|
|
aSat = (max != 0) ? ((delta * 255) / max) : 0;
|
|
|
|
r1 = r;
|
|
|
|
b1 = b;
|
|
|
|
g1 = g;
|
|
|
|
|
|
|
|
if (aSat == 0) {
|
|
|
|
hue = 1000;
|
|
|
|
} else {
|
|
|
|
if (r == max) {
|
|
|
|
hue = (float)(g1 - b1) / (float)delta;
|
|
|
|
} else if (g1 == max) {
|
|
|
|
hue = 2.0f + (float)(b1 - r1) / (float)delta;
|
2017-07-06 15:00:35 +03:00
|
|
|
} else {
|
2002-09-05 22:18:40 +04:00
|
|
|
hue = 4.0f + (float)(r1 - g1) / (float)delta;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hue < 999) {
|
|
|
|
hue *= 60;
|
|
|
|
if (hue < 0) {
|
|
|
|
hue += 360;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
hue = 0;
|
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
aHue = (uint16_t)hue;
|
2008-10-28 05:05:38 +03:00
|
|
|
|
|
|
|
aAlpha = NS_GET_A(aColor);
|
2002-09-05 22:18:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Function to convert HSV color space into the RGB colorspace
|
|
|
|
// Hue is the primary color defined from 0 to 359 degrees
|
2008-10-28 05:05:38 +03:00
|
|
|
// Saturation is defined from 0 to 255. The higher the number.. the deeper
|
|
|
|
// the color Value is the brightness of the color. 0 is black, 255 is white.
|
2019-05-01 11:47:10 +03:00
|
|
|
void NS_HSV2RGB(nscolor& aColor, uint16_t aHue, uint16_t aSat, uint16_t aValue,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint8_t aAlpha) {
|
|
|
|
uint16_t r = 0, g = 0, b = 0;
|
|
|
|
uint16_t i, p, q, t;
|
2008-10-28 05:05:38 +03:00
|
|
|
double h, f, percent;
|
2002-09-05 22:18:40 +04:00
|
|
|
|
|
|
|
if (aSat == 0) {
|
|
|
|
// achromatic color, no hue is defined
|
|
|
|
r = aValue;
|
|
|
|
g = aValue;
|
|
|
|
b = aValue;
|
|
|
|
} else {
|
|
|
|
// hue in in degrees around the color wheel defined from
|
2017-07-06 15:00:35 +03:00
|
|
|
// 0 to 360 degrees.
|
2002-09-05 22:18:40 +04:00
|
|
|
if (aHue >= 360) {
|
|
|
|
aHue = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// we break the color wheel into 6 areas.. these
|
|
|
|
// areas define how the saturation and value define the color.
|
|
|
|
// reds behave differently than the blues
|
|
|
|
h = (double)aHue / 60.0;
|
2012-08-22 19:56:38 +04:00
|
|
|
i = (uint16_t)floor(h);
|
2002-09-05 22:18:40 +04:00
|
|
|
f = h - (double)i;
|
|
|
|
percent = ((double)aValue /
|
|
|
|
255.0); // this needs to be a value from 0 to 1, so a percentage
|
|
|
|
// can be calculated of the saturation.
|
2012-08-22 19:56:38 +04:00
|
|
|
p = (uint16_t)(percent * (255 - aSat));
|
|
|
|
q = (uint16_t)(percent * (255 - (aSat * f)));
|
|
|
|
t = (uint16_t)(percent * (255 - (aSat * (1.0 - f))));
|
2002-09-05 22:18:40 +04:00
|
|
|
|
2005-11-21 01:05:24 +03:00
|
|
|
// i is guaranteed to never be larger than 5.
|
2002-09-05 22:18:40 +04:00
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
r = aValue;
|
|
|
|
g = t;
|
|
|
|
b = p;
|
|
|
|
break;
|
2018-11-30 13:46:48 +03:00
|
|
|
case 1:
|
|
|
|
r = q;
|
2002-09-05 22:18:40 +04:00
|
|
|
g = aValue;
|
|
|
|
b = p;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
r = p;
|
|
|
|
g = aValue;
|
|
|
|
b = t;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
r = p;
|
|
|
|
g = q;
|
|
|
|
b = aValue;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
r = t;
|
|
|
|
g = p;
|
|
|
|
b = aValue;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
r = aValue;
|
|
|
|
g = p;
|
|
|
|
b = q;
|
2018-11-30 13:46:48 +03:00
|
|
|
break;
|
2002-09-05 22:18:40 +04:00
|
|
|
}
|
|
|
|
}
|
2008-10-28 05:05:38 +03:00
|
|
|
aColor = NS_RGBA(r, g, b, aAlpha);
|
2002-09-05 22:18:40 +04:00
|
|
|
}
|
2013-12-03 05:56:50 +04:00
|
|
|
|
|
|
|
#undef RED_LUMINOSITY
|
|
|
|
#undef GREEN_LUMINOSITY
|
|
|
|
#undef BLUE_LUMINOSITY
|
|
|
|
#undef INTENSITY_FACTOR
|
|
|
|
#undef LUMINOSITY_FACTOR
|