5 # include <X11/Xft/Xft.h>
16 #include <X11/Xlocale.h>
21 #if defined(HAVE_MBSNRTOWCS1)
24 wmbsnrtowcs(wchar_t *dest
, const char **src
, size_t nbytes
, size_t len
)
29 memset(&ps
, 0, sizeof(mbstate_t));
30 n
= mbsnrtowcs(dest
, src
, nbytes
, len
, &ps
);
31 if (n
!=(size_t)-1 && *src
) {
38 #elif defined(HAVE_MBRTOWC)
40 // This is 8 times slower than the version above.
42 wmbsnrtowcs(wchar_t *dest
, const char **src
, size_t nbytes
, size_t len
)
55 memset(&ps
, 0, sizeof(mbstate_t));
59 nb
= mbrtowc(NULL
, ptr
, nbytes
, &ps
);
62 } else if (nb
==0 || nb
>nbytes
) {
72 nb
= mbrtowc(dest
, ptr
, nbytes
, &ps
);
76 } else if (nb
== -1) {
94 # error No mbsnrtowcs. You loose.
99 WMCreateFont(WMScreen
*scrPtr
, char *fontName
)
102 Display
*display
= scrPtr
->display
;
105 /* This is for back-compat (to allow reading of old xlfd descriptions) */
106 if (fontName
[0]=='-' && (ptr
= strchr(fontName
, ','))) {
107 fname
= wmalloc(ptr
- fontName
+ 1);
108 strncpy(fname
, fontName
, ptr
- fontName
);
109 fname
[ptr
- fontName
] = 0;
111 fname
= wstrdup(fontName
);
114 font
= WMHashGet(scrPtr
->fontCache
, fname
);
121 font
= wmalloc(sizeof(WMFont
));
122 memset(font
, 0, sizeof(WMFont
));
124 font
->screen
= scrPtr
;
126 printf("%s\n", fname
);
127 if (fname
[0] == '-') {
128 /* Backward compat thing. Remove in a later version */
129 font
->font
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
131 font
->font
= XftFontOpenName(display
, scrPtr
->screen
, fname
);
138 font
->height
= font
->font
->ascent
+font
->font
->descent
;
139 font
->y
= font
->font
->ascent
;
145 assert(WMHashInsert(scrPtr
->fontCache
, font
->name
, font
)==NULL
);
152 WMRetainFont(WMFont
*font
)
154 wassertrv(font
!=NULL
, NULL
);
163 WMReleaseFont(WMFont
*font
)
165 wassertr(font
!=NULL
);
168 if (font
->refCount
< 1) {
169 XftFontClose(font
->screen
->display
, font
->font
);
171 WMHashRemove(font
->screen
->fontCache
, font
->name
);
180 WMIsAntialiasingEnabled(WMScreen
*scrPtr
)
182 return scrPtr
->antialiasedText
;
187 WMFontHeight(WMFont
*font
)
189 wassertrv(font
!=NULL
, 0);
196 WMGetFontName(WMFont
*font
)
198 wassertrv(font
!=NULL
, NULL
);
205 WMDefaultSystemFont(WMScreen
*scrPtr
)
207 return WMRetainFont(scrPtr
->normalFont
);
212 WMDefaultBoldSystemFont(WMScreen
*scrPtr
)
214 return WMRetainFont(scrPtr
->boldFont
);
219 WMSystemFontOfSize(WMScreen
*scrPtr
, int size
)
224 // we can here use fontnames like arial,times,sans-8:...
225 // which allow automatic fallback to times if arial is not available
226 // then sans if times is also unavailable.
227 fontSpec
= makeFontSetOfSize(WINGsConfiguration
.systemFont
, size
);
229 font
= WMCreateFont(scrPtr
, fontSpec
);
232 wwarning(_("could not load font %s. Trying sans."), fontSpec
);
233 font
= WMCreateFont(scrPtr
, "sans:pixelsize=12");
242 WMBoldSystemFontOfSize(WMScreen
*scrPtr
, int size
)
247 // we can here use fontnames like arial,times,sans-8:...
248 // which allow automatic fallback to times if arial is not available
249 // then sans if times is also unavailable.
250 fontSpec
= makeFontSetOfSize(WINGsConfiguration
.boldSystemFont
, size
);
252 font
= WMCreateFont(scrPtr
, fontSpec
);
255 wwarning(_("could not load font %s. Trying sans."), fontSpec
);
256 font
= WMCreateFont(scrPtr
, "sans:bold:pixelsize=12");
265 WMWidthOfString(WMFont
*font
, char *text
, int length
)
269 wassertrv(font
!=NULL
, 0);
270 wassertrv(text
!=NULL
, 0);
272 if (!font
->notFontSet
) {
277 wtext
= (wchar_t *)wmalloc(sizeof(wchar_t)*(length
+1));
279 len
= wmbsnrtowcs(wtext
, &mtext
, length
, length
);
281 wtext
[len
] = L
'\0'; /* not really necessary here */
282 XftTextExtents32(font
->screen
->display
, font
->font
,
283 (XftChar32
*)wtext
, len
, &extents
);
286 wwarning(_("Conversion to widechar failed (possible "
287 "invalid multibyte sequence): '%s':(pos %d)\n"),
294 XftTextExtents8(font
->screen
->display
, font
->font
,
295 (XftChar8
*)text
, length
, &extents
);
298 return extents
.xOff
; /* don't ask :P */
304 WMDrawString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMFont
*font
,
305 int x
, int y
, char *text
, int length
)
309 wassertr(font
!=NULL
);
311 xftcolor
.color
.red
= color
->color
.red
;
312 xftcolor
.color
.green
= color
->color
.green
;
313 xftcolor
.color
.blue
= color
->color
.blue
;
314 xftcolor
.color
.alpha
= color
->alpha
;;
315 xftcolor
.pixel
= W_PIXEL(color
);
317 XftDrawChange(scr
->xftdraw
, d
);
319 if (!font
->notFontSet
) {
324 wtext
= (wchar_t *)wmalloc(sizeof(wchar_t)*(length
+1));
326 len
= wmbsnrtowcs(wtext
, &mtext
, length
, length
);
328 XftDrawString32(scr
->xftdraw
, &xftcolor
, font
->font
,
329 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
330 } else if (len
==-1) {
331 wwarning(_("Conversion to widechar failed (possible invalid "
332 "multibyte sequence): '%s':(pos %d)\n"),
334 /* we can draw normal text, or we can draw as much widechar
335 * text as was already converted until the error. go figure */
336 /*XftDrawString8(scr->xftdraw, &xftcolor, font->font,
337 x, y + font->y, (XftChar8*)text, length);*/
341 XftDrawString8(scr
->xftdraw
, &xftcolor
, font
->font
,
342 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
348 WMDrawImageString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMColor
*background
,
349 WMFont
*font
, int x
, int y
, char *text
, int length
)
354 wassertr(font
!=NULL
);
356 textColor
.color
.red
= color
->color
.red
;
357 textColor
.color
.green
= color
->color
.green
;
358 textColor
.color
.blue
= color
->color
.blue
;
359 textColor
.color
.alpha
= color
->alpha
;;
360 textColor
.pixel
= W_PIXEL(color
);
362 bgColor
.color
.red
= background
->color
.red
;
363 bgColor
.color
.green
= background
->color
.green
;
364 bgColor
.color
.blue
= background
->color
.blue
;
365 bgColor
.color
.alpha
= background
->alpha
;;
366 bgColor
.pixel
= W_PIXEL(background
);
368 XftDrawChange(scr
->xftdraw
, d
);
370 XftDrawRect(scr
->xftdraw
, &bgColor
, x
, y
,
371 WMWidthOfString(font
, text
, length
),
374 if (!font
->notFontSet
) {
380 wtext
= (wchar_t *)wmalloc(sizeof(wchar_t)*(length
+1));
381 len
= wmbsnrtowcs(wtext
, &mtext
, length
, length
);
383 XftDrawString32(scr
->xftdraw
, &textColor
, font
->font
,
384 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
385 } else if (len
==-1) {
386 wwarning(_("Conversion to widechar failed (possible invalid "
387 "multibyte sequence): '%s':(pos %d)\n"),
389 /* we can draw normal text, or we can draw as much widechar
390 * text as was already converted until the error. go figure */
391 /*XftDrawString8(scr->xftdraw, &textColor, font->font,
392 x, y + font->y, (XftChar8*)text, length);*/
396 XftDrawString8(scr
->xftdraw
, &textColor
, font
->font
,
397 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
405 makeFontSetOfSize(char *fontset
, int size
)
417 ptr
= strchr(fontset
, ',');
419 int count
= ptr
-fontset
;
422 wwarning(_("font description %s is too large."), fontset
);
424 memcpy(font
, fontset
, count
);
435 tmp
= wmalloc(end
+ strlen(f
) + 8);
437 sprintf(tmp
, "%s,", newfs
);
438 sprintf(tmp
+ end
+ 1, f
, size
);
440 sprintf(tmp
+ end
, f
, size
);
454 #define FONT_PROPS 14
457 char *props
[FONT_PROPS
];
462 changeFontProp(char *buf
, char *newprop
, int position
)
465 char *ptr
, *pptr
, *rptr
;
469 /* // remove warning later. or maybe not */
470 wwarning(_("Invalid font specification: '%s'\n"), buf
);
474 ptr
= pptr
= rptr
= buf
;
476 while (*ptr
&& *ptr
!=',') {
479 if (count
-1==position
+1) {
483 if (count
-1==position
) {
489 if (position
==FONT_PROPS
-1) {
494 snprintf(buf2
, 512, "%s%s%s", buf
, newprop
, rptr
);
500 getOptions(char *options
)
502 char *ptr
, *ptr2
, *str
;
506 result
= WMCreateArrayWithDestructor(2, (WMFreeDataProc
*)wfree
);
510 ptr2
= strchr(ptr
, ',');
512 WMAddToArray(result
, wstrdup(ptr
));
516 str
= wmalloc(count
+1);
517 memcpy(str
, ptr
, count
);
519 WMAddToArray(result
, str
);
529 WMCopyFontWithChanges(WMScreen
*scrPtr
, WMFont
*font
,
530 const WMFontAttributes
*changes
)
532 int index
[FONT_PROPS
], count
[FONT_PROPS
];
533 int totalProps
, i
, j
, carry
;
541 snprintf(fname
, 512, "%s", font
->name
);
543 fFlags
= (font
->antialiased
? WFAntialiased
: WFNotAntialiased
);
544 fFlags
|= (font
->notFontSet
? WFNormalFont
: WFFontSet
);
546 props
= WMCreateBagWithDestructor(1, (WMFreeDataProc
*)WMFreeArray
);
549 for (i
=0; i
<FONT_PROPS
; i
++) {
550 prop
= ((W_FontAttributes
*)changes
)->props
[i
];
551 count
[i
] = index
[i
] = 0;
553 /* No change for this property */
555 } else if (strchr(prop
, ',')==NULL
) {
557 changeFontProp(fname
, prop
, i
);
559 /* Option with fallback alternatives */
560 if ((changes
==WFAEmphasized
|| changes
==WFABoldEmphasized
) &&
561 font
->antialiased
&& strcmp(prop
, "o,i")==0) {
562 options
= getOptions("i,o");
564 options
= getOptions(prop
);
566 WMInsertInBag(props
, i
, options
);
567 count
[i
] = WMGetArrayItemCount(options
);
570 totalProps
= totalProps
* count
[i
];
574 if (totalProps
== 0) {
575 /* No options with fallback alternatives at all */
577 return WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
580 for (i
=0; i
<totalProps
; i
++) {
581 for (j
=0; j
<FONT_PROPS
; j
++) {
583 options
= WMGetFromBag(props
, j
);
584 prop
= WMGetFromArray(options
, index
[j
]);
586 changeFontProp(fname
, prop
, j
);
590 result
= WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
595 for (j
=FONT_PROPS
-1, carry
=1; j
>=0; j
--) {
598 carry
= (index
[j
]==count
[j
]);
599 index
[j
] %= count
[j
];
610 #else /* No XFT support */
613 static char *makeFontSetOfSize(char *fontset
, int size
);
617 /* XLFD pattern matching */
619 getElementFromXLFD(const char *xlfd
, int index
)
621 const char *p
= xlfd
;
623 if (*p
== '-' && --index
== 0) {
624 const char *end
= strchr(p
+ 1, '-');
627 if (end
== 0) end
= p
+ strlen(p
);
630 memcpy(buf
, p
+ 1, len
);
640 /* XLFD pattern matching */
642 generalizeXLFD(const char *xlfd
)
646 char *weight
= getElementFromXLFD(xlfd
, 3);
647 char *slant
= getElementFromXLFD(xlfd
, 4);
648 char *pxlsz
= getElementFromXLFD(xlfd
, 7);
650 #define Xstrlen(A) ((A)?strlen(A):0)
651 len
= Xstrlen(xlfd
)+Xstrlen(weight
)+Xstrlen(slant
)+Xstrlen(pxlsz
)*2+60;
654 buf
= wmalloc(len
+ 1);
655 snprintf(buf
, len
+ 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
656 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
657 xlfd
, weight
, slant
, pxlsz
, pxlsz
);
666 /* XLFD pattern matching */
668 W_CreateFontSetWithGuess(Display
*dpy
, char *xlfd
, char ***missing
,
669 int *nmissing
, char **def_string
)
671 XFontSet fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
673 if (fs
!= NULL
&& *nmissing
== 0) return fs
;
675 /* for non-iso8859-1 language and iso8859-1 specification
676 (this fontset is only for pattern analysis) */
678 if (*nmissing
!= 0) XFreeStringList(*missing
);
679 setlocale(LC_CTYPE
, "C");
680 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
681 setlocale(LC_CTYPE
, "");
684 /* make XLFD font name for pattern analysis */
686 XFontStruct
**fontstructs
;
688 if (XFontsOfFontSet(fs
, &fontstructs
, &fontnames
) > 0)
692 xlfd
= generalizeXLFD(xlfd
);
694 if (*nmissing
!= 0) XFreeStringList(*missing
);
695 if (fs
!= NULL
) XFreeFontSet(dpy
, fs
);
697 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
705 xlfdFromFontName(char *fontName
, Bool antialiased
)
707 char *systemFont
, *boldSystemFont
;
712 systemFont
= WINGsConfiguration
.antialiasedSystemFont
;
713 boldSystemFont
= WINGsConfiguration
.antialiasedBoldSystemFont
;
715 systemFont
= WINGsConfiguration
.systemFont
;
716 boldSystemFont
= WINGsConfiguration
.boldSystemFont
;
719 size
= WINGsConfiguration
.defaultFontSize
;
721 if (strcmp(fontName
, "SystemFont")==0) {
723 size
= WINGsConfiguration
.defaultFontSize
;
724 } else if (strncmp(fontName
, "SystemFont-", 11)==0) {
726 if (sscanf(&fontName
[11], "%i", &size
)!=1) {
727 size
= WINGsConfiguration
.defaultFontSize
;
728 wwarning(_("Invalid size specification '%s' in %s. "
729 "Using default %d\n"), &fontName
[11], fontName
, size
);
731 } else if (strcmp(fontName
, "BoldSystemFont")==0) {
732 font
= boldSystemFont
;
733 size
= WINGsConfiguration
.defaultFontSize
;
734 } else if (strncmp(fontName
, "BoldSystemFont-", 15)==0) {
735 font
= boldSystemFont
;
736 if (sscanf(&fontName
[15], "%i", &size
)!=1) {
737 size
= WINGsConfiguration
.defaultFontSize
;
738 wwarning(_("Invalid size specification '%s' in %s. "
739 "Using default %d\n"), &fontName
[15], fontName
, size
);
745 return (font
!=NULL
? makeFontSetOfSize(font
, size
) : wstrdup(fontName
));
750 WMCreateFontSet(WMScreen
*scrPtr
, char *fontName
)
753 Display
*display
= scrPtr
->display
;
758 XFontSetExtents
*extents
;
760 fname
= xlfdFromFontName(fontName
, False
);
762 font
= WMHashGet(scrPtr
->fontSetCache
, fname
);
769 font
= wmalloc(sizeof(WMFont
));
770 memset(font
, 0, sizeof(WMFont
));
772 font
->notFontSet
= 0;
773 font
->antialiased
= 0;
775 font
->screen
= scrPtr
;
777 font
->font
.set
= W_CreateFontSetWithGuess(display
, fname
, &missing
,
778 &nmissing
, &defaultString
);
779 if (nmissing
> 0 && font
->font
.set
) {
782 wwarning(_("the following character sets are missing in %s:"), fname
);
783 for (i
= 0; i
< nmissing
; i
++) {
784 wwarning(missing
[i
]);
786 XFreeStringList(missing
);
788 wwarning(_("the string \"%s\" will be used in place of any characters from those sets."),
791 if (!font
->font
.set
) {
797 extents
= XExtentsOfFontSet(font
->font
.set
);
799 font
->height
= extents
->max_logical_extent
.height
;
800 font
->y
= font
->height
- (font
->height
+ extents
->max_logical_extent
.y
);
806 assert(WMHashInsert(scrPtr
->fontSetCache
, font
->name
, font
)==NULL
);
814 WMCreateNormalFont(WMScreen
*scrPtr
, char *fontName
)
817 Display
*display
= scrPtr
->display
;
820 fontName
= xlfdFromFontName(fontName
, False
);
822 if ((ptr
= strchr(fontName
, ','))) {
823 fname
= wmalloc(ptr
- fontName
+ 1);
824 strncpy(fname
, fontName
, ptr
- fontName
);
825 fname
[ptr
- fontName
] = 0;
827 fname
= wstrdup(fontName
);
832 font
= WMHashGet(scrPtr
->fontCache
, fname
);
839 font
= wmalloc(sizeof(WMFont
));
840 memset(font
, 0, sizeof(WMFont
));
842 font
->notFontSet
= 1;
843 font
->antialiased
= 0;
845 font
->screen
= scrPtr
;
847 font
->font
.normal
= XLoadQueryFont(display
, fname
);
848 if (!font
->font
.normal
) {
853 font
->height
= font
->font
.normal
->ascent
+font
->font
.normal
->descent
;
854 font
->y
= font
->font
.normal
->ascent
;
860 assert(WMHashInsert(scrPtr
->fontCache
, font
->name
, font
)==NULL
);
867 WMCreateAntialiasedFont(WMScreen
*scrPtr
, char *fontName
)
871 Display
*display
= scrPtr
->display
;
874 fontName
= xlfdFromFontName(fontName
, True
);
876 if ((ptr
= strchr(fontName
, ','))) {
877 fname
= wmalloc(ptr
- fontName
+ 1);
878 strncpy(fname
, fontName
, ptr
- fontName
);
879 fname
[ptr
- fontName
] = 0;
881 fname
= wstrdup(fontName
);
886 font
= WMHashGet(scrPtr
->xftFontCache
, fname
);
893 font
= wmalloc(sizeof(WMFont
));
894 memset(font
, 0, sizeof(WMFont
));
896 font
->notFontSet
= 1;
897 font
->antialiased
= 1;
899 font
->screen
= scrPtr
;
901 /* Xft sux. Loading a font with an invalid XLFD will give strange results
902 * sometimes without returning any warning or error.
903 * However Xft's idea of what font is invalid is quite strange:
904 * 1. If the XLFD doesn't have all its fields present will fail and
906 * 2. If all fields are present, but hold invalid values then it will:
907 * a. If family is invalid, will load a default font without warning.
908 * b. If the font size is invalid (non-numerical) it will fail and
910 * c. If other fields are invalid, will load the font specified by
911 * the valid family name, ignoring any invalid fields. It will
912 * use a default medium weight and a default roman slant if they
915 printf("%s\n", fname
);
916 if (fname
[0] == '-') {
917 font
->font
.xft
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
919 font
->font
.xft
= XftFontOpenName(display
, scrPtr
->screen
, fname
);
921 if (!font
->font
.xft
) {
926 font
->height
= font
->font
.xft
->ascent
+font
->font
.xft
->descent
;
927 font
->y
= font
->font
.xft
->ascent
;
933 assert(WMHashInsert(scrPtr
->xftFontCache
, font
->name
, font
)==NULL
);
943 WMCreateAntialiasedFontSet(WMScreen
*scrPtr
, char *fontName
)
947 Display
*display
= scrPtr
->display
;
950 fontName
= xlfdFromFontName(fontName
, True
);
952 if ((ptr
= strchr(fontName
, ','))) {
953 fname
= wmalloc(ptr
- fontName
+ 1);
954 strncpy(fname
, fontName
, ptr
- fontName
);
955 fname
[ptr
- fontName
] = 0;
957 fname
= wstrdup(fontName
);
962 font
= WMHashGet(scrPtr
->xftFontSetCache
, fname
);
969 font
= wmalloc(sizeof(WMFont
));
970 memset(font
, 0, sizeof(WMFont
));
972 font
->notFontSet
= 0;
973 font
->antialiased
= 1;
975 font
->screen
= scrPtr
;
977 /* Xft sux. Loading a font with an invalid XLFD will give strange results
978 * sometimes without returning any warning or error.
979 * However Xft's idea of what font is invalid is quite strange:
980 * 1. If the XLFD doesn't have all its fields present will fail and
982 * 2. If all fields are present, but hold invalid values then it will:
983 * a. If family is invalid, will load a default font without warning.
984 * b. If the font size is invalid (non-numerical) it will fail and
986 * c. If other fields are invalid, will load the font specified by
987 * the valid family name, ignoring any invalid fields. It will
988 * use a default medium weight and a default roman slant if they
991 if (fname
[0] == '-') {
992 font
->font
.xft
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
994 font
->font
.xft
= XftFontOpenName(display
, scrPtr
->screen
, fname
);
996 if (!font
->font
.xft
) {
1001 font
->height
= font
->font
.xft
->ascent
+font
->font
.xft
->descent
;
1002 font
->y
= font
->font
.xft
->ascent
;
1008 assert(WMHashInsert(scrPtr
->xftFontSetCache
, font
->name
, font
)==NULL
);
1018 WMCreateFont(WMScreen
*scrPtr
, char *fontName
)
1020 return WMCreateFontWithFlags(scrPtr
, fontName
, WFDefaultFont
);
1025 WMCreateFontWithFlags(WMScreen
*scrPtr
, char *fontName
, WMFontFlags flags
)
1027 Bool multiByte
= scrPtr
->useMultiByte
;
1028 Bool antialiased
= scrPtr
->antialiasedText
;
1031 if (flags
& WFFontSet
) {
1033 } else if (flags
& WFNormalFont
) {
1036 if (flags
& WFAntialiased
) {
1038 } else if (flags
& WFNotAntialiased
) {
1039 antialiased
= False
;
1042 if (antialiased
&& multiByte
) {
1043 font
= WMCreateAntialiasedFontSet(scrPtr
, fontName
);
1044 /* If we cannot create an antialiased font set and antialiasing is
1045 * not explicitly requested in flags, fallback to standard font sets */
1046 if (!font
&& (flags
& WFAntialiased
)==0) {
1047 font
= WMCreateFontSet(scrPtr
, fontName
);
1049 } else if (antialiased
) {
1050 font
= WMCreateAntialiasedFont(scrPtr
, fontName
);
1051 /* If we cannot create an antialiased font and antialiasing is
1052 * not explicitly requested in flags, fallback to normal font */
1053 if (!font
&& (flags
& WFAntialiased
)==0) {
1054 font
= WMCreateNormalFont(scrPtr
, fontName
);
1056 } else if (multiByte
) {
1057 font
= WMCreateFontSet(scrPtr
, fontName
);
1059 font
= WMCreateNormalFont(scrPtr
, fontName
);
1067 WMRetainFont(WMFont
*font
)
1069 wassertrv(font
!=NULL
, NULL
);
1078 WMReleaseFont(WMFont
*font
)
1080 wassertr(font
!=NULL
);
1083 if (font
->refCount
< 1) {
1084 if (font
->antialiased
) {
1086 XftFontClose(font
->screen
->display
, font
->font
.xft
);
1090 } else if (font
->notFontSet
) {
1091 XFreeFont(font
->screen
->display
, font
->font
.normal
);
1093 XFreeFontSet(font
->screen
->display
, font
->font
.set
);
1097 if (font
->antialiased
&& !font
->notFontSet
) {
1098 WMHashRemove(font
->screen
->xftFontSetCache
, font
->name
);
1099 } else if (font
->antialiased
) {
1100 WMHashRemove(font
->screen
->xftFontCache
, font
->name
);
1101 } else if (font
->notFontSet
) {
1102 WMHashRemove(font
->screen
->fontCache
, font
->name
);
1104 WMHashRemove(font
->screen
->fontSetCache
, font
->name
);
1114 WMIsAntialiasingEnabled(WMScreen
*scrPtr
)
1116 return scrPtr
->antialiasedText
;
1121 WMIsAntialiasedFont(WMFont
*font
)
1123 wassertrv(font
!=NULL
, False
);
1125 return font
->antialiased
;
1130 WMFontHeight(WMFont
*font
)
1132 wassertrv(font
!=NULL
, 0);
1134 return font
->height
;
1139 WMGetFontName(WMFont
*font
)
1141 wassertrv(font
!=NULL
, NULL
);
1148 WMDefaultSystemFont(WMScreen
*scrPtr
)
1150 return WMRetainFont(scrPtr
->normalFont
);
1155 WMDefaultBoldSystemFont(WMScreen
*scrPtr
)
1157 return WMRetainFont(scrPtr
->boldFont
);
1162 makeSystemFontOfSize(WMScreen
*scrPtr
, int size
, Bool bold
)
1165 char *fontSpec
, *xftFontSpec
;
1167 #define WConf WINGsConfiguration
1169 fontSpec
= makeFontSetOfSize(WConf
.boldSystemFont
, size
);
1170 xftFontSpec
= makeFontSetOfSize(WConf
.antialiasedBoldSystemFont
, size
);
1172 fontSpec
= makeFontSetOfSize(WConf
.systemFont
, size
);
1173 xftFontSpec
= makeFontSetOfSize(WConf
.antialiasedSystemFont
, size
);
1177 if (scrPtr
->antialiasedText
&& scrPtr
->useMultiByte
) {
1178 font
= WMCreateAntialiasedFontSet(scrPtr
, xftFontSpec
);
1179 } else if (scrPtr
->antialiasedText
) {
1180 font
= WMCreateAntialiasedFont(scrPtr
, xftFontSpec
);
1181 } else if (scrPtr
->useMultiByte
) {
1182 font
= WMCreateFontSet(scrPtr
, fontSpec
);
1184 font
= WMCreateNormalFont(scrPtr
, fontSpec
);
1188 if (scrPtr
->antialiasedText
&& scrPtr
->useMultiByte
) {
1189 // is arial a good fallback for multibyte?
1190 wwarning(_("could not load font %s. Trying arial."), xftFontSpec
);
1192 font
= WMCreateAntialiasedFontSet(scrPtr
, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
1194 font
= WMCreateAntialiasedFontSet(scrPtr
, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
1197 wwarning(_("could not load antialiased font set. Reverting to standard font sets."));
1198 font
= WMCreateFontSet(scrPtr
, fontSpec
);
1200 wwarning(_("could not load FontSet %s. Trying fixed."), fontSpec
);
1201 font
= WMCreateFontSet(scrPtr
, "fixed");
1204 } else if (scrPtr
->antialiasedText
) {
1205 wwarning(_("could not load font %s. Trying arial."), xftFontSpec
);
1207 font
= WMCreateAntialiasedFont(scrPtr
, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
1209 font
= WMCreateAntialiasedFont(scrPtr
, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
1212 wwarning(_("could not load antialiased fonts. Reverting to normal fonts."));
1213 font
= WMCreateNormalFont(scrPtr
, fontSpec
);
1215 wwarning(_("could not load font %s. Trying fixed."), fontSpec
);
1216 font
= WMCreateNormalFont(scrPtr
, "fixed");
1219 } else if (scrPtr
->useMultiByte
) {
1220 wwarning(_("could not load font set %s. Trying fixed."), fontSpec
);
1221 font
= WMCreateFontSet(scrPtr
, "fixed");
1223 font
= WMCreateFontSet(scrPtr
, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
1226 wwarning(_("could not load font %s. Trying fixed."), fontSpec
);
1227 font
= WMCreateNormalFont(scrPtr
, "fixed");
1230 wwarning(_("could not load fixed font!"));
1244 WMSystemFontOfSize(WMScreen
*scrPtr
, int size
)
1246 return makeSystemFontOfSize(scrPtr
, size
, False
);
1251 WMBoldSystemFontOfSize(WMScreen
*scrPtr
, int size
)
1253 return makeSystemFontOfSize(scrPtr
, size
, True
);
1258 WMGetFontFontSet(WMFont
*font
)
1260 wassertrv(font
!=NULL
, NULL
);
1262 if (!font
->notFontSet
&& !font
->antialiased
)
1263 return font
->font
.set
;
1270 WMWidthOfString(WMFont
*font
, char *text
, int length
)
1272 wassertrv(font
!=NULL
, 0);
1273 wassertrv(text
!=NULL
, 0);
1275 if (font
->antialiased
) {
1279 if (!font
->notFontSet
) {
1284 /* Use mtext instead of text, because mbstrtowcs() alters it */
1286 wtext
= (wchar_t *)wmalloc(4*length
+4);
1287 /* pass a real ps instead of NULL below? for multithread safety
1288 * as from manual page */
1289 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
1291 XftTextExtents32(font
->screen
->display
, font
->font
.xft
,
1292 (XftChar32
*)wtext
, len
, &extents
);
1295 wwarning(_("Conversion to widechar failed (possible "
1296 "invalid multibyte sequence): '%s':(pos %d)\n"),
1297 text
, mtext
-text
+1);
1303 XftTextExtents8(font
->screen
->display
, font
->font
.xft
,
1304 (XftChar8
*)text
, length
, &extents
);
1307 return extents
.xOff
; /* don't ask :P */
1309 wassertrv(False
, 0);
1311 } else if (font
->notFontSet
) {
1312 return XTextWidth(font
->font
.normal
, text
, length
);
1315 XRectangle AIXsucks
;
1317 XmbTextExtents(font
->font
.set
, text
, length
, &AIXsucks
, &rect
);
1326 WMDrawString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMFont
*font
,
1327 int x
, int y
, char *text
, int length
)
1329 wassertr(font
!=NULL
);
1331 if (font
->antialiased
) {
1335 xftcolor
.color
.red
= color
->color
.red
;
1336 xftcolor
.color
.green
= color
->color
.green
;
1337 xftcolor
.color
.blue
= color
->color
.blue
;
1338 xftcolor
.color
.alpha
= color
->alpha
;;
1339 xftcolor
.pixel
= W_PIXEL(color
);
1341 XftDrawChange(scr
->xftdraw
, d
);
1343 if (!font
->notFontSet
) {
1348 /* Use mtext instead of text, because mbstrtowcs() alters it */
1350 wtext
= (wchar_t *)wmalloc(4*length
+4);
1351 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
1353 XftDrawString32(scr
->xftdraw
, &xftcolor
, font
->font
.xft
,
1354 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
1355 } else if (len
==-1) {
1356 wwarning(_("Conversion to widechar failed (possible invalid "
1357 "multibyte sequence): '%s':(pos %d)\n"),
1358 text
, mtext
-text
+1);
1359 /* we can draw normal text, or we can draw as much widechar
1360 * text as was already converted until the error. go figure */
1361 /*XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
1362 x, y + font->y, (XftChar8*)text, length);*/
1366 XftDrawString8(scr
->xftdraw
, &xftcolor
, font
->font
.xft
,
1367 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
1372 } else if (font
->notFontSet
) {
1373 XSetFont(scr
->display
, scr
->drawStringGC
, font
->font
.normal
->fid
);
1374 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
1375 XDrawString(scr
->display
, d
, scr
->drawStringGC
, x
, y
+ font
->y
,
1378 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
1379 XmbDrawString(scr
->display
, d
, font
->font
.set
, scr
->drawStringGC
,
1380 x
, y
+ font
->y
, text
, length
);
1386 WMDrawImageString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMColor
*background
,
1387 WMFont
*font
, int x
, int y
, char *text
, int length
)
1389 wassertr(font
!=NULL
);
1391 if (font
->antialiased
) {
1396 textColor
.color
.red
= color
->color
.red
;
1397 textColor
.color
.green
= color
->color
.green
;
1398 textColor
.color
.blue
= color
->color
.blue
;
1399 textColor
.color
.alpha
= color
->alpha
;;
1400 textColor
.pixel
= W_PIXEL(color
);
1402 bgColor
.color
.red
= background
->color
.red
;
1403 bgColor
.color
.green
= background
->color
.green
;
1404 bgColor
.color
.blue
= background
->color
.blue
;
1405 bgColor
.color
.alpha
= background
->alpha
;;
1406 bgColor
.pixel
= W_PIXEL(background
);
1409 XftDrawChange(scr
->xftdraw
, d
);
1411 XftDrawRect(scr
->xftdraw
, &bgColor
, x
, y
,
1412 WMWidthOfString(font
, text
, length
), font
->height
);
1414 if (!font
->notFontSet
) {
1419 /* Use mtext instead of text, because mbstrtowcs() alters it */
1421 wtext
= (wchar_t *)wmalloc(4*length
+4);
1422 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
1424 XftDrawString32(scr
->xftdraw
, &textColor
, font
->font
.xft
,
1425 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
1426 } else if (len
==-1) {
1427 wwarning(_("Conversion to widechar failed (possible invalid "
1428 "multibyte sequence): '%s':(pos %d)\n"),
1429 text
, mtext
-text
+1);
1430 /* we can draw normal text, or we can draw as much widechar
1431 * text as was already converted until the error. go figure */
1432 /*XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
1433 x, y + font->y, (XftChar8*)text, length);*/
1437 XftDrawString8(scr
->xftdraw
, &textColor
, font
->font
.xft
,
1438 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
1443 } else if (font
->notFontSet
) {
1444 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
1445 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
1446 XSetFont(scr
->display
, scr
->drawImStringGC
, font
->font
.normal
->fid
);
1447 XDrawImageString(scr
->display
, d
, scr
->drawImStringGC
,
1448 x
, y
+ font
->y
, text
, length
);
1450 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
1451 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
1452 XmbDrawImageString(scr
->display
, d
, font
->font
.set
, scr
->drawImStringGC
,
1453 x
, y
+ font
->y
, text
, length
);
1461 makeFontSetOfSize(char *fontset
, int size
)
1473 ptr
= strchr(fontset
, ',');
1475 int count
= ptr
-fontset
;
1478 wwarning(_("font description %s is too large."), fontset
);
1480 memcpy(font
, fontset
, count
);
1487 end
= strlen(newfs
);
1491 tmp
= wmalloc(end
+ strlen(f
) + 8);
1493 sprintf(tmp
, "%s,", newfs
);
1494 sprintf(tmp
+ end
+ 1, f
, size
);
1496 sprintf(tmp
+ end
, f
, size
);
1504 } while (ptr
!=NULL
);
1510 #define FONT_PROPS 14
1513 char *props
[FONT_PROPS
];
1518 changeFontProp(char *buf
, char *newprop
, int position
)
1521 char *ptr
, *pptr
, *rptr
;
1525 /* // remove warning later. or maybe not */
1526 wwarning(_("Invalid font specification: '%s'\n"), buf
);
1530 ptr
= pptr
= rptr
= buf
;
1532 while (*ptr
&& *ptr
!=',') {
1535 if (count
-1==position
+1) {
1539 if (count
-1==position
) {
1545 if (position
==FONT_PROPS
-1) {
1550 snprintf(buf2
, 512, "%s%s%s", buf
, newprop
, rptr
);
1556 getOptions(char *options
)
1558 char *ptr
, *ptr2
, *str
;
1562 result
= WMCreateArrayWithDestructor(2, (WMFreeDataProc
*)wfree
);
1566 ptr2
= strchr(ptr
, ',');
1568 WMAddToArray(result
, wstrdup(ptr
));
1572 str
= wmalloc(count
+1);
1573 memcpy(str
, ptr
, count
);
1575 WMAddToArray(result
, str
);
1585 WMCopyFontWithChanges(WMScreen
*scrPtr
, WMFont
*font
,
1586 const WMFontAttributes
*changes
)
1588 int index
[FONT_PROPS
], count
[FONT_PROPS
];
1589 int totalProps
, i
, j
, carry
;
1597 snprintf(fname
, 512, "%s", font
->name
);
1599 fFlags
= (font
->antialiased
? WFAntialiased
: WFNotAntialiased
);
1600 fFlags
|= (font
->notFontSet
? WFNormalFont
: WFFontSet
);
1602 props
= WMCreateBagWithDestructor(1, (WMFreeDataProc
*)WMFreeArray
);
1605 for (i
=0; i
<FONT_PROPS
; i
++) {
1606 prop
= ((W_FontAttributes
*)changes
)->props
[i
];
1607 count
[i
] = index
[i
] = 0;
1609 /* No change for this property */
1611 } else if (strchr(prop
, ',')==NULL
) {
1613 changeFontProp(fname
, prop
, i
);
1615 /* Option with fallback alternatives */
1616 if ((changes
==WFAEmphasized
|| changes
==WFABoldEmphasized
) &&
1617 font
->antialiased
&& strcmp(prop
, "o,i")==0) {
1618 options
= getOptions("i,o");
1620 options
= getOptions(prop
);
1622 WMInsertInBag(props
, i
, options
);
1623 count
[i
] = WMGetArrayItemCount(options
);
1626 totalProps
= totalProps
* count
[i
];
1630 if (totalProps
== 0) {
1631 /* No options with fallback alternatives at all */
1633 return WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
1636 for (i
=0; i
<totalProps
; i
++) {
1637 for (j
=0; j
<FONT_PROPS
; j
++) {
1639 options
= WMGetFromBag(props
, j
);
1640 prop
= WMGetFromArray(options
, index
[j
]);
1642 changeFontProp(fname
, prop
, j
);
1646 result
= WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
1651 for (j
=FONT_PROPS
-1, carry
=1; j
>=0; j
--) {
1654 carry
= (index
[j
]==count
[j
]);
1655 index
[j
] %= count
[j
];
1668 // should WFANormal also set "normal" or leave it alone?
1669 static const WMFontAttributes W_FANormal
= {
1670 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", "r", "normal",
1671 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1672 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1676 static const WMFontAttributes W_FABold
= {
1677 WFAUnchanged
, WFAUnchanged
, "bold", WFAUnchanged
,
1678 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1679 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1683 static const WMFontAttributes W_FANotBold
= {
1684 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", WFAUnchanged
,
1685 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1686 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1690 static const WMFontAttributes W_FAEmphasized
= {
1691 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "o,i",
1692 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1693 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1697 static const WMFontAttributes W_FANotEmphasized
= {
1698 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "r",
1699 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1700 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1704 static const WMFontAttributes W_FABoldEmphasized
= {
1705 WFAUnchanged
, WFAUnchanged
, "bold", "o,i",
1706 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1707 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1711 const WMFontAttributes
*WFANormal
= &W_FANormal
;
1712 const WMFontAttributes
*WFABold
= &W_FABold
;
1713 const WMFontAttributes
*WFANotBold
= &W_FANotBold
;
1714 const WMFontAttributes
*WFAEmphasized
= &W_FAEmphasized
;
1715 const WMFontAttributes
*WFANotEmphasized
= &W_FANotEmphasized
;
1716 const WMFontAttributes
*WFABoldEmphasized
= &W_FABoldEmphasized
;