Dimitri Shlyakhtenko <[EMAIL PROTECTED]> writes: | Hello all, | | The patch below is a hack allowing lyx to use anti-aliased fonts (via | libXft and the render extension in recent versions of XFree86). The | patch is against lyx-1.1.6fix2. | | I am fully aware of the fact that this patch is not an elegant solution | at all, and that one should (in principle) modify LyX's internal font | handling to allocate and use XftFonts. Unfortunately, I lack the | knowledge for such an undertaking... As a result, the enclosed solution | is much less elegant and slower than it should be. On the other hand, I | used these modifications for a little while now, and am quite happy with | the new fonts in LyX. I hope it works for you! | | Please look in the file README.render for more information on what I | changed. Ok, interesting. (but you diff do many files...) You coding style is a bit too "C-like" for my taste. - Use c++ style casts - use bool - use preincrement. Also I belive that what you do could be better integrated into lyx, I also thing the caches would benefit from stl. | --- lyx-1.1.6fix2/config/lyxinclude.m4 Mon Mar 5 06:02:49 2001 | +++ lyx-1.1.6fix2-antialias/config/lyxinclude.m4 Sun Jul 15 08:51:49 2001 | @@ -556,6 +556,20 @@ | fi | ]) | | +dnl Usage LYX_PATH_XFT: Checks for Xft library and header | +AC_DEFUN(LYX_PATH_XFT,[ | +### Check for Xft library | +AC_CHECK_LIB(Xft, XftDrawString8, LYX_LIBS="-lXft $LYX_LIBS", | + true, $LYX_LIBS) | + | +### Check for Xft headers | +lyx_cv_xft_h_location="<Xft/Xft.h>" | +AC_CHECK_HEADER(X11/Xft/Xft.h,[ | + ac_cv_header_xft_h=yes | + lyx_cv_xft_h_location="<X11/Xft/Xft.h>"],[]) | + AC_DEFINE_UNQUOTED(XFT_H_LOCATION, $lyx_cv_xft_h_location) | +]) | + | dnl Usage LYX_PATH_XPM: Checks for xpm library and header | AC_DEFUN(LYX_PATH_XPM,[ ok... | diff -Pur lyx-1.1.6fix2/src/FontLoader.h lyx-1.1.6fix2-antialias/src/FontLoader.h | --- lyx-1.1.6fix2/src/FontLoader.h Mon Aug 7 13:58:21 2000 | +++ lyx-1.1.6fix2-antialias/src/FontLoader.h Sun Jul 15 08:52:21 2001 | @@ -49,23 +49,23 @@ | else | return doLoad(family, series, shape, size); | }; | + /// Array of font infos | + FontInfo * fontinfo[4][2][4]; | + | + | + /// Get font info | + void getFontinfo(LyXFont::FONT_FAMILY family, | + LyXFont::FONT_SERIES series, | + LyXFont::FONT_SHAPE shape); | private: | /// Array of font structs | XFontStruct * fontstruct[4][2][4][10]; | | - /// Array of font infos | - FontInfo * fontinfo[4][2][4]; | - | /// Reset font handler | void reset(); | | /// Unload all fonts | void unload(); | - | - /// Get font info | - void getFontinfo(LyXFont::FONT_FAMILY family, | - LyXFont::FONT_SERIES series, | - LyXFont::FONT_SHAPE shape); | | /** Does the actual loading of a font. Updates fontstruct. */ | XFontStruct * doLoad(LyXFont::FONT_FAMILY family, I wonder if this change is really needed. | +} | + | +typedef struct _cache_entry { | + Colormap c; | + Drawable w; | + GC gc; | + string colorName; | + | + XftDraw *draw; | + XftColor color; | +} cache_entry; This is C and not C++ struct cache_entry { .. }; is better in C++. | +#define MAXCACHE 90 int const MAXCACHE = 90; | +PainterBase & Painter::XDrawString(Display *d, Drawable w, GC gc, int x, | + int y, char * const s, int sl, LyXFont const &f) { | +#ifdef XFT_H_LOCATION | + | + static cache_entry cache[MAXCACHE+1]; a std::vector<cache_entry> cache; | + static int to_replace = 0; | + unsigned long foreground; | + XftFont *xftfont; | + | + Visual *visual = XDefaultVisual(d, fl_screen); | + Colormap colormap = fl_state[fl_get_vclass()].colormap; | + | + int i; | + int found = 0; bool found = false; | + string str = lcolor.getX11Name(f.realColor()); | + | + | + for (i = 0; i < MAXCACHE && ! found && cache[i].draw; i++) | + if (cache[i].c == colormap && cache[i].w == w && | + cache[i].gc == gc && | + cache[i].colorName == str) found = 1; | + if (found) i--; --i; | + if (!found || ! cache[i].draw ) { | + if (! cache[i].draw && i < MAXCACHE ) to_replace = i; | + i = to_replace % MAXCACHE; to_replace++; | + cache[i].gc = gc; | + cache[i].c = colormap; | + cache[i].w = w; | + cache[i].colorName = str; Could actually store this in a kind of "priority map" so that often used items float to the beginning of the container. | + | + XftColorAllocName(d, visual, colormap, (char *)cache[i].colorName.c_str(), | + &(cache[i].color) ); static_cast<char*>(...) or more likely const_cast<char*>(..) | + cache[i].draw = XftDrawCreate(d, w, visual, colormap); | + | + | + // lyxerr << "Inserting into cache" << i << " " << str.c_str() << "\n"; | + } | + | + int fsize = int( (lyxrc.font_sizes[f.size()] * lyxrc.dpi * | + (lyxrc.zoom/100.0) ) / 72.27 + 0.5 ); | + | + string font = fontloader.fontinfo[f.family()][f.series()][f.realShape()]-> | + getFontname(fsize); | + | +// lyxerr << font.c_str() << " " << fsize << "\n"; | + | + xftfont = getMatchingXftFont(d, fl_screen, font.c_str()); | + | + if (!xftfont) { | + lyxerr <<"Error: null font\n" << i <<"\n"; | + return *this; | + } | + | + XftDrawString8(cache[i].draw, &(cache[i].color), | + xftfont, x, y, (XftChar8 *) s, sl); | +#else | + return XDrawString(d, w, gc, x, y, s, sl); | +#endif | } | | | diff -Pur lyx-1.1.6fix2/src/Painter.h lyx-1.1.6fix2-antialias/src/Painter.h | --- lyx-1.1.6fix2/src/Painter.h Wed Nov 15 10:02:44 2000 | +++ lyx-1.1.6fix2-antialias/src/Painter.h Sun Jul 15 08:53:01 2001 | @@ -100,6 +100,9 @@ | private: | /// Check the font, and if set, draw an underline | void underline(LyXFont const & f, int x, int y, int width); | + | + PainterBase & Painter::XDrawString(Display *d, Drawable w, GC gc, int x, | + int y, char * const s, int sl, LyXFont const &f); | | /// | Display * display; | diff -Pur lyx-1.1.6fix2/src/config.h.in lyx-1.1.6fix2-antialias/src/config.h.in | --- lyx-1.1.6fix2/src/config.h.in Sun Jul 15 09:04:17 2001 | +++ lyx-1.1.6fix2-antialias/src/config.h.in Sun Jul 15 09:04:15 2001 | @@ -135,6 +135,10 @@ | #undef HAVE_STPCPY | | /* define this to the location of xpm.h to be used with #include, | + e.g. <xft.h> */ | +#undef XFT_H_LOCATION | + | +/* define this to the location of xpm.h to be used with #include, | e.g. <xpm.h> */ | #undef XPM_H_LOCATION | | diff -Pur lyx-1.1.6fix2/src/font.C lyx-1.1.6fix2-antialias/src/font.C | --- lyx-1.1.6fix2/src/font.C Mon Oct 30 13:53:28 2000 | +++ lyx-1.1.6fix2-antialias/src/font.C Sun Jul 15 08:52:14 2001 | @@ -18,8 +18,12 @@ | | #include "font.h" | #include "FontLoader.h" | +#include "FontInfo.h" | #include "lyxrc.h" | #include "encoding.h" | +#ifdef XFT_H_LOCATION | +#include "xftfont.h" | +#endif | | // namespace { | static inline | @@ -131,7 +135,7 @@ | } | | if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) { | - return ::XTextWidth(getXFontstruct(f), s, n); | + return XTextWidth((f), s, n); | } else { | // emulate smallcaps since X doesn't support this | unsigned int result = 0; | @@ -143,9 +147,9 @@ | // when islower is a macro, the cast is needed (JMarc) | if (islower(static_cast<unsigned char>(c))) { | c = toupper(c); | - result += ::XTextWidth(getXFontstruct(smallfont), &c, |1); | + result += XTextWidth((smallfont), &c, 1); | } else { | - result += ::XTextWidth(getXFontstruct(f), &c, 1); | + result += XTextWidth((f), &c, 1); | } | } | return result; | @@ -189,9 +193,26 @@ | } | } | | -int lyxfont::XTextWidth(LyXFont const & f, char const * str, int count) | -{ | - return ::XTextWidth(getXFontstruct(f), str, count); | +int lyxfont::XTextWidth(LyXFont const & f, char const * str, int count) { | + | + int fsize = int( (lyxrc.font_sizes[f.size()] * lyxrc.dpi * | + (lyxrc.zoom/100.0) ) / 72.27 + 0.5 ); | + | + fontloader.load(f.family(), f.series(), f.realShape(), f.size()); | + string font = fontloader.fontinfo[f.family()][f.series()][f.realShape()]-> | + getFontname(fsize); | + | +#ifdef XFT_H_LOCATION | + XftFont * xftfont = getMatchingXftFont(fl_display, fl_screen, font.c_str()); | + | + XGlyphInfo extents; | + | + XftTextExtents8(fl_display, xftfont, (XftChar8*) str, count, &extents); | + | + return extents.xOff; | +#else | + return ::XTextWidth(getXFontstruct(f), str, count); | +#endif | } | diff -Pur lyx-1.1.6fix2/src/xftfont.C lyx-1.1.6fix2-antialias/src/xftfont.C | --- lyx-1.1.6fix2/src/xftfont.C Wed Dec 31 16:00:00 1969 | +++ lyx-1.1.6fix2-antialias/src/xftfont.C Sun Jul 15 08:52:26 2001 | @@ -0,0 +1,49 @@ | +#include <config.h> | +#include <xftfont.h> | + | +#ifdef XFT_H_LOCATION | + | +typedef struct { | + char fontname[256]; string fontname; | + XftFont *xftfont; | +} fontCacheEntry; | + | +#define MAXCACHE 50 | + | +XftFont * getMatchingXftFont (Display *d, int s, const char | +*fontname) { use string. | + | + static fontCacheEntry cache[MAXCACHE+1]; | + static int to_replace = 0; | + static int initialized = 0; | + int i; | + int found = 0; bool found = false; | + | + if (! initialized ) { | + for (i = 0; i < MAXCACHE; i++) cache[i].xftfont = NULL; | + initialized = 1; | + } | + | + i = 0; | + while (i < MAXCACHE && !found && cache[i].xftfont) { | + if ( 0 == strcmp(cache[i].fontname, fontname) ) found =1; if (cache[i].fontname == fontname) found = true; | + i++; ++i; | + } Here a std::map could be used. Would give O(log n) lookup. | + | + if (found) i--; | + | + if (! found || ! cache[i].xftfont ) { | + if (! cache[i].xftfont && (i < MAXCACHE) ) | + to_replace = i; | + else | + XftFontClose(d, cache[i].xftfont); | + i = to_replace %MAXCACHE; to_replace ++; | + | + cache[i].xftfont = XftFontOpenXlfd(d, s, fontname); | + strcpy(cache[i].fontname, fontname); | + } | + | +/* printf("Requested %s\n returning no. %d (%x), hit = %d\n", fontname, | + i, cache[i].xftfont, found); */ | + return cache[i].xftfont; | +} | +#endif | diff -Pur lyx-1.1.6fix2/src/xftfont.h lyx-1.1.6fix2-antialias/src/xftfont.h | --- lyx-1.1.6fix2/src/xftfont.h Wed Dec 31 16:00:00 1969 | +++ lyx-1.1.6fix2-antialias/src/xftfont.h Sun Jul 15 08:52:26 2001 | @@ -0,0 +1,8 @@ | +#ifdef XFT_H_LOCATION | +#include "font.h" | + | +#include <config.h> | +#include XFT_H_LOCATION | + | +XftFont * getMatchingXftFont (Display *d, int s, const char *fontname) ; | +#endif but I like it... it is simple... it just need to get C++ified and LyXified. -- Lgb