diff options
| author | KonAki <konaki@anokonaki.org> | 2026-10-12 13:54:28 +0800 |
|---|---|---|
| committer | KonAki <konaki@anokonaki.org> | 2026-10-12 13:54:28 +0800 |
| commit | ad3144d68642d02782c10df688dd1a5340d8c091 (patch) | |
| tree | 982a22a3c932a97d8f9443f3ebc6fc37806311f3 /kon | |
| parent | 47262912ac4b644806700906f3258e8a32a54938 (diff) | |
konsofren: blend modes, bad numbers no longer reach the image drawing
Diffstat (limited to 'kon')
| -rw-r--r-- | kon/konsofren.h | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/kon/konsofren.h b/kon/konsofren.h index ce81774..b03139d 100644 --- a/kon/konsofren.h +++ b/kon/konsofren.h @@ -58,6 +58,14 @@ typedef enum kon_filter { KON_FILTER_LINEAR } kon_filter_t; +/* how a drawn pixel is mixed with what is already there. its alpha says how much of the effect to apply */ +typedef enum kon_blend { + KON_BLEND_NORMAL, + KON_BLEND_ADD, /* brightens, for glows and light beams */ + KON_BLEND_MULTIPLY, /* darkens, for shadows and colouring what is under it */ + KON_BLEND_SCREEN /* brightens without going past white */ +} kon_blend_t; + typedef struct kon_rect { int x, y, w, h; } kon_rect_t; #define KON_RECT(x, y, w, h) ((kon_rect_t){(int)(x), (int)(y), (int)(w), (int)(h)}) @@ -188,6 +196,9 @@ void kon_drawImageEx(kon_framebuffer_t *fb, const kon_image *image, kon_rect_t s the colour darkens or colours it */ void kon_drawImageTint(kon_framebuffer_t *fb, const kon_image *image, kon_rect_t src, float x, float y, float originX, float originY, float scaleX, float scaleY, float angle, kon_filter_t filter, uint32_t tint); +/* the same, mixed in with blend. positions beyond a few million pixels and values that are not numbers draw nothing */ +void kon_drawImageBlend(kon_framebuffer_t *fb, const kon_image *image, kon_rect_t src, float x, float y, float originX, float originY, float scaleX, float scaleY, float angle, kon_filter_t filter, uint32_t tint, kon_blend_t blend); + /*** draw function declarations ***/ void kon_drawRectangle(kon_framebuffer_t *fb, int x, int y, int width, int height, uint32_t color); @@ -795,13 +806,38 @@ void kon_drawImageEx(kon_framebuffer_t *fb, const kon_image *image, kon_rect_t s kon_drawImageTint(fb, image, src, x, y, originX, originY, scaleX, scaleY, angle, filter, 0xFFFFFFFFu); } +static uint32_t kon_blendMode_(uint32_t dst, uint32_t src, kon_blend_t mode) { + uint32_t a = src >> 24, out = dst & 0xFF000000u; + int shift; + + for (shift = 0; shift < 24; shift += 8) { + uint32_t d = (dst >> shift) & 0xFF, c = (src >> shift) & 0xFF, r; + + switch (mode) { + case KON_BLEND_ADD: r = d + c; if (r > 255) r = 255; break; + case KON_BLEND_MULTIPLY: r = (d * c + 127) / 255; break; + case KON_BLEND_SCREEN: r = 255 - ((255 - d) * (255 - c) + 127) / 255; break; + case KON_BLEND_NORMAL: + default: r = c; break; + } + out |= ((d * (255 - a) + r * a + 127) / 255) << shift; + } + return out; +} + void kon_drawImageTint(kon_framebuffer_t *fb, const kon_image *image, kon_rect_t src, float x, float y, float originX, float originY, float scaleX, float scaleY, float angle, kon_filter_t filter, uint32_t tint) { + kon_drawImageBlend(fb, image, src, x, y, originX, originY, scaleX, scaleY, angle, filter, tint, KON_BLEND_NORMAL); +} + +void kon_drawImageBlend(kon_framebuffer_t *fb, const kon_image *image, kon_rect_t src, float x, float y, float originX, float originY, float scaleX, float scaleY, float angle, kon_filter_t filter, uint32_t tint, kon_blend_t blend) { if (!fb || !image) return; if (!kon_clipRegion_(image, &src)) return; if (scaleX == 0.0f || scaleY == 0.0f) return; + if (!isfinite(x) || !isfinite(y) || !isfinite(originX) || !isfinite(originY) || !isfinite(scaleX) || !isfinite(scaleY) || !isfinite(angle)) return; + if (fabsf(x) > 4e6f || fabsf(y) > 4e6f || fabsf(originX) > 4e6f || fabsf(originY) > 4e6f || fabsf(scaleX) > 4e4f || fabsf(scaleY) > 4e4f) return; if (tint >> 24 == 0) return; - if (angle == 0.0f && scaleX == 1.0f && scaleY == 1.0f && filter == KON_FILTER_NEAREST && tint == 0xFFFFFFFFu) { + if (blend == KON_BLEND_NORMAL && angle == 0.0f && scaleX == 1.0f && scaleY == 1.0f && filter == KON_FILTER_NEAREST && tint == 0xFFFFFFFFu) { kon_drawImageRegion(fb, (int)floorf(x - originX + 0.5f), (int)floorf(y - originY + 0.5f), image, src); return; } @@ -851,8 +887,13 @@ void kon_drawImageTint(kon_framebuffer_t *fb, const kon_image *image, kon_rect_t if (tint != 0xFFFFFFFFu) color = kon_tintColor_(color, tint); uint32_t alpha = color >> 24; - if (alpha == 0xFF) out[px] = color; - else if (alpha != 0) out[px] = kon_blendColor(out[px], color); + if (blend != KON_BLEND_NORMAL) { + if (alpha != 0) out[px] = kon_blendMode_(out[px], color, blend); + } else if (alpha == 0xFF) { + out[px] = color; + } else if (alpha != 0) { + out[px] = kon_blendColor(out[px], color); + } } } } |
