5 # include <X11/Xft/Xft.h>
16 #include <X11/Xlocale.h>
21 #if defined(HAVE_MBSNRTOWCS)
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
)
52 memset(&ps
, 0, sizeof(mbstate_t));
55 for (ptr
=*src
, n
=0; nbytes
>0; n
++) {
56 nb
= mbrtowc(NULL
, ptr
, nbytes
, &ps
);
59 } else if (nb
==0 || nb
==-2) {
67 for (ptr
=*src
, n
=0; n
<len
&& nbytes
>0; n
++, dest
++) {
68 nb
= mbrtowc(dest
, ptr
, nbytes
, &ps
);
72 } else if (nb
== -1) {
89 // Not only 8 times slower than the version based on mbsnrtowcs
90 // but also this version is not thread safe nor reentrant
93 wmbsnrtowcs(wchar_t *dest
, const char **src
, size_t nbytes
, size_t len
)
102 mbtowc(NULL
, NULL
, 0); /* reset shift state */
105 for (ptr
=*src
, n
=0; nbytes
>0; n
++) {
106 nb
= mbtowc(NULL
, ptr
, nbytes
);
108 mbtowc(NULL
, NULL
, 0);
109 nb
= mbtowc(NULL
, ptr
, strlen(ptr
));
110 return (nb
== -1 ? (size_t)-1 : n
);
119 for (ptr
=*src
, n
=0; n
<len
&& nbytes
>0; n
++, dest
++) {
120 nb
= mbtowc(dest
, ptr
, nbytes
);
122 mbtowc(NULL
, NULL
, 0);
123 nb
= mbtowc(NULL
, ptr
, strlen(ptr
));
125 return (nb
== -1 ? (size_t)-1 : n
);
126 } else if (nb
== 0) {
142 alreadyHasStringValue(XftPattern
*pattern
, const char *object
, char *value
)
148 if (!value
|| value
[0]==0)
152 while ((r
=XftPatternGetString(pattern
, object
, id
, &s
))!=XftResultNoId
) {
153 if (r
== XftResultMatch
&& strcasecmp(value
, s
) == 0) {
163 // check if to add a fallback size too. -Dan
164 // also handle an xlfd with %d for size?
166 makeFontOfSize(char *font
, int size
, char *fallback
)
172 len
= strlen(font
) + 64;
173 pattern
= XftNameParse(font
);
174 XftPatternDel(pattern
, "pixelsize");
175 XftPatternAddDouble(pattern
, "pixelsize", (double)size
);
177 if (!alreadyHasStringValue(pattern
, "family", fallback
)) {
178 len
+= strlen(fallback
);
179 XftPatternAddString(pattern
, "family", fallback
);
182 result
= wmalloc(len
);
183 XftNameUnparse(pattern
, result
, len
);
184 XftPatternDestroy(pattern
);
191 WMCreateFont(WMScreen
*scrPtr
, char *fontName
)
194 Display
*display
= scrPtr
->display
;
197 /* This is for back-compat (to allow reading of old xlfd descriptions) */
198 if (fontName
[0]=='-' && (ptr
= strchr(fontName
, ','))) {
199 fname
= wmalloc(ptr
- fontName
+ 1);
200 strncpy(fname
, fontName
, ptr
- fontName
);
201 fname
[ptr
- fontName
] = 0;
203 fname
= wstrdup(fontName
);
206 font
= WMHashGet(scrPtr
->fontCache
, fname
);
213 font
= wmalloc(sizeof(WMFont
));
214 memset(font
, 0, sizeof(WMFont
));
216 font
->screen
= scrPtr
;
218 printf("%s\n", fname
);
219 if (fname
[0] == '-') {
220 /* Backward compat thing. Remove in a later version */
221 font
->font
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
223 font
->font
= XftFontOpenName(display
, scrPtr
->screen
, fname
);
230 font
->height
= font
->font
->ascent
+font
->font
->descent
;
231 font
->y
= font
->font
->ascent
;
237 assert(WMHashInsert(scrPtr
->fontCache
, font
->name
, font
)==NULL
);
244 WMRetainFont(WMFont
*font
)
246 wassertrv(font
!=NULL
, NULL
);
255 WMReleaseFont(WMFont
*font
)
257 wassertr(font
!=NULL
);
260 if (font
->refCount
< 1) {
261 XftFontClose(font
->screen
->display
, font
->font
);
263 WMHashRemove(font
->screen
->fontCache
, font
->name
);
272 WMIsAntialiasingEnabled(WMScreen
*scrPtr
)
274 return scrPtr
->antialiasedText
;
279 WMFontHeight(WMFont
*font
)
281 wassertrv(font
!=NULL
, 0);
288 WMGetFontName(WMFont
*font
)
290 wassertrv(font
!=NULL
, NULL
);
297 WMDefaultSystemFont(WMScreen
*scrPtr
)
299 return WMRetainFont(scrPtr
->normalFont
);
304 WMDefaultBoldSystemFont(WMScreen
*scrPtr
)
306 return WMRetainFont(scrPtr
->boldFont
);
311 WMSystemFontOfSize(WMScreen
*scrPtr
, int size
)
316 fontSpec
= makeFontOfSize(WINGsConfiguration
.systemFont
, size
, "sans");
318 font
= WMCreateFont(scrPtr
, fontSpec
);
321 wwarning(_("could not load font %s."), fontSpec
);
331 WMBoldSystemFontOfSize(WMScreen
*scrPtr
, int size
)
336 fontSpec
= makeFontOfSize(WINGsConfiguration
.boldSystemFont
, size
, "sans");
338 font
= WMCreateFont(scrPtr
, fontSpec
);
341 wwarning(_("could not load font %s."), fontSpec
);
351 WMWidthOfString(WMFont
*font
, char *text
, int length
)
355 wassertrv(font
!=NULL
, 0);
356 wassertrv(text
!=NULL
, 0);
358 if (font
->screen
->useWideChar
) {
363 wtext
= (wchar_t *)wmalloc(sizeof(wchar_t)*(length
+1));
365 len
= wmbsnrtowcs(wtext
, &mtext
, length
, length
);
367 wtext
[len
] = L
'\0'; /* not really necessary here */
368 XftTextExtents32(font
->screen
->display
, font
->font
,
369 (XftChar32
*)wtext
, len
, &extents
);
372 wwarning(_("Conversion to widechar failed (possible "
373 "invalid multibyte sequence): '%s':(pos %d)\n"),
380 XftTextExtents8(font
->screen
->display
, font
->font
,
381 (XftChar8
*)text
, length
, &extents
);
384 return extents
.xOff
; /* don't ask :P */
390 WMDrawString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMFont
*font
,
391 int x
, int y
, char *text
, int length
)
395 wassertr(font
!=NULL
);
397 xftcolor
.color
.red
= color
->color
.red
;
398 xftcolor
.color
.green
= color
->color
.green
;
399 xftcolor
.color
.blue
= color
->color
.blue
;
400 xftcolor
.color
.alpha
= color
->alpha
;;
401 xftcolor
.pixel
= W_PIXEL(color
);
403 XftDrawChange(scr
->xftdraw
, d
);
405 if (font
->screen
->useWideChar
) {
410 wtext
= (wchar_t *)wmalloc(sizeof(wchar_t)*(length
+1));
412 len
= wmbsnrtowcs(wtext
, &mtext
, length
, length
);
414 XftDrawString32(scr
->xftdraw
, &xftcolor
, font
->font
,
415 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
416 } else if (len
==-1) {
417 wwarning(_("Conversion to widechar failed (possible invalid "
418 "multibyte sequence): '%s':(pos %d)\n"),
420 /* we can draw normal text, or we can draw as much widechar
421 * text as was already converted until the error. go figure */
422 /*XftDrawString8(scr->xftdraw, &xftcolor, font->font,
423 x, y + font->y, (XftChar8*)text, length);*/
427 XftDrawString8(scr
->xftdraw
, &xftcolor
, font
->font
,
428 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
434 WMDrawImageString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMColor
*background
,
435 WMFont
*font
, int x
, int y
, char *text
, int length
)
440 wassertr(font
!=NULL
);
442 textColor
.color
.red
= color
->color
.red
;
443 textColor
.color
.green
= color
->color
.green
;
444 textColor
.color
.blue
= color
->color
.blue
;
445 textColor
.color
.alpha
= color
->alpha
;;
446 textColor
.pixel
= W_PIXEL(color
);
448 bgColor
.color
.red
= background
->color
.red
;
449 bgColor
.color
.green
= background
->color
.green
;
450 bgColor
.color
.blue
= background
->color
.blue
;
451 bgColor
.color
.alpha
= background
->alpha
;;
452 bgColor
.pixel
= W_PIXEL(background
);
454 XftDrawChange(scr
->xftdraw
, d
);
456 XftDrawRect(scr
->xftdraw
, &bgColor
, x
, y
,
457 WMWidthOfString(font
, text
, length
),
460 if (font
->screen
->useWideChar
) {
466 wtext
= (wchar_t *)wmalloc(sizeof(wchar_t)*(length
+1));
467 len
= wmbsnrtowcs(wtext
, &mtext
, length
, length
);
469 XftDrawString32(scr
->xftdraw
, &textColor
, 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, &textColor, font->font,
478 x, y + font->y, (XftChar8*)text, length);*/
482 XftDrawString8(scr
->xftdraw
, &textColor
, font
->font
,
483 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
489 WMCopyFontWithChanges(WMScreen
*scrPtr
, WMFont
*font
,
490 const WMFontAttributes
*changes
)
492 int index
[FONT_PROPS
], count
[FONT_PROPS
];
493 int totalProps
, i
, j
, carry
;
501 snprintf(fname
, 512, "%s", font
->name
);
503 fFlags
= (font
->antialiased
? WFAntialiased
: WFNotAntialiased
);
504 fFlags
|= (font
->notFontSet
? WFNormalFont
: WFFontSet
);
506 props
= WMCreateBagWithDestructor(1, (WMFreeDataProc
*)WMFreeArray
);
509 for (i
=0; i
<FONT_PROPS
; i
++) {
510 prop
= ((W_FontAttributes
*)changes
)->props
[i
];
511 count
[i
] = index
[i
] = 0;
513 /* No change for this property */
515 } else if (strchr(prop
, ',')==NULL
) {
517 changeFontProp(fname
, prop
, i
);
519 /* Option with fallback alternatives */
520 if ((changes
==WFAEmphasized
|| changes
==WFABoldEmphasized
) &&
521 font
->antialiased
&& strcmp(prop
, "o,i")==0) {
522 options
= getOptions("i,o");
524 options
= getOptions(prop
);
526 WMInsertInBag(props
, i
, options
);
527 count
[i
] = WMGetArrayItemCount(options
);
530 totalProps
= totalProps
* count
[i
];
534 if (totalProps
== 0) {
535 /* No options with fallback alternatives at all */
537 return WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
540 for (i
=0; i
<totalProps
; i
++) {
541 for (j
=0; j
<FONT_PROPS
; j
++) {
543 options
= WMGetFromBag(props
, j
);
544 prop
= WMGetFromArray(options
, index
[j
]);
546 changeFontProp(fname
, prop
, j
);
550 result
= WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
555 for (j
=FONT_PROPS
-1, carry
=1; j
>=0; j
--) {
558 carry
= (index
[j
]==count
[j
]);
559 index
[j
] %= count
[j
];
572 #define FONT_PROPS 14
575 char *props
[FONT_PROPS
];
580 changeFontProp(char *buf
, char *newprop
, int position
)
583 char *ptr
, *pptr
, *rptr
;
587 /* // remove warning later. or maybe not */
588 wwarning(_("Invalid font specification: '%s'\n"), buf
);
592 ptr
= pptr
= rptr
= buf
;
594 while (*ptr
&& *ptr
!=',') {
597 if (count
-1==position
+1) {
601 if (count
-1==position
) {
607 if (position
==FONT_PROPS
-1) {
612 snprintf(buf2
, 512, "%s%s%s", buf
, newprop
, rptr
);
618 getOptions(char *options
)
620 char *ptr
, *ptr2
, *str
;
624 result
= WMCreateArrayWithDestructor(2, (WMFreeDataProc
*)wfree
);
628 ptr2
= strchr(ptr
, ',');
630 WMAddToArray(result
, wstrdup(ptr
));
634 str
= wmalloc(count
+1);
635 memcpy(str
, ptr
, count
);
637 WMAddToArray(result
, str
);
649 #else /* No XFT support */
652 static char *makeFontSetOfSize(char *fontset
, int size
);
656 /* XLFD pattern matching */
658 getElementFromXLFD(const char *xlfd
, int index
)
660 const char *p
= xlfd
;
662 if (*p
== '-' && --index
== 0) {
663 const char *end
= strchr(p
+ 1, '-');
666 if (end
== 0) end
= p
+ strlen(p
);
669 memcpy(buf
, p
+ 1, len
);
679 /* XLFD pattern matching */
681 generalizeXLFD(const char *xlfd
)
685 char *weight
= getElementFromXLFD(xlfd
, 3);
686 char *slant
= getElementFromXLFD(xlfd
, 4);
687 char *pxlsz
= getElementFromXLFD(xlfd
, 7);
689 #define Xstrlen(A) ((A)?strlen(A):0)
690 len
= Xstrlen(xlfd
)+Xstrlen(weight
)+Xstrlen(slant
)+Xstrlen(pxlsz
)*2+60;
693 buf
= wmalloc(len
+ 1);
694 snprintf(buf
, len
+ 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
695 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
696 xlfd
, weight
, slant
, pxlsz
, pxlsz
);
705 /* XLFD pattern matching */
707 W_CreateFontSetWithGuess(Display
*dpy
, char *xlfd
, char ***missing
,
708 int *nmissing
, char **def_string
)
710 XFontSet fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
712 if (fs
!= NULL
&& *nmissing
== 0) return fs
;
714 /* for non-iso8859-1 language and iso8859-1 specification
715 (this fontset is only for pattern analysis) */
717 if (*nmissing
!= 0) XFreeStringList(*missing
);
718 setlocale(LC_CTYPE
, "C");
719 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
720 setlocale(LC_CTYPE
, "");
723 /* make XLFD font name for pattern analysis */
725 XFontStruct
**fontstructs
;
727 if (XFontsOfFontSet(fs
, &fontstructs
, &fontnames
) > 0)
731 xlfd
= generalizeXLFD(xlfd
);
733 if (*nmissing
!= 0) XFreeStringList(*missing
);
734 if (fs
!= NULL
) XFreeFontSet(dpy
, fs
);
736 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
744 xlfdFromFontName(char *fontName
, Bool antialiased
)
746 char *systemFont
, *boldSystemFont
;
751 systemFont
= WINGsConfiguration
.antialiasedSystemFont
;
752 boldSystemFont
= WINGsConfiguration
.antialiasedBoldSystemFont
;
754 systemFont
= WINGsConfiguration
.systemFont
;
755 boldSystemFont
= WINGsConfiguration
.boldSystemFont
;
758 size
= WINGsConfiguration
.defaultFontSize
;
760 if (strcmp(fontName
, "SystemFont")==0) {
762 size
= WINGsConfiguration
.defaultFontSize
;
763 } else if (strncmp(fontName
, "SystemFont-", 11)==0) {
765 if (sscanf(&fontName
[11], "%i", &size
)!=1) {
766 size
= WINGsConfiguration
.defaultFontSize
;
767 wwarning(_("Invalid size specification '%s' in %s. "
768 "Using default %d\n"), &fontName
[11], fontName
, size
);
770 } else if (strcmp(fontName
, "BoldSystemFont")==0) {
771 font
= boldSystemFont
;
772 size
= WINGsConfiguration
.defaultFontSize
;
773 } else if (strncmp(fontName
, "BoldSystemFont-", 15)==0) {
774 font
= boldSystemFont
;
775 if (sscanf(&fontName
[15], "%i", &size
)!=1) {
776 size
= WINGsConfiguration
.defaultFontSize
;
777 wwarning(_("Invalid size specification '%s' in %s. "
778 "Using default %d\n"), &fontName
[15], fontName
, size
);
784 return (font
!=NULL
? makeFontSetOfSize(font
, size
) : wstrdup(fontName
));
789 WMCreateFontSet(WMScreen
*scrPtr
, char *fontName
)
792 Display
*display
= scrPtr
->display
;
797 XFontSetExtents
*extents
;
799 fname
= xlfdFromFontName(fontName
, False
);
801 font
= WMHashGet(scrPtr
->fontSetCache
, fname
);
808 font
= wmalloc(sizeof(WMFont
));
809 memset(font
, 0, sizeof(WMFont
));
811 font
->notFontSet
= 0;
812 font
->antialiased
= 0;
814 font
->screen
= scrPtr
;
816 font
->font
.set
= W_CreateFontSetWithGuess(display
, fname
, &missing
,
817 &nmissing
, &defaultString
);
818 if (nmissing
> 0 && font
->font
.set
) {
821 wwarning(_("the following character sets are missing in %s:"), fname
);
822 for (i
= 0; i
< nmissing
; i
++) {
823 wwarning(missing
[i
]);
825 XFreeStringList(missing
);
827 wwarning(_("the string \"%s\" will be used in place of any characters from those sets."),
830 if (!font
->font
.set
) {
836 extents
= XExtentsOfFontSet(font
->font
.set
);
838 font
->height
= extents
->max_logical_extent
.height
;
839 font
->y
= font
->height
- (font
->height
+ extents
->max_logical_extent
.y
);
845 assert(WMHashInsert(scrPtr
->fontSetCache
, font
->name
, font
)==NULL
);
853 WMCreateNormalFont(WMScreen
*scrPtr
, char *fontName
)
856 Display
*display
= scrPtr
->display
;
859 fontName
= xlfdFromFontName(fontName
, False
);
861 if ((ptr
= strchr(fontName
, ','))) {
862 fname
= wmalloc(ptr
- fontName
+ 1);
863 strncpy(fname
, fontName
, ptr
- fontName
);
864 fname
[ptr
- fontName
] = 0;
866 fname
= wstrdup(fontName
);
871 font
= WMHashGet(scrPtr
->fontCache
, fname
);
878 font
= wmalloc(sizeof(WMFont
));
879 memset(font
, 0, sizeof(WMFont
));
881 font
->notFontSet
= 1;
882 font
->antialiased
= 0;
884 font
->screen
= scrPtr
;
886 font
->font
.normal
= XLoadQueryFont(display
, fname
);
887 if (!font
->font
.normal
) {
892 font
->height
= font
->font
.normal
->ascent
+font
->font
.normal
->descent
;
893 font
->y
= font
->font
.normal
->ascent
;
899 assert(WMHashInsert(scrPtr
->fontCache
, font
->name
, font
)==NULL
);
906 WMCreateAntialiasedFont(WMScreen
*scrPtr
, char *fontName
)
910 Display
*display
= scrPtr
->display
;
913 fontName
= xlfdFromFontName(fontName
, True
);
915 if ((ptr
= strchr(fontName
, ','))) {
916 fname
= wmalloc(ptr
- fontName
+ 1);
917 strncpy(fname
, fontName
, ptr
- fontName
);
918 fname
[ptr
- fontName
] = 0;
920 fname
= wstrdup(fontName
);
925 font
= WMHashGet(scrPtr
->xftFontCache
, fname
);
932 font
= wmalloc(sizeof(WMFont
));
933 memset(font
, 0, sizeof(WMFont
));
935 font
->notFontSet
= 1;
936 font
->antialiased
= 1;
938 font
->screen
= scrPtr
;
940 /* Xft sux. Loading a font with an invalid XLFD will give strange results
941 * sometimes without returning any warning or error.
942 * However Xft's idea of what font is invalid is quite strange:
943 * 1. If the XLFD doesn't have all its fields present will fail and
945 * 2. If all fields are present, but hold invalid values then it will:
946 * a. If family is invalid, will load a default font without warning.
947 * b. If the font size is invalid (non-numerical) it will fail and
949 * c. If other fields are invalid, will load the font specified by
950 * the valid family name, ignoring any invalid fields. It will
951 * use a default medium weight and a default roman slant if they
954 printf("%s\n", fname
);
955 if (fname
[0] == '-') {
956 font
->font
.xft
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
958 font
->font
.xft
= XftFontOpenName(display
, scrPtr
->screen
, fname
);
960 if (!font
->font
.xft
) {
965 font
->height
= font
->font
.xft
->ascent
+font
->font
.xft
->descent
;
966 font
->y
= font
->font
.xft
->ascent
;
972 assert(WMHashInsert(scrPtr
->xftFontCache
, font
->name
, font
)==NULL
);
982 WMCreateAntialiasedFontSet(WMScreen
*scrPtr
, char *fontName
)
986 Display
*display
= scrPtr
->display
;
989 fontName
= xlfdFromFontName(fontName
, True
);
991 if ((ptr
= strchr(fontName
, ','))) {
992 fname
= wmalloc(ptr
- fontName
+ 1);
993 strncpy(fname
, fontName
, ptr
- fontName
);
994 fname
[ptr
- fontName
] = 0;
996 fname
= wstrdup(fontName
);
1001 font
= WMHashGet(scrPtr
->xftFontSetCache
, fname
);
1008 font
= wmalloc(sizeof(WMFont
));
1009 memset(font
, 0, sizeof(WMFont
));
1011 font
->notFontSet
= 0;
1012 font
->antialiased
= 1;
1014 font
->screen
= scrPtr
;
1016 /* Xft sux. Loading a font with an invalid XLFD will give strange results
1017 * sometimes without returning any warning or error.
1018 * However Xft's idea of what font is invalid is quite strange:
1019 * 1. If the XLFD doesn't have all its fields present will fail and
1021 * 2. If all fields are present, but hold invalid values then it will:
1022 * a. If family is invalid, will load a default font without warning.
1023 * b. If the font size is invalid (non-numerical) it will fail and
1025 * c. If other fields are invalid, will load the font specified by
1026 * the valid family name, ignoring any invalid fields. It will
1027 * use a default medium weight and a default roman slant if they
1030 if (fname
[0] == '-') {
1031 font
->font
.xft
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
1033 font
->font
.xft
= XftFontOpenName(display
, scrPtr
->screen
, fname
);
1035 if (!font
->font
.xft
) {
1040 font
->height
= font
->font
.xft
->ascent
+font
->font
.xft
->descent
;
1041 font
->y
= font
->font
.xft
->ascent
;
1047 assert(WMHashInsert(scrPtr
->xftFontSetCache
, font
->name
, font
)==NULL
);
1057 WMCreateFont(WMScreen
*scrPtr
, char *fontName
)
1059 return WMCreateFontWithFlags(scrPtr
, fontName
, WFDefaultFont
);
1064 WMCreateFontWithFlags(WMScreen
*scrPtr
, char *fontName
, WMFontFlags flags
)
1066 Bool multiByte
= scrPtr
->useMultiByte
;
1067 Bool antialiased
= scrPtr
->antialiasedText
;
1070 if (flags
& WFFontSet
) {
1072 } else if (flags
& WFNormalFont
) {
1075 if (flags
& WFAntialiased
) {
1077 } else if (flags
& WFNotAntialiased
) {
1078 antialiased
= False
;
1081 if (antialiased
&& multiByte
) {
1082 font
= WMCreateAntialiasedFontSet(scrPtr
, fontName
);
1083 /* If we cannot create an antialiased font set and antialiasing is
1084 * not explicitly requested in flags, fallback to standard font sets */
1085 if (!font
&& (flags
& WFAntialiased
)==0) {
1086 font
= WMCreateFontSet(scrPtr
, fontName
);
1088 } else if (antialiased
) {
1089 font
= WMCreateAntialiasedFont(scrPtr
, fontName
);
1090 /* If we cannot create an antialiased font and antialiasing is
1091 * not explicitly requested in flags, fallback to normal font */
1092 if (!font
&& (flags
& WFAntialiased
)==0) {
1093 font
= WMCreateNormalFont(scrPtr
, fontName
);
1095 } else if (multiByte
) {
1096 font
= WMCreateFontSet(scrPtr
, fontName
);
1098 font
= WMCreateNormalFont(scrPtr
, fontName
);
1106 WMRetainFont(WMFont
*font
)
1108 wassertrv(font
!=NULL
, NULL
);
1117 WMReleaseFont(WMFont
*font
)
1119 wassertr(font
!=NULL
);
1122 if (font
->refCount
< 1) {
1123 if (font
->antialiased
) {
1125 XftFontClose(font
->screen
->display
, font
->font
.xft
);
1129 } else if (font
->notFontSet
) {
1130 XFreeFont(font
->screen
->display
, font
->font
.normal
);
1132 XFreeFontSet(font
->screen
->display
, font
->font
.set
);
1136 if (font
->antialiased
&& !font
->notFontSet
) {
1137 WMHashRemove(font
->screen
->xftFontSetCache
, font
->name
);
1138 } else if (font
->antialiased
) {
1139 WMHashRemove(font
->screen
->xftFontCache
, font
->name
);
1140 } else if (font
->notFontSet
) {
1141 WMHashRemove(font
->screen
->fontCache
, font
->name
);
1143 WMHashRemove(font
->screen
->fontSetCache
, font
->name
);
1153 WMIsAntialiasingEnabled(WMScreen
*scrPtr
)
1155 return scrPtr
->antialiasedText
;
1160 WMIsAntialiasedFont(WMFont
*font
)
1162 wassertrv(font
!=NULL
, False
);
1164 return font
->antialiased
;
1169 WMFontHeight(WMFont
*font
)
1171 wassertrv(font
!=NULL
, 0);
1173 return font
->height
;
1178 WMGetFontName(WMFont
*font
)
1180 wassertrv(font
!=NULL
, NULL
);
1187 WMDefaultSystemFont(WMScreen
*scrPtr
)
1189 return WMRetainFont(scrPtr
->normalFont
);
1194 WMDefaultBoldSystemFont(WMScreen
*scrPtr
)
1196 return WMRetainFont(scrPtr
->boldFont
);
1201 makeSystemFontOfSize(WMScreen
*scrPtr
, int size
, Bool bold
)
1204 char *fontSpec
, *xftFontSpec
;
1206 #define WConf WINGsConfiguration
1208 fontSpec
= makeFontSetOfSize(WConf
.boldSystemFont
, size
);
1209 xftFontSpec
= makeFontSetOfSize(WConf
.antialiasedBoldSystemFont
, size
);
1211 fontSpec
= makeFontSetOfSize(WConf
.systemFont
, size
);
1212 xftFontSpec
= makeFontSetOfSize(WConf
.antialiasedSystemFont
, size
);
1216 if (scrPtr
->antialiasedText
&& scrPtr
->useMultiByte
) {
1217 font
= WMCreateAntialiasedFontSet(scrPtr
, xftFontSpec
);
1218 } else if (scrPtr
->antialiasedText
) {
1219 font
= WMCreateAntialiasedFont(scrPtr
, xftFontSpec
);
1220 } else if (scrPtr
->useMultiByte
) {
1221 font
= WMCreateFontSet(scrPtr
, fontSpec
);
1223 font
= WMCreateNormalFont(scrPtr
, fontSpec
);
1227 if (scrPtr
->antialiasedText
&& scrPtr
->useMultiByte
) {
1228 // is arial a good fallback for multibyte?
1229 wwarning(_("could not load font %s. Trying arial."), xftFontSpec
);
1231 font
= WMCreateAntialiasedFontSet(scrPtr
, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
1233 font
= WMCreateAntialiasedFontSet(scrPtr
, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
1236 wwarning(_("could not load antialiased font set. Reverting to standard font sets."));
1237 font
= WMCreateFontSet(scrPtr
, fontSpec
);
1239 wwarning(_("could not load FontSet %s. Trying fixed."), fontSpec
);
1240 font
= WMCreateFontSet(scrPtr
, "fixed");
1243 } else if (scrPtr
->antialiasedText
) {
1244 wwarning(_("could not load font %s. Trying arial."), xftFontSpec
);
1246 font
= WMCreateAntialiasedFont(scrPtr
, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
1248 font
= WMCreateAntialiasedFont(scrPtr
, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
1251 wwarning(_("could not load antialiased fonts. Reverting to normal fonts."));
1252 font
= WMCreateNormalFont(scrPtr
, fontSpec
);
1254 wwarning(_("could not load font %s. Trying fixed."), fontSpec
);
1255 font
= WMCreateNormalFont(scrPtr
, "fixed");
1258 } else if (scrPtr
->useMultiByte
) {
1259 wwarning(_("could not load font set %s. Trying fixed."), fontSpec
);
1260 font
= WMCreateFontSet(scrPtr
, "fixed");
1262 font
= WMCreateFontSet(scrPtr
, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
1265 wwarning(_("could not load font %s. Trying fixed."), fontSpec
);
1266 font
= WMCreateNormalFont(scrPtr
, "fixed");
1269 wwarning(_("could not load fixed font!"));
1283 WMSystemFontOfSize(WMScreen
*scrPtr
, int size
)
1285 return makeSystemFontOfSize(scrPtr
, size
, False
);
1290 WMBoldSystemFontOfSize(WMScreen
*scrPtr
, int size
)
1292 return makeSystemFontOfSize(scrPtr
, size
, True
);
1297 WMGetFontFontSet(WMFont
*font
)
1299 wassertrv(font
!=NULL
, NULL
);
1301 if (!font
->notFontSet
&& !font
->antialiased
)
1302 return font
->font
.set
;
1309 WMWidthOfString(WMFont
*font
, char *text
, int length
)
1311 wassertrv(font
!=NULL
, 0);
1312 wassertrv(text
!=NULL
, 0);
1314 if (font
->antialiased
) {
1318 if (!font
->notFontSet
) {
1323 /* Use mtext instead of text, because mbstrtowcs() alters it */
1325 wtext
= (wchar_t *)wmalloc(4*length
+4);
1326 /* pass a real ps instead of NULL below? for multithread safety
1327 * as from manual page */
1328 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
1330 XftTextExtents32(font
->screen
->display
, font
->font
.xft
,
1331 (XftChar32
*)wtext
, len
, &extents
);
1334 wwarning(_("Conversion to widechar failed (possible "
1335 "invalid multibyte sequence): '%s':(pos %d)\n"),
1336 text
, mtext
-text
+1);
1342 XftTextExtents8(font
->screen
->display
, font
->font
.xft
,
1343 (XftChar8
*)text
, length
, &extents
);
1346 return extents
.xOff
; /* don't ask :P */
1348 wassertrv(False
, 0);
1350 } else if (font
->notFontSet
) {
1351 return XTextWidth(font
->font
.normal
, text
, length
);
1354 XRectangle AIXsucks
;
1356 XmbTextExtents(font
->font
.set
, text
, length
, &AIXsucks
, &rect
);
1365 WMDrawString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMFont
*font
,
1366 int x
, int y
, char *text
, int length
)
1368 wassertr(font
!=NULL
);
1370 if (font
->antialiased
) {
1374 xftcolor
.color
.red
= color
->color
.red
;
1375 xftcolor
.color
.green
= color
->color
.green
;
1376 xftcolor
.color
.blue
= color
->color
.blue
;
1377 xftcolor
.color
.alpha
= color
->alpha
;;
1378 xftcolor
.pixel
= W_PIXEL(color
);
1380 XftDrawChange(scr
->xftdraw
, d
);
1382 if (!font
->notFontSet
) {
1387 /* Use mtext instead of text, because mbstrtowcs() alters it */
1389 wtext
= (wchar_t *)wmalloc(4*length
+4);
1390 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
1392 XftDrawString32(scr
->xftdraw
, &xftcolor
, font
->font
.xft
,
1393 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
1394 } else if (len
==-1) {
1395 wwarning(_("Conversion to widechar failed (possible invalid "
1396 "multibyte sequence): '%s':(pos %d)\n"),
1397 text
, mtext
-text
+1);
1398 /* we can draw normal text, or we can draw as much widechar
1399 * text as was already converted until the error. go figure */
1400 /*XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
1401 x, y + font->y, (XftChar8*)text, length);*/
1405 XftDrawString8(scr
->xftdraw
, &xftcolor
, font
->font
.xft
,
1406 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
1411 } else if (font
->notFontSet
) {
1412 XSetFont(scr
->display
, scr
->drawStringGC
, font
->font
.normal
->fid
);
1413 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
1414 XDrawString(scr
->display
, d
, scr
->drawStringGC
, x
, y
+ font
->y
,
1417 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
1418 XmbDrawString(scr
->display
, d
, font
->font
.set
, scr
->drawStringGC
,
1419 x
, y
+ font
->y
, text
, length
);
1425 WMDrawImageString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMColor
*background
,
1426 WMFont
*font
, int x
, int y
, char *text
, int length
)
1428 wassertr(font
!=NULL
);
1430 if (font
->antialiased
) {
1435 textColor
.color
.red
= color
->color
.red
;
1436 textColor
.color
.green
= color
->color
.green
;
1437 textColor
.color
.blue
= color
->color
.blue
;
1438 textColor
.color
.alpha
= color
->alpha
;;
1439 textColor
.pixel
= W_PIXEL(color
);
1441 bgColor
.color
.red
= background
->color
.red
;
1442 bgColor
.color
.green
= background
->color
.green
;
1443 bgColor
.color
.blue
= background
->color
.blue
;
1444 bgColor
.color
.alpha
= background
->alpha
;;
1445 bgColor
.pixel
= W_PIXEL(background
);
1448 XftDrawChange(scr
->xftdraw
, d
);
1450 XftDrawRect(scr
->xftdraw
, &bgColor
, x
, y
,
1451 WMWidthOfString(font
, text
, length
), font
->height
);
1453 if (!font
->notFontSet
) {
1458 /* Use mtext instead of text, because mbstrtowcs() alters it */
1460 wtext
= (wchar_t *)wmalloc(4*length
+4);
1461 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
1463 XftDrawString32(scr
->xftdraw
, &textColor
, font
->font
.xft
,
1464 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
1465 } else if (len
==-1) {
1466 wwarning(_("Conversion to widechar failed (possible invalid "
1467 "multibyte sequence): '%s':(pos %d)\n"),
1468 text
, mtext
-text
+1);
1469 /* we can draw normal text, or we can draw as much widechar
1470 * text as was already converted until the error. go figure */
1471 /*XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
1472 x, y + font->y, (XftChar8*)text, length);*/
1476 XftDrawString8(scr
->xftdraw
, &textColor
, font
->font
.xft
,
1477 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
1482 } else if (font
->notFontSet
) {
1483 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
1484 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
1485 XSetFont(scr
->display
, scr
->drawImStringGC
, font
->font
.normal
->fid
);
1486 XDrawImageString(scr
->display
, d
, scr
->drawImStringGC
,
1487 x
, y
+ font
->y
, text
, length
);
1489 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
1490 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
1491 XmbDrawImageString(scr
->display
, d
, font
->font
.set
, scr
->drawImStringGC
,
1492 x
, y
+ font
->y
, text
, length
);
1500 makeFontSetOfSize(char *fontset
, int size
)
1512 ptr
= strchr(fontset
, ',');
1514 int count
= ptr
-fontset
;
1517 wwarning(_("font description %s is too large."), fontset
);
1519 memcpy(font
, fontset
, count
);
1526 end
= strlen(newfs
);
1530 tmp
= wmalloc(end
+ strlen(f
) + 8);
1532 sprintf(tmp
, "%s,", newfs
);
1533 sprintf(tmp
+ end
+ 1, f
, size
);
1535 sprintf(tmp
+ end
, f
, size
);
1543 } while (ptr
!=NULL
);
1549 #define FONT_PROPS 14
1552 char *props
[FONT_PROPS
];
1557 changeFontProp(char *buf
, char *newprop
, int position
)
1560 char *ptr
, *pptr
, *rptr
;
1564 /* // remove warning later. or maybe not */
1565 wwarning(_("Invalid font specification: '%s'\n"), buf
);
1569 ptr
= pptr
= rptr
= buf
;
1571 while (*ptr
&& *ptr
!=',') {
1574 if (count
-1==position
+1) {
1578 if (count
-1==position
) {
1584 if (position
==FONT_PROPS
-1) {
1589 snprintf(buf2
, 512, "%s%s%s", buf
, newprop
, rptr
);
1595 getOptions(char *options
)
1597 char *ptr
, *ptr2
, *str
;
1601 result
= WMCreateArrayWithDestructor(2, (WMFreeDataProc
*)wfree
);
1605 ptr2
= strchr(ptr
, ',');
1607 WMAddToArray(result
, wstrdup(ptr
));
1611 str
= wmalloc(count
+1);
1612 memcpy(str
, ptr
, count
);
1614 WMAddToArray(result
, str
);
1624 WMCopyFontWithChanges(WMScreen
*scrPtr
, WMFont
*font
,
1625 const WMFontAttributes
*changes
)
1627 int index
[FONT_PROPS
], count
[FONT_PROPS
];
1628 int totalProps
, i
, j
, carry
;
1636 snprintf(fname
, 512, "%s", font
->name
);
1638 fFlags
= (font
->antialiased
? WFAntialiased
: WFNotAntialiased
);
1639 fFlags
|= (font
->notFontSet
? WFNormalFont
: WFFontSet
);
1641 props
= WMCreateBagWithDestructor(1, (WMFreeDataProc
*)WMFreeArray
);
1644 for (i
=0; i
<FONT_PROPS
; i
++) {
1645 prop
= ((W_FontAttributes
*)changes
)->props
[i
];
1646 count
[i
] = index
[i
] = 0;
1648 /* No change for this property */
1650 } else if (strchr(prop
, ',')==NULL
) {
1652 changeFontProp(fname
, prop
, i
);
1654 /* Option with fallback alternatives */
1655 if ((changes
==WFAEmphasized
|| changes
==WFABoldEmphasized
) &&
1656 font
->antialiased
&& strcmp(prop
, "o,i")==0) {
1657 options
= getOptions("i,o");
1659 options
= getOptions(prop
);
1661 WMInsertInBag(props
, i
, options
);
1662 count
[i
] = WMGetArrayItemCount(options
);
1665 totalProps
= totalProps
* count
[i
];
1669 if (totalProps
== 0) {
1670 /* No options with fallback alternatives at all */
1672 return WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
1675 for (i
=0; i
<totalProps
; i
++) {
1676 for (j
=0; j
<FONT_PROPS
; j
++) {
1678 options
= WMGetFromBag(props
, j
);
1679 prop
= WMGetFromArray(options
, index
[j
]);
1681 changeFontProp(fname
, prop
, j
);
1685 result
= WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
1690 for (j
=FONT_PROPS
-1, carry
=1; j
>=0; j
--) {
1693 carry
= (index
[j
]==count
[j
]);
1694 index
[j
] %= count
[j
];
1707 // should WFANormal also set "normal" or leave it alone?
1708 static const WMFontAttributes W_FANormal
= {
1709 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", "r", "normal",
1710 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1711 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1715 static const WMFontAttributes W_FABold
= {
1716 WFAUnchanged
, WFAUnchanged
, "bold", WFAUnchanged
,
1717 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1718 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1722 static const WMFontAttributes W_FANotBold
= {
1723 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", WFAUnchanged
,
1724 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1725 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1729 static const WMFontAttributes W_FAEmphasized
= {
1730 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "o,i",
1731 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1732 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1736 static const WMFontAttributes W_FANotEmphasized
= {
1737 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "r",
1738 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1739 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1743 static const WMFontAttributes W_FABoldEmphasized
= {
1744 WFAUnchanged
, WFAUnchanged
, "bold", "o,i",
1745 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1746 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1750 const WMFontAttributes
*WFANormal
= &W_FANormal
;
1751 const WMFontAttributes
*WFABold
= &W_FABold
;
1752 const WMFontAttributes
*WFANotBold
= &W_FANotBold
;
1753 const WMFontAttributes
*WFAEmphasized
= &W_FAEmphasized
;
1754 const WMFontAttributes
*WFANotEmphasized
= &W_FANotEmphasized
;
1755 const WMFontAttributes
*WFABoldEmphasized
= &W_FABoldEmphasized
;