michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* functions that manipulate colors */ michael@0: michael@0: #include "nsCSSColorUtils.h" michael@0: #include "nsDebug.h" michael@0: #include michael@0: michael@0: // Weird color computing code stolen from winfe which was stolen michael@0: // from the xfe which was written originally by Eric Bina. So there. michael@0: michael@0: #define RED_LUMINOSITY 299 michael@0: #define GREEN_LUMINOSITY 587 michael@0: #define BLUE_LUMINOSITY 114 michael@0: #define INTENSITY_FACTOR 25 michael@0: #define LUMINOSITY_FACTOR 75 michael@0: michael@0: #define MAX_COLOR 255 michael@0: #define COLOR_DARK_THRESHOLD 51 michael@0: #define COLOR_LIGHT_THRESHOLD 204 michael@0: michael@0: #define COLOR_LITE_BS_FACTOR 45 michael@0: #define COLOR_LITE_TS_FACTOR 70 michael@0: michael@0: #define COLOR_DARK_BS_FACTOR 30 michael@0: #define COLOR_DARK_TS_FACTOR 50 michael@0: michael@0: #define LIGHT_GRAY NS_RGB(192, 192, 192) michael@0: #define DARK_GRAY NS_RGB(96, 96, 96) michael@0: michael@0: #define MAX_BRIGHTNESS 254 michael@0: #define MAX_DARKNESS 0 michael@0: michael@0: void NS_GetSpecial3DColors(nscolor aResult[2], michael@0: nscolor aBackgroundColor, michael@0: nscolor aBorderColor) michael@0: { michael@0: michael@0: uint8_t f0, f1; michael@0: uint8_t r, g, b; michael@0: michael@0: uint8_t rb = NS_GET_R(aBorderColor); michael@0: uint8_t gb = NS_GET_G(aBorderColor); michael@0: uint8_t bb = NS_GET_B(aBorderColor); michael@0: michael@0: uint8_t a = NS_GET_A(aBorderColor); michael@0: michael@0: // This needs to be optimized. michael@0: // Calculating background brightness again and again is michael@0: // a waste of time!!!. Just calculate it only once. michael@0: // .....somehow!!! michael@0: michael@0: uint8_t red = NS_GET_R(aBackgroundColor); michael@0: uint8_t green = NS_GET_G(aBackgroundColor); michael@0: uint8_t blue = NS_GET_B(aBackgroundColor); michael@0: michael@0: uint8_t elementBrightness = NS_GetBrightness(rb,gb,bb); michael@0: uint8_t backgroundBrightness = NS_GetBrightness(red, green, blue); michael@0: michael@0: michael@0: if (backgroundBrightness < COLOR_DARK_THRESHOLD) { michael@0: f0 = COLOR_DARK_BS_FACTOR; michael@0: f1 = COLOR_DARK_TS_FACTOR; michael@0: if(elementBrightness == MAX_DARKNESS) michael@0: { michael@0: rb = NS_GET_R(DARK_GRAY); michael@0: gb = NS_GET_G(DARK_GRAY); michael@0: bb = NS_GET_B(DARK_GRAY); michael@0: } michael@0: }else if (backgroundBrightness > COLOR_LIGHT_THRESHOLD) { michael@0: f0 = COLOR_LITE_BS_FACTOR; michael@0: f1 = COLOR_LITE_TS_FACTOR; michael@0: if(elementBrightness == MAX_BRIGHTNESS) michael@0: { michael@0: rb = NS_GET_R(LIGHT_GRAY); michael@0: gb = NS_GET_G(LIGHT_GRAY); michael@0: bb = NS_GET_B(LIGHT_GRAY); michael@0: } michael@0: }else { michael@0: f0 = COLOR_DARK_BS_FACTOR + michael@0: (backgroundBrightness * michael@0: (COLOR_LITE_BS_FACTOR - COLOR_DARK_BS_FACTOR) / MAX_COLOR); michael@0: f1 = COLOR_DARK_TS_FACTOR + michael@0: (backgroundBrightness * michael@0: (COLOR_LITE_TS_FACTOR - COLOR_DARK_TS_FACTOR) / MAX_COLOR); michael@0: } michael@0: michael@0: michael@0: r = rb - (f0 * rb / 100); michael@0: g = gb - (f0 * gb / 100); michael@0: b = bb - (f0 * bb / 100); michael@0: aResult[0] = NS_RGBA(r, g, b, a); michael@0: michael@0: r = rb + (f1 * (MAX_COLOR - rb) / 100); michael@0: g = gb + (f1 * (MAX_COLOR - gb) / 100); michael@0: b = bb + (f1 * (MAX_COLOR - bb) / 100); michael@0: aResult[1] = NS_RGBA(r, g, b, a); michael@0: } michael@0: michael@0: int NS_GetBrightness(uint8_t aRed, uint8_t aGreen, uint8_t aBlue) michael@0: { michael@0: michael@0: uint8_t intensity = (aRed + aGreen + aBlue) / 3; michael@0: michael@0: uint8_t luminosity = NS_GetLuminosity(NS_RGB(aRed, aGreen, aBlue)) / 1000; michael@0: michael@0: return ((intensity * INTENSITY_FACTOR) + michael@0: (luminosity * LUMINOSITY_FACTOR)) / 100; michael@0: } michael@0: michael@0: int32_t NS_GetLuminosity(nscolor aColor) michael@0: { michael@0: // When aColor is not opaque, the perceived luminosity will depend michael@0: // on what color(s) aColor is ultimately drawn on top of, which we michael@0: // do not know. michael@0: NS_ASSERTION(NS_GET_A(aColor) == 255, michael@0: "impossible to compute luminosity of a non-opaque color"); michael@0: michael@0: return (NS_GET_R(aColor) * RED_LUMINOSITY + michael@0: NS_GET_G(aColor) * GREEN_LUMINOSITY + michael@0: NS_GET_B(aColor) * BLUE_LUMINOSITY); michael@0: } michael@0: michael@0: // Function to convert RGB color space into the HSV colorspace michael@0: // Hue is the primary color defined from 0 to 359 degrees michael@0: // Saturation is defined from 0 to 255. The higher the number.. the deeper michael@0: // the color Value is the brightness of the color. 0 is black, 255 is white. michael@0: void NS_RGB2HSV(nscolor aColor, uint16_t &aHue, uint16_t &aSat, michael@0: uint16_t &aValue, uint8_t &aAlpha) michael@0: { michael@0: uint8_t r, g, b; michael@0: int16_t delta, min, max, r1, b1, g1; michael@0: float hue; michael@0: michael@0: r = NS_GET_R(aColor); michael@0: g = NS_GET_G(aColor); michael@0: b = NS_GET_B(aColor); michael@0: michael@0: if (r>g) { michael@0: max = r; michael@0: min = g; michael@0: } else { michael@0: max = g; michael@0: min = r; michael@0: } michael@0: michael@0: if (b>max) { michael@0: max = b; michael@0: } michael@0: if (b= 360) { michael@0: aHue = 0; michael@0: } michael@0: michael@0: // we break the color wheel into 6 areas.. these michael@0: // areas define how the saturation and value define the color. michael@0: // reds behave differently than the blues michael@0: h = (double)aHue / 60.0; michael@0: i = (uint16_t) floor(h); michael@0: f = h-(double)i; michael@0: percent = ((double)aValue/255.0); // this needs to be a value from 0 to 1, so a percentage michael@0: // can be calculated of the saturation. michael@0: p = (uint16_t)(percent*(255-aSat)); michael@0: q = (uint16_t)(percent*(255-(aSat*f))); michael@0: t = (uint16_t)(percent*(255-(aSat*(1.0-f)))); michael@0: michael@0: // i is guaranteed to never be larger than 5. michael@0: switch(i){ michael@0: case 0: r = aValue; g = t; b = p;break; michael@0: case 1: r = q; g = aValue; b = p;break; michael@0: case 2: r = p; g = aValue; b = t;break; michael@0: case 3: r = p; g = q; b = aValue;break; michael@0: case 4: r = t; g = p; b = aValue;break; michael@0: case 5: r = aValue; g = p; b = q;break; michael@0: } michael@0: } michael@0: aColor = NS_RGBA(r, g, b, aAlpha); michael@0: } michael@0: michael@0: #undef RED_LUMINOSITY michael@0: #undef GREEN_LUMINOSITY michael@0: #undef BLUE_LUMINOSITY michael@0: #undef INTENSITY_FACTOR michael@0: #undef LUMINOSITY_FACTOR michael@0: michael@0: #undef MAX_COLOR michael@0: #undef COLOR_DARK_THRESHOLD michael@0: #undef COLOR_LIGHT_THRESHOLD michael@0: michael@0: #undef COLOR_LITE_BS_FACTOR michael@0: #undef COLOR_LITE_TS_FACTOR michael@0: michael@0: #undef COLOR_DARK_BS_FACTOR michael@0: #undef COLOR_DARK_TS_FACTOR michael@0: michael@0: #undef LIGHT_GRAY michael@0: #undef DARK_GRAY michael@0: michael@0: #undef MAX_BRIGHTNESS michael@0: #undef MAX_DARKNESS