update dev300-m58
[ooovba.git] / agg / inc / agg_pixfmt_rgb.h
blob767bb4e74c85354980ed383b0c8a86802015f804
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
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.
9 //
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.
21 //
22 //----------------------------------------------------------------------------
24 #ifndef AGG_PIXFMT_RGB_INCLUDED
25 #define AGG_PIXFMT_RGB_INCLUDED
27 #include <string.h>
28 #include "agg_basics.h"
29 #include "agg_color_rgba.h"
30 #include "agg_rendering_buffer.h"
32 namespace agg
35 //=====================================================apply_gamma_dir_rgb
36 template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgb
38 public:
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]);
50 private:
51 const GammaLut& m_gamma;
56 //=====================================================apply_gamma_inv_rgb
57 template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgb
59 public:
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]);
71 private:
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_shift = color_type::base_shift };
85 //--------------------------------------------------------------------
86 static AGG_INLINE void blend_pix(value_type* p,
87 unsigned cr, unsigned cg, unsigned cb,
88 unsigned alpha,
89 unsigned)
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_shift = color_type::base_shift };
107 //--------------------------------------------------------------------
108 static AGG_INLINE void blend_pix(value_type* p,
109 unsigned cr, unsigned cg, unsigned cb,
110 unsigned alpha,
111 unsigned cover)
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);
123 //===================================================blender_rgb_gamma
124 template<class ColorT, class Order, class Gamma> class blender_rgb_gamma
126 public:
127 typedef ColorT color_type;
128 typedef Order order_type;
129 typedef Gamma gamma_type;
130 typedef typename color_type::value_type value_type;
131 typedef typename color_type::calc_type calc_type;
132 enum { base_shift = color_type::base_shift };
134 //--------------------------------------------------------------------
135 blender_rgb_gamma() : m_gamma(0) {}
136 void gamma(const gamma_type& g) { m_gamma = &g; }
138 //--------------------------------------------------------------------
139 AGG_INLINE void blend_pix(value_type* p,
140 unsigned cr, unsigned cg, unsigned cb,
141 unsigned alpha,
142 unsigned)
144 calc_type r = m_gamma->dir(p[Order::R]);
145 calc_type g = m_gamma->dir(p[Order::G]);
146 calc_type b = m_gamma->dir(p[Order::B]);
147 p[Order::R] = m_gamma->inv((((m_gamma->dir(cr) - r) * alpha) >> base_shift) + r);
148 p[Order::G] = m_gamma->inv((((m_gamma->dir(cg) - g) * alpha) >> base_shift) + g);
149 p[Order::B] = m_gamma->inv((((m_gamma->dir(cb) - b) * alpha) >> base_shift) + b);
152 private:
153 const gamma_type* m_gamma;
159 //==================================================pixel_formats_rgb
160 template<class Blender> class pixel_formats_rgb
162 public:
163 typedef rendering_buffer::row_data row_data;
164 typedef typename Blender::color_type color_type;
165 typedef typename Blender::order_type order_type;
166 typedef typename color_type::value_type value_type;
167 typedef typename color_type::calc_type calc_type;
168 enum
170 base_shift = color_type::base_shift,
171 base_size = color_type::base_size,
172 base_mask = color_type::base_mask
175 private:
176 //--------------------------------------------------------------------
177 AGG_INLINE void copy_or_blend_pix(value_type* p,
178 const color_type& c,
179 unsigned cover)
181 if (c.a)
183 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
184 if(alpha == base_mask)
186 p[order_type::R] = c.r;
187 p[order_type::G] = c.g;
188 p[order_type::B] = c.b;
190 else
192 m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
197 //--------------------------------------------------------------------
198 AGG_INLINE void copy_or_blend_opaque_pix(value_type* p,
199 const color_type& c,
200 unsigned cover)
202 if(cover == 255)
204 p[order_type::R] = c.r;
205 p[order_type::G] = c.g;
206 p[order_type::B] = c.b;
208 else
210 m_blender.blend_pix(p, c.r, c.g, c.b, (cover + 1) << (base_shift - 8), cover);
215 public:
216 //--------------------------------------------------------------------
217 pixel_formats_rgb(rendering_buffer& rb) :
218 m_rbuf(&rb)
221 //--------------------------------------------------------------------
222 Blender& blender() { return m_blender; }
224 //--------------------------------------------------------------------
225 AGG_INLINE unsigned width() const { return m_rbuf->width(); }
226 AGG_INLINE unsigned height() const { return m_rbuf->height(); }
228 //--------------------------------------------------------------------
229 AGG_INLINE color_type pixel(int x, int y) const
231 value_type* p = (value_type*)m_rbuf->row(y) + x + x + x;
232 return color_type(p[order_type::R],
233 p[order_type::G],
234 p[order_type::B]);
237 //--------------------------------------------------------------------
238 row_data span(int x, int y) const
240 return row_data(x,
241 width() - 1,
242 m_rbuf->row(y) + x * 3 * sizeof(value_type));
245 //--------------------------------------------------------------------
246 AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
248 value_type* p = (value_type*)m_rbuf->row(y) + x + x + x;
249 p[order_type::R] = c.r;
250 p[order_type::G] = c.g;
251 p[order_type::B] = c.b;
254 //--------------------------------------------------------------------
255 AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
257 copy_or_blend_pix((value_type*)m_rbuf->row(y) + x + x + x, c, cover);
261 //--------------------------------------------------------------------
262 AGG_INLINE void copy_hline(int x, int y,
263 unsigned len,
264 const color_type& c)
266 value_type* p = (value_type*)m_rbuf->row(y) + x + x + x;
269 p[order_type::R] = c.r;
270 p[order_type::G] = c.g;
271 p[order_type::B] = c.b;
272 p += 3;
274 while(--len);
278 //--------------------------------------------------------------------
279 AGG_INLINE void copy_vline(int x, int y,
280 unsigned len,
281 const color_type& c)
283 value_type* p = (value_type*)m_rbuf->row(y) + x + x + x;
286 p[order_type::R] = c.r;
287 p[order_type::G] = c.g;
288 p[order_type::B] = c.b;
289 p = (value_type*)m_rbuf->next_row(p);
291 while(--len);
295 //--------------------------------------------------------------------
296 void blend_hline(int x, int y,
297 unsigned len,
298 const color_type& c,
299 int8u cover)
301 if (c.a)
303 value_type* p = (value_type*)m_rbuf->row(y) + x + x + x;
304 calc_type alpha = (calc_type(c.a) * (calc_type(cover) + 1)) >> 8;
305 if(alpha == base_mask)
309 p[order_type::R] = c.r;
310 p[order_type::G] = c.g;
311 p[order_type::B] = c.b;
312 p += 3;
314 while(--len);
316 else
320 m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
321 p += 3;
323 while(--len);
329 //--------------------------------------------------------------------
330 void blend_vline(int x, int y,
331 unsigned len,
332 const color_type& c,
333 int8u cover)
335 if (c.a)
337 value_type* p = (value_type*)m_rbuf->row(y) + x + x + x;
338 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
339 if(alpha == base_mask)
343 p[order_type::R] = c.r;
344 p[order_type::G] = c.g;
345 p[order_type::B] = c.b;
346 p = (value_type*)m_rbuf->next_row(p);
348 while(--len);
350 else
354 m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
355 p = (value_type*)m_rbuf->next_row(p);
357 while(--len);
363 //--------------------------------------------------------------------
364 void blend_solid_hspan(int x, int y,
365 unsigned len,
366 const color_type& c,
367 const int8u* covers)
369 if (c.a)
371 value_type* p = (value_type*)m_rbuf->row(y) + x + x + x;
374 calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
375 if(alpha == base_mask)
377 p[order_type::R] = c.r;
378 p[order_type::G] = c.g;
379 p[order_type::B] = c.b;
381 else
383 m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
385 p += 3;
386 ++covers;
388 while(--len);
393 //--------------------------------------------------------------------
394 void blend_solid_vspan(int x, int y,
395 unsigned len,
396 const color_type& c,
397 const int8u* covers)
399 if (c.a)
401 value_type* p = (value_type*)m_rbuf->row(y) + x + x + x;
404 calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
405 if(alpha == base_mask)
407 p[order_type::R] = c.r;
408 p[order_type::G] = c.g;
409 p[order_type::B] = c.b;
411 else
413 m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
415 p = (value_type*)m_rbuf->next_row(p);
416 ++covers;
418 while(--len);
423 //--------------------------------------------------------------------
424 void blend_color_hspan(int x, int y,
425 unsigned len,
426 const color_type* colors,
427 const int8u* covers,
428 int8u cover)
430 value_type* p = (value_type*)m_rbuf->row(y) + x + x + x;
431 if(covers)
435 copy_or_blend_pix(p, *colors++, *covers++);
436 p += 3;
438 while(--len);
440 else
442 if(cover == 255)
446 if(colors->a == base_mask)
448 p[order_type::R] = colors->r;
449 p[order_type::G] = colors->g;
450 p[order_type::B] = colors->b;
452 else
454 copy_or_blend_pix(p, *colors, 255);
456 p += 3;
457 ++colors;
459 while(--len);
461 else
465 copy_or_blend_pix(p, *colors++, cover);
466 p += 3;
468 while(--len);
475 //--------------------------------------------------------------------
476 void blend_color_vspan(int x, int y,
477 unsigned len,
478 const color_type* colors,
479 const int8u* covers,
480 int8u cover)
482 value_type* p = (value_type*)m_rbuf->row(y) + x + x + x;
483 if(covers)
487 copy_or_blend_pix(p, *colors++, *covers++);
488 p = (value_type*)m_rbuf->next_row(p);
490 while(--len);
492 else
494 if(cover == 255)
498 if(colors->a == base_mask)
500 p[order_type::R] = colors->r;
501 p[order_type::G] = colors->g;
502 p[order_type::B] = colors->b;
504 else
506 copy_or_blend_pix(p, *colors, 255);
508 p = (value_type*)m_rbuf->next_row(p);
509 ++colors;
511 while(--len);
513 else
517 copy_or_blend_pix(p, *colors++, cover);
518 p = (value_type*)m_rbuf->next_row(p);
520 while(--len);
526 //--------------------------------------------------------------------
527 void blend_opaque_color_hspan(int x, int y,
528 unsigned len,
529 const color_type* colors,
530 const int8u* covers,
531 int8u cover)
533 value_type* p = (value_type*)m_rbuf->row(y) + x + x + x;
534 if(covers)
538 copy_or_blend_opaque_pix(p, *colors++, *covers++);
539 p += 3;
541 while(--len);
543 else
545 if(cover == 255)
549 p[order_type::R] = colors->r;
550 p[order_type::G] = colors->g;
551 p[order_type::B] = colors->b;
552 p += 3;
553 ++colors;
555 while(--len);
557 else
561 copy_or_blend_opaque_pix(p, *colors++, cover);
562 p += 3;
564 while(--len);
570 //--------------------------------------------------------------------
571 void blend_opaque_color_vspan(int x, int y,
572 unsigned len,
573 const color_type* colors,
574 const int8u* covers,
575 int8u cover)
577 value_type* p = (value_type*)m_rbuf->row(y) + x + x + x;
578 if(covers)
582 copy_or_blend_opaque_pix(p, *colors++, *covers++);
583 p = (value_type*)m_rbuf->next_row(p);
585 while(--len);
587 else
589 if(cover == 255)
593 p[order_type::R] = colors->r;
594 p[order_type::G] = colors->g;
595 p[order_type::B] = colors->b;
596 p = (value_type*)m_rbuf->next_row(p);
597 ++colors;
599 while(--len);
601 else
605 copy_or_blend_opaque_pix(p, *colors++, cover);
606 p = (value_type*)m_rbuf->next_row(p);
608 while(--len);
613 //--------------------------------------------------------------------
614 template<class Function> void for_each_pixel(Function f)
616 unsigned y;
617 for(y = 0; y < height(); ++y)
619 unsigned len = width();
620 value_type* p = (value_type*)m_rbuf->row(y);
623 f(p);
624 p += 3;
626 while(--len);
630 //--------------------------------------------------------------------
631 template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
633 for_each_pixel(apply_gamma_dir_rgb<color_type, order_type, GammaLut>(g));
636 //--------------------------------------------------------------------
637 template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
639 for_each_pixel(apply_gamma_inv_rgb<color_type, order_type, GammaLut>(g));
642 //--------------------------------------------------------------------
643 void copy_from(const rendering_buffer& from,
644 int xdst, int ydst,
645 int xsrc, int ysrc,
646 unsigned len)
648 memmove((value_type*)m_rbuf->row(ydst) + xdst * 3,
649 (const value_type*)from.row(ysrc) + xsrc * 3,
650 sizeof(value_type) * 3 * len);
654 //--------------------------------------------------------------------
655 template<class SrcPixelFormatRenderer>
656 void blend_from(const SrcPixelFormatRenderer& from,
657 const int8u* psrc_,
658 int xdst, int ydst,
659 int xsrc, int ysrc,
660 unsigned len)
662 typedef typename SrcPixelFormatRenderer::order_type src_order;
664 const value_type* psrc = (const value_type*)psrc_;
665 value_type* pdst = (value_type*)m_rbuf->row(ydst) + xdst * 3;
668 value_type alpha = psrc[src_order::A];
669 if(alpha)
671 if(alpha == base_mask)
673 pdst[order_type::R] = psrc[src_order::R];
674 pdst[order_type::G] = psrc[src_order::G];
675 pdst[order_type::B] = psrc[src_order::B];
677 else
679 m_blender.blend_pix(pdst,
680 psrc[src_order::R],
681 psrc[src_order::G],
682 psrc[src_order::B],
683 alpha,
684 255);
687 psrc += 4;
688 pdst += 3;
690 while(--len);
693 private:
694 rendering_buffer* m_rbuf;
695 Blender m_blender;
698 typedef pixel_formats_rgb<blender_rgb<rgba8, order_rgb> > pixfmt_rgb24; //----pixfmt_rgb24
699 typedef pixel_formats_rgb<blender_rgb<rgba8, order_bgr> > pixfmt_bgr24; //----pixfmt_bgr24
700 typedef pixel_formats_rgb<blender_rgb<rgba16, order_rgb> > pixfmt_rgb48; //----pixfmt_rgb48
701 typedef pixel_formats_rgb<blender_rgb<rgba16, order_bgr> > pixfmt_bgr48; //----pixfmt_bgr48
703 typedef pixel_formats_rgb<blender_rgb_pre<rgba8, order_rgb> > pixfmt_rgb24_pre; //----pixfmt_rgb24_pre
704 typedef pixel_formats_rgb<blender_rgb_pre<rgba8, order_bgr> > pixfmt_bgr24_pre; //----pixfmt_bgr24_pre
705 typedef pixel_formats_rgb<blender_rgb_pre<rgba16, order_rgb> > pixfmt_rgb48_pre; //----pixfmt_rgb48_pre
706 typedef pixel_formats_rgb<blender_rgb_pre<rgba16, order_bgr> > pixfmt_bgr48_pre; //----pixfmt_bgr48_pre
708 //-----------------------------------------------------pixfmt_rgb24_gamma
709 template<class Gamma> class pixfmt_rgb24_gamma :
710 public pixel_formats_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma> >
712 public:
713 pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) :
714 pixel_formats_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma> >(rb)
716 this->blender().gamma(g);
720 //-----------------------------------------------------pixfmt_bgr24_gamma
721 template<class Gamma> class pixfmt_bgr24_gamma :
722 public pixel_formats_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma> >
724 public:
725 pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) :
726 pixel_formats_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma> >(rb)
728 this->blender().gamma(g);
732 //-----------------------------------------------------pixfmt_rgb48_gamma
733 template<class Gamma> class pixfmt_rgb48_gamma :
734 public pixel_formats_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma> >
736 public:
737 pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) :
738 pixel_formats_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma> >(rb)
740 this->blender().gamma(g);
744 //-----------------------------------------------------pixfmt_bgr48_gamma
745 template<class Gamma> class pixfmt_bgr48_gamma :
746 public pixel_formats_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma> >
748 public:
749 pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) :
750 pixel_formats_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma> >(rb)
752 this->blender().gamma(g);
759 #endif