draw.c (6540B)
1 #include <libc.h> 2 #include <uefi.h> 3 #include <draw.h> 4 #include <console.h> 5 6 Window root_window; 7 8 void (* pixel)(Window *dst, Point p, RGBA32 col); 9 RGBA32 (*get_pixel)(Window *win, Point at); 10 11 static void pixelRedGreenBlueReserved(Window *dst, Point p, RGBA32 col); 12 static void pixelBlueGreenRedReserved(Window *dst, Point p, RGBA32 col); 13 static RGBA32 get_pixelRedGreenBlueReserved(Window *win, Point at); 14 static RGBA32 get_pixelBlueGreenRedReserved(Window *win, Point at); 15 16 int 17 init_root_window(uint32 *fb_base, int hres, int vres, int ppsl, EFI_GRAPHICS_PIXEL_FORMAT pf) 18 { 19 if (pf == PixelRedGreenBlueReserved8BitPerColor) { 20 pixel = pixelRedGreenBlueReserved; 21 get_pixel = get_pixelRedGreenBlueReserved; 22 } else if (pf == PixelBlueGreenRedReserved8BitPerColor) { 23 pixel = pixelBlueGreenRedReserved; 24 get_pixel = get_pixelBlueGreenRedReserved; 25 } else { 26 strcpy(err.ename, "pixel format not supported."); 27 return -1; 28 } 29 root_window.fb = fb_base; 30 root_window.fg = 0x000000ff; 31 root_window.bg = 0x555555ff; 32 root_window.ppsl = ppsl; 33 root_window.parent = &root_window; 34 root_window.size = (Point){hres, vres}; 35 root_window.children = NULL; 36 root_window.nchildren = 0; 37 clear(&root_window); 38 return 0; 39 } 40 41 static void 42 pixelRedGreenBlueReserved(Window *dst, Point p, RGBA32 col) 43 { 44 Window *parent; 45 uint32 r, g, b, or, og, ob, old_col, alpha; 46 47 if (p.x < 0 || dst->size.x <= p.x || p.y < 0 || dst->size.y <= p.y) { 48 return; 49 } 50 if ((parent = dst->parent) != dst) { 51 pixel(parent, (Point) {p.x + dst->pos.x, p.y + dst->pos.y}, col); 52 return; 53 } 54 alpha = col & 0x000000ff; 55 r = (col & 0xff000000) >> 24; 56 g = (col & 0x00ff0000) >> 16; 57 b = (col & 0x0000ff00) >> 8; 58 old_col = dst->fb[p.y * dst->ppsl + p.x]; 59 or = (old_col & 0x000000ff); 60 og = (old_col & 0x0000ff00) >> 8; 61 ob = (old_col & 0x00ff0000) >> 16; 62 r = (or * (255-alpha) + r*alpha) / 255; 63 g = (og * (255-alpha) + g*alpha) / 255; 64 b = (ob * (255-alpha) + b*alpha) / 255; 65 dst->fb[p.y * dst->ppsl + p.x] = r | g << 8 | b << 16; 66 } 67 68 static void 69 pixelBlueGreenRedReserved(Window *dst, Point p, RGBA32 col) 70 { 71 Window *parent; 72 uint32 r, g, b, or, og, ob, old_col, alpha; 73 74 if (p.x < 0 || dst->size.x <= p.x || p.y < 0 || dst->size.y <= p.y) { 75 return; 76 } 77 if ((parent = dst->parent) != dst) { 78 pixel(parent, (Point) {p.x + dst->pos.x, p.y + dst->pos.y}, col); 79 return; 80 } 81 alpha = col & 0x000000ff; 82 r = (col & 0xff000000) >> 24; 83 g = (col & 0x00ff0000) >> 16; 84 b = (col & 0x0000ff00) >> 8; 85 old_col = dst->fb[p.y * dst->ppsl + p.x]; 86 or = (old_col & 0x00ff0000) >> 16; 87 og = (old_col & 0x0000ff00) >> 8; 88 ob = (old_col & 0x000000ff); 89 r = (or * (255-alpha) + r*alpha) / 255; 90 g = (og * (255-alpha) + g*alpha) / 255; 91 b = (ob * (255-alpha) + b*alpha) / 255; 92 dst->fb[p.y * dst->ppsl + p.x] = r << 16 | g << 8 | b; 93 } 94 95 static RGBA32 96 get_pixelRedGreenBlueReserved(Window *win, Point at) 97 { 98 Window *parent; 99 uint32 col; 100 if (at.x < 0 || win->size.x <= at.x || at.y < 0 || win->size.y <= at.y) { 101 return 0; 102 } 103 if ((parent = win->parent) != win) { 104 return get_pixel(parent, (Point) {at.x + win->pos.x, at.y + win->pos.y}); 105 } 106 col = win->fb[at.y * win->ppsl + at.x]; 107 return 0x000000ff | // A 108 (col & 0x00ff0000) >> 8 | // B 109 (col & 0x0000ff00) << 8 | // G 110 (col & 0x000000ff) << 24 ; // R 111 } 112 113 static RGBA32 114 get_pixelBlueGreenRedReserved(Window *win, Point at) 115 { 116 Window *parent; 117 uint32 col; 118 if (at.x < 0 || win->size.x <= at.x || at.y < 0 || win->size.y <= at.y) { 119 return 0; 120 } 121 if ((parent = win->parent) != win) { 122 return get_pixel(parent, (Point) {at.x + win->pos.x, at.y + win->pos.y}); 123 } 124 col = win->fb[at.y * win->ppsl + at.x]; 125 return 0x000000ff | // A 126 (col & 0x00ff0000) << 8 | // R 127 (col & 0x0000ff00) << 8 | // G 128 (col & 0x000000ff) << 8 ; // B 129 } 130 131 void 132 line(Window *dst, Point p0, Point p1, RGBA32 col) 133 { 134 int x, y, sx, sy, dx, dy; 135 int err, e2; 136 if (p0.x < p1.x) { 137 dx = p1.x - p0.x; 138 sx = 1; 139 } else { 140 dx = p0.x - p1.x; 141 sx = -1; 142 } 143 if (p0.y < p1.y) { 144 dy = p1.y - p0.y; 145 sy = 1; 146 } else { 147 dy = p0.y - p1.y; 148 sy = -1; 149 } 150 err = dx - dy; 151 x = p0.x; 152 y = p0.y; 153 pixel(dst, (Point){x, y}, col); 154 // TODO: skip and break the points outside the window. 155 for (;x != p1.x || y != p1.y;) { 156 e2 = 2 * err; 157 if (e2 > -dy) { 158 err -= dy; 159 x += sx; 160 } 161 if (e2 < dx) { 162 err +=dx; 163 y += sy; 164 } 165 pixel(dst, (Point){x, y}, col); 166 } 167 } 168 169 void 170 border(Window *dst, Rectangle r, int i, RGBA32 col) 171 { 172 int x, y; 173 int j; 174 int start, end; 175 if (i < 0) { 176 start = -1; 177 end = i - 1; 178 } else { 179 start = 0; 180 end = i + 1; 181 } 182 int delta = i > 0 ? 1 : -1; 183 for (j = start; j != end; j += delta) { 184 for (x = r.min.x+j, y = r.min.y+j; x < r.max.x-j; x++) { 185 pixel(dst, (Point){x, y}, col); 186 } 187 for (x = r.max.x-1-j, y = r.min.y+j; y < r.max.y-j; y++) { 188 pixel(dst, (Point){x, y}, col); 189 } 190 for (x = r.max.x-1-j, y = r.max.y-1-j; x >= r.min.x+j; x--) { 191 pixel(dst, (Point){x, y}, col); 192 } 193 for (x = r.min.x+j, y = r.max.y-1-j; y >= r.min.y+j; y--) { 194 pixel(dst, (Point){x, y}, col); 195 } 196 } 197 } 198 199 void 200 fill(Window *dst, Rectangle r, RGBA32 col) 201 { 202 int x, y; 203 for (x = r.min.x; x < r.max.x; x++) { 204 for (y = r.min.y; y < r.max.y; y++) { 205 pixel(dst, (Point){x, y}, col); 206 } 207 } 208 } 209 210 void 211 clear(Window *dst) 212 { 213 int x, y; 214 for (x = 0; x < dst->size.x; x++) { 215 for (y = 0; y < dst->size.y; y++) { 216 pixel(dst, (Point){x, y}, dst->bg); 217 } 218 } 219 } 220 221 int 222 make_window(Window *parent, Window *child, Point pos, Point size, RGBA32 fg, RGBA32 bg) 223 { 224 if (parent->nchildren == MAX_CHILD_WIN) { 225 return -1; 226 } 227 child->fg = fg; 228 child->bg = bg; 229 child->parent = parent; 230 child->pos = pos; 231 child->size = size; 232 child->children = NULL; // TODO: allocate memory. 233 child->nchildren = 0; 234 235 parent->children[parent->nchildren] = child; // TODO: allocate dynamically. 236 parent->nchildren++; 237 238 clear(child); 239 border(parent, (Rectangle){pos, (Point){pos.x + size.x, pos.y + size.y}}, -4, 0x3f312bff); 240 241 return 0; 242 } 243 244 void 245 draw_mouse(Window *dst, Mouse *mouse) 246 { 247 int i, j; 248 for (i = 0; i < mouse->size.y; i++) { 249 for (j = 0; j < mouse->size.x; j++) { 250 mouse->hidden[j + i*mouse->size.x] = get_pixel(dst, (Point){mouse->pos.x + j, mouse->pos.y + i}); 251 pixel(dst, (Point){mouse->pos.x + j, mouse->pos.y + i}, 252 mouse->img[j + i*mouse->size.x]); 253 } 254 } 255 } 256 257 void 258 clear_mouse(Window *dst, Mouse *mouse) 259 { 260 int i, j; 261 for (i = 0; i < mouse->size.y; i++) { 262 for (j = 0; j < mouse->size.x; j++) { 263 pixel(dst, (Point){mouse->pos.x + j, mouse->pos.y + i}, 264 mouse->hidden[j + i*mouse->size.x]); 265 } 266 } 267 }