diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2025-02-10 00:56:18 +0100 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2025-02-10 00:56:18 +0100 |
commit | 1ed3fbcfc0dbb388917b9ae11f443e7834d4a489 (patch) | |
tree | 7646718a4774f4793a45495f9562a36dc6347653 /graphics.c | |
parent | e5b0ce30cb80abeeb1aeb0c510c095084af883ce (diff) | |
download | reduced_system_layer-1ed3fbcfc0dbb388917b9ae11f443e7834d4a489.zip |
Cleanup graphics procs
Diffstat (limited to 'graphics.c')
-rwxr-xr-x | graphics.c | 589 |
1 files changed, 378 insertions, 211 deletions
@@ -81,41 +81,12 @@ typedef struct { vec4_f32 *pixels; } Pixel_Buffer; -vec3_f32 lab_from_rgb(vec3_f32 rgb); -vec3_f32 rgb_from_lab(vec3_f32 lab); -vec3_f32 lab_from_lch(vec3_f32 lch); -vec3_f32 lch_from_lab(vec3_f32 lab); -vec3_f32 rgb_from_lch(vec3_f32 lch); -vec3_f32 lch_from_rgb(vec3_f32 rgb); - -// NOTE: General rule to work with gamma is removing it, -// then doing computations like blending, interpolation, etc, -// then adding it back. - -vec3_f32 rgb_gamma_add (vec3_f32 rgb); -vec3_f32 rgb_gamma_remove (vec3_f32 rgb); -vec4_f32 rgba_gamma_add (vec4_f32 rgb); -vec4_f32 rgba_gamma_remove(vec4_f32 rgb); - -vec3_f32 rgb_gamma_lerp (vec3_f32 a, vec3_f32 b, f32 t); -vec4_f32 rgba_gamma_lerp(vec4_f32 a, vec4_f32 b, f32 t); -vec3_f32 rgb_mix (vec3_f32 a, vec3_f32 b, f32 t); -vec4_f32 rgba_mix (vec4_f32 a, vec4_f32 b, f32 t); -vec3_f32 lch_mix (vec3_f32 a, vec3_f32 b, f32 t); -vec3_f32 lch_lerp (vec3_f32 a, vec3_f32 b, f32 t); - -u32 rgb_u32_from_f32(vec3_f32 color); -vec3_f32 rgb_f32_from_u32(u32 color); -u32 rgba_u32_from_f32(vec4_f32 color); -vec4_f32 rgba_f32_from_u32(u32 color); - -b8 hit_rectangle(f64 x0, f64 y0, f64 width, f64 height, f64 px, f64 py); -b8 hit_triangle (f64 x0, f64 y0, f64 x1, f64 y1, f64 x2, f64 y2, f64 px, f64 py); -b8 hit_quad (f64 x0, f64 y0, f64 x1, f64 y1, f64 x2, f64 y2, f64 x3, f64 y3, f64 px, f64 py); -b8 hit_ellipse (f64 x0, f64 y0, f64 width, f64 height, f64 px, f64 py); -b8 hit_line (f64 x0, f64 y0, f64 x1, f64 y1, f64 width, f64 px, f64 py); - -// ================================================================ +typedef struct { + f64 x; + f64 y; + f64 width; + f64 height; +} Box; enum { GRAPHICS_OP_NONE = 0, @@ -130,13 +101,6 @@ enum { GRAPHICS_OP_TEXT_CURSOR, }; -typedef struct { - f64 x; - f64 y; - f64 width; - f64 height; -} Box; - typedef struct graphics_request_ { u16 op; union { @@ -180,22 +144,63 @@ typedef struct graphics_request_ { vec4_f32 color; Box area; vec2 max_size; - i64 cursor; - i64 selection; i64 num_chars; c32 * text; + i64 cursor; + i64 selection; } text_cursor; }; } Graphics_Request; typedef struct { - i64 sketch_size; - vec4_f32 * sketch; vec2 scale; Pixel_Buffer dst; } Graphics_Context; -void perform_graphics_reqeust(Graphics_Context context, Graphics_Request req); +vec3_f32 lab_from_rgb(vec3_f32 rgb); +vec3_f32 rgb_from_lab(vec3_f32 lab); +vec3_f32 lab_from_lch(vec3_f32 lch); +vec3_f32 lch_from_lab(vec3_f32 lab); +vec3_f32 rgb_from_lch(vec3_f32 lch); +vec3_f32 lch_from_rgb(vec3_f32 rgb); + +// NOTE: General rule to work with gamma is removing it, +// then doing computations like blending, interpolation, etc, +// then adding it back. + +vec3_f32 rgb_gamma_add (vec3_f32 rgb); +vec3_f32 rgb_gamma_remove (vec3_f32 rgb); +vec4_f32 rgba_gamma_add (vec4_f32 rgb); +vec4_f32 rgba_gamma_remove(vec4_f32 rgb); + +vec3_f32 rgb_gamma_lerp (vec3_f32 a, vec3_f32 b, f32 t); +vec4_f32 rgba_gamma_lerp(vec4_f32 a, vec4_f32 b, f32 t); +vec3_f32 rgb_mix (vec3_f32 a, vec3_f32 b, f32 t); +vec4_f32 rgba_mix (vec4_f32 a, vec4_f32 b, f32 t); +vec3_f32 lch_mix (vec3_f32 a, vec3_f32 b, f32 t); +vec3_f32 lch_lerp (vec3_f32 a, vec3_f32 b, f32 t); + +u32 rgb_u32_from_f32(vec3_f32 color); +vec3_f32 rgb_f32_from_u32(u32 color); +u32 rgba_u32_from_f32(vec4_f32 color); +vec4_f32 rgba_f32_from_u32(u32 color); + +b8 hit_rectangle(Box area, vec2 point); +b8 hit_triangle (vec2 vertices[3], vec2 point); +b8 hit_quad (vec2 vertices[4], vec2 point); +b8 hit_ellipse (Box area, vec2 point); +b8 hit_line (vec2 vertices[2], f64 width, vec2 point); + +void draw_pixels (Box area, Pixel_Buffer src); +void fill_rectangle (vec4_f32 color, Box area); +void fill_triangle (vec4_f32 color, vec2 vertices[3]); +void fill_quad (vec4_f32 color, vec2 vertices[4]); +void fill_ellipse (vec4_f32 color, Box area); +void fill_line (vec4_f32 color, vec2 vertices[2], f64 width); +void draw_text_area (vec4_f32 color, Box area, vec2 max_size, i64 num_chars, c32 *text); +void draw_text_cursor(vec4_f32 color, Box area, vec2 max_size, i64 num_chars, c32 *text, i64 cursor, i64 selection); + +void perform_graphics_request(Graphics_Context context, Graphics_Request req); #endif // GRAPHICS_HEADER_GUARD_ @@ -253,7 +258,7 @@ static f64 gamma_re_(f64 x) { return x / 12.92; } -static void put_pixel_alpha_(Pixel_Buffer dst, vec4_f32 color, i64 x, i64 y) { +static void put_pixel_(Pixel_Buffer dst, vec4_f32 color, i64 x, i64 y) { i64 n = y * dst.stride + x; if (color.w == 1.f) @@ -271,16 +276,16 @@ static void put_pixel_alpha_(Pixel_Buffer dst, vec4_f32 color, i64 x, i64 y) { } } -void draw_pixels_raw(Pixel_Buffer dst, f64 x0, f64 y0, f64 w, f64 h, Pixel_Buffer src) { - f64 x1 = x0 + w; - f64 y1 = y0 + h; +void draw_pixels_raw(Pixel_Buffer dst, Box area, Pixel_Buffer src) { + f64 x1 = area.x + area.width; + f64 y1 = area.y + area.height; - if (w < EPSILON || h < EPSILON) + if (area.width < EPSILON || area.height < EPSILON) return; - i64 i0 = (i64) floor(x0); + i64 i0 = (i64) floor(area.x); i64 i1 = (i64) floor(x1); - i64 j0 = (i64) floor(y0); + i64 j0 = (i64) floor(area.y); i64 j1 = (i64) floor(y1); if (i0 < 0) i0 = 0; @@ -288,19 +293,19 @@ void draw_pixels_raw(Pixel_Buffer dst, f64 x0, f64 y0, f64 w, f64 h, Pixel_Buffe if (j0 < 0) j0 = 0; if (j1 >= dst.height) j1 = dst.height - 1; - f64 w_inv = 1. / w; - f64 h_inv = 1. / h; + f64 w_inv = 1. / area.width; + f64 h_inv = 1. / area.height; for (i64 j = j0; j <= j1; ++j) { - i64 src_j0 = (i64) floor(((j - y0) * src.height) * h_inv + .5); - i64 src_j1 = (i64) floor(((j + 1 - y0) * src.height) * h_inv + .5); + i64 src_j0 = (i64) floor(((j - area.y) * src.height) * h_inv + .5); + i64 src_j1 = (i64) floor(((j + 1 - area.y) * src.height) * h_inv + .5); if (src_j0 == src_j1) src_j1 = src_j0 + 1; if (src_j1 <= 0 || src_j0 >= src.height) continue; if (src_j0 < 0) src_j0 = 0; if (src_j1 > src.height) src_j1 = src.height; for (i64 i = i0; i <= i1; ++i) { - i64 src_i0 = (i64) floor(((i - x0) * src.width) * w_inv + .5); - i64 src_i1 = (i64) floor(((i + 1 - x0) * src.width) * w_inv + .5); + i64 src_i0 = (i64) floor(((i - area.x) * src.width) * w_inv + .5); + i64 src_i1 = (i64) floor(((i + 1 - area.x) * src.width) * w_inv + .5); if (src_i0 == src_i1) src_i1 = src_i0 + 1; if (src_i1 <= 0 || src_i0 >= src.width) continue; if (src_i0 < 0) src_i0 = 0; @@ -322,18 +327,18 @@ void draw_pixels_raw(Pixel_Buffer dst, f64 x0, f64 y0, f64 w, f64 h, Pixel_Buffe color.y = gamma_(color.y * n_inv); color.z = gamma_(color.z * n_inv); color.w = gamma_(color.w * n_inv); - put_pixel_alpha_(dst, color, i, j); + put_pixel_(dst, color, i, j); } } } -void fill_rectangle_raw(Pixel_Buffer dst, vec4_f32 color, f64 x0, f64 y0, f64 w, f64 h) { - f64 x1 = x0 + w; - f64 y1 = y0 + h; +void fill_rectangle_raw(Pixel_Buffer dst, vec4_f32 color, Box area) { + f64 x1 = area.x + area.width; + f64 y1 = area.y + area.height; - i64 i0 = (i64) ceil (x0); + i64 i0 = (i64) ceil (area.x); i64 i1 = (i64) floor(x1); - i64 j0 = (i64) ceil (y0); + i64 j0 = (i64) ceil (area.y); i64 j1 = (i64) floor(y1); i64 i00 = i0; @@ -346,14 +351,14 @@ void fill_rectangle_raw(Pixel_Buffer dst, vec4_f32 color, f64 x0, f64 y0, f64 w, if (j0 < 0) j0 = 0; if (j1 > dst.height) j1 = dst.height; - f64 kx0 = i00 - x0; + f64 kx0 = i00 - area.x; f64 kx1 = x1 - i10; - f64 ky0 = j00 - y0; + f64 ky0 = j00 - area.y; f64 ky1 = y1 - j10; for (i64 j = j0; j < j1; ++j) for (i64 i = i0; i < i1; ++i) - put_pixel_alpha_(dst, color, i, j); + put_pixel_(dst, color, i, j); if (i00 > i10) { kx0 *= kx1; @@ -370,53 +375,60 @@ void fill_rectangle_raw(Pixel_Buffer dst, vec4_f32 color, f64 x0, f64 y0, f64 w, if (i00 - 1 >= 0 && i00 - 1 < dst.width) { color.w = gamma_(gamma_re_(alpha) * kx0); for (i64 j = j0; j < j1; ++j) - put_pixel_alpha_(dst, color, i00 - 1, j); + put_pixel_(dst, color, i00 - 1, j); } if (i10 >= 0 && i10 < dst.width) { color.w = gamma_(gamma_re_(alpha) * kx1); for (i64 j = j0; j < j1; ++j) - put_pixel_alpha_(dst, color, i10, j); + put_pixel_(dst, color, i10, j); } if (j00 - 1 >= 0 && j00 - 1 < dst.height) { color.w = gamma_(gamma_re_(alpha) * ky0); for (i64 i = i0; i < i1; ++i) - put_pixel_alpha_(dst, color, i, j00 - 1); + put_pixel_(dst, color, i, j00 - 1); } if (j10 >= 0 && j10 < dst.height) { color.w = gamma_(gamma_re_(alpha) * ky1); for (i64 i = i0; i < i1; ++i) - put_pixel_alpha_(dst, color, i, j10); + put_pixel_(dst, color, i, j10); } if ( i00 - 1 >= 0 && i00 - 1 < dst.width && j00 - 1 >= 0 && j00 - 1 < dst.height) { color.w = gamma_(gamma_re_(alpha) * kx0 * ky0); - put_pixel_alpha_(dst, color, i00 - 1, j00 - 1); + put_pixel_(dst, color, i00 - 1, j00 - 1); } if ( i10 >= 0 && i10 < dst.width && j00 - 1 >= 0 && j00 - 1 < dst.height) { color.w = gamma_(gamma_re_(alpha) * kx1 * ky0); - put_pixel_alpha_(dst, color, i10, j00 - 1); + put_pixel_(dst, color, i10, j00 - 1); } if ( i00 - 1 >= 0 && i00 - 1 < dst.width && j10 >= 0 && j10 < dst.height) { color.w = gamma_(gamma_re_(alpha) * kx0 * ky1); - put_pixel_alpha_(dst, color, i00 - 1, j10); + put_pixel_(dst, color, i00 - 1, j10); } if ( i10 >= 0 && i10 < dst.width && j10 >= 0 && j10 < dst.height) { color.w = gamma_(gamma_re_(alpha) * kx1 * ky1); - put_pixel_alpha_(dst, color, i10, j10); + put_pixel_(dst, color, i10, j10); } } -void fill_triangle_raw(Pixel_Buffer dst, vec4_f32 color, f64 x0, f64 y0, f64 x1, f64 y1, f64 x2, f64 y2) { +void fill_triangle_raw(Pixel_Buffer dst, vec4_f32 color, vec2 vertices[3]) { + f64 x0 = vertices[0].x; + f64 y0 = vertices[0].y; + f64 x1 = vertices[1].x; + f64 y1 = vertices[1].y; + f64 x2 = vertices[2].x; + f64 y2 = vertices[2].y; + i64 i0 = (i64) floor(min3_(x0, x1, x2)); i64 j0 = (i64) floor(min3_(y0, y1, y2)); i64 i1 = (i64) ceil (max3_(x0, x1, x2)); @@ -434,23 +446,33 @@ void fill_triangle_raw(Pixel_Buffer dst, vec4_f32 color, f64 x0, f64 y0, f64 x1, i64 right = i0; for (i64 i = i0; i <= i1; ++i) - if (hit_triangle(x0, y0, x1, y1, x2, y2, (f64) i, (f64) j)) { + if (hit_triangle(vertices, (vec2) { (f64) i, (f64) j, })) { left = i; break; } for (i64 i = i1; i >= i0; --i) - if (hit_triangle(x0, y0, x1, y1, x2, y2, (f64) i, (f64) j)) { + if (hit_triangle(vertices, (vec2) { (f64) i, (f64) j, })) { right = i; break; } for (i64 i = left; i <= right; ++i) - put_pixel_alpha_(dst, color, i, j); + put_pixel_(dst, color, i, j); } } -void fill_quad_raw(Pixel_Buffer dst, vec4_f32 color, f64 x0, f64 y0, f64 x1, f64 y1, f64 x2, f64 y2, f64 x3, f64 y3) { +void fill_quad_raw(Pixel_Buffer dst, vec4_f32 color, vec2 vertices[4]) { + f64 x0 = vertices[0].x; + f64 y0 = vertices[0].y; + f64 x1 = vertices[1].x; + f64 y1 = vertices[1].y; + f64 x2 = vertices[2].x; + f64 y2 = vertices[2].y; + f64 x3 = vertices[3].x; + f64 y3 = vertices[3].y; + + i64 i0 = (i64) floor(min3_(x0, x1, x2)); i64 j0 = (i64) floor(min3_(y0, y1, y2)); i64 i1 = (i64) ceil (max3_(x0, x1, x2)); @@ -468,40 +490,40 @@ void fill_quad_raw(Pixel_Buffer dst, vec4_f32 color, f64 x0, f64 y0, f64 x1, f64 i64 right = i0; for (i64 i = i0; i <= i1; ++i) - if (hit_quad(x0, y0, x1, y1, x2, y2, x3, y3, (f64) i, (f64) j)) { + if (hit_quad(vertices, (vec2) { (f64) i, (f64) j, })) { left = i; break; } for (i64 i = i1; i >= i0; --i) - if (hit_quad(x0, y0, x1, y1, x2, y2, x3, y3, (f64) i, (f64) j)) { + if (hit_quad(vertices, (vec2) { (f64) i, (f64) j, })) { right = i; break; } for (i64 i = left; i <= right; ++i) - put_pixel_alpha_(dst, color, i, j); + put_pixel_(dst, color, i, j); } } -void fill_ellipse_raw(Pixel_Buffer dst, vec4_f32 color, f64 x0, f64 y0, f64 w, f64 h) { - f64 y1 = y0 + h; +void fill_ellipse_raw(Pixel_Buffer dst, vec4_f32 color, Box area) { + f64 y1 = area.y + area.height; - i64 j0 = (i64) floor(y0); + i64 j0 = (i64) floor(area.y); i64 j1 = (i64) ceil (y1); if (j0 < 0) j0 = 0; if (j1 >= dst.height) j1 = dst.height - 1; - f64 half_w = w / 2.0; - f64 half_h = h / 2.0; + f64 half_w = area.width / 2.0; + f64 half_h = area.height / 2.0; if (half_h < EPSILON) return; f64 inv_half_h = 1.0 / half_h; - f64 cx = x0 + half_w; - f64 cy = y0 + half_h; + f64 cx = area.x + half_w; + f64 cy = area.y + half_h; for (i64 j = j0; j <= j1; ++j) { f64 ry = (j - cy) * inv_half_h; @@ -517,14 +539,19 @@ void fill_ellipse_raw(Pixel_Buffer dst, vec4_f32 color, f64 x0, f64 y0, f64 w, f if (right >= dst.width) right = dst.width - 1; for (i64 i = left; i <= right; ++i) - put_pixel_alpha_(dst, color, i, j); + put_pixel_(dst, color, i, j); } } -void fill_line_raw(Pixel_Buffer dst, vec4_f32 color, f64 x0, f64 y0, f64 x1, f64 y1, f64 width) { +void fill_line_raw(Pixel_Buffer dst, vec4_f32 color, vec2 vertices[2], f64 width) { if (width < EPSILON) return; + f64 x0 = vertices[0].x; + f64 y0 = vertices[0].y; + f64 x1 = vertices[1].x; + f64 y1 = vertices[1].y; + f64 dx = x1 - x0; f64 dy = y1 - y0; @@ -541,7 +568,12 @@ void fill_line_raw(Pixel_Buffer dst, vec4_f32 color, f64 x0, f64 y0, f64 x1, f64 tx *= width * k; ty *= width * k; - fill_quad_raw(dst, color, x0 - tx, y0 - ty, x0 + tx, y0 + ty, x1 + tx, y1 + ty, x1 - tx, y1 - ty); + fill_quad_raw(dst, color, (vec2[4]) { + { x0 - tx, y0 - ty }, + { x0 + tx, y0 + ty }, + { x1 + tx, y1 + ty }, + { x1 - tx, y1 - ty }, + }); } static i64 char_column_offset_(c32 c, i64 column_index) { @@ -743,7 +775,7 @@ static void draw_text_(Pixel_Buffer dst, vec4_f32 color, f64 x0, f64 y0, f64 sca for (i64 j = j0; j <= j1; ++j) { i64 row = (i64) floor(((j - y) * CHAR_NUM_BITS_Y_) * h_inv + .5); if (char_bit_(offset, row)) - put_pixel_alpha_(dst, color, i, j); + put_pixel_(dst, color, i, j); } } } @@ -752,29 +784,29 @@ static void draw_text_(Pixel_Buffer dst, vec4_f32 color, f64 x0, f64 y0, f64 sca } } -void draw_text_area_raw(Pixel_Buffer dst, vec4_f32 color, f64 x, f64 y, f64 width, f64 height, f64 max_width, f64 max_height, i64 num_chars, c32 *text) { - if (text == NULL || num_chars <= 0 || max_width < EPSILON || max_height < EPSILON) +void draw_text_area_raw(Pixel_Buffer dst, vec4_f32 color, Box area, vec2 max_size, i64 num_chars, c32 *text) { + if (text == NULL || num_chars <= 0 || max_size.x < EPSILON || max_size.y < EPSILON) return; i64 num_columns = enum_text_columns_(num_chars, text); i64 num_rows = enum_text_rows_(num_chars, text); - f64 scale_x = width / num_columns; - f64 scale_y = height / num_rows; + f64 scale_x = area.width / num_columns; + f64 scale_y = area.height / num_rows; - f64 kx = scale_x / max_width; - f64 ky = scale_y / max_height; + f64 kx = scale_x / max_size.x; + f64 ky = scale_y / max_size.y; f64 k = kx < ky ? kx : ky; - kx = k * max_width; - ky = k * max_height; + kx = k * max_size.x; + ky = k * max_size.y; - draw_text_(dst, color, x, y, kx, ky, num_chars, text); + draw_text_(dst, color, area.x, area.y, kx, ky, num_chars, text); } -void draw_text_cursor_raw(Pixel_Buffer dst, vec4_f32 color, f64 x, f64 y, f64 width, f64 height, f64 max_width, f64 max_height, i64 cursor, i64 selection, i64 num_chars, c32 *text) { - if (max_width < EPSILON || max_height < EPSILON) +void draw_text_cursor_raw(Pixel_Buffer dst, vec4_f32 color, Box area, vec2 max_size, i64 num_chars, c32 *text, i64 cursor, i64 selection) { + if (max_size.x< EPSILON || max_size.y < EPSILON) return; i64 num_columns = enum_text_columns_(num_chars, text); @@ -782,16 +814,16 @@ void draw_text_cursor_raw(Pixel_Buffer dst, vec4_f32 color, f64 x, f64 y, f64 wi i64 cursor_x = text_cursor_(cursor, text); i64 cursor_y = enum_text_rows_(cursor, text); - f64 scale_x = width / num_columns; - f64 scale_y = height / num_rows; + f64 scale_x = area.width / num_columns; + f64 scale_y = area.height / num_rows; - f64 kx = scale_x / max_width; - f64 ky = scale_y / max_height; + f64 kx = scale_x / max_size.x; + f64 ky = scale_y / max_size.y; f64 k = kx < ky ? kx : ky; - kx = k * max_width; - ky = k * max_height; + kx = k * max_size.x; + ky = k * max_size.y; if (selection != 0) { i64 selection_x, selection_y; @@ -810,46 +842,56 @@ void draw_text_cursor_raw(Pixel_Buffer dst, vec4_f32 color, f64 x, f64 y, f64 wi fill_rectangle_raw( dst, color, - x + kx * cursor_x, - y + ky * cursor_y - ky * (CHAR_NUM_BITS_Y_ + 1), - kx * (selection_x - cursor_x), - ky * (CHAR_NUM_BITS_Y_ + 1) + (Box) { + .x = area.x + kx * cursor_x, + .y = area.y + ky * cursor_y - ky * (CHAR_NUM_BITS_Y_ + 1), + .width = kx * (selection_x - cursor_x), + .height = ky * (CHAR_NUM_BITS_Y_ + 1), + } ); else { fill_rectangle_raw( dst, color, - x + kx * cursor_x, - y + ky * cursor_y - ky * (CHAR_NUM_BITS_Y_ + 1), - kx * (num_columns - cursor_x), - ky * (CHAR_NUM_BITS_Y_ + 1) + (Box) { + .x = area.x + kx * cursor_x, + .y = area.y + ky * cursor_y - ky * (CHAR_NUM_BITS_Y_ + 1), + .width = kx * (num_columns - cursor_x), + .height = ky * (CHAR_NUM_BITS_Y_ + 1), + } ); for (i64 j = cursor_y + CHAR_NUM_BITS_Y_ + 1; j < selection_y; j += CHAR_NUM_BITS_Y_ + 1) fill_rectangle_raw( dst, color, - x, - y + ky * j - ky * (CHAR_NUM_BITS_Y_ + 1), - kx * num_columns, - ky * (CHAR_NUM_BITS_Y_ + 1) + (Box) { + .x = area.x, + .y = area.y + ky * j - ky * (CHAR_NUM_BITS_Y_ + 1), + .width = kx * num_columns, + .height = ky * (CHAR_NUM_BITS_Y_ + 1), + } ); fill_rectangle_raw( dst, color, - x, - y + ky * selection_y - ky * (CHAR_NUM_BITS_Y_ + 1), - kx * selection_x, - ky * (CHAR_NUM_BITS_Y_ + 1) + (Box) { + .x = area.x, + .y = area.y + ky * selection_y - ky * (CHAR_NUM_BITS_Y_ + 1), + .width = kx * selection_x, + .height = ky * (CHAR_NUM_BITS_Y_ + 1), + } ); } } else fill_rectangle_raw( dst, color, - x + kx * cursor_x, - y + ky * cursor_y - ky * CHAR_NUM_BITS_Y_, - kx * .5, - ky * (CHAR_NUM_BITS_Y_ - 1) + (Box) { + .x = area.x + kx * cursor_x, + .y = area.y + ky * cursor_y - ky * CHAR_NUM_BITS_Y_, + .width = kx * .5, + .height = ky * (CHAR_NUM_BITS_Y_ - 1), + } ); } @@ -1086,14 +1128,23 @@ vec4_f32 rgba_f32_from_u32(u32 color) { }; } -b8 hit_rectangle(f64 x0, f64 y0, f64 width, f64 height, f64 px, f64 py) { - return px >= x0 && px < x0 + width && py >= y0 && py < y0 + height; +b8 hit_rectangle(Box area, vec2 point) { + return point.x >= area.x && point.x < area.x + area.width && point.y >= area.y && point.y < area.y + area.height; } -b8 hit_triangle(f64 x0, f64 y0, f64 x1, f64 y1, f64 x2, f64 y2, f64 px, f64 py) { +b8 hit_triangle(vec2 vertices[3], vec2 point) { // Z-components of cross-products // + f64 x0 = vertices[0].x; + f64 y0 = vertices[0].y; + f64 x1 = vertices[1].x; + f64 y1 = vertices[1].y; + f64 x2 = vertices[2].x; + f64 y2 = vertices[2].y; + f64 px = point.x; + f64 py = point.y; + f64 x10 = x1 - x0; f64 x21 = x2 - x1; f64 x02 = x0 - x2; @@ -1115,30 +1166,44 @@ b8 hit_triangle(f64 x0, f64 y0, f64 x1, f64 y1, f64 x2, f64 y2, f64 px, f64 py) && same_sign_(z2, pz2); } -b8 hit_quad(f64 x0, f64 y0, f64 x1, f64 y1, f64 x2, f64 y2, f64 x3, f64 y3, f64 px, f64 py) { - return hit_triangle(x0, y0, x1, y1, x2, y2, px, py) - || hit_triangle(x0, y0, x2, y2, x3, y3, px, py); +b8 hit_quad(vec2 vertices[4], vec2 point) { + f64 x0 = vertices[0].x; + f64 y0 = vertices[0].y; + f64 x1 = vertices[1].x; + f64 y1 = vertices[1].y; + f64 x2 = vertices[2].x; + f64 y2 = vertices[2].y; + f64 x3 = vertices[3].x; + f64 y3 = vertices[3].y; + + return hit_triangle((vec2[3]) { { x0, y0 }, { x1, y1 }, { x2, y2 }, }, point) + || hit_triangle((vec2[3]) { { x0, y0 }, { x2, y2 }, { x3, y3 }, }, point); } -b8 hit_ellipse(f64 x0, f64 y0, f64 width, f64 height, f64 px, f64 py) { - f64 dw = width / 2; - f64 dh = height / 2; +b8 hit_ellipse(Box area, vec2 point) { + f64 dw = area.width / 2; + f64 dh = area.height / 2; if (dw < EPSILON || dh < EPSILON) return 0; - f64 cx = x0 + dw; - f64 cy = y0 + dh; + f64 cx = area.x + dw; + f64 cy = area.y + dh; f64 kx = 1. / dw; f64 ky = 1. / dh; - f64 dx = (px - cx) * kx; - f64 dy = (py - cy) * ky; + f64 dx = (point.x - cx) * kx; + f64 dy = (point.y - cy) * ky; return dx * dx + dy * dy - 1.0 < EPSILON; } -b8 hit_line(f64 x0, f64 y0, f64 x1, f64 y1, f64 width, f64 px, f64 py) { +b8 hit_line(vec2 vertices[2], f64 width, vec2 point) { + f64 x0 = vertices[0].x; + f64 y0 = vertices[0].y; + f64 x1 = vertices[1].x; + f64 y1 = vertices[1].y; + f64 dx = x1 - x0; f64 dy = y1 - y0; @@ -1154,7 +1219,134 @@ b8 hit_line(f64 x0, f64 y0, f64 x1, f64 y1, f64 width, f64 px, f64 py) { tx *= width * .5; ty *= width * .5; - return hit_quad(x0 - tx, y0 - ty, x0 + tx, y0 + ty, x1 + tx, y1 + ty, x1 - tx, y1 - ty, px, py); + return hit_quad((vec2[4]) { + { x0 - tx, y0 - ty }, + { x0 + tx, y0 + ty }, + { x1 + tx, y1 + ty }, + { x1 - tx, y1 - ty }, + }, point); +} + +void draw_pixels(Box area, Pixel_Buffer src) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_OP_PIXELS, + .pixels = { + .area = area, + .src = src, + }, + } + ); +} + +void fill_rectangle(vec4_f32 color, Box area) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_OP_RECTANGLE, + .rectangle = { + .color = color, + .area = area, + }, + } + ); +} + +void fill_triangle(vec4_f32 color, vec2 vertices[3]) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_OP_TRIANGLE, + .triangle = { + .color = color, + .vertices = { + vertices[0], + vertices[1], + vertices[2], + }, + }, + } + ); +} + +void fill_quad(vec4_f32 color, vec2 vertices[4]) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_OP_QUAD, + .quad = { + .color = color, + .vertices = { + vertices[0], + vertices[1], + vertices[2], + vertices[3], + }, + }, + } + ); +} + +void fill_ellipse(vec4_f32 color, Box area) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_OP_ELLIPSE, + .ellipse = { + .color = color, + .area = area, + }, + } + ); +} + +void fill_line(vec4_f32 color, vec2 vertices[2], f64 width) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_OP_LINE, + .line = { + .color = color, + .vertices = { vertices[0], vertices[1], }, + .width = width, + }, + } + ); +} + +void draw_text_area(vec4_f32 color, Box area, vec2 max_size, i64 num_chars, c32 *text) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_OP_TEXT_AREA, + .text_area = { + .color = color, + .area = area, + .max_size = max_size, + .num_chars = num_chars, + .text = text, + }, + } + ); +} + +void draw_text_cursor(vec4_f32 color, Box area, vec2 max_size, i64 num_chars, c32 *text, i64 cursor, i64 selection) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_OP_TEXT_CURSOR, + .text_cursor = { + .color = color, + .area = area, + .max_size = max_size, + .num_chars = num_chars, + .text = text, + .cursor = cursor, + .selection = selection, + }, + } + ); } // ================================================================ @@ -1169,10 +1361,7 @@ void perform_raw_graphics_request_(Graphics_Context context, Graphics_Request re case GRAPHICS_OP_PIXELS: draw_pixels_raw( context.dst, - req.pixels.area.x, - req.pixels.area.y, - req.pixels.area.width, - req.pixels.area.height, + req.pixels.area, req.pixels.src ); break; @@ -1181,10 +1370,7 @@ void perform_raw_graphics_request_(Graphics_Context context, Graphics_Request re fill_rectangle_raw( context.dst, req.rectangle.color, - req.rectangle.area.x, - req.rectangle.area.y, - req.rectangle.area.width, - req.rectangle.area.height + req.rectangle.area ); break; @@ -1192,12 +1378,7 @@ void perform_raw_graphics_request_(Graphics_Context context, Graphics_Request re fill_triangle_raw( context.dst, req.triangle.color, - req.triangle.vertices[0].x, - req.triangle.vertices[0].y, - req.triangle.vertices[1].x, - req.triangle.vertices[1].y, - req.triangle.vertices[2].x, - req.triangle.vertices[2].y + req.triangle.vertices ); break; @@ -1205,14 +1386,7 @@ void perform_raw_graphics_request_(Graphics_Context context, Graphics_Request re fill_quad_raw( context.dst, req.quad.color, - req.quad.vertices[0].x, - req.quad.vertices[0].y, - req.quad.vertices[1].x, - req.quad.vertices[1].y, - req.quad.vertices[2].x, - req.quad.vertices[2].y, - req.quad.vertices[3].x, - req.quad.vertices[3].y + req.quad.vertices ); break; @@ -1220,10 +1394,7 @@ void perform_raw_graphics_request_(Graphics_Context context, Graphics_Request re fill_ellipse_raw( context.dst, req.ellipse.color, - req.ellipse.area.x, - req.ellipse.area.y, - req.ellipse.area.width, - req.ellipse.area.height + req.ellipse.area ); break; @@ -1231,10 +1402,7 @@ void perform_raw_graphics_request_(Graphics_Context context, Graphics_Request re fill_line_raw( context.dst, req.line.color, - req.line.vertices[0].x, - req.line.vertices[0].y, - req.line.vertices[1].x, - req.line.vertices[1].y, + req.line.vertices, req.line.width ); break; @@ -1243,12 +1411,8 @@ void perform_raw_graphics_request_(Graphics_Context context, Graphics_Request re draw_text_area_raw( context.dst, req.text_area.color, - req.text_area.area.x, - req.text_area.area.y, - req.text_area.area.width, - req.text_area.area.height, - req.text_area.max_size.x, - req.text_area.max_size.y, + req.text_area.area, + req.text_area.max_size, req.text_area.num_chars, req.text_area.text ); @@ -1258,16 +1422,12 @@ void perform_raw_graphics_request_(Graphics_Context context, Graphics_Request re draw_text_cursor_raw( context.dst, req.text_cursor.color, - req.text_cursor.area.x, - req.text_cursor.area.y, - req.text_cursor.area.width, - req.text_cursor.area.height, - req.text_cursor.max_size.x, - req.text_cursor.max_size.y, - req.text_cursor.cursor, - req.text_cursor.selection, + req.text_cursor.area, + req.text_cursor.max_size, req.text_cursor.num_chars, - req.text_cursor.text + req.text_cursor.text, + req.text_cursor.cursor, + req.text_cursor.selection ); break; @@ -1379,11 +1539,6 @@ void scale_and_perform_graphics_request_(Graphics_Context context, Graphics_Requ // ================================================================ void perform_graphics_request(Graphics_Context context, Graphics_Request req) { - if (context.sketch == NULL) { - context.sketch_size = MAX_NUM_PIXELS; - context.sketch = g_platform.sketch; - } - if (context.dst.pixels == NULL) { context.dst.width = g_platform.frame_width; context.dst.height = g_platform.frame_height; @@ -1495,56 +1650,68 @@ Pixel_Buffer pixels = { .width = 1280, .height = 720, .stride = 1280, - .pixels = g_platform.sketch, + .pixels = (vec4_f32[1280 * 720]) {0}, }; vec4_f32 color = { 1., 1., 1., 1., }; -BENCHMARK("fill rectangle") { +BENCHMARK("fill rectangle raw") { BENCHMARK_BEGIN; { - fill_rectangle_raw(pixels, color, 100, 100, 300, 200); + fill_rectangle_raw(pixels, color, (Box) { .x = 100, .y = 100, .width = 300, .height = 200, }); } BENCHMARK_END; } -BENCHMARK("fill triangle") { +BENCHMARK("fill triangle raw") { BENCHMARK_BEGIN; { - fill_triangle_raw(pixels, color, 100, 100, 300, 100, 200, 250); + fill_triangle_raw(pixels, color, (vec2[3]) { + { 100, 100 }, + { 300, 100 }, + { 200, 250 }, + }); } BENCHMARK_END; } -BENCHMARK("fill quad") { +BENCHMARK("fill quad raw") { BENCHMARK_BEGIN; { - fill_quad_raw(pixels, color, 100, 100, 300, 100, 300, 200, 100, 200); + fill_quad_raw(pixels, color, (vec2[4]) { + { 100, 100 }, + { 300, 100 }, + { 300, 200 }, + { 100, 200 }, + }); } BENCHMARK_END; } -BENCHMARK("fill ellipse") { +BENCHMARK("fill ellipse raw") { BENCHMARK_BEGIN; { - fill_ellipse_raw(pixels, color, 80, 80, 340, 240); + fill_ellipse_raw(pixels, color, (Box) { .x = 80, .y = 80, .width = 340, .height = 240, }); } BENCHMARK_END; } -BENCHMARK("fill line") { +BENCHMARK("fill line raw") { BENCHMARK_BEGIN; { - fill_line_raw(pixels, color, 100, 100, 300, 200, 40); + fill_line_raw(pixels, color, (vec2[2]) { + { 100, 100 }, + { 300, 200 }, + }, 40); } BENCHMARK_END; } -BENCHMARK("draw text area") { +BENCHMARK("draw text area raw") { BENCHMARK_BEGIN; { c32 text[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'S', 'a', 'i', 'l', 'o', 'r', '!', }; - draw_text_area_raw(pixels, color, 100, 100, 300, 200, 100, 200, sizeof text / sizeof *text, text); + draw_text_area_raw(pixels, color, (Box) { .x = 100, .y = 100, .width = 300, .height = 200, }, (vec2) { 100, 200 }, sizeof text / sizeof *text, text); } BENCHMARK_END; } |