summaryrefslogtreecommitdiffstats
path: root/layout/base/nsCSSColorUtils.cpp
blob: 66e6a333bac167a9d9abbd780ef9e60b03a2de99 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */

/* functions that manipulate colors */

#include "nsCSSColorUtils.h"
#include "nsDebug.h"
#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.

#define RED_LUMINOSITY 299
#define GREEN_LUMINOSITY 587
#define BLUE_LUMINOSITY 114
#define INTENSITY_FACTOR 25
#define LUMINOSITY_FACTOR 75

void NS_GetSpecial3DColors(nscolor aResult[2], nscolor aBorderColor) {
  const float kDarkerScale = 2.0f / 3.0f;

  uint8_t r = NS_GET_R(aBorderColor);
  uint8_t g = NS_GET_G(aBorderColor);
  uint8_t b = NS_GET_B(aBorderColor);
  uint8_t a = NS_GET_A(aBorderColor);
  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;
  }

  aResult[0] = NS_RGBA(uint8_t(r * kDarkerScale), uint8_t(g * kDarkerScale),
                       uint8_t(b * kDarkerScale), a);
  aResult[1] = aBorderColor;
}

int NS_GetBrightness(uint8_t aRed, uint8_t aGreen, uint8_t aBlue) {
  uint8_t intensity = (aRed + aGreen + aBlue) / 3;

  uint8_t luminosity = NS_GetLuminosity(NS_RGB(aRed, aGreen, aBlue)) / 1000;

  return ((intensity * INTENSITY_FACTOR) + (luminosity * LUMINOSITY_FACTOR)) /
         100;
}

int32_t NS_GetLuminosity(nscolor aColor) {
  // 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");

  return (NS_GET_R(aColor) * RED_LUMINOSITY +
          NS_GET_G(aColor) * GREEN_LUMINOSITY +
          NS_GET_B(aColor) * BLUE_LUMINOSITY);
}

// Function to convert RGB color space into the HSV colorspace
// Hue is the primary color defined from 0 to 359 degrees
// 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.
void NS_RGB2HSV(nscolor aColor, uint16_t& aHue, uint16_t& aSat,
                uint16_t& aValue, uint8_t& aAlpha) {
  uint8_t r, g, b;
  int16_t delta, min, max, r1, b1, g1;
  float hue;

  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)
  aValue = max;
  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;
    } else {
      hue = 4.0f + (float)(r1 - g1) / (float)delta;
    }
  }

  if (hue < 999) {
    hue *= 60;
    if (hue < 0) {
      hue += 360;
    }
  } else {
    hue = 0;
  }

  aHue = (uint16_t)hue;

  aAlpha = NS_GET_A(aColor);
}

// Function to convert HSV color space into the RGB colorspace
// Hue is the primary color defined from 0 to 359 degrees
// 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.
void NS_HSV2RGB(nscolor& aColor, uint16_t aHue, uint16_t aSat, uint16_t aValue,
                uint8_t aAlpha) {
  uint16_t r = 0, g = 0, b = 0;
  uint16_t i, p, q, t;
  double h, f, percent;

  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
    // 0 to 360 degrees.
    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;
    i = (uint16_t)floor(h);
    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.
    p = (uint16_t)(percent * (255 - aSat));
    q = (uint16_t)(percent * (255 - (aSat * f)));
    t = (uint16_t)(percent * (255 - (aSat * (1.0 - f))));

    // i is guaranteed to never be larger than 5.
    switch (i) {
      case 0:
        r = aValue;
        g = t;
        b = p;
        break;
      case 1:
        r = q;
        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;
        break;
    }
  }
  aColor = NS_RGBA(r, g, b, aAlpha);
}

#undef RED_LUMINOSITY
#undef GREEN_LUMINOSITY
#undef BLUE_LUMINOSITY
#undef INTENSITY_FACTOR
#undef LUMINOSITY_FACTOR