From dafebc5bb70303f0b5baf0b087cf4d9a64b5c7f0 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 12 Sep 2011 11:27:51 +0200 Subject: Synchronised line endinge with release branch --- libXft/configure.ac | 308 +++--- libXft/src/xftcore.c | 2766 +++++++++++++++++++++++++------------------------- libXft/src/xftdpy.c | 1104 ++++++++++---------- libXft/src/xftdraw.c | 1988 ++++++++++++++++++------------------ 4 files changed, 3083 insertions(+), 3083 deletions(-) (limited to 'libXft') diff --git a/libXft/configure.ac b/libXft/configure.ac index b031a0116..9b9f6a74d 100644 --- a/libXft/configure.ac +++ b/libXft/configure.ac @@ -1,154 +1,154 @@ -# -# Copyright © 2003 Keith Packard, Noah Levitt -# -# Permission to use, copy, modify, distribute, and sell this software and its -# documentation for any purpose is hereby granted without fee, provided that -# the above copyright notice appear in all copies and that both that -# copyright notice and this permission notice appear in supporting -# documentation, and that the name of Keith Packard not be used in -# advertising or publicity pertaining to distribution of the software without -# specific, written prior permission. Keith Packard makes no -# representations about the suitability of this software for any purpose. It -# is provided "as is" without express or implied warranty. -# -# KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO -# EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR -# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -# PERFORMANCE OF THIS SOFTWARE. -# - -# Initialize Autoconf -AC_PREREQ([2.60]) -# -# This is the package version number, not the shared library -# version. This version number will be substituted into Xft.h -# Please bump the minor library number at each release as well. -# -AC_INIT([libXft], [2.2.0], - [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [libXft]) -AC_CONFIG_SRCDIR([Makefile.am]) -AC_CONFIG_HEADERS([config.h]) - -# Initialize Automake -AM_INIT_AUTOMAKE([foreign dist-bzip2]) -AM_MAINTAINER_MODE - -# Initialize libtool -AC_PROG_LIBTOOL - -# Require X.Org macros 1.8 or later for MAN_SUBSTS set by XORG_MANPAGE_SECTIONS -m4_ifndef([XORG_MACROS_VERSION], - [m4_fatal([must install xorg-macros 1.8 or later before running autoconf/autogen])]) -XORG_MACROS_VERSION(1.8) -XORG_DEFAULT_OPTIONS - -# Set library version for Xft.h from package version set in AC_INIT -# copied from PACKAGE_VERSION_* settings in XORG_VERSION -AC_CONFIG_HEADERS([include/X11/Xft/Xft.h]) -AC_DEFINE_UNQUOTED([XFT_MAJOR], - [`echo $PACKAGE_VERSION | cut -d . -f 1`], - [Major version of Xft]) -AC_DEFINE_UNQUOTED([XFT_MINOR], - [`echo $PACKAGE_VERSION | cut -d . -f 2 | cut -d - -f 1`], - [Minor version of Xft]) -AC_DEFINE_UNQUOTED([XFT_REVISION], - [`echo $PACKAGE_VERSION | cut -d . -f 3 | cut -d - -f 1`], - [Micro revision of Xft]) - -XFT_LT_VERSION=`echo $PACKAGE_VERSION | tr '.' ':'` -AC_SUBST([XFT_LT_VERSION]) - -# -# Check for Xrender -# -PKG_CHECK_MODULES(XRENDER, xrender >= 0.8.2, [xrender_found_with_pkgconfig=yes], - [xrender_found_with_pkgconfig=no]) -case "$xrender_found_with_pkgconfig" in -no) - PKG_CHECK_MODULES(XRENDER, xrender >= 0, [old_xrender_found_with_pkgconfig=yes], - [old_xrender_found_with_pkgconfig=no]) - case "$old_xrender_found_with_pkgconfig" in - yes) - XRENDER_LIBS="$XRENDER_LIBS -lXext -lX11" - ;; - *) - # checks for X - AC_PATH_X - - XRENDER_CFLAGS="-I$x_includes" - XRENDER_LIBS="-L$x_libraries -lXrender -lXext -lX11" - - saved_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $XRENDER_CFLAGS" - AC_CHECK_HEADERS([X11/extensions/Xrender.h], [], [AC_MSG_ERROR([Xrender.h not found.])]) - CPPFLAGS="$saved_CPPFLAGS" - - saved_LIBS="$LIBS" - LIBS="$LIBS $XRENDER_LIBS" - AC_CHECK_FUNCS([XRenderFindStandardFormat], [], [AC_MSG_ERROR([libXrender not found or too old.])]) - LIBS="$saved_LIBS" - ;; - esac - ;; -esac - -# Check freetype configuration -AC_ARG_WITH(freetype-config, [ --with-freetype-config=PROG Use FreeType configuration program PROG], freetype_config=$withval, freetype_config=auto) - -if test "$freetype_config" = "auto"; then - PKG_CHECK_MODULES(FREETYPE, freetype2, - freetype_config=no, freetype_config=yes) -fi - -if test "$freetype_config" = "yes"; then - AC_PATH_PROG(ft_config,freetype-config,no) - if test "$ft_config" = "no"; then - AC_MSG_ERROR([You must have freetype installed; see http://www.freetype.org/]) - fi -else - ft_config="$freetype_config" -fi - -if test "$freetype_config" != "no"; then - FREETYPE_CFLAGS="`$ft_config --cflags`" - FREETYPE_LIBS="`$ft_config --libs`" -fi - -# Check fontconfig configuration -PKG_CHECK_MODULES(FONTCONFIG, fontconfig >= 2.2) - -AC_SUBST(XRENDER_CFLAGS) -AC_SUBST(XRENDER_LIBS) -AC_SUBST(FREETYPE_CFLAGS) -AC_SUBST(FREETYPE_LIBS) -AC_SUBST(FONTCONFIG_CFLAGS) -AC_SUBST(FONTCONFIG_LIBS) - -fontconfig_save_libs="$LIBS" -fontconfig_save_cflags="$CFLAGS" -LIBS="$LIBS $FREETYPE_LIBS" -CFLAGS="$CFLAGS $FREETYPE_CFLAGS" -AC_CHECK_FUNCS(FT_Get_Next_Char FT_Get_BDF_Property FT_Get_PS_Font_Info FT_Has_PS_Glyph_Names FT_GlyphSlot_Embolden) -AC_CHECK_MEMBER(FT_Bitmap_Size.y_ppem, - HAVE_FT_BITMAP_SIZE_Y_PPEM=1, - HAVE_FT_BITMAP_SIZE_Y_PPEM=0, -[#include -#include FT_FREETYPE_H]) -AC_DEFINE_UNQUOTED(HAVE_FT_BITMAP_SIZE_Y_PPEM,$HAVE_FT_BITMAP_SIZE_Y_PPEM, - [FT_Bitmap_Size structure includes y_ppem field]) - -LIBS="$fontconfig_save_libs" -CFLAGS="$fontconfig_save_cflags" - -if test "$VERSION" = "" ; then - VERSION=$PACKAGE_VERSION; -fi - -AC_CONFIG_FILES([Makefile - xft.pc - src/Makefile - man/Makefile]) -AC_OUTPUT +# +# Copyright © 2003 Keith Packard, Noah Levitt +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of Keith Packard not be used in +# advertising or publicity pertaining to distribution of the software without +# specific, written prior permission. Keith Packard makes no +# representations about the suitability of this software for any purpose. It +# is provided "as is" without express or implied warranty. +# +# KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +# + +# Initialize Autoconf +AC_PREREQ([2.60]) +# +# This is the package version number, not the shared library +# version. This version number will be substituted into Xft.h +# Please bump the minor library number at each release as well. +# +AC_INIT([libXft], [2.2.0], + [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [libXft]) +AC_CONFIG_SRCDIR([Makefile.am]) +AC_CONFIG_HEADERS([config.h]) + +# Initialize Automake +AM_INIT_AUTOMAKE([foreign dist-bzip2]) +AM_MAINTAINER_MODE + +# Initialize libtool +AC_PROG_LIBTOOL + +# Require X.Org macros 1.8 or later for MAN_SUBSTS set by XORG_MANPAGE_SECTIONS +m4_ifndef([XORG_MACROS_VERSION], + [m4_fatal([must install xorg-macros 1.8 or later before running autoconf/autogen])]) +XORG_MACROS_VERSION(1.8) +XORG_DEFAULT_OPTIONS + +# Set library version for Xft.h from package version set in AC_INIT +# copied from PACKAGE_VERSION_* settings in XORG_VERSION +AC_CONFIG_HEADERS([include/X11/Xft/Xft.h]) +AC_DEFINE_UNQUOTED([XFT_MAJOR], + [`echo $PACKAGE_VERSION | cut -d . -f 1`], + [Major version of Xft]) +AC_DEFINE_UNQUOTED([XFT_MINOR], + [`echo $PACKAGE_VERSION | cut -d . -f 2 | cut -d - -f 1`], + [Minor version of Xft]) +AC_DEFINE_UNQUOTED([XFT_REVISION], + [`echo $PACKAGE_VERSION | cut -d . -f 3 | cut -d - -f 1`], + [Micro revision of Xft]) + +XFT_LT_VERSION=`echo $PACKAGE_VERSION | tr '.' ':'` +AC_SUBST([XFT_LT_VERSION]) + +# +# Check for Xrender +# +PKG_CHECK_MODULES(XRENDER, xrender >= 0.8.2, [xrender_found_with_pkgconfig=yes], + [xrender_found_with_pkgconfig=no]) +case "$xrender_found_with_pkgconfig" in +no) + PKG_CHECK_MODULES(XRENDER, xrender >= 0, [old_xrender_found_with_pkgconfig=yes], + [old_xrender_found_with_pkgconfig=no]) + case "$old_xrender_found_with_pkgconfig" in + yes) + XRENDER_LIBS="$XRENDER_LIBS -lXext -lX11" + ;; + *) + # checks for X + AC_PATH_X + + XRENDER_CFLAGS="-I$x_includes" + XRENDER_LIBS="-L$x_libraries -lXrender -lXext -lX11" + + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $XRENDER_CFLAGS" + AC_CHECK_HEADERS([X11/extensions/Xrender.h], [], [AC_MSG_ERROR([Xrender.h not found.])]) + CPPFLAGS="$saved_CPPFLAGS" + + saved_LIBS="$LIBS" + LIBS="$LIBS $XRENDER_LIBS" + AC_CHECK_FUNCS([XRenderFindStandardFormat], [], [AC_MSG_ERROR([libXrender not found or too old.])]) + LIBS="$saved_LIBS" + ;; + esac + ;; +esac + +# Check freetype configuration +AC_ARG_WITH(freetype-config, [ --with-freetype-config=PROG Use FreeType configuration program PROG], freetype_config=$withval, freetype_config=auto) + +if test "$freetype_config" = "auto"; then + PKG_CHECK_MODULES(FREETYPE, freetype2, + freetype_config=no, freetype_config=yes) +fi + +if test "$freetype_config" = "yes"; then + AC_PATH_PROG(ft_config,freetype-config,no) + if test "$ft_config" = "no"; then + AC_MSG_ERROR([You must have freetype installed; see http://www.freetype.org/]) + fi +else + ft_config="$freetype_config" +fi + +if test "$freetype_config" != "no"; then + FREETYPE_CFLAGS="`$ft_config --cflags`" + FREETYPE_LIBS="`$ft_config --libs`" +fi + +# Check fontconfig configuration +PKG_CHECK_MODULES(FONTCONFIG, fontconfig >= 2.2) + +AC_SUBST(XRENDER_CFLAGS) +AC_SUBST(XRENDER_LIBS) +AC_SUBST(FREETYPE_CFLAGS) +AC_SUBST(FREETYPE_LIBS) +AC_SUBST(FONTCONFIG_CFLAGS) +AC_SUBST(FONTCONFIG_LIBS) + +fontconfig_save_libs="$LIBS" +fontconfig_save_cflags="$CFLAGS" +LIBS="$LIBS $FREETYPE_LIBS" +CFLAGS="$CFLAGS $FREETYPE_CFLAGS" +AC_CHECK_FUNCS(FT_Get_Next_Char FT_Get_BDF_Property FT_Get_PS_Font_Info FT_Has_PS_Glyph_Names FT_GlyphSlot_Embolden) +AC_CHECK_MEMBER(FT_Bitmap_Size.y_ppem, + HAVE_FT_BITMAP_SIZE_Y_PPEM=1, + HAVE_FT_BITMAP_SIZE_Y_PPEM=0, +[#include +#include FT_FREETYPE_H]) +AC_DEFINE_UNQUOTED(HAVE_FT_BITMAP_SIZE_Y_PPEM,$HAVE_FT_BITMAP_SIZE_Y_PPEM, + [FT_Bitmap_Size structure includes y_ppem field]) + +LIBS="$fontconfig_save_libs" +CFLAGS="$fontconfig_save_cflags" + +if test "$VERSION" = "" ; then + VERSION=$PACKAGE_VERSION; +fi + +AC_CONFIG_FILES([Makefile + xft.pc + src/Makefile + man/Makefile]) +AC_OUTPUT diff --git a/libXft/src/xftcore.c b/libXft/src/xftcore.c index 04fa47640..a0103cf26 100644 --- a/libXft/src/xftcore.c +++ b/libXft/src/xftcore.c @@ -1,1383 +1,1383 @@ -/* - * Copyright © 2000 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#include "xftint.h" - -_X_HIDDEN void -XftRectCore (XftDraw *draw, - _Xconst XftColor *color, - int x, - int y, - unsigned int width, - unsigned int height) -{ - if (color->color.alpha >= 0x8000) - { - XSetForeground (draw->dpy, draw->core.gc, color->pixel); - XFillRectangle (draw->dpy, draw->drawable, draw->core.gc, - x, y, width, height); - } -} - -/* - * Use the core protocol to draw the glyphs - */ - -static void -_XftSharpGlyphMono (XftDraw *draw, - XftGlyph *glyph, - int x, - int y) -{ - unsigned char *srcLine = glyph->bitmap, *src; - unsigned char bits, bitsMask; - int width = glyph->metrics.width; - int stride = ((width + 31) & ~31) >> 3; - int height = glyph->metrics.height; - int w; - int xspan, lenspan; - - x -= glyph->metrics.x; - y -= glyph->metrics.y; - while (height--) - { - src = srcLine; - srcLine += stride; - w = width; - - bitsMask = 0x80; /* FreeType is always MSB first */ - bits = *src++; - - xspan = x; - while (w) - { - if (bits & bitsMask) - { - lenspan = 0; - do - { - lenspan++; - if (lenspan == w) - break; - bitsMask = bitsMask >> 1; - if (!bitsMask) - { - bits = *src++; - bitsMask = 0x80; - } - } while (bits & bitsMask); - XFillRectangle (draw->dpy, draw->drawable, - draw->core.gc, xspan, y, lenspan, 1); - xspan += lenspan; - w -= lenspan; - } - else - { - do - { - w--; - xspan++; - if (!w) - break; - bitsMask = bitsMask >> 1; - if (!bitsMask) - { - bits = *src++; - bitsMask = 0x80; - } - } while (!(bits & bitsMask)); - } - } - y++; - } -} - -/* - * Draw solid color text from an anti-aliased bitmap. This is a - * fallback for cases where a particular drawable has no AA code - */ -static void -_XftSharpGlyphGray (XftDraw *draw, - XftGlyph *glyph, - int x, - int y) -{ - unsigned char *srcLine = glyph->bitmap, *src, bits; - int width = glyph->metrics.width; - int stride = ((width + 3) & ~3); - int height = glyph->metrics.height; - int w; - int xspan, lenspan; - - x -= glyph->metrics.x; - y -= glyph->metrics.y; - while (height--) - { - src = srcLine; - srcLine += stride; - w = width; - - bits = *src++; - xspan = x; - while (w) - { - if (bits >= 0x80) - { - lenspan = 0; - do - { - lenspan++; - if (lenspan == w) - break; - bits = *src++; - } while (bits >= 0x80); - XFillRectangle (draw->dpy, draw->drawable, - draw->core.gc, xspan, y, lenspan, 1); - xspan += lenspan; - w -= lenspan; - } - else - { - do - { - w--; - xspan++; - if (!w) - break; - bits = *src++; - } while (bits < 0x80); - } - } - y++; - } -} - -static void -_XftSharpGlyphRgba (XftDraw *draw, - XftGlyph *glyph, - int x, - int y) -{ - CARD32 *srcLine = glyph->bitmap, *src, bits; - int width = glyph->metrics.width; - int stride = ((width + 3) & ~3); - int height = glyph->metrics.height; - int w; - int xspan, lenspan; - - x -= glyph->metrics.x; - y -= glyph->metrics.y; - while (height--) - { - src = srcLine; - srcLine += stride; - w = width; - - bits = *src++; - xspan = x; - while (w) - { - if (bits >= 0x80000000) - { - lenspan = 0; - do - { - lenspan++; - if (lenspan == w) - break; - bits = *src++; - } while (bits >= 0x80000000); - XFillRectangle (draw->dpy, draw->drawable, - draw->core.gc, xspan, y, lenspan, 1); - xspan += lenspan; - w -= lenspan; - } - else - { - do - { - w--; - xspan++; - if (!w) - break; - bits = *src++; - } while (bits < 0x80000000); - } - } - y++; - } -} - -typedef void (*XftSharpGlyph) (XftDraw *draw, - XftGlyph *glyph, - int x, - int y); - -static XftSharpGlyph -_XftSharpGlyphFind (XftDraw *draw, XftFont *public) -{ - XftFontInt *font = (XftFontInt *) public; - - if (!font->info.antialias) - return _XftSharpGlyphMono; - else switch (font->info.rgba) { - case FC_RGBA_RGB: - case FC_RGBA_BGR: - case FC_RGBA_VRGB: - case FC_RGBA_VBGR: - return _XftSharpGlyphRgba; - default: - return _XftSharpGlyphGray; - } -} - -/* - * Draw glyphs to a target that supports anti-aliasing - */ - -/* - * Primitives for converting between RGB values and TrueColor pixels - */ - -static void -_XftExamineBitfield (unsigned long mask, int *shift, int *len) -{ - int s, l; - - s = 0; - while ((mask & 1) == 0) - { - mask >>= 1; - s++; - } - l = 0; - while ((mask & 1) == 1) - { - mask >>= 1; - l++; - } - *shift = s; - *len = l; -} - -static CARD32 -_XftGetField (unsigned long l_pixel, int shift, int len) -{ - CARD32 pixel = (CARD32) l_pixel; - - pixel = pixel & (((1 << (len)) - 1) << shift); - pixel = pixel << (32 - (shift + len)) >> 24; - while (len < 8) - { - pixel |= (pixel >> len); - len <<= 1; - } - return pixel; -} - -static unsigned long -_XftPutField (CARD32 pixel, int shift, int len) -{ - unsigned long l_pixel = (unsigned long) pixel; - - shift = shift - (8 - len); - if (len <= 8) - l_pixel &= (((1 << len) - 1) << (8 - len)); - if (shift < 0) - l_pixel >>= -shift; - else - l_pixel <<= shift; - return l_pixel; -} - -/* - * This is used when doing XftCharFontSpec/XftGlyphFontSpec where - * some of the fonts are bitmaps and some are anti-aliased to handle - * the bitmap portions - */ -static void -_XftSmoothGlyphMono (XImage *image, - _Xconst XftGlyph *xftg, - int x, - int y, - _Xconst XftColor *color) -{ - unsigned char *srcLine = xftg->bitmap, *src; - unsigned char bits, bitsMask; - int width = xftg->metrics.width; - int stride = ((width + 31) & ~31) >> 3; - int height = xftg->metrics.height; - int w; - int xspan; - int r_shift, r_len; - int g_shift, g_len; - int b_shift, b_len; - unsigned long pixel; - - _XftExamineBitfield (image->red_mask, &r_shift, &r_len); - _XftExamineBitfield (image->green_mask, &g_shift, &g_len); - _XftExamineBitfield (image->blue_mask, &b_shift, &b_len); - pixel = (_XftPutField (color->color.red >> 8, r_shift, r_len) | - _XftPutField (color->color.green >> 8, g_shift, g_len) | - _XftPutField (color->color.blue >> 8, b_shift, b_len)); - x -= xftg->metrics.x; - y -= xftg->metrics.y; - while (height--) - { - src = srcLine; - srcLine += stride; - w = width; - - bitsMask = 0x80; /* FreeType is always MSB first */ - bits = *src++; - - xspan = x; - while (w--) - { - if (bits & bitsMask) - XPutPixel (image, xspan, y, pixel); - bitsMask = bitsMask >> 1; - if (!bitsMask) - { - bits = *src++; - bitsMask = 0x80; - } - xspan++; - } - y++; - } -} - -/* - * As simple anti-aliasing is likely to be common, there are three - * optimized versions for the usual true color pixel formats (888, 565, 555). - * Other formats are handled by the general case - */ - -#define cvt8888to0565(s) ((((s) >> 3) & 0x001f) | \ - (((s) >> 5) & 0x07e0) | \ - (((s) >> 8) & 0xf800)) - -#define cvt0565to8888(s) (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \ - ((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \ - ((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000))) - -#define cvt8888to0555(s) ((((s) >> 3) & 0x001f) | \ - (((s) >> 6) & 0x03e0) | \ - (((s) >> 7) & 0x7c00)) - -#define cvt0555to8888(s) (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \ - ((((s) << 6) & 0xf800) | (((s) >> 0) & 0x300)) | \ - ((((s) << 9) & 0xf80000) | (((s) << 4) & 0x70000))) - - -#define XftIntMult(a,b,t) ( (t) = (a) * (b) + 0x80, ( ( ( (t)>>8 ) + (t) )>>8 ) ) -#define XftIntDiv(a,b) (((CARD16) (a) * 255) / (b)) - -#define XftGet8(v,i) ((CARD16) (CARD8) ((v) >> i)) - -/* - * There are two ways of handling alpha -- either as a single unified value or - * a separate value for each component, hence each macro must have two - * versions. The unified alpha version has a 'U' at the end of the name, - * the component version has a 'C'. Similarly, functions which deal with - * this difference will have two versions using the same convention. - */ - -#define XftOverU(x,y,i,a,t) ((t) = XftIntMult(XftGet8(y,i),(a),(t)) + XftGet8(x,i),\ - (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) - -#define XftOverC(x,y,i,a,t) ((t) = XftIntMult(XftGet8(y,i),XftGet8(a,i),(t)) + XftGet8(x,i),\ - (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) - -#define XftInU(x,i,a,t) ((CARD32) XftIntMult(XftGet8(x,i),(a),(t)) << (i)) - -#define XftInC(x,i,a,t) ((CARD32) XftIntMult(XftGet8(x,i),XftGet8(a,i),(t)) << (i)) - -#define XftGen(x,y,i,ax,ay,t,u,v) ((t) = (XftIntMult(XftGet8(y,i),ay,(u)) + \ - XftIntMult(XftGet8(x,i),ax,(v))),\ - (CARD32) ((CARD8) ((t) | \ - (0 - ((t) >> 8)))) << (i)) - -#define XftAdd(x,y,i,t) ((t) = XftGet8(x,i) + XftGet8(y,i), \ - (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) - - -static CARD32 -fbOver24 (CARD32 x, CARD32 y) -{ - CARD16 a = ~x >> 24; - CARD16 t; - CARD32 m,n,o; - - m = XftOverU(x,y,0,a,t); - n = XftOverU(x,y,8,a,t); - o = XftOverU(x,y,16,a,t); - return m|n|o; -} - -static CARD32 -fbIn (CARD32 x, CARD8 y) -{ - CARD16 a = y; - CARD16 t; - CARD32 m,n,o,p; - - m = XftInU(x,0,a,t); - n = XftInU(x,8,a,t); - o = XftInU(x,16,a,t); - p = XftInU(x,24,a,t); - return m|n|o|p; -} - -static void -_XftSmoothGlyphGray8888 (XImage *image, - _Xconst XftGlyph *xftg, - int x, - int y, - _Xconst XftColor *color) -{ - CARD32 src, srca; - CARD32 r, g, b; - CARD32 *dstLine, *dst, d; - CARD8 *maskLine, *mask, m; - int dstStride, maskStride; - int width, height; - int w; - - srca = color->color.alpha >> 8; - - /* This handles only RGB and BGR */ - g = (color->color.green & 0xff00); - if (image->red_mask == 0xff0000) - { - r = (color->color.red & 0xff00) << 8; - b = color->color.blue >> 8; - } - else - { - r = color->color.red >> 8; - b = (color->color.blue & 0xff00) << 8; - } - src = (srca << 24) | r | g | b; - - width = xftg->metrics.width; - height = xftg->metrics.height; - - x -= xftg->metrics.x; - y -= xftg->metrics.y; - - dstLine = (CARD32 *) (image->data + image->bytes_per_line * y + (x << 2)); - dstStride = image->bytes_per_line >> 2; - maskLine = (unsigned char *) xftg->bitmap; - maskStride = (width + 3) & ~3; - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - mask = maskLine; - maskLine += maskStride; - w = width; - - while (w--) - { - m = *mask++; - if (m == 0xff) - { - if (srca == 0xff) - *dst = src; - else - *dst = fbOver24 (src, *dst); - } - else if (m) - { - d = fbIn (src, m); - *dst = fbOver24 (d, *dst); - } - dst++; - } - } -} - -static void -_XftSmoothGlyphGray565 (XImage *image, - _Xconst XftGlyph *xftg, - int x, - int y, - _Xconst XftColor *color) -{ - CARD32 src, srca; - CARD32 r, g, b; - CARD32 d; - CARD16 *dstLine, *dst; - CARD8 *maskLine, *mask, m; - int dstStride, maskStride; - int width, height; - int w; - - srca = color->color.alpha >> 8; - - /* This handles only RGB and BGR */ - g = (color->color.green & 0xff00); - if (image->red_mask == 0xf800) - { - r = (color->color.red & 0xff00) << 8; - b = color->color.blue >> 8; - } - else - { - r = color->color.red >> 8; - b = (color->color.blue & 0xff00) << 8; - } - src = (srca << 24) | r | g | b; - - width = xftg->metrics.width; - height = xftg->metrics.height; - - x -= xftg->metrics.x; - y -= xftg->metrics.y; - - dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1)); - dstStride = image->bytes_per_line >> 1; - maskLine = (unsigned char *) xftg->bitmap; - maskStride = (width + 3) & ~3; - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - mask = maskLine; - maskLine += maskStride; - w = width; - - while (w--) - { - m = *mask++; - if (m == 0xff) - { - if (srca == 0xff) - d = src; - else - { - d = *dst; - d = fbOver24 (src, cvt0565to8888(d)); - } - *dst = cvt8888to0565(d); - } - else if (m) - { - d = *dst; - d = fbOver24 (fbIn(src,m), cvt0565to8888(d)); - *dst = cvt8888to0565(d); - } - dst++; - } - } -} - -static void -_XftSmoothGlyphGray555 (XImage *image, - _Xconst XftGlyph *xftg, - int x, - int y, - _Xconst XftColor *color) -{ - CARD32 src, srca; - CARD32 r, g, b; - CARD32 d; - CARD16 *dstLine, *dst; - CARD8 *maskLine, *mask, m; - int dstStride, maskStride; - int width, height; - int w; - - srca = color->color.alpha >> 8; - - /* This handles only RGB and BGR */ - g = (color->color.green & 0xff00); - if (image->red_mask == 0xf800) - { - r = (color->color.red & 0xff00) << 8; - b = color->color.blue >> 8; - } - else - { - r = color->color.red >> 8; - b = (color->color.blue & 0xff00) << 8; - } - src = (srca << 24) | r | g | b; - - width = xftg->metrics.width; - height = xftg->metrics.height; - - x -= xftg->metrics.x; - y -= xftg->metrics.y; - - dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1)); - dstStride = image->bytes_per_line >> 1; - maskLine = (unsigned char *) xftg->bitmap; - maskStride = (width + 3) & ~3; - - while (height--) - { - dst = dstLine; - dstLine += dstStride; - mask = maskLine; - maskLine += maskStride; - w = width; - - while (w--) - { - m = *mask++; - if (m == 0xff) - { - if (srca == 0xff) - d = src; - else - { - d = *dst; - d = fbOver24 (src, cvt0555to8888(d)); - } - *dst = cvt8888to0555(d); - } - else if (m) - { - d = *dst; - d = fbOver24 (fbIn(src,m), cvt0555to8888(d)); - *dst = cvt8888to0555(d); - } - dst++; - } - } -} - -static void -_XftSmoothGlyphGray (XImage *image, - _Xconst XftGlyph *xftg, - int x, - int y, - _Xconst XftColor *color) -{ - CARD32 src, srca; - int r_shift, r_len; - int g_shift, g_len; - int b_shift, b_len; - CARD8 *maskLine, *mask, m; - int maskStride; - CARD32 d; - unsigned long pixel; - int width, height; - int w, tx; - - srca = color->color.alpha >> 8; - src = (srca << 24 | - (color->color.red & 0xff00) << 8 | - (color->color.green & 0xff00) | - (color->color.blue) >> 8); - x -= xftg->metrics.x; - y -= xftg->metrics.y; - width = xftg->metrics.width; - height = xftg->metrics.height; - - maskLine = (unsigned char *) xftg->bitmap; - maskStride = (width + 3) & ~3; - - _XftExamineBitfield (image->red_mask, &r_shift, &r_len); - _XftExamineBitfield (image->green_mask, &g_shift, &g_len); - _XftExamineBitfield (image->blue_mask, &b_shift, &b_len); - while (height--) - { - mask = maskLine; - maskLine += maskStride; - w = width; - tx = x; - - while (w--) - { - m = *mask++; - if (m == 0xff) - { - if (srca == 0xff) - d = src; - else - { - pixel = XGetPixel (image, tx, y); - d = (_XftGetField (pixel, r_shift, r_len) << 16 | - _XftGetField (pixel, g_shift, g_len) << 8 | - _XftGetField (pixel, b_shift, b_len)); - d = fbOver24 (src, d); - } - pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) | - _XftPutField ((d >> 8) & 0xff, g_shift, g_len) | - _XftPutField ((d ) & 0xff, b_shift, b_len)); - XPutPixel (image, tx, y, pixel); - } - else if (m) - { - pixel = XGetPixel (image, tx, y); - d = (_XftGetField (pixel, r_shift, r_len) << 16 | - _XftGetField (pixel, g_shift, g_len) << 8 | - _XftGetField (pixel, b_shift, b_len)); - d = fbOver24 (fbIn(src,m), d); - pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) | - _XftPutField ((d >> 8) & 0xff, g_shift, g_len) | - _XftPutField ((d ) & 0xff, b_shift, b_len)); - XPutPixel (image, tx, y, pixel); - } - tx++; - } - y++; - } -} - -static void -_XftSmoothGlyphRgba (XImage *image, - _Xconst XftGlyph *xftg, - int x, - int y, - _Xconst XftColor *color) -{ - CARD32 src, srca; - int r_shift, r_len; - int g_shift, g_len; - int b_shift, b_len; - CARD32 *mask, ma; - CARD32 d; - unsigned long pixel; - int width, height; - int w, tx; - - srca = color->color.alpha >> 8; - src = (srca << 24 | - (color->color.red & 0xff00) << 8 | - (color->color.green & 0xff00) | - (color->color.blue) >> 8); - x -= xftg->metrics.x; - y -= xftg->metrics.y; - width = xftg->metrics.width; - height = xftg->metrics.height; - - mask = (CARD32 *) xftg->bitmap; - - _XftExamineBitfield (image->red_mask, &r_shift, &r_len); - _XftExamineBitfield (image->green_mask, &g_shift, &g_len); - _XftExamineBitfield (image->blue_mask, &b_shift, &b_len); - while (height--) - { - w = width; - tx = x; - - while (w--) - { - ma = *mask++; - if (ma == 0xffffffff) - { - if (srca == 0xff) - d = src; - else - { - pixel = XGetPixel (image, tx, y); - d = (_XftGetField (pixel, r_shift, r_len) << 16 | - _XftGetField (pixel, g_shift, g_len) << 8 | - _XftGetField (pixel, b_shift, b_len)); - d = fbOver24 (src, d); - } - pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) | - _XftPutField ((d >> 8) & 0xff, g_shift, g_len) | - _XftPutField ((d ) & 0xff, b_shift, b_len)); - XPutPixel (image, tx, y, pixel); - } - else if (ma) - { - CARD32 m,n,o; - pixel = XGetPixel (image, tx, y); - d = (_XftGetField (pixel, r_shift, r_len) << 16 | - _XftGetField (pixel, g_shift, g_len) << 8 | - _XftGetField (pixel, b_shift, b_len)); -#define XftInOverC(src,srca,msk,dst,i,result) { \ - CARD16 __a = XftGet8(msk,i); \ - CARD32 __t, __ta; \ - CARD32 __i; \ - __t = XftIntMult (XftGet8(src,i), __a,__i); \ - __ta = (CARD8) ~XftIntMult (srca, __a,__i); \ - __t = __t + XftIntMult(XftGet8(dst,i),__ta,__i); \ - __t = (CARD32) (CARD8) (__t | (-(__t >> 8))); \ - result = __t << (i); \ -} - XftInOverC(src,srca,ma,d,0,m); - XftInOverC(src,srca,ma,d,8,n); - XftInOverC(src,srca,ma,d,16,o); - d = m | n | o; - pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) | - _XftPutField ((d >> 8) & 0xff, g_shift, g_len) | - _XftPutField ((d ) & 0xff, b_shift, b_len)); - XPutPixel (image, tx, y, pixel); - } - tx++; - } - y++; - } -} - -static FcBool -_XftSmoothGlyphPossible (XftDraw *draw) -{ - if (!draw->visual) - return FcFalse; - if (draw->visual->class != TrueColor) - return FcFalse; - return FcTrue; -} - -typedef void (*XftSmoothGlyph) (XImage *image, - _Xconst XftGlyph *xftg, - int x, - int y, - _Xconst XftColor *color); - -static XftSmoothGlyph -_XftSmoothGlyphFind (XftDraw *draw, XftFont *public) -{ - XftFontInt *font = (XftFontInt *) public; - - if (!font->info.antialias) - return _XftSmoothGlyphMono; - else switch (font->info.rgba) { - case FC_RGBA_RGB: - case FC_RGBA_BGR: - case FC_RGBA_VRGB: - case FC_RGBA_VBGR: - return _XftSmoothGlyphRgba; - default: - switch (XftDrawBitsPerPixel (draw)) { - case 32: - if ((draw->visual->red_mask == 0xff0000 && - draw->visual->green_mask == 0x00ff00 && - draw->visual->blue_mask == 0x0000ff) || - (draw->visual->red_mask == 0x0000ff && - draw->visual->green_mask == 0x00ff00 && - draw->visual->blue_mask == 0xff0000)) - { - return _XftSmoothGlyphGray8888; - } - break; - case 16: - if ((draw->visual->red_mask == 0xf800 && - draw->visual->green_mask == 0x07e0 && - draw->visual->blue_mask == 0x001f) || - (draw->visual->red_mask == 0x001f && - draw->visual->green_mask == 0x07e0 && - draw->visual->blue_mask == 0xf800)) - { - return _XftSmoothGlyphGray565; - } - if ((draw->visual->red_mask == 0x7c00 && - draw->visual->green_mask == 0x03e0 && - draw->visual->blue_mask == 0x001f) || - (draw->visual->red_mask == 0x001f && - draw->visual->green_mask == 0x03e0 && - draw->visual->blue_mask == 0x7c00)) - { - return _XftSmoothGlyphGray555; - } - break; - default: - break; - } - return _XftSmoothGlyphGray; - } -} - -static XftGlyph * -_XftGlyphDefault (Display *dpy, XftFont *public) -{ - XftFontInt *font = (XftFontInt *) public; - FT_UInt missing[XFT_NMISSING]; - int nmissing; - FcBool glyphs_loaded = FcFalse; - - if (XftFontCheckGlyph (dpy, public, FcTrue, 0, missing, &nmissing)) - glyphs_loaded = FcTrue; - if (nmissing) - XftFontLoadGlyphs (dpy, public, glyphs_loaded, missing, nmissing); - return font->glyphs[0]; -} - -static int XftGetImageErrorHandler (Display *dpy, XErrorEvent *error_event) -{ - return 0; -} - -_X_HIDDEN void -XftGlyphCore (XftDraw *draw, - _Xconst XftColor *color, - XftFont *public, - int x, - int y, - _Xconst FT_UInt *glyphs, - int nglyphs) -{ - Display *dpy = draw->dpy; - XftFontInt *font = (XftFontInt *) public; - XftGlyph *xftg; - FT_UInt glyph; - _Xconst FT_UInt *g; - FT_UInt missing[XFT_NMISSING]; - FcBool glyphs_loaded; - int nmissing; - int n; - XErrorHandler prev_error; - - /* - * Load missing glyphs - */ - g = glyphs; - n = nglyphs; - nmissing = 0; - glyphs_loaded = FcFalse; - while (n--) - if (XftFontCheckGlyph (dpy, public, FcTrue, *g++, missing, &nmissing)) - glyphs_loaded = FcTrue; - if (nmissing) - XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing); - - g = glyphs; - n = nglyphs; - if ((font->info.antialias || color->color.alpha != 0xffff) && - _XftSmoothGlyphPossible (draw)) - { - XGlyphInfo gi; - XImage *image; - unsigned int depth; - int ox, oy; - XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public); - - XftGlyphExtents (dpy, public, glyphs, nglyphs, &gi); - if (!gi.width || !gi.height) - goto bail1; - ox = x - gi.x; - oy = y - gi.y; - /* - * Try to get bits directly from the drawable; if that fails, - * use a temporary pixmap. When it does fail, assume it - * will probably fail for a while and keep using temporary - * pixmaps for a while to avoid double round trips. - */ - if (draw->core.use_pixmap == 0) - { - prev_error = XSetErrorHandler (XftGetImageErrorHandler); - image = XGetImage (dpy, draw->drawable, - ox, oy, - gi.width, gi.height, AllPlanes, - ZPixmap); - XSetErrorHandler (prev_error); - if (!image) - draw->core.use_pixmap = XFT_ASSUME_PIXMAP; - } - else - { - draw->core.use_pixmap--; - image = NULL; - } - if (!image && (depth = XftDrawDepth (draw))) - { - Pixmap pix; - GC gc; - XGCValues gcv; - - pix = XCreatePixmap (dpy, draw->drawable, - gi.width, gi.height, depth); - gcv.graphics_exposures = False; - gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv); - XCopyArea (dpy, draw->drawable, pix, gc, ox, oy, - gi.width, gi.height, 0, 0); - XFreeGC (dpy, gc); - image = XGetImage (dpy, pix, 0, 0, gi.width, gi.height, AllPlanes, - ZPixmap); - XFreePixmap (dpy, pix); - } - if (!image) - goto bail1; - image->red_mask = draw->visual->red_mask; - image->green_mask = draw->visual->green_mask; - image->blue_mask = draw->visual->blue_mask; - if (image->byte_order != XftNativeByteOrder ()) - XftSwapImage (image); - while (n--) - { - glyph = *g++; - if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) - xftg = _XftGlyphDefault (dpy, public); - if (xftg) - { - (*smooth) (image, xftg, x - ox, y - oy, color); - x += xftg->metrics.xOff; - y += xftg->metrics.yOff; - } - } - if (image->byte_order != XftNativeByteOrder ()) - XftSwapImage (image); - XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, ox, oy, - gi.width, gi.height); - XDestroyImage (image); - } - else - { - XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public); - while (n--) - { - glyph = *g++; - if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) - xftg = _XftGlyphDefault (dpy, public); - if (xftg) - { - (*sharp) (draw, xftg, x, y); - x += xftg->metrics.xOff; - y += xftg->metrics.yOff; - } - } - } -bail1: - if (glyphs_loaded) - _XftFontManageMemory (dpy, public); -} - -#define NUM_LOCAL 1024 - -_X_HIDDEN void -XftGlyphSpecCore (XftDraw *draw, - _Xconst XftColor *color, - XftFont *public, - _Xconst XftGlyphSpec *glyphs, - int nglyphs) -{ - Display *dpy = draw->dpy; - XftFontInt *font = (XftFontInt *) public; - XftGlyph *xftg; - FT_UInt missing[XFT_NMISSING]; - FcBool glyphs_loaded; - int nmissing; - int i; - XErrorHandler prev_error; - int x1, y1, x2, y2; - - /* - * Load missing glyphs - */ - glyphs_loaded = FcFalse; - x1 = y1 = x2 = y2 = 0; - for (i = 0; i < nglyphs; i++) - { - XGlyphInfo gi; - int g_x1, g_x2, g_y1, g_y2; - - nmissing = 0; - if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing)) - glyphs_loaded = FcTrue; - if (nmissing) - XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing); - - XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi); - g_x1 = glyphs[i].x - gi.x; - g_y1 = glyphs[i].y - gi.y; - g_x2 = g_x1 + gi.width; - g_y2 = g_y1 + gi.height; - if (i) - { - if (g_x1 < x1) - x1 = g_x1; - if (g_y1 < y1) - y1 = g_y1; - if (g_x2 > x2) - x2 = g_x2; - if (g_y2 > y2) - y2 = g_y2; - } - else - { - x1 = g_x1; - y1 = g_y1; - x2 = g_x2; - y2 = g_y2; - } - } - - if (x1 == x2 || y1 == y2) - goto bail1; - - if ((font->info.antialias || color->color.alpha != 0xffff) && - _XftSmoothGlyphPossible (draw)) - { - XImage *image; - unsigned int depth; - int width = x2 - x1, height = y2 - y1; - XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public); - - /* - * Try to get bits directly from the drawable; if that fails, - * use a temporary pixmap. When it does fail, assume it - * will probably fail for a while and keep using temporary - * pixmaps for a while to avoid double round trips. - */ - if (draw->core.use_pixmap == 0) - { - prev_error = XSetErrorHandler (XftGetImageErrorHandler); - image = XGetImage (dpy, draw->drawable, - x1, y1, - width, height, AllPlanes, - ZPixmap); - XSetErrorHandler (prev_error); - if (!image) - draw->core.use_pixmap = XFT_ASSUME_PIXMAP; - } - else - { - draw->core.use_pixmap--; - image = NULL; - } - if (!image && (depth = XftDrawDepth (draw))) - { - Pixmap pix; - GC gc; - XGCValues gcv; - - pix = XCreatePixmap (dpy, draw->drawable, - width, height, depth); - gcv.graphics_exposures = False; - gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv); - XCopyArea (dpy, draw->drawable, pix, gc, x1, y1, - width, height, 0, 0); - XFreeGC (dpy, gc); - image = XGetImage (dpy, pix, 0, 0, width, height, AllPlanes, - ZPixmap); - XFreePixmap (dpy, pix); - } - if (!image) - goto bail1; - image->red_mask = draw->visual->red_mask; - image->green_mask = draw->visual->green_mask; - image->blue_mask = draw->visual->blue_mask; - if (image->byte_order != XftNativeByteOrder ()) - XftSwapImage (image); - for (i = 0; i < nglyphs; i++) - { - FT_UInt glyph = glyphs[i].glyph; - if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) - xftg = _XftGlyphDefault (dpy, public); - if (xftg) - { - (*smooth) (image, xftg, glyphs[i].x - x1, - glyphs[i].y - y1, color); - } - } - if (image->byte_order != XftNativeByteOrder ()) - XftSwapImage (image); - XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1, - width, height); - XDestroyImage (image); - } - else - { - XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public); - for (i = 0; i < nglyphs; i++) - { - FT_UInt glyph = glyphs[i].glyph; - if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) - xftg = _XftGlyphDefault (dpy, public); - if (xftg) - (*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y); - } - } -bail1: - if (glyphs_loaded) - _XftFontManageMemory (dpy, public); -} - -_X_HIDDEN void -XftGlyphFontSpecCore (XftDraw *draw, - _Xconst XftColor *color, - _Xconst XftGlyphFontSpec *glyphs, - int nglyphs) -{ - Display *dpy = draw->dpy; - XftGlyph *xftg; - FT_UInt missing[XFT_NMISSING]; - FcBool glyphs_loaded; - int nmissing; - int i; - XErrorHandler prev_error; - int x1, y1, x2, y2; - - /* - * Load missing glyphs - */ - glyphs_loaded = FcFalse; - x1 = y1 = x2 = y2 = 0; - for (i = 0; i < nglyphs; i++) - { - XftFont *public = glyphs[i].font; - XGlyphInfo gi; - int g_x1, g_x2, g_y1, g_y2; - - nmissing = 0; - if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing)) - glyphs_loaded = FcTrue; - if (nmissing) - XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing); - - XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi); - g_x1 = glyphs[i].x - gi.x; - g_y1 = glyphs[i].y - gi.y; - g_x2 = g_x1 + gi.width; - g_y2 = g_y1 + gi.height; - if (i) - { - if (g_x1 < x1) - { - if (g_x1 < 0) - { - /* do nothing if the given glyphs are out of range */ - short t = glyphs[i-1].font->max_advance_width - + glyphs[i-1].x; - if (t < 0 && glyphs[i-1].x > 0) - goto bail1; - } - x1 = g_x1; - } - if (g_y1 < y1) - y1 = g_y1; - if (g_x2 > x2) - x2 = g_x2; - if (g_y2 > y2) - y2 = g_y2; - } - else - { - x1 = g_x1; - y1 = g_y1; - x2 = g_x2; - y2 = g_y2; - } - } - - if (x1 == x2 || y1 == y2) - goto bail1; - - for (i = 0; i < nglyphs; i++) - if (((XftFontInt *) glyphs[i].font)->info.antialias) - break; - - if ((i != nglyphs || color->color.alpha != 0xffff) && - _XftSmoothGlyphPossible (draw)) - { - XImage *image; - unsigned int depth; - int width = x2 - x1, height = y2 - y1; - - /* - * Try to get bits directly from the drawable; if that fails, - * use a temporary pixmap. When it does fail, assume it - * will probably fail for a while and keep using temporary - * pixmaps for a while to avoid double round trips. - */ - if (draw->core.use_pixmap == 0) - { - prev_error = XSetErrorHandler (XftGetImageErrorHandler); - image = XGetImage (dpy, draw->drawable, - x1, y1, - width, height, AllPlanes, - ZPixmap); - XSetErrorHandler (prev_error); - if (!image) - draw->core.use_pixmap = XFT_ASSUME_PIXMAP; - } - else - { - draw->core.use_pixmap--; - image = NULL; - } - if (!image && (depth = XftDrawDepth (draw))) - { - Pixmap pix; - GC gc; - XGCValues gcv; - - pix = XCreatePixmap (dpy, draw->drawable, - width, height, depth); - gcv.graphics_exposures = False; - gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv); - XCopyArea (dpy, draw->drawable, pix, gc, x1, y1, - width, height, 0, 0); - XFreeGC (dpy, gc); - image = XGetImage (dpy, pix, 0, 0, width, height, AllPlanes, - ZPixmap); - XFreePixmap (dpy, pix); - } - if (!image) - goto bail1; - image->red_mask = draw->visual->red_mask; - image->green_mask = draw->visual->green_mask; - image->blue_mask = draw->visual->blue_mask; - if (image->byte_order != XftNativeByteOrder ()) - XftSwapImage (image); - for (i = 0; i < nglyphs; i++) - { - XftFont *public = glyphs[i].font; - XftFontInt *font = (XftFontInt *) public; - XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public); - FT_UInt glyph = glyphs[i].glyph; - - if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) - xftg = _XftGlyphDefault (dpy, public); - if (xftg) - { - (*smooth) (image, xftg, glyphs[i].x - x1, - glyphs[i].y - y1, color); - } - } - if (image->byte_order != XftNativeByteOrder ()) - XftSwapImage (image); - XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1, - width, height); - XDestroyImage (image); - } - else - { - for (i = 0; i < nglyphs; i++) - { - XftFont *public = glyphs[i].font; - XftFontInt *font = (XftFontInt *) public; - XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public); - FT_UInt glyph = glyphs[i].glyph; - - if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) - xftg = _XftGlyphDefault (dpy, public); - if (xftg) - (*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y); - } - } -bail1: - if (glyphs_loaded) - for (i = 0; i < nglyphs; i++) - _XftFontManageMemory (dpy, glyphs[i].font); -} +/* + * Copyright © 2000 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "xftint.h" + +_X_HIDDEN void +XftRectCore (XftDraw *draw, + _Xconst XftColor *color, + int x, + int y, + unsigned int width, + unsigned int height) +{ + if (color->color.alpha >= 0x8000) + { + XSetForeground (draw->dpy, draw->core.gc, color->pixel); + XFillRectangle (draw->dpy, draw->drawable, draw->core.gc, + x, y, width, height); + } +} + +/* + * Use the core protocol to draw the glyphs + */ + +static void +_XftSharpGlyphMono (XftDraw *draw, + XftGlyph *glyph, + int x, + int y) +{ + unsigned char *srcLine = glyph->bitmap, *src; + unsigned char bits, bitsMask; + int width = glyph->metrics.width; + int stride = ((width + 31) & ~31) >> 3; + int height = glyph->metrics.height; + int w; + int xspan, lenspan; + + x -= glyph->metrics.x; + y -= glyph->metrics.y; + while (height--) + { + src = srcLine; + srcLine += stride; + w = width; + + bitsMask = 0x80; /* FreeType is always MSB first */ + bits = *src++; + + xspan = x; + while (w) + { + if (bits & bitsMask) + { + lenspan = 0; + do + { + lenspan++; + if (lenspan == w) + break; + bitsMask = bitsMask >> 1; + if (!bitsMask) + { + bits = *src++; + bitsMask = 0x80; + } + } while (bits & bitsMask); + XFillRectangle (draw->dpy, draw->drawable, + draw->core.gc, xspan, y, lenspan, 1); + xspan += lenspan; + w -= lenspan; + } + else + { + do + { + w--; + xspan++; + if (!w) + break; + bitsMask = bitsMask >> 1; + if (!bitsMask) + { + bits = *src++; + bitsMask = 0x80; + } + } while (!(bits & bitsMask)); + } + } + y++; + } +} + +/* + * Draw solid color text from an anti-aliased bitmap. This is a + * fallback for cases where a particular drawable has no AA code + */ +static void +_XftSharpGlyphGray (XftDraw *draw, + XftGlyph *glyph, + int x, + int y) +{ + unsigned char *srcLine = glyph->bitmap, *src, bits; + int width = glyph->metrics.width; + int stride = ((width + 3) & ~3); + int height = glyph->metrics.height; + int w; + int xspan, lenspan; + + x -= glyph->metrics.x; + y -= glyph->metrics.y; + while (height--) + { + src = srcLine; + srcLine += stride; + w = width; + + bits = *src++; + xspan = x; + while (w) + { + if (bits >= 0x80) + { + lenspan = 0; + do + { + lenspan++; + if (lenspan == w) + break; + bits = *src++; + } while (bits >= 0x80); + XFillRectangle (draw->dpy, draw->drawable, + draw->core.gc, xspan, y, lenspan, 1); + xspan += lenspan; + w -= lenspan; + } + else + { + do + { + w--; + xspan++; + if (!w) + break; + bits = *src++; + } while (bits < 0x80); + } + } + y++; + } +} + +static void +_XftSharpGlyphRgba (XftDraw *draw, + XftGlyph *glyph, + int x, + int y) +{ + CARD32 *srcLine = glyph->bitmap, *src, bits; + int width = glyph->metrics.width; + int stride = ((width + 3) & ~3); + int height = glyph->metrics.height; + int w; + int xspan, lenspan; + + x -= glyph->metrics.x; + y -= glyph->metrics.y; + while (height--) + { + src = srcLine; + srcLine += stride; + w = width; + + bits = *src++; + xspan = x; + while (w) + { + if (bits >= 0x80000000) + { + lenspan = 0; + do + { + lenspan++; + if (lenspan == w) + break; + bits = *src++; + } while (bits >= 0x80000000); + XFillRectangle (draw->dpy, draw->drawable, + draw->core.gc, xspan, y, lenspan, 1); + xspan += lenspan; + w -= lenspan; + } + else + { + do + { + w--; + xspan++; + if (!w) + break; + bits = *src++; + } while (bits < 0x80000000); + } + } + y++; + } +} + +typedef void (*XftSharpGlyph) (XftDraw *draw, + XftGlyph *glyph, + int x, + int y); + +static XftSharpGlyph +_XftSharpGlyphFind (XftDraw *draw, XftFont *public) +{ + XftFontInt *font = (XftFontInt *) public; + + if (!font->info.antialias) + return _XftSharpGlyphMono; + else switch (font->info.rgba) { + case FC_RGBA_RGB: + case FC_RGBA_BGR: + case FC_RGBA_VRGB: + case FC_RGBA_VBGR: + return _XftSharpGlyphRgba; + default: + return _XftSharpGlyphGray; + } +} + +/* + * Draw glyphs to a target that supports anti-aliasing + */ + +/* + * Primitives for converting between RGB values and TrueColor pixels + */ + +static void +_XftExamineBitfield (unsigned long mask, int *shift, int *len) +{ + int s, l; + + s = 0; + while ((mask & 1) == 0) + { + mask >>= 1; + s++; + } + l = 0; + while ((mask & 1) == 1) + { + mask >>= 1; + l++; + } + *shift = s; + *len = l; +} + +static CARD32 +_XftGetField (unsigned long l_pixel, int shift, int len) +{ + CARD32 pixel = (CARD32) l_pixel; + + pixel = pixel & (((1 << (len)) - 1) << shift); + pixel = pixel << (32 - (shift + len)) >> 24; + while (len < 8) + { + pixel |= (pixel >> len); + len <<= 1; + } + return pixel; +} + +static unsigned long +_XftPutField (CARD32 pixel, int shift, int len) +{ + unsigned long l_pixel = (unsigned long) pixel; + + shift = shift - (8 - len); + if (len <= 8) + l_pixel &= (((1 << len) - 1) << (8 - len)); + if (shift < 0) + l_pixel >>= -shift; + else + l_pixel <<= shift; + return l_pixel; +} + +/* + * This is used when doing XftCharFontSpec/XftGlyphFontSpec where + * some of the fonts are bitmaps and some are anti-aliased to handle + * the bitmap portions + */ +static void +_XftSmoothGlyphMono (XImage *image, + _Xconst XftGlyph *xftg, + int x, + int y, + _Xconst XftColor *color) +{ + unsigned char *srcLine = xftg->bitmap, *src; + unsigned char bits, bitsMask; + int width = xftg->metrics.width; + int stride = ((width + 31) & ~31) >> 3; + int height = xftg->metrics.height; + int w; + int xspan; + int r_shift, r_len; + int g_shift, g_len; + int b_shift, b_len; + unsigned long pixel; + + _XftExamineBitfield (image->red_mask, &r_shift, &r_len); + _XftExamineBitfield (image->green_mask, &g_shift, &g_len); + _XftExamineBitfield (image->blue_mask, &b_shift, &b_len); + pixel = (_XftPutField (color->color.red >> 8, r_shift, r_len) | + _XftPutField (color->color.green >> 8, g_shift, g_len) | + _XftPutField (color->color.blue >> 8, b_shift, b_len)); + x -= xftg->metrics.x; + y -= xftg->metrics.y; + while (height--) + { + src = srcLine; + srcLine += stride; + w = width; + + bitsMask = 0x80; /* FreeType is always MSB first */ + bits = *src++; + + xspan = x; + while (w--) + { + if (bits & bitsMask) + XPutPixel (image, xspan, y, pixel); + bitsMask = bitsMask >> 1; + if (!bitsMask) + { + bits = *src++; + bitsMask = 0x80; + } + xspan++; + } + y++; + } +} + +/* + * As simple anti-aliasing is likely to be common, there are three + * optimized versions for the usual true color pixel formats (888, 565, 555). + * Other formats are handled by the general case + */ + +#define cvt8888to0565(s) ((((s) >> 3) & 0x001f) | \ + (((s) >> 5) & 0x07e0) | \ + (((s) >> 8) & 0xf800)) + +#define cvt0565to8888(s) (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \ + ((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \ + ((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000))) + +#define cvt8888to0555(s) ((((s) >> 3) & 0x001f) | \ + (((s) >> 6) & 0x03e0) | \ + (((s) >> 7) & 0x7c00)) + +#define cvt0555to8888(s) (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \ + ((((s) << 6) & 0xf800) | (((s) >> 0) & 0x300)) | \ + ((((s) << 9) & 0xf80000) | (((s) << 4) & 0x70000))) + + +#define XftIntMult(a,b,t) ( (t) = (a) * (b) + 0x80, ( ( ( (t)>>8 ) + (t) )>>8 ) ) +#define XftIntDiv(a,b) (((CARD16) (a) * 255) / (b)) + +#define XftGet8(v,i) ((CARD16) (CARD8) ((v) >> i)) + +/* + * There are two ways of handling alpha -- either as a single unified value or + * a separate value for each component, hence each macro must have two + * versions. The unified alpha version has a 'U' at the end of the name, + * the component version has a 'C'. Similarly, functions which deal with + * this difference will have two versions using the same convention. + */ + +#define XftOverU(x,y,i,a,t) ((t) = XftIntMult(XftGet8(y,i),(a),(t)) + XftGet8(x,i),\ + (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) + +#define XftOverC(x,y,i,a,t) ((t) = XftIntMult(XftGet8(y,i),XftGet8(a,i),(t)) + XftGet8(x,i),\ + (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) + +#define XftInU(x,i,a,t) ((CARD32) XftIntMult(XftGet8(x,i),(a),(t)) << (i)) + +#define XftInC(x,i,a,t) ((CARD32) XftIntMult(XftGet8(x,i),XftGet8(a,i),(t)) << (i)) + +#define XftGen(x,y,i,ax,ay,t,u,v) ((t) = (XftIntMult(XftGet8(y,i),ay,(u)) + \ + XftIntMult(XftGet8(x,i),ax,(v))),\ + (CARD32) ((CARD8) ((t) | \ + (0 - ((t) >> 8)))) << (i)) + +#define XftAdd(x,y,i,t) ((t) = XftGet8(x,i) + XftGet8(y,i), \ + (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) + + +static CARD32 +fbOver24 (CARD32 x, CARD32 y) +{ + CARD16 a = ~x >> 24; + CARD16 t; + CARD32 m,n,o; + + m = XftOverU(x,y,0,a,t); + n = XftOverU(x,y,8,a,t); + o = XftOverU(x,y,16,a,t); + return m|n|o; +} + +static CARD32 +fbIn (CARD32 x, CARD8 y) +{ + CARD16 a = y; + CARD16 t; + CARD32 m,n,o,p; + + m = XftInU(x,0,a,t); + n = XftInU(x,8,a,t); + o = XftInU(x,16,a,t); + p = XftInU(x,24,a,t); + return m|n|o|p; +} + +static void +_XftSmoothGlyphGray8888 (XImage *image, + _Xconst XftGlyph *xftg, + int x, + int y, + _Xconst XftColor *color) +{ + CARD32 src, srca; + CARD32 r, g, b; + CARD32 *dstLine, *dst, d; + CARD8 *maskLine, *mask, m; + int dstStride, maskStride; + int width, height; + int w; + + srca = color->color.alpha >> 8; + + /* This handles only RGB and BGR */ + g = (color->color.green & 0xff00); + if (image->red_mask == 0xff0000) + { + r = (color->color.red & 0xff00) << 8; + b = color->color.blue >> 8; + } + else + { + r = color->color.red >> 8; + b = (color->color.blue & 0xff00) << 8; + } + src = (srca << 24) | r | g | b; + + width = xftg->metrics.width; + height = xftg->metrics.height; + + x -= xftg->metrics.x; + y -= xftg->metrics.y; + + dstLine = (CARD32 *) (image->data + image->bytes_per_line * y + (x << 2)); + dstStride = image->bytes_per_line >> 2; + maskLine = (unsigned char *) xftg->bitmap; + maskStride = (width + 3) & ~3; + + while (height--) + { + dst = dstLine; + dstLine += dstStride; + mask = maskLine; + maskLine += maskStride; + w = width; + + while (w--) + { + m = *mask++; + if (m == 0xff) + { + if (srca == 0xff) + *dst = src; + else + *dst = fbOver24 (src, *dst); + } + else if (m) + { + d = fbIn (src, m); + *dst = fbOver24 (d, *dst); + } + dst++; + } + } +} + +static void +_XftSmoothGlyphGray565 (XImage *image, + _Xconst XftGlyph *xftg, + int x, + int y, + _Xconst XftColor *color) +{ + CARD32 src, srca; + CARD32 r, g, b; + CARD32 d; + CARD16 *dstLine, *dst; + CARD8 *maskLine, *mask, m; + int dstStride, maskStride; + int width, height; + int w; + + srca = color->color.alpha >> 8; + + /* This handles only RGB and BGR */ + g = (color->color.green & 0xff00); + if (image->red_mask == 0xf800) + { + r = (color->color.red & 0xff00) << 8; + b = color->color.blue >> 8; + } + else + { + r = color->color.red >> 8; + b = (color->color.blue & 0xff00) << 8; + } + src = (srca << 24) | r | g | b; + + width = xftg->metrics.width; + height = xftg->metrics.height; + + x -= xftg->metrics.x; + y -= xftg->metrics.y; + + dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1)); + dstStride = image->bytes_per_line >> 1; + maskLine = (unsigned char *) xftg->bitmap; + maskStride = (width + 3) & ~3; + + while (height--) + { + dst = dstLine; + dstLine += dstStride; + mask = maskLine; + maskLine += maskStride; + w = width; + + while (w--) + { + m = *mask++; + if (m == 0xff) + { + if (srca == 0xff) + d = src; + else + { + d = *dst; + d = fbOver24 (src, cvt0565to8888(d)); + } + *dst = cvt8888to0565(d); + } + else if (m) + { + d = *dst; + d = fbOver24 (fbIn(src,m), cvt0565to8888(d)); + *dst = cvt8888to0565(d); + } + dst++; + } + } +} + +static void +_XftSmoothGlyphGray555 (XImage *image, + _Xconst XftGlyph *xftg, + int x, + int y, + _Xconst XftColor *color) +{ + CARD32 src, srca; + CARD32 r, g, b; + CARD32 d; + CARD16 *dstLine, *dst; + CARD8 *maskLine, *mask, m; + int dstStride, maskStride; + int width, height; + int w; + + srca = color->color.alpha >> 8; + + /* This handles only RGB and BGR */ + g = (color->color.green & 0xff00); + if (image->red_mask == 0xf800) + { + r = (color->color.red & 0xff00) << 8; + b = color->color.blue >> 8; + } + else + { + r = color->color.red >> 8; + b = (color->color.blue & 0xff00) << 8; + } + src = (srca << 24) | r | g | b; + + width = xftg->metrics.width; + height = xftg->metrics.height; + + x -= xftg->metrics.x; + y -= xftg->metrics.y; + + dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1)); + dstStride = image->bytes_per_line >> 1; + maskLine = (unsigned char *) xftg->bitmap; + maskStride = (width + 3) & ~3; + + while (height--) + { + dst = dstLine; + dstLine += dstStride; + mask = maskLine; + maskLine += maskStride; + w = width; + + while (w--) + { + m = *mask++; + if (m == 0xff) + { + if (srca == 0xff) + d = src; + else + { + d = *dst; + d = fbOver24 (src, cvt0555to8888(d)); + } + *dst = cvt8888to0555(d); + } + else if (m) + { + d = *dst; + d = fbOver24 (fbIn(src,m), cvt0555to8888(d)); + *dst = cvt8888to0555(d); + } + dst++; + } + } +} + +static void +_XftSmoothGlyphGray (XImage *image, + _Xconst XftGlyph *xftg, + int x, + int y, + _Xconst XftColor *color) +{ + CARD32 src, srca; + int r_shift, r_len; + int g_shift, g_len; + int b_shift, b_len; + CARD8 *maskLine, *mask, m; + int maskStride; + CARD32 d; + unsigned long pixel; + int width, height; + int w, tx; + + srca = color->color.alpha >> 8; + src = (srca << 24 | + (color->color.red & 0xff00) << 8 | + (color->color.green & 0xff00) | + (color->color.blue) >> 8); + x -= xftg->metrics.x; + y -= xftg->metrics.y; + width = xftg->metrics.width; + height = xftg->metrics.height; + + maskLine = (unsigned char *) xftg->bitmap; + maskStride = (width + 3) & ~3; + + _XftExamineBitfield (image->red_mask, &r_shift, &r_len); + _XftExamineBitfield (image->green_mask, &g_shift, &g_len); + _XftExamineBitfield (image->blue_mask, &b_shift, &b_len); + while (height--) + { + mask = maskLine; + maskLine += maskStride; + w = width; + tx = x; + + while (w--) + { + m = *mask++; + if (m == 0xff) + { + if (srca == 0xff) + d = src; + else + { + pixel = XGetPixel (image, tx, y); + d = (_XftGetField (pixel, r_shift, r_len) << 16 | + _XftGetField (pixel, g_shift, g_len) << 8 | + _XftGetField (pixel, b_shift, b_len)); + d = fbOver24 (src, d); + } + pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) | + _XftPutField ((d >> 8) & 0xff, g_shift, g_len) | + _XftPutField ((d ) & 0xff, b_shift, b_len)); + XPutPixel (image, tx, y, pixel); + } + else if (m) + { + pixel = XGetPixel (image, tx, y); + d = (_XftGetField (pixel, r_shift, r_len) << 16 | + _XftGetField (pixel, g_shift, g_len) << 8 | + _XftGetField (pixel, b_shift, b_len)); + d = fbOver24 (fbIn(src,m), d); + pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) | + _XftPutField ((d >> 8) & 0xff, g_shift, g_len) | + _XftPutField ((d ) & 0xff, b_shift, b_len)); + XPutPixel (image, tx, y, pixel); + } + tx++; + } + y++; + } +} + +static void +_XftSmoothGlyphRgba (XImage *image, + _Xconst XftGlyph *xftg, + int x, + int y, + _Xconst XftColor *color) +{ + CARD32 src, srca; + int r_shift, r_len; + int g_shift, g_len; + int b_shift, b_len; + CARD32 *mask, ma; + CARD32 d; + unsigned long pixel; + int width, height; + int w, tx; + + srca = color->color.alpha >> 8; + src = (srca << 24 | + (color->color.red & 0xff00) << 8 | + (color->color.green & 0xff00) | + (color->color.blue) >> 8); + x -= xftg->metrics.x; + y -= xftg->metrics.y; + width = xftg->metrics.width; + height = xftg->metrics.height; + + mask = (CARD32 *) xftg->bitmap; + + _XftExamineBitfield (image->red_mask, &r_shift, &r_len); + _XftExamineBitfield (image->green_mask, &g_shift, &g_len); + _XftExamineBitfield (image->blue_mask, &b_shift, &b_len); + while (height--) + { + w = width; + tx = x; + + while (w--) + { + ma = *mask++; + if (ma == 0xffffffff) + { + if (srca == 0xff) + d = src; + else + { + pixel = XGetPixel (image, tx, y); + d = (_XftGetField (pixel, r_shift, r_len) << 16 | + _XftGetField (pixel, g_shift, g_len) << 8 | + _XftGetField (pixel, b_shift, b_len)); + d = fbOver24 (src, d); + } + pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) | + _XftPutField ((d >> 8) & 0xff, g_shift, g_len) | + _XftPutField ((d ) & 0xff, b_shift, b_len)); + XPutPixel (image, tx, y, pixel); + } + else if (ma) + { + CARD32 m,n,o; + pixel = XGetPixel (image, tx, y); + d = (_XftGetField (pixel, r_shift, r_len) << 16 | + _XftGetField (pixel, g_shift, g_len) << 8 | + _XftGetField (pixel, b_shift, b_len)); +#define XftInOverC(src,srca,msk,dst,i,result) { \ + CARD16 __a = XftGet8(msk,i); \ + CARD32 __t, __ta; \ + CARD32 __i; \ + __t = XftIntMult (XftGet8(src,i), __a,__i); \ + __ta = (CARD8) ~XftIntMult (srca, __a,__i); \ + __t = __t + XftIntMult(XftGet8(dst,i),__ta,__i); \ + __t = (CARD32) (CARD8) (__t | (-(__t >> 8))); \ + result = __t << (i); \ +} + XftInOverC(src,srca,ma,d,0,m); + XftInOverC(src,srca,ma,d,8,n); + XftInOverC(src,srca,ma,d,16,o); + d = m | n | o; + pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) | + _XftPutField ((d >> 8) & 0xff, g_shift, g_len) | + _XftPutField ((d ) & 0xff, b_shift, b_len)); + XPutPixel (image, tx, y, pixel); + } + tx++; + } + y++; + } +} + +static FcBool +_XftSmoothGlyphPossible (XftDraw *draw) +{ + if (!draw->visual) + return FcFalse; + if (draw->visual->class != TrueColor) + return FcFalse; + return FcTrue; +} + +typedef void (*XftSmoothGlyph) (XImage *image, + _Xconst XftGlyph *xftg, + int x, + int y, + _Xconst XftColor *color); + +static XftSmoothGlyph +_XftSmoothGlyphFind (XftDraw *draw, XftFont *public) +{ + XftFontInt *font = (XftFontInt *) public; + + if (!font->info.antialias) + return _XftSmoothGlyphMono; + else switch (font->info.rgba) { + case FC_RGBA_RGB: + case FC_RGBA_BGR: + case FC_RGBA_VRGB: + case FC_RGBA_VBGR: + return _XftSmoothGlyphRgba; + default: + switch (XftDrawBitsPerPixel (draw)) { + case 32: + if ((draw->visual->red_mask == 0xff0000 && + draw->visual->green_mask == 0x00ff00 && + draw->visual->blue_mask == 0x0000ff) || + (draw->visual->red_mask == 0x0000ff && + draw->visual->green_mask == 0x00ff00 && + draw->visual->blue_mask == 0xff0000)) + { + return _XftSmoothGlyphGray8888; + } + break; + case 16: + if ((draw->visual->red_mask == 0xf800 && + draw->visual->green_mask == 0x07e0 && + draw->visual->blue_mask == 0x001f) || + (draw->visual->red_mask == 0x001f && + draw->visual->green_mask == 0x07e0 && + draw->visual->blue_mask == 0xf800)) + { + return _XftSmoothGlyphGray565; + } + if ((draw->visual->red_mask == 0x7c00 && + draw->visual->green_mask == 0x03e0 && + draw->visual->blue_mask == 0x001f) || + (draw->visual->red_mask == 0x001f && + draw->visual->green_mask == 0x03e0 && + draw->visual->blue_mask == 0x7c00)) + { + return _XftSmoothGlyphGray555; + } + break; + default: + break; + } + return _XftSmoothGlyphGray; + } +} + +static XftGlyph * +_XftGlyphDefault (Display *dpy, XftFont *public) +{ + XftFontInt *font = (XftFontInt *) public; + FT_UInt missing[XFT_NMISSING]; + int nmissing; + FcBool glyphs_loaded = FcFalse; + + if (XftFontCheckGlyph (dpy, public, FcTrue, 0, missing, &nmissing)) + glyphs_loaded = FcTrue; + if (nmissing) + XftFontLoadGlyphs (dpy, public, glyphs_loaded, missing, nmissing); + return font->glyphs[0]; +} + +static int XftGetImageErrorHandler (Display *dpy, XErrorEvent *error_event) +{ + return 0; +} + +_X_HIDDEN void +XftGlyphCore (XftDraw *draw, + _Xconst XftColor *color, + XftFont *public, + int x, + int y, + _Xconst FT_UInt *glyphs, + int nglyphs) +{ + Display *dpy = draw->dpy; + XftFontInt *font = (XftFontInt *) public; + XftGlyph *xftg; + FT_UInt glyph; + _Xconst FT_UInt *g; + FT_UInt missing[XFT_NMISSING]; + FcBool glyphs_loaded; + int nmissing; + int n; + XErrorHandler prev_error; + + /* + * Load missing glyphs + */ + g = glyphs; + n = nglyphs; + nmissing = 0; + glyphs_loaded = FcFalse; + while (n--) + if (XftFontCheckGlyph (dpy, public, FcTrue, *g++, missing, &nmissing)) + glyphs_loaded = FcTrue; + if (nmissing) + XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing); + + g = glyphs; + n = nglyphs; + if ((font->info.antialias || color->color.alpha != 0xffff) && + _XftSmoothGlyphPossible (draw)) + { + XGlyphInfo gi; + XImage *image; + unsigned int depth; + int ox, oy; + XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public); + + XftGlyphExtents (dpy, public, glyphs, nglyphs, &gi); + if (!gi.width || !gi.height) + goto bail1; + ox = x - gi.x; + oy = y - gi.y; + /* + * Try to get bits directly from the drawable; if that fails, + * use a temporary pixmap. When it does fail, assume it + * will probably fail for a while and keep using temporary + * pixmaps for a while to avoid double round trips. + */ + if (draw->core.use_pixmap == 0) + { + prev_error = XSetErrorHandler (XftGetImageErrorHandler); + image = XGetImage (dpy, draw->drawable, + ox, oy, + gi.width, gi.height, AllPlanes, + ZPixmap); + XSetErrorHandler (prev_error); + if (!image) + draw->core.use_pixmap = XFT_ASSUME_PIXMAP; + } + else + { + draw->core.use_pixmap--; + image = NULL; + } + if (!image && (depth = XftDrawDepth (draw))) + { + Pixmap pix; + GC gc; + XGCValues gcv; + + pix = XCreatePixmap (dpy, draw->drawable, + gi.width, gi.height, depth); + gcv.graphics_exposures = False; + gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv); + XCopyArea (dpy, draw->drawable, pix, gc, ox, oy, + gi.width, gi.height, 0, 0); + XFreeGC (dpy, gc); + image = XGetImage (dpy, pix, 0, 0, gi.width, gi.height, AllPlanes, + ZPixmap); + XFreePixmap (dpy, pix); + } + if (!image) + goto bail1; + image->red_mask = draw->visual->red_mask; + image->green_mask = draw->visual->green_mask; + image->blue_mask = draw->visual->blue_mask; + if (image->byte_order != XftNativeByteOrder ()) + XftSwapImage (image); + while (n--) + { + glyph = *g++; + if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) + xftg = _XftGlyphDefault (dpy, public); + if (xftg) + { + (*smooth) (image, xftg, x - ox, y - oy, color); + x += xftg->metrics.xOff; + y += xftg->metrics.yOff; + } + } + if (image->byte_order != XftNativeByteOrder ()) + XftSwapImage (image); + XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, ox, oy, + gi.width, gi.height); + XDestroyImage (image); + } + else + { + XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public); + while (n--) + { + glyph = *g++; + if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) + xftg = _XftGlyphDefault (dpy, public); + if (xftg) + { + (*sharp) (draw, xftg, x, y); + x += xftg->metrics.xOff; + y += xftg->metrics.yOff; + } + } + } +bail1: + if (glyphs_loaded) + _XftFontManageMemory (dpy, public); +} + +#define NUM_LOCAL 1024 + +_X_HIDDEN void +XftGlyphSpecCore (XftDraw *draw, + _Xconst XftColor *color, + XftFont *public, + _Xconst XftGlyphSpec *glyphs, + int nglyphs) +{ + Display *dpy = draw->dpy; + XftFontInt *font = (XftFontInt *) public; + XftGlyph *xftg; + FT_UInt missing[XFT_NMISSING]; + FcBool glyphs_loaded; + int nmissing; + int i; + XErrorHandler prev_error; + int x1, y1, x2, y2; + + /* + * Load missing glyphs + */ + glyphs_loaded = FcFalse; + x1 = y1 = x2 = y2 = 0; + for (i = 0; i < nglyphs; i++) + { + XGlyphInfo gi; + int g_x1, g_x2, g_y1, g_y2; + + nmissing = 0; + if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing)) + glyphs_loaded = FcTrue; + if (nmissing) + XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing); + + XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi); + g_x1 = glyphs[i].x - gi.x; + g_y1 = glyphs[i].y - gi.y; + g_x2 = g_x1 + gi.width; + g_y2 = g_y1 + gi.height; + if (i) + { + if (g_x1 < x1) + x1 = g_x1; + if (g_y1 < y1) + y1 = g_y1; + if (g_x2 > x2) + x2 = g_x2; + if (g_y2 > y2) + y2 = g_y2; + } + else + { + x1 = g_x1; + y1 = g_y1; + x2 = g_x2; + y2 = g_y2; + } + } + + if (x1 == x2 || y1 == y2) + goto bail1; + + if ((font->info.antialias || color->color.alpha != 0xffff) && + _XftSmoothGlyphPossible (draw)) + { + XImage *image; + unsigned int depth; + int width = x2 - x1, height = y2 - y1; + XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public); + + /* + * Try to get bits directly from the drawable; if that fails, + * use a temporary pixmap. When it does fail, assume it + * will probably fail for a while and keep using temporary + * pixmaps for a while to avoid double round trips. + */ + if (draw->core.use_pixmap == 0) + { + prev_error = XSetErrorHandler (XftGetImageErrorHandler); + image = XGetImage (dpy, draw->drawable, + x1, y1, + width, height, AllPlanes, + ZPixmap); + XSetErrorHandler (prev_error); + if (!image) + draw->core.use_pixmap = XFT_ASSUME_PIXMAP; + } + else + { + draw->core.use_pixmap--; + image = NULL; + } + if (!image && (depth = XftDrawDepth (draw))) + { + Pixmap pix; + GC gc; + XGCValues gcv; + + pix = XCreatePixmap (dpy, draw->drawable, + width, height, depth); + gcv.graphics_exposures = False; + gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv); + XCopyArea (dpy, draw->drawable, pix, gc, x1, y1, + width, height, 0, 0); + XFreeGC (dpy, gc); + image = XGetImage (dpy, pix, 0, 0, width, height, AllPlanes, + ZPixmap); + XFreePixmap (dpy, pix); + } + if (!image) + goto bail1; + image->red_mask = draw->visual->red_mask; + image->green_mask = draw->visual->green_mask; + image->blue_mask = draw->visual->blue_mask; + if (image->byte_order != XftNativeByteOrder ()) + XftSwapImage (image); + for (i = 0; i < nglyphs; i++) + { + FT_UInt glyph = glyphs[i].glyph; + if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) + xftg = _XftGlyphDefault (dpy, public); + if (xftg) + { + (*smooth) (image, xftg, glyphs[i].x - x1, + glyphs[i].y - y1, color); + } + } + if (image->byte_order != XftNativeByteOrder ()) + XftSwapImage (image); + XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1, + width, height); + XDestroyImage (image); + } + else + { + XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public); + for (i = 0; i < nglyphs; i++) + { + FT_UInt glyph = glyphs[i].glyph; + if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) + xftg = _XftGlyphDefault (dpy, public); + if (xftg) + (*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y); + } + } +bail1: + if (glyphs_loaded) + _XftFontManageMemory (dpy, public); +} + +_X_HIDDEN void +XftGlyphFontSpecCore (XftDraw *draw, + _Xconst XftColor *color, + _Xconst XftGlyphFontSpec *glyphs, + int nglyphs) +{ + Display *dpy = draw->dpy; + XftGlyph *xftg; + FT_UInt missing[XFT_NMISSING]; + FcBool glyphs_loaded; + int nmissing; + int i; + XErrorHandler prev_error; + int x1, y1, x2, y2; + + /* + * Load missing glyphs + */ + glyphs_loaded = FcFalse; + x1 = y1 = x2 = y2 = 0; + for (i = 0; i < nglyphs; i++) + { + XftFont *public = glyphs[i].font; + XGlyphInfo gi; + int g_x1, g_x2, g_y1, g_y2; + + nmissing = 0; + if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing)) + glyphs_loaded = FcTrue; + if (nmissing) + XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing); + + XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi); + g_x1 = glyphs[i].x - gi.x; + g_y1 = glyphs[i].y - gi.y; + g_x2 = g_x1 + gi.width; + g_y2 = g_y1 + gi.height; + if (i) + { + if (g_x1 < x1) + { + if (g_x1 < 0) + { + /* do nothing if the given glyphs are out of range */ + short t = glyphs[i-1].font->max_advance_width + + glyphs[i-1].x; + if (t < 0 && glyphs[i-1].x > 0) + goto bail1; + } + x1 = g_x1; + } + if (g_y1 < y1) + y1 = g_y1; + if (g_x2 > x2) + x2 = g_x2; + if (g_y2 > y2) + y2 = g_y2; + } + else + { + x1 = g_x1; + y1 = g_y1; + x2 = g_x2; + y2 = g_y2; + } + } + + if (x1 == x2 || y1 == y2) + goto bail1; + + for (i = 0; i < nglyphs; i++) + if (((XftFontInt *) glyphs[i].font)->info.antialias) + break; + + if ((i != nglyphs || color->color.alpha != 0xffff) && + _XftSmoothGlyphPossible (draw)) + { + XImage *image; + unsigned int depth; + int width = x2 - x1, height = y2 - y1; + + /* + * Try to get bits directly from the drawable; if that fails, + * use a temporary pixmap. When it does fail, assume it + * will probably fail for a while and keep using temporary + * pixmaps for a while to avoid double round trips. + */ + if (draw->core.use_pixmap == 0) + { + prev_error = XSetErrorHandler (XftGetImageErrorHandler); + image = XGetImage (dpy, draw->drawable, + x1, y1, + width, height, AllPlanes, + ZPixmap); + XSetErrorHandler (prev_error); + if (!image) + draw->core.use_pixmap = XFT_ASSUME_PIXMAP; + } + else + { + draw->core.use_pixmap--; + image = NULL; + } + if (!image && (depth = XftDrawDepth (draw))) + { + Pixmap pix; + GC gc; + XGCValues gcv; + + pix = XCreatePixmap (dpy, draw->drawable, + width, height, depth); + gcv.graphics_exposures = False; + gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv); + XCopyArea (dpy, draw->drawable, pix, gc, x1, y1, + width, height, 0, 0); + XFreeGC (dpy, gc); + image = XGetImage (dpy, pix, 0, 0, width, height, AllPlanes, + ZPixmap); + XFreePixmap (dpy, pix); + } + if (!image) + goto bail1; + image->red_mask = draw->visual->red_mask; + image->green_mask = draw->visual->green_mask; + image->blue_mask = draw->visual->blue_mask; + if (image->byte_order != XftNativeByteOrder ()) + XftSwapImage (image); + for (i = 0; i < nglyphs; i++) + { + XftFont *public = glyphs[i].font; + XftFontInt *font = (XftFontInt *) public; + XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public); + FT_UInt glyph = glyphs[i].glyph; + + if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) + xftg = _XftGlyphDefault (dpy, public); + if (xftg) + { + (*smooth) (image, xftg, glyphs[i].x - x1, + glyphs[i].y - y1, color); + } + } + if (image->byte_order != XftNativeByteOrder ()) + XftSwapImage (image); + XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1, + width, height); + XDestroyImage (image); + } + else + { + for (i = 0; i < nglyphs; i++) + { + XftFont *public = glyphs[i].font; + XftFontInt *font = (XftFontInt *) public; + XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public); + FT_UInt glyph = glyphs[i].glyph; + + if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) + xftg = _XftGlyphDefault (dpy, public); + if (xftg) + (*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y); + } + } +bail1: + if (glyphs_loaded) + for (i = 0; i < nglyphs; i++) + _XftFontManageMemory (dpy, glyphs[i].font); +} diff --git a/libXft/src/xftdpy.c b/libXft/src/xftdpy.c index 862c7e8ab..cd50358d2 100644 --- a/libXft/src/xftdpy.c +++ b/libXft/src/xftdpy.c @@ -1,552 +1,552 @@ -/* - * Copyright © 2000 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#include "xftint.h" - -_X_HIDDEN XftDisplayInfo *_XftDisplayInfo; - -static int -_XftCloseDisplay (Display *dpy, XExtCodes *codes) -{ - XftDisplayInfo *info, **prev; - - info = _XftDisplayInfoGet (dpy, FcFalse); - if (!info) - return 0; - - /* - * Get rid of any dangling unreferenced fonts - */ - info->max_unref_fonts = 0; - XftFontManageMemory (dpy); - - /* - * Clean up the default values - */ - if (info->defaults) - FcPatternDestroy (info->defaults); - - /* - * Unhook from the global list - */ - for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next) - if (info->display == dpy) - break; - *prev = info->next; - - free (info); - return 0; -} - - -_X_HIDDEN XftDisplayInfo * -_XftDisplayInfoGet (Display *dpy, FcBool createIfNecessary) -{ - XftDisplayInfo *info, **prev; - XRenderPictFormat pf; - int i; - int event_base, error_base; - - for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next) - { - if (info->display == dpy) - { - /* - * MRU the list - */ - if (prev != &_XftDisplayInfo) - { - *prev = info->next; - info->next = _XftDisplayInfo; - _XftDisplayInfo = info; - } - return info; - } - } - if (!createIfNecessary) - return NULL; - - info = (XftDisplayInfo *) malloc (sizeof (XftDisplayInfo)); - if (!info) - goto bail0; - info->codes = XAddExtension (dpy); - if (!info->codes) - goto bail1; - (void) XESetCloseDisplay (dpy, info->codes->extension, _XftCloseDisplay); - - info->display = dpy; - info->defaults = NULL; - info->solidFormat = NULL; - info->hasRender = (XRenderQueryExtension (dpy, &event_base, &error_base) && - (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != NULL)); - info->use_free_glyphs = FcTrue; - if (info->hasRender) - { - int major, minor; - XRenderQueryVersion (dpy, &major, &minor); - if (major < 0 || (major == 0 && minor <= 2)) - info->use_free_glyphs = FcFalse; - - pf.type = PictTypeDirect; - pf.depth = 32; - pf.direct.redMask = 0xff; - pf.direct.greenMask = 0xff; - pf.direct.blueMask = 0xff; - pf.direct.alphaMask = 0xff; - info->solidFormat = XRenderFindFormat (dpy, - (PictFormatType| - PictFormatDepth| - PictFormatRedMask| - PictFormatGreenMask| - PictFormatBlueMask| - PictFormatAlphaMask), - &pf, - 0); - } - if (XftDebug () & XFT_DBG_RENDER) - { - Visual *visual = DefaultVisual (dpy, DefaultScreen (dpy)); - XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); - - printf ("XftDisplayInfoGet Default visual 0x%x ", - (int) visual->visualid); - if (format) - { - if (format->type == PictTypeDirect) - { - printf ("format %d,%d,%d,%d\n", - format->direct.alpha, - format->direct.red, - format->direct.green, - format->direct.blue); - } - else - { - printf ("format indexed\n"); - } - } - else - printf ("No Render format for default visual\n"); - - printf ("XftDisplayInfoGet initialized, hasRender set to \"%s\"\n", - info->hasRender ? "True" : "False"); - } - for (i = 0; i < XFT_NUM_SOLID_COLOR; i++) - { - info->colors[i].screen = -1; - info->colors[i].pict = 0; - } - info->fonts = NULL; - - info->next = _XftDisplayInfo; - _XftDisplayInfo = info; - - info->glyph_memory = 0; - info->max_glyph_memory = XftDefaultGetInteger (dpy, - XFT_MAX_GLYPH_MEMORY, 0, - XFT_DPY_MAX_GLYPH_MEMORY); - if (XftDebug () & XFT_DBG_CACHE) - printf ("global max cache memory %ld\n", info->max_glyph_memory); - - - info->num_unref_fonts = 0; - info->max_unref_fonts = XftDefaultGetInteger (dpy, - XFT_MAX_UNREF_FONTS, 0, - XFT_DPY_MAX_UNREF_FONTS); - if (XftDebug() & XFT_DBG_CACHE) - printf ("global max unref fonts %d\n", info->max_unref_fonts); - - memset (info->fontHash, '\0', sizeof (XftFont *) * XFT_NUM_FONT_HASH); - return info; - -bail1: - free (info); -bail0: - if (XftDebug () & XFT_DBG_RENDER) - { - printf ("XftDisplayInfoGet failed to initialize, Xft unhappy\n"); - } - return NULL; -} - -/* - * Reduce memory usage in X server - */ - -static void -_XftDisplayValidateMemory (XftDisplayInfo *info) -{ - XftFont *public; - XftFontInt *font; - unsigned long glyph_memory; - - glyph_memory = 0; - for (public = info->fonts; public; public = font->next) - { - font = (XftFontInt *) public; - glyph_memory += font->glyph_memory; - } - if (glyph_memory != info->glyph_memory) - printf ("Display glyph cache incorrect has %ld bytes, should have %ld\n", - info->glyph_memory, glyph_memory); -} - -_X_HIDDEN void -_XftDisplayManageMemory (Display *dpy) -{ - XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False); - unsigned long glyph_memory; - XftFont *public; - XftFontInt *font; - - if (!info || !info->max_glyph_memory) - return; - if (XftDebug () & XFT_DBG_CACHE) - { - if (info->glyph_memory > info->max_glyph_memory) - printf ("Reduce global memory from %ld to %ld\n", - info->glyph_memory, info->max_glyph_memory); - _XftDisplayValidateMemory (info); - } - while (info->glyph_memory > info->max_glyph_memory) - { - glyph_memory = rand () % info->glyph_memory; - public = info->fonts; - while (public) - { - font = (XftFontInt *) public; - - if (font->glyph_memory > glyph_memory) - { - _XftFontUncacheGlyph (dpy, public); - break; - } - public = font->next; - glyph_memory -= font->glyph_memory; - } - } - if (XftDebug () & XFT_DBG_CACHE) - _XftDisplayValidateMemory (info); -} - -_X_EXPORT Bool -XftDefaultHasRender (Display *dpy) -{ - XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); - - if (!info) - return False; - return info->hasRender; -} - -_X_EXPORT Bool -XftDefaultSet (Display *dpy, FcPattern *defaults) -{ - XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); - - if (!info) - return False; - if (info->defaults) - FcPatternDestroy (info->defaults); - info->defaults = defaults; - if (!info->max_glyph_memory) - info->max_glyph_memory = XFT_DPY_MAX_GLYPH_MEMORY; - info->max_glyph_memory = XftDefaultGetInteger (dpy, - XFT_MAX_GLYPH_MEMORY, 0, - info->max_glyph_memory); - if (!info->max_unref_fonts) - info->max_unref_fonts = XFT_DPY_MAX_UNREF_FONTS; - info->max_unref_fonts = XftDefaultGetInteger (dpy, - XFT_MAX_UNREF_FONTS, 0, - info->max_unref_fonts); - return True; -} - -_X_HIDDEN int -XftDefaultParseBool (char *v) -{ - char c0, c1; - - c0 = *v; - if (isupper ((int)c0)) - c0 = tolower (c0); - if (c0 == 't' || c0 == 'y' || c0 == '1') - return 1; - if (c0 == 'f' || c0 == 'n' || c0 == '0') - return 0; - if (c0 == 'o') - { - c1 = v[1]; - if (isupper ((int)c1)) - c1 = tolower (c1); - if (c1 == 'n') - return 1; - if (c1 == 'f') - return 0; - } - return -1; -} - -static Bool -_XftDefaultInitBool (Display *dpy, FcPattern *pat, char *option) -{ - char *v; - int i; - - v = XGetDefault (dpy, "Xft", option); - if (v && (i = XftDefaultParseBool (v)) >= 0) - return FcPatternAddBool (pat, option, i != 0); - return True; -} - -static Bool -_XftDefaultInitDouble (Display *dpy, FcPattern *pat, char *option) -{ - char *v, *e; - double d; - - v = XGetDefault (dpy, "Xft", option); - if (v) - { - d = strtod (v, &e); - if (e != v) - return FcPatternAddDouble (pat, option, d); - } - return True; -} - -static Bool -_XftDefaultInitInteger (Display *dpy, FcPattern *pat, char *option) -{ - char *v, *e; - int i; - - v = XGetDefault (dpy, "Xft", option); - if (v) - { - if (FcNameConstant ((FcChar8 *) v, &i)) - return FcPatternAddInteger (pat, option, i); - i = strtol (v, &e, 0); - if (e != v) - return FcPatternAddInteger (pat, option, i); - } - return True; -} - -static FcPattern * -_XftDefaultInit (Display *dpy) -{ - FcPattern *pat; - - pat = FcPatternCreate (); - if (!pat) - goto bail0; - - if (!_XftDefaultInitDouble (dpy, pat, FC_SCALE)) - goto bail1; - if (!_XftDefaultInitDouble (dpy, pat, FC_DPI)) - goto bail1; - if (!_XftDefaultInitBool (dpy, pat, XFT_RENDER)) - goto bail1; - if (!_XftDefaultInitInteger (dpy, pat, FC_RGBA)) - goto bail1; - if (!_XftDefaultInitBool (dpy, pat, FC_ANTIALIAS)) - goto bail1; -#ifdef FC_EMBOLDEN - if (!_XftDefaultInitBool (dpy, pat, FC_EMBOLDEN)) - goto bail1; -#endif - if (!_XftDefaultInitBool (dpy, pat, FC_AUTOHINT)) - goto bail1; -#ifdef FC_HINT_STYLE - if (!_XftDefaultInitInteger (dpy, pat, FC_HINT_STYLE)) - goto bail1; -#endif - if (!_XftDefaultInitBool (dpy, pat, FC_HINTING)) - goto bail1; - if (!_XftDefaultInitBool (dpy, pat, FC_MINSPACE)) - goto bail1; - if (!_XftDefaultInitInteger (dpy, pat, XFT_MAX_GLYPH_MEMORY)) - goto bail1; - - return pat; - -bail1: - FcPatternDestroy (pat); -bail0: - return NULL; -} - -static FcResult -_XftDefaultGet (Display *dpy, const char *object, int screen, FcValue *v) -{ - XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); - FcResult r; - - if (!info) - return FcResultNoMatch; - - if (!info->defaults) - { - info->defaults = _XftDefaultInit (dpy); - if (!info->defaults) - return FcResultNoMatch; - } - r = FcPatternGet (info->defaults, object, screen, v); - if (r == FcResultNoId && screen > 0) - r = FcPatternGet (info->defaults, object, 0, v); - return r; -} - -_X_HIDDEN Bool -XftDefaultGetBool (Display *dpy, const char *object, int screen, Bool def) -{ - FcResult r; - FcValue v; - - r = _XftDefaultGet (dpy, object, screen, &v); - if (r != FcResultMatch || v.type != FcTypeBool) - return def; - return v.u.b; -} - -_X_HIDDEN int -XftDefaultGetInteger (Display *dpy, const char *object, int screen, int def) -{ - FcResult r; - FcValue v; - - r = _XftDefaultGet (dpy, object, screen, &v); - if (r != FcResultMatch || v.type != FcTypeInteger) - return def; - return v.u.i; -} - -_X_HIDDEN double -XftDefaultGetDouble (Display *dpy, const char *object, int screen, double def) -{ - FcResult r; - FcValue v; - - r = _XftDefaultGet (dpy, object, screen, &v); - if (r != FcResultMatch || v.type != FcTypeDouble) - return def; - return v.u.d; -} - -_X_EXPORT void -XftDefaultSubstitute (Display *dpy, int screen, FcPattern *pattern) -{ - FcValue v; - double dpi; - - if (FcPatternGet (pattern, XFT_RENDER, 0, &v) == FcResultNoMatch) - { - FcPatternAddBool (pattern, XFT_RENDER, - XftDefaultGetBool (dpy, XFT_RENDER, screen, - XftDefaultHasRender (dpy))); - } - if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch) - { - FcPatternAddBool (pattern, FC_ANTIALIAS, - XftDefaultGetBool (dpy, FC_ANTIALIAS, screen, - True)); - } -#ifdef FC_EMBOLDEN - if (FcPatternGet (pattern, FC_EMBOLDEN, 0, &v) == FcResultNoMatch) - { - FcPatternAddBool (pattern, FC_EMBOLDEN, - XftDefaultGetBool (dpy, FC_EMBOLDEN, screen, - False)); - } -#endif - if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch) - { - FcPatternAddBool (pattern, FC_HINTING, - XftDefaultGetBool (dpy, FC_HINTING, screen, - True)); - } -#ifdef FC_HINT_STYLE - if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch) - { - FcPatternAddInteger (pattern, FC_HINT_STYLE, - XftDefaultGetInteger (dpy, FC_HINT_STYLE, screen, - FC_HINT_FULL)); - } -#endif - if (FcPatternGet (pattern, FC_AUTOHINT, 0, &v) == FcResultNoMatch) - { - FcPatternAddBool (pattern, FC_AUTOHINT, - XftDefaultGetBool (dpy, FC_AUTOHINT, screen, - False)); - } - if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch) - { - int subpixel = FC_RGBA_UNKNOWN; -#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6 - if (XftDefaultHasRender (dpy)) - { - int render_order = XRenderQuerySubpixelOrder (dpy, screen); - switch (render_order) { - default: - case SubPixelUnknown: subpixel = FC_RGBA_UNKNOWN; break; - case SubPixelHorizontalRGB: subpixel = FC_RGBA_RGB; break; - case SubPixelHorizontalBGR: subpixel = FC_RGBA_BGR; break; - case SubPixelVerticalRGB: subpixel = FC_RGBA_VRGB; break; - case SubPixelVerticalBGR: subpixel = FC_RGBA_VBGR; break; - case SubPixelNone: subpixel = FC_RGBA_NONE; break; - } - } -#endif - FcPatternAddInteger (pattern, FC_RGBA, - XftDefaultGetInteger (dpy, FC_RGBA, screen, - subpixel)); - } - if (FcPatternGet (pattern, FC_MINSPACE, 0, &v) == FcResultNoMatch) - { - FcPatternAddBool (pattern, FC_MINSPACE, - XftDefaultGetBool (dpy, FC_MINSPACE, screen, - False)); - } - if (FcPatternGet (pattern, FC_DPI, 0, &v) == FcResultNoMatch) - { - dpi = (((double) DisplayHeight (dpy, screen) * 25.4) / - (double) DisplayHeightMM (dpy, screen)); - FcPatternAddDouble (pattern, FC_DPI, - XftDefaultGetDouble (dpy, FC_DPI, screen, - dpi)); - } - if (FcPatternGet (pattern, FC_SCALE, 0, &v) == FcResultNoMatch) - { - FcPatternAddDouble (pattern, FC_SCALE, - XftDefaultGetDouble (dpy, FC_SCALE, screen, 1.0)); - } - if (FcPatternGet (pattern, XFT_MAX_GLYPH_MEMORY, 0, &v) == FcResultNoMatch) - { - FcPatternAddInteger (pattern, XFT_MAX_GLYPH_MEMORY, - XftDefaultGetInteger (dpy, XFT_MAX_GLYPH_MEMORY, - screen, - XFT_FONT_MAX_GLYPH_MEMORY)); - } - FcDefaultSubstitute (pattern); -} - +/* + * Copyright © 2000 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "xftint.h" + +_X_HIDDEN XftDisplayInfo *_XftDisplayInfo; + +static int +_XftCloseDisplay (Display *dpy, XExtCodes *codes) +{ + XftDisplayInfo *info, **prev; + + info = _XftDisplayInfoGet (dpy, FcFalse); + if (!info) + return 0; + + /* + * Get rid of any dangling unreferenced fonts + */ + info->max_unref_fonts = 0; + XftFontManageMemory (dpy); + + /* + * Clean up the default values + */ + if (info->defaults) + FcPatternDestroy (info->defaults); + + /* + * Unhook from the global list + */ + for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next) + if (info->display == dpy) + break; + *prev = info->next; + + free (info); + return 0; +} + + +_X_HIDDEN XftDisplayInfo * +_XftDisplayInfoGet (Display *dpy, FcBool createIfNecessary) +{ + XftDisplayInfo *info, **prev; + XRenderPictFormat pf; + int i; + int event_base, error_base; + + for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next) + { + if (info->display == dpy) + { + /* + * MRU the list + */ + if (prev != &_XftDisplayInfo) + { + *prev = info->next; + info->next = _XftDisplayInfo; + _XftDisplayInfo = info; + } + return info; + } + } + if (!createIfNecessary) + return NULL; + + info = (XftDisplayInfo *) malloc (sizeof (XftDisplayInfo)); + if (!info) + goto bail0; + info->codes = XAddExtension (dpy); + if (!info->codes) + goto bail1; + (void) XESetCloseDisplay (dpy, info->codes->extension, _XftCloseDisplay); + + info->display = dpy; + info->defaults = NULL; + info->solidFormat = NULL; + info->hasRender = (XRenderQueryExtension (dpy, &event_base, &error_base) && + (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != NULL)); + info->use_free_glyphs = FcTrue; + if (info->hasRender) + { + int major, minor; + XRenderQueryVersion (dpy, &major, &minor); + if (major < 0 || (major == 0 && minor <= 2)) + info->use_free_glyphs = FcFalse; + + pf.type = PictTypeDirect; + pf.depth = 32; + pf.direct.redMask = 0xff; + pf.direct.greenMask = 0xff; + pf.direct.blueMask = 0xff; + pf.direct.alphaMask = 0xff; + info->solidFormat = XRenderFindFormat (dpy, + (PictFormatType| + PictFormatDepth| + PictFormatRedMask| + PictFormatGreenMask| + PictFormatBlueMask| + PictFormatAlphaMask), + &pf, + 0); + } + if (XftDebug () & XFT_DBG_RENDER) + { + Visual *visual = DefaultVisual (dpy, DefaultScreen (dpy)); + XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); + + printf ("XftDisplayInfoGet Default visual 0x%x ", + (int) visual->visualid); + if (format) + { + if (format->type == PictTypeDirect) + { + printf ("format %d,%d,%d,%d\n", + format->direct.alpha, + format->direct.red, + format->direct.green, + format->direct.blue); + } + else + { + printf ("format indexed\n"); + } + } + else + printf ("No Render format for default visual\n"); + + printf ("XftDisplayInfoGet initialized, hasRender set to \"%s\"\n", + info->hasRender ? "True" : "False"); + } + for (i = 0; i < XFT_NUM_SOLID_COLOR; i++) + { + info->colors[i].screen = -1; + info->colors[i].pict = 0; + } + info->fonts = NULL; + + info->next = _XftDisplayInfo; + _XftDisplayInfo = info; + + info->glyph_memory = 0; + info->max_glyph_memory = XftDefaultGetInteger (dpy, + XFT_MAX_GLYPH_MEMORY, 0, + XFT_DPY_MAX_GLYPH_MEMORY); + if (XftDebug () & XFT_DBG_CACHE) + printf ("global max cache memory %ld\n", info->max_glyph_memory); + + + info->num_unref_fonts = 0; + info->max_unref_fonts = XftDefaultGetInteger (dpy, + XFT_MAX_UNREF_FONTS, 0, + XFT_DPY_MAX_UNREF_FONTS); + if (XftDebug() & XFT_DBG_CACHE) + printf ("global max unref fonts %d\n", info->max_unref_fonts); + + memset (info->fontHash, '\0', sizeof (XftFont *) * XFT_NUM_FONT_HASH); + return info; + +bail1: + free (info); +bail0: + if (XftDebug () & XFT_DBG_RENDER) + { + printf ("XftDisplayInfoGet failed to initialize, Xft unhappy\n"); + } + return NULL; +} + +/* + * Reduce memory usage in X server + */ + +static void +_XftDisplayValidateMemory (XftDisplayInfo *info) +{ + XftFont *public; + XftFontInt *font; + unsigned long glyph_memory; + + glyph_memory = 0; + for (public = info->fonts; public; public = font->next) + { + font = (XftFontInt *) public; + glyph_memory += font->glyph_memory; + } + if (glyph_memory != info->glyph_memory) + printf ("Display glyph cache incorrect has %ld bytes, should have %ld\n", + info->glyph_memory, glyph_memory); +} + +_X_HIDDEN void +_XftDisplayManageMemory (Display *dpy) +{ + XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False); + unsigned long glyph_memory; + XftFont *public; + XftFontInt *font; + + if (!info || !info->max_glyph_memory) + return; + if (XftDebug () & XFT_DBG_CACHE) + { + if (info->glyph_memory > info->max_glyph_memory) + printf ("Reduce global memory from %ld to %ld\n", + info->glyph_memory, info->max_glyph_memory); + _XftDisplayValidateMemory (info); + } + while (info->glyph_memory > info->max_glyph_memory) + { + glyph_memory = rand () % info->glyph_memory; + public = info->fonts; + while (public) + { + font = (XftFontInt *) public; + + if (font->glyph_memory > glyph_memory) + { + _XftFontUncacheGlyph (dpy, public); + break; + } + public = font->next; + glyph_memory -= font->glyph_memory; + } + } + if (XftDebug () & XFT_DBG_CACHE) + _XftDisplayValidateMemory (info); +} + +_X_EXPORT Bool +XftDefaultHasRender (Display *dpy) +{ + XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); + + if (!info) + return False; + return info->hasRender; +} + +_X_EXPORT Bool +XftDefaultSet (Display *dpy, FcPattern *defaults) +{ + XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); + + if (!info) + return False; + if (info->defaults) + FcPatternDestroy (info->defaults); + info->defaults = defaults; + if (!info->max_glyph_memory) + info->max_glyph_memory = XFT_DPY_MAX_GLYPH_MEMORY; + info->max_glyph_memory = XftDefaultGetInteger (dpy, + XFT_MAX_GLYPH_MEMORY, 0, + info->max_glyph_memory); + if (!info->max_unref_fonts) + info->max_unref_fonts = XFT_DPY_MAX_UNREF_FONTS; + info->max_unref_fonts = XftDefaultGetInteger (dpy, + XFT_MAX_UNREF_FONTS, 0, + info->max_unref_fonts); + return True; +} + +_X_HIDDEN int +XftDefaultParseBool (char *v) +{ + char c0, c1; + + c0 = *v; + if (isupper ((int)c0)) + c0 = tolower (c0); + if (c0 == 't' || c0 == 'y' || c0 == '1') + return 1; + if (c0 == 'f' || c0 == 'n' || c0 == '0') + return 0; + if (c0 == 'o') + { + c1 = v[1]; + if (isupper ((int)c1)) + c1 = tolower (c1); + if (c1 == 'n') + return 1; + if (c1 == 'f') + return 0; + } + return -1; +} + +static Bool +_XftDefaultInitBool (Display *dpy, FcPattern *pat, char *option) +{ + char *v; + int i; + + v = XGetDefault (dpy, "Xft", option); + if (v && (i = XftDefaultParseBool (v)) >= 0) + return FcPatternAddBool (pat, option, i != 0); + return True; +} + +static Bool +_XftDefaultInitDouble (Display *dpy, FcPattern *pat, char *option) +{ + char *v, *e; + double d; + + v = XGetDefault (dpy, "Xft", option); + if (v) + { + d = strtod (v, &e); + if (e != v) + return FcPatternAddDouble (pat, option, d); + } + return True; +} + +static Bool +_XftDefaultInitInteger (Display *dpy, FcPattern *pat, char *option) +{ + char *v, *e; + int i; + + v = XGetDefault (dpy, "Xft", option); + if (v) + { + if (FcNameConstant ((FcChar8 *) v, &i)) + return FcPatternAddInteger (pat, option, i); + i = strtol (v, &e, 0); + if (e != v) + return FcPatternAddInteger (pat, option, i); + } + return True; +} + +static FcPattern * +_XftDefaultInit (Display *dpy) +{ + FcPattern *pat; + + pat = FcPatternCreate (); + if (!pat) + goto bail0; + + if (!_XftDefaultInitDouble (dpy, pat, FC_SCALE)) + goto bail1; + if (!_XftDefaultInitDouble (dpy, pat, FC_DPI)) + goto bail1; + if (!_XftDefaultInitBool (dpy, pat, XFT_RENDER)) + goto bail1; + if (!_XftDefaultInitInteger (dpy, pat, FC_RGBA)) + goto bail1; + if (!_XftDefaultInitBool (dpy, pat, FC_ANTIALIAS)) + goto bail1; +#ifdef FC_EMBOLDEN + if (!_XftDefaultInitBool (dpy, pat, FC_EMBOLDEN)) + goto bail1; +#endif + if (!_XftDefaultInitBool (dpy, pat, FC_AUTOHINT)) + goto bail1; +#ifdef FC_HINT_STYLE + if (!_XftDefaultInitInteger (dpy, pat, FC_HINT_STYLE)) + goto bail1; +#endif + if (!_XftDefaultInitBool (dpy, pat, FC_HINTING)) + goto bail1; + if (!_XftDefaultInitBool (dpy, pat, FC_MINSPACE)) + goto bail1; + if (!_XftDefaultInitInteger (dpy, pat, XFT_MAX_GLYPH_MEMORY)) + goto bail1; + + return pat; + +bail1: + FcPatternDestroy (pat); +bail0: + return NULL; +} + +static FcResult +_XftDefaultGet (Display *dpy, const char *object, int screen, FcValue *v) +{ + XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); + FcResult r; + + if (!info) + return FcResultNoMatch; + + if (!info->defaults) + { + info->defaults = _XftDefaultInit (dpy); + if (!info->defaults) + return FcResultNoMatch; + } + r = FcPatternGet (info->defaults, object, screen, v); + if (r == FcResultNoId && screen > 0) + r = FcPatternGet (info->defaults, object, 0, v); + return r; +} + +_X_HIDDEN Bool +XftDefaultGetBool (Display *dpy, const char *object, int screen, Bool def) +{ + FcResult r; + FcValue v; + + r = _XftDefaultGet (dpy, object, screen, &v); + if (r != FcResultMatch || v.type != FcTypeBool) + return def; + return v.u.b; +} + +_X_HIDDEN int +XftDefaultGetInteger (Display *dpy, const char *object, int screen, int def) +{ + FcResult r; + FcValue v; + + r = _XftDefaultGet (dpy, object, screen, &v); + if (r != FcResultMatch || v.type != FcTypeInteger) + return def; + return v.u.i; +} + +_X_HIDDEN double +XftDefaultGetDouble (Display *dpy, const char *object, int screen, double def) +{ + FcResult r; + FcValue v; + + r = _XftDefaultGet (dpy, object, screen, &v); + if (r != FcResultMatch || v.type != FcTypeDouble) + return def; + return v.u.d; +} + +_X_EXPORT void +XftDefaultSubstitute (Display *dpy, int screen, FcPattern *pattern) +{ + FcValue v; + double dpi; + + if (FcPatternGet (pattern, XFT_RENDER, 0, &v) == FcResultNoMatch) + { + FcPatternAddBool (pattern, XFT_RENDER, + XftDefaultGetBool (dpy, XFT_RENDER, screen, + XftDefaultHasRender (dpy))); + } + if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch) + { + FcPatternAddBool (pattern, FC_ANTIALIAS, + XftDefaultGetBool (dpy, FC_ANTIALIAS, screen, + True)); + } +#ifdef FC_EMBOLDEN + if (FcPatternGet (pattern, FC_EMBOLDEN, 0, &v) == FcResultNoMatch) + { + FcPatternAddBool (pattern, FC_EMBOLDEN, + XftDefaultGetBool (dpy, FC_EMBOLDEN, screen, + False)); + } +#endif + if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch) + { + FcPatternAddBool (pattern, FC_HINTING, + XftDefaultGetBool (dpy, FC_HINTING, screen, + True)); + } +#ifdef FC_HINT_STYLE + if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch) + { + FcPatternAddInteger (pattern, FC_HINT_STYLE, + XftDefaultGetInteger (dpy, FC_HINT_STYLE, screen, + FC_HINT_FULL)); + } +#endif + if (FcPatternGet (pattern, FC_AUTOHINT, 0, &v) == FcResultNoMatch) + { + FcPatternAddBool (pattern, FC_AUTOHINT, + XftDefaultGetBool (dpy, FC_AUTOHINT, screen, + False)); + } + if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch) + { + int subpixel = FC_RGBA_UNKNOWN; +#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6 + if (XftDefaultHasRender (dpy)) + { + int render_order = XRenderQuerySubpixelOrder (dpy, screen); + switch (render_order) { + default: + case SubPixelUnknown: subpixel = FC_RGBA_UNKNOWN; break; + case SubPixelHorizontalRGB: subpixel = FC_RGBA_RGB; break; + case SubPixelHorizontalBGR: subpixel = FC_RGBA_BGR; break; + case SubPixelVerticalRGB: subpixel = FC_RGBA_VRGB; break; + case SubPixelVerticalBGR: subpixel = FC_RGBA_VBGR; break; + case SubPixelNone: subpixel = FC_RGBA_NONE; break; + } + } +#endif + FcPatternAddInteger (pattern, FC_RGBA, + XftDefaultGetInteger (dpy, FC_RGBA, screen, + subpixel)); + } + if (FcPatternGet (pattern, FC_MINSPACE, 0, &v) == FcResultNoMatch) + { + FcPatternAddBool (pattern, FC_MINSPACE, + XftDefaultGetBool (dpy, FC_MINSPACE, screen, + False)); + } + if (FcPatternGet (pattern, FC_DPI, 0, &v) == FcResultNoMatch) + { + dpi = (((double) DisplayHeight (dpy, screen) * 25.4) / + (double) DisplayHeightMM (dpy, screen)); + FcPatternAddDouble (pattern, FC_DPI, + XftDefaultGetDouble (dpy, FC_DPI, screen, + dpi)); + } + if (FcPatternGet (pattern, FC_SCALE, 0, &v) == FcResultNoMatch) + { + FcPatternAddDouble (pattern, FC_SCALE, + XftDefaultGetDouble (dpy, FC_SCALE, screen, 1.0)); + } + if (FcPatternGet (pattern, XFT_MAX_GLYPH_MEMORY, 0, &v) == FcResultNoMatch) + { + FcPatternAddInteger (pattern, XFT_MAX_GLYPH_MEMORY, + XftDefaultGetInteger (dpy, XFT_MAX_GLYPH_MEMORY, + screen, + XFT_FONT_MAX_GLYPH_MEMORY)); + } + FcDefaultSubstitute (pattern); +} + diff --git a/libXft/src/xftdraw.c b/libXft/src/xftdraw.c index 7b8f84dd5..21f8538a3 100644 --- a/libXft/src/xftdraw.c +++ b/libXft/src/xftdraw.c @@ -1,994 +1,994 @@ -/* - * Copyright © 2000 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#include "xftint.h" - -/* - * Ok, this is a pain. To share source pictures across multiple destinations, - * the screen for each drawable must be discovered. - */ - -static int -_XftDrawScreen (Display *dpy, Drawable drawable, Visual *visual) -{ - int s; - Window root; - int x, y; - unsigned int width, height, borderWidth, depth; - /* Special case the most common environment */ - if (ScreenCount (dpy) == 1) - return 0; - /* - * If we've got a visual, look for the screen that points at it. - * This requires no round trip. - */ - if (visual) - { - for (s = 0; s < ScreenCount (dpy); s++) - { - XVisualInfo template, *ret; - int nret; - - template.visualid = visual->visualid; - template.screen = s; - ret = XGetVisualInfo (dpy, VisualIDMask|VisualScreenMask, - &template, &nret); - if (ret) - { - XFree (ret); - return s; - } - } - } - /* - * Otherwise, as the server for the drawable geometry and find - * the screen from the root window. - * This takes a round trip. - */ - if (XGetGeometry (dpy, drawable, &root, &x, &y, &width, &height, - &borderWidth, &depth)) - { - for (s = 0; s < ScreenCount (dpy); s++) - { - if (RootWindow (dpy, s) == root) - return s; - } - } - /* - * Make a guess -- it's probably wrong, but then the app probably - * handed us a bogus drawable in this case - */ - return 0; -} - -_X_HIDDEN unsigned int -XftDrawDepth (XftDraw *draw) -{ - if (!draw->depth) - { - Window root; - int x, y; - unsigned int width, height, borderWidth, depth; - if (XGetGeometry (draw->dpy, draw->drawable, - &root, &x, &y, &width, &height, - &borderWidth, &depth)) - draw->depth = depth; - } - return draw->depth; -} - -_X_HIDDEN unsigned int -XftDrawBitsPerPixel (XftDraw *draw) -{ - if (!draw->bits_per_pixel) - { - XPixmapFormatValues *formats; - int nformats; - unsigned int depth; - - if ((depth = XftDrawDepth (draw)) && - (formats = XListPixmapFormats (draw->dpy, &nformats))) - { - int i; - - for (i = 0; i < nformats; i++) - { - if (formats[i].depth == depth) - { - draw->bits_per_pixel = formats[i].bits_per_pixel; - break; - } - } - XFree (formats); - } - } - return draw->bits_per_pixel; -} - -_X_EXPORT XftDraw * -XftDrawCreate (Display *dpy, - Drawable drawable, - Visual *visual, - Colormap colormap) -{ - XftDraw *draw; - - draw = (XftDraw *) malloc (sizeof (XftDraw)); - if (!draw) - return NULL; - - draw->dpy = dpy; - draw->drawable = drawable; - draw->screen = _XftDrawScreen (dpy, drawable, visual); - draw->depth = 0; /* don't find out unless we need to know */ - draw->bits_per_pixel = 0; /* don't find out unless we need to know */ - draw->visual = visual; - draw->colormap = colormap; - draw->render.pict = 0; - draw->core.gc = NULL; - draw->core.use_pixmap = 0; - draw->clip_type = XftClipTypeNone; - draw->subwindow_mode = ClipByChildren; - XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw)); - return draw; -} - -_X_EXPORT XftDraw * -XftDrawCreateBitmap (Display *dpy, - Pixmap bitmap) -{ - XftDraw *draw; - - draw = (XftDraw *) malloc (sizeof (XftDraw)); - if (!draw) - return NULL; - draw->dpy = dpy; - draw->drawable = (Drawable) bitmap; - draw->screen = _XftDrawScreen (dpy, bitmap, NULL); - draw->depth = 1; - draw->bits_per_pixel = 1; - draw->visual = NULL; - draw->colormap = 0; - draw->render.pict = 0; - draw->core.gc = NULL; - draw->core.use_pixmap = 0; - draw->clip_type = XftClipTypeNone; - draw->subwindow_mode = ClipByChildren; - XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw)); - return draw; -} - -_X_EXPORT XftDraw * -XftDrawCreateAlpha (Display *dpy, - Pixmap pixmap, - int depth) -{ - XftDraw *draw; - - draw = (XftDraw *) malloc (sizeof (XftDraw)); - if (!draw) - return NULL; - draw->dpy = dpy; - draw->drawable = (Drawable) pixmap; - draw->screen = _XftDrawScreen (dpy, pixmap, NULL); - draw->depth = depth; - draw->bits_per_pixel = 0; /* don't find out until we need it */ - draw->visual = NULL; - draw->colormap = 0; - draw->render.pict = 0; - draw->core.gc = NULL; - draw->core.use_pixmap = 0; - draw->clip_type = XftClipTypeNone; - draw->subwindow_mode = ClipByChildren; - XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw)); - return draw; -} - -static XRenderPictFormat * -_XftDrawFormat (XftDraw *draw) -{ - XftDisplayInfo *info = _XftDisplayInfoGet (draw->dpy, True); - - if (!info || !info->hasRender) - return NULL; - - if (draw->visual == NULL) - { - XRenderPictFormat pf; - - pf.type = PictTypeDirect; - pf.depth = XftDrawDepth (draw); - pf.direct.alpha = 0; - pf.direct.alphaMask = (1 << pf.depth) - 1; - return XRenderFindFormat (draw->dpy, - (PictFormatType| - PictFormatDepth| - PictFormatAlpha| - PictFormatAlphaMask), - &pf, - 0); - } - else - return XRenderFindVisualFormat (draw->dpy, draw->visual); -} - -_X_EXPORT void -XftDrawChange (XftDraw *draw, - Drawable drawable) -{ - draw->drawable = drawable; - if (draw->render.pict) - { - XRenderFreePicture (draw->dpy, draw->render.pict); - draw->render.pict = 0; - } - if (draw->core.gc) - { - XFreeGC (draw->dpy, draw->core.gc); - draw->core.gc = NULL; - } -} - -_X_EXPORT Display * -XftDrawDisplay (XftDraw *draw) -{ - return draw->dpy; -} - -_X_EXPORT Drawable -XftDrawDrawable (XftDraw *draw) -{ - return draw->drawable; -} - -_X_EXPORT Colormap -XftDrawColormap (XftDraw *draw) -{ - return draw->colormap; -} - -_X_EXPORT Visual * -XftDrawVisual (XftDraw *draw) -{ - return draw->visual; -} - -_X_EXPORT void -XftDrawDestroy (XftDraw *draw) -{ - if (draw->render.pict) - XRenderFreePicture (draw->dpy, draw->render.pict); - if (draw->core.gc) - XFreeGC (draw->dpy, draw->core.gc); - switch (draw->clip_type) { - case XftClipTypeRegion: - XDestroyRegion (draw->clip.region); - break; - case XftClipTypeRectangles: - free (draw->clip.rect); - break; - case XftClipTypeNone: - break; - } - XftMemFree (XFT_MEM_DRAW, sizeof (XftDraw)); - free (draw); -} - -_X_EXPORT Picture -XftDrawSrcPicture (XftDraw *draw, _Xconst XftColor *color) -{ - Display *dpy = draw->dpy; - XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); - int i; - XftColor bitmapColor; - - if (!info || !info->solidFormat) - return 0; - - /* - * Monochrome targets require special handling; the PictOp controls - * the color, and the color must be opaque - */ - if (!draw->visual && draw->depth == 1) - { - bitmapColor.color.alpha = 0xffff; - bitmapColor.color.red = 0xffff; - bitmapColor.color.green = 0xffff; - bitmapColor.color.blue = 0xffff; - color = &bitmapColor; - } - - /* - * See if there's one already available - */ - for (i = 0; i < XFT_NUM_SOLID_COLOR; i++) - { - if (info->colors[i].pict && - info->colors[i].screen == draw->screen && - !memcmp ((void *) &color->color, - (void *) &info->colors[i].color, - sizeof (XRenderColor))) - return info->colors[i].pict; - } - /* - * Pick one to replace at random - */ - i = (unsigned int) rand () % XFT_NUM_SOLID_COLOR; - /* - * Recreate if it was for the wrong screen - */ - if (info->colors[i].screen != draw->screen && info->colors[i].pict) - { - XRenderFreePicture (dpy, info->colors[i].pict); - info->colors[i].pict = 0; - } - /* - * Create picture if necessary - */ - if (!info->colors[i].pict) - { - Pixmap pix; - XRenderPictureAttributes pa; - - pix = XCreatePixmap (dpy, RootWindow (dpy, draw->screen), 1, 1, - info->solidFormat->depth); - pa.repeat = True; - info->colors[i].pict = XRenderCreatePicture (draw->dpy, - pix, - info->solidFormat, - CPRepeat, &pa); - XFreePixmap (dpy, pix); - } - /* - * Set to the new color - */ - info->colors[i].color = color->color; - info->colors[i].screen = draw->screen; - XRenderFillRectangle (dpy, PictOpSrc, - info->colors[i].pict, - &color->color, 0, 0, 1, 1); - return info->colors[i].pict; -} - -static int -_XftDrawOp (_Xconst XftDraw *draw, _Xconst XftColor *color) -{ - if (draw->visual || draw->depth != 1) - return PictOpOver; - if (color->color.alpha >= 0x8000) - return PictOpOver; - return PictOpOutReverse; -} - -static FcBool -_XftDrawRenderPrepare (XftDraw *draw) -{ - if (!draw->render.pict) - { - XRenderPictFormat *format; - XRenderPictureAttributes pa; - unsigned long mask = 0; - - format = _XftDrawFormat (draw); - if (!format) - return FcFalse; - - if (draw->subwindow_mode == IncludeInferiors) - { - pa.subwindow_mode = IncludeInferiors; - mask |= CPSubwindowMode; - } - draw->render.pict = XRenderCreatePicture (draw->dpy, draw->drawable, - format, mask, &pa); - if (!draw->render.pict) - return FcFalse; - switch (draw->clip_type) { - case XftClipTypeRegion: - XRenderSetPictureClipRegion (draw->dpy, draw->render.pict, - draw->clip.region); - break; - case XftClipTypeRectangles: - XRenderSetPictureClipRectangles (draw->dpy, draw->render.pict, - draw->clip.rect->xOrigin, - draw->clip.rect->yOrigin, - XftClipRects(draw->clip.rect), - draw->clip.rect->n); - break; - case XftClipTypeNone: - break; - } - } - return FcTrue; -} - -static FcBool -_XftDrawCorePrepare (XftDraw *draw, _Xconst XftColor *color) -{ - if (!draw->core.gc) - { - XGCValues gcv; - unsigned long mask = 0; - if (draw->subwindow_mode == IncludeInferiors) - { - gcv.subwindow_mode = IncludeInferiors; - mask |= GCSubwindowMode; - } - draw->core.gc = XCreateGC (draw->dpy, draw->drawable, mask, &gcv); - if (!draw->core.gc) - return FcFalse; - switch (draw->clip_type) { - case XftClipTypeRegion: - XSetRegion (draw->dpy, draw->core.gc, draw->clip.region); - break; - case XftClipTypeRectangles: - XSetClipRectangles (draw->dpy, draw->core.gc, - draw->clip.rect->xOrigin, - draw->clip.rect->yOrigin, - XftClipRects (draw->clip.rect), - draw->clip.rect->n, - Unsorted); - break; - case XftClipTypeNone: - break; - } - } - XSetForeground (draw->dpy, draw->core.gc, color->pixel); - return FcTrue; -} - -_X_EXPORT Picture -XftDrawPicture (XftDraw *draw) -{ - if (!_XftDrawRenderPrepare (draw)) - return 0; - return draw->render.pict; -} - -#define NUM_LOCAL 1024 - -_X_EXPORT void -XftDrawGlyphs (XftDraw *draw, - _Xconst XftColor *color, - XftFont *pub, - int x, - int y, - _Xconst FT_UInt *glyphs, - int nglyphs) -{ - XftFontInt *font = (XftFontInt *) pub; - - if (font->format) - { - Picture src; - - if (_XftDrawRenderPrepare (draw) && - (src = XftDrawSrcPicture (draw, color))) - XftGlyphRender (draw->dpy, _XftDrawOp (draw, color), - src, pub, draw->render.pict, - 0, 0, x, y, glyphs, nglyphs); - } - else - { - if (_XftDrawCorePrepare (draw, color)) - XftGlyphCore (draw, color, pub, x, y, glyphs, nglyphs); - } -} - -_X_EXPORT void -XftDrawString8 (XftDraw *draw, - _Xconst XftColor *color, - XftFont *pub, - int x, - int y, - _Xconst FcChar8 *string, - int len) -{ - FT_UInt *glyphs, glyphs_local[NUM_LOCAL]; - int i; - - if (XftDebug () & XFT_DBG_DRAW) - printf ("DrawString \"%*.*s\"\n", len, len, string); - - if (len <= NUM_LOCAL) - glyphs = glyphs_local; - else - { - glyphs = malloc (len * sizeof (FT_UInt)); - if (!glyphs) - return; - } - for (i = 0; i < len; i++) - glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]); - XftDrawGlyphs (draw, color, pub, x, y, glyphs, len); - if (glyphs != glyphs_local) - free (glyphs); -} - -_X_EXPORT void -XftDrawString16 (XftDraw *draw, - _Xconst XftColor *color, - XftFont *pub, - int x, - int y, - _Xconst FcChar16 *string, - int len) -{ - FT_UInt *glyphs, glyphs_local[NUM_LOCAL]; - int i; - - if (len <= NUM_LOCAL) - glyphs = glyphs_local; - else - { - glyphs = malloc (len * sizeof (FT_UInt)); - if (!glyphs) - return; - } - for (i = 0; i < len; i++) - glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]); - - XftDrawGlyphs (draw, color, pub, x, y, glyphs, len); - if (glyphs != glyphs_local) - free (glyphs); -} - -_X_EXPORT void -XftDrawString32 (XftDraw *draw, - _Xconst XftColor *color, - XftFont *pub, - int x, - int y, - _Xconst FcChar32 *string, - int len) -{ - FT_UInt *glyphs, glyphs_local[NUM_LOCAL]; - int i; - - if (len <= NUM_LOCAL) - glyphs = glyphs_local; - else - { - glyphs = malloc (len * sizeof (FT_UInt)); - if (!glyphs) - return; - } - for (i = 0; i < len; i++) - glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]); - - XftDrawGlyphs (draw, color, pub, x, y, glyphs, len); - if (glyphs != glyphs_local) - free (glyphs); -} - -_X_EXPORT void -XftDrawStringUtf8 (XftDraw *draw, - _Xconst XftColor *color, - XftFont *pub, - int x, - int y, - _Xconst FcChar8 *string, - int len) -{ - FT_UInt *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL]; - FcChar32 ucs4; - int i; - int l; - int size; - - i = 0; - glyphs = glyphs_local; - size = NUM_LOCAL; - while (len && (l = FcUtf8ToUcs4 (string, &ucs4, len)) > 0) - { - if (i == size) - { - glyphs_new = malloc (size * 2 * sizeof (FT_UInt)); - if (!glyphs_new) - { - if (glyphs != glyphs_local) - free (glyphs); - return; - } - memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt)); - size *= 2; - if (glyphs != glyphs_local) - free (glyphs); - glyphs = glyphs_new; - } - glyphs[i++] = XftCharIndex (draw->dpy, pub, ucs4); - string += l; - len -= l; - } - XftDrawGlyphs (draw, color, pub, x, y, glyphs, i); - if (glyphs != glyphs_local) - free (glyphs); -} - -_X_EXPORT void -XftDrawStringUtf16 (XftDraw *draw, - _Xconst XftColor *color, - XftFont *pub, - int x, - int y, - _Xconst FcChar8 *string, - FcEndian endian, - int len) -{ - FT_UInt *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL]; - FcChar32 ucs4; - int i; - int l; - int size; - - i = 0; - glyphs = glyphs_local; - size = NUM_LOCAL; - while (len && (l = FcUtf16ToUcs4 (string, endian, &ucs4, len)) > 0) - { - if (i == size) - { - glyphs_new = malloc (size * 2 * sizeof (FT_UInt)); - if (!glyphs_new) - { - if (glyphs != glyphs_local) - free (glyphs); - return; - } - memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt)); - size *= 2; - if (glyphs != glyphs_local) - free (glyphs); - glyphs = glyphs_new; - } - glyphs[i++] = XftCharIndex (draw->dpy, pub, ucs4); - string += l; - len -= l; - } - XftDrawGlyphs (draw, color, pub, x, y, glyphs, i); - if (glyphs != glyphs_local) - free (glyphs); -} - -_X_EXPORT void -XftDrawGlyphSpec (XftDraw *draw, - _Xconst XftColor *color, - XftFont *pub, - _Xconst XftGlyphSpec *glyphs, - int len) -{ - XftFontInt *font = (XftFontInt *) pub; - - if (font->format) - { - Picture src; - - if (_XftDrawRenderPrepare (draw) && - (src = XftDrawSrcPicture (draw, color))) - { - XftGlyphSpecRender (draw->dpy, _XftDrawOp (draw, color), - src, pub, draw->render.pict, - 0, 0, glyphs, len); - } - } - else - { - if (_XftDrawCorePrepare (draw, color)) - XftGlyphSpecCore (draw, color, pub, glyphs, len); - } -} - -_X_EXPORT void -XftDrawGlyphFontSpec (XftDraw *draw, - _Xconst XftColor *color, - _Xconst XftGlyphFontSpec *glyphs, - int len) -{ - int i; - int start; - - i = 0; - while (i < len) - { - start = i; - if (((XftFontInt *) glyphs[i].font)->format) - { - Picture src; - while (i < len && ((XftFontInt *) glyphs[i].font)->format) - i++; - if (_XftDrawRenderPrepare (draw) && - (src = XftDrawSrcPicture (draw, color))) - { - XftGlyphFontSpecRender (draw->dpy, _XftDrawOp (draw, color), - src, draw->render.pict, - 0, 0, glyphs + start , i - start); - } - } - else - { - while (i < len && !((XftFontInt *) glyphs[i].font)->format) - i++; - if (_XftDrawCorePrepare (draw, color)) - XftGlyphFontSpecCore (draw, color, glyphs + start, i - start); - } - } -} - -_X_EXPORT void -XftDrawCharSpec (XftDraw *draw, - _Xconst XftColor *color, - XftFont *pub, - _Xconst XftCharSpec *chars, - int len) -{ - XftGlyphSpec *glyphs, glyphs_local[NUM_LOCAL]; - int i; - - if (len <= NUM_LOCAL) - glyphs = glyphs_local; - else - { - glyphs = malloc (len * sizeof (XftGlyphSpec)); - if (!glyphs) - return; - } - for (i = 0; i < len; i++) - { - glyphs[i].glyph = XftCharIndex(draw->dpy, pub, chars[i].ucs4); - glyphs[i].x = chars[i].x; - glyphs[i].y = chars[i].y; - } - - XftDrawGlyphSpec (draw, color, pub, glyphs, len); - if (glyphs != glyphs_local) - free (glyphs); -} - -_X_EXPORT void -XftDrawCharFontSpec (XftDraw *draw, - _Xconst XftColor *color, - _Xconst XftCharFontSpec *chars, - int len) -{ - XftGlyphFontSpec *glyphs, glyphs_local[NUM_LOCAL]; - int i; - - if (len <= NUM_LOCAL) - glyphs = glyphs_local; - else - { - glyphs = malloc (len * sizeof (XftGlyphFontSpec)); - if (!glyphs) - return; - } - for (i = 0; i < len; i++) - { - glyphs[i].font = chars[i].font; - glyphs[i].glyph = XftCharIndex(draw->dpy, glyphs[i].font, chars[i].ucs4); - glyphs[i].x = chars[i].x; - glyphs[i].y = chars[i].y; - } - - XftDrawGlyphFontSpec (draw, color, glyphs, len); - if (glyphs != glyphs_local) - free (glyphs); -} - -_X_EXPORT void -XftDrawRect (XftDraw *draw, - _Xconst XftColor *color, - int x, - int y, - unsigned int width, - unsigned int height) -{ - if (_XftDrawRenderPrepare (draw)) - { - XRenderFillRectangle (draw->dpy, PictOpSrc, draw->render.pict, - &color->color, x, y, width, height); - } - else if (_XftDrawCorePrepare (draw, color)) - { - /* note: not XftRectCore() */ - XSetForeground (draw->dpy, draw->core.gc, color->pixel); - XFillRectangle (draw->dpy, draw->drawable, draw->core.gc, - x, y, width, height); - } -} - -_X_EXPORT Bool -XftDrawSetClip (XftDraw *draw, - Region r) -{ - Region n = NULL; - - /* - * Check for quick exits - */ - if (!r && draw->clip_type == XftClipTypeNone) - return True; - - if (r && - draw->clip_type == XftClipTypeRegion && - XEqualRegion (r, draw->clip.region)) - { - return True; - } - - /* - * Duplicate the region so future changes can be short circuited - */ - if (r) - { - n = XCreateRegion (); - if (n) - { - if (!XUnionRegion (n, r, n)) - { - XDestroyRegion (n); - return False; - } - } - } - - /* - * Destroy existing clip - */ - switch (draw->clip_type) { - case XftClipTypeRegion: - XDestroyRegion (draw->clip.region); - break; - case XftClipTypeRectangles: - free (draw->clip.rect); - break; - case XftClipTypeNone: - break; - } - - /* - * Set the clip - */ - if (n) - { - draw->clip_type = XftClipTypeRegion; - draw->clip.region = n; - } - else - { - draw->clip_type = XftClipTypeNone; - } - /* - * Apply new clip to existing objects - */ - if (draw->render.pict) - { - if (n) - XRenderSetPictureClipRegion (draw->dpy, draw->render.pict, n); - else - { - XRenderPictureAttributes pa; - pa.clip_mask = None; - XRenderChangePicture (draw->dpy, draw->render.pict, - CPClipMask, &pa); - } - } - if (draw->core.gc) - { - if (n) - XSetRegion (draw->dpy, draw->core.gc, draw->clip.region); - else - XSetClipMask (draw->dpy, draw->core.gc, None); - } - return True; -} - -_X_EXPORT Bool -XftDrawSetClipRectangles (XftDraw *draw, - int xOrigin, - int yOrigin, - _Xconst XRectangle *rects, - int n) -{ - XftClipRect *new = NULL; - - /* - * Check for quick exit - */ - if (draw->clip_type == XftClipTypeRectangles && - draw->clip.rect->n == n && - (n == 0 || (draw->clip.rect->xOrigin == xOrigin && - draw->clip.rect->yOrigin == yOrigin)) && - !memcmp (XftClipRects (draw->clip.rect), rects, n * sizeof (XRectangle))) - { - return True; - } - - /* - * Duplicate the region so future changes can be short circuited - */ - new = malloc (sizeof (XftClipRect) + n * sizeof (XRectangle)); - if (!new) - return False; - - new->n = n; - new->xOrigin = xOrigin; - new->yOrigin = yOrigin; - memcpy (XftClipRects (new), rects, n * sizeof (XRectangle)); - - /* - * Destroy existing clip - */ - switch (draw->clip_type) { - case XftClipTypeRegion: - XDestroyRegion (draw->clip.region); - break; - case XftClipTypeRectangles: - free (draw->clip.rect); - break; - case XftClipTypeNone: - break; - } - - /* - * Set the clip - */ - draw->clip_type = XftClipTypeRectangles; - draw->clip.rect = new; - /* - * Apply new clip to existing objects - */ - if (draw->render.pict) - { - XRenderSetPictureClipRectangles (draw->dpy, draw->render.pict, - new->xOrigin, - new->yOrigin, - XftClipRects(new), - new->n); - } - if (draw->core.gc) - { - XSetClipRectangles (draw->dpy, draw->core.gc, - new->xOrigin, - new->yOrigin, - XftClipRects (new), - new->n, - Unsorted); - } - return True; -} - -_X_EXPORT void -XftDrawSetSubwindowMode (XftDraw *draw, int mode) -{ - if (mode == draw->subwindow_mode) - return; - draw->subwindow_mode = mode; - if (draw->render.pict) - { - XRenderPictureAttributes pa; - - pa.subwindow_mode = mode; - XRenderChangePicture (draw->dpy, draw->render.pict, - CPSubwindowMode, &pa); - } - if (draw->core.gc) - XSetSubwindowMode (draw->dpy, draw->core.gc, mode); -} +/* + * Copyright © 2000 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "xftint.h" + +/* + * Ok, this is a pain. To share source pictures across multiple destinations, + * the screen for each drawable must be discovered. + */ + +static int +_XftDrawScreen (Display *dpy, Drawable drawable, Visual *visual) +{ + int s; + Window root; + int x, y; + unsigned int width, height, borderWidth, depth; + /* Special case the most common environment */ + if (ScreenCount (dpy) == 1) + return 0; + /* + * If we've got a visual, look for the screen that points at it. + * This requires no round trip. + */ + if (visual) + { + for (s = 0; s < ScreenCount (dpy); s++) + { + XVisualInfo template, *ret; + int nret; + + template.visualid = visual->visualid; + template.screen = s; + ret = XGetVisualInfo (dpy, VisualIDMask|VisualScreenMask, + &template, &nret); + if (ret) + { + XFree (ret); + return s; + } + } + } + /* + * Otherwise, as the server for the drawable geometry and find + * the screen from the root window. + * This takes a round trip. + */ + if (XGetGeometry (dpy, drawable, &root, &x, &y, &width, &height, + &borderWidth, &depth)) + { + for (s = 0; s < ScreenCount (dpy); s++) + { + if (RootWindow (dpy, s) == root) + return s; + } + } + /* + * Make a guess -- it's probably wrong, but then the app probably + * handed us a bogus drawable in this case + */ + return 0; +} + +_X_HIDDEN unsigned int +XftDrawDepth (XftDraw *draw) +{ + if (!draw->depth) + { + Window root; + int x, y; + unsigned int width, height, borderWidth, depth; + if (XGetGeometry (draw->dpy, draw->drawable, + &root, &x, &y, &width, &height, + &borderWidth, &depth)) + draw->depth = depth; + } + return draw->depth; +} + +_X_HIDDEN unsigned int +XftDrawBitsPerPixel (XftDraw *draw) +{ + if (!draw->bits_per_pixel) + { + XPixmapFormatValues *formats; + int nformats; + unsigned int depth; + + if ((depth = XftDrawDepth (draw)) && + (formats = XListPixmapFormats (draw->dpy, &nformats))) + { + int i; + + for (i = 0; i < nformats; i++) + { + if (formats[i].depth == depth) + { + draw->bits_per_pixel = formats[i].bits_per_pixel; + break; + } + } + XFree (formats); + } + } + return draw->bits_per_pixel; +} + +_X_EXPORT XftDraw * +XftDrawCreate (Display *dpy, + Drawable drawable, + Visual *visual, + Colormap colormap) +{ + XftDraw *draw; + + draw = (XftDraw *) malloc (sizeof (XftDraw)); + if (!draw) + return NULL; + + draw->dpy = dpy; + draw->drawable = drawable; + draw->screen = _XftDrawScreen (dpy, drawable, visual); + draw->depth = 0; /* don't find out unless we need to know */ + draw->bits_per_pixel = 0; /* don't find out unless we need to know */ + draw->visual = visual; + draw->colormap = colormap; + draw->render.pict = 0; + draw->core.gc = NULL; + draw->core.use_pixmap = 0; + draw->clip_type = XftClipTypeNone; + draw->subwindow_mode = ClipByChildren; + XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw)); + return draw; +} + +_X_EXPORT XftDraw * +XftDrawCreateBitmap (Display *dpy, + Pixmap bitmap) +{ + XftDraw *draw; + + draw = (XftDraw *) malloc (sizeof (XftDraw)); + if (!draw) + return NULL; + draw->dpy = dpy; + draw->drawable = (Drawable) bitmap; + draw->screen = _XftDrawScreen (dpy, bitmap, NULL); + draw->depth = 1; + draw->bits_per_pixel = 1; + draw->visual = NULL; + draw->colormap = 0; + draw->render.pict = 0; + draw->core.gc = NULL; + draw->core.use_pixmap = 0; + draw->clip_type = XftClipTypeNone; + draw->subwindow_mode = ClipByChildren; + XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw)); + return draw; +} + +_X_EXPORT XftDraw * +XftDrawCreateAlpha (Display *dpy, + Pixmap pixmap, + int depth) +{ + XftDraw *draw; + + draw = (XftDraw *) malloc (sizeof (XftDraw)); + if (!draw) + return NULL; + draw->dpy = dpy; + draw->drawable = (Drawable) pixmap; + draw->screen = _XftDrawScreen (dpy, pixmap, NULL); + draw->depth = depth; + draw->bits_per_pixel = 0; /* don't find out until we need it */ + draw->visual = NULL; + draw->colormap = 0; + draw->render.pict = 0; + draw->core.gc = NULL; + draw->core.use_pixmap = 0; + draw->clip_type = XftClipTypeNone; + draw->subwindow_mode = ClipByChildren; + XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw)); + return draw; +} + +static XRenderPictFormat * +_XftDrawFormat (XftDraw *draw) +{ + XftDisplayInfo *info = _XftDisplayInfoGet (draw->dpy, True); + + if (!info || !info->hasRender) + return NULL; + + if (draw->visual == NULL) + { + XRenderPictFormat pf; + + pf.type = PictTypeDirect; + pf.depth = XftDrawDepth (draw); + pf.direct.alpha = 0; + pf.direct.alphaMask = (1 << pf.depth) - 1; + return XRenderFindFormat (draw->dpy, + (PictFormatType| + PictFormatDepth| + PictFormatAlpha| + PictFormatAlphaMask), + &pf, + 0); + } + else + return XRenderFindVisualFormat (draw->dpy, draw->visual); +} + +_X_EXPORT void +XftDrawChange (XftDraw *draw, + Drawable drawable) +{ + draw->drawable = drawable; + if (draw->render.pict) + { + XRenderFreePicture (draw->dpy, draw->render.pict); + draw->render.pict = 0; + } + if (draw->core.gc) + { + XFreeGC (draw->dpy, draw->core.gc); + draw->core.gc = NULL; + } +} + +_X_EXPORT Display * +XftDrawDisplay (XftDraw *draw) +{ + return draw->dpy; +} + +_X_EXPORT Drawable +XftDrawDrawable (XftDraw *draw) +{ + return draw->drawable; +} + +_X_EXPORT Colormap +XftDrawColormap (XftDraw *draw) +{ + return draw->colormap; +} + +_X_EXPORT Visual * +XftDrawVisual (XftDraw *draw) +{ + return draw->visual; +} + +_X_EXPORT void +XftDrawDestroy (XftDraw *draw) +{ + if (draw->render.pict) + XRenderFreePicture (draw->dpy, draw->render.pict); + if (draw->core.gc) + XFreeGC (draw->dpy, draw->core.gc); + switch (draw->clip_type) { + case XftClipTypeRegion: + XDestroyRegion (draw->clip.region); + break; + case XftClipTypeRectangles: + free (draw->clip.rect); + break; + case XftClipTypeNone: + break; + } + XftMemFree (XFT_MEM_DRAW, sizeof (XftDraw)); + free (draw); +} + +_X_EXPORT Picture +XftDrawSrcPicture (XftDraw *draw, _Xconst XftColor *color) +{ + Display *dpy = draw->dpy; + XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); + int i; + XftColor bitmapColor; + + if (!info || !info->solidFormat) + return 0; + + /* + * Monochrome targets require special handling; the PictOp controls + * the color, and the color must be opaque + */ + if (!draw->visual && draw->depth == 1) + { + bitmapColor.color.alpha = 0xffff; + bitmapColor.color.red = 0xffff; + bitmapColor.color.green = 0xffff; + bitmapColor.color.blue = 0xffff; + color = &bitmapColor; + } + + /* + * See if there's one already available + */ + for (i = 0; i < XFT_NUM_SOLID_COLOR; i++) + { + if (info->colors[i].pict && + info->colors[i].screen == draw->screen && + !memcmp ((void *) &color->color, + (void *) &info->colors[i].color, + sizeof (XRenderColor))) + return info->colors[i].pict; + } + /* + * Pick one to replace at random + */ + i = (unsigned int) rand () % XFT_NUM_SOLID_COLOR; + /* + * Recreate if it was for the wrong screen + */ + if (info->colors[i].screen != draw->screen && info->colors[i].pict) + { + XRenderFreePicture (dpy, info->colors[i].pict); + info->colors[i].pict = 0; + } + /* + * Create picture if necessary + */ + if (!info->colors[i].pict) + { + Pixmap pix; + XRenderPictureAttributes pa; + + pix = XCreatePixmap (dpy, RootWindow (dpy, draw->screen), 1, 1, + info->solidFormat->depth); + pa.repeat = True; + info->colors[i].pict = XRenderCreatePicture (draw->dpy, + pix, + info->solidFormat, + CPRepeat, &pa); + XFreePixmap (dpy, pix); + } + /* + * Set to the new color + */ + info->colors[i].color = color->color; + info->colors[i].screen = draw->screen; + XRenderFillRectangle (dpy, PictOpSrc, + info->colors[i].pict, + &color->color, 0, 0, 1, 1); + return info->colors[i].pict; +} + +static int +_XftDrawOp (_Xconst XftDraw *draw, _Xconst XftColor *color) +{ + if (draw->visual || draw->depth != 1) + return PictOpOver; + if (color->color.alpha >= 0x8000) + return PictOpOver; + return PictOpOutReverse; +} + +static FcBool +_XftDrawRenderPrepare (XftDraw *draw) +{ + if (!draw->render.pict) + { + XRenderPictFormat *format; + XRenderPictureAttributes pa; + unsigned long mask = 0; + + format = _XftDrawFormat (draw); + if (!format) + return FcFalse; + + if (draw->subwindow_mode == IncludeInferiors) + { + pa.subwindow_mode = IncludeInferiors; + mask |= CPSubwindowMode; + } + draw->render.pict = XRenderCreatePicture (draw->dpy, draw->drawable, + format, mask, &pa); + if (!draw->render.pict) + return FcFalse; + switch (draw->clip_type) { + case XftClipTypeRegion: + XRenderSetPictureClipRegion (draw->dpy, draw->render.pict, + draw->clip.region); + break; + case XftClipTypeRectangles: + XRenderSetPictureClipRectangles (draw->dpy, draw->render.pict, + draw->clip.rect->xOrigin, + draw->clip.rect->yOrigin, + XftClipRects(draw->clip.rect), + draw->clip.rect->n); + break; + case XftClipTypeNone: + break; + } + } + return FcTrue; +} + +static FcBool +_XftDrawCorePrepare (XftDraw *draw, _Xconst XftColor *color) +{ + if (!draw->core.gc) + { + XGCValues gcv; + unsigned long mask = 0; + if (draw->subwindow_mode == IncludeInferiors) + { + gcv.subwindow_mode = IncludeInferiors; + mask |= GCSubwindowMode; + } + draw->core.gc = XCreateGC (draw->dpy, draw->drawable, mask, &gcv); + if (!draw->core.gc) + return FcFalse; + switch (draw->clip_type) { + case XftClipTypeRegion: + XSetRegion (draw->dpy, draw->core.gc, draw->clip.region); + break; + case XftClipTypeRectangles: + XSetClipRectangles (draw->dpy, draw->core.gc, + draw->clip.rect->xOrigin, + draw->clip.rect->yOrigin, + XftClipRects (draw->clip.rect), + draw->clip.rect->n, + Unsorted); + break; + case XftClipTypeNone: + break; + } + } + XSetForeground (draw->dpy, draw->core.gc, color->pixel); + return FcTrue; +} + +_X_EXPORT Picture +XftDrawPicture (XftDraw *draw) +{ + if (!_XftDrawRenderPrepare (draw)) + return 0; + return draw->render.pict; +} + +#define NUM_LOCAL 1024 + +_X_EXPORT void +XftDrawGlyphs (XftDraw *draw, + _Xconst XftColor *color, + XftFont *pub, + int x, + int y, + _Xconst FT_UInt *glyphs, + int nglyphs) +{ + XftFontInt *font = (XftFontInt *) pub; + + if (font->format) + { + Picture src; + + if (_XftDrawRenderPrepare (draw) && + (src = XftDrawSrcPicture (draw, color))) + XftGlyphRender (draw->dpy, _XftDrawOp (draw, color), + src, pub, draw->render.pict, + 0, 0, x, y, glyphs, nglyphs); + } + else + { + if (_XftDrawCorePrepare (draw, color)) + XftGlyphCore (draw, color, pub, x, y, glyphs, nglyphs); + } +} + +_X_EXPORT void +XftDrawString8 (XftDraw *draw, + _Xconst XftColor *color, + XftFont *pub, + int x, + int y, + _Xconst FcChar8 *string, + int len) +{ + FT_UInt *glyphs, glyphs_local[NUM_LOCAL]; + int i; + + if (XftDebug () & XFT_DBG_DRAW) + printf ("DrawString \"%*.*s\"\n", len, len, string); + + if (len <= NUM_LOCAL) + glyphs = glyphs_local; + else + { + glyphs = malloc (len * sizeof (FT_UInt)); + if (!glyphs) + return; + } + for (i = 0; i < len; i++) + glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]); + XftDrawGlyphs (draw, color, pub, x, y, glyphs, len); + if (glyphs != glyphs_local) + free (glyphs); +} + +_X_EXPORT void +XftDrawString16 (XftDraw *draw, + _Xconst XftColor *color, + XftFont *pub, + int x, + int y, + _Xconst FcChar16 *string, + int len) +{ + FT_UInt *glyphs, glyphs_local[NUM_LOCAL]; + int i; + + if (len <= NUM_LOCAL) + glyphs = glyphs_local; + else + { + glyphs = malloc (len * sizeof (FT_UInt)); + if (!glyphs) + return; + } + for (i = 0; i < len; i++) + glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]); + + XftDrawGlyphs (draw, color, pub, x, y, glyphs, len); + if (glyphs != glyphs_local) + free (glyphs); +} + +_X_EXPORT void +XftDrawString32 (XftDraw *draw, + _Xconst XftColor *color, + XftFont *pub, + int x, + int y, + _Xconst FcChar32 *string, + int len) +{ + FT_UInt *glyphs, glyphs_local[NUM_LOCAL]; + int i; + + if (len <= NUM_LOCAL) + glyphs = glyphs_local; + else + { + glyphs = malloc (len * sizeof (FT_UInt)); + if (!glyphs) + return; + } + for (i = 0; i < len; i++) + glyphs[i] = XftCharIndex (draw->dpy, pub, string[i]); + + XftDrawGlyphs (draw, color, pub, x, y, glyphs, len); + if (glyphs != glyphs_local) + free (glyphs); +} + +_X_EXPORT void +XftDrawStringUtf8 (XftDraw *draw, + _Xconst XftColor *color, + XftFont *pub, + int x, + int y, + _Xconst FcChar8 *string, + int len) +{ + FT_UInt *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL]; + FcChar32 ucs4; + int i; + int l; + int size; + + i = 0; + glyphs = glyphs_local; + size = NUM_LOCAL; + while (len && (l = FcUtf8ToUcs4 (string, &ucs4, len)) > 0) + { + if (i == size) + { + glyphs_new = malloc (size * 2 * sizeof (FT_UInt)); + if (!glyphs_new) + { + if (glyphs != glyphs_local) + free (glyphs); + return; + } + memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt)); + size *= 2; + if (glyphs != glyphs_local) + free (glyphs); + glyphs = glyphs_new; + } + glyphs[i++] = XftCharIndex (draw->dpy, pub, ucs4); + string += l; + len -= l; + } + XftDrawGlyphs (draw, color, pub, x, y, glyphs, i); + if (glyphs != glyphs_local) + free (glyphs); +} + +_X_EXPORT void +XftDrawStringUtf16 (XftDraw *draw, + _Xconst XftColor *color, + XftFont *pub, + int x, + int y, + _Xconst FcChar8 *string, + FcEndian endian, + int len) +{ + FT_UInt *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL]; + FcChar32 ucs4; + int i; + int l; + int size; + + i = 0; + glyphs = glyphs_local; + size = NUM_LOCAL; + while (len && (l = FcUtf16ToUcs4 (string, endian, &ucs4, len)) > 0) + { + if (i == size) + { + glyphs_new = malloc (size * 2 * sizeof (FT_UInt)); + if (!glyphs_new) + { + if (glyphs != glyphs_local) + free (glyphs); + return; + } + memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt)); + size *= 2; + if (glyphs != glyphs_local) + free (glyphs); + glyphs = glyphs_new; + } + glyphs[i++] = XftCharIndex (draw->dpy, pub, ucs4); + string += l; + len -= l; + } + XftDrawGlyphs (draw, color, pub, x, y, glyphs, i); + if (glyphs != glyphs_local) + free (glyphs); +} + +_X_EXPORT void +XftDrawGlyphSpec (XftDraw *draw, + _Xconst XftColor *color, + XftFont *pub, + _Xconst XftGlyphSpec *glyphs, + int len) +{ + XftFontInt *font = (XftFontInt *) pub; + + if (font->format) + { + Picture src; + + if (_XftDrawRenderPrepare (draw) && + (src = XftDrawSrcPicture (draw, color))) + { + XftGlyphSpecRender (draw->dpy, _XftDrawOp (draw, color), + src, pub, draw->render.pict, + 0, 0, glyphs, len); + } + } + else + { + if (_XftDrawCorePrepare (draw, color)) + XftGlyphSpecCore (draw, color, pub, glyphs, len); + } +} + +_X_EXPORT void +XftDrawGlyphFontSpec (XftDraw *draw, + _Xconst XftColor *color, + _Xconst XftGlyphFontSpec *glyphs, + int len) +{ + int i; + int start; + + i = 0; + while (i < len) + { + start = i; + if (((XftFontInt *) glyphs[i].font)->format) + { + Picture src; + while (i < len && ((XftFontInt *) glyphs[i].font)->format) + i++; + if (_XftDrawRenderPrepare (draw) && + (src = XftDrawSrcPicture (draw, color))) + { + XftGlyphFontSpecRender (draw->dpy, _XftDrawOp (draw, color), + src, draw->render.pict, + 0, 0, glyphs + start , i - start); + } + } + else + { + while (i < len && !((XftFontInt *) glyphs[i].font)->format) + i++; + if (_XftDrawCorePrepare (draw, color)) + XftGlyphFontSpecCore (draw, color, glyphs + start, i - start); + } + } +} + +_X_EXPORT void +XftDrawCharSpec (XftDraw *draw, + _Xconst XftColor *color, + XftFont *pub, + _Xconst XftCharSpec *chars, + int len) +{ + XftGlyphSpec *glyphs, glyphs_local[NUM_LOCAL]; + int i; + + if (len <= NUM_LOCAL) + glyphs = glyphs_local; + else + { + glyphs = malloc (len * sizeof (XftGlyphSpec)); + if (!glyphs) + return; + } + for (i = 0; i < len; i++) + { + glyphs[i].glyph = XftCharIndex(draw->dpy, pub, chars[i].ucs4); + glyphs[i].x = chars[i].x; + glyphs[i].y = chars[i].y; + } + + XftDrawGlyphSpec (draw, color, pub, glyphs, len); + if (glyphs != glyphs_local) + free (glyphs); +} + +_X_EXPORT void +XftDrawCharFontSpec (XftDraw *draw, + _Xconst XftColor *color, + _Xconst XftCharFontSpec *chars, + int len) +{ + XftGlyphFontSpec *glyphs, glyphs_local[NUM_LOCAL]; + int i; + + if (len <= NUM_LOCAL) + glyphs = glyphs_local; + else + { + glyphs = malloc (len * sizeof (XftGlyphFontSpec)); + if (!glyphs) + return; + } + for (i = 0; i < len; i++) + { + glyphs[i].font = chars[i].font; + glyphs[i].glyph = XftCharIndex(draw->dpy, glyphs[i].font, chars[i].ucs4); + glyphs[i].x = chars[i].x; + glyphs[i].y = chars[i].y; + } + + XftDrawGlyphFontSpec (draw, color, glyphs, len); + if (glyphs != glyphs_local) + free (glyphs); +} + +_X_EXPORT void +XftDrawRect (XftDraw *draw, + _Xconst XftColor *color, + int x, + int y, + unsigned int width, + unsigned int height) +{ + if (_XftDrawRenderPrepare (draw)) + { + XRenderFillRectangle (draw->dpy, PictOpSrc, draw->render.pict, + &color->color, x, y, width, height); + } + else if (_XftDrawCorePrepare (draw, color)) + { + /* note: not XftRectCore() */ + XSetForeground (draw->dpy, draw->core.gc, color->pixel); + XFillRectangle (draw->dpy, draw->drawable, draw->core.gc, + x, y, width, height); + } +} + +_X_EXPORT Bool +XftDrawSetClip (XftDraw *draw, + Region r) +{ + Region n = NULL; + + /* + * Check for quick exits + */ + if (!r && draw->clip_type == XftClipTypeNone) + return True; + + if (r && + draw->clip_type == XftClipTypeRegion && + XEqualRegion (r, draw->clip.region)) + { + return True; + } + + /* + * Duplicate the region so future changes can be short circuited + */ + if (r) + { + n = XCreateRegion (); + if (n) + { + if (!XUnionRegion (n, r, n)) + { + XDestroyRegion (n); + return False; + } + } + } + + /* + * Destroy existing clip + */ + switch (draw->clip_type) { + case XftClipTypeRegion: + XDestroyRegion (draw->clip.region); + break; + case XftClipTypeRectangles: + free (draw->clip.rect); + break; + case XftClipTypeNone: + break; + } + + /* + * Set the clip + */ + if (n) + { + draw->clip_type = XftClipTypeRegion; + draw->clip.region = n; + } + else + { + draw->clip_type = XftClipTypeNone; + } + /* + * Apply new clip to existing objects + */ + if (draw->render.pict) + { + if (n) + XRenderSetPictureClipRegion (draw->dpy, draw->render.pict, n); + else + { + XRenderPictureAttributes pa; + pa.clip_mask = None; + XRenderChangePicture (draw->dpy, draw->render.pict, + CPClipMask, &pa); + } + } + if (draw->core.gc) + { + if (n) + XSetRegion (draw->dpy, draw->core.gc, draw->clip.region); + else + XSetClipMask (draw->dpy, draw->core.gc, None); + } + return True; +} + +_X_EXPORT Bool +XftDrawSetClipRectangles (XftDraw *draw, + int xOrigin, + int yOrigin, + _Xconst XRectangle *rects, + int n) +{ + XftClipRect *new = NULL; + + /* + * Check for quick exit + */ + if (draw->clip_type == XftClipTypeRectangles && + draw->clip.rect->n == n && + (n == 0 || (draw->clip.rect->xOrigin == xOrigin && + draw->clip.rect->yOrigin == yOrigin)) && + !memcmp (XftClipRects (draw->clip.rect), rects, n * sizeof (XRectangle))) + { + return True; + } + + /* + * Duplicate the region so future changes can be short circuited + */ + new = malloc (sizeof (XftClipRect) + n * sizeof (XRectangle)); + if (!new) + return False; + + new->n = n; + new->xOrigin = xOrigin; + new->yOrigin = yOrigin; + memcpy (XftClipRects (new), rects, n * sizeof (XRectangle)); + + /* + * Destroy existing clip + */ + switch (draw->clip_type) { + case XftClipTypeRegion: + XDestroyRegion (draw->clip.region); + break; + case XftClipTypeRectangles: + free (draw->clip.rect); + break; + case XftClipTypeNone: + break; + } + + /* + * Set the clip + */ + draw->clip_type = XftClipTypeRectangles; + draw->clip.rect = new; + /* + * Apply new clip to existing objects + */ + if (draw->render.pict) + { + XRenderSetPictureClipRectangles (draw->dpy, draw->render.pict, + new->xOrigin, + new->yOrigin, + XftClipRects(new), + new->n); + } + if (draw->core.gc) + { + XSetClipRectangles (draw->dpy, draw->core.gc, + new->xOrigin, + new->yOrigin, + XftClipRects (new), + new->n, + Unsorted); + } + return True; +} + +_X_EXPORT void +XftDrawSetSubwindowMode (XftDraw *draw, int mode) +{ + if (mode == draw->subwindow_mode) + return; + draw->subwindow_mode = mode; + if (draw->render.pict) + { + XRenderPictureAttributes pa; + + pa.subwindow_mode = mode; + XRenderChangePicture (draw->dpy, draw->render.pict, + CPSubwindowMode, &pa); + } + if (draw->core.gc) + XSetSubwindowMode (draw->dpy, draw->core.gc, mode); +} -- cgit v1.2.3