summaryrefslogtreecommitdiff
path: root/kon
diff options
context:
space:
mode:
authorKonAki <konaki@anokonaki.org>2026-10-12 13:54:28 +0800
committerKonAki <konaki@anokonaki.org>2026-10-12 13:54:28 +0800
commitad3144d68642d02782c10df688dd1a5340d8c091 (patch)
tree982a22a3c932a97d8f9443f3ebc6fc37806311f3 /kon
parent47262912ac4b644806700906f3258e8a32a54938 (diff)
konsofren: blend modes, bad numbers no longer reach the image drawing
Diffstat (limited to 'kon')
-rw-r--r--kon/konsofren.h47
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);
+ }
}
}
}