Skip to content

Commit

Permalink
Add RGB Highlights
Browse files Browse the repository at this point in the history
  • Loading branch information
smasher816 committed Oct 26, 2023
1 parent e1f0b07 commit ce6597a
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 14 deletions.
79 changes: 79 additions & 0 deletions blitbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ static const char*
// Helpers to pack pixels manually, without going through the Color structs.
#define Y8_To_Y8A(v) (0xFFu << 8U | v)
#define RGB_To_RGB32(r, g, b) ((uint32_t) (0xFFu << 24U) | (uint32_t) (b << 16U) | (uint32_t) (g << 8U) | r)
#define RGBA_To_RGB32(r, g, b, a) ((uint32_t) (a << 24U) | (uint32_t) (b << 16U) | (uint32_t) (g << 8U) | r)
#define Y8_To_RGB32(v) ((uint32_t) (0xFFu << 24U) | (uint32_t) (v << 16U) | (uint32_t) (v << 8U) | v)

// __auto_type was introduced in GCC 4.9 (and Clang ~3.8)...
Expand Down Expand Up @@ -416,6 +417,65 @@ void BB_fill_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsi
}
}

void BB_fill_rect_color(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, ColorRGB32 * restrict color) {
const int rotation = GET_BB_ROTATION(bb);
unsigned int rx, ry, rw, rh;
// Compute rotated rectangle coordinates & size
switch (rotation) {
case 0:
rx = x;
ry = y;
rw = w;
rh = h;
break;
case 1:
rx = bb->w - (y + h);
ry = x;
rw = h;
rh = w;
break;
case 2:
rx = bb->w - (x + w);
ry = bb->h - (y + h);
rw = w;
rh = h;
break;
case 3:
rx = y;
ry = bb->h - (x + w);
rw = h;
rh = w;
break;
}

// Handle any target pitch properly
const int bb_type = GET_BB_TYPE(bb);
switch (bb_type) {
case TYPE_BBRGB32:
// And here either, as we want to preserve the alpha byte
if (rx == 0 && rw == bb->w) {
// Single step for contiguous scanlines
const uint32_t src = (uint32_t) RGBA_To_RGB32(color->r, color->g, color->b, color->alpha);
uint32_t * restrict p = (uint32_t *) (bb->data + bb->stride*ry);
size_t px_count = bb->pixel_stride*rh;
while (px_count--) {
*p++ = src;
}
} else {
// Scanline per scanline
const uint32_t src = (uint32_t) RGBA_To_RGB32(color->r, color->g, color->b, color->alpha);
for (unsigned int j = ry; j < ry+rh; j++) {
uint32_t * restrict p = (uint32_t *) (bb->data + bb->stride*j) + rx;
size_t px_count = rw;
while (px_count--) {
*p++ = src;
}
}
}
break;
}
}

void BB_blend_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, Color8A * restrict color) {
const int bb_type = GET_BB_TYPE(bb);
const int bb_rotation = GET_BB_ROTATION(bb);
Expand Down Expand Up @@ -477,6 +537,25 @@ void BB_blend_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, uns
}
}

void BB_blend_rect_color(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, ColorRGB32 * restrict color) {
const int bb_type = GET_BB_TYPE(bb);
const int bb_rotation = GET_BB_ROTATION(bb);
switch (bb_type) {
case TYPE_BBRGB32:
for (unsigned int j = y; j < y + h; j++) {
for (unsigned int i = x; i < x + w; i++) {
ColorRGB32 * restrict dstptr;
BB_GET_PIXEL(bb, bb_rotation, ColorRGB32, i, j, &dstptr);
dstptr->r = (uint8_t) MAX(color->r - (255 - dstptr->r), 0);
dstptr->g = (uint8_t) MAX(color->g - (255 - dstptr->g), 0);
dstptr->b = (uint8_t) MAX(color->b - (255 - dstptr->b), 0);
dstptr->alpha = 0xFF;
}
}
break;
}
}

