layout/base/nsCSSColorUtils.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial