• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 #include <cmath>
3 
4 #include <kms++/kms++.h>
5 #include <kms++util/kms++util.h>
6 #include <kms++util/endian.h>
7 
8 using namespace std;
9 
10 namespace kms
11 {
draw_rgb_pixel(IFramebuffer & buf,unsigned x,unsigned y,RGB color)12 void draw_rgb_pixel(IFramebuffer& buf, unsigned x, unsigned y, RGB color)
13 {
14 	if (x >= buf.width() || y >= buf.height())
15 		throw runtime_error("attempt to draw outside the buffer");
16 
17 	switch (buf.format()) {
18 	case PixelFormat::XRGB8888:
19 	case PixelFormat::ARGB8888: {
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 		uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
27 		*p = color.abgr8888();
28 		break;
29 	}
30 	case PixelFormat::RGBX8888:
31 	case PixelFormat::RGBA8888: {
32 		uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
33 		*p = color.rgba8888();
34 		break;
35 	}
36 	case PixelFormat::BGRX8888:
37 	case PixelFormat::BGRA8888: {
38 		uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
39 		*p = color.bgra8888();
40 		break;
41 	}
42 	case PixelFormat::XRGB2101010:
43 	case PixelFormat::ARGB2101010: {
44 		uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
45 		*p = color.argb2101010();
46 		break;
47 	}
48 	case PixelFormat::XBGR2101010:
49 	case PixelFormat::ABGR2101010: {
50 		uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
51 		*p = color.abgr2101010();
52 		break;
53 	}
54 	case PixelFormat::RGBX1010102:
55 	case PixelFormat::RGBA1010102: {
56 		uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
57 		*p = color.rgba1010102();
58 		break;
59 	}
60 	case PixelFormat::BGRX1010102:
61 	case PixelFormat::BGRA1010102: {
62 		uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
63 		*p = color.bgra1010102();
64 		break;
65 	}
66 	case PixelFormat::RGB888: {
67 		uint8_t* p = buf.map(0) + buf.stride(0) * y + x * 3;
68 		p[0] = color.b;
69 		p[1] = color.g;
70 		p[2] = color.r;
71 		break;
72 	}
73 	case PixelFormat::BGR888: {
74 		uint8_t* p = buf.map(0) + buf.stride(0) * y + x * 3;
75 		p[0] = color.r;
76 		p[1] = color.g;
77 		p[2] = color.b;
78 		break;
79 	}
80 	case PixelFormat::RGB332: {
81 		uint8_t* p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x);
82 		*p = color.rgb332();
83 		break;
84 	}
85 	case PixelFormat::RGB565: {
86 		uint16_t* p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
87 		*p = color.rgb565();
88 		break;
89 	}
90 	case PixelFormat::BGR565: {
91 		uint16_t* p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
92 		*p = color.bgr565();
93 		break;
94 	}
95 	case PixelFormat::XRGB4444:
96 	case PixelFormat::ARGB4444: {
97 		uint16_t* p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
98 		*p = color.argb4444();
99 		break;
100 	}
101 	case PixelFormat::XRGB1555:
102 	case PixelFormat::ARGB1555: {
103 		uint16_t* p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
104 		*p = color.argb1555();
105 		break;
106 	}
107 	default:
108 		throw std::invalid_argument("invalid pixelformat");
109 	}
110 }
111 
draw_yuv444_pixel(IFramebuffer & buf,unsigned x,unsigned y,YUV yuv)112 void draw_yuv444_pixel(IFramebuffer& buf, unsigned x, unsigned y, YUV yuv)
113 {
114 	if (x >= buf.width() || y >= buf.height())
115 		throw runtime_error("attempt to draw outside the buffer");
116 
117 	uint8_t* py = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x);
118 	uint8_t* pu = (uint8_t*)(buf.map(1) + buf.stride(1) * y + x);
119 	uint8_t* pv = (uint8_t*)(buf.map(2) + buf.stride(2) * y + x);
120 
121 	switch (buf.format()) {
122 	case PixelFormat::YUV444:
123 		py[0] = yuv.y;
124 		pu[0] = yuv.u;
125 		pv[0] = yuv.v;
126 		break;
127 
128 	case PixelFormat::YVU444:
129 		py[0] = yuv.y;
130 		pu[0] = yuv.v;
131 		pv[0] = yuv.u;
132 		break;
133 
134 	default:
135 		throw std::invalid_argument("invalid pixelformat");
136 	}
137 }
138 
draw_yuv422_packed_macropixel(IFramebuffer & buf,unsigned x,unsigned y,YUV yuv1,YUV yuv2)139 static void draw_yuv422_packed_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
140 					  YUV yuv1, YUV yuv2)
141 {
142 	uint8_t* p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
143 
144 	uint8_t y0 = yuv1.y;
145 	uint8_t y1 = yuv2.y;
146 	uint8_t u = (yuv1.u + yuv2.u) / 2;
147 	uint8_t v = (yuv1.v + yuv2.v) / 2;
148 
149 	switch (buf.format()) {
150 	case PixelFormat::UYVY:
151 		p[0] = u;
152 		p[1] = y0;
153 		p[2] = v;
154 		p[3] = y1;
155 		break;
156 
157 	case PixelFormat::YUYV:
158 		p[0] = y0;
159 		p[1] = u;
160 		p[2] = y1;
161 		p[3] = v;
162 		break;
163 
164 	case PixelFormat::YVYU:
165 		p[0] = y0;
166 		p[1] = v;
167 		p[2] = y1;
168 		p[3] = u;
169 		break;
170 
171 	case PixelFormat::VYUY:
172 		p[0] = v;
173 		p[1] = y0;
174 		p[2] = u;
175 		p[3] = y1;
176 		break;
177 
178 	default:
179 		throw std::invalid_argument("invalid pixelformat");
180 	}
181 }
182 
draw_y2xx_packed_macropixel(IFramebuffer & buf,unsigned x,unsigned y,YUV yuv1,YUV yuv2)183 static void draw_y2xx_packed_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
184 					YUV yuv1, YUV yuv2)
185 {
186 	const uint32_t macro_size = 4;
187 	uint16_t* p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * macro_size);
188 
189 	switch (buf.format()) {
190 	case PixelFormat::Y210: {
191 		// XXX naive expansion to 10 bits, similar to 10-bit funcs in class RGB
192 		uint16_t y0 = yuv1.y << 2;
193 		uint16_t y1 = yuv2.y << 2;
194 		uint16_t cb = ((yuv1.u << 2) + (yuv2.u << 2)) / 2;
195 		uint16_t cr = ((yuv1.v << 2) + (yuv2.v << 2)) / 2;
196 
197 		// The 10 bits occupy the msb, so we shift left by 16-10 = 6
198 		write16le(&p[0], y0 << 6);
199 		write16le(&p[1], cb << 6);
200 		write16le(&p[2], y1 << 6);
201 		write16le(&p[3], cr << 6);
202 		break;
203 	}
204 
205 	case PixelFormat::Y212: {
206 		// XXX naive expansion to 12 bits
207 		uint16_t y0 = yuv1.y << 4;
208 		uint16_t y1 = yuv2.y << 4;
209 		uint16_t cb = ((yuv1.u << 4) + (yuv2.u << 4)) / 2;
210 		uint16_t cr = ((yuv1.v << 4) + (yuv2.v << 4)) / 2;
211 
212 		// The 10 bits occupy the msb, so we shift left by 16-12 = 4
213 		write16le(&p[0], y0 << 4);
214 		write16le(&p[1], cb << 4);
215 		write16le(&p[2], y1 << 4);
216 		write16le(&p[3], cr << 4);
217 		break;
218 	}
219 
220 	case PixelFormat::Y216: {
221 		// XXX naive expansion to 16 bits
222 		uint16_t y0 = yuv1.y << 8;
223 		uint16_t y1 = yuv2.y << 8;
224 		uint16_t cb = ((yuv1.u << 8) + (yuv2.u << 8)) / 2;
225 		uint16_t cr = ((yuv1.v << 8) + (yuv2.v << 8)) / 2;
226 
227 		write16le(&p[0], y0);
228 		write16le(&p[1], cb);
229 		write16le(&p[2], y1);
230 		write16le(&p[3], cr);
231 		break;
232 	}
233 
234 	default:
235 		throw std::invalid_argument("invalid pixelformat");
236 	}
237 }
238 
draw_yuv422_semiplanar_macropixel(IFramebuffer & buf,unsigned x,unsigned y,YUV yuv1,YUV yuv2)239 static void draw_yuv422_semiplanar_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
240 					      YUV yuv1, YUV yuv2)
241 {
242 	uint8_t* py = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x);
243 	uint8_t* puv = (uint8_t*)(buf.map(1) + buf.stride(1) * y + x);
244 
245 	uint8_t y0 = yuv1.y;
246 	uint8_t y1 = yuv2.y;
247 	uint8_t u = (yuv1.u + yuv2.u) / 2;
248 	uint8_t v = (yuv1.v + yuv2.v) / 2;
249 
250 	switch (buf.format()) {
251 	case PixelFormat::NV16:
252 		py[0] = y0;
253 		py[1] = y1;
254 		puv[0] = u;
255 		puv[1] = v;
256 		break;
257 
258 	case PixelFormat::NV61:
259 		py[0] = y0;
260 		py[1] = y1;
261 		puv[0] = v;
262 		puv[1] = u;
263 		break;
264 
265 	default:
266 		throw std::invalid_argument("invalid pixelformat");
267 	}
268 }
269 
draw_yuv422_planar_macropixel(IFramebuffer & buf,unsigned x,unsigned y,YUV yuv1,YUV yuv2)270 static void draw_yuv422_planar_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
271 					  YUV yuv1, YUV yuv2)
272 {
273 	uint8_t* py = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x);
274 	uint8_t* pu = (uint8_t*)(buf.map(1) + buf.stride(1) * y + x / 2);
275 	uint8_t* pv = (uint8_t*)(buf.map(2) + buf.stride(2) * y + x / 2);
276 
277 	uint8_t y0 = yuv1.y;
278 	uint8_t y1 = yuv2.y;
279 	uint8_t u = (yuv1.u + yuv2.u) / 2;
280 	uint8_t v = (yuv1.v + yuv2.v) / 2;
281 
282 	switch (buf.format()) {
283 	case PixelFormat::YUV422:
284 		py[0] = y0;
285 		py[1] = y1;
286 		pu[0] = u;
287 		pv[0] = v;
288 		break;
289 
290 	case PixelFormat::YVU422:
291 		py[0] = y0;
292 		py[1] = y1;
293 		pu[0] = v;
294 		pv[0] = u;
295 		break;
296 
297 	default:
298 		throw std::invalid_argument("invalid pixelformat");
299 	}
300 }
301 
draw_yuv422_macropixel(IFramebuffer & buf,unsigned x,unsigned y,YUV yuv1,YUV yuv2)302 void draw_yuv422_macropixel(IFramebuffer& buf, unsigned x, unsigned y, YUV yuv1, YUV yuv2)
303 {
304 	if ((x + 1) >= buf.width() || y >= buf.height())
305 		throw runtime_error("attempt to draw outside the buffer");
306 
307 	ASSERT((x & 1) == 0);
308 
309 	switch (buf.format()) {
310 	case PixelFormat::UYVY:
311 	case PixelFormat::YUYV:
312 	case PixelFormat::YVYU:
313 	case PixelFormat::VYUY:
314 		draw_yuv422_packed_macropixel(buf, x, y, yuv1, yuv2);
315 		break;
316 
317 	case PixelFormat::Y210:
318 	case PixelFormat::Y212:
319 	case PixelFormat::Y216:
320 		draw_y2xx_packed_macropixel(buf, x, y, yuv1, yuv2);
321 		break;
322 
323 	case PixelFormat::NV16:
324 	case PixelFormat::NV61:
325 		draw_yuv422_semiplanar_macropixel(buf, x, y, yuv1, yuv2);
326 		break;
327 
328 	case PixelFormat::YUV422:
329 	case PixelFormat::YVU422:
330 		draw_yuv422_planar_macropixel(buf, x, y, yuv1, yuv2);
331 		break;
332 
333 	default:
334 		throw std::invalid_argument("invalid pixelformat");
335 	}
336 }
337 
draw_yuv420_semiplanar_macropixel(IFramebuffer & buf,unsigned x,unsigned y,YUV yuv1,YUV yuv2,YUV yuv3,YUV yuv4)338 static void draw_yuv420_semiplanar_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
339 					      YUV yuv1, YUV yuv2, YUV yuv3, YUV yuv4)
340 {
341 	uint8_t* py1 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 0) + x);
342 	uint8_t* py2 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 1) + x);
343 
344 	uint8_t* puv = (uint8_t*)(buf.map(1) + buf.stride(1) * (y / 2) + x);
345 
346 	uint8_t y0 = yuv1.y;
347 	uint8_t y1 = yuv2.y;
348 	uint8_t y2 = yuv3.y;
349 	uint8_t y3 = yuv4.y;
350 	uint8_t u = (yuv1.u + yuv2.u + yuv3.u + yuv4.u) / 4;
351 	uint8_t v = (yuv1.v + yuv2.v + yuv3.v + yuv4.v) / 4;
352 
353 	switch (buf.format()) {
354 	case PixelFormat::NV12:
355 		py1[0] = y0;
356 		py1[1] = y1;
357 		py2[0] = y2;
358 		py2[1] = y3;
359 		puv[0] = u;
360 		puv[1] = v;
361 		break;
362 
363 	case PixelFormat::NV21:
364 		py1[0] = y0;
365 		py1[1] = y1;
366 		py2[0] = y2;
367 		py2[1] = y3;
368 		puv[0] = v;
369 		puv[1] = u;
370 		break;
371 
372 	default:
373 		throw std::invalid_argument("invalid pixelformat");
374 	}
375 }
376 
draw_yuv420_planar_macropixel(IFramebuffer & buf,unsigned x,unsigned y,YUV yuv1,YUV yuv2,YUV yuv3,YUV yuv4)377 static void draw_yuv420_planar_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
378 					  YUV yuv1, YUV yuv2, YUV yuv3, YUV yuv4)
379 {
380 	uint8_t* py1 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 0) + x);
381 	uint8_t* py2 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 1) + x);
382 
383 	uint8_t* pu = (uint8_t*)(buf.map(1) + buf.stride(1) * (y / 2) + x / 2);
384 	uint8_t* pv = (uint8_t*)(buf.map(2) + buf.stride(2) * (y / 2) + x / 2);
385 
386 	uint8_t y0 = yuv1.y;
387 	uint8_t y1 = yuv2.y;
388 	uint8_t y2 = yuv3.y;
389 	uint8_t y3 = yuv4.y;
390 	uint8_t u = (yuv1.u + yuv2.u + yuv3.u + yuv4.u) / 4;
391 	uint8_t v = (yuv1.v + yuv2.v + yuv3.v + yuv4.v) / 4;
392 
393 	switch (buf.format()) {
394 	case PixelFormat::YUV420:
395 		py1[0] = y0;
396 		py1[1] = y1;
397 		py2[0] = y2;
398 		py2[1] = y3;
399 		pu[0] = u;
400 		pv[0] = v;
401 		break;
402 
403 	case PixelFormat::YVU420:
404 		py1[0] = y0;
405 		py1[1] = y1;
406 		py2[0] = y2;
407 		py2[1] = y3;
408 		pu[0] = v;
409 		pv[0] = u;
410 		break;
411 
412 	default:
413 		throw std::invalid_argument("invalid pixelformat");
414 	}
415 }
416 
draw_yuv420_macropixel(IFramebuffer & buf,unsigned x,unsigned y,YUV yuv1,YUV yuv2,YUV yuv3,YUV yuv4)417 void draw_yuv420_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
418 			    YUV yuv1, YUV yuv2, YUV yuv3, YUV yuv4)
419 {
420 	if ((x + 1) >= buf.width() || (y + 1) >= buf.height())
421 		throw runtime_error("attempt to draw outside the buffer");
422 
423 	ASSERT((x & 1) == 0);
424 	ASSERT((y & 1) == 0);
425 
426 	switch (buf.format()) {
427 	case PixelFormat::NV12:
428 	case PixelFormat::NV21:
429 		draw_yuv420_semiplanar_macropixel(buf, x, y, yuv1, yuv2, yuv3, yuv4);
430 		break;
431 
432 	case PixelFormat::YUV420:
433 	case PixelFormat::YVU420:
434 		draw_yuv420_planar_macropixel(buf, x, y, yuv1, yuv2, yuv3, yuv4);
435 		break;
436 
437 	default:
438 		throw std::invalid_argument("invalid pixelformat");
439 	}
440 }
441 
draw_rect(IFramebuffer & fb,uint32_t x,uint32_t y,uint32_t w,uint32_t h,RGB color)442 void draw_rect(IFramebuffer& fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, RGB color)
443 {
444 	unsigned i, j;
445 	YUV yuvcolor = color.yuv();
446 
447 	switch (fb.format()) {
448 	case PixelFormat::XRGB8888:
449 	case PixelFormat::XBGR8888:
450 	case PixelFormat::ARGB8888:
451 	case PixelFormat::ABGR8888:
452 	case PixelFormat::RGB888:
453 	case PixelFormat::BGR888:
454 	case PixelFormat::RGB565:
455 	case PixelFormat::BGR565:
456 	case PixelFormat::XRGB4444:
457 	case PixelFormat::XRGB1555:
458 	case PixelFormat::ARGB4444:
459 	case PixelFormat::ARGB1555:
460 	case PixelFormat::RGB332:
461 		for (j = 0; j < h; j++) {
462 			for (i = 0; i < w; i++) {
463 				draw_rgb_pixel(fb, x + i, y + j, color);
464 			}
465 		}
466 		break;
467 
468 	case PixelFormat::YUV444:
469 	case PixelFormat::YVU444:
470 		for (j = 0; j < h; j++) {
471 			for (i = 0; i < w; i++) {
472 				draw_yuv444_pixel(fb, x + i, y + j, yuvcolor);
473 			}
474 		}
475 		break;
476 
477 	case PixelFormat::UYVY:
478 	case PixelFormat::YUYV:
479 	case PixelFormat::YVYU:
480 	case PixelFormat::VYUY:
481 	case PixelFormat::NV16:
482 	case PixelFormat::NV61:
483 	case PixelFormat::YUV422:
484 	case PixelFormat::YVU422:
485 		for (j = 0; j < h; j++) {
486 			for (i = 0; i < w; i += 2) {
487 				draw_yuv422_macropixel(fb, x + i, y + j, yuvcolor, yuvcolor);
488 			}
489 		}
490 		break;
491 
492 	case PixelFormat::NV12:
493 	case PixelFormat::NV21:
494 	case PixelFormat::YUV420:
495 	case PixelFormat::YVU420:
496 		for (j = 0; j < h; j += 2) {
497 			for (i = 0; i < w; i += 2) {
498 				draw_yuv420_macropixel(fb, x + i, y + j,
499 						       yuvcolor, yuvcolor, yuvcolor, yuvcolor);
500 			}
501 		}
502 		break;
503 	default:
504 		throw std::invalid_argument("draw_rect: unknown pixelformat");
505 	}
506 }
507 
draw_horiz_line(IFramebuffer & fb,uint32_t x1,uint32_t x2,uint32_t y,RGB color)508 void draw_horiz_line(IFramebuffer& fb, uint32_t x1, uint32_t x2, uint32_t y, RGB color)
509 {
510 	for (uint32_t x = x1; x <= x2; ++x)
511 		draw_rgb_pixel(fb, x, y, color);
512 }
513 
draw_circle(IFramebuffer & fb,int32_t xCenter,int32_t yCenter,int32_t radius,RGB color)514 void draw_circle(IFramebuffer& fb, int32_t xCenter, int32_t yCenter, int32_t radius, RGB color)
515 {
516 	int32_t r2 = radius * radius;
517 
518 	for (int y = -radius; y <= radius; y++) {
519 		int32_t x = (int)(sqrt(r2 - y * y) + 0.5);
520 		draw_horiz_line(fb, xCenter - x, xCenter + x, yCenter - y, color);
521 	}
522 }
523 
get_char_pixel(char c,uint32_t x,uint32_t y)524 static bool get_char_pixel(char c, uint32_t x, uint32_t y)
525 {
526 #include "font_8x8.h"
527 
528 	uint8_t bits = fontdata_8x8[8 * c + y];
529 	bool bit = (bits >> (7 - x)) & 1;
530 
531 	return bit;
532 }
533 
draw_char(IFramebuffer & buf,uint32_t xpos,uint32_t ypos,char c,RGB color)534 static void draw_char(IFramebuffer& buf, uint32_t xpos, uint32_t ypos, char c, RGB color)
535 {
536 	unsigned x, y;
537 	YUV yuvcolor = color.yuv();
538 
539 	switch (buf.format()) {
540 	case PixelFormat::XRGB8888:
541 	case PixelFormat::XBGR8888:
542 	case PixelFormat::ARGB8888:
543 	case PixelFormat::ABGR8888:
544 	case PixelFormat::RGB888:
545 	case PixelFormat::BGR888:
546 	case PixelFormat::RGB565:
547 	case PixelFormat::BGR565:
548 	case PixelFormat::XRGB4444:
549 	case PixelFormat::XRGB1555:
550 	case PixelFormat::ARGB4444:
551 	case PixelFormat::ARGB1555:
552 	case PixelFormat::RGB332:
553 		for (y = 0; y < 8; y++) {
554 			for (x = 0; x < 8; x++) {
555 				bool b = get_char_pixel(c, x, y);
556 
557 				draw_rgb_pixel(buf, xpos + x, ypos + y, b ? color : RGB());
558 			}
559 		}
560 		break;
561 
562 	case PixelFormat::YUV444:
563 	case PixelFormat::YVU444:
564 		for (y = 0; y < 8; y++) {
565 			for (x = 0; x < 8; x++) {
566 				bool b = get_char_pixel(c, x, y);
567 
568 				draw_yuv444_pixel(buf, xpos + x, ypos + y, b ? yuvcolor : YUV(RGB()));
569 			}
570 		}
571 		break;
572 
573 	case PixelFormat::UYVY:
574 	case PixelFormat::YUYV:
575 	case PixelFormat::YVYU:
576 	case PixelFormat::VYUY:
577 	case PixelFormat::NV16:
578 	case PixelFormat::NV61:
579 	case PixelFormat::YUV422:
580 	case PixelFormat::YVU422:
581 		for (y = 0; y < 8; y++) {
582 			for (x = 0; x < 8; x += 2) {
583 				bool b0 = get_char_pixel(c, x, y);
584 				bool b1 = get_char_pixel(c, x + 1, y);
585 
586 				draw_yuv422_macropixel(buf, xpos + x, ypos + y,
587 						       b0 ? yuvcolor : YUV(RGB()), b1 ? yuvcolor : YUV(RGB()));
588 			}
589 		}
590 		break;
591 
592 	case PixelFormat::NV12:
593 	case PixelFormat::NV21:
594 	case PixelFormat::YUV420:
595 	case PixelFormat::YVU420:
596 		for (y = 0; y < 8; y += 2) {
597 			for (x = 0; x < 8; x += 2) {
598 				bool b00 = get_char_pixel(c, x, y);
599 				bool b10 = get_char_pixel(c, x + 1, y);
600 				bool b01 = get_char_pixel(c, x, y + 1);
601 				bool b11 = get_char_pixel(c, x + 1, y + 1);
602 
603 				draw_yuv420_macropixel(buf, xpos + x, ypos + y,
604 						       b00 ? yuvcolor : YUV(RGB()), b10 ? yuvcolor : YUV(RGB()),
605 						       b01 ? yuvcolor : YUV(RGB()), b11 ? yuvcolor : YUV(RGB()));
606 			}
607 		}
608 		break;
609 	default:
610 		throw std::invalid_argument("draw_char: unknown pixelformat");
611 	}
612 }
613 
draw_text(IFramebuffer & buf,uint32_t x,uint32_t y,const string & str,RGB color)614 void draw_text(IFramebuffer& buf, uint32_t x, uint32_t y, const string& str, RGB color)
615 {
616 	for (unsigned i = 0; i < str.size(); i++)
617 		draw_char(buf, (x + 8 * i), y, str[i], color);
618 }
619 
620 } // namespace kms
621