• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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