setos

拙OS
Log | Files | Refs | LICENSE

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 }