1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
16 // Adaptation for high precision colors has been sponsored by
17 // Liberty Technology Systems, Inc., visit http://lib-sys.com
19 // Liberty Technology Systems, Inc. is the provider of
20 // PostScript and PDF technology for software developers.
22 //----------------------------------------------------------------------------
24 // color types gray8, gray16
26 //----------------------------------------------------------------------------
28 #ifndef AGG_COLOR_GRAY_INCLUDED
29 #define AGG_COLOR_GRAY_INCLUDED
31 #include "agg_basics.h"
32 #include "agg_color_rgba.h"
37 //===================================================================gray8
40 typedef int8u value_type
;
41 typedef int32u calc_type
;
42 typedef int32 long_type
;
46 base_scale
= 1 << base_shift
,
47 base_mask
= base_scale
- 1
49 typedef gray8 self_type
;
54 //--------------------------------------------------------------------
57 //--------------------------------------------------------------------
58 explicit gray8(unsigned v_
, unsigned a_
=base_mask
) :
59 v(int8u(v_
)), a(int8u(a_
)) {}
61 //--------------------------------------------------------------------
62 gray8(const self_type
& c
, unsigned a_
) :
63 v(c
.v
), a(value_type(a_
)) {}
65 //--------------------------------------------------------------------
66 gray8(const rgba
& c
) :
67 v((value_type
)uround((0.299*c
.r
+ 0.587*c
.g
+ 0.114*c
.b
) * double(base_mask
))),
68 a((value_type
)uround(c
.a
* double(base_mask
))) {}
70 //--------------------------------------------------------------------
71 gray8(const rgba
& c
, double a_
) :
72 v((value_type
)uround((0.299*c
.r
+ 0.587*c
.g
+ 0.114*c
.b
) * double(base_mask
))),
73 a((value_type
)uround(a_
* double(base_mask
))) {}
75 //--------------------------------------------------------------------
76 gray8(const rgba8
& c
) :
77 v((c
.r
*77 + c
.g
*150 + c
.b
*29) >> 8),
80 //--------------------------------------------------------------------
81 gray8(const rgba8
& c
, unsigned a_
) :
82 v((c
.r
*77 + c
.g
*150 + c
.b
*29) >> 8),
85 //--------------------------------------------------------------------
91 //--------------------------------------------------------------------
92 const self_type
& transparent()
98 //--------------------------------------------------------------------
99 void opacity(double a_
)
101 if(a_
< 0.0) a_
= 0.0;
102 if(a_
> 1.0) a_
= 1.0;
103 a
= (value_type
)uround(a_
* double(base_mask
));
106 //--------------------------------------------------------------------
107 double opacity() const
109 return double(a
) / double(base_mask
);
113 //--------------------------------------------------------------------
114 const self_type
& premultiply()
116 if(a
== base_mask
) return *this;
122 v
= value_type((calc_type(v
) * a
) >> base_shift
);
126 //--------------------------------------------------------------------
127 const self_type
& premultiply(unsigned a_
)
129 if(a
== base_mask
&& a_
>= base_mask
) return *this;
130 if(a
== 0 || a_
== 0)
135 calc_type v_
= (calc_type(v
) * a_
) / a
;
136 v
= value_type((v_
> a_
) ? a_
: v_
);
141 //--------------------------------------------------------------------
142 const self_type
& demultiply()
144 if(a
== base_mask
) return *this;
150 calc_type v_
= (calc_type(v
) * base_mask
) / a
;
151 v
= value_type((v_
> base_mask
) ? base_mask
: v_
);
155 //--------------------------------------------------------------------
156 self_type
gradient(self_type c
, double k
) const
159 calc_type ik
= uround(k
* base_scale
);
160 ret
.v
= value_type(calc_type(v
) + (((calc_type(c
.v
) - v
) * ik
) >> base_shift
));
161 ret
.a
= value_type(calc_type(a
) + (((calc_type(c
.a
) - a
) * ik
) >> base_shift
));
165 //--------------------------------------------------------------------
166 AGG_INLINE
void add(const self_type
& c
, unsigned cover
)
169 if(cover
== cover_mask
)
177 cv
= v
+ c
.v
; v
= (cv
> calc_type(base_mask
)) ? calc_type(base_mask
) : cv
;
178 ca
= a
+ c
.a
; a
= (ca
> calc_type(base_mask
)) ? calc_type(base_mask
) : ca
;
183 cv
= v
+ ((c
.v
* cover
+ cover_mask
/2) >> cover_shift
);
184 ca
= a
+ ((c
.a
* cover
+ cover_mask
/2) >> cover_shift
);
185 v
= (cv
> calc_type(base_mask
)) ? calc_type(base_mask
) : cv
;
186 a
= (ca
> calc_type(base_mask
)) ? calc_type(base_mask
) : ca
;
190 //--------------------------------------------------------------------
191 static self_type
no_color() { return self_type(0,0); }
195 //-------------------------------------------------------------gray8_pre
196 inline gray8
gray8_pre(unsigned v
, unsigned a
= gray8::base_mask
)
198 return gray8(v
,a
).premultiply();
200 inline gray8
gray8_pre(const gray8
& c
, unsigned a
)
202 return gray8(c
,a
).premultiply();
204 inline gray8
gray8_pre(const rgba
& c
)
206 return gray8(c
).premultiply();
208 inline gray8
gray8_pre(const rgba
& c
, double a
)
210 return gray8(c
,a
).premultiply();
212 inline gray8
gray8_pre(const rgba8
& c
)
214 return gray8(c
).premultiply();
216 inline gray8
gray8_pre(const rgba8
& c
, unsigned a
)
218 return gray8(c
,a
).premultiply();
224 //==================================================================gray16
227 typedef int16u value_type
;
228 typedef int32u calc_type
;
229 typedef int64 long_type
;
233 base_scale
= 1 << base_shift
,
234 base_mask
= base_scale
- 1
236 typedef gray16 self_type
;
241 //--------------------------------------------------------------------
244 //--------------------------------------------------------------------
245 explicit gray16(unsigned v_
, unsigned a_
=base_mask
) :
246 v(int16u(v_
)), a(int16u(a_
)) {}
248 //--------------------------------------------------------------------
249 gray16(const self_type
& c
, unsigned a_
) :
250 v(c
.v
), a(value_type(a_
)) {}
252 //--------------------------------------------------------------------
253 gray16(const rgba
& c
) :
254 v((value_type
)uround((0.299*c
.r
+ 0.587*c
.g
+ 0.114*c
.b
) * double(base_mask
))),
255 a((value_type
)uround(c
.a
* double(base_mask
))) {}
257 //--------------------------------------------------------------------
258 gray16(const rgba
& c
, double a_
) :
259 v((value_type
)uround((0.299*c
.r
+ 0.587*c
.g
+ 0.114*c
.b
) * double(base_mask
))),
260 a((value_type
)uround(a_
* double(base_mask
))) {}
262 //--------------------------------------------------------------------
263 gray16(const rgba8
& c
) :
264 v(c
.r
*77 + c
.g
*150 + c
.b
*29),
265 a((value_type(c
.a
) << 8) | c
.a
) {}
267 //--------------------------------------------------------------------
268 gray16(const rgba8
& c
, unsigned a_
) :
269 v(c
.r
*77 + c
.g
*150 + c
.b
*29),
270 a((value_type(a_
) << 8) | c
.a
) {}
272 //--------------------------------------------------------------------
278 //--------------------------------------------------------------------
279 const self_type
& transparent()
285 //--------------------------------------------------------------------
286 void opacity(double a_
)
288 if(a_
< 0.0) a_
= 0.0;
289 if(a_
> 1.0) a_
= 1.0;
290 a
= (value_type
)uround(a_
* double(base_mask
));
293 //--------------------------------------------------------------------
294 double opacity() const
296 return double(a
) / double(base_mask
);
300 //--------------------------------------------------------------------
301 const self_type
& premultiply()
303 if(a
== base_mask
) return *this;
309 v
= value_type((calc_type(v
) * a
) >> base_shift
);
313 //--------------------------------------------------------------------
314 const self_type
& premultiply(unsigned a_
)
316 if(a
== base_mask
&& a_
>= base_mask
) return *this;
317 if(a
== 0 || a_
== 0)
322 calc_type v_
= (calc_type(v
) * a_
) / a
;
323 v
= value_type((v_
> a_
) ? a_
: v_
);
328 //--------------------------------------------------------------------
329 const self_type
& demultiply()
331 if(a
== base_mask
) return *this;
337 calc_type v_
= (calc_type(v
) * base_mask
) / a
;
338 v
= value_type((v_
> base_mask
) ? base_mask
: v_
);
342 //--------------------------------------------------------------------
343 self_type
gradient(self_type c
, double k
) const
346 calc_type ik
= uround(k
* base_scale
);
347 ret
.v
= value_type(calc_type(v
) + (((calc_type(c
.v
) - v
) * ik
) >> base_shift
));
348 ret
.a
= value_type(calc_type(a
) + (((calc_type(c
.a
) - a
) * ik
) >> base_shift
));
352 //--------------------------------------------------------------------
353 AGG_INLINE
void add(const self_type
& c
, unsigned cover
)
356 if(cover
== cover_mask
)
364 cv
= v
+ c
.v
; v
= (cv
> calc_type(base_mask
)) ? calc_type(base_mask
) : cv
;
365 ca
= a
+ c
.a
; a
= (ca
> calc_type(base_mask
)) ? calc_type(base_mask
) : ca
;
370 cv
= v
+ ((c
.v
* cover
+ cover_mask
/2) >> cover_shift
);
371 ca
= a
+ ((c
.a
* cover
+ cover_mask
/2) >> cover_shift
);
372 v
= (cv
> calc_type(base_mask
)) ? calc_type(base_mask
) : cv
;
373 a
= (ca
> calc_type(base_mask
)) ? calc_type(base_mask
) : ca
;
377 //--------------------------------------------------------------------
378 static self_type
no_color() { return self_type(0,0); }
382 //------------------------------------------------------------gray16_pre
383 inline gray16
gray16_pre(unsigned v
, unsigned a
= gray16::base_mask
)
385 return gray16(v
,a
).premultiply();
387 inline gray16
gray16_pre(const gray16
& c
, unsigned a
)
389 return gray16(c
,a
).premultiply();
391 inline gray16
gray16_pre(const rgba
& c
)
393 return gray16(c
).premultiply();
395 inline gray16
gray16_pre(const rgba
& c
, double a
)
397 return gray16(c
,a
).premultiply();
399 inline gray16
gray16_pre(const rgba8
& c
)
401 return gray16(c
).premultiply();
403 inline gray16
gray16_pre(const rgba8
& c
, unsigned a
)
405 return gray16(c
,a
).premultiply();