- Converted functions in wfont.c to use xft semantics in place of old X core
[wmaker-crm.git] / WINGs / wfont.c
blob0684121909a5c9bf4968d5f7ca4d6ee5639637a1
2 #include "wconfig.h"
4 #ifdef XFT
5 # include <X11/Xft/Xft.h>
6 # ifdef HAVE_WCHAR_H
7 # include <wchar.h>
8 # endif
9 # include <stdlib.h>
10 #endif
12 #include "WINGsP.h"
14 #include <wraster.h>
15 #include <assert.h>
16 #include <X11/Xlocale.h>
19 #ifdef XFT
21 #if defined(HAVE_MBSNRTOWCS)
23 static size_t
24 wmbsnrtowcs(wchar_t *dest, const char **src, size_t nbytes, size_t len)
26 mbstate_t ps;
27 size_t n;
29 memset(&ps, 0, sizeof(mbstate_t));
30 n = mbsnrtowcs(dest, src, nbytes, len, &ps);
31 if (n!=(size_t)-1 && *src) {
32 *src -= ps.__count;
35 return n;
38 #elif defined(HAVE_MBRTOWC)
40 // This is 8 times slower than the version above.
41 static size_t
42 wmbsnrtowcs(wchar_t *dest, const char **src, size_t nbytes, size_t len)
44 mbstate_t ps;
45 const char *ptr;
46 size_t n;
47 int nb;
49 if (nbytes==0)
50 return 0;
52 memset(&ps, 0, sizeof(mbstate_t));
54 if (dest == NULL) {
55 for (ptr=*src, n=0; nbytes>0; n++) {
56 nb = mbrtowc(NULL, ptr, nbytes, &ps);
57 if (nb == -1) {
58 return ((size_t)-1);
59 } else if (nb==0 || nb==-2) {
60 return n;
62 ptr += nb;
63 nbytes -= nb;
67 for (ptr=*src, n=0; n<len && nbytes>0; n++, dest++) {
68 nb = mbrtowc(dest, ptr, nbytes, &ps);
69 if (nb == -2) {
70 *src = ptr;
71 return n;
72 } else if (nb == -1) {
73 *src = ptr;
74 return ((size_t)-1);
75 } else if (nb == 0) {
76 *src = NULL;
77 return n;
79 ptr += nb;
80 nbytes -= nb;
83 *src = ptr;
84 return n;
87 #else
89 // Not only 8 times slower than the version based on mbsnrtowcs
90 // but also this version is not thread safe nor reentrant
92 static size_t
93 wmbsnrtowcs(wchar_t *dest, const char **src, size_t nbytes, size_t len)
95 const char *ptr;
96 size_t n;
97 int nb;
99 if (nbytes==0)
100 return 0;
102 mbtowc(NULL, NULL, 0); /* reset shift state */
104 if (dest == NULL) {
105 for (ptr=*src, n=0; nbytes>0; n++) {
106 nb = mbtowc(NULL, ptr, nbytes);
107 if (nb == -1) {
108 mbtowc(NULL, NULL, 0);
109 nb = mbtowc(NULL, ptr, strlen(ptr));
110 return (nb == -1 ? (size_t)-1 : n);
111 } else if (nb==0) {
112 return n;
114 ptr += nb;
115 nbytes -= nb;
119 for (ptr=*src, n=0; n<len && nbytes>0; n++, dest++) {
120 nb = mbtowc(dest, ptr, nbytes);
121 if (nb == -1) {
122 mbtowc(NULL, NULL, 0);
123 nb = mbtowc(NULL, ptr, strlen(ptr));
124 *src = ptr;
125 return (nb == -1 ? (size_t)-1 : n);
126 } else if (nb == 0) {
127 *src = NULL;
128 return n;
130 ptr += nb;
131 nbytes -= nb;
134 *src = ptr;
135 return n;
138 #endif
141 static Bool
142 alreadyHasStringValue(XftPattern *pattern, const char *object, char *value)
144 XftResult r;
145 char *s;
146 int id;
148 if (!value || value[0]==0)
149 return True;
151 id = 0;
152 while ((r=XftPatternGetString(pattern, object, id, &s))!=XftResultNoId) {
153 if (r == XftResultMatch && strcasecmp(value, s) == 0) {
154 return True;
156 id++;
159 return False;
163 // check if to add a fallback size too. -Dan
164 static char*
165 makeFontOfSize(char *font, int size, char *fallback)
167 XftPattern *pattern;
168 char *result;
169 int len;
171 len = strlen(font) + 64;
172 pattern = XftNameParse(font);
173 XftPatternDel(pattern, "pixelsize");
174 XftPatternAddDouble(pattern, "pixelsize", (double)size);
175 if (fallback) {
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);
185 return result;
189 WMFont*
190 WMCreateFont(WMScreen *scrPtr, char *fontName)
192 WMFont *font;
193 Display *display = scrPtr->display;
194 char *fname, *ptr;
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;
201 } else {
202 fname = wstrdup(fontName);
205 font = WMHashGet(scrPtr->fontCache, fname);
206 if (font) {
207 WMRetainFont(font);
208 wfree(fname);
209 return font;
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);
221 } else {
222 font->font = XftFontOpenName(display, scrPtr->screen, fname);
224 if (!font->font) {
225 wfree(font);
226 wfree(fname);
227 return NULL;
229 font->height = font->font->ascent+font->font->descent;
230 font->y = font->font->ascent;
232 font->refCount = 1;
234 font->name = fname;
236 assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL);
238 return font;
242 WMFont*
243 WMRetainFont(WMFont *font)
245 wassertrv(font!=NULL, NULL);
247 font->refCount++;
249 return font;
253 void
254 WMReleaseFont(WMFont *font)
256 wassertr(font!=NULL);
258 font->refCount--;
259 if (font->refCount < 1) {
260 XftFontClose(font->screen->display, font->font);
261 if (font->name) {
262 WMHashRemove(font->screen->fontCache, font->name);
263 wfree(font->name);
265 wfree(font);
270 Bool
271 WMIsAntialiasingEnabled(WMScreen *scrPtr)
273 return scrPtr->antialiasedText;
277 unsigned int
278 WMFontHeight(WMFont *font)
280 wassertrv(font!=NULL, 0);
282 return font->height;
286 char*
287 WMGetFontName(WMFont *font)
289 wassertrv(font!=NULL, NULL);
291 return font->name;
295 WMFont*
296 WMDefaultSystemFont(WMScreen *scrPtr)
298 return WMRetainFont(scrPtr->normalFont);
302 WMFont*
303 WMDefaultBoldSystemFont(WMScreen *scrPtr)
305 return WMRetainFont(scrPtr->boldFont);
309 WMFont*
310 WMSystemFontOfSize(WMScreen *scrPtr, int size)
312 WMFont *font;
313 char *fontSpec;
315 fontSpec = makeFontOfSize(WINGsConfiguration.systemFont, size, "sans");
317 font = WMCreateFont(scrPtr, fontSpec);
319 if (!font) {
320 wwarning(_("could not load font %s."), fontSpec);
323 wfree(fontSpec);
325 return font;
329 WMFont*
330 WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
332 WMFont *font;
333 char *fontSpec;
335 fontSpec = makeFontOfSize(WINGsConfiguration.boldSystemFont, size, "sans");
337 font = WMCreateFont(scrPtr, fontSpec);
339 if (!font) {
340 wwarning(_("could not load font %s."), fontSpec);
343 wfree(fontSpec);
345 return font;
350 WMWidthOfString(WMFont *font, char *text, int length)
352 XGlyphInfo extents;
354 wassertrv(font!=NULL, 0);
355 wassertrv(text!=NULL, 0);
357 if (font->screen->useWideChar) {
358 wchar_t *wtext;
359 const char *mtext;
360 int len;
362 wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1));
363 mtext = text;
364 len = wmbsnrtowcs(wtext, &mtext, length, length);
365 if (len>0) {
366 wtext[len] = L'\0'; /* not really necessary here */
367 XftTextExtents32(font->screen->display, font->font,
368 (XftChar32 *)wtext, len, &extents);
369 } else {
370 if (len==-1) {
371 wwarning(_("Conversion to widechar failed (possible "
372 "invalid multibyte sequence): '%s':(pos %d)\n"),
373 text, mtext-text+1);
375 extents.xOff = 0;
377 wfree(wtext);
378 } else {
379 XftTextExtents8(font->screen->display, font->font,
380 (XftChar8 *)text, length, &extents);
383 return extents.xOff; /* don't ask :P */
388 void
389 WMDrawString(WMScreen *scr, Drawable d, WMColor *color, WMFont *font,
390 int x, int y, char *text, int length)
392 XftColor xftcolor;
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) {
405 wchar_t *wtext;
406 const char *mtext;
407 int len;
409 wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1));
410 mtext = text;
411 len = wmbsnrtowcs(wtext, &mtext, length, length);
412 if (len>0) {
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"),
418 text, mtext-text+1);
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);*/
424 wfree(wtext);
425 } else {
426 XftDrawString8(scr->xftdraw, &xftcolor, font->font,
427 x, y + font->y, (XftChar8*)text, length);
432 void
433 WMDrawImageString(WMScreen *scr, Drawable d, WMColor *color, WMColor *background,
434 WMFont *font, int x, int y, char *text, int length)
436 XftColor textColor;
437 XftColor bgColor;
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),
457 font->height);
459 if (font->screen->useWideChar) {
460 wchar_t *wtext;
461 const char *mtext;
462 int len;
464 mtext = text;
465 wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1));
466 len = wmbsnrtowcs(wtext, &mtext, length, length);
467 if (len>0) {
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"),
473 text, mtext-text+1);
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);*/
479 wfree(wtext);
480 } else {
481 XftDrawString8(scr->xftdraw, &textColor, font->font,
482 x, y + font->y, (XftChar8*)text, length);
487 WMFont*
488 WMCopyFontWithChanges(WMScreen *scrPtr, WMFont *font,
489 const WMFontAttributes *changes)
491 int index[FONT_PROPS], count[FONT_PROPS];
492 int totalProps, i, j, carry;
493 char fname[512];
494 WMFontFlags fFlags;
495 WMBag *props;
496 WMArray *options;
497 WMFont *result;
498 char *prop;
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);
507 totalProps = 0;
508 for (i=0; i<FONT_PROPS; i++) {
509 prop = ((W_FontAttributes*)changes)->props[i];
510 count[i] = index[i] = 0;
511 if (!prop) {
512 /* No change for this property */
513 continue;
514 } else if (strchr(prop, ',')==NULL) {
515 /* Simple option */
516 changeFontProp(fname, prop, i);
517 } else {
518 /* Option with fallback alternatives */
519 if ((changes==WFAEmphasized || changes==WFABoldEmphasized) &&
520 font->antialiased && strcmp(prop, "o,i")==0) {
521 options = getOptions("i,o");
522 } else {
523 options = getOptions(prop);
525 WMInsertInBag(props, i, options);
526 count[i] = WMGetArrayItemCount(options);
527 if (totalProps==0)
528 totalProps = 1;
529 totalProps = totalProps * count[i];
533 if (totalProps == 0) {
534 /* No options with fallback alternatives at all */
535 WMFreeBag(props);
536 return WMCreateFontWithFlags(scrPtr, fname, fFlags);
539 for (i=0; i<totalProps; i++) {
540 for (j=0; j<FONT_PROPS; j++) {
541 if (count[j]!=0) {
542 options = WMGetFromBag(props, j);
543 prop = WMGetFromArray(options, index[j]);
544 if (prop) {
545 changeFontProp(fname, prop, j);
549 result = WMCreateFontWithFlags(scrPtr, fname, fFlags);
550 if (result) {
551 WMFreeBag(props);
552 return result;
554 for (j=FONT_PROPS-1, carry=1; j>=0; j--) {
555 if (count[j]!=0) {
556 index[j] += carry;
557 carry = (index[j]==count[j]);
558 index[j] %= count[j];
563 WMFreeBag(props);
565 return NULL;
569 #if 0
571 #define FONT_PROPS 14
573 typedef struct {
574 char *props[FONT_PROPS];
575 } W_FontAttributes;
578 static void
579 changeFontProp(char *buf, char *newprop, int position)
581 char buf2[512];
582 char *ptr, *pptr, *rptr;
583 int count;
585 if (buf[0]!='-') {
586 /* // remove warning later. or maybe not */
587 wwarning(_("Invalid font specification: '%s'\n"), buf);
588 return;
591 ptr = pptr = rptr = buf;
592 count = 0;
593 while (*ptr && *ptr!=',') {
594 if (*ptr == '-') {
595 count++;
596 if (count-1==position+1) {
597 rptr = ptr;
598 break;
600 if (count-1==position) {
601 pptr = ptr+1;
604 ptr++;
606 if (position==FONT_PROPS-1) {
607 rptr = ptr;
610 *pptr = 0;
611 snprintf(buf2, 512, "%s%s%s", buf, newprop, rptr);
612 strcpy(buf, buf2);
616 static WMArray*
617 getOptions(char *options)
619 char *ptr, *ptr2, *str;
620 WMArray *result;
621 int count;
623 result = WMCreateArrayWithDestructor(2, (WMFreeDataProc*)wfree);
625 ptr = options;
626 while (1) {
627 ptr2 = strchr(ptr, ',');
628 if (!ptr2) {
629 WMAddToArray(result, wstrdup(ptr));
630 break;
631 } else {
632 count = ptr2 - ptr;
633 str = wmalloc(count+1);
634 memcpy(str, ptr, count);
635 str[count] = 0;
636 WMAddToArray(result, str);
637 ptr = ptr2 + 1;
641 return result;
645 #endif
648 #else /* No XFT support */
651 static char *makeFontSetOfSize(char *fontset, int size);
655 /* XLFD pattern matching */
656 static char*
657 getElementFromXLFD(const char *xlfd, int index)
659 const char *p = xlfd;
660 while (*p != 0) {
661 if (*p == '-' && --index == 0) {
662 const char *end = strchr(p + 1, '-');
663 char *buf;
664 size_t len;
665 if (end == 0) end = p + strlen(p);
666 len = end - (p + 1);
667 buf = wmalloc(len);
668 memcpy(buf, p + 1, len);
669 buf[len] = 0;
670 return buf;
672 p++;
674 return strdup("*");
678 /* XLFD pattern matching */
679 static char*
680 generalizeXLFD(const char *xlfd)
682 char *buf;
683 int len;
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;
690 #undef Xstrlen
692 buf = wmalloc(len + 1);
693 snprintf(buf, len + 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
694 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
695 xlfd, weight, slant, pxlsz, pxlsz);
697 wfree(pxlsz);
698 wfree(slant);
699 wfree(weight);
701 return buf;
704 /* XLFD pattern matching */
705 static XFontSet
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) */
715 if (fs == NULL) {
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 */
723 if (fs != NULL) {
724 XFontStruct **fontstructs;
725 char **fontnames;
726 if (XFontsOfFontSet(fs, &fontstructs, &fontnames) > 0)
727 xlfd = 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);
737 wfree(xlfd);
738 return fs;
742 static char*
743 xlfdFromFontName(char *fontName, Bool antialiased)
745 char *systemFont, *boldSystemFont;
746 char *font;
747 int size;
749 if (antialiased) {
750 systemFont = WINGsConfiguration.antialiasedSystemFont;
751 boldSystemFont = WINGsConfiguration.antialiasedBoldSystemFont;
752 } else {
753 systemFont = WINGsConfiguration.systemFont;
754 boldSystemFont = WINGsConfiguration.boldSystemFont;
757 size = WINGsConfiguration.defaultFontSize;
759 if (strcmp(fontName, "SystemFont")==0) {
760 font = systemFont;
761 size = WINGsConfiguration.defaultFontSize;
762 } else if (strncmp(fontName, "SystemFont-", 11)==0) {
763 font = systemFont;
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);
779 } else {
780 font = NULL;
783 return (font!=NULL ? makeFontSetOfSize(font, size) : wstrdup(fontName));
787 WMFont*
788 WMCreateFontSet(WMScreen *scrPtr, char *fontName)
790 WMFont *font;
791 Display *display = scrPtr->display;
792 char **missing;
793 int nmissing = 0;
794 char *defaultString;
795 char *fname;
796 XFontSetExtents *extents;
798 fname = xlfdFromFontName(fontName, False);
800 font = WMHashGet(scrPtr->fontSetCache, fname);
801 if (font) {
802 WMRetainFont(font);
803 wfree(fname);
804 return font;
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) {
818 int i;
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);
825 if (defaultString)
826 wwarning(_("the string \"%s\" will be used in place of any characters from those sets."),
827 defaultString);
829 if (!font->font.set) {
830 wfree(font);
831 wfree(fname);
832 return NULL;
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);
840 font->refCount = 1;
842 font->name = fname;
844 assert(WMHashInsert(scrPtr->fontSetCache, font->name, font)==NULL);
846 return font;
851 WMFont*
852 WMCreateNormalFont(WMScreen *scrPtr, char *fontName)
854 WMFont *font;
855 Display *display = scrPtr->display;
856 char *fname, *ptr;
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;
864 } else {
865 fname = wstrdup(fontName);
868 wfree(fontName);
870 font = WMHashGet(scrPtr->fontCache, fname);
871 if (font) {
872 WMRetainFont(font);
873 wfree(fname);
874 return font;
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) {
887 wfree(font);
888 wfree(fname);
889 return NULL;
891 font->height = font->font.normal->ascent+font->font.normal->descent;
892 font->y = font->font.normal->ascent;
894 font->refCount = 1;
896 font->name = fname;
898 assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL);
900 return font;
904 WMFont*
905 WMCreateAntialiasedFont(WMScreen *scrPtr, char *fontName)
907 #ifdef XFT
908 WMFont *font;
909 Display *display = scrPtr->display;
910 char *fname, *ptr;
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;
918 } else {
919 fname = wstrdup(fontName);
922 wfree(fontName);
924 font = WMHashGet(scrPtr->xftFontCache, fname);
925 if (font) {
926 WMRetainFont(font);
927 wfree(fname);
928 return font;
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
943 * return NULL.
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
947 * return NULL.
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
951 * are invalid.
953 printf("%s\n", fname);
954 if (fname[0] == '-') {
955 font->font.xft = XftFontOpenXlfd(display, scrPtr->screen, fname);
956 } else {
957 font->font.xft = XftFontOpenName(display, scrPtr->screen, fname);
959 if (!font->font.xft) {
960 wfree(font);
961 wfree(fname);
962 return NULL;
964 font->height = font->font.xft->ascent+font->font.xft->descent;
965 font->y = font->font.xft->ascent;
967 font->refCount = 1;
969 font->name = fname;
971 assert(WMHashInsert(scrPtr->xftFontCache, font->name, font)==NULL);
973 return font;
974 #else
975 return NULL;
976 #endif
980 WMFont*
981 WMCreateAntialiasedFontSet(WMScreen *scrPtr, char *fontName)
983 #ifdef XFT
984 WMFont *font;
985 Display *display = scrPtr->display;
986 char *fname, *ptr;
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;
994 } else {
995 fname = wstrdup(fontName);
998 wfree(fontName);
1000 font = WMHashGet(scrPtr->xftFontSetCache, fname);
1001 if (font) {
1002 WMRetainFont(font);
1003 wfree(fname);
1004 return font;
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
1019 * return NULL.
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
1023 * return NULL.
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
1027 * are invalid.
1029 if (fname[0] == '-') {
1030 font->font.xft = XftFontOpenXlfd(display, scrPtr->screen, fname);
1031 } else {
1032 font->font.xft = XftFontOpenName(display, scrPtr->screen, fname);
1034 if (!font->font.xft) {
1035 wfree(font);
1036 wfree(fname);
1037 return NULL;
1039 font->height = font->font.xft->ascent+font->font.xft->descent;
1040 font->y = font->font.xft->ascent;
1042 font->refCount = 1;
1044 font->name = fname;
1046 assert(WMHashInsert(scrPtr->xftFontSetCache, font->name, font)==NULL);
1048 return font;
1049 #else
1050 return NULL;
1051 #endif
1055 WMFont*
1056 WMCreateFont(WMScreen *scrPtr, char *fontName)
1058 return WMCreateFontWithFlags(scrPtr, fontName, WFDefaultFont);
1062 WMFont*
1063 WMCreateFontWithFlags(WMScreen *scrPtr, char *fontName, WMFontFlags flags)
1065 Bool multiByte = scrPtr->useMultiByte;
1066 Bool antialiased = scrPtr->antialiasedText;
1067 WMFont *font;
1069 if (flags & WFFontSet) {
1070 multiByte = True;
1071 } else if (flags & WFNormalFont) {
1072 multiByte = False;
1074 if (flags & WFAntialiased) {
1075 antialiased = True;
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);
1096 } else {
1097 font = WMCreateNormalFont(scrPtr, fontName);
1100 return font;
1104 WMFont*
1105 WMRetainFont(WMFont *font)
1107 wassertrv(font!=NULL, NULL);
1109 font->refCount++;
1111 return font;
1115 void
1116 WMReleaseFont(WMFont *font)
1118 wassertr(font!=NULL);
1120 font->refCount--;
1121 if (font->refCount < 1) {
1122 if (font->antialiased) {
1123 #ifdef XFT
1124 XftFontClose(font->screen->display, font->font.xft);
1125 #else
1126 assert(False);
1127 #endif
1128 } else if (font->notFontSet) {
1129 XFreeFont(font->screen->display, font->font.normal);
1130 } else {
1131 XFreeFontSet(font->screen->display, font->font.set);
1134 if (font->name) {
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);
1141 } else {
1142 WMHashRemove(font->screen->fontSetCache, font->name);
1144 wfree(font->name);
1146 wfree(font);
1151 Bool
1152 WMIsAntialiasingEnabled(WMScreen *scrPtr)
1154 return scrPtr->antialiasedText;
1158 Bool
1159 WMIsAntialiasedFont(WMFont *font)
1161 wassertrv(font!=NULL, False);
1163 return font->antialiased;
1167 unsigned int
1168 WMFontHeight(WMFont *font)
1170 wassertrv(font!=NULL, 0);
1172 return font->height;
1176 char*
1177 WMGetFontName(WMFont *font)
1179 wassertrv(font!=NULL, NULL);
1181 return font->name;
1185 WMFont*
1186 WMDefaultSystemFont(WMScreen *scrPtr)
1188 return WMRetainFont(scrPtr->normalFont);
1192 WMFont*
1193 WMDefaultBoldSystemFont(WMScreen *scrPtr)
1195 return WMRetainFont(scrPtr->boldFont);
1199 static WMFont*
1200 makeSystemFontOfSize(WMScreen *scrPtr, int size, Bool bold)
1202 WMFont *font;
1203 char *fontSpec, *xftFontSpec;
1205 #define WConf WINGsConfiguration
1206 if (bold) {
1207 fontSpec = makeFontSetOfSize(WConf.boldSystemFont, size);
1208 xftFontSpec = makeFontSetOfSize(WConf.antialiasedBoldSystemFont, size);
1209 } else {
1210 fontSpec = makeFontSetOfSize(WConf.systemFont, size);
1211 xftFontSpec = makeFontSetOfSize(WConf.antialiasedSystemFont, size);
1213 #undef WConf
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);
1221 } else {
1222 font = WMCreateNormalFont(scrPtr, fontSpec);
1225 if (!font) {
1226 if (scrPtr->antialiasedText && scrPtr->useMultiByte) {
1227 // is arial a good fallback for multibyte?
1228 wwarning(_("could not load font %s. Trying arial."), xftFontSpec);
1229 if (bold) {
1230 font = WMCreateAntialiasedFontSet(scrPtr, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
1231 } else {
1232 font = WMCreateAntialiasedFontSet(scrPtr, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
1234 if (!font) {
1235 wwarning(_("could not load antialiased font set. Reverting to standard font sets."));
1236 font = WMCreateFontSet(scrPtr, fontSpec);
1237 if (!font) {
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);
1244 if (bold) {
1245 font = WMCreateAntialiasedFont(scrPtr, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
1246 } else {
1247 font = WMCreateAntialiasedFont(scrPtr, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
1249 if (!font) {
1250 wwarning(_("could not load antialiased fonts. Reverting to normal fonts."));
1251 font = WMCreateNormalFont(scrPtr, fontSpec);
1252 if (!font) {
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");
1260 if (!font) {
1261 font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
1263 } else {
1264 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
1265 font = WMCreateNormalFont(scrPtr, "fixed");
1267 if (!font) {
1268 wwarning(_("could not load fixed font!"));
1269 wfree(fontSpec);
1270 wfree(xftFontSpec);
1271 return NULL;
1274 wfree(fontSpec);
1275 wfree(xftFontSpec);
1277 return font;
1281 WMFont*
1282 WMSystemFontOfSize(WMScreen *scrPtr, int size)
1284 return makeSystemFontOfSize(scrPtr, size, False);
1288 WMFont*
1289 WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
1291 return makeSystemFontOfSize(scrPtr, size, True);
1295 XFontSet
1296 WMGetFontFontSet(WMFont *font)
1298 wassertrv(font!=NULL, NULL);
1300 if (!font->notFontSet && !font->antialiased)
1301 return font->font.set;
1303 return NULL;
1308 WMWidthOfString(WMFont *font, char *text, int length)
1310 wassertrv(font!=NULL, 0);
1311 wassertrv(text!=NULL, 0);
1313 if (font->antialiased) {
1314 #ifdef XFT
1315 XGlyphInfo extents;
1317 if (!font->notFontSet) {
1318 wchar_t *wtext;
1319 char *mtext;
1320 int len;
1322 /* Use mtext instead of text, because mbstrtowcs() alters it */
1323 mtext = text;
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);
1328 if (len>0) {
1329 XftTextExtents32(font->screen->display, font->font.xft,
1330 (XftChar32 *)wtext, len, &extents);
1331 } else {
1332 if (len==-1) {
1333 wwarning(_("Conversion to widechar failed (possible "
1334 "invalid multibyte sequence): '%s':(pos %d)\n"),
1335 text, mtext-text+1);
1337 extents.xOff = 0;
1339 wfree(wtext);
1340 } else {
1341 XftTextExtents8(font->screen->display, font->font.xft,
1342 (XftChar8 *)text, length, &extents);
1345 return extents.xOff; /* don't ask :P */
1346 #else
1347 wassertrv(False, 0);
1348 #endif
1349 } else if (font->notFontSet) {
1350 return XTextWidth(font->font.normal, text, length);
1351 } else {
1352 XRectangle rect;
1353 XRectangle AIXsucks;
1355 XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect);
1357 return rect.width;
1363 void
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) {
1370 #ifdef XFT
1371 XftColor xftcolor;
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) {
1382 wchar_t *wtext;
1383 char *mtext;
1384 int len;
1386 /* Use mtext instead of text, because mbstrtowcs() alters it */
1387 mtext = text;
1388 wtext = (wchar_t *)wmalloc(4*length+4);
1389 len = mbsrtowcs(wtext, (const char **) &mtext, length, NULL);
1390 if (len>0) {
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);*/
1402 wfree(wtext);
1403 } else {
1404 XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
1405 x, y + font->y, (XftChar8*)text, length);
1407 #else
1408 wassertr(False);
1409 #endif
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,
1414 text, length);
1415 } else {
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);
1423 void
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) {
1430 #ifdef XFT
1431 XftColor textColor;
1432 XftColor bgColor;
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) {
1453 wchar_t *wtext;
1454 char *mtext;
1455 int len;
1457 /* Use mtext instead of text, because mbstrtowcs() alters it */
1458 mtext = text;
1459 wtext = (wchar_t *)wmalloc(4*length+4);
1460 len = mbsrtowcs(wtext, (const char **) &mtext, length, NULL);
1461 if (len>0) {
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);*/
1473 wfree(wtext);
1474 } else {
1475 XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
1476 x, y + font->y, (XftChar8*)text, length);
1478 #else
1479 wassertr(False);
1480 #endif
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);
1487 } else {
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);
1498 static char*
1499 makeFontSetOfSize(char *fontset, int size)
1501 char font[300], *f;
1502 char *newfs = NULL;
1503 char *ptr;
1505 do {
1506 char *tmp;
1507 int end;
1510 f = fontset;
1511 ptr = strchr(fontset, ',');
1512 if (ptr) {
1513 int count = ptr-fontset;
1515 if (count > 255) {
1516 wwarning(_("font description %s is too large."), fontset);
1517 } else {
1518 memcpy(font, fontset, count);
1519 font[count] = 0;
1520 f = (char*)font;
1524 if (newfs)
1525 end = strlen(newfs);
1526 else
1527 end = 0;
1529 tmp = wmalloc(end + strlen(f) + 8);
1530 if (end != 0) {
1531 sprintf(tmp, "%s,", newfs);
1532 sprintf(tmp + end + 1, f, size);
1533 } else {
1534 sprintf(tmp + end, f, size);
1537 if (newfs)
1538 wfree(newfs);
1539 newfs = tmp;
1541 fontset = ptr+1;
1542 } while (ptr!=NULL);
1544 return newfs;
1548 #define FONT_PROPS 14
1550 typedef struct {
1551 char *props[FONT_PROPS];
1552 } W_FontAttributes;
1555 static void
1556 changeFontProp(char *buf, char *newprop, int position)
1558 char buf2[512];
1559 char *ptr, *pptr, *rptr;
1560 int count;
1562 if (buf[0]!='-') {
1563 /* // remove warning later. or maybe not */
1564 wwarning(_("Invalid font specification: '%s'\n"), buf);
1565 return;
1568 ptr = pptr = rptr = buf;
1569 count = 0;
1570 while (*ptr && *ptr!=',') {
1571 if (*ptr == '-') {
1572 count++;
1573 if (count-1==position+1) {
1574 rptr = ptr;
1575 break;
1577 if (count-1==position) {
1578 pptr = ptr+1;
1581 ptr++;
1583 if (position==FONT_PROPS-1) {
1584 rptr = ptr;
1587 *pptr = 0;
1588 snprintf(buf2, 512, "%s%s%s", buf, newprop, rptr);
1589 strcpy(buf, buf2);
1593 static WMArray*
1594 getOptions(char *options)
1596 char *ptr, *ptr2, *str;
1597 WMArray *result;
1598 int count;
1600 result = WMCreateArrayWithDestructor(2, (WMFreeDataProc*)wfree);
1602 ptr = options;
1603 while (1) {
1604 ptr2 = strchr(ptr, ',');
1605 if (!ptr2) {
1606 WMAddToArray(result, wstrdup(ptr));
1607 break;
1608 } else {
1609 count = ptr2 - ptr;
1610 str = wmalloc(count+1);
1611 memcpy(str, ptr, count);
1612 str[count] = 0;
1613 WMAddToArray(result, str);
1614 ptr = ptr2 + 1;
1618 return result;
1622 WMFont*
1623 WMCopyFontWithChanges(WMScreen *scrPtr, WMFont *font,
1624 const WMFontAttributes *changes)
1626 int index[FONT_PROPS], count[FONT_PROPS];
1627 int totalProps, i, j, carry;
1628 char fname[512];
1629 WMFontFlags fFlags;
1630 WMBag *props;
1631 WMArray *options;
1632 WMFont *result;
1633 char *prop;
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);
1642 totalProps = 0;
1643 for (i=0; i<FONT_PROPS; i++) {
1644 prop = ((W_FontAttributes*)changes)->props[i];
1645 count[i] = index[i] = 0;
1646 if (!prop) {
1647 /* No change for this property */
1648 continue;
1649 } else if (strchr(prop, ',')==NULL) {
1650 /* Simple option */
1651 changeFontProp(fname, prop, i);
1652 } else {
1653 /* Option with fallback alternatives */
1654 if ((changes==WFAEmphasized || changes==WFABoldEmphasized) &&
1655 font->antialiased && strcmp(prop, "o,i")==0) {
1656 options = getOptions("i,o");
1657 } else {
1658 options = getOptions(prop);
1660 WMInsertInBag(props, i, options);
1661 count[i] = WMGetArrayItemCount(options);
1662 if (totalProps==0)
1663 totalProps = 1;
1664 totalProps = totalProps * count[i];
1668 if (totalProps == 0) {
1669 /* No options with fallback alternatives at all */
1670 WMFreeBag(props);
1671 return WMCreateFontWithFlags(scrPtr, fname, fFlags);
1674 for (i=0; i<totalProps; i++) {
1675 for (j=0; j<FONT_PROPS; j++) {
1676 if (count[j]!=0) {
1677 options = WMGetFromBag(props, j);
1678 prop = WMGetFromArray(options, index[j]);
1679 if (prop) {
1680 changeFontProp(fname, prop, j);
1684 result = WMCreateFontWithFlags(scrPtr, fname, fFlags);
1685 if (result) {
1686 WMFreeBag(props);
1687 return result;
1689 for (j=FONT_PROPS-1, carry=1; j>=0; j--) {
1690 if (count[j]!=0) {
1691 index[j] += carry;
1692 carry = (index[j]==count[j]);
1693 index[j] %= count[j];
1698 WMFreeBag(props);
1700 return NULL;
1703 #endif
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;