From c0c52a07376d22339a06d031892af649c2eb8acc Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Wed, 22 Jan 2025 17:27:34 +0100 Subject: Clipboard image and sound proc decls --- graphics.c | 111 ++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 73 insertions(+), 38 deletions(-) (limited to 'graphics.c') diff --git a/graphics.c b/graphics.c index 3b9f071..eb0db72 100755 --- a/graphics.c +++ b/graphics.c @@ -71,6 +71,7 @@ vec4_f32 vec4_f32_lerp (vec4_f32 a, vec4_f32 b, f32 t); // ================================================================ typedef struct { + // NOTE: Dimensions are in pixels. i64 width; i64 height; i64 stride; @@ -79,6 +80,8 @@ typedef struct { typedef struct { Pixel_Buffer buffer; + i64 sketch_size; + vec4_f32 *sketch; vec2 position; vec2 scale; b8 quick : 1; // If set, anti-aliasing is skipped. @@ -94,10 +97,9 @@ 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. +// 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); @@ -128,7 +130,6 @@ b8 ellipse_contains (f64 x0, f64 y0, f64 width, f64 height, b8 line_contains (f64 x0, f64 y0, f64 x1, f64 y1, f64 width, f64 px, f64 py); Pixel_Buffer frame_pixels (void); -Pixel_Buffer sketch_pixels(i64 width, i64 height); Pixel_Buffer subimage (Pixel_Buffer image, i64 x, i64 y, i64 width, i64 height); void put_pixel (Brush brush, i64 x, i64 y); @@ -279,20 +280,52 @@ void transform_box_(Brush brush, f64 x, f64 y, f64 width, f64 height, f64 *x0, f } } +Pixel_Buffer sketch_pixels_(Brush brush, i64 width, i64 height) { + vec4_f32 *buffer_end = brush.buffer.pixels + brush.buffer.stride * (brush.buffer.height - 1) + brush.buffer.width; + vec4_f32 *sketch_end = brush.sketch + brush.sketch_size; + + b8 is_inside_sketch_area = buffer_end > brush.sketch && brush.buffer.pixels < sketch_end; + + b8 offset = is_inside_sketch_area + ? buffer_end - brush.sketch + : 0; + + if (brush.sketch_size - offset < width * height) + return (Pixel_Buffer) { + .width = 0, + .height = 0, + .stride = 0, + .pixels = brush.sketch, + }; + + return (Pixel_Buffer) { + .width = width, + .height = height, + .stride = width, + .pixels = brush.sketch + offset, + }; +} + Brush antialiasing_brush_(Brush brush) { return (Brush) { - .buffer = sketch_pixels(brush.buffer.width * ANTIALIASING_SCALE, brush.buffer.height * ANTIALIASING_SCALE), - .position = brush.position, - .scale = { + .buffer = sketch_pixels_( + brush, + brush.buffer.width * ANTIALIASING_SCALE, + brush.buffer.height * ANTIALIASING_SCALE + ), + .sketch_size = brush.sketch_size, + .sketch = brush.sketch, + .position = brush.position, + .scale = { .x = brush.scale.x * ANTIALIASING_SCALE, .y = brush.scale.y * ANTIALIASING_SCALE, }, - .quick = 1, - .alpha = 0, - .xor_color = 0, - .color = brush.alpha - ? brush.color - : vec4_from_vec3_f32(vec3_from_vec4_f32(brush.color), 1.f), + .quick = 1, + .alpha = 0, + .xor_color = 0, + .color = brush.alpha + ? brush.color + : vec4_from_vec3_f32(vec3_from_vec4_f32(brush.color), 1.f), }; } @@ -366,14 +399,31 @@ void draw_pixels_(Brush brush, f64 x, f64 y, f64 width, f64 height, Pixel_Buffer put_pixel_(brush, i, j); } } - else + else if (!brush.alpha && !brush.xor_color) { + i32 iw = (i32) floor(w + .5); + i32 ih = (i32) floor(h + .5); + i32 ix0 = (i32) floor(x0 + .5); + i32 iy0 = (i32) floor(y0 + .5); + for (i32 j = j0; j <= j1; ++j) { + i32 src_j = ((j - iy0) * src.height) / ih; + i32 dst_j = j * brush.buffer.stride; + if (src_j < 0 || src_j >= src.height) continue; + src_j *= src.stride; + for (i32 i = i0; i <= i1; ++i) { + i32 src_i = ((i - ix0) * src.width) / iw; + if (src_i < 0 || src_i >= src.width) continue; + brush.buffer.pixels[dst_j + i] = src.pixels[src_j + src_i]; + } + } + } else for (i64 j = j0; j <= j1; ++j) { i64 src_j = (i64) floor(((j - y0) * src.height) * h_inv + .5); if (src_j < 0 || src_j >= src.height) continue; + src_j *= src.stride; for (i64 i = i0; i <= i1; ++i) { i64 src_i = (i64) floor(((i - x0) * src.width) * w_inv + .5); if (src_i < 0 || src_i >= src.width) continue; - brush.color = src.pixels[src_j * src.stride + src_i]; + brush.color = src.pixels[src_j + src_i]; put_pixel_(brush, i, j); } } @@ -569,6 +619,8 @@ void fill_triangle_(Brush brush, f64 x0, f64 y0, f64 x1, f64 y1, f64 x2, f64 y2) i64 i1 = (i64) ceil (max3_(x0, x1, x2)); i64 j1 = (i64) ceil (max3_(y0, y1, y2)); + if (i0 < 0) i0 = 0; + if (i1 >= brush.buffer.width) i1 = brush.buffer.width - 1; if (j0 < 0) j0 = 0; if (j1 >= brush.buffer.height) j1 = brush.buffer.height - 1; @@ -588,9 +640,6 @@ void fill_triangle_(Brush brush, f64 x0, f64 y0, f64 x1, f64 y1, f64 x2, f64 y2) break; } - if (left < 0) left = 0; - if (right >= brush.buffer.width) right = brush.buffer.width - 1; - if (brush.xor_color) for (i64 i = left; i <= right; ++i) put_pixel_xor_(brush, i, j); @@ -893,6 +942,11 @@ static Brush brush_defaults_(Brush b) { if (b.buffer.stride == 0) b.buffer.stride = b.buffer.width; + if (b.sketch_size == 0 && b.sketch == NULL) { + b.sketch_size = MAX_NUM_PIXELS; + b.sketch = g_platform.sketch; + } + return b; } @@ -1211,25 +1265,6 @@ Pixel_Buffer frame_pixels(void) { }; } -Pixel_Buffer sketch_pixels(i64 width, i64 height) { - if (width <= 0 || height <= 0) { - width = g_platform.frame_width; - height = g_platform.frame_height; - } - - if (width * height > MAX_NUM_PIXELS) { - width = 0; - height = 0; - } - - return (Pixel_Buffer) { - .width = width, - .height = height, - .stride = width, - .pixels = g_platform.sketch, - }; -} - Pixel_Buffer subimage(Pixel_Buffer image, i64 x, i64 y, i64 width, i64 height) { if (x < 0 || y < 0 || width <= 0 || height <= 0 || x + width > image.width || y + height > image.height || image.pixels == NULL) return (Pixel_Buffer) { -- cgit v1.2.3