- If fonts are specified as xlfd, convert to fc names before creating them.
[wmaker-crm.git] / WINGs / wfont.c
blobae2a3922d2c5755eaf7259e904a6c22e483f8363
2 #include "wconfig.h"
4 #include <X11/Xft/Xft.h>
5 #include <fontconfig/fontconfig.h>
7 #include <stdlib.h>
9 #include "WINGsP.h"
11 #include <wraster.h>
12 #include <assert.h>
13 #include <X11/Xlocale.h>
16 #define DEFAULT_FONT "sans-serif:pixelsize=12"
18 #define DEFAULT_SIZE WINGsConfiguration.defaultFontSize
21 static FcPattern*
22 xlfdToFcPattern(char *xlfd, int size)
24 FcPattern *pattern;
25 char *fname, *ptr;
27 fname = wmalloc(strlen(xlfd) + 20);
28 if (strstr(xlfd, "%d")!=NULL)
29 sprintf(fname, xlfd, size ? size : DEFAULT_SIZE);
30 else
31 strcpy(fname, xlfd);
33 if ((ptr = strchr(fname, ','))) {
34 *ptr = 0;
37 pattern = XftXlfdParse(fname, False, False);
38 wfree(fname);
40 if (!pattern) {
41 wwarning(_("invalid font: %s. Using default %s"), xlfd, DEFAULT_FONT);
42 pattern = FcNameParse(DEFAULT_FONT);
45 return pattern;
49 static char*
50 xlfdToFcName(char *xlfd, int size)
52 FcPattern *pattern;
53 char *fname;
55 pattern = xlfdToFcPattern(xlfd, size);
56 fname = FcNameUnparse(pattern);
57 FcPatternDestroy(pattern);
59 return fname;
63 static Bool
64 hasProperty(FcPattern *pattern, const char *property)
66 FcValue val;
68 if (FcPatternGet(pattern, property, 0, &val)==FcResultMatch) {
69 return True;
72 return False;
76 static Bool
77 hasPropertyWithStringValue(FcPattern *pattern, const char *object, char *value)
79 FcChar8 *str;
80 int id;
82 if (!value || value[0]==0)
83 return True;
85 id = 0;
86 while (FcPatternGetString(pattern, object, id, &str)==FcResultMatch) {
87 if (strcasecmp(value, (char*)str) == 0) {
88 return True;
90 id++;
93 return False;
97 static char*
98 makeFontOfSize(char *font, int size, char *fallback)
100 FcPattern *pattern;
101 char *result;
103 if (font[0]=='-') {
104 pattern = xlfdToFcPattern(font, size);
105 } else {
106 pattern = FcNameParse(font);
109 /*FcPatternPrint(pattern);*/
111 if (size > 0) {
112 FcPatternDel(pattern, FC_PIXEL_SIZE);
113 FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)size);
114 } else if (size==0 && !hasProperty(pattern, "size") &&
115 !hasProperty(pattern, FC_PIXEL_SIZE)) {
116 FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)DEFAULT_SIZE);
119 if (fallback && !hasPropertyWithStringValue(pattern, FC_FAMILY, fallback)) {
120 FcPatternAddString(pattern, FC_FAMILY, fallback);
123 /*FcPatternPrint(pattern);*/
125 result = FcNameUnparse(pattern);
126 FcPatternDestroy(pattern);
128 return result;
132 WMFont*
133 WMCreateFont(WMScreen *scrPtr, char *fontName)
135 Display *display = scrPtr->display;
136 WMFont *font;
137 char *fname;
139 if (fontName[0]=='-'){
140 fname = xlfdToFcName(fontName, 0);
141 } else {
142 fname = wstrdup(fontName);
145 if (!WINGsConfiguration.antialiasedText && !strstr(fname, ":antialias=")) {
146 fname = wstrappend(fname, ":antialias=false");
149 font = WMHashGet(scrPtr->fontCache, fname);
150 if (font) {
151 WMRetainFont(font);
152 wfree(fname);
153 return font;
156 font = wmalloc(sizeof(WMFont));
157 memset(font, 0, sizeof(WMFont));
159 font->screen = scrPtr;
161 font->font = XftFontOpenName(display, scrPtr->screen, fname);
162 if (!font->font) {
163 wfree(font);
164 wfree(fname);
165 return NULL;
167 font->height = font->font->ascent+font->font->descent;
168 font->y = font->font->ascent;
170 font->refCount = 1;
172 font->name = fname;
174 assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL);
176 return font;
180 WMFont*
181 WMRetainFont(WMFont *font)
183 wassertrv(font!=NULL, NULL);
185 font->refCount++;
187 return font;
191 void
192 WMReleaseFont(WMFont *font)
194 wassertr(font!=NULL);
196 font->refCount--;
197 if (font->refCount < 1) {
198 XftFontClose(font->screen->display, font->font);
199 if (font->name) {
200 WMHashRemove(font->screen->fontCache, font->name);
201 wfree(font->name);
203 wfree(font);
208 Bool
209 WMIsAntialiasingEnabled(WMScreen *scrPtr)
211 return scrPtr->antialiasedText;
215 unsigned int
216 WMFontHeight(WMFont *font)
218 wassertrv(font!=NULL, 0);
220 return font->height;
224 char*
225 WMGetFontName(WMFont *font)
227 wassertrv(font!=NULL, NULL);
229 return font->name;
233 WMFont*
234 WMDefaultSystemFont(WMScreen *scrPtr)
236 return WMRetainFont(scrPtr->normalFont);
240 WMFont*
241 WMDefaultBoldSystemFont(WMScreen *scrPtr)
243 return WMRetainFont(scrPtr->boldFont);
247 WMFont*
248 WMSystemFontOfSize(WMScreen *scrPtr, int size)
250 WMFont *font;
251 char *fontSpec;
253 fontSpec = makeFontOfSize(WINGsConfiguration.systemFont, size, NULL);
255 font = WMCreateFont(scrPtr, fontSpec);
257 if (!font) {
258 wwarning(_("could not load font: %s."), fontSpec);
261 wfree(fontSpec);
263 return font;
267 WMFont*
268 WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
270 WMFont *font;
271 char *fontSpec;
273 fontSpec = makeFontOfSize(WINGsConfiguration.boldSystemFont, size, NULL);
275 font = WMCreateFont(scrPtr, fontSpec);
277 if (!font) {
278 wwarning(_("could not load font: %s."), fontSpec);
281 wfree(fontSpec);
283 return font;
288 WMWidthOfString(WMFont *font, char *text, int length)
290 XGlyphInfo extents;
292 wassertrv(font!=NULL && text!=NULL, 0);
294 XftTextExtentsUtf8(font->screen->display, font->font,
295 (XftChar8 *)text, length, &extents);
297 return extents.xOff; /* don't ask :P */
302 void
303 WMDrawString(WMScreen *scr, Drawable d, WMColor *color, WMFont *font,
304 int x, int y, char *text, int length)
306 XftColor xftcolor;
308 wassertr(font!=NULL);
310 xftcolor.color.red = color->color.red;
311 xftcolor.color.green = color->color.green;
312 xftcolor.color.blue = color->color.blue;
313 xftcolor.color.alpha = color->alpha;;
314 xftcolor.pixel = W_PIXEL(color);
316 XftDrawChange(scr->xftdraw, d);
318 XftDrawStringUtf8(scr->xftdraw, &xftcolor, font->font,
319 x, y + font->y, (XftChar8*)text, length);
323 void
324 WMDrawImageString(WMScreen *scr, Drawable d, WMColor *color, WMColor *background,
325 WMFont *font, int x, int y, char *text, int length)
327 XftColor textColor;
328 XftColor bgColor;
330 wassertr(font!=NULL);
332 textColor.color.red = color->color.red;
333 textColor.color.green = color->color.green;
334 textColor.color.blue = color->color.blue;
335 textColor.color.alpha = color->alpha;;
336 textColor.pixel = W_PIXEL(color);
338 bgColor.color.red = background->color.red;
339 bgColor.color.green = background->color.green;
340 bgColor.color.blue = background->color.blue;
341 bgColor.color.alpha = background->alpha;;
342 bgColor.pixel = W_PIXEL(background);
344 XftDrawChange(scr->xftdraw, d);
346 XftDrawRect(scr->xftdraw, &bgColor, x, y,
347 WMWidthOfString(font, text, length),
348 font->height);
350 XftDrawStringUtf8(scr->xftdraw, &textColor, font->font,
351 x, y + font->y, (XftChar8*)text, length);
355 WMFont*
356 WMCopyFontWithStyle(WMScreen *scrPtr, WMFont *font, WMFontStyle style)
358 FcPattern *pattern;
359 WMFont *copy;
360 char *name;
362 if (!font)
363 return NULL;
365 pattern = FcNameParse(WMGetFontName(font));
366 switch (style) {
367 case WFSNormal:
368 FcPatternDel(pattern, FC_WEIGHT);
369 FcPatternDel(pattern, FC_SLANT);
370 //FcPatternAddString(pattern, FC_WEIGHT, "medium");
371 //FcPatternAddString(pattern, FC_WEIGHT, "light");
372 //FcPatternAddString(pattern, FC_SLANT, "roman");
373 break;
374 case WFSBold:
375 FcPatternDel(pattern, FC_WEIGHT);
376 FcPatternAddString(pattern, FC_WEIGHT, "bold");
377 FcPatternAddString(pattern, FC_WEIGHT, "demibold");
378 FcPatternAddString(pattern, FC_WEIGHT, "black");
379 break;
380 case WFSItalic:
381 FcPatternDel(pattern, FC_SLANT);
382 FcPatternAddString(pattern, FC_SLANT, "italic");
383 FcPatternAddString(pattern, FC_SLANT, "oblique");
384 //FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
385 //FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_OBLIQUE);
386 break;
387 case WFSBoldItalic:
388 FcPatternDel(pattern, FC_WEIGHT);
389 FcPatternDel(pattern, FC_SLANT);
390 FcPatternAddString(pattern, FC_WEIGHT, "bold");
391 FcPatternAddString(pattern, FC_WEIGHT, "demibold");
392 FcPatternAddString(pattern, FC_WEIGHT, "black");
393 FcPatternAddString(pattern, FC_SLANT, "italic");
394 FcPatternAddString(pattern, FC_SLANT, "oblique");
395 break;
398 name = FcNameUnparse(pattern);
399 copy = WMCreateFont(scrPtr, name);
400 FcPatternDestroy(pattern);
401 wfree(name);
403 return copy;