Anti-Grain Geometry Tutorial
agg_pixfmt_rgb_packed.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_PACKED_INCLUDED
25 #define AGG_PIXFMT_RGB_PACKED_INCLUDED
26 
27 #include <cstring>
28 #include "agg_basics.h"
29 #include "agg_color_rgba.h"
30 #include "agg_rendering_buffer.h"
31 
32 namespace agg
33 {
34  //=========================================================blender_rgb555
36  {
37  typedef rgba8 color_type;
38  typedef color_type::value_type value_type;
39  typedef color_type::calc_type calc_type;
40  typedef int16u pixel_type;
41 
42  static AGG_INLINE void blend_pix(pixel_type* p,
43  unsigned cr, unsigned cg, unsigned cb,
44  unsigned alpha,
45  unsigned)
46  {
47  pixel_type rgb = *p;
48  calc_type r = (rgb >> 7) & 0xF8;
49  calc_type g = (rgb >> 2) & 0xF8;
50  calc_type b = (rgb << 3) & 0xF8;
51  *p = (pixel_type)
52  (((((cr - r) * alpha + (r << 8)) >> 1) & 0x7C00) |
53  ((((cg - g) * alpha + (g << 8)) >> 6) & 0x03E0) |
54  (((cb - b) * alpha + (b << 8)) >> 11) | 0x8000);
55  }
56 
57  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
58  {
59  return (pixel_type)(((r & 0xF8) << 7) |
60  ((g & 0xF8) << 2) |
61  (b >> 3) | 0x8000);
62  }
63 
64  static AGG_INLINE color_type make_color(pixel_type p)
65  {
66  return color_type((p >> 7) & 0xF8,
67  (p >> 2) & 0xF8,
68  (p << 3) & 0xF8);
69  }
70  };
71 
72 
73  //=====================================================blender_rgb555_pre
75  {
76  typedef rgba8 color_type;
77  typedef color_type::value_type value_type;
78  typedef color_type::calc_type calc_type;
79  typedef int16u pixel_type;
80 
81  static AGG_INLINE void blend_pix(pixel_type* p,
82  unsigned cr, unsigned cg, unsigned cb,
83  unsigned alpha,
84  unsigned cover)
85  {
86  alpha = color_type::base_mask - alpha;
87  pixel_type rgb = *p;
88  calc_type r = (rgb >> 7) & 0xF8;
89  calc_type g = (rgb >> 2) & 0xF8;
90  calc_type b = (rgb << 3) & 0xF8;
91  *p = (pixel_type)
92  ((((r * alpha + cr * cover) >> 1) & 0x7C00) |
93  (((g * alpha + cg * cover) >> 6) & 0x03E0) |
94  ((b * alpha + cb * cover) >> 11) | 0x8000);
95  }
96 
97  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
98  {
99  return (pixel_type)(((r & 0xF8) << 7) |
100  ((g & 0xF8) << 2) |
101  (b >> 3) | 0x8000);
102  }
103 
104  static AGG_INLINE color_type make_color(pixel_type p)
105  {
106  return color_type((p >> 7) & 0xF8,
107  (p >> 2) & 0xF8,
108  (p << 3) & 0xF8);
109  }
110  };
111 
112 
113 
114 
115  //=====================================================blender_rgb555_gamma
116  template<class Gamma> class blender_rgb555_gamma
117  {
118  public:
119  typedef rgba8 color_type;
120  typedef color_type::value_type value_type;
121  typedef color_type::calc_type calc_type;
122  typedef int16u pixel_type;
123  typedef Gamma gamma_type;
124 
125  blender_rgb555_gamma() : m_gamma(0) {}
126  void gamma(const gamma_type& g) { m_gamma = &g; }
127 
128  AGG_INLINE void blend_pix(pixel_type* p,
129  unsigned cr, unsigned cg, unsigned cb,
130  unsigned alpha,
131  unsigned)
132  {
133  pixel_type rgb = *p;
134  calc_type r = m_gamma->dir((rgb >> 7) & 0xF8);
135  calc_type g = m_gamma->dir((rgb >> 2) & 0xF8);
136  calc_type b = m_gamma->dir((rgb << 3) & 0xF8);
137  *p = (pixel_type)
138  (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 7) & 0x7C00) |
139  ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 2) & 0x03E0) |
140  (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3) | 0x8000);
141  }
142 
143  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
144  {
145  return (pixel_type)(((r & 0xF8) << 7) |
146  ((g & 0xF8) << 2) |
147  (b >> 3) | 0x8000);
148  }
149 
150  static AGG_INLINE color_type make_color(pixel_type p)
151  {
152  return color_type((p >> 7) & 0xF8,
153  (p >> 2) & 0xF8,
154  (p << 3) & 0xF8);
155  }
156 
157  private:
158  const Gamma* m_gamma;
159  };
160 
161 
162 
163 
164 
165  //=========================================================blender_rgb565
167  {
168  typedef rgba8 color_type;
169  typedef color_type::value_type value_type;
170  typedef color_type::calc_type calc_type;
171  typedef int16u pixel_type;
172 
173  static AGG_INLINE void blend_pix(pixel_type* p,
174  unsigned cr, unsigned cg, unsigned cb,
175  unsigned alpha,
176  unsigned)
177  {
178  pixel_type rgb = *p;
179  calc_type r = (rgb >> 8) & 0xF8;
180  calc_type g = (rgb >> 3) & 0xFC;
181  calc_type b = (rgb << 3) & 0xF8;
182  *p = (pixel_type)
183  (((((cr - r) * alpha + (r << 8)) ) & 0xF800) |
184  ((((cg - g) * alpha + (g << 8)) >> 5) & 0x07E0) |
185  (((cb - b) * alpha + (b << 8)) >> 11));
186  }
187 
188  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
189  {
190  return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3));
191  }
192 
193  static AGG_INLINE color_type make_color(pixel_type p)
194  {
195  return color_type((p >> 8) & 0xF8,
196  (p >> 3) & 0xFC,
197  (p << 3) & 0xF8);
198  }
199  };
200 
201 
202 
203  //=====================================================blender_rgb565_pre
205  {
206  typedef rgba8 color_type;
207  typedef color_type::value_type value_type;
208  typedef color_type::calc_type calc_type;
209  typedef int16u pixel_type;
210 
211  static AGG_INLINE void blend_pix(pixel_type* p,
212  unsigned cr, unsigned cg, unsigned cb,
213  unsigned alpha,
214  unsigned cover)
215  {
216  alpha = color_type::base_mask - alpha;
217  pixel_type rgb = *p;
218  calc_type r = (rgb >> 8) & 0xF8;
219  calc_type g = (rgb >> 3) & 0xFC;
220  calc_type b = (rgb << 3) & 0xF8;
221  *p = (pixel_type)
222  ((((r * alpha + cr * cover) ) & 0xF800) |
223  (((g * alpha + cg * cover) >> 5 ) & 0x07E0) |
224  ((b * alpha + cb * cover) >> 11));
225  }
226 
227  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
228  {
229  return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3));
230  }
231 
232  static AGG_INLINE color_type make_color(pixel_type p)
233  {
234  return color_type((p >> 8) & 0xF8,
235  (p >> 3) & 0xFC,
236  (p << 3) & 0xF8);
237  }
238  };
239 
240 
241 
242  //=====================================================blender_rgb565_gamma
243  template<class Gamma> class blender_rgb565_gamma
244  {
245  public:
246  typedef rgba8 color_type;
247  typedef color_type::value_type value_type;
248  typedef color_type::calc_type calc_type;
249  typedef int16u pixel_type;
250  typedef Gamma gamma_type;
251 
252  blender_rgb565_gamma() : m_gamma(0) {}
253  void gamma(const gamma_type& g) { m_gamma = &g; }
254 
255  AGG_INLINE void blend_pix(pixel_type* p,
256  unsigned cr, unsigned cg, unsigned cb,
257  unsigned alpha,
258  unsigned)
259  {
260  pixel_type rgb = *p;
261  calc_type r = m_gamma->dir((rgb >> 8) & 0xF8);
262  calc_type g = m_gamma->dir((rgb >> 3) & 0xFC);
263  calc_type b = m_gamma->dir((rgb << 3) & 0xF8);
264  *p = (pixel_type)
265  (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 8) & 0xF800) |
266  ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 3) & 0x07E0) |
267  (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3));
268  }
269 
270  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
271  {
272  return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3));
273  }
274 
275  static AGG_INLINE color_type make_color(pixel_type p)
276  {
277  return color_type((p >> 8) & 0xF8,
278  (p >> 3) & 0xFC,
279  (p << 3) & 0xF8);
280  }
281 
282  private:
283  const Gamma* m_gamma;
284  };
285 
286 
287 
288  //=====================================================blender_rgbAAA
290  {
291  typedef rgba16 color_type;
292  typedef color_type::value_type value_type;
293  typedef color_type::calc_type calc_type;
294  typedef int32u pixel_type;
295 
296  static AGG_INLINE void blend_pix(pixel_type* p,
297  unsigned cr, unsigned cg, unsigned cb,
298  unsigned alpha,
299  unsigned)
300  {
301  pixel_type rgb = *p;
302  calc_type r = (rgb >> 14) & 0xFFC0;
303  calc_type g = (rgb >> 4) & 0xFFC0;
304  calc_type b = (rgb << 6) & 0xFFC0;
305  *p = (pixel_type)
306  (((((cr - r) * alpha + (r << 16)) >> 2) & 0x3FF00000) |
307  ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) |
308  (((cb - b) * alpha + (b << 16)) >> 22) | 0xC0000000);
309  }
310 
311  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
312  {
313  return (pixel_type)(((r & 0xFFC0) << 14) |
314  ((g & 0xFFC0) << 4) |
315  (b >> 6) | 0xC0000000);
316  }
317 
318  static AGG_INLINE color_type make_color(pixel_type p)
319  {
320  return color_type((p >> 14) & 0xFFC0,
321  (p >> 4) & 0xFFC0,
322  (p << 6) & 0xFFC0);
323  }
324  };
325 
326 
327 
328  //==================================================blender_rgbAAA_pre
330  {
331  typedef rgba16 color_type;
332  typedef color_type::value_type value_type;
333  typedef color_type::calc_type calc_type;
334  typedef int32u pixel_type;
335 
336  static AGG_INLINE void blend_pix(pixel_type* p,
337  unsigned cr, unsigned cg, unsigned cb,
338  unsigned alpha,
339  unsigned cover)
340  {
341  alpha = color_type::base_mask - alpha;
342  cover = (cover + 1) << (color_type::base_shift - 8);
343  pixel_type rgb = *p;
344  calc_type r = (rgb >> 14) & 0xFFC0;
345  calc_type g = (rgb >> 4) & 0xFFC0;
346  calc_type b = (rgb << 6) & 0xFFC0;
347  *p = (pixel_type)
348  ((((r * alpha + cr * cover) >> 2) & 0x3FF00000) |
349  (((g * alpha + cg * cover) >> 12) & 0x000FFC00) |
350  ((b * alpha + cb * cover) >> 22) | 0xC0000000);
351  }
352 
353  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
354  {
355  return (pixel_type)(((r & 0xFFC0) << 14) |
356  ((g & 0xFFC0) << 4) |
357  (b >> 6) | 0xC0000000);
358  }
359 
360  static AGG_INLINE color_type make_color(pixel_type p)
361  {
362  return color_type((p >> 14) & 0xFFC0,
363  (p >> 4) & 0xFFC0,
364  (p << 6) & 0xFFC0);
365  }
366  };
367 
368 
369 
370  //=================================================blender_rgbAAA_gamma
371  template<class Gamma> class blender_rgbAAA_gamma
372  {
373  public:
374  typedef rgba16 color_type;
375  typedef color_type::value_type value_type;
376  typedef color_type::calc_type calc_type;
377  typedef int32u pixel_type;
378  typedef Gamma gamma_type;
379 
380  blender_rgbAAA_gamma() : m_gamma(0) {}
381  void gamma(const gamma_type& g) { m_gamma = &g; }
382 
383  AGG_INLINE void blend_pix(pixel_type* p,
384  unsigned cr, unsigned cg, unsigned cb,
385  unsigned alpha,
386  unsigned)
387  {
388  pixel_type rgb = *p;
389  calc_type r = m_gamma->dir((rgb >> 14) & 0xFFC0);
390  calc_type g = m_gamma->dir((rgb >> 4) & 0xFFC0);
391  calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0);
392  *p = (pixel_type)
393  (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 14) & 0x3FF00000) |
394  ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) |
395  (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 ) | 0xC0000000);
396  }
397 
398  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
399  {
400  return (pixel_type)(((r & 0xFFC0) << 14) |
401  ((g & 0xFFC0) << 4) |
402  (b >> 6) | 0xC0000000);
403  }
404 
405  static AGG_INLINE color_type make_color(pixel_type p)
406  {
407  return color_type((p >> 14) & 0xFFC0,
408  (p >> 4) & 0xFFC0,
409  (p << 6) & 0xFFC0);
410  }
411  private:
412  const Gamma* m_gamma;
413  };
414 
415 
416  //=====================================================blender_bgrAAA
418  {
419  typedef rgba16 color_type;
420  typedef color_type::value_type value_type;
421  typedef color_type::calc_type calc_type;
422  typedef int32u pixel_type;
423 
424  static AGG_INLINE void blend_pix(pixel_type* p,
425  unsigned cr, unsigned cg, unsigned cb,
426  unsigned alpha,
427  unsigned)
428  {
429  pixel_type bgr = *p;
430  calc_type b = (bgr >> 14) & 0xFFC0;
431  calc_type g = (bgr >> 4) & 0xFFC0;
432  calc_type r = (bgr << 6) & 0xFFC0;
433  *p = (pixel_type)
434  (((((cb - b) * alpha + (b << 16)) >> 2) & 0x3FF00000) |
435  ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) |
436  (((cr - r) * alpha + (r << 16)) >> 22) | 0xC0000000);
437  }
438 
439  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
440  {
441  return (pixel_type)(((b & 0xFFC0) << 14) |
442  ((g & 0xFFC0) << 4) |
443  (r >> 6) | 0xC0000000);
444  }
445 
446  static AGG_INLINE color_type make_color(pixel_type p)
447  {
448  return color_type((p << 6) & 0xFFC0,
449  (p >> 4) & 0xFFC0,
450  (p >> 14) & 0xFFC0);
451  }
452  };
453 
454 
455 
456  //=================================================blender_bgrAAA_pre
458  {
459  typedef rgba16 color_type;
460  typedef color_type::value_type value_type;
461  typedef color_type::calc_type calc_type;
462  typedef int32u pixel_type;
463 
464  static AGG_INLINE void blend_pix(pixel_type* p,
465  unsigned cr, unsigned cg, unsigned cb,
466  unsigned alpha,
467  unsigned cover)
468  {
469  alpha = color_type::base_mask - alpha;
470  cover = (cover + 1) << (color_type::base_shift - 8);
471  pixel_type bgr = *p;
472  calc_type b = (bgr >> 14) & 0xFFC0;
473  calc_type g = (bgr >> 4) & 0xFFC0;
474  calc_type r = (bgr << 6) & 0xFFC0;
475  *p = (pixel_type)
476  ((((b * alpha + cb * cover) >> 2) & 0x3FF00000) |
477  (((g * alpha + cg * cover) >> 12) & 0x000FFC00) |
478  ((r * alpha + cr * cover) >> 22) | 0xC0000000);
479  }
480 
481  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
482  {
483  return (pixel_type)(((b & 0xFFC0) << 14) |
484  ((g & 0xFFC0) << 4) |
485  (r >> 6) | 0xC0000000);
486  }
487 
488  static AGG_INLINE color_type make_color(pixel_type p)
489  {
490  return color_type((p << 6) & 0xFFC0,
491  (p >> 4) & 0xFFC0,
492  (p >> 14) & 0xFFC0);
493  }
494  };
495 
496 
497 
498  //=================================================blender_bgrAAA_gamma
499  template<class Gamma> class blender_bgrAAA_gamma
500  {
501  public:
502  typedef rgba16 color_type;
503  typedef color_type::value_type value_type;
504  typedef color_type::calc_type calc_type;
505  typedef int32u pixel_type;
506  typedef Gamma gamma_type;
507 
508  blender_bgrAAA_gamma() : m_gamma(0) {}
509  void gamma(const gamma_type& g) { m_gamma = &g; }
510 
511  AGG_INLINE void blend_pix(pixel_type* p,
512  unsigned cr, unsigned cg, unsigned cb,
513  unsigned alpha,
514  unsigned)
515  {
516  pixel_type bgr = *p;
517  calc_type b = m_gamma->dir((bgr >> 14) & 0xFFC0);
518  calc_type g = m_gamma->dir((bgr >> 4) & 0xFFC0);
519  calc_type r = m_gamma->dir((bgr << 6) & 0xFFC0);
520  *p = (pixel_type)
521  (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 14) & 0x3FF00000) |
522  ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) |
523  (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 6 ) | 0xC0000000);
524  }
525 
526  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
527  {
528  return (pixel_type)(((b & 0xFFC0) << 14) |
529  ((g & 0xFFC0) << 4) |
530  (r >> 6) | 0xC0000000);
531  }
532 
533  static AGG_INLINE color_type make_color(pixel_type p)
534  {
535  return color_type((p << 6) & 0xFFC0,
536  (p >> 4) & 0xFFC0,
537  (p >> 14) & 0xFFC0);
538  }
539 
540  private:
541  const Gamma* m_gamma;
542  };
543 
544 
545 
546  //=====================================================blender_rgbBBA
548  {
549  typedef rgba16 color_type;
550  typedef color_type::value_type value_type;
551  typedef color_type::calc_type calc_type;
552  typedef int32u pixel_type;
553 
554  static AGG_INLINE void blend_pix(pixel_type* p,
555  unsigned cr, unsigned cg, unsigned cb,
556  unsigned alpha,
557  unsigned)
558  {
559  pixel_type rgb = *p;
560  calc_type r = (rgb >> 16) & 0xFFE0;
561  calc_type g = (rgb >> 5) & 0xFFE0;
562  calc_type b = (rgb << 6) & 0xFFC0;
563  *p = (pixel_type)
564  (((((cr - r) * alpha + (r << 16)) ) & 0xFFE00000) |
565  ((((cg - g) * alpha + (g << 16)) >> 11) & 0x001FFC00) |
566  (((cb - b) * alpha + (b << 16)) >> 22));
567  }
568 
569  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
570  {
571  return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6));
572  }
573 
574  static AGG_INLINE color_type make_color(pixel_type p)
575  {
576  return color_type((p >> 16) & 0xFFE0,
577  (p >> 5) & 0xFFE0,
578  (p << 6) & 0xFFC0);
579  }
580  };
581 
582 
583  //=================================================blender_rgbBBA_pre
585  {
586  typedef rgba16 color_type;
587  typedef color_type::value_type value_type;
588  typedef color_type::calc_type calc_type;
589  typedef int32u pixel_type;
590 
591  static AGG_INLINE void blend_pix(pixel_type* p,
592  unsigned cr, unsigned cg, unsigned cb,
593  unsigned alpha,
594  unsigned cover)
595  {
596  alpha = color_type::base_mask - alpha;
597  cover = (cover + 1) << (color_type::base_shift - 8);
598  pixel_type rgb = *p;
599  calc_type r = (rgb >> 16) & 0xFFE0;
600  calc_type g = (rgb >> 5) & 0xFFE0;
601  calc_type b = (rgb << 6) & 0xFFC0;
602  *p = (pixel_type)
603  ((((r * alpha + cr * cover) ) & 0xFFE00000) |
604  (((g * alpha + cg * cover) >> 11) & 0x001FFC00) |
605  ((b * alpha + cb * cover) >> 22));
606  }
607 
608  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
609  {
610  return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6));
611  }
612 
613  static AGG_INLINE color_type make_color(pixel_type p)
614  {
615  return color_type((p >> 16) & 0xFFE0,
616  (p >> 5) & 0xFFE0,
617  (p << 6) & 0xFFC0);
618  }
619  };
620 
621 
622 
623  //=================================================blender_rgbBBA_gamma
624  template<class Gamma> class blender_rgbBBA_gamma
625  {
626  public:
627  typedef rgba16 color_type;
628  typedef color_type::value_type value_type;
629  typedef color_type::calc_type calc_type;
630  typedef int32u pixel_type;
631  typedef Gamma gamma_type;
632 
633  blender_rgbBBA_gamma() : m_gamma(0) {}
634  void gamma(const gamma_type& g) { m_gamma = &g; }
635 
636  AGG_INLINE void blend_pix(pixel_type* p,
637  unsigned cr, unsigned cg, unsigned cb,
638  unsigned alpha,
639  unsigned)
640  {
641  pixel_type rgb = *p;
642  calc_type r = m_gamma->dir((rgb >> 16) & 0xFFE0);
643  calc_type g = m_gamma->dir((rgb >> 5) & 0xFFE0);
644  calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0);
645  *p = (pixel_type)
646  (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 16) & 0xFFE00000) |
647  ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 5 ) & 0x001FFC00) |
648  (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 ));
649  }
650 
651  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
652  {
653  return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6));
654  }
655 
656  static AGG_INLINE color_type make_color(pixel_type p)
657  {
658  return color_type((p >> 16) & 0xFFE0,
659  (p >> 5) & 0xFFE0,
660  (p << 6) & 0xFFC0);
661  }
662 
663  private:
664  const Gamma* m_gamma;
665  };
666 
667 
668  //=====================================================blender_bgrABB
670  {
671  typedef rgba16 color_type;
672  typedef color_type::value_type value_type;
673  typedef color_type::calc_type calc_type;
674  typedef int32u pixel_type;
675 
676  static AGG_INLINE void blend_pix(pixel_type* p,
677  unsigned cr, unsigned cg, unsigned cb,
678  unsigned alpha,
679  unsigned)
680  {
681  pixel_type bgr = *p;
682  calc_type b = (bgr >> 16) & 0xFFC0;
683  calc_type g = (bgr >> 6) & 0xFFE0;
684  calc_type r = (bgr << 5) & 0xFFE0;
685  *p = (pixel_type)
686  (((((cb - b) * alpha + (b << 16)) ) & 0xFFC00000) |
687  ((((cg - g) * alpha + (g << 16)) >> 10) & 0x003FF800) |
688  (((cr - r) * alpha + (r << 16)) >> 21));
689  }
690 
691  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
692  {
693  return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5));
694  }
695 
696  static AGG_INLINE color_type make_color(pixel_type p)
697  {
698  return color_type((p << 5) & 0xFFE0,
699  (p >> 6) & 0xFFE0,
700  (p >> 16) & 0xFFC0);
701  }
702  };
703 
704 
705  //=================================================blender_bgrABB_pre
707  {
708  typedef rgba16 color_type;
709  typedef color_type::value_type value_type;
710  typedef color_type::calc_type calc_type;
711  typedef int32u pixel_type;
712 
713  static AGG_INLINE void blend_pix(pixel_type* p,
714  unsigned cr, unsigned cg, unsigned cb,
715  unsigned alpha,
716  unsigned cover)
717  {
718  alpha = color_type::base_mask - alpha;
719  cover = (cover + 1) << (color_type::base_shift - 8);
720  pixel_type bgr = *p;
721  calc_type b = (bgr >> 16) & 0xFFC0;
722  calc_type g = (bgr >> 6) & 0xFFE0;
723  calc_type r = (bgr << 5) & 0xFFE0;
724  *p = (pixel_type)
725  ((((b * alpha + cb * cover) ) & 0xFFC00000) |
726  (((g * alpha + cg * cover) >> 10) & 0x003FF800) |
727  ((r * alpha + cr * cover) >> 21));
728  }
729 
730  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
731  {
732  return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5));
733  }
734 
735  static AGG_INLINE color_type make_color(pixel_type p)
736  {
737  return color_type((p << 5) & 0xFFE0,
738  (p >> 6) & 0xFFE0,
739  (p >> 16) & 0xFFC0);
740  }
741  };
742 
743 
744 
745  //=================================================blender_bgrABB_gamma
746  template<class Gamma> class blender_bgrABB_gamma
747  {
748  public:
749  typedef rgba16 color_type;
750  typedef color_type::value_type value_type;
751  typedef color_type::calc_type calc_type;
752  typedef int32u pixel_type;
753  typedef Gamma gamma_type;
754 
755  blender_bgrABB_gamma() : m_gamma(0) {}
756  void gamma(const gamma_type& g) { m_gamma = &g; }
757 
758  AGG_INLINE void blend_pix(pixel_type* p,
759  unsigned cr, unsigned cg, unsigned cb,
760  unsigned alpha,
761  unsigned)
762  {
763  pixel_type bgr = *p;
764  calc_type b = m_gamma->dir((bgr >> 16) & 0xFFC0);
765  calc_type g = m_gamma->dir((bgr >> 6) & 0xFFE0);
766  calc_type r = m_gamma->dir((bgr << 5) & 0xFFE0);
767  *p = (pixel_type)
768  (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 16) & 0xFFC00000) |
769  ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 6 ) & 0x003FF800) |
770  (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 5 ));
771  }
772 
773  static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
774  {
775  return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5));
776  }
777 
778  static AGG_INLINE color_type make_color(pixel_type p)
779  {
780  return color_type((p << 5) & 0xFFE0,
781  (p >> 6) & 0xFFE0,
782  (p >> 16) & 0xFFC0);
783  }
784 
785  private:
786  const Gamma* m_gamma;
787  };
788 
789 
790 
791  //===========================================pixfmt_alpha_blend_rgb_packed
792  template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb_packed
793  {
794  public:
795  typedef RenBuf rbuf_type;
796  typedef typename rbuf_type::row_data row_data;
797  typedef Blender blender_type;
798  typedef typename blender_type::color_type color_type;
799  typedef typename blender_type::pixel_type pixel_type;
800  typedef int order_type; // A fake one
801  typedef typename color_type::value_type value_type;
802  typedef typename color_type::calc_type calc_type;
803  enum base_scale_e
804  {
805  base_shift = color_type::base_shift,
806  base_scale = color_type::base_scale,
807  base_mask = color_type::base_mask,
808  pix_width = sizeof(pixel_type),
809  };
810 
811  private:
812  //--------------------------------------------------------------------
813  AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover)
814  {
815  if (c.a)
816  {
817  calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
818  if(alpha == base_mask)
819  {
820  *p = m_blender.make_pix(c.r, c.g, c.b);
821  }
822  else
823  {
824  m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
825  }
826  }
827  }
828 
829  public:
830  //--------------------------------------------------------------------
831  explicit pixfmt_alpha_blend_rgb_packed(rbuf_type& rb) : m_rbuf(&rb) {}
832  void attach(rbuf_type& rb) { m_rbuf = &rb; }
833 
834  //--------------------------------------------------------------------
835  template<class PixFmt>
836  bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
837  {
838  rect_i r(x1, y1, x2, y2);
839  if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
840  {
841  int stride = pixf.stride();
842  m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
843  (r.x2 - r.x1) + 1,
844  (r.y2 - r.y1) + 1,
845  stride);
846  return true;
847  }
848  return false;
849  }
850 
851  Blender& blender() { return m_blender; }
852 
853  //--------------------------------------------------------------------
854  AGG_INLINE unsigned width() const { return m_rbuf->width(); }
855  AGG_INLINE unsigned height() const { return m_rbuf->height(); }
856  AGG_INLINE int stride() const { return m_rbuf->stride(); }
857 
858  //--------------------------------------------------------------------
859  AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
860  AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
861  AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
862 
863  //--------------------------------------------------------------------
864  AGG_INLINE int8u* pix_ptr(int x, int y)
865  {
866  return m_rbuf->row_ptr(y) + x * pix_width;
867  }
868 
869  AGG_INLINE const int8u* pix_ptr(int x, int y) const
870  {
871  return m_rbuf->row_ptr(y) + x * pix_width;
872  }
873 
874  //--------------------------------------------------------------------
875  AGG_INLINE void make_pix(int8u* p, const color_type& c)
876  {
877  *(pixel_type*)p = m_blender.make_pix(c.r, c.g, c.b);
878  }
879 
880  //--------------------------------------------------------------------
881  AGG_INLINE color_type pixel(int x, int y) const
882  {
883  return m_blender.make_color(((pixel_type*)m_rbuf->row_ptr(y))[x]);
884  }
885 
886  //--------------------------------------------------------------------
887  AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
888  {
889  ((pixel_type*)
890  m_rbuf->row_ptr(x, y, 1))[x] =
891  m_blender.make_pix(c.r, c.g, c.b);
892  }
893 
894  //--------------------------------------------------------------------
895  AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
896  {
897  copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y, 1) + x, c, cover);
898  }
899 
900  //--------------------------------------------------------------------
901  AGG_INLINE void copy_hline(int x, int y,
902  unsigned len,
903  const color_type& c)
904  {
905  pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x;
906  pixel_type v = m_blender.make_pix(c.r, c.g, c.b);
907  do
908  {
909  *p++ = v;
910  }
911  while(--len);
912  }
913 
914  //--------------------------------------------------------------------
915  AGG_INLINE void copy_vline(int x, int y,
916  unsigned len,
917  const color_type& c)
918  {
919  pixel_type v = m_blender.make_pix(c.r, c.g, c.b);
920  do
921  {
922  pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x;
923  *p = v;
924  }
925  while(--len);
926  }
927 
928  //--------------------------------------------------------------------
929  void blend_hline(int x, int y,
930  unsigned len,
931  const color_type& c,
932  int8u cover)
933  {
934  if (c.a)
935  {
936  pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x;
937  calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
938  if(alpha == base_mask)
939  {
940  pixel_type v = m_blender.make_pix(c.r, c.g, c.b);
941  do
942  {
943  *p++ = v;
944  }
945  while(--len);
946  }
947  else
948  {
949  do
950  {
951  m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
952  ++p;
953  }
954  while(--len);
955  }
956  }
957  }
958 
959  //--------------------------------------------------------------------
960  void blend_vline(int x, int y,
961  unsigned len,
962  const color_type& c,
963  int8u cover)
964  {
965  if (c.a)
966  {
967  calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
968  if(alpha == base_mask)
969  {
970  pixel_type v = m_blender.make_pix(c.r, c.g, c.b);
971  do
972  {
973  ((pixel_type*)m_rbuf->row_ptr(x, y++, 1))[x] = v;
974  }
975  while(--len);
976  }
977  else
978  {
979  do
980  {
981  m_blender.blend_pix(
982  (pixel_type*)m_rbuf->row_ptr(x, y++, 1),
983  c.r, c.g, c.b, alpha, cover);
984  }
985  while(--len);
986  }
987  }
988  }
989 
990  //--------------------------------------------------------------------
991  void blend_solid_hspan(int x, int y,
992  unsigned len,
993  const color_type& c,
994  const int8u* covers)
995  {
996  pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x;
997  do
998  {
999  copy_or_blend_pix(p, c, *covers++);
1000  ++p;
1001  }
1002  while(--len);
1003  }
1004 
1005  //--------------------------------------------------------------------
1006  void blend_solid_vspan(int x, int y,
1007  unsigned len,
1008  const color_type& c,
1009  const int8u* covers)
1010  {
1011  do
1012  {
1013  copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x,
1014  c, *covers++);
1015  }
1016  while(--len);
1017  }
1018 
1019  //--------------------------------------------------------------------
1020  void copy_color_hspan(int x, int y,
1021  unsigned len,
1022  const color_type* colors)
1023  {
1024  pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x;
1025  do
1026  {
1027  *p++ = m_blender.make_pix(colors->r, colors->g, colors->b);
1028  ++colors;
1029  }
1030  while(--len);
1031  }
1032 
1033  //--------------------------------------------------------------------
1034  void copy_color_vspan(int x, int y,
1035  unsigned len,
1036  const color_type* colors)
1037  {
1038  do
1039  {
1040  pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x;
1041  *p = m_blender.make_pix(colors->r, colors->g, colors->b);
1042  ++colors;
1043  }
1044  while(--len);
1045  }
1046 
1047  //--------------------------------------------------------------------
1048  void blend_color_hspan(int x, int y,
1049  unsigned len,
1050  const color_type* colors,
1051  const int8u* covers,
1052  int8u cover)
1053  {
1054  pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x;
1055  do
1056  {
1057  copy_or_blend_pix(p++, *colors++, covers ? *covers++ : cover);
1058  }
1059  while(--len);
1060  }
1061 
1062  //--------------------------------------------------------------------
1063  void blend_color_vspan(int x, int y,
1064  unsigned len,
1065  const color_type* colors,
1066  const int8u* covers,
1067  int8u cover)
1068  {
1069  do
1070  {
1071  copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x,
1072  *colors++, covers ? *covers++ : cover);
1073  }
1074  while(--len);
1075  }
1076 
1077  //--------------------------------------------------------------------
1078  template<class RenBuf2>
1079  void copy_from(const RenBuf2& from,
1080  int xdst, int ydst,
1081  int xsrc, int ysrc,
1082  unsigned len)
1083  {
1084  const int8u* p = from.row_ptr(ysrc);
1085  if(p)
1086  {
1087  std::memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
1088  p + xsrc * pix_width,
1089  len * pix_width);
1090  }
1091  }
1092 
1093  //--------------------------------------------------------------------
1094  template<class SrcPixelFormatRenderer>
1095  void blend_from(const SrcPixelFormatRenderer& from,
1096  int xdst, int ydst,
1097  int xsrc, int ysrc,
1098  unsigned len,
1099  int8u cover)
1100  {
1101  typedef typename SrcPixelFormatRenderer::order_type src_order;
1102 
1103  const value_type* psrc = (const value_type*)from.row_ptr(ysrc);
1104  if(psrc)
1105  {
1106  psrc += xsrc * 4;
1107  pixel_type* pdst =
1108  (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
1109  do
1110  {
1111  value_type alpha = psrc[src_order::A];
1112  if(alpha)
1113  {
1114  if(alpha == base_mask && cover == 255)
1115  {
1116  *pdst = m_blender.make_pix(psrc[src_order::R],
1117  psrc[src_order::G],
1118  psrc[src_order::B]);
1119  }
1120  else
1121  {
1122  m_blender.blend_pix(pdst,
1123  psrc[src_order::R],
1124  psrc[src_order::G],
1125  psrc[src_order::B],
1126  alpha,
1127  cover);
1128  }
1129  }
1130  psrc += 4;
1131  ++pdst;
1132  }
1133  while(--len);
1134  }
1135  }
1136 
1137  //--------------------------------------------------------------------
1138  template<class SrcPixelFormatRenderer>
1139  void blend_from_color(const SrcPixelFormatRenderer& from,
1140  const color_type& color,
1141  int xdst, int ydst,
1142  int xsrc, int ysrc,
1143  unsigned len,
1144  int8u cover)
1145  {
1146  typedef typename SrcPixelFormatRenderer::value_type src_value_type;
1147  typedef typename SrcPixelFormatRenderer::color_type src_color_type;
1148  const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
1149  if(psrc)
1150  {
1151  psrc += xsrc * SrcPixelFormatRenderer::pix_step + SrcPixelFormatRenderer::pix_offset;
1152  pixel_type* pdst =
1153  (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
1154 
1155  do
1156  {
1157  m_blender.blend_pix(pdst,
1158  color.r, color.g, color.b, color.a,
1159  cover);
1160  psrc += SrcPixelFormatRenderer::pix_step;
1161  ++pdst;
1162  }
1163  while(--len);
1164  }
1165  }
1166 
1167  //--------------------------------------------------------------------
1168  template<class SrcPixelFormatRenderer>
1169  void blend_from_lut(const SrcPixelFormatRenderer& from,
1170  const color_type* color_lut,
1171  int xdst, int ydst,
1172  int xsrc, int ysrc,
1173  unsigned len,
1174  int8u cover)
1175  {
1176  typedef typename SrcPixelFormatRenderer::value_type src_value_type;
1177  const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
1178  if(psrc)
1179  {
1180  psrc += xsrc * SrcPixelFormatRenderer::pix_step + SrcPixelFormatRenderer::pix_offset;
1181  pixel_type* pdst =
1182  (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
1183 
1184  do
1185  {
1186  const color_type& color = color_lut[*psrc];
1187  m_blender.blend_pix(pdst,
1188  color.r, color.g, color.b, color.a,
1189  cover);
1190  psrc += SrcPixelFormatRenderer::pix_step;
1191  ++pdst;
1192  }
1193  while(--len);
1194  }
1195  }
1196 
1197 
1198 
1199  private:
1200  rbuf_type* m_rbuf;
1201  Blender m_blender;
1202  };
1203 
1206 
1209 
1214 
1219 
1220 
1221  //-----------------------------------------------------pixfmt_rgb555_gamma
1222  template<class Gamma> class pixfmt_rgb555_gamma :
1223  public pixfmt_alpha_blend_rgb_packed<blender_rgb555_gamma<Gamma>,
1224  rendering_buffer>
1225  {
1226  public:
1227  pixfmt_rgb555_gamma(rendering_buffer& rb, const Gamma& g) :
1229  rendering_buffer>(rb)
1230  {
1231  this->blender().gamma(g);
1232  }
1233  };
1234 
1235 
1236  //-----------------------------------------------------pixfmt_rgb565_gamma
1237  template<class Gamma> class pixfmt_rgb565_gamma :
1238  public pixfmt_alpha_blend_rgb_packed<blender_rgb565_gamma<Gamma>, rendering_buffer>
1239  {
1240  public:
1241  pixfmt_rgb565_gamma(rendering_buffer& rb, const Gamma& g) :
1243  {
1244  this->blender().gamma(g);
1245  }
1246  };
1247 
1248 
1249  //-----------------------------------------------------pixfmt_rgbAAA_gamma
1250  template<class Gamma> class pixfmt_rgbAAA_gamma :
1251  public pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_gamma<Gamma>,
1252  rendering_buffer>
1253  {
1254  public:
1255  pixfmt_rgbAAA_gamma(rendering_buffer& rb, const Gamma& g) :
1257  rendering_buffer>(rb)
1258  {
1259  this->blender().gamma(g);
1260  }
1261  };
1262 
1263 
1264  //-----------------------------------------------------pixfmt_bgrAAA_gamma
1265  template<class Gamma> class pixfmt_bgrAAA_gamma :
1266  public pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_gamma<Gamma>,
1267  rendering_buffer>
1268  {
1269  public:
1270  pixfmt_bgrAAA_gamma(rendering_buffer& rb, const Gamma& g) :
1272  rendering_buffer>(rb)
1273  {
1274  this->blender().gamma(g);
1275  }
1276  };
1277 
1278 
1279  //-----------------------------------------------------pixfmt_rgbBBA_gamma
1280  template<class Gamma> class pixfmt_rgbBBA_gamma :
1281  public pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_gamma<Gamma>,
1282  rendering_buffer>
1283  {
1284  public:
1285  pixfmt_rgbBBA_gamma(rendering_buffer& rb, const Gamma& g) :
1287  rendering_buffer>(rb)
1288  {
1289  this->blender().gamma(g);
1290  }
1291  };
1292 
1293 
1294  //-----------------------------------------------------pixfmt_bgrABB_gamma
1295  template<class Gamma> class pixfmt_bgrABB_gamma :
1296  public pixfmt_alpha_blend_rgb_packed<blender_bgrABB_gamma<Gamma>,
1297  rendering_buffer>
1298  {
1299  public:
1300  pixfmt_bgrABB_gamma(rendering_buffer& rb, const Gamma& g) :
1302  rendering_buffer>(rb)
1303  {
1304  this->blender().gamma(g);
1305  }
1306  };
1307 
1308 
1309 }
1310 
1311 #endif
1312 
Definition: agg_arc.cpp:24