]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/mag-gfx/include/gfx_colors
Inital import
[l4.git] / l4 / pkg / mag-gfx / include / gfx_colors
1 // vi:ft=cpp
2
3 #pragma once
4
5 #include <l4/sys/types.h>
6 #include <l4/re/video/colors>
7
8
9 namespace Mag_gfx
10 {
11
12 /*** PRIVATE Murx */
13 namespace _Local
14 {
15
16   /*** int-to-type template */
17   template< int X >
18   class IT
19   {};
20
21   /*** Conversion for a single color component */
22   template< typename From, typename To >
23   static inline typename To::Value convert_comp(typename From::Value c, IT<true> const &)
24   {
25     enum { Sh = From::Shift - To::Shift + From::Size - To::Size };
26     return ((c & From::Mask) >> Sh) & To::Mask;
27   }
28
29   template< typename From, typename To >
30   static inline typename To::Value convert_comp(typename From::Value c, IT<false> const &)
31   {
32     enum { Sh = From::Shift - To::Shift + From::Size - To::Size };
33     return (((typename To::Value)(c & From::Mask)) << -Sh) & To::Mask;
34   }
35
36   template< typename From, typename To >
37   static inline typename To::Value convert_comp(typename From::Value c)
38   {
39     enum { Sh = From::Shift - To::Shift + From::Size - To::Size };
40     return convert_comp<From, To>(c, IT<(Sh > 0)>());
41   }
42
43
44   /*** Trivial pixel type with a size of a native data type and size-alignment. */
45   template< typename T >
46   class Trivial_pixel
47   {
48   private:
49     T _v; /* refernece to video memory representation */
50   public:
51     typedef T Value;
52     enum { Bpp = sizeof(T) };
53
54     Trivial_pixel() {}
55     explicit Trivial_pixel(T v) : _v(v) {}
56
57     T v() const { return _v; }
58   } __attribute__((packed));
59 }
60
61 /*** Encapsulation of properties of a pixel */
62 /* A pixel occupies the given number of bytes in video memory and
63  * has a representation in a some machine useable type (byte, short,
64  * unsigned).
65  */
66 template< int Bytes >
67 class Pixel_traits;
68
69 /*** Spezilization for 2byte */
70 template<>
71 class Pixel_traits<2>
72 {
73 public:
74   typedef _Local::Trivial_pixel<l4_uint16_t> Pixel;
75 };
76
77 /*** Spezialization for 4byte */
78 template<>
79 class Pixel_traits<4>
80 {
81 public:
82   typedef _Local::Trivial_pixel<l4_uint32_t> Pixel;
83 };
84
85
86 /*** Spezialization for 3byte */
87 template<>
88 class Pixel_traits<3>
89 {
90 public:
91   /*** Encapsulation for 3byte memory references */
92   /* Looks like a pointer to a native data type  */
93   class Pixel
94   {
95   public:
96     enum { Bpp = 3 };
97     typedef l4_uint32_t Value;
98
99   private:
100     char _b[3];
101     Value get() const 
102     { return (Value)(*(l4_uint16_t const *)_b) | ((l4_uint32_t)_b[2] << 16); }
103
104   public:
105     Pixel() {}
106
107     explicit Pixel(Value c)
108     {
109       *(l4_uint16_t*)_b = (l4_uint16_t)c;
110       _b[2] = c >> 16;
111     }
112
113     Value v() const { return get(); }
114   } __attribute__((packed));
115 };
116
117 class Factory;
118
119 struct Pixel_info : public L4Re::Video::Pixel_info
120 {
121   Factory *factory;
122
123   Pixel_info(char bytes, char r, char rs, char g, char gs,
124              char b, char bs, char a, char as)
125   : L4Re::Video::Pixel_info(bytes, r, rs, g, gs, b, bs, a, as)
126   {}
127
128   struct Color
129   {
130     int r, g, b, a;
131     Color(int r, int g, int b, int a = 0xffff) : r(r), g(g), b(b), a(a) {}
132   };
133
134   Color get(void const *d) const
135   {
136     unsigned v;
137     switch (bytes_per_pixel())
138       {
139       case 2:
140         v = *(unsigned short const *)d;
141         break;
142
143       case 3:
144       case 4:
145         v = *(unsigned const *)d;
146         break;
147
148       default:
149         v = 0;
150         break;
151       }
152     return Color(r().get(v), g().get(v), b().get(v), a().get(v));
153   }
154
155   void set(void *d, Color const &c) const
156   {
157     unsigned v = r().set(c.r) | g().set(c.g) | b().set(c.b) | a().set(c.a);
158     switch (bytes_per_pixel())
159       {
160       case 2:
161         *(unsigned short *)d = v;
162         break;
163
164       case 3:
165           {
166             char *_d = (char *)d;
167             _d[0] = v;
168             _d[1] = v >> 8; 
169             _d[2] = v >> 16; 
170             break;
171           }
172       case 4:
173         *(unsigned *)d = v;
174         break;
175
176       default:
177         break;
178       }
179   }
180 };
181
182
183 template<
184         typename PT,
185         int _Rshift, int _Rsize,
186         int _Gshift, int _Gsize,
187         int _Bshift, int _Bsize,
188         int _Ashift = 0, int _Asize = 0
189 >
190 struct Color_def
191 {
192   enum { Extra_alpha = 128 };
193   typedef typename PT::Pixel Pixel;
194   template< int _size, int _shift >
195   struct C { enum { Size = _size, Shift = _shift }; };
196
197   typedef C<_Rsize, _Rshift> R;
198   typedef C<_Gsize, _Gshift> G;
199   typedef C<_Bsize, _Bshift> B;
200   typedef C<_Asize, _Ashift> A;
201
202 };
203
204 namespace _Local {
205   template< template < class UT > class CT, typename CD, bool AC >
206   struct Alpha_traits;
207
208   template< template < class UT > class CT, typename CD >
209   struct Alpha_traits< CT, CD, true >
210   {
211     typedef CT< Color_def< Pixel_traits< CD::Pixel::Bpp >,
212             CD::R::Shift, CD::R::Size,
213             CD::G::Shift, CD::G::Size,
214             CD::B::Shift, CD::B::Size> > No_alpha;
215
216     typedef CT<CD> Alpha;
217   };
218
219   template< template < class UT > class CT, typename CD >
220   struct Alpha_traits< CT, CD, false >
221   {
222     typedef CT<CD> No_alpha;
223     typedef CT< Color_def<  Pixel_traits< CD::Pixel::Bpp >,
224             CD::R::Shift, CD::R::Size,
225             CD::G::Shift, CD::G::Size,
226             CD::B::Shift, CD::B::Size> > Alpha;
227   };
228 }
229
230 /*** Encapsulation of color bit fields of any kind */
231 /* _Pixel                 must be the Pixel for the mode.
232  * _<X>shift and _<X>size is the bit shift and number of bits used for
233  *                        each color (and alpha)
234  *
235  * Local types are:
236  *   Color   the register representation of a color.
237  *   Pixel   the reference to a pixel in video memory.
238  *   R,G,B,A the traits for the single components
239  *           (define Shift, Size, and Mask for each color component)
240  *   C_space the sorted representation of the color components,
241  *           Used to find the uppermost, middle, and lowermost component
242  *           of a pixel
243  *
244  * Static methods:
245  *   blend   does optimized alpha blending
246  */
247 template< typename CD >
248 class Color_traits
249 {
250 public:
251   class Pixel : public CD::Pixel
252   {
253   public:
254     typedef Color_traits<CD> Traits;
255
256     Pixel() {}
257
258     explicit Pixel(typename CD::Pixel::Value v)
259     : CD::Pixel(v)
260     {}
261   } __attribute__((packed));
262
263   typedef Color_traits<CD> This;
264   enum
265   {
266     Bpp = CD::Pixel::Bpp,
267     Bpp_xalpha = Bpp + (CD::A::Size == 0),
268     Need_extra_alpha = (CD::A::Size == 0)
269   };
270
271   static int bytes_per_pixel(bool alpha) { return alpha ? Bpp_xalpha : Bpp; }
272
273   template< int _Shift, int _Size, typename _C = typename CD::Pixel::Value >
274   class Component
275   {
276   public:
277     typedef _C Value;
278     enum
279     {
280       Shift = _Shift,
281       Size  = _Size,
282       Mask  = ((1UL << Size) - 1) << Shift
283     };
284
285     static unsigned get(Value c)
286     { return (c & Mask) >> Shift; }
287   };
288
289   typedef Component<CD::R::Shift, CD::R::Size> R;
290   typedef Component<CD::G::Shift, CD::G::Size> G;
291   typedef Component<CD::B::Shift, CD::B::Size> B;
292   typedef Component<CD::A::Shift, CD::A::Size> A;
293
294   /** Sorting template for color components. */
295   template<
296     typename _R,
297     typename _G,
298     typename _B,
299     bool _RG = ((unsigned)_R::Shift > (unsigned)_G::Shift),
300     bool _RB = ((unsigned)_R::Shift > (unsigned)_B::Shift),
301     bool _BG = ((unsigned)_B::Shift > (unsigned)_G::Shift)
302   >
303   class C_list;
304
305   template< typename _R, typename _G, typename _B >
306   class C_list<_R, _G, _B, true, true, true>
307   {
308   public:
309     typedef _R Msb;
310     typedef _B Mid;
311     typedef _G Lsb;
312   };
313
314   template< typename _R, typename _G, typename _B >
315   class C_list<_R, _G, _B, true, true, false>
316   {
317   public:
318     typedef _R Msb;
319     typedef _G Mid;
320     typedef _B Lsb;
321   };
322
323   template< typename _R, typename _G, typename _B >
324   class C_list<_R, _G, _B, true, false, true>
325   {
326   public:
327     typedef _B Msb;
328     typedef _R Mid;
329     typedef _G Lsb;
330   };
331
332   template< typename _R, typename _G, typename _B >
333   class C_list<_R, _G, _B, false, true, false>
334   {
335   public:
336     typedef _G Msb;
337     typedef _R Mid;
338     typedef _B Lsb;
339   };
340
341   template< typename _R, typename _G, typename _B >
342   class C_list<_R, _G, _B, false, false, false>
343   {
344   public:
345     typedef _G Msb;
346     typedef _B Mid;
347     typedef _R Lsb;
348   };
349
350   template< typename _R, typename _G, typename _B >
351   class C_list<_R, _G, _B, false, false, true>
352   {
353   public:
354     typedef _B Msb;
355     typedef _G Mid;
356     typedef _R Lsb;
357   };
358
359   class C_space : public C_list<R,G,B>
360   {
361   public:
362     enum
363     {
364       Mix_mask = (R::Mask | G::Mask | B::Mask)
365                  & ~((1UL << R::Shift) | (1UL << G::Shift) 
366                       | (1UL << B::Shift))
367     };
368   };
369
370 public:
371   typedef typename _Local::Alpha_traits<Mag_gfx::Color_traits, CD, (A::Size > 0)>::No_alpha No_alpha;
372   typedef typename _Local::Alpha_traits<Mag_gfx::Color_traits, CD, (A::Size > 0)>::Alpha Alpha;
373
374   /** Encasulation for a color value of this color mode.
375    * The Color type is an efficient native representation of the color
376    * of a pixel for this color mode.  It is designed to be kept in a
377    * machine register.
378    */
379   class Color
380   {
381   public:
382     /** The value type (native data type to carry the color value. */
383     typedef typename CD::Pixel::Value Value;
384
385     /** The info for the red component of the color. */
386     typedef typename This::R R;
387
388     /** The info for the green component of the color. */
389     typedef typename This::G G;
390
391     /** The info for the blue component of the color. */
392     typedef typename This::B B;
393
394     /** The info for the alpha channel of the color. */
395     typedef typename This::A A;
396
397     /** Reference to the surrounding color traits. */
398     typedef This Traits;
399
400     enum { Mix_mask = C_space::Mix_mask };
401     enum { Amax     = (1UL << A::Size) - 1 };
402
403   private:
404     Value _c;
405
406     static Value _m(unsigned v, int s, unsigned m)
407     {
408       if (s < 0)
409         return (v >> (-s)) & m;
410       else
411         return (v << s) & m;
412     }
413
414   public:
415
416     explicit Color(Value v) : _c(v) {}
417     Color() {}
418     Color(Pixel p) : _c(p.v()) {}
419     Color(Pixel_info::Color const &c)
420     : _c(_m(c.r, R::Shift - 16 + R::Size, R::Mask)
421         |_m(c.g, G::Shift - 16 + G::Size, G::Mask)
422         |_m(c.b, B::Shift - 16 + B::Size, B::Mask)
423         |_m(c.a, A::Shift - 16 + A::Size, A::Mask))
424     {}
425
426     Color(typename No_alpha::Color const &o)
427     : _c(o.v() | ((Value)Amax << A::Shift))
428     {}
429
430     Color(typename No_alpha::Color const &o, int a)
431     : _c(o.v() | ((Value)a << A::Shift))
432     {}
433
434     Color(int r, int g, int b, int a = Amax)
435     : _c((r << R::Shift) | (g << G::Shift) | (b << B::Shift) 
436          | ((Value)a << A::Shift))
437     {}
438
439     int r() const { return (_c & R::Mask) >> R::Shift; }
440     int g() const { return (_c & G::Mask) >> G::Shift; }
441     int b() const { return (_c & B::Mask) >> B::Shift; }
442     int a() const { return A::Size ? (_c & A::Mask) >> A::Shift : (Value)Amax; }
443
444     Value v() const { return _c; }
445     //operator Value () const { return _c; }
446     operator Pixel () const { return Pixel(_c); }
447
448     Color operator + (Color const &o) const { return Color(_c + o._c); }
449   };
450
451   /** Blend color with alpha value (0-255).
452    * \param color The original color.
453    * \param alpha The alpha value (0 = Transparent, 255 = Opaque)
454    */
455   static Color blend(Color color, int alpha)
456   {
457     enum
458     {
459       AMask = C_space::Msb::Mask | C_space::Lsb::Mask,
460       BMask = C_space::Mid::Mask,
461       Gap   = C_space::Mid::Size,
462       AAs   = 8 - Gap,
463       As    = Gap,
464       Bs    = 8
465     };
466
467     return Color(((((alpha >> AAs) * (color.v() & AMask)) >> As) & AMask)
468            | (((alpha * (color.v() & BMask)) >> Bs) & BMask));
469   }
470
471   /** Mix background and foreground color with alpha blending.
472    * \param bg The background color.
473    * \param fg the foreground color.
474    * \param alpha The alpha value of the foreground (0 = Transparent, 255 = Opaque)
475    */
476   static Color mix(Color bg, Color fg, int alpha)
477   {
478     if (alpha == 255)
479       return fg;
480     else
481       return blend(bg, 256 - alpha) + blend(fg, alpha);
482   }
483
484   /** Calculate the avarage of two colors.
485    * \param c1 The first color.
486    * \param c2 The second color.
487    * \return The average value.
488    */
489   static Color avr(Color c1, Color c2)
490   {
491     return Color(((c1.v() & Color::Mix_mask) >> 1) + ((c2.v() & Color::Mix_mask) >> 1));
492   }
493
494   /** Calculate the avarage of four colors.
495    * \param c1 The first color.
496    * \param c2 The second color.
497    * \param c3 The third color.
498    * \param c4 The fourth color.
499    * \return The average value.
500    */
501   static Color avr(Color c1, Color c2, Color c3, Color c4)
502   { return avr(avr(c1, c2), avr(c3, c4)); }
503
504   typedef Pixel_info const *Type;
505   /** Returns a pointer to the dynamic pixel info for the color mode. */
506   static Type type()
507   {
508     static Pixel_info pixel_info
509       (
510         CD::Pixel::Bpp,
511         CD::R::Size, CD::R::Shift,
512         CD::G::Size, CD::G::Shift,
513         CD::B::Size, CD::B::Shift,
514         CD::A::Size, CD::A::Shift
515       );
516
517     return &pixel_info;
518   }
519
520   /** Often used color black. */
521   static Color const Black;
522
523   /** Otfen used color White. */
524   static Color const White;
525 };
526
527
528 template< typename CD >
529 typename Color_traits<CD>::Color const Color_traits<CD>::Black(0);
530
531 template< typename CD >
532 typename Color_traits<CD>::Color const Color_traits<CD>::White(~0, ~0, ~0);
533
534
535
536 namespace _Local {
537
538   /* Provides:
539    *   convert   to convert a single color from one color space to another
540    *   blit      paints the given color to the given pixel, does color
541    *             conversion if necessary, and considers alpha values if
542    *             available
543    */
544   template< typename From, typename To >
545   class Conv
546   {
547   public:
548     typedef typename To::Color T_color;
549     typedef typename To::Pixel T_pixel;
550     typedef typename From::Color F_color;
551
552     static T_color convert(F_color c)
553     {
554       typedef typename To::R TR;
555       typedef typename To::G TG;
556       typedef typename To::B TB;
557       typedef typename From::R FR;
558       typedef typename From::G FG;
559       typedef typename From::B FB;
560       return T_color(convert_comp<FR, TR>(c.v())
561           | convert_comp<FG, TG>(c.v())
562           | convert_comp<FB, TB>(c.v()));
563     }
564
565     static void blit(F_color c, T_pixel *d)
566     {
567       if (From::A::Size > 0)
568         *d = To::blend(convert(c), From::A::get(c))
569           + To::blend(*d, 255 - From::A::get(c));
570       else
571         *d = convert(c);
572     }
573
574   };
575
576   /*** Specialized conversion if source and target color space are equal */
577   template< typename T >
578   class Conv<T,T>
579   {
580   public:
581     typedef typename T::Color T_color;
582     typedef typename T::Pixel T_pixel;
583     typedef typename T::Color F_color;
584
585     static T_color convert(F_color c) { return c; }
586     static void blit(F_color c, T_pixel *d)
587     {
588       if (T::A::Size > 0)
589         *d = T::blend(c, T::A::get(c)) + T::blend(*d, 255 - T::A::get(c));
590       else
591         *d = c;
592     }
593   };
594
595 } // _Local
596
597 template< typename C1, typename C2 >
598 C1 color_conv(C2 c)
599 { return _Local::Conv<typename C2::Traits, typename C1::Traits>::convert(c); }
600
601 template< typename C >
602 C color_50(C const &c)
603 { return C((c.v() & (typename C::Value)C::Mix_mask) >> 1); }
604
605
606 /*** Typical instances for color spaces */
607 typedef Color_traits<Color_def<Pixel_traits<2>, 10,5,5,5,0,5> >      Rgb15;
608 typedef Color_traits<Color_def<Pixel_traits<2>, 0,5,5,5,10,5> >      Bgr15;
609 typedef Color_traits<Color_def<Pixel_traits<2>, 11,5,5,6,0,5> >      Rgb16;
610 typedef Color_traits<Color_def<Pixel_traits<2>, 0,5,5,6,11,5> >      Bgr16;
611 typedef Color_traits<Color_def<Pixel_traits<3>, 16,8,8,8,0,8> >      Rgb24;
612 typedef Color_traits<Color_def<Pixel_traits<4>, 16,8,8,8,0,8> >      Rgb32;
613 typedef Color_traits<Color_def<Pixel_traits<4>, 16,8,8,8,0,8,24,8> > Rgba32;
614
615 }