Przeglądaj źródła

Add bounding-box retrieval function

Léo Gaspard 8 lat temu
rodzic
commit
c04de23b96
4 zmienionych plików z 42 dodań i 2 usunięć
  1. 1 1
      TODO
  2. 28 0
      dtext.c
  3. 9 0
      dtext.h
  4. 4 1
      test.c

+ 1 - 1
TODO

@@ -1,7 +1,7 @@
 Still to do:
  * Cleanly report Xlib errors
- * Retrieval of bounding box of text without displaying it
  * Support for wide chars (wchar_t)
  * Support for bold and italics
  * Support for fallback fonts
  * Document
+ * Fix Fantasque Sans Mono ascent/descent (or is it a font issue?)

+ 28 - 0
dtext.c

@@ -5,6 +5,7 @@
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
+#include FT_ADVANCES_H
 
 #include <X11/Xlib.h>
 #include <X11/extensions/Xrender.h>
@@ -109,6 +110,33 @@ dt_free(dt_context *ctx, dt_font *fnt)
 	return err;
 }
 
+dt_error
+dt_box(dt_font *fnt, dt_bbox *bbox, char const *txt)
+{
+	dt_error err;
+	size_t len;
+	size_t i;
+	FT_Fixed adv;
+
+	if (!(len = strlen(txt)))
+		return -EINVAL;
+
+	memset(bbox, 0, sizeof(*bbox));
+
+	bbox->x = 0;
+	bbox->y = - (fnt->face->ascender >> 6);
+
+	for (i = 0; i < len; ++i) {
+		if ((err = FT_Get_Advance(fnt->face, txt[i], 0, &adv)))
+			return err;
+		bbox->w += adv >> 16;
+	}
+
+	bbox->h = fnt->face->height >> 6;
+
+	return 0;
+}
+
 dt_error
 dt_draw(dt_context *ctx, dt_font *fnt, dt_style const *style,
         uint32_t x, uint32_t y, char const *txt)

+ 9 - 0
dtext.h

@@ -20,6 +20,14 @@ typedef struct {
 	uint8_t loaded[256];
 } dt_font;
 
+typedef struct {
+	int32_t x; // Bottom-left of box, relative to point of origin of text
+	int32_t y;
+
+	uint32_t w;
+	uint32_t h;
+} dt_bbox;
+
 typedef struct {
 	uint8_t red;
 	uint8_t green;
@@ -34,5 +42,6 @@ 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, char const *txt);
 dt_error dt_draw(dt_context *ctx, dt_font *fnt, dt_style const *style,
                  uint32_t x, uint32_t y, char const *txt);

+ 4 - 1
test.c

@@ -88,9 +88,12 @@ static void setup_dt()
 
 static void draw()
 {
+	dt_bbox bbox;
+
 	assert(!dt_draw(ctx, fnt, &style, 10, 50, TEXT));
 
-	XFillRectangle(dpy, win, gc, 5, 60, 400, 100);
+	assert(!dt_box(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));
 
 	XFlush(dpy);