From 5333dc18382ecb0a2286712718ac3b4225fedf64 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Mon, 15 Apr 2024 21:40:17 +0100 Subject: implement stroke operation --- client/paintui/paintui.ha | 5 +++-- drawing/drawing.ha | 29 +++++++++++++++++++++++++++-- drawing/op.ha | 8 ++------ packet_reader/packet_reader.ha | 6 ++++-- 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/client/paintui/paintui.ha b/client/paintui/paintui.ha index 212e16b..81fa7ca 100644 --- a/client/paintui/paintui.ha +++ b/client/paintui/paintui.ha @@ -51,8 +51,9 @@ export fn tick( && (mouse_pos.0 != pstate.last_mouse_pos.0 || mouse_pos.1 != pstate.last_mouse_pos.1 || (!pstate.last_mouse_pressed))) - drawing::op_circle { - pos = mouse_pos, + drawing::op_stroke { + pos1 = mouse_pos, + pos0 = (0,0), radius = sizes[pstate.size_idx], color = pstate.color, } diff --git a/drawing/drawing.ha b/drawing/drawing.ha index 063577d..a7d9e1f 100644 --- a/drawing/drawing.ha +++ b/drawing/drawing.ha @@ -1,8 +1,7 @@ -use sdl2; use fmt; use io; use endian; -use math::random; +use math; export def CHUNKSIZE = 512; @@ -53,6 +52,8 @@ export fn outline_picture(pic: *picture) void = { fn min(a: i32, b: i32) i32 = if (a 0) 1 else 0; +fn abs(x: i32) i32 = if (x<0) -x else x; // Draws a circle onto the picture, at given position radius color // Clips at the boundaries of the picture to avoid overflow. @@ -98,6 +99,23 @@ export fn circle_hollow(picture: *picture, c: pos, r: i32, color: u32) void = { }; }; }; + +export fn stroke(picture: *picture, c0: pos, c1: pos, r: i32, color: u32) void = { + const dx = c1.0 - c0.0; + const dy = c1.1 - c0.1; + const count = (abs(dx)+abs(dy))/r; + const sx = dx: f64 / (count-1): f64; + const sy = dy: f64 / (count-1): f64; + + for (let i = 0i32; i < count; i += 1) { + const cx = c0.0 + math::roundf64(i:f64*sx):i32; + const cy = c0.1 + math::roundf64(i:f64*sy):i32; + + circle(picture, (cx, cy), r, color); + }; +}; + +// ehh should check bounding box instead of doing all pictures maybe export fn perform(pictures: []picture, op: op) void = { match (op) { case let o: op_circle => @@ -109,5 +127,12 @@ export fn perform(pictures: []picture, op: op) void = { (x - pic.world_pos.0, y - pic.world_pos.1): pos; circle(pic, pos_within_pic, r: i32, c); }; + case let s: op_stroke => + const col = s.color & 0xffffff; + for (const pic &.. pictures) { + const c0 = (s.pos0.0 - pic.world_pos.0, s.pos0.1 - pic.world_pos.1); + const c1 = (s.pos1.0 - pic.world_pos.0, s.pos1.1 - pic.world_pos.1); + stroke(pic, c0, c1, s.radius: i32, col); + }; }; }; diff --git a/drawing/op.ha b/drawing/op.ha index aa7fac4..82a412f 100644 --- a/drawing/op.ha +++ b/drawing/op.ha @@ -11,7 +11,6 @@ export type op_stroke = struct { pos1: pos, color: u32, radius: u8, - count: u8, }; export type op = (op_circle | op_stroke); @@ -22,7 +21,6 @@ type op_type = enum u8 { export type deser_fail = !void; - // return value must be freed... for now. ehh export fn ser_op(op: op) []u8 = match (op) { case let opc: op_circle => yield ser_op_circle(opc); @@ -68,8 +66,8 @@ fn deser_op_circle(bytes: []u8) (op_circle|deser_fail) = { }; }; -def SER_LEN_STROKE = 23; -// type:1 pos0:8 pos1:8 color:4 radius:1 count:1 +def SER_LEN_STROKE = 22; +// type:1 pos0:8 pos1:8 color:4 radius:1 fn ser_op_stroke(ops: op_stroke) []u8 = { let buf: []u8 = alloc([0...], SER_LEN_STROKE); buf[0] = op_type::STROKE; @@ -79,7 +77,6 @@ fn ser_op_stroke(ops: op_stroke) []u8 = { ser_pos(payload[8..16], ops.pos1); endian::leputu32(payload[16..20], ops.color); payload[20] = ops.radius; - payload[21] = ops.count; return buf; }; fn deser_op_stroke(bytes: []u8) (op_stroke|deser_fail) = { @@ -90,7 +87,6 @@ fn deser_op_stroke(bytes: []u8) (op_stroke|deser_fail) = { pos1 = deser_pos(payload[8..16]), color = endian::legetu32(payload[16..20]), radius = payload[20], - count = payload[21], }; }; diff --git a/packet_reader/packet_reader.ha b/packet_reader/packet_reader.ha index e4cbcf2..6d8c315 100644 --- a/packet_reader/packet_reader.ha +++ b/packet_reader/packet_reader.ha @@ -91,8 +91,10 @@ export fn next(pr: *packet_reader) (packet | done | error) = { const payload = packet_bytes[8..]; switch (ty) { case packet_type::DRAW_OP => - const op = drawing::deser_op(payload); - return op: packet_drawop; + match (drawing::deser_op(payload)) { + case let o: drawing::op => return o; + case drawing::deser_fail => return "deser fail": error; + }; case packet_type::SEND_CHUNK => // return value is BORROWED from the BUFFER const pos_bytes = payload[0..8]; -- cgit v1.2.3