void BB_invert_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h) {
const int rotation = GET_BB_ROTATION(bb);
unsigned int rx, ry, rw, rh;
Expand Down
2 changes: 2 additions & 0 deletions blitbuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,9 @@ typedef struct BlitBufferRGB32 {

DLL_PUBLIC void BB_fill(BlitBuffer * restrict bb, uint8_t v);
DLL_PUBLIC void BB_fill_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint8_t v);
DLL_PUBLIC void BB_fill_rect_color(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, ColorRGB32 * restrict color);
DLL_PUBLIC void BB_blend_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, Color8A * restrict color);
DLL_PUBLIC void BB_blend_rect_color(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, ColorRGB32 * restrict color);
DLL_PUBLIC void BB_invert_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h);
DLL_PUBLIC void BB_hatch_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int stripe_width, Color8 * restrict color, uint8_t alpha);
DLL_PUBLIC void BB_blit_to_BB8(const BlitBuffer * restrict src, BlitBuffer * restrict dst,
Expand Down
40 changes: 26 additions & 14 deletions ffi/blitbuffer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ typedef struct BlitBufferRGB32 {

void BB_fill(BlitBuffer * restrict bb, uint8_t v);
void BB_fill_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint8_t v);
void BB_fill_rect_color(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, ColorRGB32 * restrict color);
void BB_blend_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, Color8A * restrict color);
void BB_blend_rect_color(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, ColorRGB32 * restrict color);
void BB_invert_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h);
void BB_hatch_rect(BlitBuffer * restrict bb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int stripe_width, Color8 * restrict color, uint8_t alpha);
void BB_blit_to(const BlitBuffer * restrict source, BlitBuffer * restrict dest, unsigned int dest_x, unsigned int dest_y,
Expand Down Expand Up @@ -170,13 +172,13 @@ local P_BlitBuffer = ffi.typeof("BlitBuffer*")
local P_BlitBuffer_ROData = ffi.typeof("const BlitBuffer*")

-- metatables for color types:
local Color4L_mt = {__index={}}
local Color4U_mt = {__index={}}
local Color8_mt = {__index={}}
local Color8A_mt = {__index={}}
local ColorRGB16_mt = {__index={}}
local ColorRGB24_mt = {__index={}}
local ColorRGB32_mt = {__index={}}
local Color4L_mt = {__index={ is_rgb=false }}
local Color4U_mt = {__index={ is_rgb=false }}
local Color8_mt = {__index={ is_rgb=false }}
local Color8A_mt = {__index={ is_rgb=false }}
local ColorRGB16_mt = {__index={ is_rgb=false }}
local ColorRGB24_mt = {__index={ is_rgb=false }}
local ColorRGB32_mt = {__index={ is_rgb=true }}

-- color setting
function Color4L_mt.__index:set(color)
Expand Down Expand Up @@ -1497,8 +1499,13 @@ function BB_mt.__index:paintRect(x, y, w, h, value, setter)
h, y = BB.checkBounds(h, y, 0, self:getHeight(), 0xFFFF)
if w <= 0 or h <= 0 then return end
if self:canUseCbb() and setter == self.setPixel then
cblitbuffer.BB_fill_rect(ffi.cast(P_BlitBuffer, self),
x, y, w, h, value:getColor8().a)
if value.is_rgb then
cblitbuffer.BB_fill_rect_color(ffi.cast(P_BlitBuffer, self),
x, y, w, h, value:getColorRGB32())
else
cblitbuffer.BB_fill_rect(ffi.cast(P_BlitBuffer, self),
x, y, w, h, value:getColor8().a)
end
else
-- We can only do fast filling when there's no complex processing involved (i.e., simple setPixel only)
if setter == self.setPixel then
Expand Down Expand Up @@ -1926,16 +1933,21 @@ lighten color values in rectangular area
@param y Y coordinate
@param w width
@param h height
@param by lighten by this factor (default: 0.5)
@param color color to overlay (default: 0x80, 50% gray)
--]]
function BB_mt.__index:lightenRect(x, y, w, h, by)
local color = Color8A(0, 0xFF*(by or 0.5))
function BB_mt.__index:lightenRect(x, y, w, h, color)
color = color or Color8A(0xFF, 0x80)
if self:canUseCbb() then
w, x = BB.checkBounds(w, x, 0, self:getWidth(), 0xFFFF)
h, y = BB.checkBounds(h, y, 0, self:getHeight(), 0xFFFF)
if w <= 0 or h <= 0 then return end
cblitbuffer.BB_blend_rect(ffi.cast(P_BlitBuffer, self),
x, y, w, h, color)
if color.is_rgb then
cblitbuffer.BB_blend_rect_color(ffi.cast(P_BlitBuffer, self),
x, y, w, h, color)
else
cblitbuffer.BB_blend_rect(ffi.cast(P_BlitBuffer, self),
x, y, w, h, color)
end
else
self:paintRect(x, y, w, h, color, self.setPixelBlend)
end
Expand Down

0 comments on commit ce6597a

Please sign in to comment.