summaryrefslogtreecommitdiff
path: root/graphics.c
diff options
context:
space:
mode:
Diffstat (limited to 'graphics.c')
-rw-r--r--graphics.c195
1 files changed, 115 insertions, 80 deletions
diff --git a/graphics.c b/graphics.c
index 54519b5..dc2a88e 100644
--- a/graphics.c
+++ b/graphics.c
@@ -178,6 +178,15 @@ static void put_pixel_color_(Brush brush, i64 x, i64 y) {
brush.buffer.pixels[y * brush.buffer.line_size + x] = brush.color;
}
+static void put_pixel_(Brush brush, i64 x, i64 y) {
+ if (brush.xor_color)
+ put_pixel_xor_(brush, x, y);
+ else if (brush.alpha)
+ put_pixel_alpha_(brush, x, y);
+ else
+ put_pixel_color_(brush, x, y);
+}
+
void fill_rectangle_(Brush brush, f64 x, f64 y, f64 width, f64 height) {
f64 x0, y0, x1, y1;
@@ -203,21 +212,31 @@ void fill_rectangle_(Brush brush, f64 x, f64 y, f64 width, f64 height) {
i64 j0 = (i64) ceil (y0);
i64 j1 = (i64) floor(y1);
- f64 kx0 = i0 - x0;
- f64 kx1 = x1 - i1;
- f64 ky0 = j0 - y0;
- f64 ky1 = y1 - j1;
+ i64 i00 = i0;
+ i64 j00 = j0;
+ i64 i10 = i1;
+ i64 j10 = j1;
+
+ if (i0 < 0) i0 = 0;
+ if (i1 > brush.buffer.width) i1 = brush.buffer.width;
+ if (j0 < 0) j0 = 0;
+ if (j1 > brush.buffer.height) j1 = brush.buffer.height;
+
+ f64 kx0 = i00 - x0;
+ f64 kx1 = x1 - i10;
+ f64 ky0 = j00 - y0;
+ f64 ky1 = y1 - j10;
for (i64 j = j0; j < j1; ++j)
for (i64 i = i0; i < i1; ++i)
- put_pixel(brush, i, j);
+ put_pixel_(brush, i, j);
- if (i0 > i1) {
+ if (i00 > i10) {
kx0 *= kx1;
kx1 = 0.;
}
- if (j0 > j1) {
+ if (j00 > j10) {
ky0 *= ky1;
ky1 = 0.;
}
@@ -225,33 +244,53 @@ void fill_rectangle_(Brush brush, f64 x, f64 y, f64 width, f64 height) {
f64 alpha = brush.alpha ? brush.color.w : 1.;
brush.alpha = 1;
- brush.color.w = alpha * gamma_(kx0);
- for (i64 j = j0; j < j1; ++j)
- put_pixel(brush, i0 - 1, j);
+ if (i00 - 1 >= 0 && i00 - 1 < brush.buffer.width) {
+ brush.color.w = alpha * gamma_(kx0);
+ for (i64 j = j0; j < j1; ++j)
+ put_pixel_(brush, i00 - 1, j);
+ }
- brush.color.w = alpha * gamma_(kx1);
- for (i64 j = j0; j < j1; ++j)
- put_pixel(brush, i1, j);
+ if (i10 >= 0 && i10 < brush.buffer.width) {
+ brush.color.w = alpha * gamma_(kx1);
+ for (i64 j = j0; j < j1; ++j)
+ put_pixel_(brush, i10, j);
+ }
- brush.color.w = alpha * gamma_(ky0);
- for (i64 i = i0; i < i1; ++i)
- put_pixel(brush, i, j0 - 1);
+ if (j00 - 1 >= 0 && j00 - 1 < brush.buffer.height) {
+ brush.color.w = alpha * gamma_(ky0);
+ for (i64 i = i0; i < i1; ++i)
+ put_pixel_(brush, i, j00 - 1);
+ }
- brush.color.w = alpha * gamma_(ky1);
- for (i64 i = i0; i < i1; ++i)
- put_pixel(brush, i, j1);
+ if (j10 >= 0 && j10 < brush.buffer.height) {
+ brush.color.w = alpha * gamma_(ky1);
+ for (i64 i = i0; i < i1; ++i)
+ put_pixel_(brush, i, j10);
+ }
- brush.color.w = alpha * gamma_(kx0 * ky0);
- put_pixel(brush, i0 - 1, j0 - 1);
+ if ( i00 - 1 >= 0 && i00 - 1 < brush.buffer.width
+ && j00 - 1 >= 0 && j00 - 1 < brush.buffer.height) {
+ brush.color.w = alpha * gamma_(kx0 * ky0);
+ put_pixel_(brush, i00 - 1, j00 - 1);
+ }
- brush.color.w = alpha * gamma_(kx1 * ky0);
- put_pixel(brush, i1, j0 - 1);
+ if ( i10 >= 0 && i10 < brush.buffer.width
+ && j00 - 1 >= 0 && j00 - 1 < brush.buffer.height) {
+ brush.color.w = alpha * gamma_(kx1 * ky0);
+ put_pixel_(brush, i10, j00 - 1);
+ }
- brush.color.w = alpha * gamma_(kx0 * ky1);
- put_pixel(brush, i0 - 1, j1);
+ if ( i00 - 1 >= 0 && i00 - 1 < brush.buffer.width
+ && j10 >= 0 && j10 < brush.buffer.height) {
+ brush.color.w = alpha * gamma_(kx0 * ky1);
+ put_pixel_(brush, i00 - 1, j10);
+ }
- brush.color.w = alpha * gamma_(kx1 * ky1);
- put_pixel(brush, i1, j1);
+ if ( i10 >= 0 && i10 < brush.buffer.width
+ && j10 >= 0 && j10 < brush.buffer.height) {
+ brush.color.w = alpha * gamma_(kx1 * ky1);
+ put_pixel_(brush, i10, j10);
+ }
} else {
i64 i0 = (i64) floor(x0);
i64 i1 = (i64) ceil (x1);
@@ -265,7 +304,7 @@ void fill_rectangle_(Brush brush, f64 x, f64 y, f64 width, f64 height) {
for (i64 j = j0; j < j1; ++j)
for (i64 i = i0; i < i1; ++i)
- put_pixel(brush, i, j);
+ put_pixel_(brush, i, j);
}
}
@@ -295,7 +334,7 @@ void fill_triangle_(Brush brush, f64 x0, f64 y0, f64 x1, f64 y1, f64 x2, f64 y2)
for (i64 j = j0; j < j1; ++j)
for (i64 i = i0; i < i1; ++i)
if (triangle_contains(x0, y0, x1, y1, x2, y2, (f64) i, (f64) j))
- put_pixel(brush, i, j);
+ put_pixel_(brush, i, j);
}
static i64 char_column_offset_(c32 c, i64 column_index) {
@@ -448,31 +487,34 @@ static i64 enum_text_rows_(i64 num_chars, c32 *text) {
return rows;
}
-static void draw_text_(Brush brush, f64 x_, f64 y_, f64 scale_x, f64 scale_y, i64 num_chars, c32 *text) {
- x_ = brush.position.x + x_ * brush.scale.x;
- y_ = brush.position.y + y_ * brush.scale.y;
+static void draw_text_(Brush brush, f64 x0, f64 y0, f64 scale_x, f64 scale_y, i64 num_chars, c32 *text) {
+ x0 = brush.position.x + x0 * brush.scale.x;
+ y0 = brush.position.y + y0 * brush.scale.y;
if (brush.scale.x < 0) scale_x *= -brush.scale.x;
else scale_x *= brush.scale.x;
if (brush.scale.y < 0) scale_y *= -brush.scale.y;
else scale_y *= brush.scale.y;
- f64 x = x_;
- f64 y = y_;
-
f64 kx = scale_x;
f64 h = scale_y * CHAR_NUM_BITS_Y_;
+ if (h < EPSILON)
+ return;
+
+ f64 x = x0;
+ f64 y = y0;
+
for (i64 n = 0; n < num_chars; ++n) {
if (text[n] <= ' ') {
if (text[n] == '\n') {
- x = x_;
+ x = x0;
y += scale_y * (CHAR_NUM_BITS_Y_ + 1);
}
else if (text[n] == '\b' && n > 0)
x -= kx * (char_width_(text[n - 1]) + char_spacing_(num_chars, text, n - 1));
else if (text[n] == '\r')
- x = x_;
+ x = x0;
else
x += kx * (char_width_(' ') + char_spacing_(num_chars, text, n));
continue;
@@ -481,30 +523,27 @@ static void draw_text_(Brush brush, f64 x_, f64 y_, f64 scale_x, f64 scale_y, i6
i64 num_cols = char_width_(text[n]);
f64 w = num_cols * kx;
- i64 i0 = (i64) floor(x);
- i64 i1 = (i64) ceil (x + w);
- i64 j0 = (i64) floor(y);
- i64 j1 = (i64) ceil (y + h);
-
- i64 i00 = i0;
- i64 j00 = j0;
- i64 iz = i1 - i0;
- i64 jz = j1 - j0;
+ if (w >= EPSILON) {
+ i64 i0 = (i64) floor(x);
+ i64 i1 = (i64) ceil (x + w);
+ i64 j0 = (i64) floor(y);
+ i64 j1 = (i64) ceil (y + h);
- if (i0 < 0) i0 = 0;
- if (i1 > brush.buffer.width) i1 = brush.buffer.width;
- if (j0 < 0) j0 = 0;
- if (j1 > brush.buffer.height) j1 = brush.buffer.height;
+ 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;
- for (i64 i = i0; i < i1; ++i) {
- i64 column = ((i - i00) * num_cols) / iz;
- i64 offset = char_column_offset_(text[n], column);
+ for (i64 i = i0; i <= i1; ++i) {
+ i64 column = (i64) floor(((i - x) * num_cols) / w + .5);
+ i64 offset = char_column_offset_(text[n], column);
- for (i64 j = j0; j < j1; ++j) {
- i64 row = ((j - j00) * CHAR_NUM_BITS_Y_) / jz;
+ for (i64 j = j0; j <= j1; ++j) {
+ i64 row = (i64) floor(((j - y) * CHAR_NUM_BITS_Y_) / h + .5);
- if (char_bit_(offset, row))
- put_pixel(brush, i, j);
+ if (char_bit_(offset, row))
+ put_pixel_(brush, i, j);
+ }
}
}
@@ -855,12 +894,7 @@ void put_pixel(Brush brush, i64 x, i64 y) {
if (x < 0 || x >= brush.buffer.width || y < 0 || y >= brush.buffer.height)
return;
- if (brush.xor_color)
- put_pixel_xor_(brush, x, y);
- else if (brush.alpha)
- put_pixel_alpha_(brush, x, y);
- else
- put_pixel_color_(brush, x, y);
+ put_pixel_(brush, x, y);
}
void draw_pixels(Brush brush, f64 x, f64 y, f64 width, f64 height, Pixel_Buffer src) {
@@ -891,22 +925,25 @@ void draw_pixels(Brush brush, f64 x, f64 y, f64 width, f64 height, Pixel_Buffer
i64 j0 = (i64) floor(y0);
i64 j1 = (i64) ceil (y1);
- i64 i00 = i0;
- i64 j00 = j0;
- i64 iz = i1 - i0;
- i64 jz = j1 - j0;
+ f64 w = x1 - x0;
+ f64 h = y1 - y0;
- if (i0 < 0) i0 = 0;
- if (i1 > brush.buffer.width) i1 = brush.buffer.width;
- if (j0 < 0) j0 = 0;
- if (j1 > brush.buffer.height) j1 = brush.buffer.height;
+ if (w < EPSILON || h < EPSILON)
+ return;
- for (i64 j = j0; j < j1; ++j) {
- i64 src_j = ((j - j00) * src.height) / jz;
- for (i64 i = i0; i < i1; ++i) {
- i64 src_i = ((i - i00) * src.width) / iz;
+ 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;
+
+ for (i64 j = j0; j <= j1; ++j) {
+ i64 src_j = (i64) floor(((j - y0) * src.height) / h + .5);
+ if (src_j < 0 || src_j >= src.height) continue;
+ for (i64 i = i0; i <= i1; ++i) {
+ i64 src_i = (i64) floor(((i - x0) * src.width) / w + .5);
+ if (src_i < 0 || src_i >= src.width) continue;
brush.color = src.pixels[src_j * src.line_size + src_i];
- put_pixel(brush, i, j);
+ put_pixel_(brush, i, j);
}
}
}
@@ -962,7 +999,7 @@ void fill_ellipse(Brush brush, f64 x, f64 y, f64 width, f64 height) {
for (i64 j = j0; j < j1; ++j)
for (i64 i = i0; i < i1; ++i)
if (ellipse_contains(x0, y0, x1 - x0, y1 - y0, (f64) i, (f64) j))
- put_pixel(brush, i, j);
+ put_pixel_(brush, i, j);
}
void fill_line(Brush brush, f64 x0, f64 y0, f64 x1, f64 y1, f64 width) {
@@ -993,8 +1030,6 @@ void draw_text_area(Brush brush, f64 x, f64 y, f64 width, f64 height, f64 max_sc
if (text == NULL || num_chars <= 0 || max_scale_x < EPSILON || max_scale_y < EPSILON)
return;
- brush = brush_defaults_(brush);
-
i64 num_columns = enum_text_columns_(num_chars, text);
i64 num_rows = enum_text_rows_(num_chars, text);
@@ -1009,7 +1044,7 @@ void draw_text_area(Brush brush, f64 x, f64 y, f64 width, f64 height, f64 max_sc
kx = k * max_scale_x;
ky = k * max_scale_y;
- draw_text_(brush, x, y, kx, ky, num_chars, text);
+ draw_text_(brush_defaults_(brush), x, y, kx, ky, num_chars, text);
}
void draw_text_cursor(Brush brush, f64 x, f64 y, f64 width, f64 height, f64 max_scale_x, f64 max_scale_y, i64 cursor, i64 selection, i64 num_chars, c32 *text) {