Icon creation in only one function
[wmaker-crm.git] / WINGs / wfont.c
blob62dd7d347a328bb3ee28b5262e168350e9023a22
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>
15 #define DEFAULT_FONT "sans serif:pixelsize=12"
17 #define DEFAULT_SIZE WINGsConfiguration.defaultFontSize
19 static FcPattern *xlfdToFcPattern(char *xlfd)
21 FcPattern *pattern;
22 char *fname, *ptr;
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);
29 fname = wstrdup(xlfd);
30 if ((ptr = strchr(fname, ','))) {
31 *ptr = 0;
33 pattern = XftXlfdParse(fname, False, False);
34 wfree(fname);
36 if (!pattern) {
37 wwarning(_("invalid font: %s. Trying '%s'"), xlfd, DEFAULT_FONT);
38 pattern = FcNameParse((FcChar8 *) DEFAULT_FONT);
41 return pattern;
44 static char *xlfdToFcName(char *xlfd)
46 FcPattern *pattern;
47 char *fname;
49 pattern = xlfdToFcPattern(xlfd);
50 fname = (char *)FcNameUnparse(pattern);
51 FcPatternDestroy(pattern);
53 return fname;
56 static Bool hasProperty(FcPattern * pattern, const char *property)
58 FcValue val;
60 if (FcPatternGet(pattern, property, 0, &val) == FcResultMatch) {
61 return True;
64 return False;
67 static Bool hasPropertyWithStringValue(FcPattern * pattern, const char *object, char *value)
69 FcChar8 *str;
70 int id;
72 if (!value || value[0] == 0)
73 return True;
75 id = 0;
76 while (FcPatternGetString(pattern, object, id, &str) == FcResultMatch) {
77 if (strcasecmp(value, (char *)str) == 0) {
78 return True;
80 id++;
83 return False;
86 static char *makeFontOfSize(char *font, int size, char *fallback)
88 FcPattern *pattern;
89 char *result;
91 if (font[0] == '-') {
92 pattern = xlfdToFcPattern(font);
93 } else {
94 pattern = FcNameParse((FcChar8 *) font);
97 /*FcPatternPrint(pattern); */
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);
106 if (fallback && !hasPropertyWithStringValue(pattern, FC_FAMILY, fallback)) {
107 FcPatternAddString(pattern, FC_FAMILY, (FcChar8 *) fallback);
110 /*FcPatternPrint(pattern); */
112 result = (char *)FcNameUnparse(pattern);
113 FcPatternDestroy(pattern);
115 return result;
118 WMFont *WMCreateFont(WMScreen * scrPtr, char *fontName)
120 Display *display = scrPtr->display;
121 WMFont *font;
122 char *fname;
124 if (fontName[0] == '-') {
125 fname = xlfdToFcName(fontName);
126 } else {
127 fname = wstrdup(fontName);
130 if (!WINGsConfiguration.antialiasedText && !strstr(fname, ":antialias=")) {
131 fname = wstrappend(fname, ":antialias=false");
134 font = WMHashGet(scrPtr->fontCache, fname);
135 if (font) {
136 WMRetainFont(font);
137 wfree(fname);
138 return font;
141 font = wmalloc(sizeof(WMFont));
143 font->screen = scrPtr;
145 font->font = XftFontOpenName(display, scrPtr->screen, fname);
146 if (!font->font) {
147 wfree(font);
148 wfree(fname);
149 return NULL;
152 font->height = font->font->ascent + font->font->descent;
153 font->y = font->font->ascent;
155 font->refCount = 1;
157 font->name = fname;
159 assert(WMHashInsert(scrPtr->fontCache, font->name, font) == NULL);
161 return font;
164 WMFont *WMRetainFont(WMFont * font)
166 wassertrv(font != NULL, NULL);
168 font->refCount++;
170 return font;
173 void WMReleaseFont(WMFont * font)
175 wassertr(font != NULL);
177 font->refCount--;
178 if (font->refCount < 1) {
179 XftFontClose(font->screen->display, font->font);
180 if (font->name) {
181 WMHashRemove(font->screen->fontCache, font->name);
182 wfree(font->name);
184 wfree(font);
188 Bool WMIsAntialiasingEnabled(WMScreen * scrPtr)
190 return scrPtr->antialiasedText;
193 unsigned int WMFontHeight(WMFont * font)
195 wassertrv(font != NULL, 0);
197 return font->height;
200 char *WMGetFontName(WMFont * font)
202 wassertrv(font != NULL, NULL);
204 return font->name;
207 WMFont *WMDefaultSystemFont(WMScreen * scrPtr)
209 return WMRetainFont(scrPtr->normalFont);
212 WMFont *WMDefaultBoldSystemFont(WMScreen * scrPtr)
214 return WMRetainFont(scrPtr->boldFont);
217 WMFont *WMSystemFontOfSize(WMScreen * scrPtr, int size)
219 WMFont *font;
220 char *fontSpec;
222 fontSpec = makeFontOfSize(WINGsConfiguration.systemFont, size, NULL);
224 font = WMCreateFont(scrPtr, fontSpec);
226 if (!font) {
227 wwarning(_("could not load font: %s."), fontSpec);
230 wfree(fontSpec);
232 return font;
235 WMFont *WMBoldSystemFontOfSize(WMScreen * scrPtr, int size)
237 WMFont *font;
238 char *fontSpec;
240 fontSpec = makeFontOfSize(WINGsConfiguration.boldSystemFont, size, NULL);
242 font = WMCreateFont(scrPtr, fontSpec);
244 if (!font) {
245 wwarning(_("could not load font: %s."), fontSpec);
248 wfree(fontSpec);
250 return font;
253 int WMWidthOfString(WMFont * font, char *text, int length)
255 XGlyphInfo extents;
257 wassertrv(font != NULL && text != NULL, 0);
259 XftTextExtentsUtf8(font->screen->display, font->font, (XftChar8 *) text, length, &extents);
261 return extents.xOff; /* don't ask :P */
264 void WMDrawString(WMScreen * scr, Drawable d, WMColor * color, WMFont * font, int x, int y, char *text, int length)
266 XftColor xftcolor;
268 wassertr(font != NULL);
270 xftcolor.color.red = color->color.red;
271 xftcolor.color.green = color->color.green;
272 xftcolor.color.blue = color->color.blue;
273 xftcolor.color.alpha = color->alpha;;
274 xftcolor.pixel = W_PIXEL(color);
276 XftDrawChange(scr->xftdraw, d);
278 XftDrawStringUtf8(scr->xftdraw, &xftcolor, font->font, x, y + font->y, (XftChar8 *) text, length);
281 void
282 WMDrawImageString(WMScreen * scr, Drawable d, WMColor * color, WMColor * background,
283 WMFont * font, int x, int y, char *text, int length)
285 XftColor textColor;
286 XftColor bgColor;
288 wassertr(font != NULL);
290 textColor.color.red = color->color.red;
291 textColor.color.green = color->color.green;
292 textColor.color.blue = color->color.blue;
293 textColor.color.alpha = color->alpha;;
294 textColor.pixel = W_PIXEL(color);
296 bgColor.color.red = background->color.red;
297 bgColor.color.green = background->color.green;
298 bgColor.color.blue = background->color.blue;
299 bgColor.color.alpha = background->alpha;;
300 bgColor.pixel = W_PIXEL(background);
302 XftDrawChange(scr->xftdraw, d);
304 XftDrawRect(scr->xftdraw, &bgColor, x, y, WMWidthOfString(font, text, length), font->height);
306 XftDrawStringUtf8(scr->xftdraw, &textColor, font->font, x, y + font->y, (XftChar8 *) text, length);
309 WMFont *WMCopyFontWithStyle(WMScreen * scrPtr, WMFont * font, WMFontStyle style)
311 FcPattern *pattern;
312 WMFont *copy;
313 char *name;
315 if (!font)
316 return NULL;
318 /* It's enough to add italic to slant, even if the font has no italic
319 * variant, but only oblique. This is because fontconfig will actually
320 * return the closest match font to what we requested which is the
321 * oblique font. Same goes for using bold for weight.
323 pattern = FcNameParse((FcChar8 *) WMGetFontName(font));
324 switch (style) {
325 case WFSNormal:
326 FcPatternDel(pattern, FC_WEIGHT);
327 FcPatternDel(pattern, FC_SLANT);
328 break;
329 case WFSBold:
330 FcPatternDel(pattern, FC_WEIGHT);
331 FcPatternAddString(pattern, FC_WEIGHT, (FcChar8 *) "bold");
332 break;
333 case WFSItalic:
334 FcPatternDel(pattern, FC_SLANT);
335 FcPatternAddString(pattern, FC_SLANT, (FcChar8 *) "italic");
336 break;
337 case WFSBoldItalic:
338 FcPatternDel(pattern, FC_WEIGHT);
339 FcPatternDel(pattern, FC_SLANT);
340 FcPatternAddString(pattern, FC_WEIGHT, (FcChar8 *) "bold");
341 FcPatternAddString(pattern, FC_SLANT, (FcChar8 *) "italic");
342 break;
345 name = (char *)FcNameUnparse(pattern);
346 copy = WMCreateFont(scrPtr, name);
347 FcPatternDestroy(pattern);
348 wfree(name);
350 return copy;