]> icculus.org git repositories - dana/openbox.git/blob - render2/font.c
better font layout
[dana/openbox.git] / render2 / font.c
1 #include "render.h"
2 #include "instance.h"
3 #include "surface.h"
4 #include "font.h"
5 #include <stdlib.h>
6 #include <string.h>
7 #include <glib.h>
8
9 #define ALPHAS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" \
10                "1234567890`-=\\!@#$%^&*()~_+|[]{};':\",./<>?"
11 #define ELIPSES "..."
12
13 struct RrFont *RrFontOpen(struct RrInstance *inst, const char *fontstring)
14 {
15     struct RrFont *font;
16     int w, h;
17
18     font = malloc(sizeof(struct RrFont));
19     font->inst = inst;
20     font->font = GlftFontOpen(RrDisplay(inst), RrScreen(inst), fontstring);
21
22     GlftMeasureString(font->font, ELIPSES, strlen(ELIPSES), &w, &h);
23     font->elipses = w;
24     GlftMeasureString(font->font, ALPHAS, strlen(ALPHAS), &w, &h);
25     font->height = h;
26
27     return font;
28 }
29
30 void RrFontClose(struct RrFont *font)
31 {
32     if (font) {
33         GlftFontClose(font->font);
34         free(font);
35     }
36 }
37
38 int RrFontMeasureString(struct RrFont *font, const char *string)
39 {
40     int w, h;
41     GlftMeasureString(font->font, string, strlen(string), &w, &h);
42     return w;
43 }
44
45 int RrFontHeight(struct RrFont *font)
46 {
47     return GlftFontHeight(font->font);
48 }
49
50 int RrFontMaxCharWidth(struct RrFont *font)
51 {
52     return GlftFontMaxCharWidth(font->font);
53 }
54
55 void RrFontRenderString(struct RrSurface *sur, struct RrFont *font,
56                         struct RrColor *color, enum RrLayout layout,
57                         const char *string, int x, int y, int w, int h)
58 {
59     struct GlftColor col;
60     int fh = RrFontHeight(font);
61     int l, mw, mh;
62     GString *text;
63     int shortened = 0;
64
65     switch (layout) {
66     case RR_TOP_LEFT:
67     case RR_TOP:
68     case RR_TOP_RIGHT:
69         y += h - fh;
70         break;
71     case RR_LEFT:
72     case RR_CENTER:
73     case RR_RIGHT:
74         y += (h - fh) / 2;
75         break;
76     case RR_BOTTOM_LEFT:
77     case RR_BOTTOM:
78     case RR_BOTTOM_RIGHT:
79         break;
80     }
81
82     text = g_string_new(string);
83     l = g_utf8_strlen(text->str, -1);
84     GlftMeasureString(font->font, text->str, strlen(text->str), &mw, &mh);
85     if (font->elipses > w)
86         l = 0; /* nothing fits.. */
87     else {
88         while (l && mw > w) {
89             shortened = 1;
90             /* remove a character from the middle */
91             text = g_string_erase(text, l-- / 2, 1);
92             /* if the elipses are too large, don't show them at all */
93             GlftMeasureString(font->font, text->str, strlen(text->str),
94                               &mw, &mh);
95             mw += font->elipses;
96         }
97         if (shortened) {
98             text = g_string_insert(text, (l + 1) / 2, ELIPSES);
99             l += 3;
100         }
101     }
102     if (!l) return;
103
104     /* center in the font's height's area based on the measured height of the
105        specific string */
106     y += (fh - mh) / 2;
107
108     switch (layout) {
109     case RR_TOP_LEFT:
110     case RR_LEFT:
111     case RR_BOTTOM_LEFT:
112         break;
113     case RR_TOP:
114     case RR_CENTER:
115     case RR_BOTTOM:
116         x += (w - mw) / 2;
117         break;
118     case RR_TOP_RIGHT:
119     case RR_RIGHT:
120     case RR_BOTTOM_RIGHT:
121         x += w - mw;
122         break;
123     }
124
125     col.r = color->r;
126     col.g = color->g;
127     col.b = color->b;
128     col.a = color->a;
129     GlftRenderString(font->font, text->str, strlen(text->str), &col, x, y);
130 }