6 #include <X11/Xft/Xft.h>
7 #include <fontconfig/fontconfig.h>
9 #if defined(HAVE_MBSNRTOWCS)
23 #include <X11/Xlocale.h>
27 #if defined(HAVE_MBSNRTOWCS)
30 wmbsnrtowcs(wchar_t *dest
, const char **src
, size_t nbytes
, size_t len
)
35 memset(&ps
, 0, sizeof(mbstate_t));
36 n
= mbsnrtowcs(dest
, src
, nbytes
, len
, &ps
);
37 if (n
!=(size_t)-1 && *src
) {
44 #elif defined(HAVE_MBRTOWC)
46 // This is 8 times slower than the version above.
48 wmbsnrtowcs(wchar_t *dest
, const char **src
, size_t nbytes
, size_t len
)
58 memset(&ps
, 0, sizeof(mbstate_t));
61 for (ptr
=*src
, n
=0; nbytes
>0; n
++) {
62 nb
= mbrtowc(NULL
, ptr
, nbytes
, &ps
);
65 } else if (nb
==0 || nb
==-2) {
73 for (ptr
=*src
, n
=0; n
<len
&& nbytes
>0; n
++, dest
++) {
74 nb
= mbrtowc(dest
, ptr
, nbytes
, &ps
);
78 } else if (nb
== -1) {
95 // Not only 8 times slower than the version based on mbsnrtowcs
96 // but also this version is not thread safe nor reentrant
99 wmbsnrtowcs(wchar_t *dest
, const char **src
, size_t nbytes
, size_t len
)
108 mbtowc(NULL
, NULL
, 0); /* reset shift state */
111 for (ptr
=*src
, n
=0; nbytes
>0; n
++) {
112 nb
= mbtowc(NULL
, ptr
, nbytes
);
114 mbtowc(NULL
, NULL
, 0);
115 nb
= mbtowc(NULL
, ptr
, strlen(ptr
));
116 return (nb
== -1 ? (size_t)-1 : n
);
125 for (ptr
=*src
, n
=0; n
<len
&& nbytes
>0; n
++, dest
++) {
126 nb
= mbtowc(dest
, ptr
, nbytes
);
128 mbtowc(NULL
, NULL
, 0);
129 nb
= mbtowc(NULL
, ptr
, strlen(ptr
));
131 return (nb
== -1 ? (size_t)-1 : n
);
132 } else if (nb
== 0) {
147 #define DEFAULT_SIZE 12
150 fixXLFD(char *xlfd
, int size
)
154 fname
= wmalloc(strlen(xlfd
) + 20);
155 if (strstr(xlfd
, "%d")!=NULL
)
156 sprintf(fname
, xlfd
, size
? size
: DEFAULT_SIZE
);
160 if ((ptr
= strchr(fname
, ','))) {
169 hasProperty(FcPattern
*pattern
, const char *property
)
173 if (FcPatternGet(pattern
, property
, 0, &val
)==FcResultMatch
) {
182 hasPropertyWithStringValue(FcPattern
*pattern
, const char *object
, char *value
)
187 if (!value
|| value
[0]==0)
191 while (FcPatternGetString(pattern
, object
, id
, &str
)==FcResultMatch
) {
192 if (strcasecmp(value
, (char*)str
) == 0) {
202 // also handle an xlfd with %d for size?
204 makeFontOfSize(char *font
, int size
, char *fallback
)
212 fname
= fixXLFD(font
, size
);
213 pattern
= XftXlfdParse(fname
, False
, False
);
216 pattern
= FcNameParse(font
);
219 //FcPatternPrint(pattern);
221 FcPatternDel(pattern
, "pixelsize");
222 FcPatternAddDouble(pattern
, "pixelsize", (double)size
);
223 } else if (size
==0 && !hasProperty(pattern
, "size") &&
224 !hasProperty(pattern
, "pixelsize")) {
225 FcPatternAddDouble(pattern
, "pixelsize", (double)DEFAULT_SIZE
);
228 if (fallback
&& !hasPropertyWithStringValue(pattern
, "family", fallback
)) {
229 FcPatternAddString(pattern
, "family", fallback
);
232 result
= FcNameUnparse(pattern
);
233 FcPatternDestroy(pattern
);
240 WMCreateFont(WMScreen
*scrPtr
, char *fontName
)
243 Display
*display
= scrPtr
->display
;
246 /* This is for back-compat (to allow reading of old xlfd descriptions) */
247 if (fontName
[0]=='-' && (ptr
= strchr(fontName
, ','))) {
248 // warn for deprecation
249 fname
= wmalloc(ptr
- fontName
+ 1);
250 strncpy(fname
, fontName
, ptr
- fontName
);
251 fname
[ptr
- fontName
] = 0;
253 fname
= wstrdup(fontName
);
256 font
= WMHashGet(scrPtr
->fontCache
, fname
);
263 font
= wmalloc(sizeof(WMFont
));
264 memset(font
, 0, sizeof(WMFont
));
266 font
->screen
= scrPtr
;
269 printf("WMCreateFont: %s\n", fname
);
271 if (fname
[0] == '-') {
272 // Backward compat thing. Remove in a later version
273 font
->font
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
275 font
->font
= XftFontOpenName(display
, scrPtr
->screen
, fname
);
282 font
->height
= font
->font
->ascent
+font
->font
->descent
;
283 font
->y
= font
->font
->ascent
;
289 assert(WMHashInsert(scrPtr
->fontCache
, font
->name
, font
)==NULL
);
296 WMRetainFont(WMFont
*font
)
298 wassertrv(font
!=NULL
, NULL
);
307 WMReleaseFont(WMFont
*font
)
309 wassertr(font
!=NULL
);
312 if (font
->refCount
< 1) {
313 XftFontClose(font
->screen
->display
, font
->font
);
315 WMHashRemove(font
->screen
->fontCache
, font
->name
);
324 WMIsAntialiasingEnabled(WMScreen
*scrPtr
)
326 return scrPtr
->antialiasedText
;
331 WMFontHeight(WMFont
*font
)
333 wassertrv(font
!=NULL
, 0);
340 WMGetFontName(WMFont
*font
)
342 wassertrv(font
!=NULL
, NULL
);
349 WMDefaultSystemFont(WMScreen
*scrPtr
)
351 return WMRetainFont(scrPtr
->normalFont
);
356 WMDefaultBoldSystemFont(WMScreen
*scrPtr
)
358 return WMRetainFont(scrPtr
->boldFont
);
363 WMSystemFontOfSize(WMScreen
*scrPtr
, int size
)
368 fontSpec
= makeFontOfSize(WINGsConfiguration
.systemFont
, size
, "sans");
370 font
= WMCreateFont(scrPtr
, fontSpec
);
373 wwarning(_("could not load font %s."), fontSpec
);
383 WMBoldSystemFontOfSize(WMScreen
*scrPtr
, int size
)
388 fontSpec
= makeFontOfSize(WINGsConfiguration
.boldSystemFont
, size
, "sans");
390 font
= WMCreateFont(scrPtr
, fontSpec
);
393 wwarning(_("could not load font %s."), fontSpec
);
403 WMWidthOfString(WMFont
*font
, char *text
, int length
)
407 wassertrv(font
!=NULL
, 0);
408 wassertrv(text
!=NULL
, 0);
410 if (font
->screen
->useWideChar
) {
415 wtext
= (wchar_t *)wmalloc(sizeof(wchar_t)*(length
+1));
417 len
= wmbsnrtowcs(wtext
, &mtext
, length
, length
);
419 wtext
[len
] = L
'\0'; /* not really necessary here */
420 XftTextExtents32(font
->screen
->display
, font
->font
,
421 (XftChar32
*)wtext
, len
, &extents
);
424 wwarning(_("Conversion to widechar failed (possible "
425 "invalid multibyte sequence): '%s':(pos %d)\n"),
431 } else if (font
->screen
->useMultiByte
) {
432 XftTextExtentsUtf8(font
->screen
->display
, font
->font
,
433 (XftChar8
*)text
, length
, &extents
);
435 XftTextExtents8(font
->screen
->display
, font
->font
,
436 (XftChar8
*)text
, length
, &extents
);
439 return extents
.xOff
; /* don't ask :P */
445 WMDrawString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMFont
*font
,
446 int x
, int y
, char *text
, int length
)
450 wassertr(font
!=NULL
);
452 xftcolor
.color
.red
= color
->color
.red
;
453 xftcolor
.color
.green
= color
->color
.green
;
454 xftcolor
.color
.blue
= color
->color
.blue
;
455 xftcolor
.color
.alpha
= color
->alpha
;;
456 xftcolor
.pixel
= W_PIXEL(color
);
458 XftDrawChange(scr
->xftdraw
, d
);
460 if (font
->screen
->useWideChar
) {
465 wtext
= (wchar_t *)wmalloc(sizeof(wchar_t)*(length
+1));
467 len
= wmbsnrtowcs(wtext
, &mtext
, length
, length
);
469 XftDrawString32(scr
->xftdraw
, &xftcolor
, font
->font
,
470 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
471 } else if (len
==-1) {
472 wwarning(_("Conversion to widechar failed (possible invalid "
473 "multibyte sequence): '%s':(pos %d)\n"),
475 /* we can draw normal text, or we can draw as much widechar
476 * text as was already converted until the error. go figure */
477 /*XftDrawString8(scr->xftdraw, &xftcolor, font->font,
478 x, y + font->y, (XftChar8*)text, length);*/
481 } else if (font
->screen
->useMultiByte
) {
482 XftDrawStringUtf8(scr
->xftdraw
, &xftcolor
, font
->font
,
483 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
485 XftDrawString8(scr
->xftdraw
, &xftcolor
, font
->font
,
486 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
492 WMDrawImageString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMColor
*background
,
493 WMFont
*font
, int x
, int y
, char *text
, int length
)
498 wassertr(font
!=NULL
);
500 textColor
.color
.red
= color
->color
.red
;
501 textColor
.color
.green
= color
->color
.green
;
502 textColor
.color
.blue
= color
->color
.blue
;
503 textColor
.color
.alpha
= color
->alpha
;;
504 textColor
.pixel
= W_PIXEL(color
);
506 bgColor
.color
.red
= background
->color
.red
;
507 bgColor
.color
.green
= background
->color
.green
;
508 bgColor
.color
.blue
= background
->color
.blue
;
509 bgColor
.color
.alpha
= background
->alpha
;;
510 bgColor
.pixel
= W_PIXEL(background
);
512 XftDrawChange(scr
->xftdraw
, d
);
514 XftDrawRect(scr
->xftdraw
, &bgColor
, x
, y
,
515 WMWidthOfString(font
, text
, length
),
518 if (font
->screen
->useWideChar
) {
524 wtext
= (wchar_t *)wmalloc(sizeof(wchar_t)*(length
+1));
525 len
= wmbsnrtowcs(wtext
, &mtext
, length
, length
);
527 XftDrawString32(scr
->xftdraw
, &textColor
, font
->font
,
528 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
529 } else if (len
==-1) {
530 wwarning(_("Conversion to widechar failed (possible invalid "
531 "multibyte sequence): '%s':(pos %d)\n"),
533 /* we can draw normal text, or we can draw as much widechar
534 * text as was already converted until the error. go figure */
535 /*XftDrawString8(scr->xftdraw, &textColor, font->font,
536 x, y + font->y, (XftChar8*)text, length);*/
539 } else if (font
->screen
->useMultiByte
) {
540 XftDrawStringUtf8(scr
->xftdraw
, &textColor
, font
->font
,
541 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
543 XftDrawString8(scr
->xftdraw
, &textColor
, font
->font
,
544 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
550 WMCopyFontWithStyle(WMScreen
*scrPtr
, WMFont
*font
, WMFontStyle style
)
559 pattern
= FcNameParse(WMGetFontName(font
));
562 FcPatternDel(pattern
, "weight");
563 FcPatternDel(pattern
, "slant");
564 FcPatternAddString(pattern
, "weight", "regular");
565 FcPatternAddString(pattern
, "weight", "medium");
566 FcPatternAddString(pattern
, "slant", "roman");
569 FcPatternDel(pattern
, "weight");
570 FcPatternAddString(pattern
, "weight", "bold");
573 FcPatternDel(pattern
, "slant");
574 FcPatternAddString(pattern
, "slant", "italic");
575 FcPatternAddString(pattern
, "slant", "oblique");
577 case WFSBoldEmphasized
:
578 FcPatternDel(pattern
, "weight");
579 FcPatternDel(pattern
, "slant");
580 FcPatternAddString(pattern
, "weight", "bold");
581 FcPatternAddString(pattern
, "slant", "italic");
582 FcPatternAddString(pattern
, "slant", "oblique");
586 name
= FcNameUnparse(pattern
);
587 copy
= WMCreateFont(scrPtr
, name
);
588 FcPatternDestroy(pattern
);