vfs: check userland buffers before reading them.
[haiku.git] / headers / libs / agg / agg_pixfmt_rgb.h
blob51450cf12e8d12e434a9ebcabc891c30d517037b
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
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_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,
88 unsigned alpha,
89 unsigned cover=0)
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,
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);
120 //--------------------------------------------------------------------
121 static AGG_INLINE void blend_pix(value_type* p,
122 unsigned cr, unsigned cg, unsigned cb,
123 unsigned alpha)
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
138 public:
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,
153 unsigned alpha,
154 unsigned cover=0)
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);
164 private:
165 const gamma_type* m_gamma;
171 //==================================================pixfmt_alpha_blend_rgb
172 template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb
174 public:
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;
182 enum base_scale_e
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
190 private:
191 //--------------------------------------------------------------------
192 AGG_INLINE void copy_or_blend_pix(value_type* p,
193 const color_type& c,
194 unsigned cover)
196 if (c.a)
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;
205 else
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,
214 const color_type& c)
216 if (c.a)
218 if(c.a == base_mask)
220 p[order_type::R] = c.r;
221 p[order_type::G] = c.g;
222 p[order_type::B] = c.b;
224 else
226 m_blender.blend_pix(p, c.r, c.g, c.b, c.a);
232 public:
233 //--------------------------------------------------------------------
234 pixfmt_alpha_blend_rgb(rbuf_type& rb) :
235 m_rbuf(&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),
248 (r.x2 - r.x1) + 1,
249 (r.y2 - r.y1) + 1,
250 stride);
251 return true;
253 return false;
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],
293 p[order_type::G],
294 p[order_type::B]);
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,
315 unsigned len,
316 const color_type& c)
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;
324 p += 3;
326 while(--len);
330 //--------------------------------------------------------------------
331 AGG_INLINE void copy_vline(int x, int y,
332 unsigned len,
333 const color_type& c)
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;
343 while(--len);
347 //--------------------------------------------------------------------
348 void blend_hline(int x, int y,
349 unsigned len,
350 const color_type& c,
351 int8u cover)
353 if (c.a)
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;
366 p += 3;
368 while(--len);
370 else
374 m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
375 p += 3;
377 while(--len);
383 //--------------------------------------------------------------------
384 void blend_vline(int x, int y,
385 unsigned len,
386 const color_type& c,
387 int8u cover)
389 if (c.a)
391 value_type* p;
392 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
393 if(alpha == base_mask)
397 p = (value_type*)
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;
404 while(--len);
406 else
410 p = (value_type*)
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);
415 while(--len);
421 //--------------------------------------------------------------------
422 void blend_solid_hspan(int x, int y,
423 unsigned len,
424 const color_type& c,
425 const int8u* covers)
427 if (c.a)
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;
441 else
443 m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
445 p += 3;
446 ++covers;
448 while(--len);
453 //--------------------------------------------------------------------
454 void blend_solid_vspan(int x, int y,
455 unsigned len,
456 const color_type& c,
457 const int8u* covers)
459 if (c.a)
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;
473 else
475 m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
477 ++covers;
479 while(--len);
484 //--------------------------------------------------------------------
485 void copy_color_hspan(int x, int y,
486 unsigned len,
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;
497 ++colors;
498 p += 3;
500 while(--len);
504 //--------------------------------------------------------------------
505 void copy_color_vspan(int x, int y,
506 unsigned len,
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;
516 ++colors;
518 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*)
530 m_rbuf->row_ptr(x, y, len) + x + x + x;
532 if(covers)
536 copy_or_blend_pix(p, *colors++, *covers++);
537 p += 3;
539 while(--len);
541 else
543 if(cover == 255)
547 copy_or_blend_pix(p, *colors++);
548 p += 3;
550 while(--len);
552 else
556 copy_or_blend_pix(p, *colors++, cover);
557 p += 3;
559 while(--len);
566 //--------------------------------------------------------------------
567 void blend_color_vspan(int x, int y,
568 unsigned len,
569 const color_type* colors,
570 const int8u* covers,
571 int8u cover)
573 value_type* p;
574 if(covers)
578 p = (value_type*)
579 m_rbuf->row_ptr(x, y++, 1) + x + x + x;
581 copy_or_blend_pix(p, *colors++, *covers++);
583 while(--len);
585 else
587 if(cover == 255)
591 p = (value_type*)
592 m_rbuf->row_ptr(x, y++, 1) + x + x + x;
594 copy_or_blend_pix(p, *colors++);
596 while(--len);
598 else
602 p = (value_type*)
603 m_rbuf->row_ptr(x, y++, 1) + x + x + x;
605 copy_or_blend_pix(p, *colors++, cover);
607 while(--len);
612 //--------------------------------------------------------------------
613 template<class Function> void for_each_pixel(Function f)
615 unsigned y;
616 for(y = 0; y < height(); ++y)
618 row_data r = m_rbuf->row(y);
619 if(r.ptr)
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;
626 f(p);
627 p += 3;
629 while(--len);
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,
649 int xdst, int ydst,
650 int xsrc, int ysrc,
651 unsigned len)
653 const int8u* p = from.row_ptr(ysrc);
654 if(p)
656 memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
657 p + xsrc * pix_width,
658 len * pix_width);
663 //--------------------------------------------------------------------
664 template<class SrcPixelFormatRenderer>
665 void blend_from(const SrcPixelFormatRenderer& from,
666 int xdst, int ydst,
667 int xsrc, int ysrc,
668 unsigned len,
669 int8u cover)
671 typedef typename SrcPixelFormatRenderer::order_type src_order;
673 const value_type* psrc = (const value_type*)from.row_ptr(ysrc);
674 if(psrc)
676 psrc += xsrc * 4;
677 value_type* pdst =
678 (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
680 if(cover == 255)
684 value_type alpha = psrc[src_order::A];
685 if(alpha)
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];
693 else
695 m_blender.blend_pix(pdst,
696 psrc[src_order::R],
697 psrc[src_order::G],
698 psrc[src_order::B],
699 alpha);
702 psrc += 4;
703 pdst += 3;
705 while(--len);
707 else
709 color_type color;
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);
717 psrc += 4;
718 pdst += 3;
720 while(--len);
725 private:
726 rbuf_type* m_rbuf;
727 Blender m_blender;
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>
744 public:
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>
756 public:
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>
768 public:
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>
780 public:
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);
791 #endif