update dev300-m57
[ooovba.git] / agg / inc / agg_pixfmt_rgba.h
blob06c36abf75104b4aa3a907745beb03576e9da904
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_RGBA_INCLUDED
25 #define AGG_PIXFMT_RGBA_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 //=========================================================multiplier_rgba
36 template<class ColorT, class Order> struct multiplier_rgba
38 typedef typename ColorT::value_type value_type;
39 typedef typename ColorT::calc_type calc_type;
41 //--------------------------------------------------------------------
42 static AGG_INLINE void premultiply(value_type* p)
44 calc_type a = p[Order::A];
45 if(a < ColorT::base_mask)
47 if(a == 0)
49 p[Order::R] = p[Order::G] = p[Order::B] = 0;
50 return;
52 p[Order::R] = value_type((p[Order::R] * a) >> ColorT::base_shift);
53 p[Order::G] = value_type((p[Order::G] * a) >> ColorT::base_shift);
54 p[Order::B] = value_type((p[Order::B] * a) >> ColorT::base_shift);
59 //--------------------------------------------------------------------
60 static AGG_INLINE void demultiply(value_type* p)
62 calc_type a = p[Order::A];
63 if(a < ColorT::base_mask)
65 if(a == 0)
67 p[Order::R] = p[Order::G] = p[Order::B] = 0;
68 return;
70 calc_type r = (calc_type(p[Order::R]) * ColorT::base_mask) / a;
71 calc_type g = (calc_type(p[Order::G]) * ColorT::base_mask) / a;
72 calc_type b = (calc_type(p[Order::B]) * ColorT::base_mask) / a;
73 p[Order::R] = value_type((r > ColorT::base_mask) ? ColorT::base_mask : r);
74 p[Order::G] = value_type((g > ColorT::base_mask) ? ColorT::base_mask : g);
75 p[Order::B] = value_type((b > ColorT::base_mask) ? ColorT::base_mask : b);
81 //=====================================================apply_gamma_dir_rgba
82 template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgba
84 public:
85 typedef typename ColorT::value_type value_type;
87 apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {}
89 AGG_INLINE void operator () (value_type* p)
91 p[Order::R] = m_gamma.dir(p[Order::R]);
92 p[Order::G] = m_gamma.dir(p[Order::G]);
93 p[Order::B] = m_gamma.dir(p[Order::B]);
96 private:
97 const GammaLut& m_gamma;
102 //=====================================================apply_gamma_inv_rgba
103 template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgba
105 public:
106 typedef typename ColorT::value_type value_type;
108 apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {}
110 AGG_INLINE void operator () (value_type* p)
112 p[Order::R] = m_gamma.inv(p[Order::R]);
113 p[Order::G] = m_gamma.inv(p[Order::G]);
114 p[Order::B] = m_gamma.inv(p[Order::B]);
117 private:
118 const GammaLut& m_gamma;
123 //=============================================================blender_rgba
124 template<class ColorT, class Order, class PixelT> struct blender_rgba
126 typedef ColorT color_type;
127 typedef PixelT pixel_type;
128 typedef Order order_type;
129 typedef typename color_type::value_type value_type;
130 typedef typename color_type::calc_type calc_type;
131 enum
133 base_shift = color_type::base_shift,
134 base_mask = color_type::base_mask
137 //--------------------------------------------------------------------
138 static AGG_INLINE void blend_pix(value_type* p,
139 unsigned cr, unsigned cg, unsigned cb,
140 unsigned alpha,
141 unsigned)
143 calc_type r = p[Order::R];
144 calc_type g = p[Order::G];
145 calc_type b = p[Order::B];
146 calc_type a = p[Order::A];
147 p[Order::R] = (value_type)(((cr - r) * alpha + (r << base_shift)) >> base_shift);
148 p[Order::G] = (value_type)(((cg - g) * alpha + (g << base_shift)) >> base_shift);
149 p[Order::B] = (value_type)(((cb - b) * alpha + (b << base_shift)) >> base_shift);
150 p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift));
155 //=========================================================blender_rgba_pre
156 template<class ColorT, class Order, class PixelT> struct blender_rgba_pre
158 typedef ColorT color_type;
159 typedef PixelT pixel_type;
160 typedef Order order_type;
161 typedef typename color_type::value_type value_type;
162 typedef typename color_type::calc_type calc_type;
163 enum
165 base_shift = color_type::base_shift,
166 base_mask = color_type::base_mask
169 //--------------------------------------------------------------------
170 static AGG_INLINE void blend_pix(value_type* p,
171 unsigned cr, unsigned cg, unsigned cb,
172 unsigned alpha,
173 unsigned cover)
175 alpha = color_type::base_mask - alpha;
176 cover = (cover + 1) << (base_shift - 8);
177 p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift);
178 p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift);
179 p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift);
180 p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift));
186 //======================================================blender_rgba_plain
187 template<class ColorT, class Order, class PixelT> struct blender_rgba_plain
189 typedef ColorT color_type;
190 typedef PixelT pixel_type;
191 typedef Order order_type;
192 typedef typename color_type::value_type value_type;
193 typedef typename color_type::calc_type calc_type;
194 enum { base_shift = color_type::base_shift };
196 //--------------------------------------------------------------------
197 static AGG_INLINE void blend_pix(value_type* p,
198 unsigned cr, unsigned cg, unsigned cb,
199 unsigned alpha,
200 unsigned)
202 if(alpha == 0) return;
203 calc_type a = p[Order::A];
204 calc_type r = p[Order::R] * a;
205 calc_type g = p[Order::G] * a;
206 calc_type b = p[Order::B] * a;
207 a = ((alpha + a) << base_shift) - alpha * a;
208 p[Order::A] = (value_type)(a >> base_shift);
209 p[Order::R] = (value_type)((((cr << base_shift) - r) * alpha + (r << base_shift)) / a);
210 p[Order::G] = (value_type)((((cg << base_shift) - g) * alpha + (g << base_shift)) / a);
211 p[Order::B] = (value_type)((((cb << base_shift) - b) * alpha + (b << base_shift)) / a);
216 //====================================================blender_rgba_wrapper
217 template<class Blender> struct blender_rgba_wrapper
219 typedef typename Blender::color_type color_type;
220 typedef typename Blender::order_type order_type;
221 typedef typename Blender::pixel_type pixel_type;
222 typedef typename color_type::value_type value_type;
223 typedef typename color_type::calc_type calc_type;
224 enum
226 base_shift = color_type::base_shift,
227 base_size = color_type::base_size,
228 base_mask = color_type::base_mask
231 //--------------------------------------------------------------------
232 static AGG_INLINE void blend_pix(value_type* p,
233 unsigned cr, unsigned cg, unsigned cb,
234 unsigned alpha,
235 unsigned cover)
237 Blender::blend_pix(p, cr, cg, cb, alpha, cover);
240 //--------------------------------------------------------------------
241 static AGG_INLINE void copy_or_blend_pix(value_type* p,
242 const color_type& c,
243 unsigned cover)
245 if (c.a)
247 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
248 if(alpha == base_mask)
250 p[order_type::R] = c.r;
251 p[order_type::G] = c.g;
252 p[order_type::B] = c.b;
253 p[order_type::A] = c.a;
255 else
257 Blender::blend_pix(p, c.r, c.g, c.b, alpha, cover);
262 //--------------------------------------------------------------------
263 static AGG_INLINE void copy_or_blend_opaque_pix(value_type* p,
264 const color_type& c,
265 unsigned cover)
267 if(cover == 255)
269 p[order_type::R] = c.r;
270 p[order_type::G] = c.g;
271 p[order_type::B] = c.b;
272 p[order_type::A] = base_mask;
274 else
276 Blender::blend_pix(p, c.r, c.g, c.b, (cover + 1) << (base_shift - 8), cover);
284 //=======================================================pixel_formats_rgba
285 template<class Blender> class pixel_formats_rgba
287 public:
288 typedef rendering_buffer::row_data row_data;
289 typedef typename Blender::color_type color_type;
290 typedef typename Blender::order_type order_type;
291 typedef typename Blender::pixel_type pixel_type;
292 typedef typename color_type::value_type value_type;
293 typedef typename color_type::calc_type calc_type;
294 typedef blender_rgba_wrapper<Blender> blender_type;
295 enum
297 base_shift = color_type::base_shift,
298 base_size = color_type::base_size,
299 base_mask = color_type::base_mask
302 //--------------------------------------------------------------------
303 pixel_formats_rgba(rendering_buffer& rb) :
304 m_rbuf(&rb)
307 //--------------------------------------------------------------------
308 AGG_INLINE unsigned width() const { return m_rbuf->width(); }
309 AGG_INLINE unsigned height() const { return m_rbuf->height(); }
311 //--------------------------------------------------------------------
312 AGG_INLINE color_type pixel(int x, int y) const
314 const value_type* p = (value_type*)m_rbuf->row(y) + (x << 2);
315 return color_type(p[order_type::R],
316 p[order_type::G],
317 p[order_type::B],
318 p[order_type::A]);
321 //--------------------------------------------------------------------
322 row_data span(int x, int y) const
324 return row_data(x,
325 width() - 1,
326 m_rbuf->row(y) + x * 4 * sizeof(value_type));
329 //--------------------------------------------------------------------
330 AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
332 value_type* p = (value_type*)m_rbuf->row(y) + (x << 2);
333 p[order_type::R] = c.r;
334 p[order_type::G] = c.g;
335 p[order_type::B] = c.b;
336 p[order_type::A] = c.a;
339 //--------------------------------------------------------------------
340 AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
342 blender_type::copy_or_blend_pix((value_type*)m_rbuf->row(y) + (x << 2), c, cover);
346 //--------------------------------------------------------------------
347 AGG_INLINE void copy_hline(int x, int y,
348 unsigned len,
349 const color_type& c)
351 value_type* p = (value_type*)m_rbuf->row(y) + (x << 2);
352 pixel_type v;
353 ((value_type*)&v)[order_type::R] = c.r;
354 ((value_type*)&v)[order_type::G] = c.g;
355 ((value_type*)&v)[order_type::B] = c.b;
356 ((value_type*)&v)[order_type::A] = c.a;
359 *(pixel_type*)p = v;
360 p += 4;
362 while(--len);
366 //--------------------------------------------------------------------
367 AGG_INLINE void copy_vline(int x, int y,
368 unsigned len,
369 const color_type& c)
371 value_type* p = (value_type*)m_rbuf->row(y) + (x << 2);
372 pixel_type v;
373 ((value_type*)&v)[order_type::R] = c.r;
374 ((value_type*)&v)[order_type::G] = c.g;
375 ((value_type*)&v)[order_type::B] = c.b;
376 ((value_type*)&v)[order_type::A] = c.a;
379 *(pixel_type*)p = v;
380 p = (value_type*)m_rbuf->next_row(p);
382 while(--len);
386 //--------------------------------------------------------------------
387 void blend_hline(int x, int y,
388 unsigned len,
389 const color_type& c,
390 int8u cover)
392 if (c.a)
394 value_type* p = (value_type*)m_rbuf->row(y) + (x << 2);
395 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
396 if(alpha == base_mask)
398 pixel_type v;
399 ((value_type*)&v)[order_type::R] = c.r;
400 ((value_type*)&v)[order_type::G] = c.g;
401 ((value_type*)&v)[order_type::B] = c.b;
402 ((value_type*)&v)[order_type::A] = c.a;
405 *(pixel_type*)p = v;
406 p += 4;
408 while(--len);
410 else
414 blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover);
415 p += 4;
417 while(--len);
423 //--------------------------------------------------------------------
424 void blend_vline(int x, int y,
425 unsigned len,
426 const color_type& c,
427 int8u cover)
429 if (c.a)
431 value_type* p = (value_type*)m_rbuf->row(y) + (x << 2);
432 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
433 if(alpha == base_mask)
435 pixel_type v;
436 ((value_type*)&v)[order_type::R] = c.r;
437 ((value_type*)&v)[order_type::G] = c.g;
438 ((value_type*)&v)[order_type::B] = c.b;
439 ((value_type*)&v)[order_type::A] = c.a;
442 *(pixel_type*)p = v;
443 p = (value_type*)m_rbuf->next_row(p);
445 while(--len);
447 else
451 blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover);
452 p = (value_type*)m_rbuf->next_row(p);
454 while(--len);
460 //--------------------------------------------------------------------
461 void blend_solid_hspan(int x, int y,
462 unsigned len,
463 const color_type& c,
464 const int8u* covers)
466 if (c.a)
468 value_type* p = (value_type*)m_rbuf->row(y) + (x << 2);
471 calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
472 if(alpha == base_mask)
474 p[order_type::R] = c.r;
475 p[order_type::G] = c.g;
476 p[order_type::B] = c.b;
477 p[order_type::A] = base_mask;
479 else
481 blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers);
483 p += 4;
484 ++covers;
486 while(--len);
491 //--------------------------------------------------------------------
492 void blend_solid_vspan(int x, int y,
493 unsigned len,
494 const color_type& c,
495 const int8u* covers)
497 if (c.a)
499 value_type* p = (value_type*)m_rbuf->row(y) + (x << 2);
502 calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
503 if(alpha == base_mask)
505 p[order_type::R] = c.r;
506 p[order_type::G] = c.g;
507 p[order_type::B] = c.b;
508 p[order_type::A] = base_mask;
510 else
512 blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers);
514 p = (value_type*)m_rbuf->next_row(p);
515 ++covers;
517 while(--len);
522 //--------------------------------------------------------------------
523 void blend_color_hspan(int x, int y,
524 unsigned len,
525 const color_type* colors,
526 const int8u* covers,
527 int8u cover)
529 value_type* p = (value_type*)m_rbuf->row(y) + (x << 2);
530 if(covers)
534 blender_type::copy_or_blend_pix(p, *colors++, *covers++);
535 p += 4;
537 while(--len);
539 else
541 if(cover == 255)
545 if(colors->a == base_mask)
547 p[order_type::R] = colors->r;
548 p[order_type::G] = colors->g;
549 p[order_type::B] = colors->b;
550 p[order_type::A] = base_mask;
552 else
554 blender_type::copy_or_blend_pix(p, *colors, 255);
556 p += 4;
557 ++colors;
559 while(--len);
561 else
565 blender_type::copy_or_blend_pix(p, *colors++, cover);
566 p += 4;
568 while(--len);
575 //--------------------------------------------------------------------
576 void blend_color_vspan(int x, int y,
577 unsigned len,
578 const color_type* colors,
579 const int8u* covers,
580 int8u cover)
582 value_type* p = (value_type*)m_rbuf->row(y) + (x << 2);
583 if(covers)
587 blender_type::copy_or_blend_pix(p, *colors++, *covers++);
588 p = (value_type*)m_rbuf->next_row(p);
590 while(--len);
592 else
594 if(cover == 255)
598 if(colors->a == base_mask)
600 p[order_type::R] = colors->r;
601 p[order_type::G] = colors->g;
602 p[order_type::B] = colors->b;
603 p[order_type::A] = base_mask;
605 else
607 blender_type::copy_or_blend_pix(p, *colors, 255);
609 p = (value_type*)m_rbuf->next_row(p);
610 ++colors;
612 while(--len);
614 else
618 blender_type::copy_or_blend_pix(p, *colors++, cover);
619 p = (value_type*)m_rbuf->next_row(p);
621 while(--len);
627 //--------------------------------------------------------------------
628 void blend_opaque_color_hspan(int x, int y,
629 unsigned len,
630 const color_type* colors,
631 const int8u* covers,
632 int8u cover)
634 value_type* p = (value_type*)m_rbuf->row(y) + (x << 2);
635 if(covers)
639 blender_type::copy_or_blend_opaque_pix(p, *colors++, *covers++);
640 p += 4;
642 while(--len);
644 else
646 if(cover == 255)
650 p[order_type::R] = colors->r;
651 p[order_type::G] = colors->g;
652 p[order_type::B] = colors->b;
653 p[order_type::A] = base_mask;
654 p += 4;
655 ++colors;
657 while(--len);
659 else
663 blender_type::copy_or_blend_opaque_pix(p, *colors++, cover);
664 p += 4;
666 while(--len);
672 //--------------------------------------------------------------------
673 void blend_opaque_color_vspan(int x, int y,
674 unsigned len,
675 const color_type* colors,
676 const int8u* covers,
677 int8u cover)
679 value_type* p = (value_type*)m_rbuf->row(y) + (x << 2);
680 if(covers)
684 blender_type::copy_or_blend_opaque_pix(p, *colors++, *covers++);
685 p = (value_type*)m_rbuf->next_row(p);
687 while(--len);
689 else
691 if(cover == 255)
695 p[order_type::R] = colors->r;
696 p[order_type::G] = colors->g;
697 p[order_type::B] = colors->b;
698 p[order_type::A] = base_mask;
699 p = (value_type*)m_rbuf->next_row(p);
700 ++colors;
702 while(--len);
704 else
708 blender_type::copy_or_blend_opaque_pix(p, *colors++, cover);
709 p = (value_type*)m_rbuf->next_row(p);
711 while(--len);
717 //--------------------------------------------------------------------
718 template<class Function> void for_each_pixel(Function f)
720 unsigned y;
721 for(y = 0; y < height(); ++y)
723 unsigned len = width();
724 value_type* p = (value_type*)m_rbuf->row(y);
727 f(p);
728 p += 4;
730 while(--len);
734 //--------------------------------------------------------------------
735 void premultiply()
737 for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply);
740 //--------------------------------------------------------------------
741 void demultiply()
743 for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply);
746 //--------------------------------------------------------------------
747 template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
749 for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g));
752 //--------------------------------------------------------------------
753 template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
755 for_each_pixel(apply_gamma_inv_rgba<color_type, order_type, GammaLut>(g));
758 //--------------------------------------------------------------------
759 void copy_from(const rendering_buffer& from,
760 int xdst, int ydst,
761 int xsrc, int ysrc,
762 unsigned len)
764 memmove((value_type*)m_rbuf->row(ydst) + xdst * 4,
765 (value_type*)from.row(ysrc) + xsrc * 4,
766 sizeof(value_type) * 4 * len);
770 //--------------------------------------------------------------------
771 template<class SrcPixelFormatRenderer>
772 void blend_from(const SrcPixelFormatRenderer& from,
773 const int8u* psrc_,
774 int xdst, int ydst,
775 int xsrc, int ysrc,
776 unsigned len)
778 typedef typename SrcPixelFormatRenderer::order_type src_order;
780 const value_type* psrc = (const value_type*)psrc_;
781 value_type* pdst = (value_type*)m_rbuf->row(ydst) + (xdst << 2);
782 int incp = 4;
783 if(xdst > xsrc)
785 psrc += (len-1) << 2;
786 pdst += (len-1) << 2;
787 incp = -4;
791 value_type alpha = psrc[src_order::A];
793 if(alpha)
795 if(alpha == base_mask)
797 pdst[order_type::R] = psrc[src_order::R];
798 pdst[order_type::G] = psrc[src_order::G];
799 pdst[order_type::B] = psrc[src_order::B];
800 pdst[order_type::A] = psrc[src_order::A];
802 else
804 blender_type::blend_pix(pdst,
805 psrc[src_order::R],
806 psrc[src_order::G],
807 psrc[src_order::B],
808 alpha,
809 255);
812 psrc += incp;
813 pdst += incp;
815 while(--len);
818 private:
819 rendering_buffer* m_rbuf;
825 //================================================pixfmt_custom_rbuf_rgba
826 template<class Blender, class RenBuf> class pixfmt_custom_rbuf_rgba
828 public:
829 typedef typename Blender::color_type color_type;
830 typedef typename Blender::order_type order_type;
831 typedef typename Blender::pixel_type pixel_type;
832 typedef typename color_type::value_type value_type;
833 typedef typename color_type::calc_type calc_type;
834 typedef blender_rgba_wrapper<Blender> blender_type;
835 enum
837 base_shift = color_type::base_shift,
838 base_size = color_type::base_size,
839 base_mask = color_type::base_mask
842 typedef RenBuf rbuf_type;
843 typedef typename rbuf_type::row_data row_data;
845 //--------------------------------------------------------------------
846 pixfmt_custom_rbuf_rgba(rbuf_type& rb) : m_rbuf(&rb) {}
848 //--------------------------------------------------------------------
849 unsigned width() const { return m_rbuf->width(); }
850 unsigned height() const { return m_rbuf->height(); }
852 //--------------------------------------------------------------------
853 color_type pixel(int x, int y) const
855 const value_type* p = m_rbuf->span_ptr(x, y, 1);
856 return p ? color_type(p[order_type::R],
857 p[order_type::G],
858 p[order_type::B],
859 p[order_type::A]) :
860 color_type::no_color();
863 //--------------------------------------------------------------------
864 row_data span(int x, int y) const
866 return m_rbuf->span(x, y);
869 //--------------------------------------------------------------------
870 void copy_pixel(int x, int y, const color_type& c)
872 int8u* p = m_rbuf->span_ptr(x, y, 1);
873 p[order_type::R] = c.r;
874 p[order_type::G] = c.g;
875 p[order_type::B] = c.b;
876 p[order_type::A] = c.b;
879 //--------------------------------------------------------------------
880 void blend_pixel(int x, int y, const color_type& c, int8u cover)
882 blender_type::copy_or_blend_pix((value_type*)m_rbuf->span_ptr(x, y, 1), c, cover);
885 //--------------------------------------------------------------------
886 void copy_hline(int x, int y, unsigned len, const color_type& c)
888 value_type* p = (value_type*)m_rbuf->span_ptr(x, y, len);
889 pixel_type v;
890 ((value_type*)&v)[order_type::R] = c.r;
891 ((value_type*)&v)[order_type::G] = c.g;
892 ((value_type*)&v)[order_type::B] = c.b;
893 ((value_type*)&v)[order_type::A] = c.a;
896 *(pixel_type*)p = v;
897 p += 4;
899 while(--len);
902 //--------------------------------------------------------------------
903 void copy_vline(int x, int y, unsigned len, const color_type& c)
905 pixel_type v;
906 ((value_type*)&v)[order_type::R] = c.r;
907 ((value_type*)&v)[order_type::G] = c.g;
908 ((value_type*)&v)[order_type::B] = c.b;
909 ((value_type*)&v)[order_type::A] = c.a;
912 *(pixel_type*)(m_rbuf->span_ptr(x, y++, 1)) = v;
914 while(--len);
917 //--------------------------------------------------------------------
918 void blend_hline(int x, int y, unsigned len,
919 const color_type& c, int8u cover)
921 if (c.a)
923 value_type* p = (value_type*)m_rbuf->span_ptr(x, y, len);
924 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
925 if(alpha == base_mask)
927 pixel_type v;
928 ((value_type*)&v)[order_type::R] = c.r;
929 ((value_type*)&v)[order_type::G] = c.g;
930 ((value_type*)&v)[order_type::B] = c.b;
931 ((value_type*)&v)[order_type::A] = c.a;
934 *(pixel_type*)p = v;
935 p += 4;
937 while(--len);
939 else
943 blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover);
944 p += 4;
946 while(--len);
951 //--------------------------------------------------------------------
952 void blend_vline(int x, int y, unsigned len,
953 const color_type& c, int8u cover)
955 if (c.a)
957 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
958 if(alpha == base_mask)
960 pixel_type v;
961 ((value_type*)&v)[order_type::R] = c.r;
962 ((value_type*)&v)[order_type::G] = c.g;
963 ((value_type*)&v)[order_type::B] = c.b;
964 ((value_type*)&v)[order_type::A] = c.a;
967 *(pixel_type*)(m_rbuf->span_ptr(x, y++, 1)) = v;
969 while(--len);
971 else
975 blender_type::blend_pix(*(pixel_type*)m_rbuf->span_ptr(x, y++, 1),
976 c.r, c.g, c.b, alpha, cover);
978 while(--len);
984 //--------------------------------------------------------------------
985 void blend_solid_hspan(int x, int y, unsigned len,
986 const color_type& c, const int8u* covers)
988 value_type* p = (value_type*)m_rbuf->span_ptr(x, y, len);
991 blender_type::copy_or_blend_pix(p, c, *covers++);
992 p += 4;
994 while(--len);
999 //--------------------------------------------------------------------
1000 void blend_solid_vspan(int x, int y, unsigned len,
1001 const color_type& c, const int8u* covers)
1005 blender_type::copy_or_blend_pix((value_type*)m_rbuf->span_ptr(x, y++, 1),
1007 *covers++);
1009 while(--len);
1013 //--------------------------------------------------------------------
1014 void blend_color_hspan(int x, int y, unsigned len,
1015 const color_type* colors,
1016 const int8u* covers,
1017 int8u cover)
1019 value_type* p = (value_type*)m_rbuf->span_ptr(x, y, len);
1022 blender_type::copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
1023 p += 4;
1025 while(--len);
1029 //--------------------------------------------------------------------
1030 void blend_color_vspan(int x, int y, unsigned len,
1031 const color_type* colors,
1032 const int8u* covers,
1033 int8u cover)
1037 blender_type::copy_or_blend_pix((value_type*)m_rbuf->span_ptr(x, y++, 1),
1038 *colors++, covers ? *covers++ : cover);
1040 while(--len);
1044 //--------------------------------------------------------------------
1045 void blend_opaque_color_hspan(int x, int y,
1046 unsigned len,
1047 const color_type* colors,
1048 const int8u* covers,
1049 int8u cover)
1051 value_type* p = (value_type*)m_rbuf->span_ptr(x, y, len);
1052 if(covers)
1056 blender_type::copy_or_blend_opaque_pix(p, *colors++, *covers++);
1057 p += 4;
1059 while(--len);
1061 else
1063 if(cover == 255)
1067 p[order_type::R] = colors->r;
1068 p[order_type::G] = colors->g;
1069 p[order_type::B] = colors->b;
1070 p[order_type::A] = base_mask;
1071 p += 4;
1072 ++colors;
1074 while(--len);
1076 else
1080 blender_type::copy_or_blend_opaque_pix(p, *colors++, cover);
1081 p += 4;
1083 while(--len);
1089 //--------------------------------------------------------------------
1090 void blend_opaque_color_vspan(int x, int y,
1091 unsigned len,
1092 const color_type* colors,
1093 const int8u* covers,
1094 int8u cover)
1096 if(covers)
1100 blender_type::copy_or_blend_opaque_pix((value_type*)m_rbuf->span_ptr(x, y++, 1),
1101 *colors++, *covers++);
1103 while(--len);
1105 else
1107 if(cover == 255)
1111 value_type* p = (value_type*)m_rbuf->span_ptr(x, y++, 1);
1112 p[order_type::R] = colors->r;
1113 p[order_type::G] = colors->g;
1114 p[order_type::B] = colors->b;
1115 p[order_type::A] = base_mask;
1116 ++colors;
1118 while(--len);
1120 else
1124 blender_type::copy_or_blend_opaque_pix((value_type*)m_rbuf->span_ptr(x, y++, 1),
1125 *colors++, cover);
1127 while(--len);
1134 //--------------------------------------------------------------------
1135 template<class Function> void for_each_pixel(Function f)
1137 unsigned y;
1138 for(y = 0; y < height(); ++y)
1140 row_data sp = span(0, y);
1141 if(sp.ptr)
1143 value_type* p = (value_type*)sp.ptr;
1144 while(sp.x1 <= sp.x2)
1146 f(p);
1147 p += 4;
1148 ++sp.x1;
1155 //--------------------------------------------------------------------
1156 void premultiply()
1158 for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply);
1161 //--------------------------------------------------------------------
1162 void demultiply()
1164 for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply);
1167 //--------------------------------------------------------------------
1168 template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
1170 for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g));
1173 //--------------------------------------------------------------------
1174 template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
1176 for_each_pixel(apply_gamma_inv_rgba<color_type, order_type, GammaLut>(g));
1179 //--------------------------------------------------------------------
1180 template<class RenBuf2> void copy_from(const RenBuf2& from,
1181 int xdst, int ydst,
1182 int xsrc, int ysrc,
1183 unsigned len)
1185 const int8u* p = from.row(ysrc);
1186 if(p)
1188 p += xsrc * 4 * sizeof(value_type);
1189 memmove(m_rbuf->span_ptr(xdst, ydst, len),
1191 len * 4 * sizeof(value_type));
1197 //--------------------------------------------------------------------
1198 template<class SrcPixelFormatRenderer>
1199 void blend_from(const SrcPixelFormatRenderer& from,
1200 const int8u* psrc_,
1201 int xdst, int ydst,
1202 int xsrc, int ysrc,
1203 unsigned len)
1205 typedef typename SrcPixelFormatRenderer::order_type src_order;
1206 const value_type* psrc = (const value_type*)psrc_;
1207 value_type* pdst = (value_type*)m_rbuf->span_ptr(xdst, ydst, len);
1209 int incp = 4;
1210 if(xdst > xsrc)
1212 psrc += (len-1) << 2;
1213 pdst += (len-1) << 2;
1214 incp = -4;
1218 value_type alpha = psrc[src_order::A];
1220 if(alpha)
1222 if(alpha == base_mask)
1224 pdst[order_type::R] = psrc[src_order::R];
1225 pdst[order_type::G] = psrc[src_order::G];
1226 pdst[order_type::B] = psrc[src_order::B];
1227 pdst[order_type::A] = psrc[src_order::A];
1229 else
1231 blender_type::blend_pix(pdst,
1232 psrc[src_order::R],
1233 psrc[src_order::G],
1234 psrc[src_order::B],
1235 alpha,
1236 255);
1239 psrc += incp;
1240 pdst += incp;
1242 while(--len);
1246 private:
1247 rbuf_type* m_rbuf;
1256 //-----------------------------------------------------------------------
1257 typedef blender_rgba<rgba8, order_rgba, int32u> blender_rgba32; //----blender_rgba32
1258 typedef blender_rgba<rgba8, order_argb, int32u> blender_argb32; //----blender_argb32
1259 typedef blender_rgba<rgba8, order_abgr, int32u> blender_abgr32; //----blender_abgr32
1260 typedef blender_rgba<rgba8, order_bgra, int32u> blender_bgra32; //----blender_bgra32
1262 typedef blender_rgba_pre<rgba8, order_rgba, int32u> blender_rgba32_pre; //----blender_rgba32_pre
1263 typedef blender_rgba_pre<rgba8, order_argb, int32u> blender_argb32_pre; //----blender_argb32_pre
1264 typedef blender_rgba_pre<rgba8, order_abgr, int32u> blender_abgr32_pre; //----blender_abgr32_pre
1265 typedef blender_rgba_pre<rgba8, order_bgra, int32u> blender_bgra32_pre; //----blender_bgra32_pre
1267 typedef blender_rgba_plain<rgba8, order_rgba, int32u> blender_rgba32_plain; //----blender_rgba32_plain
1268 typedef blender_rgba_plain<rgba8, order_argb, int32u> blender_argb32_plain; //----blender_argb32_plain
1269 typedef blender_rgba_plain<rgba8, order_abgr, int32u> blender_abgr32_plain; //----blender_abgr32_plain
1270 typedef blender_rgba_plain<rgba8, order_bgra, int32u> blender_bgra32_plain; //----blender_bgra32_plain
1272 struct pixel64_type { int16u c[4]; };
1273 typedef blender_rgba<rgba16, order_rgba, pixel64_type> blender_rgba64; //----blender_rgba64
1274 typedef blender_rgba<rgba16, order_argb, pixel64_type> blender_argb64; //----blender_argb64
1275 typedef blender_rgba<rgba16, order_abgr, pixel64_type> blender_abgr64; //----blender_abgr64
1276 typedef blender_rgba<rgba16, order_bgra, pixel64_type> blender_bgra64; //----blender_bgra64
1278 typedef blender_rgba_pre<rgba16, order_rgba, pixel64_type> blender_rgba64_pre; //----blender_rgba64_pre
1279 typedef blender_rgba_pre<rgba16, order_argb, pixel64_type> blender_argb64_pre; //----blender_argb64_pre
1280 typedef blender_rgba_pre<rgba16, order_abgr, pixel64_type> blender_abgr64_pre; //----blender_abgr64_pre
1281 typedef blender_rgba_pre<rgba16, order_bgra, pixel64_type> blender_bgra64_pre; //----blender_bgra64_pre
1284 //-----------------------------------------------------------------------
1285 typedef pixel_formats_rgba<blender_rgba32> pixfmt_rgba32; //----pixfmt_rgba32
1286 typedef pixel_formats_rgba<blender_argb32> pixfmt_argb32; //----pixfmt_argb32
1287 typedef pixel_formats_rgba<blender_abgr32> pixfmt_abgr32; //----pixfmt_abgr32
1288 typedef pixel_formats_rgba<blender_bgra32> pixfmt_bgra32; //----pixfmt_bgra32
1290 typedef pixel_formats_rgba<blender_rgba32_pre> pixfmt_rgba32_pre; //----pixfmt_rgba32_pre
1291 typedef pixel_formats_rgba<blender_argb32_pre> pixfmt_argb32_pre; //----pixfmt_argb32_pre
1292 typedef pixel_formats_rgba<blender_abgr32_pre> pixfmt_abgr32_pre; //----pixfmt_abgr32_pre
1293 typedef pixel_formats_rgba<blender_bgra32_pre> pixfmt_bgra32_pre; //----pixfmt_bgra32_pre
1295 typedef pixel_formats_rgba<blender_rgba32_plain> pixfmt_rgba32_plain; //----pixfmt_rgba32_plain
1296 typedef pixel_formats_rgba<blender_argb32_plain> pixfmt_argb32_plain; //----pixfmt_argb32_plain
1297 typedef pixel_formats_rgba<blender_abgr32_plain> pixfmt_abgr32_plain; //----pixfmt_abgr32_plain
1298 typedef pixel_formats_rgba<blender_bgra32_plain> pixfmt_bgra32_plain; //----pixfmt_bgra32_plain
1300 typedef pixel_formats_rgba<blender_rgba64> pixfmt_rgba64; //----pixfmt_rgba64
1301 typedef pixel_formats_rgba<blender_argb64> pixfmt_argb64; //----pixfmt_argb64
1302 typedef pixel_formats_rgba<blender_abgr64> pixfmt_abgr64; //----pixfmt_abgr64
1303 typedef pixel_formats_rgba<blender_bgra64> pixfmt_bgra64; //----pixfmt_bgra64
1305 typedef pixel_formats_rgba<blender_rgba64_pre> pixfmt_rgba64_pre; //----pixfmt_rgba64_pre
1306 typedef pixel_formats_rgba<blender_argb64_pre> pixfmt_argb64_pre; //----pixfmt_argb64_pre
1307 typedef pixel_formats_rgba<blender_abgr64_pre> pixfmt_abgr64_pre; //----pixfmt_abgr64_pre
1308 typedef pixel_formats_rgba<blender_bgra64_pre> pixfmt_bgra64_pre; //----pixfmt_bgra64_pre
1311 #endif