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
))==XftResultMatch
) {
153 if (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
)
171 pattern
= XftNameParse(font
);
172 XftPatternDel(pattern
, "pixelsize");
173 XftPatternAddDouble(pattern
, "pixelsize", (double)size
);
176 if (!alreadyHasStringValue(pattern
, "family", fallback
)) {
177 XftPatternAddString(pattern
, "family", fallback
);
181 result
= FcNameUnparse(pattern
);
182 FcPatternDestroy(pattern
);
189 WMCreateFont(WMScreen
*scrPtr
, char *fontName
)
192 Display
*display
= scrPtr
->display
;
195 /* This is for back-compat (to allow reading of old xlfd descriptions) */
196 if (fontName
[0]=='-' && (ptr
= strchr(fontName
, ','))) {
197 // warn for deprecation
198 fname
= wmalloc(ptr
- fontName
+ 1);
199 strncpy(fname
, fontName
, ptr
- fontName
);
200 fname
[ptr
- fontName
] = 0;
202 fname
= wstrdup(fontName
);
205 font
= WMHashGet(scrPtr
->fontCache
, fname
);
212 font
= wmalloc(sizeof(WMFont
));
213 memset(font
, 0, sizeof(WMFont
));
215 font
->screen
= scrPtr
;
218 printf("WMCreateFont: %s\n", fname
);
220 if (fname
[0] == '-') {
221 // Backward compat thing. Remove in a later version
222 font
->font
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
224 font
->font
= XftFontOpenName(display
, scrPtr
->screen
, fname
);
231 font
->height
= font
->font
->ascent
+font
->font
->descent
;
232 font
->y
= font
->font
->ascent
;
238 assert(WMHashInsert(scrPtr
->fontCache
, font
->name
, font
)==NULL
);
245 WMRetainFont(WMFont
*font
)
247 wassertrv(font
!=NULL
, NULL
);
256 WMReleaseFont(WMFont
*font
)
258 wassertr(font
!=NULL
);
261 if (font
->refCount
< 1) {
262 XftFontClose(font
->screen
->display
, font
->font
);
264 WMHashRemove(font
->screen
->fontCache
, font
->name
);
273 WMIsAntialiasingEnabled(WMScreen
*scrPtr
)
275 return scrPtr
->antialiasedText
;
280 WMFontHeight(WMFont
*font
)
282 wassertrv(font
!=NULL
, 0);
289 WMGetFontName(WMFont
*font
)
291 wassertrv(font
!=NULL
, NULL
);
298 WMDefaultSystemFont(WMScreen
*scrPtr
)
300 return WMRetainFont(scrPtr
->normalFont
);
305 WMDefaultBoldSystemFont(WMScreen
*scrPtr
)
307 return WMRetainFont(scrPtr
->boldFont
);
312 WMSystemFontOfSize(WMScreen
*scrPtr
, int size
)
317 fontSpec
= makeFontOfSize(WINGsConfiguration
.systemFont
, size
, "sans");
319 font
= WMCreateFont(scrPtr
, fontSpec
);
322 wwarning(_("could not load font %s."), fontSpec
);
332 WMBoldSystemFontOfSize(WMScreen
*scrPtr
, int size
)
337 fontSpec
= makeFontOfSize(WINGsConfiguration
.boldSystemFont
, size
, "sans");
339 font
= WMCreateFont(scrPtr
, fontSpec
);
342 wwarning(_("could not load font %s."), fontSpec
);
352 WMWidthOfString(WMFont
*font
, char *text
, int length
)
356 wassertrv(font
!=NULL
, 0);
357 wassertrv(text
!=NULL
, 0);
359 if (font
->screen
->useWideChar
) {
364 wtext
= (wchar_t *)wmalloc(sizeof(wchar_t)*(length
+1));
366 len
= wmbsnrtowcs(wtext
, &mtext
, length
, length
);
368 wtext
[len
] = L
'\0'; /* not really necessary here */
369 XftTextExtents32(font
->screen
->display
, font
->font
,
370 (XftChar32
*)wtext
, len
, &extents
);
373 wwarning(_("Conversion to widechar failed (possible "
374 "invalid multibyte sequence): '%s':(pos %d)\n"),
381 XftTextExtents8(font
->screen
->display
, font
->font
,
382 (XftChar8
*)text
, length
, &extents
);
385 return extents
.xOff
; /* don't ask :P */
391 WMDrawString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMFont
*font
,
392 int x
, int y
, char *text
, int length
)
396 wassertr(font
!=NULL
);
398 xftcolor
.color
.red
= color
->color
.red
;
399 xftcolor
.color
.green
= color
->color
.green
;
400 xftcolor
.color
.blue
= color
->color
.blue
;
401 xftcolor
.color
.alpha
= color
->alpha
;;
402 xftcolor
.pixel
= W_PIXEL(color
);
404 XftDrawChange(scr
->xftdraw
, d
);
406 if (font
->screen
->useWideChar
) {
411 wtext
= (wchar_t *)wmalloc(sizeof(wchar_t)*(length
+1));
413 len
= wmbsnrtowcs(wtext
, &mtext
, length
, length
);
415 XftDrawString32(scr
->xftdraw
, &xftcolor
, font
->font
,
416 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
417 } else if (len
==-1) {
418 wwarning(_("Conversion to widechar failed (possible invalid "
419 "multibyte sequence): '%s':(pos %d)\n"),
421 /* we can draw normal text, or we can draw as much widechar
422 * text as was already converted until the error. go figure */
423 /*XftDrawString8(scr->xftdraw, &xftcolor, font->font,
424 x, y + font->y, (XftChar8*)text, length);*/
428 XftDrawString8(scr
->xftdraw
, &xftcolor
, font
->font
,
429 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
435 WMDrawImageString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMColor
*background
,
436 WMFont
*font
, int x
, int y
, char *text
, int length
)
441 wassertr(font
!=NULL
);
443 textColor
.color
.red
= color
->color
.red
;
444 textColor
.color
.green
= color
->color
.green
;
445 textColor
.color
.blue
= color
->color
.blue
;
446 textColor
.color
.alpha
= color
->alpha
;;
447 textColor
.pixel
= W_PIXEL(color
);
449 bgColor
.color
.red
= background
->color
.red
;
450 bgColor
.color
.green
= background
->color
.green
;
451 bgColor
.color
.blue
= background
->color
.blue
;
452 bgColor
.color
.alpha
= background
->alpha
;;
453 bgColor
.pixel
= W_PIXEL(background
);
455 XftDrawChange(scr
->xftdraw
, d
);
457 XftDrawRect(scr
->xftdraw
, &bgColor
, x
, y
,
458 WMWidthOfString(font
, text
, length
),
461 if (font
->screen
->useWideChar
) {
467 wtext
= (wchar_t *)wmalloc(sizeof(wchar_t)*(length
+1));
468 len
= wmbsnrtowcs(wtext
, &mtext
, length
, length
);
470 XftDrawString32(scr
->xftdraw
, &textColor
, font
->font
,
471 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
472 } else if (len
==-1) {
473 wwarning(_("Conversion to widechar failed (possible invalid "
474 "multibyte sequence): '%s':(pos %d)\n"),
476 /* we can draw normal text, or we can draw as much widechar
477 * text as was already converted until the error. go figure */
478 /*XftDrawString8(scr->xftdraw, &textColor, font->font,
479 x, y + font->y, (XftChar8*)text, length);*/
483 XftDrawString8(scr
->xftdraw
, &textColor
, font
->font
,
484 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
490 WMCopyFontWithStyle(WMScreen
*scrPtr
, WMFont
*font
, WMFontStyle style
)
499 pattern
= XftNameParse(WMGetFontName(font
));
502 XftPatternDel(pattern
, "weight");
503 XftPatternDel(pattern
, "slant");
504 XftPatternAddString(pattern
, "weight", "medium");
505 XftPatternAddString(pattern
, "slant", "roman");
508 XftPatternDel(pattern
, "weight");
509 XftPatternAddString(pattern
, "weight", "bold");
512 XftPatternDel(pattern
, "slant");
513 XftPatternAddString(pattern
, "slant", "italic");
514 XftPatternAddString(pattern
, "slant", "oblique");
516 case WFSBoldEmphasized
:
517 XftPatternDel(pattern
, "weight");
518 XftPatternDel(pattern
, "slant");
519 XftPatternAddString(pattern
, "weight", "bold");
520 XftPatternAddString(pattern
, "slant", "italic");
521 XftPatternAddString(pattern
, "slant", "oblique");
525 name
= FcNameUnparse(pattern
);
526 copy
= WMCreateFont(scrPtr
, name
);
527 FcPatternDestroy(pattern
);
534 #else /* No XFT support */
537 static char *makeFontSetOfSize(char *fontset
, int size
);
541 /* XLFD pattern matching */
543 getElementFromXLFD(const char *xlfd
, int index
)
545 const char *p
= xlfd
;
547 if (*p
== '-' && --index
== 0) {
548 const char *end
= strchr(p
+ 1, '-');
551 if (end
== 0) end
= p
+ strlen(p
);
554 memcpy(buf
, p
+ 1, len
);
564 /* XLFD pattern matching */
566 generalizeXLFD(const char *xlfd
)
570 char *weight
= getElementFromXLFD(xlfd
, 3);
571 char *slant
= getElementFromXLFD(xlfd
, 4);
572 char *pxlsz
= getElementFromXLFD(xlfd
, 7);
574 #define Xstrlen(A) ((A)?strlen(A):0)
575 len
= Xstrlen(xlfd
)+Xstrlen(weight
)+Xstrlen(slant
)+Xstrlen(pxlsz
)*2+60;
578 buf
= wmalloc(len
+ 1);
579 snprintf(buf
, len
+ 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
580 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
581 xlfd
, weight
, slant
, pxlsz
, pxlsz
);
590 /* XLFD pattern matching */
592 W_CreateFontSetWithGuess(Display
*dpy
, char *xlfd
, char ***missing
,
593 int *nmissing
, char **def_string
)
595 XFontSet fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
597 if (fs
!= NULL
&& *nmissing
== 0) return fs
;
599 /* for non-iso8859-1 language and iso8859-1 specification
600 (this fontset is only for pattern analysis) */
602 if (*nmissing
!= 0) XFreeStringList(*missing
);
603 setlocale(LC_CTYPE
, "C");
604 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
605 setlocale(LC_CTYPE
, "");
608 /* make XLFD font name for pattern analysis */
610 XFontStruct
**fontstructs
;
612 if (XFontsOfFontSet(fs
, &fontstructs
, &fontnames
) > 0)
616 xlfd
= generalizeXLFD(xlfd
);
618 if (*nmissing
!= 0) XFreeStringList(*missing
);
619 if (fs
!= NULL
) XFreeFontSet(dpy
, fs
);
621 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
629 xlfdFromFontName(char *fontName
, Bool antialiased
)
631 char *systemFont
, *boldSystemFont
;
636 systemFont
= WINGsConfiguration
.antialiasedSystemFont
;
637 boldSystemFont
= WINGsConfiguration
.antialiasedBoldSystemFont
;
639 systemFont
= WINGsConfiguration
.systemFont
;
640 boldSystemFont
= WINGsConfiguration
.boldSystemFont
;
643 size
= WINGsConfiguration
.defaultFontSize
;
645 if (strcmp(fontName
, "SystemFont")==0) {
647 size
= WINGsConfiguration
.defaultFontSize
;
648 } else if (strncmp(fontName
, "SystemFont-", 11)==0) {
650 if (sscanf(&fontName
[11], "%i", &size
)!=1) {
651 size
= WINGsConfiguration
.defaultFontSize
;
652 wwarning(_("Invalid size specification '%s' in %s. "
653 "Using default %d\n"), &fontName
[11], fontName
, size
);
655 } else if (strcmp(fontName
, "BoldSystemFont")==0) {
656 font
= boldSystemFont
;
657 size
= WINGsConfiguration
.defaultFontSize
;
658 } else if (strncmp(fontName
, "BoldSystemFont-", 15)==0) {
659 font
= boldSystemFont
;
660 if (sscanf(&fontName
[15], "%i", &size
)!=1) {
661 size
= WINGsConfiguration
.defaultFontSize
;
662 wwarning(_("Invalid size specification '%s' in %s. "
663 "Using default %d\n"), &fontName
[15], fontName
, size
);
669 return (font
!=NULL
? makeFontSetOfSize(font
, size
) : wstrdup(fontName
));
674 WMCreateFontSet(WMScreen
*scrPtr
, char *fontName
)
677 Display
*display
= scrPtr
->display
;
682 XFontSetExtents
*extents
;
684 fname
= xlfdFromFontName(fontName
, False
);
686 font
= WMHashGet(scrPtr
->fontSetCache
, fname
);
693 font
= wmalloc(sizeof(WMFont
));
694 memset(font
, 0, sizeof(WMFont
));
696 font
->notFontSet
= 0;
697 font
->antialiased
= 0;
699 font
->screen
= scrPtr
;
701 font
->font
.set
= W_CreateFontSetWithGuess(display
, fname
, &missing
,
702 &nmissing
, &defaultString
);
703 if (nmissing
> 0 && font
->font
.set
) {
706 wwarning(_("the following character sets are missing in %s:"), fname
);
707 for (i
= 0; i
< nmissing
; i
++) {
708 wwarning(missing
[i
]);
710 XFreeStringList(missing
);
712 wwarning(_("the string \"%s\" will be used in place of any characters from those sets."),
715 if (!font
->font
.set
) {
721 extents
= XExtentsOfFontSet(font
->font
.set
);
723 font
->height
= extents
->max_logical_extent
.height
;
724 font
->y
= font
->height
- (font
->height
+ extents
->max_logical_extent
.y
);
730 assert(WMHashInsert(scrPtr
->fontSetCache
, font
->name
, font
)==NULL
);
738 WMCreateNormalFont(WMScreen
*scrPtr
, char *fontName
)
741 Display
*display
= scrPtr
->display
;
744 fontName
= xlfdFromFontName(fontName
, False
);
746 if ((ptr
= strchr(fontName
, ','))) {
747 fname
= wmalloc(ptr
- fontName
+ 1);
748 strncpy(fname
, fontName
, ptr
- fontName
);
749 fname
[ptr
- fontName
] = 0;
751 fname
= wstrdup(fontName
);
756 font
= WMHashGet(scrPtr
->fontCache
, fname
);
763 font
= wmalloc(sizeof(WMFont
));
764 memset(font
, 0, sizeof(WMFont
));
766 font
->notFontSet
= 1;
767 font
->antialiased
= 0;
769 font
->screen
= scrPtr
;
771 font
->font
.normal
= XLoadQueryFont(display
, fname
);
772 if (!font
->font
.normal
) {
777 font
->height
= font
->font
.normal
->ascent
+font
->font
.normal
->descent
;
778 font
->y
= font
->font
.normal
->ascent
;
784 assert(WMHashInsert(scrPtr
->fontCache
, font
->name
, font
)==NULL
);
791 WMCreateAntialiasedFont(WMScreen
*scrPtr
, char *fontName
)
795 Display
*display
= scrPtr
->display
;
798 fontName
= xlfdFromFontName(fontName
, True
);
800 if ((ptr
= strchr(fontName
, ','))) {
801 fname
= wmalloc(ptr
- fontName
+ 1);
802 strncpy(fname
, fontName
, ptr
- fontName
);
803 fname
[ptr
- fontName
] = 0;
805 fname
= wstrdup(fontName
);
810 font
= WMHashGet(scrPtr
->xftFontCache
, fname
);
817 font
= wmalloc(sizeof(WMFont
));
818 memset(font
, 0, sizeof(WMFont
));
820 font
->notFontSet
= 1;
821 font
->antialiased
= 1;
823 font
->screen
= scrPtr
;
825 /* Xft sux. Loading a font with an invalid XLFD will give strange results
826 * sometimes without returning any warning or error.
827 * However Xft's idea of what font is invalid is quite strange:
828 * 1. If the XLFD doesn't have all its fields present will fail and
830 * 2. If all fields are present, but hold invalid values then it will:
831 * a. If family is invalid, will load a default font without warning.
832 * b. If the font size is invalid (non-numerical) it will fail and
834 * c. If other fields are invalid, will load the font specified by
835 * the valid family name, ignoring any invalid fields. It will
836 * use a default medium weight and a default roman slant if they
839 printf("%s\n", fname
);
840 if (fname
[0] == '-') {
841 font
->font
.xft
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
843 font
->font
.xft
= XftFontOpenName(display
, scrPtr
->screen
, fname
);
845 if (!font
->font
.xft
) {
850 font
->height
= font
->font
.xft
->ascent
+font
->font
.xft
->descent
;
851 font
->y
= font
->font
.xft
->ascent
;
857 assert(WMHashInsert(scrPtr
->xftFontCache
, font
->name
, font
)==NULL
);
867 WMCreateAntialiasedFontSet(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
->xftFontSetCache
, fname
);
893 font
= wmalloc(sizeof(WMFont
));
894 memset(font
, 0, sizeof(WMFont
));
896 font
->notFontSet
= 0;
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 if (fname
[0] == '-') {
916 font
->font
.xft
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
918 font
->font
.xft
= XftFontOpenName(display
, scrPtr
->screen
, fname
);
920 if (!font
->font
.xft
) {
925 font
->height
= font
->font
.xft
->ascent
+font
->font
.xft
->descent
;
926 font
->y
= font
->font
.xft
->ascent
;
932 assert(WMHashInsert(scrPtr
->xftFontSetCache
, font
->name
, font
)==NULL
);
942 WMCreateFont(WMScreen
*scrPtr
, char *fontName
)
944 return WMCreateFontWithFlags(scrPtr
, fontName
, WFDefaultFont
);
949 WMCreateFontWithFlags(WMScreen
*scrPtr
, char *fontName
, WMFontFlags flags
)
951 Bool multiByte
= scrPtr
->useMultiByte
;
952 Bool antialiased
= scrPtr
->antialiasedText
;
955 if (flags
& WFFontSet
) {
957 } else if (flags
& WFNormalFont
) {
960 if (flags
& WFAntialiased
) {
962 } else if (flags
& WFNotAntialiased
) {
966 if (antialiased
&& multiByte
) {
967 font
= WMCreateAntialiasedFontSet(scrPtr
, fontName
);
968 /* If we cannot create an antialiased font set and antialiasing is
969 * not explicitly requested in flags, fallback to standard font sets */
970 if (!font
&& (flags
& WFAntialiased
)==0) {
971 font
= WMCreateFontSet(scrPtr
, fontName
);
973 } else if (antialiased
) {
974 font
= WMCreateAntialiasedFont(scrPtr
, fontName
);
975 /* If we cannot create an antialiased font and antialiasing is
976 * not explicitly requested in flags, fallback to normal font */
977 if (!font
&& (flags
& WFAntialiased
)==0) {
978 font
= WMCreateNormalFont(scrPtr
, fontName
);
980 } else if (multiByte
) {
981 font
= WMCreateFontSet(scrPtr
, fontName
);
983 font
= WMCreateNormalFont(scrPtr
, fontName
);
991 WMRetainFont(WMFont
*font
)
993 wassertrv(font
!=NULL
, NULL
);
1002 WMReleaseFont(WMFont
*font
)
1004 wassertr(font
!=NULL
);
1007 if (font
->refCount
< 1) {
1008 if (font
->antialiased
) {
1010 XftFontClose(font
->screen
->display
, font
->font
.xft
);
1014 } else if (font
->notFontSet
) {
1015 XFreeFont(font
->screen
->display
, font
->font
.normal
);
1017 XFreeFontSet(font
->screen
->display
, font
->font
.set
);
1021 if (font
->antialiased
&& !font
->notFontSet
) {
1022 WMHashRemove(font
->screen
->xftFontSetCache
, font
->name
);
1023 } else if (font
->antialiased
) {
1024 WMHashRemove(font
->screen
->xftFontCache
, font
->name
);
1025 } else if (font
->notFontSet
) {
1026 WMHashRemove(font
->screen
->fontCache
, font
->name
);
1028 WMHashRemove(font
->screen
->fontSetCache
, font
->name
);
1038 WMIsAntialiasingEnabled(WMScreen
*scrPtr
)
1040 return scrPtr
->antialiasedText
;
1045 WMIsAntialiasedFont(WMFont
*font
)
1047 wassertrv(font
!=NULL
, False
);
1049 return font
->antialiased
;
1054 WMFontHeight(WMFont
*font
)
1056 wassertrv(font
!=NULL
, 0);
1058 return font
->height
;
1063 WMGetFontName(WMFont
*font
)
1065 wassertrv(font
!=NULL
, NULL
);
1072 WMDefaultSystemFont(WMScreen
*scrPtr
)
1074 return WMRetainFont(scrPtr
->normalFont
);
1079 WMDefaultBoldSystemFont(WMScreen
*scrPtr
)
1081 return WMRetainFont(scrPtr
->boldFont
);
1086 makeSystemFontOfSize(WMScreen
*scrPtr
, int size
, Bool bold
)
1089 char *fontSpec
, *xftFontSpec
;
1091 #define WConf WINGsConfiguration
1093 fontSpec
= makeFontSetOfSize(WConf
.boldSystemFont
, size
);
1094 xftFontSpec
= makeFontSetOfSize(WConf
.antialiasedBoldSystemFont
, size
);
1096 fontSpec
= makeFontSetOfSize(WConf
.systemFont
, size
);
1097 xftFontSpec
= makeFontSetOfSize(WConf
.antialiasedSystemFont
, size
);
1101 if (scrPtr
->antialiasedText
&& scrPtr
->useMultiByte
) {
1102 font
= WMCreateAntialiasedFontSet(scrPtr
, xftFontSpec
);
1103 } else if (scrPtr
->antialiasedText
) {
1104 font
= WMCreateAntialiasedFont(scrPtr
, xftFontSpec
);
1105 } else if (scrPtr
->useMultiByte
) {
1106 font
= WMCreateFontSet(scrPtr
, fontSpec
);
1108 font
= WMCreateNormalFont(scrPtr
, fontSpec
);
1112 if (scrPtr
->antialiasedText
&& scrPtr
->useMultiByte
) {
1113 // is arial a good fallback for multibyte?
1114 wwarning(_("could not load font %s. Trying arial."), xftFontSpec
);
1116 font
= WMCreateAntialiasedFontSet(scrPtr
, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
1118 font
= WMCreateAntialiasedFontSet(scrPtr
, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
1121 wwarning(_("could not load antialiased font set. Reverting to standard font sets."));
1122 font
= WMCreateFontSet(scrPtr
, fontSpec
);
1124 wwarning(_("could not load FontSet %s. Trying fixed."), fontSpec
);
1125 font
= WMCreateFontSet(scrPtr
, "fixed");
1128 } else if (scrPtr
->antialiasedText
) {
1129 wwarning(_("could not load font %s. Trying arial."), xftFontSpec
);
1131 font
= WMCreateAntialiasedFont(scrPtr
, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
1133 font
= WMCreateAntialiasedFont(scrPtr
, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
1136 wwarning(_("could not load antialiased fonts. Reverting to normal fonts."));
1137 font
= WMCreateNormalFont(scrPtr
, fontSpec
);
1139 wwarning(_("could not load font %s. Trying fixed."), fontSpec
);
1140 font
= WMCreateNormalFont(scrPtr
, "fixed");
1143 } else if (scrPtr
->useMultiByte
) {
1144 wwarning(_("could not load font set %s. Trying fixed."), fontSpec
);
1145 font
= WMCreateFontSet(scrPtr
, "fixed");
1147 font
= WMCreateFontSet(scrPtr
, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
1150 wwarning(_("could not load font %s. Trying fixed."), fontSpec
);
1151 font
= WMCreateNormalFont(scrPtr
, "fixed");
1154 wwarning(_("could not load fixed font!"));
1168 WMSystemFontOfSize(WMScreen
*scrPtr
, int size
)
1170 return makeSystemFontOfSize(scrPtr
, size
, False
);
1175 WMBoldSystemFontOfSize(WMScreen
*scrPtr
, int size
)
1177 return makeSystemFontOfSize(scrPtr
, size
, True
);
1182 WMGetFontFontSet(WMFont
*font
)
1184 wassertrv(font
!=NULL
, NULL
);
1186 if (!font
->notFontSet
&& !font
->antialiased
)
1187 return font
->font
.set
;
1194 WMWidthOfString(WMFont
*font
, char *text
, int length
)
1196 wassertrv(font
!=NULL
, 0);
1197 wassertrv(text
!=NULL
, 0);
1199 if (font
->antialiased
) {
1203 if (!font
->notFontSet
) {
1208 /* Use mtext instead of text, because mbstrtowcs() alters it */
1210 wtext
= (wchar_t *)wmalloc(4*length
+4);
1211 /* pass a real ps instead of NULL below? for multithread safety
1212 * as from manual page */
1213 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
1215 XftTextExtents32(font
->screen
->display
, font
->font
.xft
,
1216 (XftChar32
*)wtext
, len
, &extents
);
1219 wwarning(_("Conversion to widechar failed (possible "
1220 "invalid multibyte sequence): '%s':(pos %d)\n"),
1221 text
, mtext
-text
+1);
1227 XftTextExtents8(font
->screen
->display
, font
->font
.xft
,
1228 (XftChar8
*)text
, length
, &extents
);
1231 return extents
.xOff
; /* don't ask :P */
1233 wassertrv(False
, 0);
1235 } else if (font
->notFontSet
) {
1236 return XTextWidth(font
->font
.normal
, text
, length
);
1239 XRectangle AIXsucks
;
1241 XmbTextExtents(font
->font
.set
, text
, length
, &AIXsucks
, &rect
);
1250 WMDrawString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMFont
*font
,
1251 int x
, int y
, char *text
, int length
)
1253 wassertr(font
!=NULL
);
1255 if (font
->antialiased
) {
1259 xftcolor
.color
.red
= color
->color
.red
;
1260 xftcolor
.color
.green
= color
->color
.green
;
1261 xftcolor
.color
.blue
= color
->color
.blue
;
1262 xftcolor
.color
.alpha
= color
->alpha
;;
1263 xftcolor
.pixel
= W_PIXEL(color
);
1265 XftDrawChange(scr
->xftdraw
, d
);
1267 if (!font
->notFontSet
) {
1272 /* Use mtext instead of text, because mbstrtowcs() alters it */
1274 wtext
= (wchar_t *)wmalloc(4*length
+4);
1275 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
1277 XftDrawString32(scr
->xftdraw
, &xftcolor
, font
->font
.xft
,
1278 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
1279 } else if (len
==-1) {
1280 wwarning(_("Conversion to widechar failed (possible invalid "
1281 "multibyte sequence): '%s':(pos %d)\n"),
1282 text
, mtext
-text
+1);
1283 /* we can draw normal text, or we can draw as much widechar
1284 * text as was already converted until the error. go figure */
1285 /*XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
1286 x, y + font->y, (XftChar8*)text, length);*/
1290 XftDrawString8(scr
->xftdraw
, &xftcolor
, font
->font
.xft
,
1291 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
1296 } else if (font
->notFontSet
) {
1297 XSetFont(scr
->display
, scr
->drawStringGC
, font
->font
.normal
->fid
);
1298 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
1299 XDrawString(scr
->display
, d
, scr
->drawStringGC
, x
, y
+ font
->y
,
1302 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
1303 XmbDrawString(scr
->display
, d
, font
->font
.set
, scr
->drawStringGC
,
1304 x
, y
+ font
->y
, text
, length
);
1310 WMDrawImageString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMColor
*background
,
1311 WMFont
*font
, int x
, int y
, char *text
, int length
)
1313 wassertr(font
!=NULL
);
1315 if (font
->antialiased
) {
1320 textColor
.color
.red
= color
->color
.red
;
1321 textColor
.color
.green
= color
->color
.green
;
1322 textColor
.color
.blue
= color
->color
.blue
;
1323 textColor
.color
.alpha
= color
->alpha
;;
1324 textColor
.pixel
= W_PIXEL(color
);
1326 bgColor
.color
.red
= background
->color
.red
;
1327 bgColor
.color
.green
= background
->color
.green
;
1328 bgColor
.color
.blue
= background
->color
.blue
;
1329 bgColor
.color
.alpha
= background
->alpha
;;
1330 bgColor
.pixel
= W_PIXEL(background
);
1333 XftDrawChange(scr
->xftdraw
, d
);
1335 XftDrawRect(scr
->xftdraw
, &bgColor
, x
, y
,
1336 WMWidthOfString(font
, text
, length
), font
->height
);
1338 if (!font
->notFontSet
) {
1343 /* Use mtext instead of text, because mbstrtowcs() alters it */
1345 wtext
= (wchar_t *)wmalloc(4*length
+4);
1346 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
1348 XftDrawString32(scr
->xftdraw
, &textColor
, font
->font
.xft
,
1349 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
1350 } else if (len
==-1) {
1351 wwarning(_("Conversion to widechar failed (possible invalid "
1352 "multibyte sequence): '%s':(pos %d)\n"),
1353 text
, mtext
-text
+1);
1354 /* we can draw normal text, or we can draw as much widechar
1355 * text as was already converted until the error. go figure */
1356 /*XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
1357 x, y + font->y, (XftChar8*)text, length);*/
1361 XftDrawString8(scr
->xftdraw
, &textColor
, font
->font
.xft
,
1362 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
1367 } else if (font
->notFontSet
) {
1368 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
1369 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
1370 XSetFont(scr
->display
, scr
->drawImStringGC
, font
->font
.normal
->fid
);
1371 XDrawImageString(scr
->display
, d
, scr
->drawImStringGC
,
1372 x
, y
+ font
->y
, text
, length
);
1374 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
1375 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
1376 XmbDrawImageString(scr
->display
, d
, font
->font
.set
, scr
->drawImStringGC
,
1377 x
, y
+ font
->y
, text
, length
);
1385 makeFontSetOfSize(char *fontset
, int size
)
1397 ptr
= strchr(fontset
, ',');
1399 int count
= ptr
-fontset
;
1402 wwarning(_("font description %s is too large."), fontset
);
1404 memcpy(font
, fontset
, count
);
1411 end
= strlen(newfs
);
1415 tmp
= wmalloc(end
+ strlen(f
) + 8);
1417 sprintf(tmp
, "%s,", newfs
);
1418 sprintf(tmp
+ end
+ 1, f
, size
);
1420 sprintf(tmp
+ end
, f
, size
);
1428 } while (ptr
!=NULL
);
1434 #define FONT_PROPS 14
1437 char *props
[FONT_PROPS
];
1442 changeFontProp(char *buf
, char *newprop
, int position
)
1445 char *ptr
, *pptr
, *rptr
;
1449 /* // remove warning later. or maybe not */
1450 wwarning(_("Invalid font specification: '%s'\n"), buf
);
1454 ptr
= pptr
= rptr
= buf
;
1456 while (*ptr
&& *ptr
!=',') {
1459 if (count
-1==position
+1) {
1463 if (count
-1==position
) {
1469 if (position
==FONT_PROPS
-1) {
1474 snprintf(buf2
, 512, "%s%s%s", buf
, newprop
, rptr
);
1480 getOptions(char *options
)
1482 char *ptr
, *ptr2
, *str
;
1486 result
= WMCreateArrayWithDestructor(2, (WMFreeDataProc
*)wfree
);
1490 ptr2
= strchr(ptr
, ',');
1492 WMAddToArray(result
, wstrdup(ptr
));
1496 str
= wmalloc(count
+1);
1497 memcpy(str
, ptr
, count
);
1499 WMAddToArray(result
, str
);
1508 #define WFAUnchanged (NULL)
1509 /* Struct for font change operations */
1510 typedef struct WMFontAttributes
{
1528 WMCopyFontWithChanges(WMScreen
*scrPtr
, WMFont
*font
,
1529 const WMFontAttributes
*changes
)
1531 int index
[FONT_PROPS
], count
[FONT_PROPS
];
1532 int totalProps
, i
, j
, carry
;
1540 snprintf(fname
, 512, "%s", font
->name
);
1542 fFlags
= (font
->antialiased
? WFAntialiased
: WFNotAntialiased
);
1543 fFlags
|= (font
->notFontSet
? WFNormalFont
: WFFontSet
);
1545 props
= WMCreateBagWithDestructor(1, (WMFreeDataProc
*)WMFreeArray
);
1548 for (i
=0; i
<FONT_PROPS
; i
++) {
1549 prop
= ((W_FontAttributes
*)changes
)->props
[i
];
1550 count
[i
] = index
[i
] = 0;
1552 /* No change for this property */
1554 } else if (strchr(prop
, ',')==NULL
) {
1556 changeFontProp(fname
, prop
, i
);
1558 /* Option with fallback alternatives */
1559 if ((changes
==WFAEmphasized
|| changes
==WFABoldEmphasized
) &&
1560 font
->antialiased
&& strcmp(prop
, "o,i")==0) {
1561 options
= getOptions("i,o");
1563 options
= getOptions(prop
);
1565 WMInsertInBag(props
, i
, options
);
1566 count
[i
] = WMGetArrayItemCount(options
);
1569 totalProps
= totalProps
* count
[i
];
1573 if (totalProps
== 0) {
1574 /* No options with fallback alternatives at all */
1576 return WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
1579 for (i
=0; i
<totalProps
; i
++) {
1580 for (j
=0; j
<FONT_PROPS
; j
++) {
1582 options
= WMGetFromBag(props
, j
);
1583 prop
= WMGetFromArray(options
, index
[j
]);
1585 changeFontProp(fname
, prop
, j
);
1589 result
= WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
1594 for (j
=FONT_PROPS
-1, carry
=1; j
>=0; j
--) {
1597 carry
= (index
[j
]==count
[j
]);
1598 index
[j
] %= count
[j
];
1608 // should WFANormal also set "normal" or leave it alone?
1609 static const WMFontAttributes W_FANormal
= {
1610 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", "r", "normal",
1611 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1612 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1616 static const WMFontAttributes W_FABold
= {
1617 WFAUnchanged
, WFAUnchanged
, "bold", WFAUnchanged
,
1618 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1619 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1623 static const WMFontAttributes W_FANotBold
= {
1624 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", WFAUnchanged
,
1625 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1626 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1630 static const WMFontAttributes W_FAEmphasized
= {
1631 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "o,i",
1632 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1633 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1637 static const WMFontAttributes W_FANotEmphasized
= {
1638 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "r",
1639 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1640 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1644 static const WMFontAttributes W_FABoldEmphasized
= {
1645 WFAUnchanged
, WFAUnchanged
, "bold", "o,i",
1646 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1647 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1651 const WMFontAttributes
*WFANormal
= &W_FANormal
;
1652 const WMFontAttributes
*WFABold
= &W_FABold
;
1653 const WMFontAttributes
*WFANotBold
= &W_FANotBold
;
1654 const WMFontAttributes
*WFAEmphasized
= &W_FAEmphasized
;
1655 const WMFontAttributes
*WFANotEmphasized
= &W_FANotEmphasized
;
1656 const WMFontAttributes
*WFABoldEmphasized
= &W_FABoldEmphasized
;