Anti-Grain Geometry Tutorial
agg_pixfmt_rgb.h
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 //----------------------------------------------------------------------------
15 //
16 // Adaptation for high precision colors has been sponsored by
17 // Liberty Technology Systems, Inc., visit http://lib-sys.com
18 //
19 // Liberty Technology Systems, Inc. is the provider of
20 // PostScript and PDF technology for software developers.
21 //
22 //----------------------------------------------------------------------------
23 
24 #ifndef AGG_PIXFMT_RGB_INCLUDED
25 #define AGG_PIXFMT_RGB_INCLUDED
26 
27 #include <cstring>
28 #include "agg_pixfmt_base.h"
29 #include "agg_rendering_buffer.h"
30 
31 namespace agg
32 {
33 
34  //=====================================================apply_gamma_dir_rgb
35  template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgb
36  {
37  public:
38  typedef typename ColorT::value_type value_type;
39 
40  apply_gamma_dir_rgb(const GammaLut& gamma) : m_gamma(gamma) {}
41 
42  AGG_INLINE void operator () (value_type* p)
43  {
44  p[Order::R] = m_gamma.dir(p[Order::R]);
45  p[Order::G] = m_gamma.dir(p[Order::G]);
46  p[Order::B] = m_gamma.dir(p[Order::B]);
47  }
48 
49  private:
50  const GammaLut& m_gamma;
51  };
52 
53 
54 
55  //=====================================================apply_gamma_inv_rgb
56  template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgb
57  {
58  public:
59  typedef typename ColorT::value_type value_type;
60 
61  apply_gamma_inv_rgb(const GammaLut& gamma) : m_gamma(gamma) {}
62 
63  AGG_INLINE void operator () (value_type* p)
64  {
65  p[Order::R] = m_gamma.inv(p[Order::R]);
66  p[Order::G] = m_gamma.inv(p[Order::G]);
67  p[Order::B] = m_gamma.inv(p[Order::B]);
68  }
69 
70  private:
71  const GammaLut& m_gamma;
72  };
73 
74 
75  //=========================================================blender_rgb
76  template<class ColorT, class Order>
77  struct blender_rgb
78  {
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  typedef typename color_type::long_type long_type;
84 
85  // Blend pixels using the non-premultiplied form of Alvy-Ray Smith's
86  // compositing function. Since the render buffer is opaque we skip the
87  // initial premultiply and final demultiply.
88 
89  //--------------------------------------------------------------------
90  static AGG_INLINE void blend_pix(value_type* p,
91  value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover)
92  {
93  blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover));
94  }
95 
96  //--------------------------------------------------------------------
97  static AGG_INLINE void blend_pix(value_type* p,
98  value_type cr, value_type cg, value_type cb, value_type alpha)
99  {
100  p[Order::R] = color_type::lerp(p[Order::R], cr, alpha);
101  p[Order::G] = color_type::lerp(p[Order::G], cg, alpha);
102  p[Order::B] = color_type::lerp(p[Order::B], cb, alpha);
103  }
104  };
105 
106  //======================================================blender_rgb_pre
107  template<class ColorT, class Order>
109  {
110  typedef ColorT color_type;
111  typedef Order order_type;
112  typedef typename color_type::value_type value_type;
113  typedef typename color_type::calc_type calc_type;
114  typedef typename color_type::long_type long_type;
115 
116  // Blend pixels using the premultiplied form of Alvy-Ray Smith's
117  // compositing function.
118 
119  //--------------------------------------------------------------------
120  static AGG_INLINE void blend_pix(value_type* p,
121  value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover)
122  {
123  blend_pix(p,
124  color_type::mult_cover(cr, cover),
125  color_type::mult_cover(cg, cover),
126  color_type::mult_cover(cb, cover),
127  color_type::mult_cover(alpha, cover));
128  }
129 
130  //--------------------------------------------------------------------
131  static AGG_INLINE void blend_pix(value_type* p,
132  value_type cr, value_type cg, value_type cb, value_type alpha)
133  {
134  p[Order::R] = color_type::prelerp(p[Order::R], cr, alpha);
135  p[Order::G] = color_type::prelerp(p[Order::G], cg, alpha);
136  p[Order::B] = color_type::prelerp(p[Order::B], cb, alpha);
137  }
138  };
139 
140  //===================================================blender_rgb_gamma
141  template<class ColorT, class Order, class Gamma>
142  class blender_rgb_gamma : public blender_base<ColorT, Order>
143  {
144  public:
145  typedef ColorT color_type;
146  typedef Order order_type;
147  typedef Gamma gamma_type;
148  typedef typename color_type::value_type value_type;
149  typedef typename color_type::calc_type calc_type;
150  typedef typename color_type::long_type long_type;
151 
152  //--------------------------------------------------------------------
153  blender_rgb_gamma() : m_gamma(0) {}
154  void gamma(const gamma_type& g) { m_gamma = &g; }
155 
156  //--------------------------------------------------------------------
157  AGG_INLINE void blend_pix(value_type* p,
158  value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover)
159  {
160  blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover));
161  }
162 
163  //--------------------------------------------------------------------
164  AGG_INLINE void blend_pix(value_type* p,
165  value_type cr, value_type cg, value_type cb, value_type alpha)
166  {
167  calc_type r = m_gamma->dir(p[Order::R]);
168  calc_type g = m_gamma->dir(p[Order::G]);
169  calc_type b = m_gamma->dir(p[Order::B]);
170  p[Order::R] = m_gamma->inv(color_type::downscale((m_gamma->dir(cr) - r) * alpha) + r);
171  p[Order::G] = m_gamma->inv(color_type::downscale((m_gamma->dir(cg) - g) * alpha) + g);
172  p[Order::B] = m_gamma->inv(color_type::downscale((m_gamma->dir(cb) - b) * alpha) + b);
173  }
174 
175  private:
176  const gamma_type* m_gamma;
177  };
178 
179 
180  //==================================================pixfmt_alpha_blend_rgb
181  template<class Blender, class RenBuf, unsigned Step, unsigned Offset = 0>
183  {
184  public:
186  typedef RenBuf rbuf_type;
187  typedef Blender blender_type;
188  typedef typename rbuf_type::row_data row_data;
189  typedef typename blender_type::color_type color_type;
190  typedef typename blender_type::order_type order_type;
191  typedef typename color_type::value_type value_type;
192  typedef typename color_type::calc_type calc_type;
193  enum
194  {
195  num_components = 3,
196  pix_step = Step,
197  pix_offset = Offset,
198  pix_width = sizeof(value_type) * pix_step
199  };
200  struct pixel_type
201  {
202  value_type c[num_components];
203 
204  void set(value_type r, value_type g, value_type b)
205  {
206  c[order_type::R] = r;
207  c[order_type::G] = g;
208  c[order_type::B] = b;
209  }
210 
211  void set(const color_type& color)
212  {
213  set(color.r, color.g, color.b);
214  }
215 
216  void get(value_type& r, value_type& g, value_type& b) const
217  {
218  r = c[order_type::R];
219  g = c[order_type::G];
220  b = c[order_type::B];
221  }
222 
223  color_type get() const
224  {
225  return color_type(
226  c[order_type::R],
227  c[order_type::G],
228  c[order_type::B]);
229  }
230 
231  pixel_type* next()
232  {
233  return (pixel_type*)(c + pix_step);
234  }
235 
236  const pixel_type* next() const
237  {
238  return (const pixel_type*)(c + pix_step);
239  }
240 
241  pixel_type* advance(int n)
242  {
243  return (pixel_type*)(c + n * pix_step);
244  }
245 
246  const pixel_type* advance(int n) const
247  {
248  return (const pixel_type*)(c + n * pix_step);
249  }
250  };
251 
252  private:
253  //--------------------------------------------------------------------
254  AGG_INLINE void blend_pix(pixel_type* p,
255  value_type r, value_type g, value_type b, value_type a,
256  unsigned cover)
257  {
258  m_blender.blend_pix(p->c, r, g, b, a, cover);
259  }
260 
261  //--------------------------------------------------------------------
262  AGG_INLINE void blend_pix(pixel_type* p,
263  value_type r, value_type g, value_type b, value_type a)
264  {
265  m_blender.blend_pix(p->c, r, g, b, a);
266  }
267 
268  //--------------------------------------------------------------------
269  AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover)
270  {
271  m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a, cover);
272  }
273 
274  //--------------------------------------------------------------------
275  AGG_INLINE void blend_pix(pixel_type* p, const color_type& c)
276  {
277  m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a);
278  }
279 
280  //--------------------------------------------------------------------
281  AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover)
282  {
283  if (!c.is_transparent())
284  {
285  if (c.is_opaque() && cover == cover_mask)
286  {
287  p->set(c);
288  }
289  else
290  {
291  blend_pix(p, c, cover);
292  }
293  }
294  }
295 
296  //--------------------------------------------------------------------
297  AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c)
298  {
299  if (!c.is_transparent())
300  {
301  if (c.is_opaque())
302  {
303  p->set(c);
304  }
305  else
306  {
307  blend_pix(p, c);
308  }
309  }
310  }
311 
312  public:
313  //--------------------------------------------------------------------
314  explicit pixfmt_alpha_blend_rgb(rbuf_type& rb) :
315  m_rbuf(&rb)
316  {}
317  void attach(rbuf_type& rb) { m_rbuf = &rb; }
318 
319  //--------------------------------------------------------------------
320  template<class PixFmt>
321  bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
322  {
323  rect_i r(x1, y1, x2, y2);
324  if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
325  {
326  int stride = pixf.stride();
327  m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
328  (r.x2 - r.x1) + 1,
329  (r.y2 - r.y1) + 1,
330  stride);
331  return true;
332  }
333  return false;
334  }
335 
336  //--------------------------------------------------------------------
337  Blender& blender() { return m_blender; }
338 
339  //--------------------------------------------------------------------
340  AGG_INLINE unsigned width() const { return m_rbuf->width(); }
341  AGG_INLINE unsigned height() const { return m_rbuf->height(); }
342  AGG_INLINE int stride() const { return m_rbuf->stride(); }
343 
344  //--------------------------------------------------------------------
345  AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
346  AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
347  AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
348 
349  //--------------------------------------------------------------------
350  AGG_INLINE int8u* pix_ptr(int x, int y)
351  {
352  return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset);
353  }
354 
355  AGG_INLINE const int8u* pix_ptr(int x, int y) const
356  {
357  return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset);
358  }
359 
360  // Return pointer to pixel value, forcing row to be allocated.
361  AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len)
362  {
363  return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step + pix_offset));
364  }
365 
366  // Return pointer to pixel value, or null if row not allocated.
367  AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const
368  {
369  int8u* p = m_rbuf->row_ptr(y);
370  return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step + pix_offset)) : 0;
371  }
372 
373  // Get pixel pointer from raw buffer pointer.
374  AGG_INLINE static pixel_type* pix_value_ptr(void* p)
375  {
376  return (pixel_type*)((value_type*)p + pix_offset);
377  }
378 
379  // Get pixel pointer from raw buffer pointer.
380  AGG_INLINE static const pixel_type* pix_value_ptr(const void* p)
381  {
382  return (const pixel_type*)((const value_type*)p + pix_offset);
383  }
384 
385  //--------------------------------------------------------------------
386  AGG_INLINE static void write_plain_color(void* p, color_type c)
387  {
388  // RGB formats are implicitly premultiplied.
389  c.premultiply();
390  pix_value_ptr(p)->set(c);
391  }
392 
393  //--------------------------------------------------------------------
394  AGG_INLINE static color_type read_plain_color(const void* p)
395  {
396  return pix_value_ptr(p)->get();
397  }
398 
399  //--------------------------------------------------------------------
400  AGG_INLINE static void make_pix(int8u* p, const color_type& c)
401  {
402  ((pixel_type*)p)->set(c);
403  }
404 
405  //--------------------------------------------------------------------
406  AGG_INLINE color_type pixel(int x, int y) const
407  {
408  if (const pixel_type* p = pix_value_ptr(x, y))
409  {
410  return p->get();
411  }
412  return color_type::no_color();
413  }
414 
415  //--------------------------------------------------------------------
416  AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
417  {
418  pix_value_ptr(x, y, 1)->set(c);
419  }
420 
421  //--------------------------------------------------------------------
422  AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
423  {
424  copy_or_blend_pix(pix_value_ptr(x, y, 1), c, cover);
425  }
426 
427  //--------------------------------------------------------------------
428  AGG_INLINE void copy_hline(int x, int y,
429  unsigned len,
430  const color_type& c)
431  {
432  pixel_type* p = pix_value_ptr(x, y, len);
433  do
434  {
435  p->set(c);
436  p = p->next();
437  }
438  while(--len);
439  }
440 
441 
442  //--------------------------------------------------------------------
443  AGG_INLINE void copy_vline(int x, int y,
444  unsigned len,
445  const color_type& c)
446  {
447  do
448  {
449  pix_value_ptr(x, y++, 1)->set(c);
450  }
451  while (--len);
452  }
453 
454  //--------------------------------------------------------------------
455  void blend_hline(int x, int y,
456  unsigned len,
457  const color_type& c,
458  int8u cover)
459  {
460  if (!c.is_transparent())
461  {
462  pixel_type* p = pix_value_ptr(x, y, len);
463 
464  if (c.is_opaque() && cover == cover_mask)
465  {
466  do
467  {
468  p->set(c);
469  p = p->next();
470  }
471  while (--len);
472  }
473  else
474  {
475  do
476  {
477  blend_pix(p, c, cover);
478  p = p->next();
479  }
480  while (--len);
481  }
482  }
483  }
484 
485 
486  //--------------------------------------------------------------------
487  void blend_vline(int x, int y,
488  unsigned len,
489  const color_type& c,
490  int8u cover)
491  {
492  if (!c.is_transparent())
493  {
494  if (c.is_opaque() && cover == cover_mask)
495  {
496  do
497  {
498  pix_value_ptr(x, y++, 1)->set(c);
499  }
500  while (--len);
501  }
502  else
503  {
504  do
505  {
506  blend_pix(pix_value_ptr(x, y++, 1), c, cover);
507  }
508  while (--len);
509  }
510  }
511  }
512 
513  //--------------------------------------------------------------------
514  void blend_solid_hspan(int x, int y,
515  unsigned len,
516  const color_type& c,
517  const int8u* covers)
518  {
519  if (!c.is_transparent())
520  {
521  pixel_type* p = pix_value_ptr(x, y, len);
522 
523  do
524  {
525  if (c.is_opaque() && *covers == cover_mask)
526  {
527  p->set(c);
528  }
529  else
530  {
531  blend_pix(p, c, *covers);
532  }
533  p = p->next();
534  ++covers;
535  }
536  while (--len);
537  }
538  }
539 
540 
541  //--------------------------------------------------------------------
542  void blend_solid_vspan(int x, int y,
543  unsigned len,
544  const color_type& c,
545  const int8u* covers)
546  {
547  if (!c.is_transparent())
548  {
549  do
550  {
551  pixel_type* p = pix_value_ptr(x, y++, 1);
552 
553  if (c.is_opaque() && *covers == cover_mask)
554  {
555  p->set(c);
556  }
557  else
558  {
559  blend_pix(p, c, *covers);
560  }
561  ++covers;
562  }
563  while (--len);
564  }
565  }
566 
567  //--------------------------------------------------------------------
568  void copy_color_hspan(int x, int y,
569  unsigned len,
570  const color_type* colors)
571  {
572  pixel_type* p = pix_value_ptr(x, y, len);
573 
574  do
575  {
576  p->set(*colors++);
577  p = p->next();
578  }
579  while (--len);
580  }
581 
582 
583  //--------------------------------------------------------------------
584  void copy_color_vspan(int x, int y,
585  unsigned len,
586  const color_type* colors)
587  {
588  do
589  {
590  pix_value_ptr(x, y++, 1)->set(*colors++);
591  }
592  while (--len);
593  }
594 
595  //--------------------------------------------------------------------
596  void blend_color_hspan(int x, int y,
597  unsigned len,
598  const color_type* colors,
599  const int8u* covers,
600  int8u cover)
601  {
602  pixel_type* p = pix_value_ptr(x, y, len);
603 
604  if (covers)
605  {
606  do
607  {
608  copy_or_blend_pix(p, *colors++, *covers++);
609  p = p->next();
610  }
611  while (--len);
612  }
613  else
614  {
615  if (cover == cover_mask)
616  {
617  do
618  {
619  copy_or_blend_pix(p, *colors++);
620  p = p->next();
621  }
622  while (--len);
623  }
624  else
625  {
626  do
627  {
628  copy_or_blend_pix(p, *colors++, cover);
629  p = p->next();
630  }
631  while (--len);
632  }
633  }
634  }
635 
636  //--------------------------------------------------------------------
637  void blend_color_vspan(int x, int y,
638  unsigned len,
639  const color_type* colors,
640  const int8u* covers,
641  int8u cover)
642  {
643  if (covers)
644  {
645  do
646  {
647  copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++);
648  }
649  while (--len);
650  }
651  else
652  {
653  if (cover == cover_mask)
654  {
655  do
656  {
657  copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++);
658  }
659  while (--len);
660  }
661  else
662  {
663  do
664  {
665  copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover);
666  }
667  while (--len);
668  }
669  }
670  }
671 
672  //--------------------------------------------------------------------
673  template<class Function> void for_each_pixel(Function f)
674  {
675  for (unsigned y = 0; y < height(); ++y)
676  {
677  row_data r = m_rbuf->row(y);
678  if (r.ptr)
679  {
680  unsigned len = r.x2 - r.x1 + 1;
681  pixel_type* p = pix_value_ptr(r.x1, y, len);
682  do
683  {
684  f(p->c);
685  p = p->next();
686  }
687  while (--len);
688  }
689  }
690  }
691 
692  //--------------------------------------------------------------------
693  template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
694  {
696  }
697 
698  //--------------------------------------------------------------------
699  template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
700  {
702  }
703 
704  //--------------------------------------------------------------------
705  template<class RenBuf2>
706  void copy_from(const RenBuf2& from,
707  int xdst, int ydst,
708  int xsrc, int ysrc,
709  unsigned len)
710  {
711  if (const int8u* p = from.row_ptr(ysrc))
712  {
713  std::memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
714  p + xsrc * pix_width,
715  len * pix_width);
716  }
717  }
718 
719  //--------------------------------------------------------------------
720  // Blend from an RGBA surface.
721  template<class SrcPixelFormatRenderer>
722  void blend_from(const SrcPixelFormatRenderer& from,
723  int xdst, int ydst,
724  int xsrc, int ysrc,
725  unsigned len,
726  int8u cover)
727  {
728  typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
729  typedef typename SrcPixelFormatRenderer::order_type src_order;
730 
731  if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
732  {
733  pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
734 
735  if (cover == cover_mask)
736  {
737  do
738  {
739  value_type alpha = psrc->c[src_order::A];
740  if (alpha <= color_type::empty_value())
741  {
742  if (alpha >= color_type::full_value())
743  {
744  pdst->c[order_type::R] = psrc->c[src_order::R];
745  pdst->c[order_type::G] = psrc->c[src_order::G];
746  pdst->c[order_type::B] = psrc->c[src_order::B];
747  }
748  else
749  {
750  blend_pix(pdst,
751  psrc->c[src_order::R],
752  psrc->c[src_order::G],
753  psrc->c[src_order::B],
754  alpha);
755  }
756  }
757  psrc = psrc->next();
758  pdst = pdst->next();
759  }
760  while(--len);
761  }
762  else
763  {
764  do
765  {
766  copy_or_blend_pix(pdst, psrc->get(), cover);
767  psrc = psrc->next();
768  pdst = pdst->next();
769  }
770  while (--len);
771  }
772  }
773  }
774 
775  //--------------------------------------------------------------------
776  // Blend from single color, using grayscale surface as alpha channel.
777  template<class SrcPixelFormatRenderer>
778  void blend_from_color(const SrcPixelFormatRenderer& from,
779  const color_type& color,
780  int xdst, int ydst,
781  int xsrc, int ysrc,
782  unsigned len,
783  int8u cover)
784  {
785  typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
786  typedef typename SrcPixelFormatRenderer::color_type src_color_type;
787 
788  if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
789  {
790  pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
791 
792  do
793  {
794  copy_or_blend_pix(pdst, color, src_color_type::scale_cover(cover, psrc->c[0]));
795  psrc = psrc->next();
796  pdst = pdst->next();
797  }
798  while (--len);
799  }
800  }
801 
802  //--------------------------------------------------------------------
803  // Blend from color table, using grayscale surface as indexes into table.
804  // Obviously, this only works for integer value types.
805  template<class SrcPixelFormatRenderer>
806  void blend_from_lut(const SrcPixelFormatRenderer& from,
807  const color_type* color_lut,
808  int xdst, int ydst,
809  int xsrc, int ysrc,
810  unsigned len,
811  int8u cover)
812  {
813  typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
814 
815  if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
816  {
817  pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
818 
819  if (cover == cover_mask)
820  {
821  do
822  {
823  const color_type& color = color_lut[psrc->c[0]];
824  blend_pix(pdst, color);
825  psrc = psrc->next();
826  pdst = pdst->next();
827  }
828  while(--len);
829  }
830  else
831  {
832  do
833  {
834  copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover);
835  psrc = psrc->next();
836  pdst = pdst->next();
837  }
838  while(--len);
839  }
840  }
841  }
842 
843  private:
844  rbuf_type* m_rbuf;
845  Blender m_blender;
846  };
847 
848  //-----------------------------------------------------------------------
857 
866 
875 
884 
901 
918 
919 
920  //-----------------------------------------------------pixfmt_rgb24_gamma
921  template<class Gamma> class pixfmt_rgb24_gamma :
922  public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer, 3>
923  {
924  public:
925  pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) :
927  {
928  this->blender().gamma(g);
929  }
930  };
931 
932  //-----------------------------------------------------pixfmt_srgb24_gamma
933  template<class Gamma> class pixfmt_srgb24_gamma :
934  public pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_rgb, Gamma>, rendering_buffer, 3>
935  {
936  public:
937  pixfmt_srgb24_gamma(rendering_buffer& rb, const Gamma& g) :
939  {
940  this->blender().gamma(g);
941  }
942  };
943 
944  //-----------------------------------------------------pixfmt_bgr24_gamma
945  template<class Gamma> class pixfmt_bgr24_gamma :
946  public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer, 3>
947  {
948  public:
949  pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) :
951  {
952  this->blender().gamma(g);
953  }
954  };
955 
956  //-----------------------------------------------------pixfmt_sbgr24_gamma
957  template<class Gamma> class pixfmt_sbgr24_gamma :
958  public pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_bgr, Gamma>, rendering_buffer, 3>
959  {
960  public:
961  pixfmt_sbgr24_gamma(rendering_buffer& rb, const Gamma& g) :
963  {
964  this->blender().gamma(g);
965  }
966  };
967 
968  //-----------------------------------------------------pixfmt_rgb48_gamma
969  template<class Gamma> class pixfmt_rgb48_gamma :
970  public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer, 3>
971  {
972  public:
973  pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) :
975  {
976  this->blender().gamma(g);
977  }
978  };
979 
980  //-----------------------------------------------------pixfmt_bgr48_gamma
981  template<class Gamma> class pixfmt_bgr48_gamma :
982  public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer, 3>
983  {
984  public:
985  pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) :
987  {
988  this->blender().gamma(g);
989  }
990  };
991 
992 }
993 
994 #endif
995 
Definition: agg_arc.cpp:24