Skip to content

Commit

Permalink
Paint: save functionality
Browse files Browse the repository at this point in the history
The pathname is fixed right now, this GUI isn't there yet to show a
modal with a textfield. Better rename the saved file if you intend to
save several in one session. Oh wait, you can't rename a file yet!

Relatedly, fixes a memory leak when writing to a file on an ext2 file
system. I found it because at first I wrote the saved image pixel by
pixel... Which took several seconds, and made the kernel abort due to
being out of memory.
  • Loading branch information
29jm committed Nov 25, 2020
1 parent a5aa50f commit 312c7c4
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 33 deletions.
1 change: 1 addition & 0 deletions kernel/src/misc/ext2.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ uint32_t ext2_append(ext2_fs_t* fs, uint32_t inode, uint8_t* data, uint32_t size
in->size_lower += size;
update_inode(fs, inode, in);
kfree(tmp);
kfree(in);

return size;
}
Expand Down
4 changes: 1 addition & 3 deletions modules/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@ install-headers:
clean:
$(info [modules] cleaning up)
@rm -f */*.o
@find . -executable -type f -delete

# TODO: every module depends on every other, a change in one rebuilds all of them
$(MODS): $(OBJS) $(LIB_DEPS) src/start.o
$(info [modules] $(notdir $@))
@mkdir -p $(TARGETROOT)
@$(LD) src/start.o src/$(@F).o -o $@ $(LDFLAGS) $(LIBS)

%.o: %.c
$(info [modules] $(notdir $(basename $@)))
@$(CC) -c $< -o $@ $(CFLAGS)

%.o: %.S
Expand Down
6 changes: 3 additions & 3 deletions modules/src/background.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ int main() {
uint32_t n_pixels = win->fb.width*win->fb.height;
uint8_t* bg = malloc(n_pixels * 3);
fread(bg, 3, n_pixels, wp);
snow_draw_rgb(win->fb, bg, 0, 0, win->fb.width, win->fb.height, 0x000000);
snow_draw_rgb(win->fb, bg, 0, 0, win->fb.width, win->fb.height);
free(bg);
fclose(wp);
} else {
snow_draw_rect(win->fb, 0, 0, scr.width, scr.height, 0x9AC4F8);
}

snow_draw_rect(win->fb, 0, 0, win->fb.width, 22, 0x303030);
snow_draw_string(win->fb, "Snowflake OS 0.5", 3, 3, 0x00FFFFFF);
snow_draw_string(win->fb, "Snowflake OS 0.6", 3, 3, 0x00FFFFFF);
snow_render_window(win);

while (true) {
Expand Down Expand Up @@ -53,7 +53,7 @@ int main() {
};

snow_draw_rect(win->fb, 0, 0, win->fb.width, 22, 0x303030);
snow_draw_string(win->fb, "Snowflake OS 0.5", 3, 3, 0x00FFFFFF);
snow_draw_string(win->fb, "Snowflake OS 0.6", 3, 3, 0x00FFFFFF);
snow_draw_string(win->fb, time_text, x, y, 0xFFFFFF);
snow_render_window_partial(win, redraw);

Expand Down
107 changes: 83 additions & 24 deletions modules/src/paint.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
#include <string.h>

// callbacks
void on_clear_clicked(button_t* button);
void on_clear_clicked();
void on_save_clicked();

bool load(const char* path, uint32_t w, uint32_t h);
void save();

const uint32_t width = 550;
const uint32_t height = 320;
Expand Down Expand Up @@ -36,24 +40,29 @@ int main(int argc, char* argv[]) {
ui_app_t paint = ui_app_new(win, fd ? icon : NULL);

vbox_t* vbox = vbox_new();
ui_set_root(paint, (widget_t*) vbox);
ui_set_root(paint, W(vbox));

hbox_t* menu = hbox_new();
menu->widget.flags &= ~UI_EXPAND_VERTICAL;
menu->widget.bounds.h = 20;
vbox_add(vbox, (widget_t*) menu);
vbox_add(vbox, W(menu));

canvas = canvas_new();
vbox_add(vbox, (widget_t*) canvas);
canvas->color = colors[0];
vbox_add(vbox, W(canvas));

for (uint32_t i = 0; i < sizeof(colors)/sizeof(colors[0]); i++) {
color_button_t* cbutton = color_button_new(colors[i], &canvas->color);
hbox_add(menu, (widget_t*) cbutton);
hbox_add(menu, W(cbutton));
}

button_t* button = button_new("Clear");
button->on_click = on_clear_clicked;
hbox_add(menu, (widget_t*) button);
hbox_add(menu, W(button));

button_t* save_button = button_new("Save");
save_button->on_click = on_save_clicked;
hbox_add(menu, W(save_button));

ui_draw(paint);
snow_render_window(win);
Expand All @@ -64,22 +73,10 @@ int main(int argc, char* argv[]) {
uint32_t w = strtol(argv[2], NULL, 10);
uint32_t h = strtol(argv[3], NULL, 10);

FILE* fd = fopen(fname, "r");

if (fd) {
uint8_t* buf = malloc(w*h*3);

if ((uint32_t) fread(buf, 3, w*h, fd) < w*h) {
printf("paint: file smaller than expected\n");
} else {
rect_t r = ui_get_absolute_bounds(W(canvas));
snow_draw_rgb(win->fb, buf, r.x, r.y, w, h, 0);
}

free(buf);
fclose(fd);
if (load(argv[1], w, h)) {
printf("paint: opened '%s'\n", fname);
} else {
printf("paint: failed to open '%s'\n", fname);
printf("paint: failed to load '%s'\n", fname);
}
}

Expand All @@ -105,8 +102,70 @@ int main(int argc, char* argv[]) {
return 0;
}

void on_clear_clicked(button_t* button) {
(void) button;

void on_clear_clicked() {
canvas->needs_clearing = true;
}

void on_save_clicked() {
save(NULL);
}

bool load(const char* path, uint32_t w, uint32_t h) {
FILE* fd = fopen(path, "r");

if (!fd) {
return false;
}

uint8_t* buf = malloc(w*h*3);

if ((uint32_t) fread(buf, 3, w*h, fd) < w*h) {
free(buf);
return false;
} else {
rect_t r = ui_get_absolute_bounds(W(canvas));
snow_draw_rgb(win->fb, buf, r.x, r.y, w, h);
}

free(buf);
fclose(fd);

return true;
}

void save() {
char fname[256] = "drawing_";
rect_t r = ui_get_absolute_bounds(W(canvas));

itoa(r.w, fname+strlen(fname), 10);
strcat(fname, "x");
itoa(r.h, fname+strlen(fname), 10);
strcat(fname, ".rgb");

printf("paint: saving to '%s'.\n", fname);

FILE* fd = fopen(fname, "w");

if (!fd) {
printf("paint: failed to open output file '%s'\n", fname);
return;
}

uint8_t* buf = malloc(r.w*r.h*3);

/* Convert from RGBA to RGB */
for (int y = r.y; y < r.y+r.h; y++) {
for (int x = r.x; x < r.x+r.w; x++) {
uint32_t px = ((uint32_t*) win->fb.address)[y*win->fb.pitch/4 + x];
uint8_t* pixbuf = (uint8_t*) &px;
uint32_t idx = (y - r.y)*3*r.w + (x - r.x)*3;
buf[idx] = pixbuf[2];
buf[idx + 1] = pixbuf[1];
buf[idx + 2] = pixbuf[0];
}
}

