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 #ifndef AGG_PIXFMT_RGB_INCLUDED
25 #define AGG_PIXFMT_RGB_INCLUDED
28 #include "agg_basics.h"
29 #include "agg_color_rgba.h"
30 #include "agg_rendering_buffer.h"
35 //=====================================================apply_gamma_dir_rgb
36 template<class ColorT
, class Order
, class GammaLut
> class apply_gamma_dir_rgb
39 typedef typename
ColorT::value_type value_type
;
41 apply_gamma_dir_rgb(const GammaLut
& gamma
) : m_gamma(gamma
) {}
43 AGG_INLINE
void operator () (value_type
* p
)
45 p
[Order::R
] = m_gamma
.dir(p
[Order::R
]);
46 p
[Order::G
] = m_gamma
.dir(p
[Order::G
]);
47 p
[Order::B
] = m_gamma
.dir(p
[Order::B
]);
51 const GammaLut
& m_gamma
;
56 //=====================================================apply_gamma_inv_rgb
57 template<class ColorT
, class Order
, class GammaLut
> class apply_gamma_inv_rgb
60 typedef typename
ColorT::value_type value_type
;
62 apply_gamma_inv_rgb(const GammaLut
& gamma
) : m_gamma(gamma
) {}
64 AGG_INLINE
void operator () (value_type
* p
)
66 p
[Order::R
] = m_gamma
.inv(p
[Order::R
]);
67 p
[Order::G
] = m_gamma
.inv(p
[Order::G
]);
68 p
[Order::B
] = m_gamma
.inv(p
[Order::B
]);
72 const GammaLut
& m_gamma
;
76 //=========================================================blender_rgb
77 template<class ColorT
, class Order
> struct blender_rgb
79 typedef ColorT color_type
;
80 typedef Order order_type
;
81 typedef typename
color_type::value_type value_type
;
82 typedef typename
color_type::calc_type calc_type
;
83 enum base_scale_e
{ base_shift
= color_type::base_shift
};
85 //--------------------------------------------------------------------
86 static AGG_INLINE
void blend_pix(value_type
* p
,
87 unsigned cr
, unsigned cg
, unsigned cb
,
91 p
[Order::R
] += (value_type
)(((cr
- p
[Order::R
]) * alpha
) >> base_shift
);
92 p
[Order::G
] += (value_type
)(((cg
- p
[Order::G
]) * alpha
) >> base_shift
);
93 p
[Order::B
] += (value_type
)(((cb
- p
[Order::B
]) * alpha
) >> base_shift
);
98 //======================================================blender_rgb_pre
99 template<class ColorT
, class Order
> struct blender_rgb_pre
101 typedef ColorT color_type
;
102 typedef Order order_type
;
103 typedef typename
color_type::value_type value_type
;
104 typedef typename
color_type::calc_type calc_type
;
105 enum base_scale_e
{ base_shift
= color_type::base_shift
};
107 //--------------------------------------------------------------------
108 static AGG_INLINE
void blend_pix(value_type
* p
,
109 unsigned cr
, unsigned cg
, unsigned cb
,
113 alpha
= color_type::base_mask
- alpha
;
114 cover
= (cover
+ 1) << (base_shift
- 8);
115 p
[Order::R
] = (value_type
)((p
[Order::R
] * alpha
+ cr
* cover
) >> base_shift
);
116 p
[Order::G
] = (value_type
)((p
[Order::G
] * alpha
+ cg
* cover
) >> base_shift
);
117 p
[Order::B
] = (value_type
)((p
[Order::B
] * alpha
+ cb
* cover
) >> base_shift
);
120 //--------------------------------------------------------------------
121 static AGG_INLINE
void blend_pix(value_type
* p
,
122 unsigned cr
, unsigned cg
, unsigned cb
,
125 alpha
= color_type::base_mask
- alpha
;
126 p
[Order::R
] = (value_type
)(((p
[Order::R
] * alpha
) >> base_shift
) + cr
);
127 p
[Order::G
] = (value_type
)(((p
[Order::G
] * alpha
) >> base_shift
) + cg
);
128 p
[Order::B
] = (value_type
)(((p
[Order::B
] * alpha
) >> base_shift
) + cb
);
135 //===================================================blender_rgb_gamma
136 template<class ColorT
, class Order
, class Gamma
> class blender_rgb_gamma
139 typedef ColorT color_type
;
140 typedef Order order_type
;
141 typedef Gamma gamma_type
;
142 typedef typename
color_type::value_type value_type
;
143 typedef typename
color_type::calc_type calc_type
;
144 enum base_scale_e
{ base_shift
= color_type::base_shift
};
146 //--------------------------------------------------------------------
147 blender_rgb_gamma() : m_gamma(0) {}
148 void gamma(const gamma_type
& g
) { m_gamma
= &g
; }
150 //--------------------------------------------------------------------
151 AGG_INLINE
void blend_pix(value_type
* p
,
152 unsigned cr
, unsigned cg
, unsigned cb
,
156 calc_type r
= m_gamma
->dir(p
[Order::R
]);
157 calc_type g
= m_gamma
->dir(p
[Order::G
]);
158 calc_type b
= m_gamma
->dir(p
[Order::B
]);
159 p
[Order::R
] = m_gamma
->inv((((m_gamma
->dir(cr
) - r
) * alpha
) >> base_shift
) + r
);
160 p
[Order::G
] = m_gamma
->inv((((m_gamma
->dir(cg
) - g
) * alpha
) >> base_shift
) + g
);
161 p
[Order::B
] = m_gamma
->inv((((m_gamma
->dir(cb
) - b
) * alpha
) >> base_shift
) + b
);
165 const gamma_type
* m_gamma
;
171 //==================================================pixfmt_alpha_blend_rgb
172 template<class Blender
, class RenBuf
> class pixfmt_alpha_blend_rgb
175 typedef RenBuf rbuf_type
;
176 typedef Blender blender_type
;
177 typedef typename
rbuf_type::row_data row_data
;
178 typedef typename
blender_type::color_type color_type
;
179 typedef typename
blender_type::order_type order_type
;
180 typedef typename
color_type::value_type value_type
;
181 typedef typename
color_type::calc_type calc_type
;
184 base_shift
= color_type::base_shift
,
185 base_scale
= color_type::base_scale
,
186 base_mask
= color_type::base_mask
,
187 pix_width
= sizeof(value_type
) * 3
191 //--------------------------------------------------------------------
192 AGG_INLINE
void copy_or_blend_pix(value_type
* p
,
198 calc_type alpha
= (calc_type(c
.a
) * (cover
+ 1)) >> 8;
199 if(alpha
== base_mask
)
201 p
[order_type::R
] = c
.r
;
202 p
[order_type::G
] = c
.g
;
203 p
[order_type::B
] = c
.b
;
207 m_blender
.blend_pix(p
, c
.r
, c
.g
, c
.b
, alpha
, cover
);
212 //--------------------------------------------------------------------
213 AGG_INLINE
void copy_or_blend_pix(value_type
* p
,
220 p
[order_type::R
] = c
.r
;
221 p
[order_type::G
] = c
.g
;
222 p
[order_type::B
] = c
.b
;
226 m_blender
.blend_pix(p
, c
.r
, c
.g
, c
.b
, c
.a
);
233 //--------------------------------------------------------------------
234 pixfmt_alpha_blend_rgb(rbuf_type
& rb
) :
237 void attach(rbuf_type
& rb
) { m_rbuf
= &rb
; }
239 //--------------------------------------------------------------------
240 template<class PixFmt
>
241 bool attach(PixFmt
& pixf
, int x1
, int y1
, int x2
, int y2
)
243 rect_i
r(x1
, y1
, x2
, y2
);
244 if(r
.clip(rect_i(0, 0, pixf
.width()-1, pixf
.height()-1)))
246 int stride
= pixf
.stride();
247 m_rbuf
->attach(pixf
.pix_ptr(r
.x1
, stride
< 0 ? r
.y2
: r
.y1
),
256 //--------------------------------------------------------------------
257 Blender
& blender() { return m_blender
; }
259 //--------------------------------------------------------------------
260 AGG_INLINE
unsigned width() const { return m_rbuf
->width(); }
261 AGG_INLINE
unsigned height() const { return m_rbuf
->height(); }
262 AGG_INLINE
int stride() const { return m_rbuf
->stride(); }
264 //--------------------------------------------------------------------
265 AGG_INLINE int8u
* row_ptr(int y
) { return m_rbuf
->row_ptr(y
); }
266 AGG_INLINE
const int8u
* row_ptr(int y
) const { return m_rbuf
->row_ptr(y
); }
267 AGG_INLINE row_data
row(int y
) const { return m_rbuf
->row(y
); }
269 //--------------------------------------------------------------------
270 AGG_INLINE int8u
* pix_ptr(int x
, int y
)
272 return m_rbuf
->row_ptr(y
) + x
* pix_width
;
275 AGG_INLINE
const int8u
* pix_ptr(int x
, int y
) const
277 return m_rbuf
->row_ptr(y
) + x
* pix_width
;
280 //--------------------------------------------------------------------
281 AGG_INLINE
static void make_pix(int8u
* p
, const color_type
& c
)
283 ((value_type
*)p
)[order_type::R
] = c
.r
;
284 ((value_type
*)p
)[order_type::G
] = c
.g
;
285 ((value_type
*)p
)[order_type::B
] = c
.b
;
288 //--------------------------------------------------------------------
289 AGG_INLINE color_type
pixel(int x
, int y
) const
291 value_type
* p
= (value_type
*)m_rbuf
->row_ptr(y
) + x
+ x
+ x
;
292 return color_type(p
[order_type::R
],
297 //--------------------------------------------------------------------
298 AGG_INLINE
void copy_pixel(int x
, int y
, const color_type
& c
)
300 value_type
* p
= (value_type
*)m_rbuf
->row_ptr(x
, y
, 1) + x
+ x
+ x
;
301 p
[order_type::R
] = c
.r
;
302 p
[order_type::G
] = c
.g
;
303 p
[order_type::B
] = c
.b
;
306 //--------------------------------------------------------------------
307 AGG_INLINE
void blend_pixel(int x
, int y
, const color_type
& c
, int8u cover
)
309 copy_or_blend_pix((value_type
*)m_rbuf
->row_ptr(x
, y
, 1) + x
+ x
+ x
, c
, cover
);
313 //--------------------------------------------------------------------
314 AGG_INLINE
void copy_hline(int x
, int y
,
318 value_type
* p
= (value_type
*)m_rbuf
->row_ptr(x
, y
, len
) + x
+ x
+ x
;
321 p
[order_type::R
] = c
.r
;
322 p
[order_type::G
] = c
.g
;
323 p
[order_type::B
] = c
.b
;
330 //--------------------------------------------------------------------
331 AGG_INLINE
void copy_vline(int x
, int y
,
337 value_type
* p
= (value_type
*)
338 m_rbuf
->row_ptr(x
, y
++, 1) + x
+ x
+ x
;
339 p
[order_type::R
] = c
.r
;
340 p
[order_type::G
] = c
.g
;
341 p
[order_type::B
] = c
.b
;
347 //--------------------------------------------------------------------
348 void blend_hline(int x
, int y
,
355 value_type
* p
= (value_type
*)
356 m_rbuf
->row_ptr(x
, y
, len
) + x
+ x
+ x
;
358 calc_type alpha
= (calc_type(c
.a
) * (calc_type(cover
) + 1)) >> 8;
359 if(alpha
== base_mask
)
363 p
[order_type::R
] = c
.r
;
364 p
[order_type::G
] = c
.g
;
365 p
[order_type::B
] = c
.b
;
374 m_blender
.blend_pix(p
, c
.r
, c
.g
, c
.b
, alpha
, cover
);
383 //--------------------------------------------------------------------
384 void blend_vline(int x
, int y
,
392 calc_type alpha
= (calc_type(c
.a
) * (cover
+ 1)) >> 8;
393 if(alpha
== base_mask
)
398 m_rbuf
->row_ptr(x
, y
++, 1) + x
+ x
+ x
;
400 p
[order_type::R
] = c
.r
;
401 p
[order_type::G
] = c
.g
;
402 p
[order_type::B
] = c
.b
;
411 m_rbuf
->row_ptr(x
, y
++, 1) + x
+ x
+ x
;
413 m_blender
.blend_pix(p
, c
.r
, c
.g
, c
.b
, alpha
, cover
);
421 //--------------------------------------------------------------------
422 void blend_solid_hspan(int x
, int y
,
429 value_type
* p
= (value_type
*)
430 m_rbuf
->row_ptr(x
, y
, len
) + x
+ x
+ x
;
434 calc_type alpha
= (calc_type(c
.a
) * (calc_type(*covers
) + 1)) >> 8;
435 if(alpha
== base_mask
)
437 p
[order_type::R
] = c
.r
;
438 p
[order_type::G
] = c
.g
;
439 p
[order_type::B
] = c
.b
;
443 m_blender
.blend_pix(p
, c
.r
, c
.g
, c
.b
, alpha
, *covers
);
453 //--------------------------------------------------------------------
454 void blend_solid_vspan(int x
, int y
,
463 value_type
* p
= (value_type
*)
464 m_rbuf
->row_ptr(x
, y
++, 1) + x
+ x
+ x
;
466 calc_type alpha
= (calc_type(c
.a
) * (calc_type(*covers
) + 1)) >> 8;
467 if(alpha
== base_mask
)
469 p
[order_type::R
] = c
.r
;
470 p
[order_type::G
] = c
.g
;
471 p
[order_type::B
] = c
.b
;
475 m_blender
.blend_pix(p
, c
.r
, c
.g
, c
.b
, alpha
, *covers
);
484 //--------------------------------------------------------------------
485 void copy_color_hspan(int x
, int y
,
487 const color_type
* colors
)
489 value_type
* p
= (value_type
*)
490 m_rbuf
->row_ptr(x
, y
, len
) + x
+ x
+ x
;
494 p
[order_type::R
] = colors
->r
;
495 p
[order_type::G
] = colors
->g
;
496 p
[order_type::B
] = colors
->b
;
504 //--------------------------------------------------------------------
505 void copy_color_vspan(int x
, int y
,
507 const color_type
* colors
)
511 value_type
* p
= (value_type
*)
512 m_rbuf
->row_ptr(x
, y
++, 1) + x
+ x
+ x
;
513 p
[order_type::R
] = colors
->r
;
514 p
[order_type::G
] = colors
->g
;
515 p
[order_type::B
] = colors
->b
;
522 //--------------------------------------------------------------------
523 void blend_color_hspan(int x
, int y
,
525 const color_type
* colors
,
529 value_type
* p
= (value_type
*)
530 m_rbuf
->row_ptr(x
, y
, len
) + x
+ x
+ x
;
536 copy_or_blend_pix(p
, *colors
++, *covers
++);
547 copy_or_blend_pix(p
, *colors
++);
556 copy_or_blend_pix(p
, *colors
++, cover
);
566 //--------------------------------------------------------------------
567 void blend_color_vspan(int x
, int y
,
569 const color_type
* colors
,
579 m_rbuf
->row_ptr(x
, y
++, 1) + x
+ x
+ x
;
581 copy_or_blend_pix(p
, *colors
++, *covers
++);
592 m_rbuf
->row_ptr(x
, y
++, 1) + x
+ x
+ x
;
594 copy_or_blend_pix(p
, *colors
++);
603 m_rbuf
->row_ptr(x
, y
++, 1) + x
+ x
+ x
;
605 copy_or_blend_pix(p
, *colors
++, cover
);
612 //--------------------------------------------------------------------
613 template<class Function
> void for_each_pixel(Function f
)
616 for(y
= 0; y
< height(); ++y
)
618 row_data r
= m_rbuf
->row(y
);
621 unsigned len
= r
.x2
- r
.x1
+ 1;
622 value_type
* p
= (value_type
*)
623 m_rbuf
->row_ptr(r
.x1
, y
, len
) + r
.x1
* 3;
634 //--------------------------------------------------------------------
635 template<class GammaLut
> void apply_gamma_dir(const GammaLut
& g
)
637 for_each_pixel(apply_gamma_dir_rgb
<color_type
, order_type
, GammaLut
>(g
));
640 //--------------------------------------------------------------------
641 template<class GammaLut
> void apply_gamma_inv(const GammaLut
& g
)
643 for_each_pixel(apply_gamma_inv_rgb
<color_type
, order_type
, GammaLut
>(g
));
646 //--------------------------------------------------------------------
647 template<class RenBuf2
>
648 void copy_from(const RenBuf2
& from
,
653 const int8u
* p
= from
.row_ptr(ysrc
);
656 memmove(m_rbuf
->row_ptr(xdst
, ydst
, len
) + xdst
* pix_width
,
657 p
+ xsrc
* pix_width
,
663 //--------------------------------------------------------------------
664 template<class SrcPixelFormatRenderer
>
665 void blend_from(const SrcPixelFormatRenderer
& from
,
671 typedef typename
SrcPixelFormatRenderer::order_type src_order
;
673 const value_type
* psrc
= (const value_type
*)from
.row_ptr(ysrc
);
678 (value_type
*)m_rbuf
->row_ptr(xdst
, ydst
, len
) + xdst
* 3;
684 value_type alpha
= psrc
[src_order::A
];
687 if(alpha
== base_mask
)
689 pdst
[order_type::R
] = psrc
[src_order::R
];
690 pdst
[order_type::G
] = psrc
[src_order::G
];
691 pdst
[order_type::B
] = psrc
[src_order::B
];
695 m_blender
.blend_pix(pdst
,
712 color
.r
= psrc
[src_order::R
];
713 color
.g
= psrc
[src_order::G
];
714 color
.b
= psrc
[src_order::B
];
715 color
.a
= psrc
[src_order::A
];
716 copy_or_blend_pix(pdst
, color
, cover
);
730 typedef pixfmt_alpha_blend_rgb
<blender_rgb
<rgba8
, order_rgb
>, rendering_buffer
> pixfmt_rgb24
; //----pixfmt_rgb24
731 typedef pixfmt_alpha_blend_rgb
<blender_rgb
<rgba8
, order_bgr
>, rendering_buffer
> pixfmt_bgr24
; //----pixfmt_bgr24
732 typedef pixfmt_alpha_blend_rgb
<blender_rgb
<rgba16
, order_rgb
>, rendering_buffer
> pixfmt_rgb48
; //----pixfmt_rgb48
733 typedef pixfmt_alpha_blend_rgb
<blender_rgb
<rgba16
, order_bgr
>, rendering_buffer
> pixfmt_bgr48
; //----pixfmt_bgr48
735 typedef pixfmt_alpha_blend_rgb
<blender_rgb_pre
<rgba8
, order_rgb
>, rendering_buffer
> pixfmt_rgb24_pre
; //----pixfmt_rgb24_pre
736 typedef pixfmt_alpha_blend_rgb
<blender_rgb_pre
<rgba8
, order_bgr
>, rendering_buffer
> pixfmt_bgr24_pre
; //----pixfmt_bgr24_pre
737 typedef pixfmt_alpha_blend_rgb
<blender_rgb_pre
<rgba16
, order_rgb
>, rendering_buffer
> pixfmt_rgb48_pre
; //----pixfmt_rgb48_pre
738 typedef pixfmt_alpha_blend_rgb
<blender_rgb_pre
<rgba16
, order_bgr
>, rendering_buffer
> pixfmt_bgr48_pre
; //----pixfmt_bgr48_pre
740 //-----------------------------------------------------pixfmt_rgb24_gamma
741 template<class Gamma
> class pixfmt_rgb24_gamma
:
742 public pixfmt_alpha_blend_rgb
<blender_rgb_gamma
<rgba8
, order_rgb
, Gamma
>, rendering_buffer
>
745 pixfmt_rgb24_gamma(rendering_buffer
& rb
, const Gamma
& g
) :
746 pixfmt_alpha_blend_rgb
<blender_rgb_gamma
<rgba8
, order_rgb
, Gamma
>, rendering_buffer
>(rb
)
748 this->blender().gamma(g
);
752 //-----------------------------------------------------pixfmt_bgr24_gamma
753 template<class Gamma
> class pixfmt_bgr24_gamma
:
754 public pixfmt_alpha_blend_rgb
<blender_rgb_gamma
<rgba8
, order_bgr
, Gamma
>, rendering_buffer
>
757 pixfmt_bgr24_gamma(rendering_buffer
& rb
, const Gamma
& g
) :
758 pixfmt_alpha_blend_rgb
<blender_rgb_gamma
<rgba8
, order_bgr
, Gamma
>, rendering_buffer
>(rb
)
760 this->blender().gamma(g
);
764 //-----------------------------------------------------pixfmt_rgb48_gamma
765 template<class Gamma
> class pixfmt_rgb48_gamma
:
766 public pixfmt_alpha_blend_rgb
<blender_rgb_gamma
<rgba16
, order_rgb
, Gamma
>, rendering_buffer
>
769 pixfmt_rgb48_gamma(rendering_buffer
& rb
, const Gamma
& g
) :
770 pixfmt_alpha_blend_rgb
<blender_rgb_gamma
<rgba16
, order_rgb
, Gamma
>, rendering_buffer
>(rb
)
772 this->blender().gamma(g
);
776 //-----------------------------------------------------pixfmt_bgr48_gamma
777 template<class Gamma
> class pixfmt_bgr48_gamma
:
778 public pixfmt_alpha_blend_rgb
<blender_rgb_gamma
<rgba16
, order_bgr
, Gamma
>, rendering_buffer
>
781 pixfmt_bgr48_gamma(rendering_buffer
& rb
, const Gamma
& g
) :
782 pixfmt_alpha_blend_rgb
<blender_rgb_gamma
<rgba16
, order_bgr
, Gamma
>, rendering_buffer
>(rb
)
784 this->blender().gamma(g
);