diff --git a/src/hulk/framebuffer.d b/src/hulk/framebuffer.d index 02efcee..c470e30 100644 --- a/src/hulk/framebuffer.d +++ b/src/hulk/framebuffer.d @@ -8,7 +8,7 @@ import hos.memory; /** * Represent a graphical frame buffer. * - * TODO: Handle other pixel formats. Currently only ARGB is supported. + * TODO: Handle other pixel formats. Currently only BGRx is supported. */ struct Framebuffer { @@ -53,4 +53,80 @@ struct Framebuffer { memset32(m_buffer, color, m_buffer_size); } + + /** + * Blit an 8-bit alpha bitmap to the framebuffer. + * + * @param x X coordinate of left side of target location. + * @param y Y coordinate of bottom side of target location. + * @param alpha_bitmap 8-bit alpha-channel bitmap. + * @param width Bitmap width. + * @param height Bitmap height. + * @param color Color to blend with alpha value. + */ + void blit_alpha_bitmap(size_t x, size_t y, const(ubyte) * alpha_bitmap, + size_t width, size_t height, uint color) + { + y += height - 1u; + size_t bitmap_index; + for (size_t iy = 0u; iy < height; iy++) + { + for (size_t ix = 0u; ix < width; ix++) + { + size_t buffer_index = buffer_index(x + ix, y); + ubyte alpha = alpha_bitmap[bitmap_index]; + uint current_color = m_buffer[buffer_index]; + uint in_color_scaled = scale_color(color, alpha); + uint old_color_scaled = scale_color(current_color, 255u - alpha); + uint new_color = old_color_scaled + in_color_scaled; + m_buffer[buffer_index] = new_color; + bitmap_index++; + } + y--; + } + } + + /** + * Blit an 8-bit alpha bitmap to the framebuffer. + * + * @param x X coordinate of left side of target location. + * @param y Y coordinate of bottom side of target location. + * @param alpha_bitmap 8-bit alpha-channel bitmap. + * @param width Bitmap width. + * @param height Bitmap height. + * @param color Color to blend with alpha value. + */ + void blit_alpha_bitmap(size_t x, size_t y, const(ubyte)[] alpha_bitmap, + size_t width, size_t height, uint color) + { + blit_alpha_bitmap(x, y, alpha_bitmap.ptr, width, height, color); + } + + /** + * Scale a color value by an alpha amount. + * + * @param color Color value. + * @param alpha Alpha amount. + * + * @return Scaled color value. + */ + private uint scale_color(uint color, ubyte alpha) + { + return ((((color & 0xFFu) * alpha) >> 8u) & 0xFFu) | + ((((color & 0xFF00u) * alpha) >> 8u) & 0xFF00u) | + ((((color & 0xFF0000u) * alpha) >> 8u) & 0xFF0000u); + } + + /** + * Return the buffer index for the given X and Y coordinates. + * + * @param x X coordinate from left side of framebuffer. + * @param y Y coordinate from bottom side of framebuffer. + * + * @return Buffer index for the given X and Y coordinates. + */ + private size_t buffer_index(size_t x, size_t y) + { + return (m_height - y - 1u) * m_stride + x; + } }