Browse Source

Do not recompute advances on every dt_box call

Léo Gaspard 8 years ago
parent
commit
a0e391e1b4
4 changed files with 17 additions and 18 deletions
  1. 0 1
      TODO
  2. 11 12
      dtext.c
  3. 5 4
      dtext.h
  4. 1 1
      test.c

+ 0 - 1
TODO

@@ -1,6 +1,5 @@
 Still to do:
  * Cleanly report Xlib errors
- * Do not re-render glyphs both for bbox computation and actual drawing
  * Support for bold and italics
  * Support for fallback fonts
  * Document

+ 11 - 12
dtext.c

@@ -14,8 +14,8 @@
 #include "dtext.h"
 
 static dt_error load_char(dt_context *ctx, dt_font *fnt, wchar_t c);
-static uint8_t hash_get(dt_row map[DT_HASH_SIZE], wchar_t key, uint8_t def);
-static dt_error hash_set(dt_row map[DT_HASH_SIZE], wchar_t key, uint8_t val);
+static uint16_t hash_get(dt_row map[DT_HASH_SIZE], wchar_t key, uint16_t def);
+static dt_error hash_set(dt_row map[DT_HASH_SIZE], wchar_t key, uint16_t val);
 
 dt_error
 dt_init(dt_context **res, Display *dpy, Window win)
@@ -87,7 +87,7 @@ dt_load(dt_context *ctx, dt_font **res, uint8_t size, char const *name)
 		goto fail_char_size;
 
 	fnt->gs = XRenderCreateGlyphSet(ctx->dpy, ctx->argb32_format);
-	memset(fnt->loaded, 0, DT_HASH_SIZE * sizeof(fnt->loaded[0]));
+	memset(fnt->advance, 0, sizeof(fnt->advance));
 
 	*res = fnt;
 	return 0;
@@ -114,12 +114,11 @@ dt_free(dt_context *ctx, dt_font *fnt)
 }
 
 dt_error
-dt_box(dt_font *fnt, dt_bbox *bbox, wchar_t const *txt)
+dt_box(dt_context *ctx, dt_font *fnt, dt_bbox *bbox, wchar_t const *txt)
 {
 	dt_error err;
 	size_t len;
 	size_t i;
-	FT_Fixed adv;
 
 	if (!(len = wcslen(txt)))
 		return -EINVAL;
@@ -130,9 +129,9 @@ dt_box(dt_font *fnt, dt_bbox *bbox, wchar_t const *txt)
 	bbox->y = - (fnt->face->ascender >> 6);
 
 	for (i = 0; i < len; ++i) {
-		if ((err = FT_Get_Advance(fnt->face, txt[i], 0, &adv)))
+		if ((err = load_char(ctx, fnt, txt[i])))
 			return err;
-		bbox->w += adv >> 16;
+		bbox->w += hash_get(fnt->advance, txt[i], 0);
 	}
 
 	bbox->h = fnt->face->height >> 6;
@@ -187,7 +186,7 @@ load_char(dt_context *ctx, dt_font *fnt, wchar_t c)
 	char *img;
 	size_t x, y, i;
 
-	if (hash_get(fnt->loaded, c, 0))
+	if (hash_get(fnt->advance, c, 0))
 		return 0;
 
 	if ((err = FT_Load_Char(fnt->face, c, FT_LOAD_RENDER)))
@@ -216,11 +215,11 @@ load_char(dt_context *ctx, dt_font *fnt, wchar_t c)
 
 	free(img);
 
-	return hash_set(fnt->loaded, c, 1);
+	return hash_set(fnt->advance, c, slot->advance.x >> 6);
 }
 
-static uint8_t
-hash_get(dt_row map[DT_HASH_SIZE], wchar_t key, uint8_t def)
+static uint16_t
+hash_get(dt_row map[DT_HASH_SIZE], wchar_t key, uint16_t def)
 {
 	dt_row row;
 	size_t i;
@@ -234,7 +233,7 @@ hash_get(dt_row map[DT_HASH_SIZE], wchar_t key, uint8_t def)
 }
 
 static dt_error
-hash_set(dt_row map[DT_HASH_SIZE], wchar_t key, uint8_t val)
+hash_set(dt_row map[DT_HASH_SIZE], wchar_t key, uint16_t val)
 {
 	dt_row row;
 	dt_pair *d;

+ 5 - 4
dtext.h

@@ -14,8 +14,8 @@ typedef struct {
 } dt_context;
 
 typedef struct {
-	wchar_t k;
-	uint8_t v;
+	wchar_t k;  // char
+	uint16_t v; // advance
 } dt_pair;
 
 typedef struct {
@@ -29,7 +29,7 @@ typedef struct {
 	FT_Face face;
 
 	GlyphSet gs;
-	dt_row loaded[DT_HASH_SIZE];
+	dt_row advance[DT_HASH_SIZE];
 } dt_font;
 
 typedef struct {
@@ -54,6 +54,7 @@ dt_error dt_load(dt_context *ctx, dt_font **fnt,
                  uint8_t size, char const *name);
 dt_error dt_free(dt_context *ctx, dt_font *fnt);
 
-dt_error dt_box(dt_font *fnt, dt_bbox *bbox, wchar_t const *txt);
+dt_error dt_box(dt_context *ctx, dt_font *fnt, dt_bbox *bbox,
+                wchar_t const *txt);
 dt_error dt_draw(dt_context *ctx, dt_font *fnt, dt_style const *style,
                  uint32_t x, uint32_t y, wchar_t const *txt);

+ 1 - 1
test.c

@@ -92,7 +92,7 @@ static void draw()
 
 	assert(!dt_draw(ctx, fnt, &style, 10, 50, TEXT));
 
-	assert(!dt_box(fnt, &bbox, TEXT));
+	assert(!dt_box(ctx, fnt, &bbox, TEXT));
 	XFillRectangle(dpy, win, gc, 10 + bbox.x, 90 + bbox.y, bbox.w, bbox.h);
 	assert(!dt_draw(ctx, fnt, &style_inv, 10, 90, TEXT));