summaryrefslogtreecommitdiff
path: root/graphics.c
diff options
context:
space:
mode:
Diffstat (limited to 'graphics.c')
-rwxr-xr-xgraphics.c111
1 files changed, 73 insertions, 38 deletions
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) {