1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 04:20:27 +01:00

- Added support for antialiased text with multibyte languages too.

(only tested on russian, since that's the only multibyte language
  I can test).
This commit is contained in:
dan
2002-11-21 05:21:42 +00:00
parent 3929660f39
commit 2fe1b0e3f8
7 changed files with 261 additions and 91 deletions

View File

@@ -29,6 +29,13 @@ Changes since wmaker 0.80.1:
- You can now pass "SystemFont", "BoldSystemFont", "SystemFont-##" or
"BoldSystemFont-##", with ## being the font size to any font creating
function to create a font with the (bold) system font font specification.
- Added WMCreateAntialiasedFontSet() (like WMCreateAntialiasedFont() but for
languages with multibyte text). Note however that these specific font
creating functions (as well as WMCreateNormalFont() and WMCreateFontSet())
are not meant to be called directly except in very special cases.
The more generic WMCreateFont() or WMCreateFontWithFlags() should be used.
- Multibyte languages can now render antialiased text too (only tested on
russian since this is the only multibyte language I can test).
Changes since wmaker 0.80.0:

View File

@@ -129,8 +129,9 @@ fonts with transparency will be compiled into WINGs.
You need at least Xfree86 version 4.0.x for this but at least 4.1.x is
recommended.
For Xft support there is a new function to create a font that will render
using antialiasing and transparency: WMCreateAntialiasedFont().
For Xft support there are 2 new functions to create a font that will render
using antialiasing and transparency: WMCreateAntialiasedFont() and
WMCreateAntialiasedFontSet(). Later is for multibyte languages.
Passing such a font to WMDrawString() or WMDrawImageString() will result
in antialiased text displayed on screen. Modifying the alpha value for the
WMColor passed to WMDrawString() or WMDrawImageString() will result in text

View File

@@ -726,12 +726,14 @@ Bool WMIsAntialiasingEnabled(WMScreen *scrPtr);
/* ....................................................................... */
WMFont* WMCreateFontSet(WMScreen *scrPtr, char *fontName);
WMFont* WMCreateNormalFont(WMScreen *scrPtr, char *fontName);
WMFont* WMCreateFontSet(WMScreen *scrPtr, char *fontName);
WMFont* WMCreateAntialiasedFont(WMScreen *scrPtr, char *fontName);
WMFont* WMCreateAntialiasedFontSet(WMScreen *scrPtr, char *fontName);
WMFont* WMCreateFont(WMScreen *scrPtr, char *fontName);
WMFont* WMCreateFontWithFlags(WMScreen *scrPtr, char *fontName, WMFontFlags flags);

View File

