]> Dogcows Code - chaz/openbox/blob - render/font.c
remove the font code for parsing Xft font strings. we are using the individual values...
[chaz/openbox] / render / font.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3 font.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003 Ben Jansens
6 Copyright (c) 2003 Derek Foreman
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 See the COPYING file for a copy of the GNU General Public License.
19 */
20
21 #include "font.h"
22 #include "color.h"
23 #include "mask.h"
24 #include "theme.h"
25 #include "geom.h"
26 #include "instance.h"
27 #include "gettext.h"
28
29 #include <glib.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <locale.h>
33
34 #define OB_SHADOW "shadow"
35 #define OB_SHADOW_OFFSET "shadowoffset"
36 #define OB_SHADOW_ALPHA "shadowtint"
37
38 FcObjectType objs[] = {
39 { OB_SHADOW, FcTypeBool },
40 { OB_SHADOW_OFFSET, FcTypeInteger },
41 { OB_SHADOW_ALPHA, FcTypeInteger }
42 };
43
44 static gboolean started = FALSE;
45
46 static void font_startup(void)
47 {
48 if (!XftInit(0)) {
49 g_warning(_("Couldn't initialize Xft."));
50 exit(EXIT_FAILURE);
51 }
52
53 /* Here we are teaching xft about the shadow, shadowoffset & shadowtint */
54 FcNameRegisterObjectTypes(objs, (sizeof(objs) / sizeof(objs[0])));
55 }
56
57 static void measure_font(const RrInstance *inst, RrFont *f)
58 {
59 PangoFontMetrics *metrics;
60 gchar *locale, *p;
61
62 /* get the default language from the locale
63 (based on gtk_get_default_language in gtkmain.c) */
64 locale = g_strdup(setlocale(LC_CTYPE, NULL));
65 if ((p = strchr(locale, '.'))) *p = '\0'; /* strip off the . */
66 if ((p = strchr(locale, '@'))) *p = '\0'; /* strip off the @ */
67
68 /* measure the ascent and descent */
69 metrics = pango_context_get_metrics(inst->pango, f->font_desc,
70 pango_language_from_string(locale));
71 f->ascent = pango_font_metrics_get_ascent(metrics);
72 f->descent = pango_font_metrics_get_descent(metrics);
73 pango_font_metrics_unref(metrics);
74
75 g_free(locale);
76 }
77
78 RrFont *RrFontOpen(const RrInstance *inst, gchar *name, gint size,
79 RrFontWeight weight, RrFontSlant slant, gboolean shadow,
80 gint shadowoffset, gchar shadowtint)
81 {
82 RrFont *out;
83 PangoWeight pweight;
84 PangoStyle pstyle;
85
86 if (!started) {
87 font_startup();
88 started = TRUE;
89 }
90
91 g_assert(shadowtint <= 100 && shadowtint >= -100);
92
93 out = g_new(RrFont, 1);
94 out->inst = inst;
95 out->ref = 1;
96 out->font_desc = pango_font_description_new();
97 out->layout = pango_layout_new(inst->pango);
98
99 switch (weight) {
100 case RR_FONTWEIGHT_LIGHT: pweight = PANGO_WEIGHT_LIGHT; break;
101 case RR_FONTWEIGHT_NORMAL: pweight = PANGO_WEIGHT_NORMAL; break;
102 case RR_FONTWEIGHT_SEMIBOLD: pweight = PANGO_WEIGHT_SEMIBOLD; break;
103 case RR_FONTWEIGHT_BOLD: pweight = PANGO_WEIGHT_BOLD; break;
104 case RR_FONTWEIGHT_ULTRABOLD: pweight = PANGO_WEIGHT_ULTRABOLD; break;
105 default: g_assert_not_reached();
106 }
107
108 switch (slant) {
109 case RR_FONTSLANT_NORMAL: pstyle = PANGO_STYLE_NORMAL; break;
110 case RR_FONTSLANT_ITALIC: pstyle = PANGO_STYLE_ITALIC; break;
111 case RR_FONTSLANT_OBLIQUE: pstyle = PANGO_STYLE_OBLIQUE; break;
112 default: g_assert_not_reached();
113 }
114
115 /* setup the font */
116 pango_font_description_set_family(out->font_desc, name);
117 pango_font_description_set_weight(out->font_desc, pweight);
118 pango_font_description_set_style(out->font_desc, pstyle);
119 pango_font_description_set_size(out->font_desc, size * PANGO_SCALE);
120
121 /* setup the shadow */
122 out->shadow = shadow;
123 out->offset = shadowoffset;
124 out->tint = shadowtint;
125
126 /* setup the layout */
127 pango_layout_set_font_description(out->layout, out->font_desc);
128 pango_layout_set_single_paragraph_mode(out->layout, TRUE);
129 pango_layout_set_ellipsize(out->layout, PANGO_ELLIPSIZE_MIDDLE);
130
131 /* get the ascent and descent */
132 measure_font(inst, out);
133
134 return out;
135 }
136
137 RrFont *RrFontOpenDefault(const RrInstance *inst)
138 {
139 return RrFontOpen(inst, RrDefaultFontFamily, RrDefaultFontSize,
140 RrDefaultFontWeight, RrDefaultFontSlant,
141 RrDefaultFontShadow, RrDefaultFontShadowOffset,
142 RrDefaultFontShadowTint);
143 }
144
145 void RrFontRef(RrFont *f)
146 {
147 ++f->ref;
148 }
149
150 void RrFontClose(RrFont *f)
151 {
152 if (f) {
153 if (--f->ref < 1) {
154 g_object_unref(f->layout);
155 pango_font_description_free(f->font_desc);
156 g_free(f);
157 }
158 }
159 }
160
161 static void font_measure_full(const RrFont *f, const gchar *str,
162 gint *x, gint *y)
163 {
164 PangoRectangle rect;
165
166 pango_layout_set_text(f->layout, str, -1);
167 pango_layout_set_width(f->layout, -1);
168 pango_layout_get_pixel_extents(f->layout, NULL, &rect);
169 *x = rect.width + (f->shadow ? ABS(f->offset) : 0);
170 *y = rect.height + (f->shadow ? ABS(f->offset) : 0);
171 }
172
173 RrSize *RrFontMeasureString(const RrFont *f, const gchar *str)
174 {
175 RrSize *size;
176 size = g_new(RrSize, 1);
177 font_measure_full(f, str, &size->width, &size->height);
178 return size;
179 }
180
181 gint RrFontHeight(const RrFont *f)
182 {
183 return (f->ascent + f->descent) / PANGO_SCALE +
184 (f->shadow ? f->offset : 0);
185 }
186
187 static inline int font_calculate_baseline(RrFont *f, gint height)
188 {
189 /* For my own reference:
190 * _________
191 * ^space/2 ^height ^baseline
192 * v_________|_ |
193 * | ^ascent | _ _
194 * | | | | |_ _____ _| |_ _ _
195 * | | | | _/ -_) \ / _| || |
196 * | v_________v \__\___/_\_\\__|\_, |
197 * | ^descent |__/
198 * __________|_v
199 * ^space/2 |
200 * V_________v
201 */
202 return (((height * PANGO_SCALE) /* height of the space in pango units */
203 - (f->ascent + f->descent)) /* minus space taken up by text */
204 / 2 /* divided by two -> half of the empty space (this is the top
205 of the text) */
206 + f->ascent) /* now move down to the baseline */
207 / PANGO_SCALE; /* back to pixels */
208 }
209
210 void RrFontDraw(XftDraw *d, RrTextureText *t, RrRect *area)
211 {
212 gint x,y,w,h;
213 XftColor c;
214 gint mw;
215 PangoRectangle rect;
216
217 /* center the text vertically
218 We do this centering based on the 'baseline' since different fonts have
219 different top edges. It looks bad when the whole string is moved when 1
220 character from a non-default language is included in the string */
221 y = area->y +
222 font_calculate_baseline(t->font, area->height);
223
224 /* the +2 and -4 leave a small blank edge on the sides */
225 x = area->x + 2;
226 w = area->width - 4;
227 h = area->height;
228
229 pango_layout_set_text(t->font->layout, t->string, -1);
230 pango_layout_set_width(t->font->layout, w * PANGO_SCALE);
231
232 pango_layout_get_pixel_extents(t->font->layout, NULL, &rect);
233 mw = rect.width;
234
235 /* pango_layout_set_alignment doesn't work with
236 pango_xft_render_layout_line */
237 switch (t->justify) {
238 case RR_JUSTIFY_LEFT:
239 break;
240 case RR_JUSTIFY_RIGHT:
241 x += (w - mw);
242 break;
243 case RR_JUSTIFY_CENTER:
244 x += (w - mw) / 2;
245 break;
246 }
247
248 if (t->font->shadow) {
249 if (t->font->tint >= 0) {
250 c.color.red = 0;
251 c.color.green = 0;
252 c.color.blue = 0;
253 c.color.alpha = 0xffff * t->font->tint / 100;
254 c.pixel = BlackPixel(RrDisplay(t->font->inst),
255 RrScreen(t->font->inst));
256 } else {
257 c.color.red = 0xffff;
258 c.color.green = 0xffff;
259 c.color.blue = 0xffff;
260 c.color.alpha = 0xffff * -t->font->tint / 100;
261 c.pixel = WhitePixel(RrDisplay(t->font->inst),
262 RrScreen(t->font->inst));
263 }
264 /* see below... */
265 pango_xft_render_layout_line
266 (d, &c, pango_layout_get_line(t->font->layout, 0),
267 (x + t->font->offset) * PANGO_SCALE,
268 (y + t->font->offset) * PANGO_SCALE);
269 }
270
271 c.color.red = t->color->r | t->color->r << 8;
272 c.color.green = t->color->g | t->color->g << 8;
273 c.color.blue = t->color->b | t->color->b << 8;
274 c.color.alpha = 0xff | 0xff << 8; /* fully opaque text */
275 c.pixel = t->color->pixel;
276
277 /* layout_line() uses y to specify the baseline
278 The line doesn't need to be freed, it's a part of the layout */
279 pango_xft_render_layout_line
280 (d, &c, pango_layout_get_line(t->font->layout, 0),
281 x * PANGO_SCALE, y * PANGO_SCALE);
282 }
This page took 0.050695 seconds and 5 git commands to generate.