summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2025-04-25 13:12:18 +0200
committerMitya Selivanov <automainint@guattari.tech>2025-04-25 13:12:18 +0200
commit8a4b4bed8259397c6d958766573a0bfa25909b98 (patch)
tree8059d85144efa563959885dac9fa142c1eeafde7
parent32f60821408fe51d0acf45e430556c12711e5cc5 (diff)
downloadreduced_system_layer-8a4b4bed8259397c6d958766573a0bfa25909b98.zip
Cleanup
-rw-r--r--graphics.c1262
1 files changed, 639 insertions, 623 deletions
diff --git a/graphics.c b/graphics.c
index 7a97aab..5632712 100644
--- a/graphics.c
+++ b/graphics.c
@@ -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) {