diff options
Diffstat (limited to 'graphics.c')
-rw-r--r-- | graphics.c | 195 |
1 files changed, 115 insertions, 80 deletions
@@ -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) { |