diff options
| author | KonAki <konaki@anokonaki.org> | 2026-10-10 12:59:03 +0800 |
|---|---|---|
| committer | KonAki <konaki@anokonaki.org> | 2026-10-10 12:59:03 +0800 |
| commit | 4a1a5b85c8b417ae3597e40cae80ccc87891a092 (patch) | |
| tree | 0d93a629a3c02fa9c0edec9b9c27750b59adc40d | |
| parent | 4965c61e5576b516c9611acc2955057f0c6ad417 (diff) | |
faster rect fill and ttf glyph blit
| -rw-r--r-- | kon/konfont.h | 31 | ||||
| -rw-r--r-- | kon/konsofren.h | 33 |
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; } } } |
