WMCreateFont: Add missing wfree()'s
[wmaker-crm.git] / WINGs / wfont.c
blobceab0947842e1b1a5a4ea3ea14d6e4f43a432263
2 #include <stdlib.h>
4 #include "wconfig.h"
6 #include "WINGsP.h"
8 #include <wraster.h>
9 #include <assert.h>
10 #include <X11/Xlocale.h>
12 #include <X11/Xft/Xft.h>
13 #include <fontconfig/fontconfig.h>
16 #define DEFAULT_FONT "sans serif:pixelsize=12"
18 #define DEFAULT_SIZE WINGsConfiguration.defaultFontSize
21 static FcPattern*
22 xlfdToFcPattern(char *xlfd)
24 FcPattern *pattern;
25 char *fname, *ptr;
27 /* Just skip old font names that contain %d in them.
28 * We don't support that anymore. */
29 if (strchr(xlfd, '%')!=NULL)
30 return FcNameParse((FcChar8*)DEFAULT_FONT);
32 fname= wstrdup(xlfd);
33 if ((ptr = strchr(fname, ','))) {
34 *ptr = 0;
36 pattern = XftXlfdParse(fname, False, False);
37 wfree(fname);
39 if (!pattern) {
40 wwarning(_("invalid font: %s. Trying '%s'"), xlfd, DEFAULT_FONT);
41 pattern = FcNameParse((FcChar8*)DEFAULT_FONT);
44 return pattern;
48 static char*
49 xlfdToFcName(char *xlfd)
51 FcPattern *pattern;
52 char *fname;
54 pattern = xlfdToFcPattern(xlfd);
55 fname = (char*)FcNameUnparse(pattern);
56 FcPatternDestroy(pattern);
58 return fname;
62 static Bool
63 hasProperty(FcPattern *pattern, const char *property)
65 FcValue val;
67 if (FcPatternGet(pattern, property, 0, &val)==FcResultMatch) {
68 return True;
71 return False;
75 static Bool
76 hasPropertyWithStringValue(FcPattern *pattern, const char *object, char *value)
78 FcChar8 *str;
79 int id;
81 if (!value || value[0]==0)
82 return True;
84 id = 0;
85 while (FcPatternGetString(pattern, object, id, &str)==FcResultMatch) {
86 if (strcasecmp(value, (char*)str) == 0) {
87 return True;
89 id++;
92 return False;
96 static char*
97 makeFontOfSize(char *font, int size, char *fallback)
99 FcPattern *pattern;
100 char *result;
102 if (font[0]=='-') {
103 pattern = xlfdToFcPattern(font);
104 } else {
105 pattern = FcNameParse((FcChar8*)font);
108 /*FcPatternPrint(pattern);*/
110 if (size > 0) {
111 FcPatternDel(pattern, FC_PIXEL_SIZE);
112 FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)size);
113 } else if (size==0 && !hasProperty(pattern, "size") &&
114 !hasProperty(pattern, FC_PIXEL_SIZE)) {
115 FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)DEFAULT_SIZE);
118 if (fallback && !hasPropertyWithStringValue(pattern, FC_FAMILY, fallback)) {
119 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)fallback);
122 /*FcPatternPrint(pattern);*/
124 result = (char*)FcNameUnparse(pattern);
125 FcPatternDestroy(pattern);
127 return result;
131 WMFont*
132 WMCreateFont(WMScreen *scrPtr, char *fontName)
134 Display *display = scrPtr->display;
135 WMFont *font;
136 char *fname;
138 if (fontName[0]=='-'){
139 fname = xlfdToFcName(fontName);
140 } else {
141 fname = wstrdup(fontName);
144 if (!WINGsConfiguration.antialiasedText && !strstr(fname, ":antialias=")) {
145 fname = wstrappend(fname, ":antialias=false");
148 font = WMHashGet(scrPtr->fontCache, fname);
149 if (font) {
150 WMRetainFont(font);
151 wfree(fname);
152 return font;
155 font = wmalloc(sizeof(WMFont));
156 memset(font, 0, sizeof(WMFont));
158 font->screen = scrPtr;
160 font->font = XftFontOpenName(display, scrPtr->screen, fname);
161 if (!font->font) {
162 printf("Font named %s doesn't exist.\n", fname);
163 printf("Please check your system configuration.\n");
164 printf("Will try default font %s.\n", DEFAULT_FONT);
165 font->font = XftFontOpenName(display, scrPtr->screen, DEFAULT_FONT);
166 if (!font->font) {
167 printf("Unrecoverable font error! I must die!\n");
168 wfree(font);
169 wfree(fname);
170 exit(1);
171 } else
172 printf("Default font loading succeded.\n");
175 font->height = font->font->ascent+font->font->descent;
176 font->y = font->font->ascent;
178 font->refCount = 1;
180 font->name = fname;
182 assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL);
184 return font;
188 WMFont*
189 WMRetainFont(WMFont *font)
191 wassertrv(font!=NULL, NULL);
193 font->refCount++;
195 return font;
199 void
200 WMReleaseFont(WMFont *font)
202 wassertr(font!=NULL);
204 font->refCount--;
205 if (font->refCount < 1) {
206 XftFontClose(font->screen->display, font->font);
207 if (font->name) {
208 WMHashRemove(font->screen->fontCache, font->name);
209 wfree(font->name);
211 wfree(font);
216 Bool
217 WMIsAntialiasingEnabled(WMScreen *scrPtr)
219 return scrPtr->antialiasedText;
223 unsigned int
224 WMFontHeight(WMFont *font)
226 wassertrv(font!=NULL, 0);
228 return font->height;
232 char*
233 WMGetFontName(WMFont *font)
235 wassertrv(font!=NULL, NULL);
237 return font->name;
241 WMFont*
242 WMDefaultSystemFont(WMScreen *scrPtr)
244 return WMRetainFont(scrPtr->normalFont);
248 WMFont*
249 WMDefaultBoldSystemFont(WMScreen *scrPtr)
251 return WMRetainFont(scrPtr->boldFont);
255 WMFont*
256 WMSystemFontOfSize(WMScreen *scrPtr, int size)
258 WMFont *font;
259 char *fontSpec;
261 fontSpec = makeFontOfSize(WINGsConfiguration.systemFont, size, NULL);
263 font = WMCreateFont(scrPtr, fontSpec);
265 if (!font) {
266 wwarning(_("could not load font: %s."), fontSpec);
269 wfree(fontSpec);
271 return font;
275 WMFont*
276 WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
278 WMFont *font;
279 char *fontSpec;
281 fontSpec = makeFontOfSize(WINGsConfiguration.boldSystemFont, size, NULL);
283 font = WMCreateFont(scrPtr, fontSpec);
285 if (!font) {
286 wwarning(_("could not load font: %s."), fontSpec);
289 wfree(fontSpec);
291 return font;
296 WMWidthOfString(WMFont *font, char *text, int length)
298 XGlyphInfo extents;
300 wassertrv(font!=NULL && text!=NULL, 0);
302 XftTextExtentsUtf8(font->screen->display, font->font,
303 (XftChar8 *)text, length, &extents);
305 return extents.xOff; /* don't ask :P */
310 void
311 WMDrawString(WMScreen *scr, Drawable d, WMColor *color, WMFont *font,
312 int x, int y, char *text, int length)
314 XftColor xftcolor;
316 wassertr(font!=NULL);
318 xftcolor.color.red = color->color.red;
319 xftcolor.color.green = color->color.green;
320 xftcolor.color.blue = color->color.blue;
321 xftcolor.color.alpha = color->alpha;;
322 xftcolor.pixel = W_PIXEL(color);
324 XftDrawChange(scr->xftdraw, d);
326 XftDrawStringUtf8(scr->xftdraw, &xftcolor, font->font,
327 x, y + font->y, (XftChar8*)text, length);
331 void
332 WMDrawImageString(WMScreen *scr, Drawable d, WMColor *color, WMColor *background,
333 WMFont *font, int x, int y, char *text, int length)
335 XftColor textColor;
336 XftColor bgColor;
338 wassertr(font!=NULL);
340 textColor.color.red = color->color.red;
341 textColor.color.green = color->color.green;
342 textColor.color.blue = color->color.blue;
343 textColor.color.alpha = color->alpha;;
344 textColor.pixel = W_PIXEL(color);
346 bgColor.color.red = background->color.red;
347 bgColor.color.green = background->color.green;
348 bgColor.color.blue = background->color.blue;
349 bgColor.color.alpha = background->alpha;;
350 bgColor.pixel = W_PIXEL(background);
352 XftDrawChange(scr->xftdraw, d);
354 XftDrawRect(scr->xftdraw, &bgColor, x, y,
355 WMWidthOfString(font, text, length),
356 font->height);
358 XftDrawStringUtf8(scr->xftdraw, &textColor, font->font,
359 x, y + font->y, (XftChar8*)text, length);
363 WMFont*
364 WMCopyFontWithStyle(WMScreen *scrPtr, WMFont *font, WMFontStyle style)
366 FcPattern *pattern;
367 WMFont *copy;
368 char *name;
370 if (!font)
371 return NULL;
373 /* It's enough to add italic to slant, even if the font has no italic
374 * variant, but only oblique. This is because fontconfig will actually
375 * return the closest match font to what we requested which is the
376 * oblique font. Same goes for using bold for weight.
378 pattern = FcNameParse((FcChar8*)WMGetFontName(font));
379 switch (style) {
380 case WFSNormal:
381 FcPatternDel(pattern, FC_WEIGHT);
382 FcPatternDel(pattern, FC_SLANT);
383 break;
384 case WFSBold:
385 FcPatternDel(pattern, FC_WEIGHT);
386 FcPatternAddString(pattern, FC_WEIGHT, (FcChar8*)"bold");
387 break;
388 case WFSItalic:
389 FcPatternDel(pattern, FC_SLANT);
390 FcPatternAddString(pattern, FC_SLANT, (FcChar8*)"italic");
391 break;
392 case WFSBoldItalic:
393 FcPatternDel(pattern, FC_WEIGHT);
394 FcPatternDel(pattern, FC_SLANT);
395 FcPatternAddString(pattern, FC_WEIGHT, (FcChar8*)"bold");
396 FcPatternAddString(pattern, FC_SLANT, (FcChar8*)"italic");
397 break;
400 name = (char*)FcNameUnparse(pattern);
401 copy = WMCreateFont(scrPtr, name);
402 FcPatternDestroy(pattern);
403 wfree(name);
405 return copy;