]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android/external-libkmsxx.git/blob - kms++util/src/drawing.cpp
add safeguards to draw_*_pixel() to prevent memory corruption
[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(IFramebuffer& buf, unsigned x, unsigned y, RGB color)
10 {
11         if (x >= buf.width() || y >= buf.height())
12                 throw runtime_error("attempt to draw outside the buffer");
14         switch (buf.format()) {
15         case PixelFormat::XRGB8888:
16         case PixelFormat::ARGB8888:
17         {
18                 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
19                 *p = color.argb8888();
20                 break;
21         }
22         case PixelFormat::XBGR8888:
23         case PixelFormat::ABGR8888:
24         {
25                 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
26                 *p = color.abgr8888();
27                 break;
28         }
29         case PixelFormat::RGB888:
30         {
31                 uint8_t *p = buf.map(0) + buf.stride(0) * y + x * 3;
32                 p[0] = color.b;
33                 p[1] = color.g;
34                 p[2] = color.r;
35                 break;
36         }
37         case PixelFormat::BGR888:
38         {
39                 uint8_t *p = buf.map(0) + buf.stride(0) * y + x * 3;
40                 p[0] = color.r;
41                 p[1] = color.g;
42                 p[2] = color.b;
43                 break;
44         }
45         case PixelFormat::RGB565:
46         {
47                 uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
48                 *p = color.rgb565();
49                 break;
50         }
51         case PixelFormat::BGR565:
52         {
53                 uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
54                 *p = color.bgr565();
55                 break;
56         }
57         default:
58                 throw std::invalid_argument("invalid pixelformat");
59         }
60 }
62 void draw_yuv422_macropixel(IFramebuffer& buf, unsigned x, unsigned y, YUV yuv1, YUV yuv2)
63 {
64         if ((x + 1) >= buf.width() || y >= buf.height())
65                 throw runtime_error("attempt to draw outside the buffer");
67         ASSERT((x & 1) == 0);
69         uint8_t *p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
71         uint8_t y0 = yuv1.y;
72         uint8_t y1 = yuv2.y;
73         uint8_t u = (yuv1.u + yuv2.u) / 2;
74         uint8_t v = (yuv1.v + yuv2.v) / 2;
76         switch (buf.format()) {
77         case PixelFormat::UYVY:
78                 p[0] = u;
79                 p[1] = y0;
80                 p[2] = v;
81                 p[3] = y1;
82                 break;
84         case PixelFormat::YUYV:
85                 p[0] = y0;
86                 p[1] = u;
87                 p[2] = y1;
88                 p[3] = v;
89                 break;
91         case PixelFormat::YVYU:
92                 p[0] = y0;
93                 p[1] = v;
94                 p[2] = y1;
95                 p[3] = u;
96                 break;
98         case PixelFormat::VYUY:
99                 p[0] = v;
100                 p[1] = y0;
101                 p[2] = u;
102                 p[3] = y1;
103                 break;
105         default:
106                 throw std::invalid_argument("invalid pixelformat");
107         }
110 void draw_yuv420_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
111                             YUV yuv1, YUV yuv2, YUV yuv3, YUV yuv4)
113         if ((x + 1) >= buf.width() || (y + 1) >= buf.height())
114                 throw runtime_error("attempt to draw outside the buffer");
116         ASSERT((x & 1) == 0);
117         ASSERT((y & 1) == 0);
119         uint8_t *py1 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 0) + x);
120         uint8_t *py2 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 1) + x);
122         uint8_t *puv = (uint8_t*)(buf.map(1) + buf.stride(1) * (y / 2) + x);
124         uint8_t y0 = yuv1.y;
125         uint8_t y1 = yuv2.y;
126         uint8_t y2 = yuv3.y;
127         uint8_t y3 = yuv4.y;
128         uint8_t u = (yuv1.u + yuv2.u + yuv3.u + yuv4.u) / 4;
129         uint8_t v = (yuv1.v + yuv2.v + yuv3.v + yuv4.v) / 4;
131         switch (buf.format()) {
132         case PixelFormat::NV12:
133                 py1[0] = y0;
134                 py1[1] = y1;
135                 py2[0] = y2;
136                 py2[1] = y3;
137                 puv[0] = u;
138                 puv[1] = v;
139                 break;
141         case PixelFormat::NV21:
142                 py1[0] = y0;
143                 py1[1] = y1;
144                 py2[0] = y2;
145                 py2[1] = y3;
146                 puv[0] = v;
147                 puv[1] = u;
148                 break;
150         default:
151                 throw std::invalid_argument("invalid pixelformat");
152         }
155 void draw_rect(IFramebuffer &fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, RGB color)
157         unsigned i, j;
158         YUV yuvcolor = color.yuv();
160         switch (fb.format()) {
161         case PixelFormat::XRGB8888:
162         case PixelFormat::XBGR8888:
163         case PixelFormat::ARGB8888:
164         case PixelFormat::ABGR8888:
165         case PixelFormat::RGB888:
166         case PixelFormat::BGR888:
167         case PixelFormat::RGB565:
168         case PixelFormat::BGR565:
169                 for (j = 0; j < h; j++) {
170                         for (i = 0; i < w; i++) {
171                                 draw_rgb_pixel(fb, x + i, y + j, color);
172                         }
173                 }
174                 break;
176         case PixelFormat::UYVY:
177         case PixelFormat::YUYV:
178         case PixelFormat::YVYU:
179         case PixelFormat::VYUY:
180                 for (j = 0; j < h; j++) {
181                         for (i = 0; i < w; i += 2) {
182                                 draw_yuv422_macropixel(fb, x + i, y + j, yuvcolor, yuvcolor);
183                         }
184                 }
185                 break;
187         case PixelFormat::NV12:
188         case PixelFormat::NV21:
189                 for (j = 0; j < h; j += 2) {
190                         for (i = 0; i < w; i += 2) {
191                                 draw_yuv420_macropixel(fb, x + i, y + j,
192                                                        yuvcolor, yuvcolor, yuvcolor, yuvcolor);
193                         }
194                 }
195                 break;
196         default:
197                 throw std::invalid_argument("unknown pixelformat");
198         }
201 static bool get_char_pixel(char c, uint32_t x, uint32_t y)
203 #include "font_8x8.h"
205         uint8_t bits = fontdata_8x8[8 * c + y];
206         bool bit = (bits >> (7 - x)) & 1;
208         return bit;
211 static void draw_char(IFramebuffer& buf, uint32_t xpos, uint32_t ypos, char c, RGB color)
213         unsigned x, y;
214         YUV yuvcolor = color.yuv();
216         switch (buf.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                 for (y = 0; y < 8; y++) {
226                         for (x = 0; x < 8; x++) {
227                                 bool b = get_char_pixel(c, x, y);
229                                 draw_rgb_pixel(buf, xpos + x, ypos + y, b ? color : RGB());
230                         }
231                 }
232                 break;
234         case PixelFormat::UYVY:
235         case PixelFormat::YUYV:
236         case PixelFormat::YVYU:
237         case PixelFormat::VYUY:
238                 for (y = 0; y < 8; y++) {
239                         for (x = 0; x < 8; x += 2) {
240                                 bool b0 = get_char_pixel(c, x, y);
241                                 bool b1 = get_char_pixel(c, x + 1, y);
243                                 draw_yuv422_macropixel(buf, xpos + x, ypos + y,
244                                                        b0 ? yuvcolor : YUV(RGB()), b1 ? yuvcolor : YUV(RGB()));
245                         }
246                 }
247                 break;
249         case PixelFormat::NV12:
250         case PixelFormat::NV21:
251                 for (y = 0; y < 8; y += 2) {
252                         for (x = 0; x < 8; x += 2) {
253                                 bool b00 = get_char_pixel(c, x, y);
254                                 bool b10 = get_char_pixel(c, x + 1, y);
255                                 bool b01 = get_char_pixel(c, x, y + 1);
256                                 bool b11 = get_char_pixel(c, x + 1, y + 1);
258                                 draw_yuv420_macropixel(buf, xpos + x, ypos + y,
259                                                        b00 ? yuvcolor : YUV(RGB()), b10 ? yuvcolor : YUV(RGB()),
260                                                        b01 ? yuvcolor : YUV(RGB()), b11 ? yuvcolor : YUV(RGB()));
261                         }
262                 }
263                 break;
264         default:
265                 throw std::invalid_argument("unknown pixelformat");
266         }
269 void draw_text(IFramebuffer& buf, uint32_t x, uint32_t y, const string& str, RGB color)
271         for(unsigned i = 0; i < str.size(); i++)
272                 draw_char(buf, (x + 8 * i), y, str[i], color);