@@ -204,6 +204,8 @@ typedef struct W_Screen {
WMHashTable *fontSetCache;
WMHashTable *xftFontSetCache;
Bool useMultiByte;
Bool antialiasedText;

View File

@@ -92,6 +92,7 @@ W_ReadConfigurations(void)
if (locale != NULL
&& (strncmp(locale, "ja", 2) == 0
|| strncmp(locale, "zh", 2) == 0
|| strncmp(locale, "ru", 2) == 0
|| strncmp(locale, "ko", 2) == 0)) {
WINGsConfiguration.useMultiByte = True;

View File

@@ -338,6 +338,79 @@ WMCreateAntialiasedFont(WMScreen *scrPtr, char *fontName)
}
WMFont*
WMCreateAntialiasedFontSet(WMScreen *scrPtr, char *fontName)
{
#ifdef XFT
WMFont *font;
Display *display = scrPtr->display;
char *fname, *ptr;
if (!scrPtr->hasXftSupport)
return NULL;
fontName = xlfdFromFontName(fontName, True);
// use the second in list if available, instead of first?
if ((ptr = strchr(fontName, ','))) {
fname = wmalloc(ptr - fontName + 1);
strncpy(fname, fontName, ptr - fontName);
fname[ptr - fontName] = 0;
} else {
fname = wstrdup(fontName);
}
wfree(fontName);
font = WMHashGet(scrPtr->xftFontSetCache, fname);
if (font) {
WMRetainFont(font);
wfree(fname);
return font;
}
font = wmalloc(sizeof(WMFont));
memset(font, 0, sizeof(WMFont));
font->notFontSet = 0;
font->antialiased = 1;
font->screen = scrPtr;
#if 0
/* // Xft sux. Loading a font that doesn't exist will load the default
* defined in XftConfig without any warning or error */
font->font.normal = XLoadQueryFont(display, fname);
if (!font->font.normal) {
wfree(font);
wfree(fname);
return NULL;
}
XFreeFont(display, font->font.normal);
#endif
font->font.xft = XftFontOpenXlfd(display, scrPtr->screen, fname);
if (!font->font.xft) {
wfree(font);
wfree(fname);
return NULL;
}
font->height = font->font.xft->ascent+font->font.xft->descent;
font->y = font->font.xft->ascent;
font->refCount = 1;
font->name = fname;
assert(WMHashInsert(scrPtr->xftFontSetCache, font->name, font)==NULL);
return font;
#else
return NULL;
#endif
}
WMFont*
WMCreateFont(WMScreen *scrPtr, char *fontName)
{
@@ -363,12 +436,13 @@ WMCreateFontWithFlags(WMScreen *scrPtr, char *fontName, WMFontFlags flags)
antialiased = False;
}
/* Multibyte with antialiasing is not implemented. To avoid problems,
* if both multiByte and antialiasing are enabled, ignore antialiasing
* and return a FontSet.
*/
if (multiByte) {
font = WMCreateFontSet(scrPtr, fontName);
if (antialiased && multiByte) {
font = WMCreateAntialiasedFontSet(scrPtr, fontName);
/* If we cannot create an antialiased font set and antialiasing is
* not explicitly requested in flags, fallback to standard font sets */
if (!font && (flags & WFAntialiased)==0) {
font = WMCreateFontSet(scrPtr, fontName);
}
} else if (antialiased) {
font = WMCreateAntialiasedFont(scrPtr, fontName);
/* If we cannot create an antialiased font and antialiasing is
@@ -376,6 +450,8 @@ WMCreateFontWithFlags(WMScreen *scrPtr, char *fontName, WMFontFlags flags)
if (!font && (flags & WFAntialiased)==0) {
font = WMCreateNormalFont(scrPtr, fontName);
}
} else if (multiByte) {
font = WMCreateFontSet(scrPtr, fontName);
} else {
font = WMCreateNormalFont(scrPtr, fontName);
}
@@ -402,21 +478,22 @@ WMReleaseFont(WMFont *font)
font->refCount--;
if (font->refCount < 1) {
if (font->notFontSet) {
if (font->antialiased) {
if (font->antialiased) {
#ifdef XFT
XftFontClose(font->screen->display, font->font.xft);
XftFontClose(font->screen->display, font->font.xft);
#else
assert(False);
assert(False);
#endif
} else {
XFreeFont(font->screen->display, font->font.normal);
}
} else if (font->notFontSet) {
XFreeFont(font->screen->display, font->font.normal);
} else {
XFreeFontSet(font->screen->display, font->font.set);
}
XFreeFontSet(font->screen->display, font->font.set);
}
if (font->name) {
if (font->antialiased) {
if (font->antialiased && !font->notFontSet) {
WMHashRemove(font->screen->xftFontSetCache, font->name);
} else if (font->antialiased) {
WMHashRemove(font->screen->xftFontCache, font->name);
} else if (font->notFontSet) {
WMHashRemove(font->screen->fontCache, font->name);
@@ -490,20 +567,32 @@ makeSystemFontOfSize(WMScreen *scrPtr, int size, Bool bold)
}
#undef WConf
if (scrPtr->useMultiByte) {
font = WMCreateFontSet(scrPtr, fontSpec);
if (scrPtr->antialiasedText && scrPtr->useMultiByte) {
font = WMCreateAntialiasedFontSet(scrPtr, xftFontSpec);
} else if (scrPtr->antialiasedText) {
font = WMCreateAntialiasedFont(scrPtr, xftFontSpec);
} else if (scrPtr->useMultiByte) {
font = WMCreateFontSet(scrPtr, fontSpec);
} else {
font = WMCreateNormalFont(scrPtr, fontSpec);
}
if (!font) {
if (scrPtr->useMultiByte) {
wwarning(_("could not load font set %s. Trying fixed."), fontSpec);
font = WMCreateFontSet(scrPtr, "fixed");
if (scrPtr->antialiasedText && scrPtr->useMultiByte) {
// is arial a good fallback for multibyte?
wwarning(_("could not load font %s. Trying arial."), xftFontSpec);
if (bold) {
font = WMCreateAntialiasedFontSet(scrPtr, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
} else {
font = WMCreateAntialiasedFontSet(scrPtr, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
}
if (!font) {
font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
wwarning(_("could not load antialiased font set. Reverting to standard font sets."));
font = WMCreateFontSet(scrPtr, fontSpec);
if (!font) {
wwarning(_("could not load FontSet %s. Trying fixed."), fontSpec);
font = WMCreateFontSet(scrPtr, "fixed");
}
}
} else if (scrPtr->antialiasedText) {
wwarning(_("could not load font %s. Trying arial."), xftFontSpec);
@@ -520,6 +609,12 @@ makeSystemFontOfSize(WMScreen *scrPtr, int size, Bool bold)
font = WMCreateNormalFont(scrPtr, "fixed");
}
}
} else if (scrPtr->useMultiByte) {
wwarning(_("could not load font set %s. Trying fixed."), fontSpec);
font = WMCreateFontSet(scrPtr, "fixed");
if (!font) {
font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
}
} else {
wwarning(_("could not load font %s. Trying fixed."), fontSpec);
font = WMCreateNormalFont(scrPtr, "fixed");
@@ -557,10 +652,10 @@ WMGetFontFontSet(WMFont *font)
{
wassertrv(font!=NULL, NULL);
if (font->notFontSet)
return NULL;
else
return font->font.set;
if (!font->notFontSet && !font->antialiased)
return font->font.set;
return NULL;
}
@@ -570,27 +665,49 @@ WMWidthOfString(WMFont *font, char *text, int length)
wassertrv(font!=NULL, 0);
wassertrv(text!=NULL, 0);
if (font->notFontSet) {
if (font->antialiased) {
if (font->antialiased) {
#ifdef XFT
XGlyphInfo extents;
XGlyphInfo extents;
if (!font->notFontSet) {
wchar_t *wtext;
char *mtext;
/* Use mtext instead of text, because mbstrtowcs() alters it */
mtext = text;
wtext = (wchar_t *)wmalloc(4*length+4);
// pass a real ps instead of NULL below? for multithread safety as
// from manual
if (mbsrtowcs(wtext, &mtext, length, NULL)==length) {
XftTextExtents32(font->screen->display, font->font.xft,
(XftChar32 *)wtext, length, &extents);
} else {
// - should rather say that conversion to widechar failed?
// - use mtext instead of text so that the position of the
// invalid sequence is shown?
wwarning(_("Invalid multibyte sequence: '%s'\n"), text);
XftTextExtents8(font->screen->display, font->font.xft,
(XftChar8 *)text, length, &extents);
}
wfree(wtext);
} else {
XftTextExtents8(font->screen->display, font->font.xft,
(XftChar8 *)text, length, &extents);
return extents.xOff; /* don't ask :P */
#else
assert(False);
#endif
} else {
return XTextWidth(font->font.normal, text, length);
}
return extents.xOff; /* don't ask :P */
#else
wassertrv(False, 0);
#endif
} else if (font->notFontSet) {
return XTextWidth(font->font.normal, text, length);
} else {
XRectangle rect;
XRectangle AIXsucks;
XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect);
return rect.width;
XRectangle rect;
XRectangle AIXsucks;
XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect);
return rect.width;
}
}
@@ -602,30 +719,49 @@ WMDrawString(WMScreen *scr, Drawable d, WMColor *color, WMFont *font,
{
wassertr(font!=NULL);
if (font->notFontSet) {
if (font->antialiased) {
if (font->antialiased) {
#ifdef XFT
XftColor xftcolor;
XftColor xftcolor;
xftcolor.color.red = color->color.red;
xftcolor.color.green = color->color.green;
xftcolor.color.blue = color->color.blue;
xftcolor.color.alpha = color->alpha;;
xftcolor.pixel = W_PIXEL(color);
xftcolor.color.red = color->color.red;
xftcolor.color.green = color->color.green;
xftcolor.color.blue = color->color.blue;
xftcolor.color.alpha = color->alpha;;
xftcolor.pixel = W_PIXEL(color);
XftDrawChange(scr->xftdraw, d);
XftDrawChange(scr->xftdraw, d);
XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
x, y + font->y, text, length);
#else
assert(False);
#endif
if (!font->notFontSet) {
wchar_t *wtext;
char *mtext;
/* Use mtext instead of text, because mbstrtowcs() alters it */
mtext = text;
wtext = (wchar_t *)wmalloc(4*length+4);
if (mbsrtowcs(wtext, &mtext, length, NULL)==length) {
XftDrawString32(scr->xftdraw, &xftcolor, font->font.xft,
x, y + font->y, (XftChar32*)wtext, length);
} else {
// - should rather say that conversion to widechar failed?
// - use mtext instead of text so that the position of the
// invalid sequence is shown?
wwarning(_("Invalid multibyte sequence: '%s'\n"), text);
XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
x, y + font->y, (XftChar8*)text, length);
}
wfree(wtext);
} else {
XSetFont(scr->display, scr->drawStringGC, font->font.normal->fid);
XSetForeground(scr->display, scr->drawStringGC, W_PIXEL(color));
XDrawString(scr->display, d, scr->drawStringGC, x, y + font->y,
text, length);
XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
x, y + font->y, (XftChar8*)text, length);
}
#else
wassertr(False);
#endif
} else if (font->notFontSet) {
XSetFont(scr->display, scr->drawStringGC, font->font.normal->fid);
XSetForeground(scr->display, scr->drawStringGC, W_PIXEL(color));
XDrawString(scr->display, d, scr->drawStringGC, x, y + font->y,
text, length);
} else {
XSetForeground(scr->display, scr->drawStringGC, W_PIXEL(color));
XmbDrawString(scr->display, d, font->font.set, scr->drawStringGC,
@@ -638,44 +774,63 @@ void
WMDrawImageString(WMScreen *scr, Drawable d, WMColor *color, WMColor *background,
WMFont *font, int x, int y, char *text, int length)
{
wassertr(font != NULL);
wassertr(font!=NULL);
if (font->notFontSet) {
if (font->antialiased) {
if (font->antialiased) {
#ifdef XFT
XftColor textColor;
XftColor bgColor;
XftColor textColor;
XftColor bgColor;
textColor.color.red = color->color.red;
textColor.color.green = color->color.green;
textColor.color.blue = color->color.blue;
textColor.color.alpha = color->alpha;;
textColor.pixel = W_PIXEL(color);
textColor.color.red = color->color.red;
textColor.color.green = color->color.green;
textColor.color.blue = color->color.blue;
textColor.color.alpha = color->alpha;;
textColor.pixel = W_PIXEL(color);
bgColor.color.red = background->color.red;
bgColor.color.green = background->color.green;
bgColor.color.blue = background->color.blue;
bgColor.color.alpha = background->alpha;;
bgColor.pixel = W_PIXEL(background);
bgColor.color.red = background->color.red;
bgColor.color.green = background->color.green;
bgColor.color.blue = background->color.blue;
bgColor.color.alpha = background->alpha;;
bgColor.pixel = W_PIXEL(background);
XftDrawChange(scr->xftdraw, d);
XftDrawChange(scr->xftdraw, d);
XftDrawRect(scr->xftdraw, &bgColor, x, y,
WMWidthOfString(font, text, length), font->height);
XftDrawRect(scr->xftdraw, &bgColor, x, y,
WMWidthOfString(font, text, length), font->height);
XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
x, y + font->y, text, length);
#else
assert(False);
#endif
if (!font->notFontSet) {
wchar_t *wtext;
char *mtext;
/* Use mtext instead of text, because mbstrtowcs() alters it */
mtext = text;
wtext = (wchar_t *)wmalloc(4*length+4);
if (mbsrtowcs(wtext, &mtext, length, NULL)==length) {
XftDrawString32(scr->xftdraw, &textColor, font->font.xft,
x, y + font->y, (XftChar32*)wtext, length);
} else {
// - should rather say that conversion to widechar failed?
// - use mtext instead of text so that the position of the
// invalid sequence is shown?
wwarning(_("Invalid multibyte sequence: '%s'\n"), text);
XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
x, y + font->y, (XftChar8*)text, length);
}
wfree(wtext);
} else {
XSetForeground(scr->display, scr->drawImStringGC, W_PIXEL(color));
XSetBackground(scr->display, scr->drawImStringGC, W_PIXEL(background));
XSetFont(scr->display, scr->drawImStringGC, font->font.normal->fid);
XDrawImageString(scr->display, d, scr->drawImStringGC,
x, y + font->y, text, length);
XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
x, y + font->y, (XftChar8*)text, length);
}
#else
wassertr(False);
#endif
} else if (font->notFontSet) {
XSetForeground(scr->display, scr->drawImStringGC, W_PIXEL(color));
XSetBackground(scr->display, scr->drawImStringGC, W_PIXEL(background));
XSetFont(scr->display, scr->drawImStringGC, font->font.normal->fid);
XDrawImageString(scr->display, d, scr->drawImStringGC,
x, y + font->y, text, length);
} else {
XSetForeground(scr->display, scr->drawImStringGC, W_PIXEL(color));
XSetBackground(scr->display, scr->drawImStringGC, W_PIXEL(background));

View File

@@ -626,6 +626,8 @@ WMCreateScreenWithRContext(Display *display, int screen, RContext *context)
scrPtr->fontSetCache = WMCreateHashTable(WMStringPointerHashCallbacks);
scrPtr->xftFontSetCache = WMCreateHashTable(WMStringPointerHashCallbacks);
#ifdef XFT
scrPtr->hasXftSupport = XftDefaultHasRender(scrPtr->display);