fwrite(buf, 3, r.w*r.h, fd);
free(buf);
fclose(fd);
}
3 changes: 2 additions & 1 deletion snow/include/snow.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ void snow_draw_line(fb_t fb, int x0, int y0, int x1, int y1, uint32_t col);
void snow_draw_border(fb_t fb, int x, int y, int w, int h, uint32_t col);
void snow_draw_character(fb_t fb, char c, int x, int y, uint32_t col);
void snow_draw_string(fb_t fb, char* str, int x, int y, uint32_t col);
void snow_draw_rgb(fb_t fb, uint8_t* rgb, int x, int y, int w, int h, uint32_t mask);
void snow_draw_rgb(fb_t fb, uint8_t* rgb, int x, int y, int w, int h);
void snow_draw_rgb_masked(fb_t fb, uint8_t* rgb, int x, int y, int w, int h, uint32_t mask);

// GUI functions
window_t* snow_open_window(char* title, int width, int height, uint32_t flags);
Expand Down
12 changes: 11 additions & 1 deletion snow/src/graphics.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,17 @@ void snow_draw_string(fb_t fb, char* str, int x, int y, uint32_t col) {
}
}

void snow_draw_rgb(fb_t fb, uint8_t* rgb, int x, int y, int w, int h, uint32_t mask) {
void snow_draw_rgb(fb_t fb, uint8_t* rgb, int x, int y, int w, int h) {
for (int i = 0, c = 0; i < h; i++) {
for (int j = 0; j < w; j++, c += 3) {
uint32_t col = rgb[c] << 16 | rgb[c+1] << 8 | rgb[c+2];

snow_draw_pixel(fb, x + j, y + i, col);
}
}
}

void snow_draw_rgb_masked(fb_t fb, uint8_t* rgb, int x, int y, int w, int h, uint32_t mask) {
for (int i = 0, c = 0; i < h; i++) {
for (int j = 0; j < w; j++, c += 3) {
uint32_t col = rgb[c] << 16 | rgb[c+1] << 8 | rgb[c+2];
Expand Down
2 changes: 1 addition & 1 deletion ui/src/titlebar.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ void titlebar_on_draw(titlebar_t* tb, fb_t fb) {
snow_draw_rect(fb, r.x, r.y, r.w, r.h, 0x303030);

if (tb->icon) {
snow_draw_rgb(fb, tb->icon, r.x+2, r.y+2, 16, 16, 0xFFFFFF);
snow_draw_rgb_masked(fb, tb->icon, r.x+2, r.y+2, 16, 16, 0xFFFFFF);
snow_draw_string(fb, tb->title, r.x+16+5, r.y+3, 0xFFFFFF);
} else {
snow_draw_string(fb, tb->title, r.x+3, r.y+3, 0xFFFFFF);
Expand Down

0 comments on commit 312c7c4

Please sign in to comment.