draw_text: support YUV modes
[android/external-libkmsxx.git] / kms++util / src / drawing.cpp
2 #include <kms++/kms++.h>
3 #include <kms++util/kms++util.h>
5 using namespace std;
7 namespace kms
8 {
9 void draw_rgb_pixel(IMappedFramebuffer& buf, unsigned x, unsigned y, RGB color)
10 {
11         switch (buf.format()) {
12         case PixelFormat::XRGB8888:
13         case PixelFormat::ARGB8888:
14         {
15                 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
16                 *p = color.argb8888();
17                 break;
18         }
19         case PixelFormat::XBGR8888:
20         case PixelFormat::ABGR8888:
21         {
22                 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
23                 *p = color.abgr8888();
24                 break;
25         }
26         case PixelFormat::RGB565:
27         {
28                 uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
29                 *p = color.rgb565();
30                 break;
31         }
32         default:
33                 throw std::invalid_argument("invalid pixelformat");
34         }
35 }
37 void draw_yuv422_macropixel(IMappedFramebuffer& buf, unsigned x, unsigned y, YUV yuv1, YUV yuv2)
38 {
39         ASSERT((x & 1) == 0);
41         uint8_t *p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
43         uint8_t y0 = yuv1.y;
44         uint8_t y1 = yuv2.y;
45         uint8_t u = (yuv1.u + yuv2.u) / 2;
46         uint8_t v = (yuv1.v + yuv2.v) / 2;
48         switch (buf.format()) {
49         case PixelFormat::UYVY:
50                 p[0] = u;
51                 p[1] = y0;
52                 p[2] = v;
53                 p[3] = y1;
54                 break;
56         case PixelFormat::YUYV:
57                 p[0] = y0;
58                 p[1] = u;
59                 p[2] = y1;
60                 p[3] = v;
61                 break;
63         case PixelFormat::YVYU:
64                 p[0] = y0;
65                 p[1] = v;
66                 p[2] = y1;
67                 p[3] = u;
68                 break;
70         case PixelFormat::VYUY:
71                 p[0] = v;
72                 p[1] = y0;
73                 p[2] = u;
74                 p[3] = y1;
75                 break;
77         default:
78                 throw std::invalid_argument("invalid pixelformat");
79         }
80 }
82 void draw_yuv420_macropixel(IMappedFramebuffer& buf, unsigned x, unsigned y,
83                             YUV yuv1, YUV yuv2, YUV yuv3, YUV yuv4)
84 {
85         ASSERT((x & 1) == 0);
86         ASSERT((y & 1) == 0);
88         uint8_t *py1 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 0) + x);
89         uint8_t *py2 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 1) + x);
91         uint8_t *puv = (uint8_t*)(buf.map(1) + buf.stride(1) * (y / 2) + x);
93         uint8_t y0 = yuv1.y;
94         uint8_t y1 = yuv2.y;
95         uint8_t y2 = yuv3.y;
96         uint8_t y3 = yuv4.y;
97         uint8_t u = (yuv1.u + yuv2.u + yuv3.u + yuv4.u) / 4;
98         uint8_t v = (yuv1.v + yuv2.v + yuv3.v + yuv4.v) / 4;
100         switch (buf.format()) {
101         case PixelFormat::NV12:
102                 py1[0] = y0;
103                 py1[1] = y1;
104                 py2[0] = y2;
105                 py2[1] = y3;
106                 puv[0] = u;
107                 puv[1] = v;
108                 break;
110         case PixelFormat::NV21:
111                 py1[0] = y0;
112                 py1[1] = y1;
113                 py2[0] = y2;
114                 py2[1] = y3;
115                 puv[0] = v;
116                 puv[1] = u;
117                 break;
119         default:
120                 throw std::invalid_argument("invalid pixelformat");
121         }
124 void draw_rect(IMappedFramebuffer &fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, RGB color)
126         for (unsigned i = x; i < x + w; ++i) {
127                 for (unsigned j = y; j < y + h; ++j) {
128                         draw_rgb_pixel(fb, i, j, color);
129                 }
130         }
133 static bool get_char_pixel(char c, uint32_t x, uint32_t y)
135 #include "font_8x8.h"
137         uint8_t bits = fontdata_8x8[8 * c + y];
138         bool bit = (bits >> (7 - x)) & 1;
140         return bit;
143 static void draw_char(IMappedFramebuffer& buf, uint32_t xpos, uint32_t ypos, char c, RGB color)
145         unsigned x, y;
146         YUV yuvcolor = color.yuv();
148         switch (buf.format()) {
149         case PixelFormat::XRGB8888:
150         case PixelFormat::XBGR8888:
151         case PixelFormat::ARGB8888:
152         case PixelFormat::ABGR8888:
153         case PixelFormat::RGB565:
154                 for (y = 0; y < 8; y++) {
155                         for (x = 0; x < 8; x++) {
156                                 bool b = get_char_pixel(c, x, y);
158                                 draw_rgb_pixel(buf, xpos + x, ypos + y, b ? color : RGB());
159                         }
160                 }
161                 break;
163         case PixelFormat::UYVY:
164         case PixelFormat::YUYV:
165         case PixelFormat::YVYU:
166         case PixelFormat::VYUY:
167                 for (y = 0; y < 8; y++) {
168                         for (x = 0; x < 8; x += 2) {
169                                 bool b0 = get_char_pixel(c, x, y);
170                                 bool b1 = get_char_pixel(c, x + 1, y);
172                                 draw_yuv422_macropixel(buf, xpos + x, ypos + y,
173                                                        b0 ? yuvcolor : YUV(), b1 ? yuvcolor : YUV());
174                         }
175                 }
176                 break;
178         case PixelFormat::NV12:
179         case PixelFormat::NV21:
180                 for (y = 0; y < 8; y += 2) {
181                         for (x = 0; x < 8; x += 2) {
182                                 bool b00 = get_char_pixel(c, x, y);
183                                 bool b10 = get_char_pixel(c, x + 1, y);
184                                 bool b01 = get_char_pixel(c, x, y + 1);
185                                 bool b11 = get_char_pixel(c, x + 1, y + 1);
187                                 draw_yuv420_macropixel(buf, xpos + x, ypos + y,
188                                                        b00 ? yuvcolor : YUV(), b10 ? yuvcolor : YUV(),
189                                                        b01 ? yuvcolor : YUV(), b11 ? yuvcolor : YUV());
190                         }
191                 }
192                 break;
193         default:
194                 throw std::invalid_argument("unknown pixelformat");
195         }
198 void draw_text(IMappedFramebuffer& buf, uint32_t x, uint32_t y, const string& str, RGB color)
200         for(unsigned i = 0; i < str.size(); i++)
201                 draw_char(buf, (x + 8 * i), y, str[i], color);