aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2023-04-22 13:29:56 +0200
committerNathan Reiner <nathan@nathanreiner.xyz>2023-04-22 13:29:56 +0200
commit67893dc14d10f49a76652ff384ab2bf4a945ca30 (patch)
treec0612519116b0cfad0c1a1ae9df9beb92a9908e0
parentdc8f8644293b17f056edefa9e0e4a786686816a1 (diff)
add glyph caching
-rw-r--r--drw.c95
-rw-r--r--drw.h6
-rw-r--r--swt.c19
3 files changed, 74 insertions, 46 deletions
diff --git a/drw.c b/drw.c
index 6683cdb..307e942 100644
--- a/drw.c
+++ b/drw.c
@@ -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);
}
diff --git a/drw.h b/drw.h
index 4a0a25c..0885fe2 100644
--- a/drw.h
+++ b/drw.h
@@ -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
diff --git a/swt.c b/swt.c
index 2b5720c..42ff22e 100644
--- a/swt.c
+++ b/swt.c
@@ -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();
}