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
165 makeFontOfSize(char *font
, int size
, char *fallback
)
171 len
= strlen(font
) + 64;
172 pattern
= XftNameParse(font
);
173 XftPatternDel(pattern
, "pixelsize");
174 XftPatternAddDouble(pattern
, "pixelsize", (double)size
);
176 if (!alreadyHasStringValue(pattern
, "family", fallback
)) {
177 len
+= strlen(fallback
);
178 XftPatternAddString(pattern
, "family", fallback
);
181 result
= wmalloc(len
);
182 XftNameUnparse(pattern
, result
, len
);
183 XftPatternDestroy(pattern
);
190 WMCreateFont(WMScreen
*scrPtr
, char *fontName
)
193 Display
*display
= scrPtr
->display
;
196 /* This is for back-compat (to allow reading of old xlfd descriptions) */
197 if (fontName
[0]=='-' && (ptr
= strchr(fontName
, ','))) {
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
;
217 printf("%s\n", fname
);
218 if (fname
[0] == '-') {
219 /* Backward compat thing. Remove in a later version */
220 font
->font
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
222 font
->font
= XftFontOpenName(display
, scrPtr
->screen
, fname
);
229 font
->height
= font
->font
->ascent
+font
->font
->descent
;
230 font
->y
= font
->font
->ascent
;
236 assert(WMHashInsert(scrPtr
->fontCache
, font
->name
, font
)==NULL
);
243 WMRetainFont(WMFont
*font
)
245 wassertrv(font
!=NULL
, NULL
);
254 WMReleaseFont(WMFont
*font
)
256 wassertr(font
!=NULL
);
259 if (font
->refCount
< 1) {
260 XftFontClose(font
->screen
->display
, font
->font
);
262 WMHashRemove(font
->screen
->fontCache
, font
->name
);
271 WMIsAntialiasingEnabled(WMScreen
*scrPtr
)
273 return scrPtr
->antialiasedText
;
278 WMFontHeight(WMFont
*font
)
280 wassertrv(font
!=NULL
, 0);
287 WMGetFontName(WMFont
*font
)
289 wassertrv(font
!=NULL
, NULL
);
296 WMDefaultSystemFont(WMScreen
*scrPtr
)
298 return WMRetainFont(scrPtr
->normalFont
);
303 WMDefaultBoldSystemFont(WMScreen
*scrPtr
)
305 return WMRetainFont(scrPtr
->boldFont
);
310 WMSystemFontOfSize(WMScreen
*scrPtr
, int size
)
315 fontSpec
= makeFontOfSize(WINGsConfiguration
.systemFont
, size
, "sans");
317 font
= WMCreateFont(scrPtr
, fontSpec
);
320 wwarning(_("could not load font %s."), fontSpec
);
330 WMBoldSystemFontOfSize(WMScreen
*scrPtr
, int size
)
335 fontSpec
= makeFontOfSize(WINGsConfiguration
.boldSystemFont
, size
, "sans");
337 font
= WMCreateFont(scrPtr
, fontSpec
);
340 wwarning(_("could not load font %s."), fontSpec
);
350 WMWidthOfString(WMFont
*font
, char *text
, int length
)
354 wassertrv(font
!=NULL
, 0);
355 wassertrv(text
!=NULL
, 0);
357 if (font
->screen
->useWideChar
) {
362 wtext
= (wchar_t *)wmalloc(sizeof(wchar_t)*(length
+1));
364 len
= wmbsnrtowcs(wtext
, &mtext
, length
, length
);
366 wtext
[len
] = L
'\0'; /* not really necessary here */
367 XftTextExtents32(font
->screen
->display
, font
->font
,
368 (XftChar32
*)wtext
, len
, &extents
);
371 wwarning(_("Conversion to widechar failed (possible "
372 "invalid multibyte sequence): '%s':(pos %d)\n"),
379 XftTextExtents8(font
->screen
->display
, font
->font
,
380 (XftChar8
*)text
, length
, &extents
);
383 return extents
.xOff
; /* don't ask :P */
389 WMDrawString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMFont
*font
,
390 int x
, int y
, char *text
, int length
)
394 wassertr(font
!=NULL
);
396 xftcolor
.color
.red
= color
->color
.red
;
397 xftcolor
.color
.green
= color
->color
.green
;
398 xftcolor
.color
.blue
= color
->color
.blue
;
399 xftcolor
.color
.alpha
= color
->alpha
;;
400 xftcolor
.pixel
= W_PIXEL(color
);
402 XftDrawChange(scr
->xftdraw
, d
);
404 if (font
->screen
->useWideChar
) {
409 wtext
= (wchar_t *)wmalloc(sizeof(wchar_t)*(length
+1));
411 len
= wmbsnrtowcs(wtext
, &mtext
, length
, length
);
413 XftDrawString32(scr
->xftdraw
, &xftcolor
, font
->font
,
414 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
415 } else if (len
==-1) {
416 wwarning(_("Conversion to widechar failed (possible invalid "
417 "multibyte sequence): '%s':(pos %d)\n"),
419 /* we can draw normal text, or we can draw as much widechar
420 * text as was already converted until the error. go figure */
421 /*XftDrawString8(scr->xftdraw, &xftcolor, font->font,
422 x, y + font->y, (XftChar8*)text, length);*/
426 XftDrawString8(scr
->xftdraw
, &xftcolor
, font
->font
,
427 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
433 WMDrawImageString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMColor
*background
,
434 WMFont
*font
, int x
, int y
, char *text
, int length
)
439 wassertr(font
!=NULL
);
441 textColor
.color
.red
= color
->color
.red
;
442 textColor
.color
.green
= color
->color
.green
;
443 textColor
.color
.blue
= color
->color
.blue
;
444 textColor
.color
.alpha
= color
->alpha
;;
445 textColor
.pixel
= W_PIXEL(color
);
447 bgColor
.color
.red
= background
->color
.red
;
448 bgColor
.color
.green
= background
->color
.green
;
449 bgColor
.color
.blue
= background
->color
.blue
;
450 bgColor
.color
.alpha
= background
->alpha
;;
451 bgColor
.pixel
= W_PIXEL(background
);
453 XftDrawChange(scr
->xftdraw
, d
);
455 XftDrawRect(scr
->xftdraw
, &bgColor
, x
, y
,
456 WMWidthOfString(font
, text
, length
),
459 if (font
->screen
->useWideChar
) {
465 wtext
= (wchar_t *)wmalloc(sizeof(wchar_t)*(length
+1));
466 len
= wmbsnrtowcs(wtext
, &mtext
, length
, length
);
468 XftDrawString32(scr
->xftdraw
, &textColor
, font
->font
,
469 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
470 } else if (len
==-1) {
471 wwarning(_("Conversion to widechar failed (possible invalid "
472 "multibyte sequence): '%s':(pos %d)\n"),
474 /* we can draw normal text, or we can draw as much widechar
475 * text as was already converted until the error. go figure */
476 /*XftDrawString8(scr->xftdraw, &textColor, font->font,
477 x, y + font->y, (XftChar8*)text, length);*/
481 XftDrawString8(scr
->xftdraw
, &textColor
, font
->font
,
482 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
488 WMCopyFontWithChanges(WMScreen
*scrPtr
, WMFont
*font
,
489 const WMFontAttributes
*changes
)
491 int index
[FONT_PROPS
], count
[FONT_PROPS
];
492 int totalProps
, i
, j
, carry
;
500 snprintf(fname
, 512, "%s", font
->name
);
502 fFlags
= (font
->antialiased
? WFAntialiased
: WFNotAntialiased
);
503 fFlags
|= (font
->notFontSet
? WFNormalFont
: WFFontSet
);
505 props
= WMCreateBagWithDestructor(1, (WMFreeDataProc
*)WMFreeArray
);
508 for (i
=0; i
<FONT_PROPS
; i
++) {
509 prop
= ((W_FontAttributes
*)changes
)->props
[i
];
510 count
[i
] = index
[i
] = 0;
512 /* No change for this property */
514 } else if (strchr(prop
, ',')==NULL
) {
516 changeFontProp(fname
, prop
, i
);
518 /* Option with fallback alternatives */
519 if ((changes
==WFAEmphasized
|| changes
==WFABoldEmphasized
) &&
520 font
->antialiased
&& strcmp(prop
, "o,i")==0) {
521 options
= getOptions("i,o");
523 options
= getOptions(prop
);
525 WMInsertInBag(props
, i
, options
);
526 count
[i
] = WMGetArrayItemCount(options
);
529 totalProps
= totalProps
* count
[i
];
533 if (totalProps
== 0) {
534 /* No options with fallback alternatives at all */
536 return WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
539 for (i
=0; i
<totalProps
; i
++) {
540 for (j
=0; j
<FONT_PROPS
; j
++) {
542 options
= WMGetFromBag(props
, j
);
543 prop
= WMGetFromArray(options
, index
[j
]);
545 changeFontProp(fname
, prop
, j
);
549 result
= WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
554 for (j
=FONT_PROPS
-1, carry
=1; j
>=0; j
--) {
557 carry
= (index
[j
]==count
[j
]);
558 index
[j
] %= count
[j
];
571 #define FONT_PROPS 14
574 char *props
[FONT_PROPS
];
579 changeFontProp(char *buf
, char *newprop
, int position
)
582 char *ptr
, *pptr
, *rptr
;
586 /* // remove warning later. or maybe not */
587 wwarning(_("Invalid font specification: '%s'\n"), buf
);
591 ptr
= pptr
= rptr
= buf
;
593 while (*ptr
&& *ptr
!=',') {
596 if (count
-1==position
+1) {
600 if (count
-1==position
) {
606 if (position
==FONT_PROPS
-1) {
611 snprintf(buf2
, 512, "%s%s%s", buf
, newprop
, rptr
);
617 getOptions(char *options
)
619 char *ptr
, *ptr2
, *str
;
623 result
= WMCreateArrayWithDestructor(2, (WMFreeDataProc
*)wfree
);
627 ptr2
= strchr(ptr
, ',');
629 WMAddToArray(result
, wstrdup(ptr
));
633 str
= wmalloc(count
+1);
634 memcpy(str
, ptr
, count
);
636 WMAddToArray(result
, str
);
648 #else /* No XFT support */
651 static char *makeFontSetOfSize(char *fontset
, int size
);
655 /* XLFD pattern matching */
657 getElementFromXLFD(const char *xlfd
, int index
)
659 const char *p
= xlfd
;
661 if (*p
== '-' && --index
== 0) {
662 const char *end
= strchr(p
+ 1, '-');
665 if (end
== 0) end
= p
+ strlen(p
);
668 memcpy(buf
, p
+ 1, len
);
678 /* XLFD pattern matching */
680 generalizeXLFD(const char *xlfd
)
684 char *weight
= getElementFromXLFD(xlfd
, 3);
685 char *slant
= getElementFromXLFD(xlfd
, 4);
686 char *pxlsz
= getElementFromXLFD(xlfd
, 7);
688 #define Xstrlen(A) ((A)?strlen(A):0)
689 len
= Xstrlen(xlfd
)+Xstrlen(weight
)+Xstrlen(slant
)+Xstrlen(pxlsz
)*2+60;
692 buf
= wmalloc(len
+ 1);
693 snprintf(buf
, len
+ 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
694 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
695 xlfd
, weight
, slant
, pxlsz
, pxlsz
);
704 /* XLFD pattern matching */
706 W_CreateFontSetWithGuess(Display
*dpy
, char *xlfd
, char ***missing
,
707 int *nmissing
, char **def_string
)
709 XFontSet fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
711 if (fs
!= NULL
&& *nmissing
== 0) return fs
;
713 /* for non-iso8859-1 language and iso8859-1 specification
714 (this fontset is only for pattern analysis) */
716 if (*nmissing
!= 0) XFreeStringList(*missing
);
717 setlocale(LC_CTYPE
, "C");
718 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
719 setlocale(LC_CTYPE
, "");
722 /* make XLFD font name for pattern analysis */
724 XFontStruct
**fontstructs
;
726 if (XFontsOfFontSet(fs
, &fontstructs
, &fontnames
) > 0)
730 xlfd
= generalizeXLFD(xlfd
);
732 if (*nmissing
!= 0) XFreeStringList(*missing
);
733 if (fs
!= NULL
) XFreeFontSet(dpy
, fs
);
735 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
743 xlfdFromFontName(char *fontName
, Bool antialiased
)
745 char *systemFont
, *boldSystemFont
;
750 systemFont
= WINGsConfiguration
.antialiasedSystemFont
;
751 boldSystemFont
= WINGsConfiguration
.antialiasedBoldSystemFont
;
753 systemFont
= WINGsConfiguration
.systemFont
;
754 boldSystemFont
= WINGsConfiguration
.boldSystemFont
;
757 size
= WINGsConfiguration
.defaultFontSize
;
759 if (strcmp(fontName
, "SystemFont")==0) {
761 size
= WINGsConfiguration
.defaultFontSize
;
762 } else if (strncmp(fontName
, "SystemFont-", 11)==0) {
764 if (sscanf(&fontName
[11], "%i", &size
)!=1) {
765 size
= WINGsConfiguration
.defaultFontSize
;
766 wwarning(_("Invalid size specification '%s' in %s. "
767 "Using default %d\n"), &fontName
[11], fontName
, size
);
769 } else if (strcmp(fontName
, "BoldSystemFont")==0) {
770 font
= boldSystemFont
;
771 size
= WINGsConfiguration
.defaultFontSize
;
772 } else if (strncmp(fontName
, "BoldSystemFont-", 15)==0) {
773 font
= boldSystemFont
;
774 if (sscanf(&fontName
[15], "%i", &size
)!=1) {
775 size
= WINGsConfiguration
.defaultFontSize
;
776 wwarning(_("Invalid size specification '%s' in %s. "
777 "Using default %d\n"), &fontName
[15], fontName
, size
);
783 return (font
!=NULL
? makeFontSetOfSize(font
, size
) : wstrdup(fontName
));
788 WMCreateFontSet(WMScreen
*scrPtr
, char *fontName
)
791 Display
*display
= scrPtr
->display
;
796 XFontSetExtents
*extents
;
798 fname
= xlfdFromFontName(fontName
, False
);
800 font
= WMHashGet(scrPtr
->fontSetCache
, fname
);
807 font
= wmalloc(sizeof(WMFont
));
808 memset(font
, 0, sizeof(WMFont
));
810 font
->notFontSet
= 0;
811 font
->antialiased
= 0;
813 font
->screen
= scrPtr
;
815 font
->font
.set
= W_CreateFontSetWithGuess(display
, fname
, &missing
,
816 &nmissing
, &defaultString
);
817 if (nmissing
> 0 && font
->font
.set
) {
820 wwarning(_("the following character sets are missing in %s:"), fname
);
821 for (i
= 0; i
< nmissing
; i
++) {
822 wwarning(missing
[i
]);
824 XFreeStringList(missing
);
826 wwarning(_("the string \"%s\" will be used in place of any characters from those sets."),
829 if (!font
->font
.set
) {
835 extents
= XExtentsOfFontSet(font
->font
.set
);
837 font
->height
= extents
->max_logical_extent
.height
;
838 font
->y
= font
->height
- (font
->height
+ extents
->max_logical_extent
.y
);
844 assert(WMHashInsert(scrPtr
->fontSetCache
, font
->name
, font
)==NULL
);
852 WMCreateNormalFont(WMScreen
*scrPtr
, char *fontName
)
855 Display
*display
= scrPtr
->display
;
858 fontName
= xlfdFromFontName(fontName
, False
);
860 if ((ptr
= strchr(fontName
, ','))) {
861 fname
= wmalloc(ptr
- fontName
+ 1);
862 strncpy(fname
, fontName
, ptr
- fontName
);
863 fname
[ptr
- fontName
] = 0;
865 fname
= wstrdup(fontName
);
870 font
= WMHashGet(scrPtr
->fontCache
, fname
);
877 font
= wmalloc(sizeof(WMFont
));
878 memset(font
, 0, sizeof(WMFont
));
880 font
->notFontSet
= 1;
881 font
->antialiased
= 0;
883 font
->screen
= scrPtr
;
885 font
->font
.normal
= XLoadQueryFont(display
, fname
);
886 if (!font
->font
.normal
) {
891 font
->height
= font
->font
.normal
->ascent
+font
->font
.normal
->descent
;
892 font
->y
= font
->font
.normal
->ascent
;
898 assert(WMHashInsert(scrPtr
->fontCache
, font
->name
, font
)==NULL
);
905 WMCreateAntialiasedFont(WMScreen
*scrPtr
, char *fontName
)
909 Display
*display
= scrPtr
->display
;
912 fontName
= xlfdFromFontName(fontName
, True
);
914 if ((ptr
= strchr(fontName
, ','))) {
915 fname
= wmalloc(ptr
- fontName
+ 1);
916 strncpy(fname
, fontName
, ptr
- fontName
);
917 fname
[ptr
- fontName
] = 0;
919 fname
= wstrdup(fontName
);
924 font
= WMHashGet(scrPtr
->xftFontCache
, fname
);
931 font
= wmalloc(sizeof(WMFont
));
932 memset(font
, 0, sizeof(WMFont
));
934 font
->notFontSet
= 1;
935 font
->antialiased
= 1;
937 font
->screen
= scrPtr
;
939 /* Xft sux. Loading a font with an invalid XLFD will give strange results
940 * sometimes without returning any warning or error.
941 * However Xft's idea of what font is invalid is quite strange:
942 * 1. If the XLFD doesn't have all its fields present will fail and
944 * 2. If all fields are present, but hold invalid values then it will:
945 * a. If family is invalid, will load a default font without warning.
946 * b. If the font size is invalid (non-numerical) it will fail and
948 * c. If other fields are invalid, will load the font specified by
949 * the valid family name, ignoring any invalid fields. It will
950 * use a default medium weight and a default roman slant if they
953 printf("%s\n", fname
);
954 if (fname
[0] == '-') {
955 font
->font
.xft
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
957 font
->font
.xft
= XftFontOpenName(display
, scrPtr
->screen
, fname
);
959 if (!font
->font
.xft
) {
964 font
->height
= font
->font
.xft
->ascent
+font
->font
.xft
->descent
;
965 font
->y
= font
->font
.xft
->ascent
;
971 assert(WMHashInsert(scrPtr
->xftFontCache
, font
->name
, font
)==NULL
);
981 WMCreateAntialiasedFontSet(WMScreen
*scrPtr
, char *fontName
)
985 Display
*display
= scrPtr
->display
;
988 fontName
= xlfdFromFontName(fontName
, True
);
990 if ((ptr
= strchr(fontName
, ','))) {
991 fname
= wmalloc(ptr
- fontName
+ 1);
992 strncpy(fname
, fontName
, ptr
- fontName
);
993 fname
[ptr
- fontName
] = 0;
995 fname
= wstrdup(fontName
);
1000 font
= WMHashGet(scrPtr
->xftFontSetCache
, fname
);
1007 font
= wmalloc(sizeof(WMFont
));
1008 memset(font
, 0, sizeof(WMFont
));
1010 font
->notFontSet
= 0;
1011 font
->antialiased
= 1;
1013 font
->screen
= scrPtr
;
1015 /* Xft sux. Loading a font with an invalid XLFD will give strange results
1016 * sometimes without returning any warning or error.
1017 * However Xft's idea of what font is invalid is quite strange:
1018 * 1. If the XLFD doesn't have all its fields present will fail and
1020 * 2. If all fields are present, but hold invalid values then it will:
1021 * a. If family is invalid, will load a default font without warning.
1022 * b. If the font size is invalid (non-numerical) it will fail and
1024 * c. If other fields are invalid, will load the font specified by
1025 * the valid family name, ignoring any invalid fields. It will
1026 * use a default medium weight and a default roman slant if they
1029 if (fname
[0] == '-') {
1030 font
->font
.xft
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
1032 font
->font
.xft
= XftFontOpenName(display
, scrPtr
->screen
, fname
);
1034 if (!font
->font
.xft
) {
1039 font
->height
= font
->font
.xft
->ascent
+font
->font
.xft
->descent
;
1040 font
->y
= font
->font
.xft
->ascent
;
1046 assert(WMHashInsert(scrPtr
->xftFontSetCache
, font
->name
, font
)==NULL
);
1056 WMCreateFont(WMScreen
*scrPtr
, char *fontName
)
1058 return WMCreateFontWithFlags(scrPtr
, fontName
, WFDefaultFont
);
1063 WMCreateFontWithFlags(WMScreen
*scrPtr
, char *fontName
, WMFontFlags flags
)
1065 Bool multiByte
= scrPtr
->useMultiByte
;
1066 Bool antialiased
= scrPtr
->antialiasedText
;
1069 if (flags
& WFFontSet
) {
1071 } else if (flags
& WFNormalFont
) {
1074 if (flags
& WFAntialiased
) {
1076 } else if (flags
& WFNotAntialiased
) {
1077 antialiased
= False
;
1080 if (antialiased
&& multiByte
) {
1081 font
= WMCreateAntialiasedFontSet(scrPtr
, fontName
);
1082 /* If we cannot create an antialiased font set and antialiasing is
1083 * not explicitly requested in flags, fallback to standard font sets */
1084 if (!font
&& (flags
& WFAntialiased
)==0) {
1085 font
= WMCreateFontSet(scrPtr
, fontName
);
1087 } else if (antialiased
) {
1088 font
= WMCreateAntialiasedFont(scrPtr
, fontName
);
1089 /* If we cannot create an antialiased font and antialiasing is
1090 * not explicitly requested in flags, fallback to normal font */
1091 if (!font
&& (flags
& WFAntialiased
)==0) {
1092 font
= WMCreateNormalFont(scrPtr
, fontName
);
1094 } else if (multiByte
) {
1095 font
= WMCreateFontSet(scrPtr
, fontName
);
1097 font
= WMCreateNormalFont(scrPtr
, fontName
);
1105 WMRetainFont(WMFont
*font
)
1107 wassertrv(font
!=NULL
, NULL
);
1116 WMReleaseFont(WMFont
*font
)
1118 wassertr(font
!=NULL
);
1121 if (font
->refCount
< 1) {
1122 if (font
->antialiased
) {
1124 XftFontClose(font
->screen
->display
, font
->font
.xft
);
1128 } else if (font
->notFontSet
) {
1129 XFreeFont(font
->screen
->display
, font
->font
.normal
);
1131 XFreeFontSet(font
->screen
->display
, font
->font
.set
);
1135 if (font
->antialiased
&& !font
->notFontSet
) {
1136 WMHashRemove(font
->screen
->xftFontSetCache
, font
->name
);
1137 } else if (font
->antialiased
) {
1138 WMHashRemove(font
->screen
->xftFontCache
, font
->name
);
1139 } else if (font
->notFontSet
) {
1140 WMHashRemove(font
->screen
->fontCache
, font
->name
);
1142 WMHashRemove(font
->screen
->fontSetCache
, font
->name
);
1152 WMIsAntialiasingEnabled(WMScreen
*scrPtr
)
1154 return scrPtr
->antialiasedText
;
1159 WMIsAntialiasedFont(WMFont
*font
)
1161 wassertrv(font
!=NULL
, False
);
1163 return font
->antialiased
;
1168 WMFontHeight(WMFont
*font
)
1170 wassertrv(font
!=NULL
, 0);
1172 return font
->height
;
1177 WMGetFontName(WMFont
*font
)
1179 wassertrv(font
!=NULL
, NULL
);
1186 WMDefaultSystemFont(WMScreen
*scrPtr
)
1188 return WMRetainFont(scrPtr
->normalFont
);
1193 WMDefaultBoldSystemFont(WMScreen
*scrPtr
)
1195 return WMRetainFont(scrPtr
->boldFont
);
1200 makeSystemFontOfSize(WMScreen
*scrPtr
, int size
, Bool bold
)
1203 char *fontSpec
, *xftFontSpec
;
1205 #define WConf WINGsConfiguration
1207 fontSpec
= makeFontSetOfSize(WConf
.boldSystemFont
, size
);
1208 xftFontSpec
= makeFontSetOfSize(WConf
.antialiasedBoldSystemFont
, size
);
1210 fontSpec
= makeFontSetOfSize(WConf
.systemFont
, size
);
1211 xftFontSpec
= makeFontSetOfSize(WConf
.antialiasedSystemFont
, size
);
1215 if (scrPtr
->antialiasedText
&& scrPtr
->useMultiByte
) {
1216 font
= WMCreateAntialiasedFontSet(scrPtr
, xftFontSpec
);
1217 } else if (scrPtr
->antialiasedText
) {
1218 font
= WMCreateAntialiasedFont(scrPtr
, xftFontSpec
);
1219 } else if (scrPtr
->useMultiByte
) {
1220 font
= WMCreateFontSet(scrPtr
, fontSpec
);
1222 font
= WMCreateNormalFont(scrPtr
, fontSpec
);
1226 if (scrPtr
->antialiasedText
&& scrPtr
->useMultiByte
) {
1227 // is arial a good fallback for multibyte?
1228 wwarning(_("could not load font %s. Trying arial."), xftFontSpec
);
1230 font
= WMCreateAntialiasedFontSet(scrPtr
, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
1232 font
= WMCreateAntialiasedFontSet(scrPtr
, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
1235 wwarning(_("could not load antialiased font set. Reverting to standard font sets."));
1236 font
= WMCreateFontSet(scrPtr
, fontSpec
);
1238 wwarning(_("could not load FontSet %s. Trying fixed."), fontSpec
);
1239 font
= WMCreateFontSet(scrPtr
, "fixed");
1242 } else if (scrPtr
->antialiasedText
) {
1243 wwarning(_("could not load font %s. Trying arial."), xftFontSpec
);
1245 font
= WMCreateAntialiasedFont(scrPtr
, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
1247 font
= WMCreateAntialiasedFont(scrPtr
, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
1250 wwarning(_("could not load antialiased fonts. Reverting to normal fonts."));
1251 font
= WMCreateNormalFont(scrPtr
, fontSpec
);
1253 wwarning(_("could not load font %s. Trying fixed."), fontSpec
);
1254 font
= WMCreateNormalFont(scrPtr
, "fixed");
1257 } else if (scrPtr
->useMultiByte
) {
1258 wwarning(_("could not load font set %s. Trying fixed."), fontSpec
);
1259 font
= WMCreateFontSet(scrPtr
, "fixed");
1261 font
= WMCreateFontSet(scrPtr
, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
1264 wwarning(_("could not load font %s. Trying fixed."), fontSpec
);
1265 font
= WMCreateNormalFont(scrPtr
, "fixed");
1268 wwarning(_("could not load fixed font!"));
1282 WMSystemFontOfSize(WMScreen
*scrPtr
, int size
)
1284 return makeSystemFontOfSize(scrPtr
, size
, False
);
1289 WMBoldSystemFontOfSize(WMScreen
*scrPtr
, int size
)
1291 return makeSystemFontOfSize(scrPtr
, size
, True
);
1296 WMGetFontFontSet(WMFont
*font
)
1298 wassertrv(font
!=NULL
, NULL
);
1300 if (!font
->notFontSet
&& !font
->antialiased
)
1301 return font
->font
.set
;
1308 WMWidthOfString(WMFont
*font
, char *text
, int length
)
1310 wassertrv(font
!=NULL
, 0);
1311 wassertrv(text
!=NULL
, 0);
1313 if (font
->antialiased
) {
1317 if (!font
->notFontSet
) {
1322 /* Use mtext instead of text, because mbstrtowcs() alters it */
1324 wtext
= (wchar_t *)wmalloc(4*length
+4);
1325 /* pass a real ps instead of NULL below? for multithread safety
1326 * as from manual page */
1327 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
1329 XftTextExtents32(font
->screen
->display
, font
->font
.xft
,
1330 (XftChar32
*)wtext
, len
, &extents
);
1333 wwarning(_("Conversion to widechar failed (possible "
1334 "invalid multibyte sequence): '%s':(pos %d)\n"),
1335 text
, mtext
-text
+1);
1341 XftTextExtents8(font
->screen
->display
, font
->font
.xft
,
1342 (XftChar8
*)text
, length
, &extents
);
1345 return extents
.xOff
; /* don't ask :P */
1347 wassertrv(False
, 0);
1349 } else if (font
->notFontSet
) {
1350 return XTextWidth(font
->font
.normal
, text
, length
);
1353 XRectangle AIXsucks
;
1355 XmbTextExtents(font
->font
.set
, text
, length
, &AIXsucks
, &rect
);
1364 WMDrawString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMFont
*font
,
1365 int x
, int y
, char *text
, int length
)
1367 wassertr(font
!=NULL
);
1369 if (font
->antialiased
) {
1373 xftcolor
.color
.red
= color
->color
.red
;
1374 xftcolor
.color
.green
= color
->color
.green
;
1375 xftcolor
.color
.blue
= color
->color
.blue
;
1376 xftcolor
.color
.alpha
= color
->alpha
;;
1377 xftcolor
.pixel
= W_PIXEL(color
);
1379 XftDrawChange(scr
->xftdraw
, d
);
1381 if (!font
->notFontSet
) {
1386 /* Use mtext instead of text, because mbstrtowcs() alters it */
1388 wtext
= (wchar_t *)wmalloc(4*length
+4);
1389 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
1391 XftDrawString32(scr
->xftdraw
, &xftcolor
, font
->font
.xft
,
1392 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
1393 } else if (len
==-1) {
1394 wwarning(_("Conversion to widechar failed (possible invalid "
1395 "multibyte sequence): '%s':(pos %d)\n"),
1396 text
, mtext
-text
+1);
1397 /* we can draw normal text, or we can draw as much widechar
1398 * text as was already converted until the error. go figure */
1399 /*XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
1400 x, y + font->y, (XftChar8*)text, length);*/
1404 XftDrawString8(scr
->xftdraw
, &xftcolor
, font
->font
.xft
,
1405 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
1410 } else if (font
->notFontSet
) {
1411 XSetFont(scr
->display
, scr
->drawStringGC
, font
->font
.normal
->fid
);
1412 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
1413 XDrawString(scr
->display
, d
, scr
->drawStringGC
, x
, y
+ font
->y
,
1416 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
1417 XmbDrawString(scr
->display
, d
, font
->font
.set
, scr
->drawStringGC
,
1418 x
, y
+ font
->y
, text
, length
);
1424 WMDrawImageString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMColor
*background
,
1425 WMFont
*font
, int x
, int y
, char *text
, int length
)
1427 wassertr(font
!=NULL
);
1429 if (font
->antialiased
) {
1434 textColor
.color
.red
= color
->color
.red
;
1435 textColor
.color
.green
= color
->color
.green
;
1436 textColor
.color
.blue
= color
->color
.blue
;
1437 textColor
.color
.alpha
= color
->alpha
;;
1438 textColor
.pixel
= W_PIXEL(color
);
1440 bgColor
.color
.red
= background
->color
.red
;
1441 bgColor
.color
.green
= background
->color
.green
;
1442 bgColor
.color
.blue
= background
->color
.blue
;
1443 bgColor
.color
.alpha
= background
->alpha
;;
1444 bgColor
.pixel
= W_PIXEL(background
);
1447 XftDrawChange(scr
->xftdraw
, d
);
1449 XftDrawRect(scr
->xftdraw
, &bgColor
, x
, y
,
1450 WMWidthOfString(font
, text
, length
), font
->height
);
1452 if (!font
->notFontSet
) {
1457 /* Use mtext instead of text, because mbstrtowcs() alters it */
1459 wtext
= (wchar_t *)wmalloc(4*length
+4);
1460 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
1462 XftDrawString32(scr
->xftdraw
, &textColor
, font
->font
.xft
,
1463 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
1464 } else if (len
==-1) {
1465 wwarning(_("Conversion to widechar failed (possible invalid "
1466 "multibyte sequence): '%s':(pos %d)\n"),
1467 text
, mtext
-text
+1);
1468 /* we can draw normal text, or we can draw as much widechar
1469 * text as was already converted until the error. go figure */
1470 /*XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
1471 x, y + font->y, (XftChar8*)text, length);*/
1475 XftDrawString8(scr
->xftdraw
, &textColor
, font
->font
.xft
,
1476 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
1481 } else if (font
->notFontSet
) {
1482 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
1483 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
1484 XSetFont(scr
->display
, scr
->drawImStringGC
, font
->font
.normal
->fid
);
1485 XDrawImageString(scr
->display
, d
, scr
->drawImStringGC
,
1486 x
, y
+ font
->y
, text
, length
);
1488 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
1489 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
1490 XmbDrawImageString(scr
->display
, d
, font
->font
.set
, scr
->drawImStringGC
,
1491 x
, y
+ font
->y
, text
, length
);
1499 makeFontSetOfSize(char *fontset
, int size
)
1511 ptr
= strchr(fontset
, ',');
1513 int count
= ptr
-fontset
;
1516 wwarning(_("font description %s is too large."), fontset
);
1518 memcpy(font
, fontset
, count
);
1525 end
= strlen(newfs
);
1529 tmp
= wmalloc(end
+ strlen(f
) + 8);
1531 sprintf(tmp
, "%s,", newfs
);
1532 sprintf(tmp
+ end
+ 1, f
, size
);
1534 sprintf(tmp
+ end
, f
, size
);
1542 } while (ptr
!=NULL
);
1548 #define FONT_PROPS 14
1551 char *props
[FONT_PROPS
];
1556 changeFontProp(char *buf
, char *newprop
, int position
)
1559 char *ptr
, *pptr
, *rptr
;
1563 /* // remove warning later. or maybe not */
1564 wwarning(_("Invalid font specification: '%s'\n"), buf
);
1568 ptr
= pptr
= rptr
= buf
;
1570 while (*ptr
&& *ptr
!=',') {
1573 if (count
-1==position
+1) {
1577 if (count
-1==position
) {
1583 if (position
==FONT_PROPS
-1) {
1588 snprintf(buf2
, 512, "%s%s%s", buf
, newprop
, rptr
);
1594 getOptions(char *options
)
1596 char *ptr
, *ptr2
, *str
;
1600 result
= WMCreateArrayWithDestructor(2, (WMFreeDataProc
*)wfree
);
1604 ptr2
= strchr(ptr
, ',');
1606 WMAddToArray(result
, wstrdup(ptr
));
1610 str
= wmalloc(count
+1);
1611 memcpy(str
, ptr
, count
);
1613 WMAddToArray(result
, str
);
1623 WMCopyFontWithChanges(WMScreen
*scrPtr
, WMFont
*font
,
1624 const WMFontAttributes
*changes
)
1626 int index
[FONT_PROPS
], count
[FONT_PROPS
];
1627 int totalProps
, i
, j
, carry
;
1635 snprintf(fname
, 512, "%s", font
->name
);
1637 fFlags
= (font
->antialiased
? WFAntialiased
: WFNotAntialiased
);
1638 fFlags
|= (font
->notFontSet
? WFNormalFont
: WFFontSet
);
1640 props
= WMCreateBagWithDestructor(1, (WMFreeDataProc
*)WMFreeArray
);
1643 for (i
=0; i
<FONT_PROPS
; i
++) {
1644 prop
= ((W_FontAttributes
*)changes
)->props
[i
];
1645 count
[i
] = index
[i
] = 0;
1647 /* No change for this property */
1649 } else if (strchr(prop
, ',')==NULL
) {
1651 changeFontProp(fname
, prop
, i
);
1653 /* Option with fallback alternatives */
1654 if ((changes
==WFAEmphasized
|| changes
==WFABoldEmphasized
) &&
1655 font
->antialiased
&& strcmp(prop
, "o,i")==0) {
1656 options
= getOptions("i,o");
1658 options
= getOptions(prop
);
1660 WMInsertInBag(props
, i
, options
);
1661 count
[i
] = WMGetArrayItemCount(options
);
1664 totalProps
= totalProps
* count
[i
];
1668 if (totalProps
== 0) {
1669 /* No options with fallback alternatives at all */
1671 return WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
1674 for (i
=0; i
<totalProps
; i
++) {
1675 for (j
=0; j
<FONT_PROPS
; j
++) {
1677 options
= WMGetFromBag(props
, j
);
1678 prop
= WMGetFromArray(options
, index
[j
]);
1680 changeFontProp(fname
, prop
, j
);
1684 result
= WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
1689 for (j
=FONT_PROPS
-1, carry
=1; j
>=0; j
--) {
1692 carry
= (index
[j
]==count
[j
]);
1693 index
[j
] %= count
[j
];
1706 // should WFANormal also set "normal" or leave it alone?
1707 static const WMFontAttributes W_FANormal
= {
1708 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", "r", "normal",
1709 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1710 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1714 static const WMFontAttributes W_FABold
= {
1715 WFAUnchanged
, WFAUnchanged
, "bold", WFAUnchanged
,
1716 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1717 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1721 static const WMFontAttributes W_FANotBold
= {
1722 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", WFAUnchanged
,
1723 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1724 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1728 static const WMFontAttributes W_FAEmphasized
= {
1729 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "o,i",
1730 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1731 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1735 static const WMFontAttributes W_FANotEmphasized
= {
1736 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "r",
1737 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1738 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1742 static const WMFontAttributes W_FABoldEmphasized
= {
1743 WFAUnchanged
, WFAUnchanged
, "bold", "o,i",
1744 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1745 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1749 const WMFontAttributes
*WFANormal
= &W_FANormal
;
1750 const WMFontAttributes
*WFABold
= &W_FABold
;
1751 const WMFontAttributes
*WFANotBold
= &W_FANotBold
;
1752 const WMFontAttributes
*WFAEmphasized
= &W_FAEmphasized
;
1753 const WMFontAttributes
*WFANotEmphasized
= &W_FANotEmphasized
;
1754 const WMFontAttributes
*WFABoldEmphasized
= &W_FABoldEmphasized
;