diff options
| author | dam <dam@gudinoff> | 2023-08-17 20:28:47 +0100 |
|---|---|---|
| committer | dam <dam@gudinoff> | 2023-08-17 20:28:47 +0100 |
| commit | 709879ee56d31fe543a0ad882713bd4e3d17d2d2 (patch) | |
| tree | 12a35282bdd0f1f8a2159ade147944c89254db24 /kscurses/canvas.jai | |
| parent | fa1b8ea54646f1a0f3eadef33e3a660b875cc1ff (diff) | |
| download | task-time-tracker-709879ee56d31fe543a0ad882713bd4e3d17d2d2.tar.zst task-time-tracker-709879ee56d31fe543a0ad882713bd4e3d17d2d2.zip | |
Added kscurses and testing program.
Diffstat (limited to 'kscurses/canvas.jai')
| -rw-r--r-- | kscurses/canvas.jai | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/kscurses/canvas.jai b/kscurses/canvas.jai new file mode 100644 index 0000000..df0b021 --- /dev/null +++ b/kscurses/canvas.jai @@ -0,0 +1,172 @@ +Canvas :: struct { + zone : Ibox2; + + count : int; + pixels_last_draw : []Char; + pixels_buf : []Char; + links : []Link; + + diff_count := 0; + force_full_refresh := true; + + Link :: struct { prev, next : s32; } +} + +deinit :: (using canvas : *Canvas) { + array_free(pixels_last_draw); + array_free(pixels_buf); pixels_buf = .[]; + array_free(links); +} +resize_clear :: (using canvas : *Canvas, new_zone : Ibox2, filler := Char.{}) { + if new_zone != zone { + array_free(pixels_last_draw); + array_free(pixels_buf); + array_free(links); + + zone = new_zone; + count = zone.width * zone.height; + + pixels_last_draw = NewArray(count, Char); + pixels_buf = NewArray(count, Char); + links = NewArray(count + 1, Link); + links[count] = .{xx count, xx count}; + + if filler != .{} then { + for * pixels_buf { + <<it = filler; + } + } + links[count] = .{-1, -1}; + + force_full_refresh = true; + } else { + for y : 0..zone.height-1 { + for x : 0..zone.width-1 { + c_putchar(canvas, filler, .{xx x, xx y}); + } + } + } +} +// add *void to fill_function +resize_fill :: (using canvas : *Canvas, new_zone : Ibox2, fill_function : (coord : ivec2, zone : Ibox2) -> Char) { + if zone != new_zone { + array_free(pixels_last_draw); + array_free(pixels_buf); + array_free(links); + + zone = new_zone; + count = zone.width * zone.height; + + pixels_last_draw = NewArray(count, Char); + pixels_buf = NewArray(count, Char); + links = NewArray(count + 1, Link); + links[count] = .{xx count, xx count}; + force_full_refresh = true; + } + + c_fill(canvas, fill_function); + // i := 0; + // for y : 0..zone.height-1 { + // for x : 0..zone.width-1 { + // pixels_buf[i] = fill_function(.{x, y}, zone); + // i += 1; + // diff_count += 1; + // } + // } + + // for * links { + // <<it = .{-1, -1}; + // } +} +b_draw_canvas :: (builder : *String_Builder, using canvas : *Canvas) { + if force_full_refresh || diff_count * 4 > zone.width * zone.height { + i := 0; + for y : 0..zone.height-1 { + b_move_cursor(builder, zone.corner + ivec2.{0, y}); + for x : 0..zone.width-1 { + b_putchar(builder, pixels_buf[i]); + pixels_last_draw[i] = pixels_buf[i]; + links[i] = .{-1, -1}; + i += 1; + } + } + } else { + last_pos := ivec2.{-1, -1}; + current := links[count].next; + I := 0; + + while current != count { + assert(I < count); + assert(current >= 0); + + pos := ivec2.{xx(current % zone.width), xx(current / zone.width)} + zone.corner; + if pos.x != last_pos.x + 1 || pos.y != last_pos.y { + b_move_cursor(builder, pos); + } + b_putchar(builder, pixels_buf[current]); + pixels_last_draw[current] = pixels_buf[current]; + + next := links[current].next; + links[current] = .{-1, -1}; + current = next; + last_pos = pos; + I += 1; + } + } + + diff_count = 0; + force_full_refresh = false; + links[count] = .{xx count, xx count}; +} +c_putchar :: (using canvas : *Canvas, pixel : Char, pos_local : ivec2) { + // pos_local := pos - zone.corner; + if !point_inside(pos_local, .{size = zone.size}) return; + current := pos_local.x + pos_local.y * zone.width; + + c_last_draw := pixels_last_draw[current]; + pixels_buf[current] = pixel; + + if links[current].prev == -1 { + assert(links[current].next == -1); + if c_last_draw != pixel { + links[current] = .{links[count].prev, xx count}; + links[links[count].prev].next = current; + links[count].prev = current; + diff_count += 1; + } + } else { + if c_last_draw == pixel { + nbs := links[current]; + assert(links[nbs.prev].next == current && links[nbs.next].prev == current); + links[nbs.prev].next = nbs.next; + links[nbs.next].prev = nbs.prev; + links[current] = .{-1, -1}; + diff_count -= 1; + } + } +} + +c_fill :: (using canvas : *Canvas, fill_function : (coord : ivec2, zone : Ibox2) -> Char) { + for y : 0..zone.height-1 { + for x : 0..zone.width-1 { + char := fill_function(.{x, y}, zone); + c_putchar(canvas, char, .{x, y}); + } + } + // i := 0; + // for y : 0..zone.height-1 { + // for x : 0..zone.width-1 { + // pixels_buf[i] = fill_function(.{x, y}, zone); + // i += 1; + // diff_count += 1; + // } + // } + // refresh_all = true; +} +ks_draw_canvas :: (canvas : *Canvas) { + builder := String_Builder.{allocator = temp}; + b_draw_canvas(*builder, canvas); + ks_write(builder_to_string(*builder, allocator = temp)); +} + + |
