1
2 #include <cmath>
3
4 #include <kms++/kms++.h>
5 #include <kms++util/kms++util.h>
6
7 using namespace std;
8
9 namespace kms
10 {
draw_rgb_pixel(IFramebuffer & buf,unsigned x,unsigned y,RGB color)11 void draw_rgb_pixel(IFramebuffer& buf, unsigned x, unsigned y, RGB color)
12 {
13 if (x >= buf.width() || y >= buf.height())
14 throw runtime_error("attempt to draw outside the buffer");
15
16 switch (buf.format()) {
17 case PixelFormat::XRGB8888:
18 case PixelFormat::ARGB8888:
19 {
20 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
21 *p = color.argb8888();
22 break;
23 }
24 case PixelFormat::XBGR8888:
25 case PixelFormat::ABGR8888:
26 {
27 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
28 *p = color.abgr8888();
29 break;
30 }
31 case PixelFormat::RGBX8888:
32 case PixelFormat::RGBA8888:
33 {
34 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
35 *p = color.rgba8888();
36 break;
37 }
38 case PixelFormat::BGRX8888:
39 case PixelFormat::BGRA8888:
40 {
41 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
42 *p = color.bgra8888();
43 break;
44 }
45 case PixelFormat::XRGB2101010:
46 case PixelFormat::ARGB2101010:
47 {
48 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
49 *p = color.argb2101010();
50 break;
51 }
52 case PixelFormat::XBGR2101010:
53 case PixelFormat::ABGR2101010:
54 {
55 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
56 *p = color.abgr2101010();
57 break;
58 }
59 case PixelFormat::RGBX1010102:
60 case PixelFormat::RGBA1010102:
61 {
62 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
63 *p = color.rgba1010102();
64 break;
65 }
66 case PixelFormat::BGRX1010102:
67 case PixelFormat::BGRA1010102:
68 {
69 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
70 *p = color.bgra1010102();
71 break;
72 }
73 case PixelFormat::RGB888:
74 {
75 uint8_t *p = buf.map(0) + buf.stride(0) * y + x * 3;
76 p[0] = color.b;
77 p[1] = color.g;
78 p[2] = color.r;
79 break;
80 }
81 case PixelFormat::BGR888:
82 {
83 uint8_t *p = buf.map(0) + buf.stride(0) * y + x * 3;
84 p[0] = color.r;
85 p[1] = color.g;
86 p[2] = color.b;
87 break;
88 }
89 case PixelFormat::RGB565:
90 {
91 uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
92 *p = color.rgb565();
93 break;
94 }
95 case PixelFormat::BGR565:
96 {
97 uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
98 *p = color.bgr565();
99 break;
100 }
101 case PixelFormat::ARGB4444:
102 {
103 uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
104 *p = color.argb4444();
105 break;
106 }
107 case PixelFormat::ARGB1555:
108 {
109 uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
110 *p = color.argb1555();
111 break;
112 }
113 default:
114 throw std::invalid_argument("invalid pixelformat");
115 }
116 }
117
draw_yuv422_macropixel(IFramebuffer & buf,unsigned x,unsigned y,YUV yuv1,YUV yuv2)118 void draw_yuv422_macropixel(IFramebuffer& buf, unsigned x, unsigned y, YUV yuv1, YUV yuv2)
119 {
120 if ((x + 1) >= buf.width() || y >= buf.height())
121 throw runtime_error("attempt to draw outside the buffer");
122
123 ASSERT((x & 1) == 0);
124
125 uint8_t *p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
126
127 uint8_t y0 = yuv1.y;
128 uint8_t y1 = yuv2.y;
129 uint8_t u = (yuv1.u + yuv2.u) / 2;
130 uint8_t v = (yuv1.v + yuv2.v) / 2;
131
132 switch (buf.format()) {
133 case PixelFormat::UYVY:
134 p[0] = u;
135 p[1] = y0;
136 p[2] = v;
137 p[3] = y1;
138 break;
139
140 case PixelFormat::YUYV:
141 p[0] = y0;
142 p[1] = u;
143 p[2] = y1;
144 p[3] = v;
145 break;
146
147 case PixelFormat::YVYU:
148 p[0] = y0;
149 p[1] = v;
150 p[2] = y1;
151 p[3] = u;
152 break;
153
154 case PixelFormat::VYUY:
155 p[0] = v;
156 p[1] = y0;
157 p[2] = u;
158 p[3] = y1;
159 break;
160
161 default:
162 throw std::invalid_argument("invalid pixelformat");
163 }
164 }
165
draw_yuv420_macropixel(IFramebuffer & buf,unsigned x,unsigned y,YUV yuv1,YUV yuv2,YUV yuv3,YUV yuv4)166 void draw_yuv420_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
167 YUV yuv1, YUV yuv2, YUV yuv3, YUV yuv4)
168 {
169 if ((x + 1) >= buf.width() || (y + 1) >= buf.height())
170 throw runtime_error("attempt to draw outside the buffer");
171
172 ASSERT((x & 1) == 0);
173 ASSERT((y & 1) == 0);
174
175 uint8_t *py1 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 0) + x);
176 uint8_t *py2 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 1) + x);
177
178 uint8_t *puv = (uint8_t*)(buf.map(1) + buf.stride(1) * (y / 2) + x);
179
180 uint8_t y0 = yuv1.y;
181 uint8_t y1 = yuv2.y;
182 uint8_t y2 = yuv3.y;
183 uint8_t y3 = yuv4.y;
184 uint8_t u = (yuv1.u + yuv2.u + yuv3.u + yuv4.u) / 4;
185 uint8_t v = (yuv1.v + yuv2.v + yuv3.v + yuv4.v) / 4;
186
187 switch (buf.format()) {
188 case PixelFormat::NV12:
189 py1[0] = y0;
190 py1[1] = y1;
191 py2[0] = y2;
192 py2[1] = y3;
193 puv[0] = u;
194 puv[1] = v;
195 break;
196
197 case PixelFormat::NV21:
198 py1[0] = y0;
199 py1[1] = y1;
200 py2[0] = y2;
201 py2[1] = y3;
202 puv[0] = v;
203 puv[1] = u;
204 break;
205
206 default:
207 throw std::invalid_argument("invalid pixelformat");
208 }
209 }
210
draw_rect(IFramebuffer & fb,uint32_t x,uint32_t y,uint32_t w,uint32_t h,RGB color)211 void draw_rect(IFramebuffer &fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, RGB color)
212 {
213 unsigned i, j;
214 YUV yuvcolor = color.yuv();
215
216 switch (fb.format()) {
217 case PixelFormat::XRGB8888:
218 case PixelFormat::XBGR8888:
219 case PixelFormat::ARGB8888:
220 case PixelFormat::ABGR8888:
221 case PixelFormat::RGB888:
222 case PixelFormat::BGR888:
223 case PixelFormat::RGB565:
224 case PixelFormat::BGR565:
225 case PixelFormat::ARGB4444:
226 case PixelFormat::ARGB1555:
227 for (j = 0; j < h; j++) {
228 for (i = 0; i < w; i++) {
229 draw_rgb_pixel(fb, x + i, y + j, color);
230 }
231 }
232 break;
233
234 case PixelFormat::UYVY:
235 case PixelFormat::YUYV:
236 case PixelFormat::YVYU:
237 case PixelFormat::VYUY:
238 for (j = 0; j < h; j++) {
239 for (i = 0; i < w; i += 2) {
240 draw_yuv422_macropixel(fb, x + i, y + j, yuvcolor, yuvcolor);
241 }
242 }
243 break;
244
245 case PixelFormat::NV12:
246 case PixelFormat::NV21:
247 for (j = 0; j < h; j += 2) {
248 for (i = 0; i < w; i += 2) {
249 draw_yuv420_macropixel(fb, x + i, y + j,
250 yuvcolor, yuvcolor, yuvcolor, yuvcolor);
251 }
252 }
253 break;
254 default:
255 throw std::invalid_argument("draw_rect: unknown pixelformat");
256 }
257 }
258
draw_horiz_line(IFramebuffer & fb,uint32_t x1,uint32_t x2,uint32_t y,RGB color)259 void draw_horiz_line(IFramebuffer& fb, uint32_t x1, uint32_t x2, uint32_t y, RGB color)
260 {
261 for (uint32_t x = x1; x <= x2; ++x)
262 draw_rgb_pixel(fb, x, y, color);
263 }
264
draw_circle(IFramebuffer & fb,int32_t xCenter,int32_t yCenter,int32_t radius,RGB color)265 void draw_circle(IFramebuffer& fb, int32_t xCenter, int32_t yCenter, int32_t radius, RGB color)
266 {
267 int32_t r2 = radius * radius;
268
269 for (int y = -radius; y <= radius; y++) {
270 int32_t x = (int)(sqrt(r2 - y * y) + 0.5);
271 draw_horiz_line(fb, xCenter - x, xCenter + x, yCenter - y, color);
272 }
273 }
274
get_char_pixel(char c,uint32_t x,uint32_t y)275 static bool get_char_pixel(char c, uint32_t x, uint32_t y)
276 {
277 #include "font_8x8.h"
278
279 uint8_t bits = fontdata_8x8[8 * c + y];
280 bool bit = (bits >> (7 - x)) & 1;
281
282 return bit;
283 }
284
draw_char(IFramebuffer & buf,uint32_t xpos,uint32_t ypos,char c,RGB color)285 static void draw_char(IFramebuffer& buf, uint32_t xpos, uint32_t ypos, char c, RGB color)
286 {
287 unsigned x, y;
288 YUV yuvcolor = color.yuv();
289
290 switch (buf.format()) {
291 case PixelFormat::XRGB8888:
292 case PixelFormat::XBGR8888:
293 case PixelFormat::ARGB8888:
294 case PixelFormat::ABGR8888:
295 case PixelFormat::RGB888:
296 case PixelFormat::BGR888:
297 case PixelFormat::RGB565:
298 case PixelFormat::BGR565:
299 case PixelFormat::ARGB4444:
300 case PixelFormat::ARGB1555:
301 for (y = 0; y < 8; y++) {
302 for (x = 0; x < 8; x++) {
303 bool b = get_char_pixel(c, x, y);
304
305 draw_rgb_pixel(buf, xpos + x, ypos + y, b ? color : RGB());
306 }
307 }
308 break;
309
310 case PixelFormat::UYVY:
311 case PixelFormat::YUYV:
312 case PixelFormat::YVYU:
313 case PixelFormat::VYUY:
314 for (y = 0; y < 8; y++) {
315 for (x = 0; x < 8; x += 2) {
316 bool b0 = get_char_pixel(c, x, y);
317 bool b1 = get_char_pixel(c, x + 1, y);
318
319 draw_yuv422_macropixel(buf, xpos + x, ypos + y,
320 b0 ? yuvcolor : YUV(RGB()), b1 ? yuvcolor : YUV(RGB()));
321 }
322 }
323 break;
324
325 case PixelFormat::NV12:
326 case PixelFormat::NV21:
327 for (y = 0; y < 8; y += 2) {
328 for (x = 0; x < 8; x += 2) {
329 bool b00 = get_char_pixel(c, x, y);
330 bool b10 = get_char_pixel(c, x + 1, y);
331 bool b01 = get_char_pixel(c, x, y + 1);
332 bool b11 = get_char_pixel(c, x + 1, y + 1);
333
334 draw_yuv420_macropixel(buf, xpos + x, ypos + y,
335 b00 ? yuvcolor : YUV(RGB()), b10 ? yuvcolor : YUV(RGB()),
336 b01 ? yuvcolor : YUV(RGB()), b11 ? yuvcolor : YUV(RGB()));
337 }
338 }
339 break;
340 default:
341 throw std::invalid_argument("draw_char: unknown pixelformat");
342 }
343 }
344
draw_text(IFramebuffer & buf,uint32_t x,uint32_t y,const string & str,RGB color)345 void draw_text(IFramebuffer& buf, uint32_t x, uint32_t y, const string& str, RGB color)
346 {
347 for(unsigned i = 0; i < str.size(); i++)
348 draw_char(buf, (x + 8 * i), y, str[i], color);
349 }
350
351 }
352