]> Dogcows Code - chaz/openbox/blob - render/font.c
fix using uninit'd 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-2007 Dana 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 static void measure_font(const RrInstance *inst, RrFont *f)
35 {
36 PangoFontMetrics *metrics;
37 gchar *locale, *p;
38
39 /* get the default language from the locale
40 (based on gtk_get_default_language in gtkmain.c) */
41 locale = g_strdup(setlocale(LC_CTYPE, NULL));
42 if ((p = strchr(locale, '.'))) *p = '\0'; /* strip off the . */
43 if ((p = strchr(locale, '@'))) *p = '\0'; /* strip off the @ */
44
45 /* measure the ascent and descent */
46 metrics = pango_context_get_metrics(inst->pango, f->font_desc,
47 pango_language_from_string(locale));
48 f->ascent = pango_font_metrics_get_ascent(metrics);
49 f->descent = pango_font_metrics_get_descent(metrics);
50 pango_font_metrics_unref(metrics);
51
52 g_free(locale);
53 }
54
55 RrFont *RrFontOpen(const RrInstance *inst, const gchar *name, gint size,
56 RrFontWeight weight, RrFontSlant slant)
57 {
58 RrFont *out;
59 PangoWeight pweight;
60 PangoStyle pstyle;
61 PangoAttrList *attrlist;
62
63 out = g_new(RrFont, 1);
64 out->inst = inst;
65 out->ref = 1;
66 out->font_desc = pango_font_description_new();
67 out->layout = pango_layout_new(inst->pango);
68 out->shortcut_underline = pango_attr_underline_new(PANGO_UNDERLINE_LOW);
69 out->shortcut_underline->start_index = 0;
70 out->shortcut_underline->end_index = 0;
71
72 attrlist = pango_attr_list_new();
73 /* shortcut_underline is owned by the attrlist */
74 pango_attr_list_insert(attrlist, out->shortcut_underline);
75 /* the attributes are owned by the layout */
76 pango_layout_set_attributes(out->layout, attrlist);
77 pango_attr_list_unref(attrlist);
78
79 switch (weight) {
80 case RR_FONTWEIGHT_LIGHT: pweight = PANGO_WEIGHT_LIGHT; break;
81 case RR_FONTWEIGHT_NORMAL: pweight = PANGO_WEIGHT_NORMAL; break;
82 case RR_FONTWEIGHT_SEMIBOLD: pweight = PANGO_WEIGHT_SEMIBOLD; break;
83 case RR_FONTWEIGHT_BOLD: pweight = PANGO_WEIGHT_BOLD; break;
84 case RR_FONTWEIGHT_ULTRABOLD: pweight = PANGO_WEIGHT_ULTRABOLD; break;
85 default: g_assert_not_reached();
86 }
87
88 switch (slant) {
89 case RR_FONTSLANT_NORMAL: pstyle = PANGO_STYLE_NORMAL; break;
90 case RR_FONTSLANT_ITALIC: pstyle = PANGO_STYLE_ITALIC; break;
91 case RR_FONTSLANT_OBLIQUE: pstyle = PANGO_STYLE_OBLIQUE; break;
92 default: g_assert_not_reached();
93 }
94
95 /* setup the font */
96 pango_font_description_set_family(out->font_desc, name);
97 pango_font_description_set_weight(out->font_desc, pweight);
98 pango_font_description_set_style(out->font_desc, pstyle);
99 pango_font_description_set_size(out->font_desc, size * PANGO_SCALE);
100
101 /* setup the layout */
102 pango_layout_set_font_description(out->layout, out->font_desc);
103 pango_layout_set_single_paragraph_mode(out->layout, TRUE);
104 pango_layout_set_ellipsize(out->layout, PANGO_ELLIPSIZE_MIDDLE);
105
106 /* get the ascent and descent */
107 measure_font(inst, out);
108
109 return out;
110 }
111
112 RrFont *RrFontOpenDefault(const RrInstance *inst)
113 {
114 return RrFontOpen(inst, RrDefaultFontFamily, RrDefaultFontSize,
115 RrDefaultFontWeight, RrDefaultFontSlant);
116 }
117
118 void RrFontRef(RrFont *f)
119 {
120 ++f->ref;
121 }
122
123 void RrFontClose(RrFont *f)
124 {
125 if (f) {
126 if (--f->ref < 1) {
127 g_object_unref(f->layout);
128 pango_font_description_free(f->font_desc);
129 g_free(f);
130 }
131 }
132 }
133
134 static void font_measure_full(const RrFont *f, const gchar *str,
135 gint *x, gint *y, gint shadow_x, gint shadow_y)
136 {
137 PangoRectangle rect;
138
139 pango_layout_set_text(f->layout, str, -1);
140 pango_layout_set_width(f->layout, -1);
141 pango_layout_get_pixel_extents(f->layout, NULL, &rect);
142 *x = rect.width + ABS(shadow_x) + 4 /* we put a 2 px edge on each side */;
143 *y = rect.height + ABS(shadow_y);
144 }
145
146 RrSize *RrFontMeasureString(const RrFont *f, const gchar *str,
147 gint shadow_x, gint shadow_y)
148 {
149 RrSize *size;
150 size = g_new(RrSize, 1);
151 font_measure_full(f, str, &size->width, &size->height, shadow_x, shadow_y);
152 return size;
153 }
154
155 gint RrFontHeight(const RrFont *f, gint shadow_y)
156 {
157 return (f->ascent + f->descent) / PANGO_SCALE + ABS(shadow_y);
158 }
159
160 static inline int font_calculate_baseline(RrFont *f, gint height)
161 {
162 /* For my own reference:
163 * _________
164 * ^space/2 ^height ^baseline
165 * v_________|_ |
166 * | ^ascent | _ _
167 * | | | | |_ _____ _| |_ _ _
168 * | | | | _/ -_) \ / _| || |
169 * | v_________v \__\___/_\_\\__|\_, |
170 * | ^descent |__/
171 * __________|_v
172 * ^space/2 |
173 * V_________v
174 */
175 return (((height * PANGO_SCALE) /* height of the space in pango units */
176 - (f->ascent + f->descent)) /* minus space taken up by text */
177 / 2 /* divided by two -> half of the empty space (this is the top
178 of the text) */
179 + f->ascent) /* now move down to the baseline */
180 / PANGO_SCALE; /* back to pixels */
181 }
182
183 void RrFontDraw(XftDraw *d, RrTextureText *t, RrRect *area)
184 {
185 gint x,y,w,h;
186 XftColor c;
187 gint mw;
188 PangoRectangle rect;
189 PangoAttrList *attrlist;
190
191 /* center the text vertically
192 We do this centering based on the 'baseline' since different fonts have
193 different top edges. It looks bad when the whole string is moved when 1
194 character from a non-default language is included in the string */
195 y = area->y +
196 font_calculate_baseline(t->font, area->height);
197
198 /* the +2 and -4 leave a small blank edge on the sides */
199 x = area->x + 2;
200 w = area->width - 4;
201 h = area->height;
202
203 pango_layout_set_text(t->font->layout, t->string, -1);
204 pango_layout_set_width(t->font->layout, w * PANGO_SCALE);
205
206 /* * * end of setting up the layout * * */
207
208 pango_layout_get_pixel_extents(t->font->layout, NULL, &rect);
209 mw = rect.width;
210
211 /* pango_layout_set_alignment doesn't work with
212 pango_xft_render_layout_line */
213 switch (t->justify) {
214 case RR_JUSTIFY_LEFT:
215 break;
216 case RR_JUSTIFY_RIGHT:
217 x += (w - mw);
218 break;
219 case RR_JUSTIFY_CENTER:
220 x += (w - mw) / 2;
221 break;
222 }
223
224 if (t->shadow_offset_x || t->shadow_offset_y) {
225 c.color.red = t->shadow_color->r | t->shadow_color->r << 8;
226 c.color.green = t->shadow_color->g | t->shadow_color->g << 8;
227 c.color.blue = t->shadow_color->b | t->shadow_color->b << 8;
228 c.color.alpha = 0xffff * t->shadow_alpha / 255;
229 c.pixel = t->shadow_color->pixel;
230
231 /* see below... */
232 pango_xft_render_layout_line
233 (d, &c, pango_layout_get_line(t->font->layout, 0),
234 (x + t->shadow_offset_x) * PANGO_SCALE,
235 (y + t->shadow_offset_y) * PANGO_SCALE);
236 }
237
238 c.color.red = t->color->r | t->color->r << 8;
239 c.color.green = t->color->g | t->color->g << 8;
240 c.color.blue = t->color->b | t->color->b << 8;
241 c.color.alpha = 0xff | 0xff << 8; /* fully opaque text */
242 c.pixel = t->color->pixel;
243
244 if (t->shortcut) {
245 const gchar *c = t->string + t->shortcut_pos;
246
247 t->font->shortcut_underline->start_index = t->shortcut_pos;
248 t->font->shortcut_underline->end_index = t->shortcut_pos +
249 (g_utf8_next_char(c) - c);
250
251 /* the attributes are owned by the layout.
252 re-add the attributes to the layout after changing the
253 start and end index */
254 attrlist = pango_layout_get_attributes(t->font->layout);
255 pango_attr_list_ref(attrlist);
256 pango_layout_set_attributes(t->font->layout, attrlist);
257 pango_attr_list_unref(attrlist);
258 }
259
260 /* layout_line() uses y to specify the baseline
261 The line doesn't need to be freed, it's a part of the layout */
262 pango_xft_render_layout_line
263 (d, &c, pango_layout_get_line(t->font->layout, 0),
264 x * PANGO_SCALE, y * PANGO_SCALE);
265
266 if (t->shortcut) {
267 t->font->shortcut_underline->start_index = 0;
268 t->font->shortcut_underline->end_index = 0;
269 /* the attributes are owned by the layout.
270 re-add the attributes to the layout after changing the
271 start and end index */
272 attrlist = pango_layout_get_attributes(t->font->layout);
273 pango_attr_list_ref(attrlist);
274 pango_layout_set_attributes(t->font->layout, attrlist);
275 pango_attr_list_unref(attrlist);
276 }
277 }
This page took 0.046684 seconds and 5 git commands to generate.