diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2023-04-22 13:29:56 +0200 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2023-04-22 13:29:56 +0200 |
| commit | 67893dc14d10f49a76652ff384ab2bf4a945ca30 (patch) | |
| tree | c0612519116b0cfad0c1a1ae9df9beb92a9908e0 | |
| parent | dc8f8644293b17f056edefa9e0e4a786686816a1 (diff) | |
add glyph caching
| -rw-r--r-- | drw.c | 95 | ||||
| -rw-r--r-- | drw.h | 6 | ||||
| -rw-r--r-- | swt.c | 19 |
3 files changed, 74 insertions, 46 deletions
@@ -158,7 +158,7 @@ free_drw(Canvas *canvas) void push_buffer(Canvas *canvas) { - memcpy(canvas->buffer_data, canvas->data, canvas->size); + //memcpy(canvas->buffer_data, canvas->data, canvas->size); } @@ -168,7 +168,7 @@ draw_point(Canvas *canvas, unsigned x, unsigned y, uint32_t color) if (!(x < canvas->width && y < canvas->height)) return; - canvas->data[x + canvas->width * y] = color; + canvas->buffer_data[x + canvas->width * y] = color; } @@ -299,6 +299,7 @@ init_font(Font *font) FT_Stroker_New(font->library, &font->stroke); font->loaded = 1; + memset(font->cache, 0, CACHE_SIZE); } @@ -329,7 +330,7 @@ draw_bitmap(Canvas *canvas, FT_Bitmap *bitmap, unsigned x, unsigned y, uint32_t continue; } - bg = to_color(canvas->data[i + j * canvas->width]); + bg = to_color(canvas->buffer_data[i + j * canvas->width]); strength = bitmap->buffer[p + q * bitmap->width]; strength /= 255; @@ -379,59 +380,75 @@ get_font_with_charcode(FontCache *fontcache, uint_least32_t charcode) } -unsigned -draw_char(Canvas *canvas, FontCache *fontcache, uint_least32_t charcode, unsigned x, unsigned y, uint32_t color) +FT_BitmapGlyph +load_bitmap(Font *font, uint_least32_t charcode) { - FT_GlyphSlot slot; - FT_Error error; - FT_UInt glyph_index; - FT_UInt previous = 0; FT_Bool has_kerning; FT_Vector delta; - Font *font; + FT_UInt glyph_index; + FT_Error error; + FT_GlyphSlot slot; FT_BitmapGlyph bg; FT_Glyph glyph; - font = get_font_with_charcode(fontcache, charcode); - FT_Set_Pixel_Sizes(font->face, 0, fontcache->fontsize); + slot = font->face->glyph; + glyph_index = FT_Get_Char_Index(font->face, charcode); - if (boldstokemode && fontcache->fonttype == FONT_BOLD) { - FT_Stroker_Set(font->stroke, fontcache->fontsize * 2, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, fontcache->fontsize * 2); + if (glyph_index >= CACHE_SIZE || font->cache[glyph_index] == 0) { + has_kerning = FT_HAS_KERNING(font->face); + if (has_kerning && glyph_index) { + FT_Get_Kerning(font->face, 0, glyph_index, FT_KERNING_DEFAULT, &delta); + } - y -= fontcache->fontsize * 2 / 64 + 1; + error = FT_Load_Glyph(font->face, glyph_index, FT_LOAD_DEFAULT); + if (error) { + fprintf(stderr, "warning: char not loaded, skipping...\n"); + return 0; + } + + FT_Get_Glyph(slot, &glyph); + FT_Glyph_StrokeBorder(&glyph, font->stroke, 0, 1); + if (error) { + fprintf(stderr, "warning: could not apply stroke\n"); + return 0; + } + + FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1); + bg = (FT_BitmapGlyph)glyph; + + if (glyph_index >= CACHE_SIZE) { + FT_Done_Glyph(glyph); + } else { + font->cache[glyph_index] = bg; + } } else { - FT_Stroker_Set(font->stroke, 0, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); + bg = font->cache[glyph_index]; } - slot = font->face->glyph; - glyph_index = FT_Get_Char_Index(font->face, charcode); + return bg; +} - has_kerning = FT_HAS_KERNING(font->face); - if (has_kerning && previous && glyph_index) { - FT_Get_Kerning(font->face, previous, glyph_index, FT_KERNING_DEFAULT, &delta); - x += delta.x >> 6; - } +void +draw_char(Canvas *canvas, FontCache *fontcache, uint_least32_t charcode, unsigned x, unsigned y, uint32_t color) +{ + Font *font; + FT_BitmapGlyph bg; - error = FT_Load_Glyph(font->face, glyph_index, FT_LOAD_DEFAULT); - if (error) { - fprintf(stderr, "warning: char not loaded, skipping...\n"); - return x; - } + font = get_font_with_charcode(fontcache, charcode); + FT_Set_Pixel_Sizes(font->face, 0, fontcache->fontsize); - FT_Get_Glyph(slot, &glyph); - FT_Glyph_StrokeBorder(&glyph, font->stroke, 0, 1); - if (error) { - fprintf(stderr, "warning: could not apply stroke\n"); - return x; + if (boldstokemode && fontcache->fonttype == FONT_BOLD) { + FT_Stroker_Set(font->stroke, fontcache->fontsize * 2, FT_STROKER_LINECAP_BUTT, FT_STROKER_LINEJOIN_ROUND, fontcache->fontsize * 2); + y -= fontcache->fontsize * 2 / 64 + 1; + } else { + FT_Stroker_Set(font->stroke, 0, FT_STROKER_LINECAP_BUTT, FT_STROKER_LINEJOIN_ROUND, 0); } - FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1); - bg = (FT_BitmapGlyph)glyph; - draw_bitmap(canvas, &bg->bitmap, x + bg->left, y - bg->top, color); - FT_Done_Glyph(glyph); + bg = load_bitmap(font, charcode); - x += fontcache->box.width >> 6; + if (bg == 0) + return; - return x; + draw_bitmap(canvas, &bg->bitmap, x + bg->left, y - bg->top, color); } @@ -6,9 +6,12 @@ #include FT_FREETYPE_H #include FT_BITMAP_H #include FT_STROKER_H +#include FT_CACHE_H #include "wayland.h" +#define CACHE_SIZE 4096 + /* type definitions */ typedef struct { uint32_t *data; @@ -30,6 +33,7 @@ typedef struct { FT_Library library; FT_Face face; FT_Stroker stroke; + FT_BitmapGlyph cache[CACHE_SIZE]; } Font; enum FontType { @@ -78,6 +82,6 @@ void draw_point(Canvas *canvas, unsigned x, unsigned y, uint32_t color); FontCache *create_font_cache(FontPath *fontpath, int size, unsigned fontsize); void font_cache_generate_box(FontCache *fontcache); void free_font_cache(FontCache *fontcache); -unsigned draw_char(Canvas *canvas, FontCache *fontcache, uint_least32_t charcode, unsigned x, unsigned y, uint32_t color); +void draw_char(Canvas *canvas, FontCache *fontcache, uint_least32_t charcode, unsigned x, unsigned y, uint32_t color); #endif @@ -261,7 +261,6 @@ draw_glyph(Glyph g, int x, int y) ); } - draw_char( win.canvas, win.fontcache, @@ -270,6 +269,14 @@ draw_glyph(Glyph g, int x, int y) borderpx + y * win.fontcache->box.height + win.fontcache->fontsize, fg ); + + wl_surface_damage_buffer( + win.surface.wl, + borderpx + x * win.fontcache->box.width, + borderpx + y * win.fontcache->box.height, + win.fontcache->box.width, + win.fontcache->box.height + ); } @@ -449,9 +456,7 @@ draw_frame() void commit_surface() { - push_buffer(win.canvas); wl_surface_attach(win.surface.wl, win.canvas->buffer, 0, 0); - wl_surface_damage_buffer(win.surface.wl, 0, 0, win.width, win.height); wl_surface_commit(win.surface.wl); } @@ -462,8 +467,11 @@ surface_configure(void *data, struct xdg_surface *surface, uint32_t serial) int first_configure = win.canvas == 0; xdg_surface_ack_configure(surface, serial); - if (first_configure); + if (first_configure) { + wl_surface_attach(win.surface.wl, win.canvas->buffer, 0, 0); + wl_surface_damage_buffer(win.surface.wl, 0, 0, win.width, win.height); commit_surface(); + } } @@ -484,7 +492,6 @@ toplevel_configure(void *data, struct xdg_toplevel *toplevel, int32_t width, int } else { resize_drw(win.canvas, width, height); } - draw_frame(); win.tty.width = (win.width - 2 * borderpx) / win.fontcache->box.width; win.tty.height = (win.height - 2 * borderpx) / win.fontcache->box.height; @@ -891,9 +898,9 @@ setup() wl_surface_attach(client.pointer.surface, client.pointer.buffer, 0, 0); wl_surface_commit(client.pointer.surface); - wl_display_roundtrip(client.display); draw(); + commit_surface(); } |