summaryrefslogtreecommitdiff
path: root/kon
diff options
context:
space:
mode:
authorKonAki <konaki@anokonaki.org>2026-10-10 12:59:03 +0800
committerKonAki <konaki@anokonaki.org>2026-10-10 12:59:03 +0800
commit4a1a5b85c8b417ae3597e40cae80ccc87891a092 (patch)
tree0d93a629a3c02fa9c0edec9b9c27750b59adc40d /kon
parent4965c61e5576b516c9611acc2955057f0c6ad417 (diff)
faster rect fill and ttf glyph blit
Diffstat (limited to 'kon')
-rw-r--r--kon/konfont.h31
-rw-r--r--kon/konsofren.h33
2 files changed, 56 insertions, 8 deletions
diff --git a/kon/konfont.h b/kon/konfont.h
index 3cd1006..1e01b01 100644
--- a/kon/konfont.h
+++ b/kon/konfont.h
@@ -348,12 +348,35 @@ void kon_drawText(kon_framebuffer_t *fb, kon_font_t *font, int x, int y, const c
int glyphW = (int)(q.x1 - q.x0);
int glyphH = (int)(q.y1 - q.y0);
- for (int gy = 0; gy < glyphH; gy++) {
- for (int gx = 0; gx < glyphW; gx++) {
- uint8_t alpha = font->atlasPixels[(src_y0 + gy) * font->atlasSize + (src_x0 + gx)];
+ int dstX = (int)q.x0;
+ int dstY = (int)q.y0;
+ int gx0 = 0, gy0 = 0;
+
+ if (dstX < 0) gx0 = -dstX;
+ if (dstY < 0) gy0 = -dstY;
+ int gx1 = glyphW, gy1 = glyphH;
+ if (dstX + gx1 > fb->width) gx1 = fb->width - dstX;
+ if (dstY + gy1 > fb->height) gy1 = fb->height - dstY;
+
+ for (int gy = gy0; gy < gy1; gy++) {
+ const uint8_t *in = font->atlasPixels + (size_t)(src_y0 + gy) * font->atlasSize + src_x0;
+ uint32_t *out = fb->data + (size_t)(dstY + gy) * fb->width + dstX;
+
+ for (int gx = gx0; gx < gx1; gx++) {
+ uint32_t alpha = in[gx];
if (alpha == 0) continue;
- kon_putPixel(fb, (int)q.x0 + gx, (int)q.y0 + gy, ((uint32_t)alpha << 24) | baseColor);
+ if (alpha == 0xFF) {
+ out[gx] = 0xFF000000u | baseColor;
+ continue;
+ }
+
+ uint32_t dst = out[gx];
+ uint32_t inv = 255 - alpha;
+ uint32_t r = (((baseColor >> 16) & 0xFF) * alpha + ((dst >> 16) & 0xFF) * inv) / 255;
+ uint32_t g = (((baseColor >> 8) & 0xFF) * alpha + ((dst >> 8) & 0xFF) * inv) / 255;
+ uint32_t b = ((baseColor & 0xFF) * alpha + (dst & 0xFF) * inv) / 255;
+ out[gx] = (dst & 0xFF000000u) | (r << 16) | (g << 8) | b;
}
}
}
diff --git a/kon/konsofren.h b/kon/konsofren.h
index c45091b..e89915a 100644
--- a/kon/konsofren.h
+++ b/kon/konsofren.h
@@ -476,11 +476,36 @@ void kon_fillRectangle(kon_framebuffer_t *fb, int x, int y, int width, int heigh
if (x + width > fb->width ) width = fb->width - x;
if (y + height > fb->height) height = fb->height - y;
- for (int offset_y = 0; offset_y < height; offset_y++) {
- for (int offset_x = 0; offset_x < width; offset_x++) {
- uint32_t dst = fb->data[(offset_y + y) * fb->width + (offset_x + x)];
- fb->data[(y + offset_y) * fb->width + (x + offset_x)] = kon_blendColor(dst, color);
+ if (width <= 0 || height <= 0) return;
+
+ uint32_t a = color >> 24;
+ if (a == 0) return;
+
+ if (a == 0xFF) {
+ for (int row = 0; row < height; row++) {
+ uint32_t *out = fb->data + (size_t)(y + row) * fb->width + x;
+ for (int col = 0; col < width; col++) out[col] = color;
+ }
+ return;
+ }
+ /* same result as kon_blendColor, with x / 255 done as shifts */
+ uint32_t inv = 255 - a;
+ uint32_t sr = ((color >> 16) & 0xFF) * a;
+ uint32_t sg = ((color >> 8) & 0xFF) * a;
+ uint32_t sb = (color & 0xFF) * a;
+
+ for (int row = 0; row < height; row++) {
+ uint32_t *out = fb->data + (size_t)(y + row) * fb->width + x;
+ for (int col = 0; col < width; col++) {
+ uint32_t dst = out[col];
+ uint32_t r = sr + ((dst >> 16) & 0xFF) * inv;
+ uint32_t g = sg + ((dst >> 8) & 0xFF) * inv;
+ uint32_t b = sb + (dst & 0xFF) * inv;
+ r = (r + 1 + (r >> 8)) >> 8;
+ g = (g + 1 + (g >> 8)) >> 8;
+ b = (b + 1 + (b >> 8)) >> 8;
+ out[col] = (dst & 0xFF000000u) | (r << 16) | (g << 8) | b;
}
}
}