Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / wfont.c
Commit [+]AuthorDateLineData
9d2e6ef9 scottc1998-09-29 22:36:29 +00001
9aca0d5f dan2004-10-12 01:34:32 +00002#include <stdlib.h>
17f26077 dan2002-10-09 05:14:28 +00003
e9e1186f dan2004-10-30 06:39:27 +00004#include "wconfig.h"
5
17f26077 dan2002-10-09 05:14:28 +00006#include "WINGsP.h"
7
9d2e6ef9 scottc1998-09-29 22:36:29 +00008#include <wraster.h>
9#include <assert.h>
e410e186 kojima2000-06-17 19:07:57 +000010#include <X11/Xlocale.h>
9d2e6ef9 scottc1998-09-29 22:36:29 +000011
e9e1186f dan2004-10-30 06:39:27 +000012#include <X11/Xft/Xft.h>
13#include <fontconfig/fontconfig.h>
14
d08691d5 dan2004-10-22 22:27:11 +000015#define DEFAULT_FONT "sans serif:pixelsize=12"
08e811aa dan2004-10-22 00:21:51 +000016
9aca0d5f dan2004-10-12 01:34:32 +000017#define DEFAULT_SIZE WINGsConfiguration.defaultFontSize
08225948 dan2003-08-14 01:39:27 +000018
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020019static FcPattern *xlfdToFcPattern(char *xlfd)
08225948 dan2003-08-14 01:39:27 +000020{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020021 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;
08e811aa dan2004-10-22 00:21:51 +000042}
43
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020044static char *xlfdToFcName(char *xlfd)
08e811aa dan2004-10-22 00:21:51 +000045{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020046 FcPattern *pattern;
47 char *fname;
08e811aa dan2004-10-22 00:21:51 +000048
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020049 pattern = xlfdToFcPattern(xlfd);
50 fname = (char *)FcNameUnparse(pattern);
51 FcPatternDestroy(pattern);
08e811aa dan2004-10-22 00:21:51 +000052
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020053 return fname;
08225948 dan2003-08-14 01:39:27 +000054}
55
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020056static Bool hasProperty(FcPattern * pattern, const char *property)
39b9edfd dan2003-08-15 02:58:04 +000057{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020058 FcValue val;
39b9edfd dan2003-08-15 02:58:04 +000059
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020060 if (FcPatternGet(pattern, property, 0, &val) == FcResultMatch) {
61 return True;
62 }
39b9edfd dan2003-08-15 02:58:04 +000063
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020064 return False;
39b9edfd dan2003-08-15 02:58:04 +000065}
66
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020067static Bool hasPropertyWithStringValue(FcPattern * pattern, const char *object, char *value)
39b9edfd dan2003-08-15 02:58:04 +000068{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020069 FcChar8 *str;
70 int id;
39b9edfd dan2003-08-15 02:58:04 +000071
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020072 if (!value || value[0] == 0)
73 return True;
39b9edfd dan2003-08-15 02:58:04 +000074
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020075 id = 0;
76 while (FcPatternGetString(pattern, object, id, &str) == FcResultMatch) {
77 if (strcasecmp(value, (char *)str) == 0) {
78 return True;
79 }
80 id++;
81 }
39b9edfd dan2003-08-15 02:58:04 +000082
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020083 return False;
39b9edfd dan2003-08-15 02:58:04 +000084}
85
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020086static char *makeFontOfSize(char *font, int size, char *fallback)
39b9edfd dan2003-08-15 02:58:04 +000087{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020088 FcPattern *pattern;
89 char *result;
39b9edfd dan2003-08-15 02:58:04 +000090
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020091 if (font[0] == '-') {
92 pattern = xlfdToFcPattern(font);
93 } else {
94 pattern = FcNameParse((FcChar8 *) font);
95 }
9aca0d5f dan2004-10-12 01:34:32 +000096
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020097 /*FcPatternPrint(pattern); */
08e811aa dan2004-10-22 00:21:51 +000098
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020099 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 }
9aca0d5f dan2004-10-12 01:34:32 +0000105
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200106 if (fallback && !hasPropertyWithStringValue(pattern, FC_FAMILY, fallback)) {
107 FcPatternAddString(pattern, FC_FAMILY, (FcChar8 *) fallback);
108 }
e7d0c5d9 dan2004-04-07 02:50:52 +0000109
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200110 /*FcPatternPrint(pattern); */
08e811aa dan2004-10-22 00:21:51 +0000111
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200112 result = (char *)FcNameUnparse(pattern);
113 FcPatternDestroy(pattern);
39b9edfd dan2003-08-15 02:58:04 +0000114
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200115 return result;
39b9edfd dan2003-08-15 02:58:04 +0000116}
117
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200118WMFont *WMCreateFont(WMScreen * scrPtr, char *fontName)
08225948 dan2003-08-14 01:39:27 +0000119{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200120 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);
ee28b025 Carlos R. Mafra2008-05-02 20:23:00 -0300147 if (!font->font) {
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200148 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 }
ee28b025 Carlos R. Mafra2008-05-02 20:23:00 -0300160
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200161 font->height = font->font->ascent + font->font->descent;
162 font->y = font->font->ascent;
08225948 dan2003-08-14 01:39:27 +0000163
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200164 font->refCount = 1;
08225948 dan2003-08-14 01:39:27 +0000165
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200166 font->name = fname;
08225948 dan2003-08-14 01:39:27 +0000167
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200168 assert(WMHashInsert(scrPtr->fontCache, font->name, font) == NULL);
08225948 dan2003-08-14 01:39:27 +0000169
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200170 return font;
08225948 dan2003-08-14 01:39:27 +0000171}
172
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200173WMFont *WMRetainFont(WMFont * font)
08225948 dan2003-08-14 01:39:27 +0000174{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200175 wassertrv(font != NULL, NULL);
08225948 dan2003-08-14 01:39:27 +0000176
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200177 font->refCount++;
08225948 dan2003-08-14 01:39:27 +0000178
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200179 return font;
08225948 dan2003-08-14 01:39:27 +0000180}
181
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200182void WMReleaseFont(WMFont * font)
08225948 dan2003-08-14 01:39:27 +0000183{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200184 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 }
08225948 dan2003-08-14 01:39:27 +0000195}
196
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200197Bool WMIsAntialiasingEnabled(WMScreen * scrPtr)
08225948 dan2003-08-14 01:39:27 +0000198{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200199 return scrPtr->antialiasedText;
08225948 dan2003-08-14 01:39:27 +0000200}
201
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200202unsigned int WMFontHeight(WMFont * font)
08225948 dan2003-08-14 01:39:27 +0000203{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200204 wassertrv(font != NULL, 0);
08225948 dan2003-08-14 01:39:27 +0000205
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200206 return font->height;
08225948 dan2003-08-14 01:39:27 +0000207}
208
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200209char *WMGetFontName(WMFont * font)
08225948 dan2003-08-14 01:39:27 +0000210{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200211 wassertrv(font != NULL, NULL);
08225948 dan2003-08-14 01:39:27 +0000212
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200213 return font->name;
08225948 dan2003-08-14 01:39:27 +0000214}
215
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200216WMFont *WMDefaultSystemFont(WMScreen * scrPtr)
08225948 dan2003-08-14 01:39:27 +0000217{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200218 return WMRetainFont(scrPtr->normalFont);
08225948 dan2003-08-14 01:39:27 +0000219}
220
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200221WMFont *WMDefaultBoldSystemFont(WMScreen * scrPtr)
08225948 dan2003-08-14 01:39:27 +0000222{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200223 return WMRetainFont(scrPtr->boldFont);
08225948 dan2003-08-14 01:39:27 +0000224}
225
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200226WMFont *WMSystemFontOfSize(WMScreen * scrPtr, int size)
08225948 dan2003-08-14 01:39:27 +0000227{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200228 WMFont *font;
229 char *fontSpec;
08225948 dan2003-08-14 01:39:27 +0000230
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200231 fontSpec = makeFontOfSize(WINGsConfiguration.systemFont, size, NULL);
08225948 dan2003-08-14 01:39:27 +0000232
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200233 font = WMCreateFont(scrPtr, fontSpec);
08225948 dan2003-08-14 01:39:27 +0000234
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200235 if (!font) {
236 wwarning(_("could not load font: %s."), fontSpec);
237 }
39b9edfd dan2003-08-15 02:58:04 +0000238
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200239 wfree(fontSpec);
08225948 dan2003-08-14 01:39:27 +0000240
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200241 return font;
08225948 dan2003-08-14 01:39:27 +0000242}
243
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200244WMFont *WMBoldSystemFontOfSize(WMScreen * scrPtr, int size)
08225948 dan2003-08-14 01:39:27 +0000245{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200246 WMFont *font;
247 char *fontSpec;
08225948 dan2003-08-14 01:39:27 +0000248
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200249 fontSpec = makeFontOfSize(WINGsConfiguration.boldSystemFont, size, NULL);
08225948 dan2003-08-14 01:39:27 +0000250
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200251 font = WMCreateFont(scrPtr, fontSpec);
08225948 dan2003-08-14 01:39:27 +0000252
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200253 if (!font) {
254 wwarning(_("could not load font: %s."), fontSpec);
255 }
39b9edfd dan2003-08-15 02:58:04 +0000256
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200257 wfree(fontSpec);
08225948 dan2003-08-14 01:39:27 +0000258
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200259 return font;
08225948 dan2003-08-14 01:39:27 +0000260}
261
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200262int WMWidthOfString(WMFont * font, char *text, int length)
08225948 dan2003-08-14 01:39:27 +0000263{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200264 XGlyphInfo extents;
08225948 dan2003-08-14 01:39:27 +0000265
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200266 wassertrv(font != NULL && text != NULL, 0);
9aca0d5f dan2004-10-12 01:34:32 +0000267
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200268 XftTextExtentsUtf8(font->screen->display, font->font, (XftChar8 *) text, length, &extents);
08225948 dan2003-08-14 01:39:27 +0000269
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200270 return extents.xOff; /* don't ask :P */
08225948 dan2003-08-14 01:39:27 +0000271}
272
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200273void WMDrawString(WMScreen * scr, Drawable d, WMColor * color, WMFont * font, int x, int y, char *text, int length)
08225948 dan2003-08-14 01:39:27 +0000274{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200275 XftColor xftcolor;
08225948 dan2003-08-14 01:39:27 +0000276
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200277 wassertr(font != NULL);
08225948 dan2003-08-14 01:39:27 +0000278
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200279 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);
08225948 dan2003-08-14 01:39:27 +0000284
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200285 XftDrawChange(scr->xftdraw, d);
08225948 dan2003-08-14 01:39:27 +0000286
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200287 XftDrawStringUtf8(scr->xftdraw, &xftcolor, font->font, x, y + font->y, (XftChar8 *) text, length);
08225948 dan2003-08-14 01:39:27 +0000288}
289
08225948 dan2003-08-14 01:39:27 +0000290void
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200291WMDrawImageString(WMScreen * scr, Drawable d, WMColor * color, WMColor * background,
292 WMFont * font, int x, int y, char *text, int length)
08225948 dan2003-08-14 01:39:27 +0000293{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200294 XftColor textColor;
295 XftColor bgColor;
08225948 dan2003-08-14 01:39:27 +0000296
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200297 wassertr(font != NULL);
08225948 dan2003-08-14 01:39:27 +0000298
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200299 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);
08225948 dan2003-08-14 01:39:27 +0000304
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200305 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);
08225948 dan2003-08-14 01:39:27 +0000310
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200311 XftDrawChange(scr->xftdraw, d);
08225948 dan2003-08-14 01:39:27 +0000312
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200313 XftDrawRect(scr->xftdraw, &bgColor, x, y, WMWidthOfString(font, text, length), font->height);
08225948 dan2003-08-14 01:39:27 +0000314
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200315 XftDrawStringUtf8(scr->xftdraw, &textColor, font->font, x, y + font->y, (XftChar8 *) text, length);
08225948 dan2003-08-14 01:39:27 +0000316}
317
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200318WMFont *WMCopyFontWithStyle(WMScreen * scrPtr, WMFont * font, WMFontStyle style)
08225948 dan2003-08-14 01:39:27 +0000319{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200320 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;
08225948 dan2003-08-14 01:39:27 +0000360}