diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2025-04-25 13:12:18 +0200 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2025-04-25 13:12:18 +0200 |
commit | 8a4b4bed8259397c6d958766573a0bfa25909b98 (patch) | |
tree | 8059d85144efa563959885dac9fa142c1eeafde7 | |
parent | 32f60821408fe51d0acf45e430556c12711e5cc5 (diff) | |
download | reduced_system_layer-8a4b4bed8259397c6d958766573a0bfa25909b98.zip |
Cleanup
-rw-r--r-- | graphics.c | 1262 |
1 files changed, 639 insertions, 623 deletions
@@ -240,11 +240,366 @@ void clean_graphics_requests_cache(i64 amount); #endif // GRAPHICS_HEADER_GUARD_ // ================================================================ +// +// IMPLEMENTATION +// +// ================================================================ #ifndef GRAPHICS_HEADER #ifndef GRAPHICS_IMPL_GUARD_ #define GRAPHICS_IMPL_GUARD_ +// ================================================================ +// +// Colors +// +// ================================================================ + +vec3_f32 vec3_from_vec4_f32(vec4_f32 v) { + return (vec3_f32) { + .x = v.x, + .y = v.y, + .z = v.z, + }; +} + +vec4_f32 vec4_from_vec3_f32(vec3_f32 v, f32 w) { + return (vec4_f32) { + .x = v.x, + .y = v.y, + .z = v.z, + .w = w, + }; +} + +vec3_f32 vec3_f32_lerp(vec3_f32 a, vec3_f32 b, f32 t) { + return (vec3_f32) { + .x = a.x + (b.x - a.x) * t, + .y = a.y + (b.y - a.y) * t, + .z = a.z + (b.z - a.z) * t, + }; +} + +vec4_f32 vec4_f32_lerp(vec4_f32 a, vec4_f32 b, f32 t) { + return (vec4_f32) { + .x = a.x + (b.x - a.x) * t, + .y = a.y + (b.y - a.y) * t, + .z = a.z + (b.z - a.z) * t, + .w = a.w + (b.w - a.w) * t, + }; +} + +vec3_f32 rgb_gamma_add(vec3_f32 rgb) { + return (vec3_f32) { + .x = gamma_(rgb.x), + .y = gamma_(rgb.y), + .z = gamma_(rgb.z), + }; +} + +vec3_f32 rgb_gamma_remove(vec3_f32 rgb) { + return (vec3_f32) { + .x = gamma_re_(rgb.x), + .y = gamma_re_(rgb.y), + .z = gamma_re_(rgb.z), + }; +} + +vec4_f32 rgba_gamma_add(vec4_f32 rgba) { + return (vec4_f32) { + .x = gamma_(rgba.x), + .y = gamma_(rgba.y), + .z = gamma_(rgba.z), + .w = gamma_(rgba.w), + }; +} + +vec4_f32 rgba_gamma_remove(vec4_f32 rgba) { + return (vec4_f32) { + .x = gamma_re_(rgba.x), + .y = gamma_re_(rgba.y), + .z = gamma_re_(rgba.z), + .w = gamma_re_(rgba.w), + }; +} + +vec3_f32 lab_from_rgb(vec3_f32 rgb) { + f64 l = 0.4122214708 * rgb.x + 0.5363325363 * rgb.y + 0.0514459929 * rgb.z; + f64 m = 0.2119034982 * rgb.x + 0.6806995451 * rgb.y + 0.1073969566 * rgb.z; + f64 s = 0.0883024619 * rgb.x + 0.2817188376 * rgb.y + 0.6299787005 * rgb.z; + + f64 l_ = cbrt(l); + f64 m_ = cbrt(m); + f64 s_ = cbrt(s); + + return (vec3_f32) { + .x = (f32) (0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_), + .y = (f32) (1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_), + .z = (f32) (0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_), + }; +} + +vec3_f32 rgb_from_lab(vec3_f32 lab) { + f64 l_ = lab.x + 0.3963377774 * lab.y + 0.2158037573 * lab.z; + f64 m_ = lab.x - 0.1055613458 * lab.y - 0.0638541728 * lab.z; + f64 s_ = lab.x - 0.0894841775 * lab.y - 1.2914855480 * lab.z; + + f64 l = l_ * l_ * l_; + f64 m = m_ * m_ * m_; + f64 s = s_ * s_ * s_; + + return (vec3_f32) { + .x = (f32) (+4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s), + .y = (f32) (-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s), + .z = (f32) (-0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s), + }; +} + +vec3_f32 lch_from_lab(vec3_f32 lab) { + f64 a = lab.y; + f64 b = lab.z; + + return (vec3_f32) { + .x = lab.x, + .y = (f32) sqrt (a * a + b * b), + .z = (f32) atan2(b, a), + }; +} + +vec3_f32 lab_from_lch(vec3_f32 lch) { + return (vec3_f32) { + .x = lch.x, + .y = (f32) (lch.y * cos(lch.z)), + .z = (f32) (lch.y * sin(lch.z)), + }; +} + +vec3_f32 rgb_from_lch(vec3_f32 lch) { + return rgb_from_lab(lab_from_lch(lch)); +} + +vec3_f32 lch_from_rgb(vec3_f32 rgb) { + return lch_from_lab(lab_from_rgb(rgb)); +} + +vec3_f32 rgb_gamma_lerp (vec3_f32 a, vec3_f32 b, f32 t) { + return rgb_gamma_add(vec3_f32_lerp( + rgb_gamma_remove(a), + rgb_gamma_remove(b), + t + )); +} + +vec4_f32 rgba_gamma_lerp(vec4_f32 a, vec4_f32 b, f32 t) { + return rgba_gamma_add(vec4_f32_lerp( + rgba_gamma_remove(a), + rgba_gamma_remove(b), + t + )); +} + +vec3_f32 rgb_mix(vec3_f32 a, vec3_f32 b, f32 t) { + vec3_f32 a_lch = lch_from_rgb(a); + vec3_f32 b_lch = lch_from_rgb(b); + + return rgb_from_lch((vec3_f32) { + a_lch.x + (b_lch.x - a_lch.x) * t, + a_lch.y + (b_lch.y - a_lch.y) * t, + lch_from_rgb(rgb_gamma_lerp(a, b, t)).z, + }); +} + +vec4_f32 rgba_mix(vec4_f32 a, vec4_f32 b, f32 t) { + vec3_f32 a_lch = lch_from_rgb(vec3_from_vec4_f32(a)); + vec3_f32 b_lch = lch_from_rgb(vec3_from_vec4_f32(b)); + vec4_f32 ab = rgba_gamma_lerp(a, b, t); + + return vec4_from_vec3_f32(rgb_from_lch((vec3_f32) { + a_lch.x + (b_lch.x - a_lch.x) * t, + a_lch.y + (b_lch.y - a_lch.y) * t, + lch_from_rgb(vec3_from_vec4_f32(ab)).z, + }), ab.w); +} + +vec3_f32 lch_mix(vec3_f32 a, vec3_f32 b, f32 t) { + return (vec3_f32) { + a.x + (b.x - a.x) * t, + a.y + (b.y - a.y) * t, + lch_from_rgb(rgb_gamma_lerp(rgb_from_lch(a), rgb_from_lch(b), t)).z, + }; +} + +vec3_f32 lch_lerp(vec3_f32 a, vec3_f32 b, f32 t) { + f32 delta_hue = b.z - a.z; + if (delta_hue > M_PI) delta_hue -= M_PI * 2; + if (delta_hue < -M_PI) delta_hue += M_PI * 2; + + return (vec3_f32) { + .x = a.x + (b.x - a.x) * t, + .y = a.y + (b.y - a.y) * t, + .z = a.z + delta_hue * t, + }; +} + +u32 rgb_u32_from_f32(vec3_f32 color) { + i32 ir = (i32) floor(color.x * 255. + .5); + i32 ig = (i32) floor(color.y * 255. + .5); + i32 ib = (i32) floor(color.z * 255. + .5); + + u32 r = ir < 0 ? 0u : ir > 255 ? 255u : (u32) ir; + u32 g = ig < 0 ? 0u : ig > 255 ? 255u : (u32) ig; + u32 b = ib < 0 ? 0u : ib > 255 ? 255u : (u32) ib; + + return (r << 16) | (g << 8) | b; +} + +vec3_f32 rgb_f32_from_u32(u32 color) { + return (vec3_f32) { + .x = ((color & 0xff0000) >> 16) / 255.f, + .y = ((color & 0x00ff00) >> 8) / 255.f, + .z = (color & 0x0000ff) / 255.f, + }; +} + +u32 rgba_u32_from_f32(vec4_f32 color) { + i32 ir = (i32) floor(color.x * 255. + .5); + i32 ig = (i32) floor(color.y * 255. + .5); + i32 ib = (i32) floor(color.z * 255. + .5); + i32 ia = (i32) floor(color.w * 255. + .5); + + u32 r = ir < 0 ? 0u : ir > 255 ? 255u : (u32) ir; + u32 g = ig < 0 ? 0u : ig > 255 ? 255u : (u32) ig; + u32 b = ib < 0 ? 0u : ib > 255 ? 255u : (u32) ib; + u32 a = ia < 0 ? 0u : ia > 255 ? 255u : (u32) ia; + + return (a << 24) | (r << 16) | (g << 8) | b; +} + +vec4_f32 rgba_f32_from_u32(u32 color) { + return (vec4_f32) { + .x = ((color & 0x00ff0000) >> 16) / 255.f, + .y = ((color & 0x0000ff00) >> 8) / 255.f, + .z = (color & 0x000000ff) / 255.f, + .w = ((color & 0xff000000) >> 24) / 255.f, + }; +} + +// ================================================================ +// +// Basic shapes rendering +// +// ================================================================ + +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; +} + +static b8 same_sign_(f64 a, f64 b) { + if (a >= EPSILON && b <= -EPSILON) return 0; + if (a <= -EPSILON && b >= EPSILON) return 0; + return 1; +} + +b8 hit_triangle(vec2 vertices[3], 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 px = point.x; + f64 py = point.y; + + if ( (px < x0 && px < x1 && px < x2) + || (px > x0 && px > x1 && px > x2) + || (py < y0 && py < y1 && py < y2) + || (py > y0 && py > y1 && py > y2) ) + return 0; + + f64 x10 = x1 - x0; + f64 x21 = x2 - x1; + f64 x02 = x0 - x2; + + f64 y10 = y1 - y0; + f64 y21 = y2 - y1; + f64 y02 = y0 - y2; + + // Z-components of cross-products + + f64 z0 = x02 * y10 - x10 * y02; + f64 z1 = x10 * y21 - x21 * y10; + f64 z2 = x21 * y02 - x02 * y21; + + f64 pz0 = x02 * (py - y0) - (px - x0) * y02; + f64 pz1 = x10 * (py - y1) - (px - x1) * y10; + f64 pz2 = x21 * (py - y2) - (px - x2) * y21; + + return same_sign_(z0, pz0) + && same_sign_(z1, pz1) + && same_sign_(z2, pz2); +} + +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(Box area, vec2 point) { + f64 dw = area.width / 2; + f64 dh = area.height / 2; + + if (dw < EPSILON || dh < EPSILON) + return 0; + + f64 cx = area.x + dw; + f64 cy = area.y + dh; + f64 kx = 1. / dw; + f64 ky = 1. / dh; + + f64 dx = (point.x - cx) * kx; + f64 dy = (point.y - cy) * ky; + + return dx * dx + dy * dy - 1.0 < EPSILON; +} + +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; + + // Tangent + // + f64 tx = -dy; + f64 ty = dx; + f64 tl = sqrt(tx * tx + ty * ty); + if (tl >= EPSILON) { + tx /= tl; + ty /= tl; + } + tx *= width * .5; + ty *= width * .5; + + return hit_quad((vec2[4]) { + { x0 - tx, y0 - ty }, + { x0 + tx, y0 + ty }, + { x1 + tx, y1 + ty }, + { x1 - tx, y1 - ty }, + }, point); +} + static void put_pixel_(vec4_f32 *dst, vec4_f32 color) { if (color.w == 1.f) *dst = color; @@ -561,7 +916,7 @@ void fill_line_to_buffer(Pixel_Buffer dst, vec4_f32 color, vec2 vertices[2], f64 // ================================================================ // -// LCD text rendering +// LCD text rendering // // ================================================================ @@ -1016,628 +1371,9 @@ void draw_text_cursor_to_buffer(Pixel_Buffer dst, i32 font, vec4_f32 color, Box } // ================================================================ - -vec3_f32 vec3_from_vec4_f32(vec4_f32 v) { - return (vec3_f32) { - .x = v.x, - .y = v.y, - .z = v.z, - }; -} - -vec4_f32 vec4_from_vec3_f32(vec3_f32 v, f32 w) { - return (vec4_f32) { - .x = v.x, - .y = v.y, - .z = v.z, - .w = w, - }; -} - -vec3_f32 vec3_f32_lerp(vec3_f32 a, vec3_f32 b, f32 t) { - return (vec3_f32) { - .x = a.x + (b.x - a.x) * t, - .y = a.y + (b.y - a.y) * t, - .z = a.z + (b.z - a.z) * t, - }; -} - -vec4_f32 vec4_f32_lerp(vec4_f32 a, vec4_f32 b, f32 t) { - return (vec4_f32) { - .x = a.x + (b.x - a.x) * t, - .y = a.y + (b.y - a.y) * t, - .z = a.z + (b.z - a.z) * t, - .w = a.w + (b.w - a.w) * t, - }; -} - -// ================================================================ - -vec3_f32 rgb_gamma_add(vec3_f32 rgb) { - return (vec3_f32) { - .x = gamma_(rgb.x), - .y = gamma_(rgb.y), - .z = gamma_(rgb.z), - }; -} - -vec3_f32 rgb_gamma_remove(vec3_f32 rgb) { - return (vec3_f32) { - .x = gamma_re_(rgb.x), - .y = gamma_re_(rgb.y), - .z = gamma_re_(rgb.z), - }; -} - -vec4_f32 rgba_gamma_add(vec4_f32 rgba) { - return (vec4_f32) { - .x = gamma_(rgba.x), - .y = gamma_(rgba.y), - .z = gamma_(rgba.z), - .w = gamma_(rgba.w), - }; -} - -vec4_f32 rgba_gamma_remove(vec4_f32 rgba) { - return (vec4_f32) { - .x = gamma_re_(rgba.x), - .y = gamma_re_(rgba.y), - .z = gamma_re_(rgba.z), - .w = gamma_re_(rgba.w), - }; -} - -vec3_f32 lab_from_rgb(vec3_f32 rgb) { - f64 l = 0.4122214708 * rgb.x + 0.5363325363 * rgb.y + 0.0514459929 * rgb.z; - f64 m = 0.2119034982 * rgb.x + 0.6806995451 * rgb.y + 0.1073969566 * rgb.z; - f64 s = 0.0883024619 * rgb.x + 0.2817188376 * rgb.y + 0.6299787005 * rgb.z; - - f64 l_ = cbrt(l); - f64 m_ = cbrt(m); - f64 s_ = cbrt(s); - - return (vec3_f32) { - .x = (f32) (0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_), - .y = (f32) (1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_), - .z = (f32) (0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_), - }; -} - -vec3_f32 rgb_from_lab(vec3_f32 lab) { - f64 l_ = lab.x + 0.3963377774 * lab.y + 0.2158037573 * lab.z; - f64 m_ = lab.x - 0.1055613458 * lab.y - 0.0638541728 * lab.z; - f64 s_ = lab.x - 0.0894841775 * lab.y - 1.2914855480 * lab.z; - - f64 l = l_ * l_ * l_; - f64 m = m_ * m_ * m_; - f64 s = s_ * s_ * s_; - - return (vec3_f32) { - .x = (f32) (+4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s), - .y = (f32) (-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s), - .z = (f32) (-0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s), - }; -} - -vec3_f32 lch_from_lab(vec3_f32 lab) { - f64 a = lab.y; - f64 b = lab.z; - - return (vec3_f32) { - .x = lab.x, - .y = (f32) sqrt (a * a + b * b), - .z = (f32) atan2(b, a), - }; -} - -vec3_f32 lab_from_lch(vec3_f32 lch) { - return (vec3_f32) { - .x = lch.x, - .y = (f32) (lch.y * cos(lch.z)), - .z = (f32) (lch.y * sin(lch.z)), - }; -} - -vec3_f32 rgb_from_lch(vec3_f32 lch) { - return rgb_from_lab(lab_from_lch(lch)); -} - -vec3_f32 lch_from_rgb(vec3_f32 rgb) { - return lch_from_lab(lab_from_rgb(rgb)); -} - -vec3_f32 rgb_gamma_lerp (vec3_f32 a, vec3_f32 b, f32 t) { - return rgb_gamma_add(vec3_f32_lerp( - rgb_gamma_remove(a), - rgb_gamma_remove(b), - t - )); -} - -vec4_f32 rgba_gamma_lerp(vec4_f32 a, vec4_f32 b, f32 t) { - return rgba_gamma_add(vec4_f32_lerp( - rgba_gamma_remove(a), - rgba_gamma_remove(b), - t - )); -} - -vec3_f32 rgb_mix(vec3_f32 a, vec3_f32 b, f32 t) { - vec3_f32 a_lch = lch_from_rgb(a); - vec3_f32 b_lch = lch_from_rgb(b); - - return rgb_from_lch((vec3_f32) { - a_lch.x + (b_lch.x - a_lch.x) * t, - a_lch.y + (b_lch.y - a_lch.y) * t, - lch_from_rgb(rgb_gamma_lerp(a, b, t)).z, - }); -} - -vec4_f32 rgba_mix(vec4_f32 a, vec4_f32 b, f32 t) { - vec3_f32 a_lch = lch_from_rgb(vec3_from_vec4_f32(a)); - vec3_f32 b_lch = lch_from_rgb(vec3_from_vec4_f32(b)); - vec4_f32 ab = rgba_gamma_lerp(a, b, t); - - return vec4_from_vec3_f32(rgb_from_lch((vec3_f32) { - a_lch.x + (b_lch.x - a_lch.x) * t, - a_lch.y + (b_lch.y - a_lch.y) * t, - lch_from_rgb(vec3_from_vec4_f32(ab)).z, - }), ab.w); -} - -vec3_f32 lch_mix(vec3_f32 a, vec3_f32 b, f32 t) { - return (vec3_f32) { - a.x + (b.x - a.x) * t, - a.y + (b.y - a.y) * t, - lch_from_rgb(rgb_gamma_lerp(rgb_from_lch(a), rgb_from_lch(b), t)).z, - }; -} - -vec3_f32 lch_lerp(vec3_f32 a, vec3_f32 b, f32 t) { - f32 delta_hue = b.z - a.z; - if (delta_hue > M_PI) delta_hue -= M_PI * 2; - if (delta_hue < -M_PI) delta_hue += M_PI * 2; - - return (vec3_f32) { - .x = a.x + (b.x - a.x) * t, - .y = a.y + (b.y - a.y) * t, - .z = a.z + delta_hue * t, - }; -} - -u32 rgb_u32_from_f32(vec3_f32 color) { - i32 ir = (i32) floor(color.x * 255. + .5); - i32 ig = (i32) floor(color.y * 255. + .5); - i32 ib = (i32) floor(color.z * 255. + .5); - - u32 r = ir < 0 ? 0u : ir > 255 ? 255u : (u32) ir; - u32 g = ig < 0 ? 0u : ig > 255 ? 255u : (u32) ig; - u32 b = ib < 0 ? 0u : ib > 255 ? 255u : (u32) ib; - - return (r << 16) | (g << 8) | b; -} - -vec3_f32 rgb_f32_from_u32(u32 color) { - return (vec3_f32) { - .x = ((color & 0xff0000) >> 16) / 255.f, - .y = ((color & 0x00ff00) >> 8) / 255.f, - .z = (color & 0x0000ff) / 255.f, - }; -} - -u32 rgba_u32_from_f32(vec4_f32 color) { - i32 ir = (i32) floor(color.x * 255. + .5); - i32 ig = (i32) floor(color.y * 255. + .5); - i32 ib = (i32) floor(color.z * 255. + .5); - i32 ia = (i32) floor(color.w * 255. + .5); - - u32 r = ir < 0 ? 0u : ir > 255 ? 255u : (u32) ir; - u32 g = ig < 0 ? 0u : ig > 255 ? 255u : (u32) ig; - u32 b = ib < 0 ? 0u : ib > 255 ? 255u : (u32) ib; - u32 a = ia < 0 ? 0u : ia > 255 ? 255u : (u32) ia; - - return (a << 24) | (r << 16) | (g << 8) | b; -} - -vec4_f32 rgba_f32_from_u32(u32 color) { - return (vec4_f32) { - .x = ((color & 0x00ff0000) >> 16) / 255.f, - .y = ((color & 0x0000ff00) >> 8) / 255.f, - .z = (color & 0x000000ff) / 255.f, - .w = ((color & 0xff000000) >> 24) / 255.f, - }; -} - -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; -} - -static b8 same_sign_(f64 a, f64 b) { - if (a >= EPSILON && b <= -EPSILON) return 0; - if (a <= -EPSILON && b >= EPSILON) return 0; - return 1; -} - -b8 hit_triangle(vec2 vertices[3], 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 px = point.x; - f64 py = point.y; - - if ( (px < x0 && px < x1 && px < x2) - || (px > x0 && px > x1 && px > x2) - || (py < y0 && py < y1 && py < y2) - || (py > y0 && py > y1 && py > y2) ) - return 0; - - f64 x10 = x1 - x0; - f64 x21 = x2 - x1; - f64 x02 = x0 - x2; - - f64 y10 = y1 - y0; - f64 y21 = y2 - y1; - f64 y02 = y0 - y2; - - // Z-components of cross-products - - f64 z0 = x02 * y10 - x10 * y02; - f64 z1 = x10 * y21 - x21 * y10; - f64 z2 = x21 * y02 - x02 * y21; - - f64 pz0 = x02 * (py - y0) - (px - x0) * y02; - f64 pz1 = x10 * (py - y1) - (px - x1) * y10; - f64 pz2 = x21 * (py - y2) - (px - x2) * y21; - - return same_sign_(z0, pz0) - && same_sign_(z1, pz1) - && same_sign_(z2, pz2); -} - -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(Box area, vec2 point) { - f64 dw = area.width / 2; - f64 dh = area.height / 2; - - if (dw < EPSILON || dh < EPSILON) - return 0; - - f64 cx = area.x + dw; - f64 cy = area.y + dh; - f64 kx = 1. / dw; - f64 ky = 1. / dh; - - f64 dx = (point.x - cx) * kx; - f64 dy = (point.y - cy) * ky; - - return dx * dx + dy * dy - 1.0 < EPSILON; -} - -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; - - // Tangent - // - f64 tx = -dy; - f64 ty = dx; - f64 tl = sqrt(tx * tx + ty * ty); - if (tl >= EPSILON) { - tx /= tl; - ty /= tl; - } - tx *= width * .5; - ty *= width * .5; - - 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_cached(Box area, Pixel_Buffer src) { - perform_graphics_request( - (Graphics_Context) {0}, - (Graphics_Request) { - .op = GRAPHICS_DRAW_PIXELS, - .pixels = { - .area = area, - .src = src, - }, - } - ); -} - -void fill_rectangle_cached(vec4_f32 color, Box area) { - perform_graphics_request( - (Graphics_Context) {0}, - (Graphics_Request) { - .op = GRAPHICS_FILL_RECTANGLE, - .rectangle = { - .color = color, - .area = area, - }, - } - ); -} - -void fill_triangle_cached(vec4_f32 color, vec2 vertices[3]) { - perform_graphics_request( - (Graphics_Context) {0}, - (Graphics_Request) { - .op = GRAPHICS_FILL_TRIANGLE, - .triangle = { - .color = color, - .vertices = { - vertices[0], - vertices[1], - vertices[2], - }, - }, - } - ); -} - -void fill_triangles_cached(vec4_f32 color, vec2 position, vec2 scale, i64 num_triangles, vec2 *vertices) { - perform_graphics_request( - (Graphics_Context) {0}, - (Graphics_Request) { - .op = GRAPHICS_FILL_TRIANGLES, - .triangles = { - .color = color, - .position = position, - .scale = scale, - .num_triangles = num_triangles, - .vertices = vertices, - }, - } - ); -} - -void fill_quad_cached(vec4_f32 color, vec2 vertices[4]) { - perform_graphics_request( - (Graphics_Context) {0}, - (Graphics_Request) { - .op = GRAPHICS_FILL_QUAD, - .quad = { - .color = color, - .vertices = { - vertices[0], - vertices[1], - vertices[2], - vertices[3], - }, - }, - } - ); -} - -void fill_ellipse_cached(vec4_f32 color, Box area) { - perform_graphics_request( - (Graphics_Context) {0}, - (Graphics_Request) { - .op = GRAPHICS_FILL_ELLIPSE, - .ellipse = { - .color = color, - .area = area, - }, - } - ); -} - -void fill_line_cached(vec4_f32 color, vec2 vertices[2], f64 width) { - perform_graphics_request( - (Graphics_Context) {0}, - (Graphics_Request) { - .op = GRAPHICS_FILL_LINE, - .line = { - .color = color, - .vertices = { vertices[0], vertices[1], }, - .width = width, - }, - } - ); -} - -void draw_text_area_cached(i32 font, vec4_f32 color, Box area, vec2 max_size, i64 num_chars, c32 *text) { - perform_graphics_request( - (Graphics_Context) {0}, - (Graphics_Request) { - .op = GRAPHICS_DRAW_TEXT_AREA, - .text_area = { - .font = font, - .color = color, - .area = area, - .max_size = max_size, - .num_chars = num_chars, - .text = text, - }, - } - ); -} - -void draw_text_cursor_cached(i32 font, 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_DRAW_TEXT_CURSOR, - .text_cursor = { - .font = font, - .color = color, - .area = area, - .max_size = max_size, - .num_chars = num_chars, - .text = text, - .cursor = cursor, - .selection = selection, - }, - } - ); -} - -void draw_pixels(Box area, Pixel_Buffer src) { - perform_graphics_request( - (Graphics_Context) { .disable_cache = 1, }, - (Graphics_Request) { - .op = GRAPHICS_DRAW_PIXELS, - .pixels = { - .area = area, - .src = src, - }, - } - ); -} - -void fill_rectangle(vec4_f32 color, Box area) { - perform_graphics_request( - (Graphics_Context) { .disable_cache = 1, }, - (Graphics_Request) { - .op = GRAPHICS_FILL_RECTANGLE, - .rectangle = { - .color = color, - .area = area, - }, - } - ); -} - -void fill_triangle(vec4_f32 color, vec2 vertices[3]) { - perform_graphics_request( - (Graphics_Context) { .disable_cache = 1, }, - (Graphics_Request) { - .op = GRAPHICS_FILL_TRIANGLE, - .triangle = { - .color = color, - .vertices = { - vertices[0], - vertices[1], - vertices[2], - }, - }, - } - ); -} - -void fill_triangles(vec4_f32 color, vec2 position, vec2 scale, i64 num_triangles, vec2 *vertices) { - perform_graphics_request( - (Graphics_Context) { .disable_cache = 1, }, - (Graphics_Request) { - .op = GRAPHICS_FILL_TRIANGLES, - .triangles = { - .color = color, - .position = position, - .scale = scale, - .num_triangles = num_triangles, - .vertices = vertices, - }, - } - ); -} - -void fill_quad(vec4_f32 color, vec2 vertices[4]) { - perform_graphics_request( - (Graphics_Context) { .disable_cache = 1, }, - (Graphics_Request) { - .op = GRAPHICS_FILL_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) { .disable_cache = 1, }, - (Graphics_Request) { - .op = GRAPHICS_FILL_ELLIPSE, - .ellipse = { - .color = color, - .area = area, - }, - } - ); -} - -void fill_line(vec4_f32 color, vec2 vertices[2], f64 width) { - perform_graphics_request( - (Graphics_Context) { .disable_cache = 1, }, - (Graphics_Request) { - .op = GRAPHICS_FILL_LINE, - .line = { - .color = color, - .vertices = { vertices[0], vertices[1], }, - .width = width, - }, - } - ); -} - -void draw_text_area(i32 font, vec4_f32 color, Box area, vec2 max_size, i64 num_chars, c32 *text) { - perform_graphics_request( - (Graphics_Context) { .disable_cache = 1, }, - (Graphics_Request) { - .op = GRAPHICS_DRAW_TEXT_AREA, - .text_area = { - .font = font, - .color = color, - .area = area, - .max_size = max_size, - .num_chars = num_chars, - .text = text, - }, - } - ); -} - -void draw_text_cursor(i32 font, vec4_f32 color, Box area, vec2 max_size, i64 num_chars, c32 *text, i64 cursor, i64 selection) { - perform_graphics_request( - (Graphics_Context) { .disable_cache = 1, }, - (Graphics_Request) { - .op = GRAPHICS_DRAW_TEXT_CURSOR, - .text_cursor = { - .font = font, - .color = color, - .area = area, - .max_size = max_size, - .num_chars = num_chars, - .text = text, - .cursor = cursor, - .selection = selection, - }, - } - ); -} - +// +// Requests cache +// // ================================================================ typedef struct { @@ -2185,6 +1921,286 @@ static Graphics_Context graphics_context_defaults_(Graphics_Context context) { return context; } +void draw_pixels_cached(Box area, Pixel_Buffer src) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_DRAW_PIXELS, + .pixels = { + .area = area, + .src = src, + }, + } + ); +} + +void fill_rectangle_cached(vec4_f32 color, Box area) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_FILL_RECTANGLE, + .rectangle = { + .color = color, + .area = area, + }, + } + ); +} + +void fill_triangle_cached(vec4_f32 color, vec2 vertices[3]) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_FILL_TRIANGLE, + .triangle = { + .color = color, + .vertices = { + vertices[0], + vertices[1], + vertices[2], + }, + }, + } + ); +} + +void fill_triangles_cached(vec4_f32 color, vec2 position, vec2 scale, i64 num_triangles, vec2 *vertices) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_FILL_TRIANGLES, + .triangles = { + .color = color, + .position = position, + .scale = scale, + .num_triangles = num_triangles, + .vertices = vertices, + }, + } + ); +} + +void fill_quad_cached(vec4_f32 color, vec2 vertices[4]) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_FILL_QUAD, + .quad = { + .color = color, + .vertices = { + vertices[0], + vertices[1], + vertices[2], + vertices[3], + }, + }, + } + ); +} + +void fill_ellipse_cached(vec4_f32 color, Box area) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_FILL_ELLIPSE, + .ellipse = { + .color = color, + .area = area, + }, + } + ); +} + +void fill_line_cached(vec4_f32 color, vec2 vertices[2], f64 width) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_FILL_LINE, + .line = { + .color = color, + .vertices = { vertices[0], vertices[1], }, + .width = width, + }, + } + ); +} + +void draw_text_area_cached(i32 font, vec4_f32 color, Box area, vec2 max_size, i64 num_chars, c32 *text) { + perform_graphics_request( + (Graphics_Context) {0}, + (Graphics_Request) { + .op = GRAPHICS_DRAW_TEXT_AREA, + .text_area = { + .font = font, + .color = color, + .area = area, + .max_size = max_size, + .num_chars = num_chars, + .text = text, + }, + } + ); +} + +void draw_text_cursor_cached(i32 font, 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_DRAW_TEXT_CURSOR, + .text_cursor = { + .font = font, + .color = color, + .area = area, + .max_size = max_size, + .num_chars = num_chars, + .text = text, + .cursor = cursor, + .selection = selection, + }, + } + ); +} + +void draw_pixels(Box area, Pixel_Buffer src) { + perform_graphics_request( + (Graphics_Context) { .disable_cache = 1, }, + (Graphics_Request) { + .op = GRAPHICS_DRAW_PIXELS, + .pixels = { + .area = area, + .src = src, + }, + } + ); +} + +void fill_rectangle(vec4_f32 color, Box area) { + perform_graphics_request( + (Graphics_Context) { .disable_cache = 1, }, + (Graphics_Request) { + .op = GRAPHICS_FILL_RECTANGLE, + .rectangle = { + .color = color, + .area = area, + }, + } + ); +} + +void fill_triangle(vec4_f32 color, vec2 vertices[3]) { + perform_graphics_request( + (Graphics_Context) { .disable_cache = 1, }, + (Graphics_Request) { + .op = GRAPHICS_FILL_TRIANGLE, + .triangle = { + .color = color, + .vertices = { + vertices[0], + vertices[1], + vertices[2], + }, + }, + } + ); +} + +void fill_triangles(vec4_f32 color, vec2 position, vec2 scale, i64 num_triangles, vec2 *vertices) { + perform_graphics_request( + (Graphics_Context) { .disable_cache = 1, }, + (Graphics_Request) { + .op = GRAPHICS_FILL_TRIANGLES, + .triangles = { + .color = color, + .position = position, + .scale = scale, + .num_triangles = num_triangles, + .vertices = vertices, + }, + } + ); +} + +void fill_quad(vec4_f32 color, vec2 vertices[4]) { + perform_graphics_request( + (Graphics_Context) { .disable_cache = 1, }, + (Graphics_Request) { + .op = GRAPHICS_FILL_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) { .disable_cache = 1, }, + (Graphics_Request) { + .op = GRAPHICS_FILL_ELLIPSE, + .ellipse = { + .color = color, + .area = area, + }, + } + ); +} + +void fill_line(vec4_f32 color, vec2 vertices[2], f64 width) { + perform_graphics_request( + (Graphics_Context) { .disable_cache = 1, }, + (Graphics_Request) { + .op = GRAPHICS_FILL_LINE, + .line = { + .color = color, + .vertices = { vertices[0], vertices[1], }, + .width = width, + }, + } + ); +} + +void draw_text_area(i32 font, vec4_f32 color, Box area, vec2 max_size, i64 num_chars, c32 *text) { + perform_graphics_request( + (Graphics_Context) { .disable_cache = 1, }, + (Graphics_Request) { + .op = GRAPHICS_DRAW_TEXT_AREA, + .text_area = { + .font = font, + .color = color, + .area = area, + .max_size = max_size, + .num_chars = num_chars, + .text = text, + }, + } + ); +} + +void draw_text_cursor(i32 font, vec4_f32 color, Box area, vec2 max_size, i64 num_chars, c32 *text, i64 cursor, i64 selection) { + perform_graphics_request( + (Graphics_Context) { .disable_cache = 1, }, + (Graphics_Request) { + .op = GRAPHICS_DRAW_TEXT_CURSOR, + .text_cursor = { + .font = font, + .color = color, + .area = area, + .max_size = max_size, + .num_chars = num_chars, + .text = text, + .cursor = cursor, + .selection = selection, + }, + } + ); +} + // ================================================================ void perform_graphics_request(Graphics_Context context, Graphics_Request req) { |