3 * (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
4 * economic rights: Technische Universität Dresden (Germany)
6 * This file is part of TUD:OS and distributed under the terms of the
7 * GNU General Public License 2.
8 * Please see the COPYING-GPL-2 file for details.
12 #include <l4/mag-gfx/canvas>
13 #include <l4/mag-gfx/mem_texture>
14 #include <l4/mag-gfx/font>
15 #include <l4/mag-gfx/blit>
20 template< typename PT >
21 class Canvas : public Mag_gfx::Canvas
24 typedef PT Pixel_traits;
25 typedef typename PT::Pixel Pixel;
26 typedef typename PT::Color Color;
30 Pixel_info const *_type;
34 Canvas(void *pixels, Area const &size, unsigned bpl)
35 : Mag_gfx::Canvas(size), _pixels((char *)pixels), _type(PT::type()), _bpl(bpl)
38 Pixel_info const *type() const { return _type; }
40 void *buffer() const { return _pixels; }
41 void buffer(void *buf) { _pixels = (char *)buf; }
42 int bytes_per_line() const { return _bpl; }
45 template< typename CT >
46 void _draw_box(char *dst_line, int _w, int h, CT color, int a)
48 Color const c = color_conv<Color>(color);
49 for (; h--; dst_line += _bpl)
52 Pixel *dst = reinterpret_cast<Pixel*>(dst_line);
53 for (w = _w; w--; dst++)
57 *dst = Color::Traits::mix(*dst, c, a);
61 template< typename CT >
62 void __draw_string(Point const &p, Font const *font,
63 typename CT::Color color,
64 char const *_str, unsigned len)
66 enum { Alphas = CT::A::Size };
67 const unsigned char *str = (const unsigned char *)_str;
68 int x = p.x(), y = p.y();
73 unsigned char const *src = font->img;
74 int d, h = font->str_h(_str);
76 /* check top clipping */
77 if ((d = _clip.y1() - y) > 0)
84 /* check bottom clipping */
85 if ((d = y + h - 1 - _clip.y2()) > 0)
91 /* skip hidden glyphs */
92 for ( ; *str && len && (x + font->wtab[*str] < _clip.x1()); --len)
93 x += font->wtab[*str++];
97 char *dst = _pixels + y * _bpl;
98 Color pix = color_conv<Color>(color);
101 alpha = color.a() << (8 - Alphas);
104 for ( ; *str && len && (x <= _clip.x2()); ++str, --len)
106 int w = font->wtab[*str];
107 int start = std::max(0, _clip.x1() - x);
108 int end = std::min(w - 1, _clip.x2() - x);
109 char *d = dst + x * sizeof(Pixel);
110 unsigned char const *s = src + font->otab[*str];
112 for (int j = 0; j < h; ++j, s += font->w, d += _bpl)
113 for (int i = start; i <= end; ++i)
116 Pixel *p = reinterpret_cast<Pixel *>(d) + i;
117 *p = Pixel_traits::mix(*p, pix, (alpha * s[i]) >> 8);
123 flush_pixels(Rect(Point(x_start, y), Area(x - x_start + 1, h)));
126 bool _draw_alpha_texture(Texture<Pixel_traits> const *texture,
127 Pixel const *src, char *dst, int offset,
128 int h, int w, int src_w)
130 typedef typename Pixel_traits::Pixel Pixel;
131 bool xa = !Pixel_traits::A::Size && texture->extra_alpha();
132 if (!xa && !Pixel_traits::A::Size)
135 unsigned char const *ab;
137 ab = texture->alpha_buffer() + offset;
139 for (int j = h; j--; src += src_w, dst += _bpl)
141 Pixel *dp = reinterpret_cast<Pixel*>(dst);
142 Pixel const *s = src;
143 unsigned char const *sab = ab;
145 for (int i = w; i--; ++s, ++dp)
149 alpha = Color(*s).a() << (8 - Pixel_traits::A::Size);
154 *dp = Pixel_traits::mix(*dp, *s, alpha);
165 void draw_box(Rect const &rect, Rgba32::Color color)
167 Rect const clipped = _clip & rect;
168 if (!clipped.valid() || color.a() == 0)
171 char *dst_line = _pixels + _bpl*clipped.y1() + sizeof(Pixel)*clipped.x1();
173 if (color.a() >= 255)
174 _draw_box(dst_line, clipped.w(), clipped.h(), Rgb32::Color(color.v()), 0);
176 _draw_box(dst_line, clipped.w(), clipped.h(), color, color.a());
178 flush_pixels(clipped);
181 void draw_string(Point const &p, Font const *font, Rgba32::Color color,
182 char const *_str, unsigned len)
184 if (color.a() != Rgba32::Color::Amax)
185 __draw_string<Rgba32>(p, font, color, _str, len);
187 __draw_string<Rgb32>(p, font, Rgb32::Color(color.v()), _str, len);
190 void draw_texture(Mag_gfx::Texture const *texture, Rgb32::Color mix_color,
191 Point const &pos, Mix_mode mode)
193 Rect const clipped = _clip & Rect(pos, texture->size());
195 if (!clipped.valid())
198 int src_w = texture->size().w();
199 Texture<Pixel_traits> const *txt;
200 txt = static_cast<Texture<Pixel_traits> const *>(texture);
201 Pixel const *src = txt->pixels()
202 + (clipped.y1() - pos.y()) * src_w
203 + clipped.x1() - pos.x();
205 char *dst = _pixels + clipped.y1() * _bpl + clipped.x1() * sizeof(Pixel);
210 Color mix_pixel = color_conv<Color>(mix_color);
215 if (_draw_alpha_texture(txt, src, dst,
216 (clipped.y1() - pos.y()) * src_w + clipped.x1() - pos.x(),
217 clipped.h(), clipped.w(), src_w))
219 // Fall through to solid!
221 // for (j = clipped.h(); j--; src += src_w, dst += _bpl)
222 // for (i = clipped.w(), s = src, d = dst; i--; ++s, d += sizeof(Pixel))
223 // *reinterpret_cast<Pixel*>(d) = *s;
224 Blit::blit(src, src_w * sizeof(Pixel),
225 dst, _bpl, clipped.w() * sizeof(Pixel), clipped.h());
229 mix_pixel = color_50(mix_pixel);
230 for (j = clipped.h(); j--; src += src_w, dst += _bpl)
231 for (i = clipped.w(), s = src, d = dst; i--; ++s, d += sizeof(Pixel))
232 *reinterpret_cast<Pixel*>(d) = color_50(Color(*s)) + mix_pixel;
236 for (j = clipped.h(); j--; src += src_w, dst += _bpl)
237 for (i = clipped.w(), s = src, d = dst; i--; ++s, d += sizeof(Pixel))
239 *reinterpret_cast<Pixel*>(d) = *s;
243 flush_pixels(clipped);