Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / wfont.c
1
2 #include <stdlib.h>
3
4 #include "wconfig.h"
5
6 #include "WINGsP.h"
7
8 #include <wraster.h>
9 #include <assert.h>
10 #include <X11/Xlocale.h>
11
12 #include <X11/Xft/Xft.h>
13 #include <fontconfig/fontconfig.h>
14
15 #define DEFAULT_FONT "sans serif:pixelsize=12"
16
17 #define DEFAULT_SIZE WINGsConfiguration.defaultFontSize
18
19 static FcPattern *xlfdToFcPattern(char *xlfd)
20 {
21         FcPattern *pattern;
22         char *fname, *ptr;
23
24         /* Just skip old font names that contain %d in them.
25          * We don't support that anymore. */
26         if (strchr(xlfd, '%') != NULL)
27                 return FcNameParse((FcChar8 *) DEFAULT_FONT);
28
29         fname = wstrdup(xlfd);
30         if ((ptr = strchr(fname, ','))) {
31                 *ptr = 0;
32         }
33         pattern = XftXlfdParse(fname, False, False);
34         wfree(fname);
35
36         if (!pattern) {
37                 wwarning(_("invalid font: %s. Trying '%s'"), xlfd, DEFAULT_FONT);
38                 pattern = FcNameParse((FcChar8 *) DEFAULT_FONT);
39         }
40
41         return pattern;
42 }
43
44 static char *xlfdToFcName(char *xlfd)
45 {
46         FcPattern *pattern;
47         char *fname;
48
49         pattern = xlfdToFcPattern(xlfd);
50         fname = (char *)FcNameUnparse(pattern);
51         FcPatternDestroy(pattern);
52
53         return fname;
54 }
55
56 static Bool hasProperty(FcPattern * pattern, const char *property)
57 {
58         FcValue val;
59
60         if (FcPatternGet(pattern, property, 0, &val) == FcResultMatch) {
61                 return True;
62         }
63
64         return False;
65 }
66
67 static Bool hasPropertyWithStringValue(FcPattern * pattern, const char *object, char *value)
68 {
69         FcChar8 *str;
70         int id;
71
72         if (!value || value[0] == 0)
73                 return True;
74
75         id = 0;
76         while (FcPatternGetString(pattern, object, id, &str) == FcResultMatch) {
77                 if (strcasecmp(value, (char *)str) == 0) {
78                         return True;
79                 }
80                 id++;
81         }
82
83         return False;
84 }
85
86 static char *makeFontOfSize(char *font, int size, char *fallback)
87 {
88         FcPattern *pattern;
89         char *result;
90
91         if (font[0] == '-') {
92                 pattern = xlfdToFcPattern(font);
93         } else {
94                 pattern = FcNameParse((FcChar8 *) font);
95         }
96
97         /*FcPatternPrint(pattern); */
98
99         if (size > 0) {
100                 FcPatternDel(pattern, FC_PIXEL_SIZE);
101                 FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)size);
102         } else if (size == 0 && !hasProperty(pattern, "size") && !hasProperty(pattern, FC_PIXEL_SIZE)) {
103                 FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)DEFAULT_SIZE);
104         }
105
106         if (fallback && !hasPropertyWithStringValue(pattern, FC_FAMILY, fallback)) {
107                 FcPatternAddString(pattern, FC_FAMILY, (FcChar8 *) fallback);
108         }
109
110         /*FcPatternPrint(pattern); */
111
112         result = (char *)FcNameUnparse(pattern);
113         FcPatternDestroy(pattern);
114
115         return result;
116 }
117
118 WMFont *WMCreateFont(WMScreen * scrPtr, char *fontName)
119 {
120         Display *display = scrPtr->display;
121         WMFont *font;
122         char *fname;
123
124         if (fontName[0] == '-') {
125                 fname = xlfdToFcName(fontName);
126         } else {
127                 fname = wstrdup(fontName);
128         }
129
130         if (!WINGsConfiguration.antialiasedText && !strstr(fname, ":antialias=")) {
131                 fname = wstrappend(fname, ":antialias=false");
132         }
133
134         font = WMHashGet(scrPtr->fontCache, fname);
135         if (font) {
136                 WMRetainFont(font);
137                 wfree(fname);
138                 return font;
139         }
140
141         font = wmalloc(sizeof(WMFont));
142         memset(font, 0, sizeof(WMFont));
143
144         font->screen = scrPtr;
145
146         font->font = XftFontOpenName(display, scrPtr->screen, fname);
147         if (!font->font) {
148                 printf("Font named %s doesn't exist.\n", fname);
149                 printf("Please check your system configuration.\n");
150                 printf("Will try default font %s.\n", DEFAULT_FONT);
151                 font->font = XftFontOpenName(display, scrPtr->screen, DEFAULT_FONT);
152                 if (!font->font) {
153                         printf("Unrecoverable font error! I must die!\n");
154                         wfree(font);
155                         wfree(fname);
156                         exit(1);
157                 } else
158                         printf("Default font loading succeded.\n");
159         }
160
161         font->height = font->font->ascent + font->font->descent;
162         font->y = font->font->ascent;
163
164         font->refCount = 1;
165
166         font->name = fname;
167
168         assert(WMHashInsert(scrPtr->fontCache, font->name, font) == NULL);
169
170         return font;
171 }
172
173 WMFont *WMRetainFont(WMFont * font)
174 {
175         wassertrv(font != NULL, NULL);
176
177         font->refCount++;
178
179         return font;
180 }
181
182 void WMReleaseFont(WMFont * font)
183 {
184         wassertr(font != NULL);
185
186         font->refCount--;
187         if (font->refCount < 1) {
188                 XftFontClose(font->screen->display, font->font);
189                 if (font->name) {
190                         WMHashRemove(font->screen->fontCache, font->name);
191                         wfree(font->name);
192                 }
193                 wfree(font);
194         }
195 }
196
197 Bool WMIsAntialiasingEnabled(WMScreen * scrPtr)
198 {
199         return scrPtr->antialiasedText;
200 }
201
202 unsigned int WMFontHeight(WMFont * font)
203 {
204         wassertrv(font != NULL, 0);
205
206         return font->height;
207 }
208
209 char *WMGetFontName(WMFont * font)
210 {
211         wassertrv(font != NULL, NULL);
212
213         return font->name;
214 }
215
216 WMFont *WMDefaultSystemFont(WMScreen * scrPtr)
217 {
218         return WMRetainFont(scrPtr->normalFont);
219 }
220
221 WMFont *WMDefaultBoldSystemFont(WMScreen * scrPtr)
222 {
223         return WMRetainFont(scrPtr->boldFont);
224 }
225
226 WMFont *WMSystemFontOfSize(WMScreen * scrPtr, int size)
227 {
228         WMFont *font;
229         char *fontSpec;
230
231         fontSpec = makeFontOfSize(WINGsConfiguration.systemFont, size, NULL);
232
233         font = WMCreateFont(scrPtr, fontSpec);
234
235         if (!font) {
236                 wwarning(_("could not load font: %s."), fontSpec);
237         }
238
239         wfree(fontSpec);
240
241         return font;
242 }
243
244 WMFont *WMBoldSystemFontOfSize(WMScreen * scrPtr, int size)
245 {
246         WMFont *font;
247         char *fontSpec;
248
249         fontSpec = makeFontOfSize(WINGsConfiguration.boldSystemFont, size, NULL);
250
251         font = WMCreateFont(scrPtr, fontSpec);
252
253         if (!font) {
254                 wwarning(_("could not load font: %s."), fontSpec);
255         }
256
257         wfree(fontSpec);
258
259         return font;
260 }
261
262 int WMWidthOfString(WMFont * font, char *text, int length)
263 {
264         XGlyphInfo extents;
265
266         wassertrv(font != NULL && text != NULL, 0);
267
268         XftTextExtentsUtf8(font->screen->display, font->font, (XftChar8 *) text, length, &extents);
269
270         return extents.xOff;    /* don't ask :P */
271 }
272
273 void WMDrawString(WMScreen * scr, Drawable d, WMColor * color, WMFont * font, int x, int y, char *text, int length)
274 {
275         XftColor xftcolor;
276
277         wassertr(font != NULL);
278
279         xftcolor.color.red = color->color.red;
280         xftcolor.color.green = color->color.green;
281         xftcolor.color.blue = color->color.blue;
282         xftcolor.color.alpha = color->alpha;;
283         xftcolor.pixel = W_PIXEL(color);
284
285         XftDrawChange(scr->xftdraw, d);
286
287         XftDrawStringUtf8(scr->xftdraw, &xftcolor, font->font, x, y + font->y, (XftChar8 *) text, length);
288 }
289
290 void
291 WMDrawImageString(WMScreen * scr, Drawable d, WMColor * color, WMColor * background,
292                   WMFont * font, int x, int y, char *text, int length)
293 {
294         XftColor textColor;
295         XftColor bgColor;
296
297         wassertr(font != NULL);
298
299         textColor.color.red = color->color.red;
300         textColor.color.green = color->color.green;
301         textColor.color.blue = color->color.blue;
302         textColor.color.alpha = color->alpha;;
303         textColor.pixel = W_PIXEL(color);
304
305         bgColor.color.red = background->color.red;
306         bgColor.color.green = background->color.green;
307         bgColor.color.blue = background->color.blue;
308         bgColor.color.alpha = background->alpha;;
309         bgColor.pixel = W_PIXEL(background);
310
311         XftDrawChange(scr->xftdraw, d);
312
313         XftDrawRect(scr->xftdraw, &bgColor, x, y, WMWidthOfString(font, text, length), font->height);
314
315         XftDrawStringUtf8(scr->xftdraw, &textColor, font->font, x, y + font->y, (XftChar8 *) text, length);
316 }
317
318 WMFont *WMCopyFontWithStyle(WMScreen * scrPtr, WMFont * font, WMFontStyle style)
319 {
320         FcPattern *pattern;
321         WMFont *copy;
322         char *name;
323
324         if (!font)
325                 return NULL;
326
327         /* It's enough to add italic to slant, even if the font has no italic
328          * variant, but only oblique. This is because fontconfig will actually
329          * return the closest match font to what we requested which is the
330          * oblique font. Same goes for using bold for weight.
331          */
332         pattern = FcNameParse((FcChar8 *) WMGetFontName(font));
333         switch (style) {
334         case WFSNormal:
335                 FcPatternDel(pattern, FC_WEIGHT);
336                 FcPatternDel(pattern, FC_SLANT);
337                 break;
338         case WFSBold:
339                 FcPatternDel(pattern, FC_WEIGHT);
340                 FcPatternAddString(pattern, FC_WEIGHT, (FcChar8 *) "bold");
341                 break;
342         case WFSItalic:
343                 FcPatternDel(pattern, FC_SLANT);
344                 FcPatternAddString(pattern, FC_SLANT, (FcChar8 *) "italic");
345                 break;
346         case WFSBoldItalic:
347                 FcPatternDel(pattern, FC_WEIGHT);
348                 FcPatternDel(pattern, FC_SLANT);
349                 FcPatternAddString(pattern, FC_WEIGHT, (FcChar8 *) "bold");
350                 FcPatternAddString(pattern, FC_SLANT, (FcChar8 *) "italic");
351                 break;
352         }
353
354         name = (char *)FcNameUnparse(pattern);
355         copy = WMCreateFont(scrPtr, name);
356         FcPatternDestroy(pattern);
357         wfree(name);
358
359         return copy;
360 }