mirror of
https://github.com/JannisHeydemann/BoredOS.git
synced 2026-05-30 02:16:58 +00:00
197 lines
5.7 KiB
C
197 lines
5.7 KiB
C
#include "paint.h"
|
|
#include "graphics.h"
|
|
#include "wm.h"
|
|
#include "memory_manager.h"
|
|
#include "fat32.h"
|
|
|
|
#define CANVAS_W 300
|
|
#define CANVAS_H 200
|
|
#define PAINT_MAGIC 0x544E5042 // 'BPNT'
|
|
|
|
Window win_paint;
|
|
static uint32_t *canvas_buffer = NULL;
|
|
static uint32_t current_color = COLOR_BLACK;
|
|
static int last_mx = -1;
|
|
static int last_my = -1;
|
|
static char current_file_path[256] = "/Desktop/drawing.pnt";
|
|
|
|
static void paint_strcpy(char *dest, const char *src) {
|
|
while (*src) *dest++ = *src++;
|
|
*dest = 0;
|
|
}
|
|
|
|
static void paint_paint(Window *win) {
|
|
// Toolbar area
|
|
draw_rect(win->x + 10, win->y + 30, 40, win->h - 40, COLOR_GRAY);
|
|
draw_bevel_rect(win->x + 10, win->y + 30, 40, win->h - 40, true);
|
|
|
|
// Color Palette
|
|
uint32_t colors[] = {COLOR_BLACK, COLOR_RED, COLOR_APPLE_GREEN, COLOR_APPLE_BLUE, COLOR_APPLE_YELLOW, COLOR_WHITE};
|
|
for (int i = 0; i < 6; i++) {
|
|
int cy = win->y + 40 + (i * 25);
|
|
draw_rect(win->x + 15, cy, 30, 20, colors[i]);
|
|
draw_rect(win->x + 15, cy, 30, 1, COLOR_BLACK);
|
|
draw_rect(win->x + 15, cy, 1, 20, COLOR_BLACK);
|
|
draw_rect(win->x + 44, cy, 1, 20, COLOR_BLACK);
|
|
draw_rect(win->x + 15, cy + 19, 30, 1, COLOR_BLACK);
|
|
|
|
// Highlight selected color
|
|
if (current_color == colors[i]) {
|
|
draw_rect(win->x + 13, cy - 2, 34, 2, COLOR_WHITE);
|
|
draw_rect(win->x + 13, cy + 20, 34, 2, COLOR_WHITE);
|
|
}
|
|
}
|
|
|
|
// Toolbar Buttons
|
|
draw_button(win->x + 12, win->y + win->h - 65, 36, 20, "CLR", false);
|
|
draw_button(win->x + 12, win->y + win->h - 40, 36, 20, "SAV", false);
|
|
|
|
// Canvas Area
|
|
int canvas_x = win->x + 60;
|
|
int canvas_y = win->y + 30;
|
|
draw_bevel_rect(canvas_x - 2, canvas_y - 2, CANVAS_W + 4, CANVAS_H + 4, true);
|
|
|
|
if (canvas_buffer) {
|
|
for (int y = 0; y < CANVAS_H; y++) {
|
|
for (int x = 0; x < CANVAS_W; x++) {
|
|
uint32_t color = canvas_buffer[y * CANVAS_W + x];
|
|
put_pixel(canvas_x + x, canvas_y + y, color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void paint_put_brush(int cx, int cy) {
|
|
if (!canvas_buffer) return;
|
|
for (int dy = 0; dy < 2; dy++) {
|
|
for (int dx = 0; dx < 2; dx++) {
|
|
int px = cx + dx;
|
|
int py = cy + dy;
|
|
if (px >= 0 && px < CANVAS_W && py >= 0 && py < CANVAS_H) {
|
|
canvas_buffer[py * CANVAS_W + px] = current_color;
|
|
}
|
|
}
|
|
}
|
|
wm_mark_dirty(win_paint.x + 60 + cx, win_paint.y + 30 + cy, 2, 2);
|
|
}
|
|
|
|
void paint_handle_mouse(int x, int y) {
|
|
int cx = x - 60;
|
|
int cy = y - 30;
|
|
|
|
if (cx < 0 || cx >= CANVAS_W || cy < 0 || cy >= CANVAS_H) {
|
|
last_mx = -1;
|
|
return;
|
|
}
|
|
|
|
if (last_mx == -1) {
|
|
paint_put_brush(cx, cy);
|
|
} else {
|
|
// Bresenham's line algorithm to fill gaps
|
|
int x0 = last_mx, y0 = last_my;
|
|
int x1 = cx, y1 = cy;
|
|
int dx = (x1 - x0 > 0) ? (x1 - x0) : (x0 - x1);
|
|
int dy = (y1 - y0 > 0) ? (y1 - y0) : (y0 - y1);
|
|
int sx = x0 < x1 ? 1 : -1;
|
|
int sy = y0 < y1 ? 1 : -1;
|
|
int err = dx - dy;
|
|
|
|
while (1) {
|
|
paint_put_brush(x0, y0);
|
|
if (x0 == x1 && y0 == y1) break;
|
|
int e2 = 2 * err;
|
|
if (e2 > -dy) { err -= dy; x0 += sx; }
|
|
if (e2 < dx) { err += dx; y0 += sy; }
|
|
}
|
|
}
|
|
last_mx = cx;
|
|
last_my = cy;
|
|
}
|
|
|
|
void paint_reset_last_pos(void) {
|
|
last_mx = -1;
|
|
last_my = -1;
|
|
}
|
|
|
|
static void paint_save(const char *path) {
|
|
FAT32_FileHandle *fh = fat32_open(path, "w");
|
|
if (fh) {
|
|
uint32_t header[3] = {PAINT_MAGIC, CANVAS_W, CANVAS_H};
|
|
fat32_write(fh, header, sizeof(header));
|
|
fat32_write(fh, canvas_buffer, CANVAS_W * CANVAS_H * sizeof(uint32_t));
|
|
fat32_close(fh);
|
|
wm_show_message("Paint", "Image saved.");
|
|
}
|
|
}
|
|
|
|
void paint_load(const char *path) {
|
|
paint_strcpy(current_file_path, path);
|
|
FAT32_FileHandle *fh = fat32_open(path, "r");
|
|
if (fh) {
|
|
uint32_t header[3];
|
|
if (fat32_read(fh, header, sizeof(header)) == sizeof(header)) {
|
|
if (header[0] == PAINT_MAGIC) {
|
|
fat32_read(fh, canvas_buffer, CANVAS_W * CANVAS_H * sizeof(uint32_t));
|
|
win_paint.visible = true;
|
|
win_paint.focused = true;
|
|
}
|
|
}
|
|
fat32_close(fh);
|
|
}
|
|
}
|
|
|
|
static void paint_click(Window *win, int x, int y) {
|
|
(void)win;
|
|
// Check Buttons
|
|
if (x >= 12 && x < 48) {
|
|
if (y >= win->h - 65 && y < win->h - 45) {
|
|
paint_reset();
|
|
return;
|
|
}
|
|
if (y >= win->h - 40 && y < win->h - 20) {
|
|
paint_save(current_file_path);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Check Palette
|
|
if (x >= 15 && x < 45) {
|
|
for (int i = 0; i < 6; i++) {
|
|
int cy = 40 + (i * 25);
|
|
if (y >= cy && y < cy + 20) {
|
|
uint32_t colors[] = {COLOR_BLACK, COLOR_RED, COLOR_APPLE_GREEN, COLOR_APPLE_BLUE, COLOR_APPLE_YELLOW, COLOR_WHITE};
|
|
current_color = colors[i];
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
paint_handle_mouse(x, y);
|
|
}
|
|
|
|
void paint_init(void) {
|
|
win_paint.title = "Paint";
|
|
win_paint.x = 150;
|
|
win_paint.y = 100;
|
|
win_paint.w = 380;
|
|
win_paint.h = 260;
|
|
win_paint.visible = false;
|
|
win_paint.focused = false;
|
|
win_paint.z_index = 0;
|
|
win_paint.paint = paint_paint;
|
|
win_paint.handle_click = paint_click;
|
|
win_paint.handle_right_click = NULL;
|
|
win_paint.handle_key = NULL;
|
|
|
|
if (!canvas_buffer) {
|
|
canvas_buffer = (uint32_t*)kmalloc(CANVAS_W * CANVAS_H * sizeof(uint32_t));
|
|
paint_reset();
|
|
}
|
|
}
|
|
|
|
void paint_reset(void) {
|
|
if (canvas_buffer) {
|
|
for (int i = 0; i < CANVAS_W * CANVAS_H; i++) {
|
|
canvas_buffer[i] = COLOR_WHITE;
|
|
}
|
|
}
|
|
} |