2 * Copyright (c) 2014 - 2017 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
4 * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
5 * Written by Gaius Mulley <gaius@glam.ac.uk>
7 * This is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2, or (at your option) any later
12 * This is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * You should have received a copy of the GNU General Public License along
18 * with groff; see the file COPYING. If not, write to the Free Software
19 * Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
39 static inline unsigned int
40 min(const unsigned int a
, const unsigned int b
)
48 color
*color::free_list
= 0;
51 void *color::operator new(size_t n
)
53 assert(n
== sizeof(color
));
55 const int BLOCK
= 128;
56 free_list
= (color
*)new char[sizeof(color
)*BLOCK
];
57 for (int i
= 0; i
< BLOCK
- 1; i
++)
58 free_list
[i
].next
= free_list
+ i
+ 1;
59 free_list
[BLOCK
-1].next
= 0;
62 free_list
= (color
*)(free_list
->next
);
67 void color::operator delete(void *p
)
70 ((color
*)p
)->next
= free_list
;
71 free_list
= (color
*)p
;
75 color::color(const color
* const c
)
79 components
[0] = c
->components
[0];
80 components
[1] = c
->components
[1];
81 components
[2] = c
->components
[2];
82 components
[3] = c
->components
[3];
89 int color::operator==(const color
& c
) const
91 if (scheme
!= c
.scheme
)
97 if (Red
!= c
.Red
|| Green
!= c
.Green
|| Blue
!= c
.Blue
)
101 if (Cyan
!= c
.Cyan
|| Magenta
!= c
.Magenta
102 || Yellow
!= c
.Yellow
|| Black
!= c
.Black
)
110 if (Cyan
!= c
.Cyan
|| Magenta
!= c
.Magenta
|| Yellow
!= c
.Yellow
)
117 int color::operator!=(const color
& c
) const
119 return !(*this == c
);
122 color_scheme
color::get_components(unsigned int *c
) const
125 if (sizeof (c
) < sizeof (unsigned int) * 4)
126 fatal("argument is not big enough to store 4 color components");
128 c
[0] = components
[0];
129 c
[1] = components
[1];
130 c
[2] = components
[2];
131 c
[3] = components
[3];
135 void color::set_default()
140 // (0, 0, 0) is black
142 void color::set_rgb(const unsigned int r
, const unsigned int g
,
143 const unsigned int b
)
146 Red
= min(MAX_COLOR_VAL
, r
);
147 Green
= min(MAX_COLOR_VAL
, g
);
148 Blue
= min(MAX_COLOR_VAL
, b
);
151 // (0, 0, 0) is white
153 void color::set_cmy(const unsigned int c
, const unsigned int m
,
154 const unsigned int y
)
157 Cyan
= min(MAX_COLOR_VAL
, c
);
158 Magenta
= min(MAX_COLOR_VAL
, m
);
159 Yellow
= min(MAX_COLOR_VAL
, y
);
162 // (0, 0, 0, 0) is white
164 void color::set_cmyk(const unsigned int c
, const unsigned int m
,
165 const unsigned int y
, const unsigned int k
)
168 Cyan
= min(MAX_COLOR_VAL
, c
);
169 Magenta
= min(MAX_COLOR_VAL
, m
);
170 Yellow
= min(MAX_COLOR_VAL
, y
);
171 Black
= min(MAX_COLOR_VAL
, k
);
176 void color::set_gray(const unsigned int g
)
179 Gray
= min(MAX_COLOR_VAL
, g
);
183 * atoh - computes the decimal value of a hexadecimal number string.
184 * `length' characters of `s' are read. Returns 1 if successful.
187 static int atoh(unsigned int *result
,
188 const char * const s
, const size_t length
)
191 unsigned int val
= 0;
192 while ((i
< length
) && csxdigit(s
[i
])) {
194 val
= val
*0x10 + (s
[i
]-'0');
195 else if (csupper(s
[i
]))
196 val
= val
*0x10 + (s
[i
]-'A') + 10;
198 val
= val
*0x10 + (s
[i
]-'a') + 10;
208 * read_encoding - set color from a hexadecimal color string.
210 * Use color scheme `cs' to parse `n' color components from string `s'.
211 * Returns 1 if successful.
214 int color::read_encoding(const color_scheme cs
, const char * const s
,
217 size_t hex_length
= 2;
219 char *p
= (char *) s
;
225 for (size_t i
= 0; i
< n
; i
++) {
226 if (!atoh(&(components
[i
]), p
, hex_length
))
229 components
[i
] *= 0x101; // scale up -- 0xff should become 0xffff
235 int color::read_rgb(const char * const s
)
237 return read_encoding(RGB
, s
, 3);
240 int color::read_cmy(const char * const s
)
242 return read_encoding(CMY
, s
, 3);
245 int color::read_cmyk(const char * const s
)
247 return read_encoding(CMYK
, s
, 4);
250 int color::read_gray(const char * const s
)
252 return read_encoding(GRAY
, s
, 1);
256 color::get_rgb(unsigned int *r
, unsigned int *g
, unsigned int *b
) const
265 *r
= MAX_COLOR_VAL
- Cyan
;
266 *g
= MAX_COLOR_VAL
- Magenta
;
267 *b
= MAX_COLOR_VAL
- Yellow
;
272 Cyan
* (MAX_COLOR_VAL
- Black
) / MAX_COLOR_VAL
+ Black
);
275 Magenta
* (MAX_COLOR_VAL
- Black
) / MAX_COLOR_VAL
+ Black
);
278 Yellow
* (MAX_COLOR_VAL
- Black
) / MAX_COLOR_VAL
+ Black
);
290 color::get_cmy(unsigned int *c
, unsigned int *m
, unsigned int *y
) const
294 *c
= MAX_COLOR_VAL
- Red
;
295 *m
= MAX_COLOR_VAL
- Green
;
296 *y
= MAX_COLOR_VAL
- Blue
;
304 *c
= min(MAX_COLOR_VAL
,
305 Cyan
* (MAX_COLOR_VAL
- Black
) / MAX_COLOR_VAL
+ Black
);
306 *m
= min(MAX_COLOR_VAL
,
307 Magenta
* (MAX_COLOR_VAL
- Black
) / MAX_COLOR_VAL
+ Black
);
308 *y
= min(MAX_COLOR_VAL
,
309 Yellow
* (MAX_COLOR_VAL
- Black
) / MAX_COLOR_VAL
+ Black
);
312 *c
= *m
= *y
= MAX_COLOR_VAL
- Gray
;
320 void color::get_cmyk(unsigned int *c
, unsigned int *m
,
321 unsigned int *y
, unsigned int *k
) const
325 *k
= min(MAX_COLOR_VAL
- Red
,
326 min(MAX_COLOR_VAL
- Green
, MAX_COLOR_VAL
- Blue
));
327 if (MAX_COLOR_VAL
== *k
) {
333 *c
= (MAX_COLOR_VAL
* (MAX_COLOR_VAL
- Red
- *k
))
334 / (MAX_COLOR_VAL
- *k
);
335 *m
= (MAX_COLOR_VAL
* (MAX_COLOR_VAL
- Green
- *k
))
336 / (MAX_COLOR_VAL
- *k
);
337 *y
= (MAX_COLOR_VAL
* (MAX_COLOR_VAL
- Blue
- *k
))
338 / (MAX_COLOR_VAL
- *k
);
342 *k
= min(Cyan
, min(Magenta
, Yellow
));
343 if (MAX_COLOR_VAL
== *k
) {
349 *c
= (MAX_COLOR_VAL
* (Cyan
- *k
)) / (MAX_COLOR_VAL
- *k
);
350 *m
= (MAX_COLOR_VAL
* (Magenta
- *k
)) / (MAX_COLOR_VAL
- *k
);
351 *y
= (MAX_COLOR_VAL
* (Yellow
- *k
)) / (MAX_COLOR_VAL
- *k
);
362 *k
= MAX_COLOR_VAL
- Gray
;
370 // we use `0.222r + 0.707g + 0.071b' (this is the ITU standard)
371 // as an approximation for gray
373 void color::get_gray(unsigned int *g
) const
377 *g
= (222*Red
+ 707*Green
+ 71*Blue
) / 1000;
380 *g
= MAX_COLOR_VAL
- (222*Cyan
+ 707*Magenta
+ 71*Yellow
) / 1000;
383 *g
= (MAX_COLOR_VAL
- (222*Cyan
+ 707*Magenta
+ 71*Yellow
) / 1000)
384 * (MAX_COLOR_VAL
- Black
);
395 char *color::print_color()
397 char *s
= new char[30];
400 sprintf(s
, "default");
403 sprintf(s
, "rgb %.2ff %.2ff %.2ff",
404 double(Red
) / MAX_COLOR_VAL
,
405 double(Green
) / MAX_COLOR_VAL
,
406 double(Blue
) / MAX_COLOR_VAL
);
409 sprintf(s
, "cmy %.2ff %.2ff %.2ff",
410 double(Cyan
) / MAX_COLOR_VAL
,
411 double(Magenta
) / MAX_COLOR_VAL
,
412 double(Yellow
) / MAX_COLOR_VAL
);
415 sprintf(s
, "cmyk %.2ff %.2ff %.2ff %.2ff",
416 double(Cyan
) / MAX_COLOR_VAL
,
417 double(Magenta
) / MAX_COLOR_VAL
,
418 double(Yellow
) / MAX_COLOR_VAL
,
419 double(Black
) / MAX_COLOR_VAL
);
422 sprintf(s
, "gray %.2ff",
423 double(Gray
) / MAX_COLOR_VAL
);