summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rw-r--r--configure.in68
-rw-r--r--src/Makefile.am44
-rw-r--r--src/vte.c23
-rw-r--r--src/vteapp.c10
-rw-r--r--src/vtedraw.c44
-rw-r--r--src/vtedraw.h12
-rw-r--r--src/vtefc.c13
-rw-r--r--src/vteft2.c338
-rw-r--r--src/vteft2.h35
-rw-r--r--src/vtegl.c414
-rw-r--r--src/vtegl.h35
-rw-r--r--src/vteglyph.c728
-rw-r--r--src/vteglyph.h86
-rw-r--r--src/vtepango.c42
-rw-r--r--src/vtepangox.c466
-rw-r--r--src/vtepangox.h35
-rw-r--r--src/vtergb.c260
-rw-r--r--src/vtergb.h52
-rw-r--r--src/vteskel.c35
-rw-r--r--src/vtexft.c39
-rw-r--r--vte.pc.in2
-rw-r--r--vte.spec6
23 files changed, 2681 insertions, 125 deletions
diff --git a/ChangeLog b/ChangeLog
index d4b0f9f..ef2e427 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2003-04-09 nalin
+ * configure.in: add specific checks for PangoX and glX.
+ * src/vteft2.c, src/vteft2.h: add drawing method using freetype and
+ GdkRGB.
+ * src/vteglyph.c, src/vteglyph.h: add.
+ * src/vtepangox.c, src/vtepangox.h: add drawing method using PangoX.
+ * src/vtergb.c, src/vtergb.h: add.
+ * src/vtegl.c, src/vtegl.h: add placeholder drawing method using
+ freetype and glX.
+ * src/Makefile.am: add newly-added source files to libvte.la target.
+ * src/vtedraw.c, src/vtedraw.h: add get_visual and get_colormap
+ methods so that drawing methods can override the default visual and
+ colormap. Rename get_text_base() to get_text_ascent(), which is more
+ correct. Remove scroll(), which would just wrap gdk_window_scroll().
+ * src/vte.c: fix logic for choosing alternate render methods when
+ VTE_USE_XFT is "0".
+ * src/vteapp.c: add -- option to stop parsing options with getopt.
+ * src/vtefc.c: fix incorrect DPI read due to type mismatch (#109513).
+
2003-03-31 Laurent Dhima <laurenti@alblinux.net>
* configure.in: Added "sq" to ALL_LINGUAS.
diff --git a/configure.in b/configure.in
index 42cda0a..52f9937 100644
--- a/configure.in
+++ b/configure.in
@@ -17,23 +17,64 @@ AM_GLIB_GNU_GETTEXT
# X_PRE_LIBS and X_EXTRA_LIBS to add even more libraries, and add -lX11 to
# the list of libraries for grins.
AC_PATH_XTRA
-HAVE_XFT=no
-X_LIBS="$X_PRE_LIBS $X_LIBS -lX11 $X_EXTRA_LIBS"
-PKG_CHECK_MODULES(GOBJECT,[glib-2.0 gobject-2.0])
+X_LIBS=
+if test $with_x = yes ; then
+ X_LIBS="$X_PRE_LIBS $X_LIBS -lX11 $X_EXTRA_LIBS"
+fi
+
savelibs="$LIBS"
LIBS="$X_LIBS $LIBS"
+PKG_CHECK_MODULES(GLIB,glib-2.0)
+PKG_CHECK_MODULES(GOBJECT,[glib-2.0 gobject-2.0])
+PKG_CHECK_MODULES(GTK,[glib-2.0 gobject-2.0 gtk+-2.0])
+
# Require GTK+ 2.0 and fontconfig.
-wantedmodules="glib-2.0 gobject-2.0 gdk-pixbuf-2.0 gtk+-2.0 fontconfig"
-# Use Xft2 if Pango has Xft2 support.
-if pkg-config --exists pangoxft '>=' 1.1.0 ; then
- AC_DEFINE(HAVE_XFT2,1,[Whether we have Xft2])
- wantedmodules="$wantedmodules xft"
-else
- AC_MSG_WARN([Xft2 not detected])
+wantedmodules="glib-2.0 gobject-2.0 gtk+-2.0 fontconfig"
+
+# Use Xft2 if Pango has Xft2 support and it isn't disabled.
+AC_ARG_WITH(xft2,[ --with-xft2 enable drawing using Xft2],with_xft2=$withval,with_xft2=yes)
+if test $with_xft2 = yes ; then
+ if pkg-config --exists pangoxft '>=' 1.1.0 ; then
+ AC_DEFINE(HAVE_XFT2,1,[Whether we have Xft2])
+ wantedmodules="$wantedmodules pangoxft >= 1.1.0 xft >= 2.0"
+ else
+ AC_MSG_WARN([Xft2 not detected])
+ fi
+fi
+
+# Use PangoX if we have it and it isn't disabled.
+AC_ARG_WITH(pangox,[ --with-pangox enable drawing using PangoX],with_pangox=$withval,with_pangox=yes)
+if test $with_pangox = yes ; then
+ if pkg-config --exists pangox ; then
+ AC_DEFINE(HAVE_PANGOX,1,[Whether we have PangoX])
+ wantedmodules="$wantedmodules pangox"
+ else
+ AC_MSG_WARN([PangoX not detected])
+ fi
fi
+
+# Use glX if we have it and it isn't disabled.
+AC_ARG_WITH(glX,[ --with-glX enable drawing using glX],with_glx=$withval,with_glx=yes)
+if test $with_glx = yes ; then
+ have_gl=0
+ have_libgl=0
+ AC_CHECK_HEADERS(GL/glx.h)
+ if test $ac_cv_header_GL_glx_h = yes ; then
+ AC_CHECK_FUNC(glXQueryExtension,[have_gl=1],AC_CHECK_LIB(GL,glXQueryExtension,[have_gl=1;have_libgl=1]))
+ fi
+ if test $have_gl = 1 ; then
+ AC_DEFINE(HAVE_GL,1,[Whether we have GL and glX.])
+ fi
+ if test $have_libgl = 1 ; then
+ LIBS="-lGLU -lGL $LIBS"
+ fi
+fi
+
# Search for the required modules.
PKG_CHECK_MODULES(VTE,[$wantedmodules])
+NEEDEDPACKAGES="$wantedmodules"
+AC_SUBST(NEEDEDPACKAGES)
# Require Freetype2. We use our local copy of the macro because packages of
# freetype's development files don't always include the proper macro.
@@ -53,24 +94,28 @@ AC_CHECK_DECLS(FT_RENDER_MODE_MONO,,,[
#include FT_FREETYPE_H
#endif
])
+
AC_CHECK_DECLS(FT_LOAD_NO_HINTING,,,[
#ifdef HAVE_FT2BUILD_H
#include <ft2build.h>
#include FT_FREETYPE_H
#endif
])
+
AC_CHECK_DECLS(FT_RENDER_MODE_LIGHT,,,[
#ifdef HAVE_FT2BUILD_H
#include <ft2build.h>
#include FT_FREETYPE_H
#endif
])
+
AC_CHECK_DECLS(FT_RENDER_MODE_NORMAL,,,[
#ifdef HAVE_FT2BUILD_H
#include <ft2build.h>
#include FT_FREETYPE_H
#endif
])
+
CFLAGS="$savecflags"
CPPFLAGS="$savecppflags"
@@ -84,6 +129,7 @@ AC_EGREP_CPP(glibc,
#endif
],
AC_DEFINE(_GNU_SOURCE,1,[Use all features.]))
+
AC_DEFINE(G_DISABLE_DEPRECATED,1,[Disable deprecated GLib features.])
AC_DEFINE(GDK_DISABLE_DEPRECATED,1,[Disable deprecated GDK features.])
AC_DEFINE(GDK_PIXBUF_DISABLE_DEPRECATED,1,[Disable deprecated gdk-pixbuf features.])
@@ -110,7 +156,7 @@ fi
if test x$have_socketpair = x1 ; then
AC_DEFINE(HAVE_SOCKETPAIR,1,[Define if you have the socketpair function.])
fi
-
+AC_CHECK_FUNC(floor,,AC_CHECK_LIB(m,floor,LIBS=["$LIBS -lm"]))
# Look for ncurses or curses or termcap.
AC_CHECK_HEADER(ncurses.h,[AC_CHECK_HEADER(term.h,[AC_CHECK_LIB(ncurses,tgetent,[LIBS="-lncurses $LIBS";AC_DEFINE(HAVE_NCURSES,1,[Define if you have ncurses.h and libncurses])])])])
diff --git a/src/Makefile.am b/src/Makefile.am
index cc3d060..d9b1f8e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -60,8 +60,18 @@ libvte_la_SOURCES = \
vtedraw.h \
vtefc.c \
vtefc.h \
+ vteft2.c \
+ vteft2.h \
+ vtegl.c \
+ vtegl.h \
+ vteglyph.c \
+ vteglyph.h \
vtepango.c \
vtepango.h \
+ vtepangox.c \
+ vtepangox.h \
+ vtergb.c \
+ vtergb.h \
vteskel.c \
vteskel.h \
vtexft.c \
@@ -98,7 +108,7 @@ else
REFLECT_ZVT =
endif
-interpret_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ @VTE_CFLAGS@ -DINTERPRET_MAIN
+interpret_CFLAGS = @CFLAGS@ @GTK_CFLAGS@ -DINTERPRET_MAIN
interpret_SOURCES = \
buffer.c \
buffer.h \
@@ -119,7 +129,7 @@ interpret_SOURCES = \
interpret.c
interpret_LDADD = @LDFLAGS@ @GOBJECT_LIBS@
-iso2022_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ @VTE_CFLAGS@ -DISO2022_MAIN
+iso2022_CFLAGS = @CFLAGS@ @GTK_CFLAGS@ -DISO2022_MAIN
iso2022_SOURCES = \
debug.c \
debug.h \
@@ -146,22 +156,22 @@ utf8echo_SOURCES = \
utf8echo.c
utf8echo_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
-nativeecho_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ -DNATIVEECHO_MAIN
+nativeecho_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@ -DNATIVEECHO_MAIN
nativeecho_SOURCES = \
nativeecho.c
nativeecho_LDADD = @LDFLAGS@ @LIBS@
-ring_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ -DRING_MAIN
+ring_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@ -DRING_MAIN
ring_SOURCES = \
debug.c \
debug.h \
ring.c \
ring.h
-ring_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
+ring_LDADD = @LDFLAGS@ @LIBS@ @GLIB_LIBS@
slowcat_SOURCES = \
slowcat.c
-slowcat_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
+slowcat_LDADD = @LDFLAGS@ @LIBS@ @GLIB_LIBS@
table_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ -DTABLE_MAIN
table_SOURCES = \
@@ -189,23 +199,23 @@ trie_SOURCES = \
trie.h
trie_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
-termcap_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ -DTERMCAP_MAIN
+termcap_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@ -DTERMCAP_MAIN
termcap_SOURCES = \
debug.c \
debug.h \
termcap.c \
termcap.h
-termcap_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
+termcap_LDADD = @LDFLAGS@ @LIBS@ @GLIB_LIBS@
-pty_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ -DPTY_MAIN
+pty_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@ -DPTY_MAIN
pty_SOURCES = \
debug.c \
debug.h \
pty.c \
pty.h
-pty_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
+pty_LDADD = @LDFLAGS@ @LIBS@ @GLIB_LIBS@
-reaper_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ @VTE_CFLAGS@ -DREAPER_MAIN
+reaper_CFLAGS = @CFLAGS@ @GTK_CFLAGS@ -DREAPER_MAIN
reaper_SOURCES = \
debug.c \
debug.h \
@@ -215,19 +225,19 @@ reaper_SOURCES = \
reaper.h
reaper_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
-buffer_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ -DBUFFER_MAIN
+buffer_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@ -DBUFFER_MAIN
buffer_SOURCES = buffer.c
-buffer_LDADD = @LDFLAGS@ @GOBJECT_LIBS@
+buffer_LDADD = @LDFLAGS@ @GLIB_LIBS@
dumpkeys_SOURCES = dumpkeys.c
-dumpkeys_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
+dumpkeys_LDADD = @LDFLAGS@ @LIBS@ @GLIB_LIBS@
mev_SOURCES = mev.c
-mev_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
+mev_LDADD = @LDFLAGS@ @LIBS@ @GLIB_LIBS@
ssfe_SOURCES = ssfe.c
ssfe_LDADD = @LDFLAGS@ @OTHERLIBS@
-xticker_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@
+xticker_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@
xticker_SOURCES = xticker.c
-xticker_LDADD = @LIBS@ @GOBJECT_LIBS@
+xticker_LDADD = @LIBS@ @GLIB_LIBS@
diff --git a/src/vte.c b/src/vte.c
index 9d857c6..f38f22f 100644
--- a/src/vte.c
+++ b/src/vte.c
@@ -10856,9 +10856,9 @@ vte_terminal_open_font(VteTerminal *terminal)
vte_terminal_apply_metrics(terminal,
_vte_draw_get_text_width(draw),
_vte_draw_get_text_height(draw),
- _vte_draw_get_text_base(draw),
+ _vte_draw_get_text_ascent(draw),
_vte_draw_get_text_height(draw) -
- _vte_draw_get_text_base(draw));
+ _vte_draw_get_text_ascent(draw));
break;
#ifdef HAVE_XFT2
case VteRenderXft2:
@@ -11585,13 +11585,14 @@ vte_terminal_init(VteTerminal *terminal, gpointer *klass)
render_max = VteRenderXft1;
}
}
- if ((render_max >= VteRenderXft1) &&
+ if ((render_max == VteRenderXft1) &&
(getenv("VTE_USE_XFT") != NULL)) {
if (atol(getenv("VTE_USE_XFT")) == 0) {
render_max = VteRenderPango;
}
}
- if ((render_max >= VteRenderXft1) &&
+ if (((render_max == VteRenderXft2) ||
+ (render_max == VteRenderXft1)) &&
(getenv("GDK_USE_XFT") != NULL)) {
if (atol(getenv("GDK_USE_XFT")) == 0) {
render_max = VteRenderPango;
@@ -11851,12 +11852,6 @@ static void
vte_terminal_unrealize(GtkWidget *widget)
{
VteTerminal *terminal;
- Display *display;
- GdkColormap *gcolormap;
- Colormap colormap;
- GdkVisual *gvisual;
- Visual *visual;
- int i;
#ifdef VTE_DEBUG
if (_vte_debug_on(VTE_DEBUG_LIFECYCLE)) {
@@ -12277,8 +12272,8 @@ vte_terminal_realize(GtkWidget *widget)
attributes.width = widget->allocation.width;
attributes.height = widget->allocation.height;
attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gtk_widget_get_visual(widget);
- attributes.colormap = gtk_widget_get_colormap(widget);
+ attributes.visual = _vte_draw_get_visual(terminal->pvt->draw);
+ attributes.colormap = _vte_draw_get_colormap(terminal->pvt->draw);
attributes.event_mask = gtk_widget_get_events(widget) |
GDK_EXPOSURE_MASK |
GDK_VISIBILITY_NOTIFY_MASK |
@@ -12291,8 +12286,8 @@ vte_terminal_realize(GtkWidget *widget)
attributes.cursor = terminal->pvt->mouse_default_cursor;
attributes_mask = GDK_WA_X |
GDK_WA_Y |
- GDK_WA_VISUAL |
- GDK_WA_COLORMAP |
+ (attributes.visual ? GDK_WA_VISUAL : 0) |
+ (attributes.colormap ? GDK_WA_COLORMAP : 0) |
GDK_WA_CURSOR;
widget->window = gdk_window_new(gtk_widget_get_parent_window(widget),
&attributes,
diff --git a/src/vteapp.c b/src/vteapp.c
index 3899c63..481161e 100644
--- a/src/vteapp.c
+++ b/src/vteapp.c
@@ -434,8 +434,10 @@ main(int argc, char **argv)
}
argv2[i] = NULL;
g_assert(i < (g_list_length(args) + 2));
+
/* Parse some command-line options. */
- while ((opt = getopt(argc, argv, "B:CDT2abc:df:ghn:st:w:")) != -1) {
+ while ((opt = getopt(argc, argv, "B:CDT2abc:df:ghn:st:w:-")) != -1) {
+ gboolean bail = FALSE;
switch (opt) {
case 'B':
background = optarg;
@@ -485,12 +487,18 @@ main(int argc, char **argv)
case 'w':
working_directory = optarg;
break;
+ case '-':
+ bail = TRUE;
+ break;
case 'h':
default:
g_print(usage, argv[0]);
exit(1);
break;
}
+ if (bail) {
+ break;
+ }
}
gtk_init(&argc, &argv);
diff --git a/src/vtedraw.c b/src/vtedraw.c
index 44c643d..61887b2 100644
--- a/src/vtedraw.c
+++ b/src/vtedraw.c
@@ -27,17 +27,27 @@
#include <gtk/gtk.h>
#include "debug.h"
#include "vtedraw.h"
+#include "vteft2.h"
+#include "vtegl.h"
#include "vtepango.h"
+#include "vtepangox.h"
#include "vteskel.h"
#include "vtexft.h"
struct _vte_draw_impl
*_vte_draw_impls[] = {
&_vte_draw_skel,
+#ifdef HAVE_GL
+ /* &_vte_draw_gl, */
+#endif
#ifdef HAVE_XFT2
&_vte_draw_xft,
#endif
+ &_vte_draw_ft2,
&_vte_draw_pango,
+#ifdef HAVE_PANGOX
+ &_vte_draw_pango_x,
+#endif
};
struct _vte_draw *
@@ -98,6 +108,22 @@ _vte_draw_free(struct _vte_draw *draw)
g_free(draw);
}
+GdkVisual *
+_vte_draw_get_visual(struct _vte_draw *draw)
+{
+ g_return_val_if_fail(draw->impl != NULL, NULL);
+ g_return_val_if_fail(draw->impl->get_visual != NULL, NULL);
+ return draw->impl->get_visual(draw);
+}
+
+GdkColormap *
+_vte_draw_get_colormap(struct _vte_draw *draw)
+{
+ g_return_val_if_fail(draw->impl != NULL, NULL);
+ g_return_val_if_fail(draw->impl->get_colormap != NULL, NULL);
+ return draw->impl->get_colormap(draw);
+}
+
void
_vte_draw_start(struct _vte_draw *draw)
{
@@ -169,11 +195,11 @@ _vte_draw_get_text_height(struct _vte_draw *draw)
}
int
-_vte_draw_get_text_base(struct _vte_draw *draw)
+_vte_draw_get_text_ascent(struct _vte_draw *draw)
{
g_return_val_if_fail(draw->impl != NULL, 1);
- g_return_val_if_fail(draw->impl->get_text_base != NULL, 1);
- return draw->impl->get_text_base(draw);
+ g_return_val_if_fail(draw->impl->get_text_ascent != NULL, 1);
+ return draw->impl->get_text_ascent(draw);
}
void
@@ -184,8 +210,7 @@ _vte_draw_text(struct _vte_draw *draw,
g_return_if_fail(draw->started == TRUE);
g_return_if_fail(draw->impl != NULL);
g_return_if_fail(draw->impl->draw_text != NULL);
- draw->impl->draw_text(draw, requests, n_requests,
- color, alpha);
+ draw->impl->draw_text(draw, requests, n_requests, color, alpha);
}
void
@@ -210,15 +235,6 @@ _vte_draw_draw_rectangle(struct _vte_draw *draw,
draw->impl->draw_rectangle(draw, x, y, width, height, color, alpha);
}
-gboolean
-_vte_draw_scroll(struct _vte_draw *draw, gint dx, gint dy)
-{
- g_return_val_if_fail(draw->started == TRUE, FALSE);
- g_return_val_if_fail(draw->impl != NULL, FALSE);
- g_return_val_if_fail(draw->impl->scroll != NULL, FALSE);
- return draw->impl->scroll(draw, dx, dy);
-}
-
void
_vte_draw_set_scroll(struct _vte_draw *draw, gint x, gint y)
{
diff --git a/src/vtedraw.h b/src/vtedraw.h
index 27fa47b..25311cf 100644
--- a/src/vtedraw.h
+++ b/src/vtedraw.h
@@ -47,6 +47,8 @@ struct _vte_draw_impl {
gboolean (*check)(struct _vte_draw *draw, GtkWidget *widget);
void (*create)(struct _vte_draw *draw, GtkWidget *widget);
void (*destroy)(struct _vte_draw *draw);
+ GdkVisual* (*get_visual)(struct _vte_draw *draw);
+ GdkColormap* (*get_colormap)(struct _vte_draw *draw);
void (*start)(struct _vte_draw *draw);
void (*end)(struct _vte_draw *draw);
void (*set_background_color)(struct _vte_draw *, GdkColor *);
@@ -55,7 +57,7 @@ struct _vte_draw_impl {
void (*set_text_font)(struct _vte_draw *, const PangoFontDescription *);
int (*get_text_width)(struct _vte_draw *);
int (*get_text_height)(struct _vte_draw *);
- int (*get_text_base)(struct _vte_draw *);
+ int (*get_text_ascent)(struct _vte_draw *);
void (*draw_text)(struct _vte_draw *,
struct _vte_draw_text_request *, gsize,
GdkColor *, guchar);
@@ -65,20 +67,21 @@ struct _vte_draw_impl {
void (*fill_rectangle)(struct _vte_draw *,
gint, gint, gint, gint,
GdkColor *, guchar);
- gboolean (*scroll)(struct _vte_draw *, gint, gint);
void (*set_scroll)(struct _vte_draw *, gint, gint);
};
struct _vte_draw {
GtkWidget *widget;
gboolean started;
- gint width, height, base;
+ gint width, height, ascent;
struct _vte_draw_impl *impl;
gpointer impl_data;
};
struct _vte_draw *_vte_draw_new(GtkWidget *widget);
void _vte_draw_free(struct _vte_draw *draw);
+GdkVisual *_vte_draw_get_visual(struct _vte_draw *draw);
+GdkColormap *_vte_draw_get_colormap(struct _vte_draw *draw);
void _vte_draw_start(struct _vte_draw *draw);
void _vte_draw_end(struct _vte_draw *draw);
@@ -91,7 +94,7 @@ void _vte_draw_set_text_font(struct _vte_draw *draw,
const PangoFontDescription *fontdesc);
int _vte_draw_get_text_width(struct _vte_draw *draw);
int _vte_draw_get_text_height(struct _vte_draw *draw);
-int _vte_draw_get_text_base(struct _vte_draw *draw);
+int _vte_draw_get_text_ascent(struct _vte_draw *draw);
void _vte_draw_text(struct _vte_draw *draw,
struct _vte_draw_text_request *requests, gsize n_requests,
GdkColor *color, guchar alpha);
@@ -102,7 +105,6 @@ void _vte_draw_fill_rectangle(struct _vte_draw *draw,
void _vte_draw_draw_rectangle(struct _vte_draw *draw,
gint x, gint y, gint width, gint height,
GdkColor *color, guchar alpha);
-gboolean _vte_draw_scroll(struct _vte_draw *draw, gint dx, gint dy);
void _vte_draw_set_scroll(struct _vte_draw *draw, gint x, gint y);
G_END_DECLS
diff --git a/src/vtefc.c b/src/vtefc.c
index 3d1d40d..6b0be99 100644
--- a/src/vtefc.c
+++ b/src/vtefc.c
@@ -17,6 +17,7 @@
*/
#include "../config.h"
+#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
#include <pango/pango.h>
@@ -82,8 +83,8 @@ _vte_fc_transcribe_from_pango_font_description(FcPattern *pattern,
/* Set the font size for the pattern, or use a sensible default. */
if (pango_mask & PANGO_FONT_MASK_SIZE) {
- size = (double) pango_font_description_get_size(font_desc);
- size /= (double) PANGO_SCALE;
+ size = pango_font_description_get_size(font_desc);
+ size /= PANGO_SCALE;
}
FcPatternAddDouble(pattern, FC_SIZE, size);
@@ -114,14 +115,16 @@ static void
_vte_fc_defaults_from_gtk(FcPattern *pattern)
{
GtkSettings *settings;
+ GdkScreen *screen;
GObjectClass *klass;
- int i, antialias = -1, hinting = -1;
- double d, dpi = -1;
+ int i, antialias = -1, hinting = -1, dpi = -1;
+ double d;
char *rgba = NULL, *hintstyle = NULL;
FcResult result;
/* Add any defaults configured for GTK+. */
- settings = gtk_settings_get_for_screen(gdk_screen_get_default());
+ screen = gdk_screen_get_default();
+ settings = gtk_settings_get_for_screen(screen);
if (settings == NULL) {
return;
}
diff --git a/src/vteft2.c b/src/vteft2.c
new file mode 100644
index 0000000..b598527
--- /dev/null
+++ b/src/vteft2.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "../config.h"
+
+#include <sys/param.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <fontconfig/fontconfig.h>
+#include "debug.h"
+#include "vtedraw.h"
+#include "vtefc.h"
+#include "vteglyph.h"
+#include "vtergb.h"
+
+#define FONT_INDEX_FUDGE 10
+#define CHAR_WIDTH_FUDGE 10
+
+struct _vte_ft2_data
+{
+ struct _vte_glyph_cache *cache;
+ struct _vte_rgb_buffer *rgb;
+ GdkColor color;
+ GdkPixbuf *pixbuf;
+ gint scrollx, scrolly;
+ gint left, right, top, bottom;
+};
+
+static gboolean
+_vte_ft2_check(struct _vte_draw *draw, GtkWidget *widget)
+{
+ /* We can draw onto any widget. */
+ return TRUE;
+}
+
+static void
+_vte_ft2_create(struct _vte_draw *draw, GtkWidget *widget)
+{
+ struct _vte_ft2_data *data;
+ data = (struct _vte_ft2_data*) g_malloc0(sizeof(struct _vte_ft2_data));
+ draw->impl_data = data;
+ data->rgb = NULL;
+ memset(&data->color, 0, sizeof(data->color));
+ data->pixbuf = NULL;
+ data->scrollx = data->scrolly = 0;
+}
+
+static void
+_vte_ft2_destroy(struct _vte_draw *draw)
+{
+ struct _vte_ft2_data *data;
+ data = (struct _vte_ft2_data*) draw->impl_data;
+ if (data->cache != NULL) {
+ _vte_glyph_cache_free(data->cache);
+ data->cache = NULL;
+ }
+ if (data->rgb != NULL) {
+ _vte_rgb_buffer_free(data->rgb);
+ }
+ memset(&data->color, 0, sizeof(data->color));
+ if (GDK_IS_PIXBUF(data->pixbuf)) {
+ g_object_unref(G_OBJECT(data->pixbuf));
+ data->pixbuf = NULL;
+ }
+ data->scrollx = data->scrolly = 0;
+ g_free(data);
+}
+
+static GdkVisual *
+_vte_ft2_get_visual(struct _vte_draw *draw)
+{
+ return gtk_widget_get_visual(draw->widget);
+}
+
+static GdkColormap *
+_vte_ft2_get_colormap(struct _vte_draw *draw)
+{
+ return gtk_widget_get_colormap(draw->widget);
+}
+
+static void
+_vte_ft2_start(struct _vte_draw *draw)
+{
+ struct _vte_ft2_data *data;
+ guint width, height;
+ data = (struct _vte_ft2_data*) draw->impl_data;
+
+ gdk_window_get_geometry(draw->widget->window,
+ NULL, NULL, &width, &height, NULL);
+ if (data->rgb == NULL) {
+ data->rgb = _vte_rgb_buffer_new(width, height);
+ } else {
+ _vte_rgb_buffer_resize(data->rgb, width, height);
+ }
+ data->left = data->right = data->top = data->bottom = -1;
+}
+
+static void
+_vte_ft2_end(struct _vte_draw *draw)
+{
+ struct _vte_ft2_data *data;
+ guint width, height;
+ GtkWidget *widget;
+ GtkStateType state;
+ data = (struct _vte_ft2_data*) draw->impl_data;
+ widget = draw->widget;
+ gdk_window_get_geometry(widget->window,
+ NULL, NULL, &width, &height, NULL);
+ gtk_widget_ensure_style(widget);
+ state = GTK_WIDGET_STATE(widget);
+ if ((data->left == -1) &&
+ (data->right == -1) &&
+ (data->top == -1) &&
+ (data->bottom == -1)) {
+ _vte_rgb_draw_on_drawable(widget->window,
+ widget->style->fg_gc[state],
+ 0, 0,
+ width, height,
+ data->rgb,
+ 0, 0);
+ } else {
+ _vte_rgb_draw_on_drawable(widget->window,
+ widget->style->fg_gc[state],
+ data->left, data->top,
+ data->right - data->left + 1,
+ data->bottom - data->top + 1,
+ data->rgb,
+ data->left, data->top);
+ }
+}
+
+static void
+_vte_ft2_set_background_color(struct _vte_draw *draw, GdkColor *color)
+{
+ struct _vte_ft2_data *data;
+ data = (struct _vte_ft2_data*) draw->impl_data;
+ data->color = *color;
+}
+
+static void
+_vte_ft2_set_background_pixbuf(struct _vte_draw *draw, GdkPixbuf *pixbuf)
+{
+ struct _vte_ft2_data *data;
+
+ data = (struct _vte_ft2_data*) draw->impl_data;
+
+ if (GDK_IS_PIXBUF(data->pixbuf)) {
+ g_object_unref(G_OBJECT(data->pixbuf));
+ }
+ data->pixbuf = pixbuf;
+ if (GDK_IS_PIXBUF(data->pixbuf)) {
+ g_object_ref(G_OBJECT(data->pixbuf));
+ }
+}
+
+static void
+update_bbox(struct _vte_ft2_data *data, gint x, gint y, gint width, gint height)
+{
+ data->left = (data->left == -1) ?
+ x : MIN(data->left, x);
+ data->right = (data->right == -1) ?
+ x + width - 1 : MAX(data->right, x + width - 1);
+ data->top = (data->top == -1) ?
+ y : MIN(data->top, y);
+ data->bottom = (data->bottom == -1) ?
+ y + height - 1 : MAX(data->bottom, y + height - 1);
+}
+
+static void
+_vte_ft2_clear(struct _vte_draw *draw,
+ gint x, gint y, gint width, gint height)
+{
+ struct _vte_ft2_data *data;
+ data = (struct _vte_ft2_data*) draw->impl_data;
+
+ if (GDK_IS_PIXBUF(data->pixbuf)) {
+ /* Tile a pixbuf in. */
+ _vte_rgb_draw_pixbuf(data->rgb, x, y, width, height,
+ data->pixbuf,
+ data->scrollx + x, data->scrolly + y);
+ } else {
+ /* The simple case is a solid color. */
+ _vte_rgb_draw_color(data->rgb, x, y, width, height,
+ &data->color);
+ }
+ update_bbox(data, x, y, width, height);
+}
+
+static void
+_vte_ft2_set_text_font(struct _vte_draw *draw,
+ const PangoFontDescription *fontdesc)
+{
+ struct _vte_ft2_data *data;
+
+ data = (struct _vte_ft2_data*) draw->impl_data;
+
+ if (data->cache != NULL) {
+ _vte_glyph_cache_free(data->cache);
+ data->cache = NULL;
+ }
+ data->cache = _vte_glyph_cache_new();
+ _vte_glyph_cache_set_description(NULL, data->cache, fontdesc);
+}
+
+static int
+_vte_ft2_get_text_width(struct _vte_draw *draw)
+{
+ struct _vte_ft2_data *data;
+ data = (struct _vte_ft2_data*) draw->impl_data;
+ return data->cache->width;
+}
+
+static int
+_vte_ft2_get_text_height(struct _vte_draw *draw)
+{
+ struct _vte_ft2_data *data;
+ data = (struct _vte_ft2_data*) draw->impl_data;
+ return data->cache->height;
+}
+
+static int
+_vte_ft2_get_text_ascent(struct _vte_draw *draw)
+{
+ struct _vte_ft2_data *data;
+ data = (struct _vte_ft2_data*) draw->impl_data;
+ return data->cache->ascent;
+}
+
+static void
+_vte_ft2_draw_text(struct _vte_draw *draw,
+ struct _vte_draw_text_request *requests, gsize n_requests,
+ GdkColor *color, guchar alpha)
+{
+ struct _vte_ft2_data *data;
+ struct _vte_glyph_cache *cache;
+ int i;
+
+ data = (struct _vte_ft2_data*) draw->impl_data;
+ cache = data->cache;
+
+ for (i = 0; i < n_requests; i++) {
+ _vte_glyph_draw(data->cache, requests[i].c, color,
+ requests[i].x, requests[i].y,
+ requests[i].columns,
+ 0,
+ data->rgb);
+ update_bbox(data, requests[i].x, requests[i].y,
+ cache->width * requests[i].columns, cache->height);
+ }
+}
+
+static void
+_vte_ft2_draw_rectangle(struct _vte_draw *draw,
+ gint x, gint y, gint width, gint height,
+ GdkColor *color, guchar alpha)
+{
+ struct _vte_ft2_data *data;
+
+ data = (struct _vte_ft2_data*) draw->impl_data;
+
+ _vte_rgb_draw_color(data->rgb,
+ x, y,
+ width, 1,
+ color);
+ _vte_rgb_draw_color(data->rgb,
+ x, y,
+ 1, height,
+ color);
+ _vte_rgb_draw_color(data->rgb,
+ x, y + height - 1,
+ width, 1,
+ color);
+ _vte_rgb_draw_color(data->rgb,
+ x + width - 1, y,
+ 1, height,
+ color);
+ update_bbox(data, x, y, width, height);
+}
+
+static void
+_vte_ft2_fill_rectangle(struct _vte_draw *draw,
+ gint x, gint y, gint width, gint height,
+ GdkColor *color, guchar alpha)
+{
+ struct _vte_ft2_data *data;
+
+ data = (struct _vte_ft2_data*) draw->impl_data;
+
+ _vte_rgb_draw_color(data->rgb, x, y, width, height, color);
+ update_bbox(data, x, y, width, height);
+}
+
+static void
+_vte_ft2_set_scroll(struct _vte_draw *draw, gint x, gint y)
+{
+ struct _vte_ft2_data *data;
+ data = (struct _vte_ft2_data*) draw->impl_data;
+ data->scrollx = x;
+ data->scrolly = y;
+}
+
+struct _vte_draw_impl _vte_draw_ft2 = {
+ "VteFT2", "VTE_USE_FT2",
+ _vte_ft2_check,
+ _vte_ft2_create,
+ _vte_ft2_destroy,
+ _vte_ft2_get_visual,
+ _vte_ft2_get_colormap,
+ _vte_ft2_start,
+ _vte_ft2_end,
+ _vte_ft2_set_background_color,
+ _vte_ft2_set_background_pixbuf,
+ _vte_ft2_clear,
+ _vte_ft2_set_text_font,
+ _vte_ft2_get_text_width,
+ _vte_ft2_get_text_height,
+ _vte_ft2_get_text_ascent,
+ _vte_ft2_draw_text,
+ _vte_ft2_draw_rectangle,
+ _vte_ft2_fill_rectangle,
+ _vte_ft2_set_scroll,
+};
diff --git a/src/vteft2.h b/src/vteft2.h
new file mode 100644
index 0000000..eb3a762
--- /dev/null
+++ b/src/vteft2.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef vte_vteft2_h_included
+#define vte_vteft2_h_included
+
+/* The interfaces in this file are subject to change at any time. */
+
+#ident "$Id$"
+
+#include "../config.h"
+#include "vtedraw.h"
+
+G_BEGIN_DECLS
+
+extern struct _vte_draw_impl _vte_draw_ft2;
+
+G_END_DECLS
+
+#endif
diff --git a/src/vtegl.c b/src/vtegl.c
new file mode 100644
index 0000000..4861491
--- /dev/null
+++ b/src/vtegl.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "../config.h"
+
+#ifdef HAVE_GL
+
+#include <sys/param.h>
+#include <stdio.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glx.h>
+#include <X11/Xutil.h>
+#include "debug.h"
+#include "vtedraw.h"
+#include "vtegl.h"
+
+struct _vte_gl_data
+{
+ XVisualInfo *visual_info;
+ gboolean double_buffered;
+ GLXContext context;
+ GLXPixmap pixmap;
+ GdkColor color;
+ GdkPixbuf *pixbuf;
+ gint scrollx, scrolly;
+};
+
+#define _vte_gl_pixmap_attributes \
+ GLX_RGBA, \
+ GLX_RED_SIZE, 8, \
+ GLX_BLUE_SIZE, 8, \
+ GLX_GREEN_SIZE, 8, \
+ GLX_ALPHA_SIZE, 8, \
+ None,
+#define _vte_gl_window_attributes \
+ GLX_RGBA, \
+ GLX_RED_SIZE, 8, \
+ GLX_BLUE_SIZE, 8, \
+ GLX_GREEN_SIZE, 8, \
+ GLX_ALPHA_SIZE, 8, \
+ GLX_DOUBLEBUFFER, \
+ None,
+
+static gboolean
+_vte_gl_check(struct _vte_draw *draw, GtkWidget *widget)
+{
+ int window_attributes[] = {_vte_gl_window_attributes};
+ int pixmap_attributes[] = {_vte_gl_pixmap_attributes};
+ XVisualInfo *visual_info;
+ GLXContext context = NULL;
+ GdkDisplay *gdisplay;
+ Display *display;
+ GdkScreen *gscreen;
+ int screen;
+ int error, event;
+
+ gdisplay = gdk_display_get_default();
+ display = gdk_x11_display_get_xdisplay(gdisplay);
+ gscreen = gdk_screen_get_default();
+ screen = gdk_x11_screen_get_screen_number(gscreen);
+
+ /* Check for GLX. */
+ if (!glXQueryExtension(display, &error, &event)) {
+ g_warning("Unable to use GLX.\n");
+ return FALSE;
+ }
+
+ /* See if a suitable visual exists. */
+ visual_info = glXChooseVisual(display, screen,
+ pixmap_attributes);
+ if (visual_info == NULL) {
+ visual_info = glXChooseVisual(display, screen,
+ window_attributes);
+ }
+ if (visual_info == NULL) {
+ return FALSE;
+ }
+
+ /* Create a GLX context. */
+ context = glXCreateContext(display, visual_info, NULL, False);
+ if (context == NULL) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+_vte_gl_create(struct _vte_draw *draw, GtkWidget *widget)
+{
+ struct _vte_gl_data *data;
+ int window_attributes[] = {_vte_gl_window_attributes};
+ int pixmap_attributes[] = {_vte_gl_pixmap_attributes};
+ GdkDisplay *gdisplay;
+ Display *display;
+ GdkScreen *gscreen;
+ int screen;
+
+ draw->impl_data = g_malloc(sizeof(struct _vte_gl_data));
+ data = (struct _vte_gl_data*) draw->impl_data;
+
+ gdisplay = gdk_display_get_default();
+ display = gdk_x11_display_get_xdisplay(gdisplay);
+ gscreen = gdk_screen_get_default();
+ screen = gdk_x11_screen_get_screen_number(gscreen);
+
+ data->visual_info = glXChooseVisual(display, screen,
+ pixmap_attributes);
+ if (data->visual_info != NULL) {
+ data->double_buffered = FALSE;
+ } else {
+ data->visual_info = glXChooseVisual(display, screen,
+ window_attributes);
+ data->double_buffered = TRUE;
+ }
+ gtk_widget_set_double_buffered(widget, !data->double_buffered);
+
+ data->context = glXCreateContext(display, data->visual_info,
+ NULL, False);
+ if (data->context == NULL) {
+ g_error("Unable to create GLX context.\n");
+ }
+
+ data->color.red = 0;
+ data->color.green = 0;
+ data->color.blue = 0;
+ data->pixbuf = NULL;
+ data->pixmap = -1;
+ data->scrollx = data->scrolly = 0;
+}
+
+static void
+_vte_gl_destroy(struct _vte_draw *draw)
+{
+ struct _vte_gl_data *data;
+ GdkDisplay *gdisplay;
+ Display *display;
+ GdkScreen *gscreen;
+ int screen;
+
+ data = (struct _vte_gl_data*) draw->impl_data;
+ gdisplay = gdk_display_get_default();
+ display = gdk_x11_display_get_xdisplay(gdisplay);
+ gscreen = gdk_screen_get_default();
+ screen = gdk_x11_screen_get_screen_number(gscreen);
+
+ if (data->pixmap != -1) {
+ glXDestroyGLXPixmap(display, data->pixmap);
+ }
+ glXDestroyContext(display, data->context);
+
+ data->scrollx = data->scrolly = 0;
+
+ if (GDK_IS_PIXBUF(data->pixbuf)) {
+ g_object_unref(G_OBJECT(data->pixbuf));
+ }
+ data->pixbuf = NULL;
+ memset(&data->color, 0, sizeof(data->color));
+
+ glXDestroyContext(display, data->context);
+
+ g_free(draw->impl_data);
+}
+
+static GdkVisual *
+_vte_gl_get_visual(struct _vte_draw *draw)
+{
+ GdkScreen *gscreen;
+ struct _vte_gl_data *data;
+
+ data = (struct _vte_gl_data*) draw->impl_data;
+ gscreen = gdk_screen_get_default();
+ return gdk_x11_screen_lookup_visual(gscreen,
+ data->visual_info->visualid);
+}
+
+static GdkColormap *
+_vte_gl_get_colormap(struct _vte_draw *draw)
+{
+ return NULL;
+}
+
+static void
+_vte_gl_start(struct _vte_draw *draw)
+{
+ struct _vte_gl_data *data;
+ GdkDisplay *gdisplay;
+ Display *display;
+ GdkScreen *gscreen;
+ int screen;
+ guint width, height;
+ GdkDrawable *drawable;
+ gint x_offset, y_offset;
+ GLXDrawable glx_drawable = -1;
+
+ data = (struct _vte_gl_data*) draw->impl_data;
+ gdisplay = gdk_display_get_default();
+ display = gdk_x11_display_get_xdisplay(gdisplay);
+ gscreen = gdk_screen_get_default();
+ screen = gdk_x11_screen_get_screen_number(gscreen);
+
+ gdk_window_get_internal_paint_info(draw->widget->window,
+ &drawable,
+ &x_offset,
+ &y_offset);
+ if (GDK_IS_PIXMAP(drawable)) {
+ gdk_drawable_get_size(drawable, &width, &height);
+ data->pixmap = glXCreateGLXPixmap(display, data->visual_info,
+ GDK_WINDOW_XID(drawable));
+ glx_drawable = data->pixmap;
+ } else
+ if (GDK_IS_WINDOW(draw->widget->window)) {
+ gdk_drawable_get_size(draw->widget->window, &width, &height);
+ x_offset = y_offset = 0;
+ glx_drawable = GDK_WINDOW_XID(drawable);
+ } else {
+ g_assert_not_reached();
+ }
+
+ glXMakeCurrent(display, glx_drawable, data->context);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluOrtho2D(x_offset, width, y_offset, height);
+ glViewport(x_offset, y_offset, width - x_offset, height - y_offset);
+
+ glClearColor(data->color.red / 65535.0,
+ data->color.green / 65535.0,
+ data->color.blue / 65535.0,
+ 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+static void
+_vte_gl_end(struct _vte_draw *draw)
+{
+ struct _vte_gl_data *data;
+ GdkDisplay *gdisplay;
+ Display *display;
+ GdkScreen *gscreen;
+ int screen;
+
+ data = (struct _vte_gl_data*) draw->impl_data;
+ gdisplay = gdk_display_get_default();
+ display = gdk_x11_display_get_xdisplay(gdisplay);
+ gscreen = gdk_screen_get_default();
+ screen = gdk_x11_screen_get_screen_number(gscreen);
+
+ glFlush();
+ if (data->double_buffered) {
+ glXSwapBuffers(display, GDK_WINDOW_XID(draw->widget->window));
+ } else {
+ glXDestroyGLXPixmap(display, data->pixmap);
+ data->pixmap = -1;
+ }
+}
+
+static void
+_vte_gl_set_background_color(struct _vte_draw *draw, GdkColor *color)
+{
+ struct _vte_gl_data *data;
+ data = (struct _vte_gl_data*) draw->impl_data;
+ data->color = *color;
+}
+
+static void
+_vte_gl_set_background_pixbuf(struct _vte_draw *draw, GdkPixbuf *pixbuf)
+{
+ struct _vte_gl_data *data;
+
+ data = (struct _vte_gl_data*) draw->impl_data;
+ if (GDK_IS_PIXBUF(pixbuf)) {
+ g_object_ref(G_OBJECT(pixbuf));
+ }
+ if (GDK_IS_PIXBUF(data->pixbuf)) {
+ g_object_unref(G_OBJECT(data->pixbuf));
+ }
+ data->pixbuf = pixbuf;
+}
+
+static void
+_vte_gl_clear(struct _vte_draw *draw,
+ gint x, gint y, gint width, gint height)
+{
+ struct _vte_gl_data *data;
+ data = (struct _vte_gl_data*) draw->impl_data;
+
+ glBegin(GL_POLYGON);
+ glColor4us(data->color.red, data->color.green, data->color.blue,
+ 0xffff);
+ glVertex2d(x, y);
+ glVertex2d(x + width, y);
+ glVertex2d(x + width, y + height);
+ glVertex2d(x, y + height);
+ glEnd();
+}
+
+static void
+_vte_gl_set_text_font(struct _vte_draw *draw,
+ const PangoFontDescription *fontdesc)
+{
+}
+
+static int
+_vte_gl_get_text_width(struct _vte_draw *draw)
+{
+ return 5;
+}
+
+static int
+_vte_gl_get_text_height(struct _vte_draw *draw)
+{
+ return 10;
+}
+
+static int
+_vte_gl_get_text_ascent(struct _vte_draw *draw)
+{
+ return 8;
+}
+
+static void
+_vte_gl_draw_text(struct _vte_draw *draw,
+ struct _vte_draw_text_request *requests, gsize n_requests,
+ GdkColor *color, guchar alpha)
+{
+ struct _vte_gl_data *data;
+ data = (struct _vte_gl_data*) draw->impl_data;
+}
+
+static void
+_vte_gl_draw_rectangle(struct _vte_draw *draw,
+ gint x, gint y, gint width, gint height,
+ GdkColor *color, guchar alpha)
+{
+ struct _vte_gl_data *data;
+ data = (struct _vte_gl_data*) draw->impl_data;
+ glBegin(GL_LINE_LOOP);
+ glColor4us(color->red, color->green, color->blue,
+ (alpha == VTE_DRAW_OPAQUE) ? 0xffff : (alpha << 8));
+ glVertex2d(x, y);
+ glVertex2d(x + width, y);
+ glVertex2d(x + width, y + height);
+ glVertex2d(x, y + height);
+ glEnd();
+}
+
+static void
+_vte_gl_fill_rectangle(struct _vte_draw *draw,
+ gint x, gint y, gint width, gint height,
+ GdkColor *color, guchar alpha)
+{
+ struct _vte_gl_data *data;
+ data = (struct _vte_gl_data*) draw->impl_data;
+ glBegin(GL_POLYGON);
+ glColor4us(color->red, color->green, color->blue,
+ (alpha == VTE_DRAW_OPAQUE) ? 0xffff : (alpha << 8));
+ glVertex2d(x, y);
+ glVertex2d(x + width, y);
+ glVertex2d(x + width, y + height);
+ glVertex2d(x, y + height);
+ glEnd();
+}
+
+static void
+_vte_gl_set_scroll(struct _vte_draw *draw, gint x, gint y)
+{
+ struct _vte_gl_data *data;
+ data = (struct _vte_gl_data*) draw->impl_data;
+ data->scrollx = x;
+ data->scrolly = y;
+}
+
+struct _vte_draw_impl _vte_draw_gl = {
+ "VteGL", "VTE_USE_GL",
+ _vte_gl_check,
+ _vte_gl_create,
+ _vte_gl_destroy,
+ _vte_gl_get_visual,
+ _vte_gl_get_colormap,
+ _vte_gl_start,
+ _vte_gl_end,
+ _vte_gl_set_background_color,
+ _vte_gl_set_background_pixbuf,
+ _vte_gl_clear,
+ _vte_gl_set_text_font,
+ _vte_gl_get_text_width,
+ _vte_gl_get_text_height,
+ _vte_gl_get_text_ascent,
+ _vte_gl_draw_text,
+ _vte_gl_draw_rectangle,
+ _vte_gl_fill_rectangle,
+ _vte_gl_set_scroll,
+};
+
+#endif
diff --git a/src/vtegl.h b/src/vtegl.h
new file mode 100644
index 0000000..5f63103
--- /dev/null
+++ b/src/vtegl.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef vte_vtegl_h_included
+#define vte_vtegl_h_included
+
+/* The interfaces in this file are subject to change at any time. */
+
+#ident "$Id$"
+
+#include "../config.h"
+#include "vtedraw.h"
+
+G_BEGIN_DECLS
+
+extern struct _vte_draw_impl _vte_draw_gl;
+
+G_END_DECLS
+
+#endif
diff --git a/src/vteglyph.c b/src/vteglyph.c
new file mode 100644
index 0000000..bb021eb
--- /dev/null
+++ b/src/vteglyph.c
@@ -0,0 +1,728 @@
+/*
+ * Copyright (C) 2002,2003 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ident "$Id$"
+
+#include "../config.h"
+#include <sys/param.h>
+#include <math.h>
+#include <gdk/gdk.h>
+#include <glib.h>
+#include "vtedraw.h"
+#include "vtefc.h"
+#include "vteglyph.h"
+
+#define FONT_INDEX_FUDGE 10
+#define CHAR_WIDTH_FUDGE 10
+#define INVALID_GLYPH -1
+
+static FT_Face _vte_glyph_cache_face_for_char(struct _vte_glyph_cache *cache,
+ gunichar c);
+
+static int
+_vte_direct_compare(gconstpointer a, gconstpointer b)
+{
+ return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
+}
+
+struct _vte_glyph_cache *
+_vte_glyph_cache_new(void)
+{
+ struct _vte_glyph_cache *ret;
+ int error;
+
+ ret = g_malloc(sizeof(struct _vte_glyph_cache));
+
+ ret->patterns = g_array_new(TRUE, TRUE, sizeof(FcPattern*));
+ ret->faces = NULL;
+ ret->cache = g_tree_new(_vte_direct_compare);
+ ret->ft_load_flags = 0;
+ ret->ft_render_flags = 0;
+ ret->width = 0;
+ ret->height = 0;
+ ret->ascent = 0;
+
+ error = FT_Init_FreeType(&ret->ft_library);
+ g_assert(error == 0);
+
+ return ret;
+}
+
+static gboolean
+free_tree_value(gpointer key, gpointer value, gpointer data)
+{
+ if (GPOINTER_TO_INT(value) != INVALID_GLYPH) {
+ g_free(value);
+ }
+ return FALSE;
+}
+
+void
+_vte_glyph_cache_free(struct _vte_glyph_cache *cache)
+{
+ GList *iter;
+ int i;
+
+ g_return_if_fail(cache != NULL);
+
+ /* Destroy the patterns. */
+ if (cache->patterns != NULL) {
+ for (i = 0; i < cache->patterns->len; i++) {
+ FcPatternDestroy(g_array_index(cache->patterns,
+ FcPattern*,
+ i));
+ }
+ g_array_free(cache->patterns, TRUE);
+ cache->patterns = NULL;
+ }
+
+ /* Close all faces. */
+ for (iter = cache->faces; iter != NULL; iter = g_list_next(iter)) {
+ FT_Done_Face((FT_Face) iter->data);
+ iter->data = NULL;
+ }
+ cache->faces = NULL;
+
+ /* Free the glyph tree. */
+ g_tree_foreach(cache->cache, free_tree_value, NULL);
+ cache->cache = NULL;
+
+ /* Close the FT library. */
+ if (cache->ft_library) {
+ FT_Done_FreeType(cache->ft_library);
+ cache->ft_library = NULL;
+ }
+
+ /* Free the cache. */
+ cache->ft_load_flags = 0;
+ cache->ft_render_flags = 0;
+ cache->width = 0;
+ cache->height = 0;
+ cache->ascent = 0;
+ g_free(cache);
+}
+
+void
+_vte_glyph_cache_set_description(FcConfig *config,
+ struct _vte_glyph_cache *cache,
+ const PangoFontDescription *fontdesc)
+{
+ FcChar8 *facefile;
+ int i, j, error, count, width, faceindex;
+ double dpi, size;
+ GList *iter;
+ FcPattern *pattern;
+ GArray *patterns;
+ FT_Face face;
+ gunichar double_wide_characters[] = {VTE_DRAW_DOUBLE_WIDE_CHARACTERS};
+
+ g_return_if_fail(cache != NULL);
+ g_return_if_fail(fontdesc != NULL);
+
+ /* Convert the font description to a sorted set of patterns. */
+ patterns = g_array_new(TRUE, TRUE, sizeof(FcPattern*));
+ if (!_vte_fc_patterns_from_pango_font_desc(fontdesc, patterns)) {
+ g_array_free(patterns, TRUE);
+ g_assert_not_reached();
+ }
+
+ /* Set the pattern list. */
+ if (cache->patterns != NULL) {
+ g_array_free(cache->patterns, TRUE);
+ }
+ cache->patterns = patterns;
+
+ /* Clear the face list. */
+ for (iter = cache->faces; iter != NULL; iter = g_list_next(iter)) {
+ FT_Done_Face((FT_Face) iter->data);
+ iter->data = NULL;
+ }
+ g_list_free(cache->faces);
+ cache->faces = NULL;
+
+ /* Clear the glyph tree. */
+ g_tree_foreach(cache->cache, free_tree_value, NULL);
+ g_tree_destroy(cache->cache);
+ cache->cache = g_tree_new(_vte_direct_compare);
+
+ /* Clear the load and render flags. */
+ cache->ft_load_flags = 0;
+ cache->ft_render_flags = 0;
+
+ /* Open the all of the faces to which the patterns resolve. */
+ for (i = 0; i < cache->patterns->len; i++) {
+ pattern = g_array_index(cache->patterns, FcPattern*, i);
+ j = 0;
+ while (FcPatternGetString(pattern, FC_FILE, j,
+ &facefile) == FcResultMatch) {
+ face = NULL;
+ if (FcPatternGetInteger(pattern, FC_INDEX, i,
+ &faceindex) != FcResultMatch) {
+ faceindex = 0;
+ }
+ error = FT_New_Face(cache->ft_library,
+ facefile, faceindex,
+ &face);
+ if (error == 0) {
+ /* Set the requested size. FIXME: what do we
+ do if horizontal and vertical DPI aren't the
+ same? */
+ dpi = 72;
+ FcPatternGetDouble(pattern, FC_DPI, 0, &dpi);
+ size = 12;
+ FcPatternGetDouble(pattern, FC_SIZE, 0, &size);
+ FT_Set_Char_Size(face, 0, floor(size * 64.0),
+ floor(dpi), floor(dpi));
+ cache->faces = g_list_append(cache->faces,
+ face);
+ } else {
+ if (face != NULL) {
+ FT_Done_Face(face);
+ }
+ face = NULL;
+ }
+ j++;
+ }
+ }
+
+ /* Make sure that we were able to load at least one face. */
+ g_assert(cache->faces != NULL);
+
+ /* Pull out other settings. */
+ cache->ft_load_flags = 0;
+ cache->ft_render_flags = 0;
+ i = 0;
+ pattern = g_array_index(cache->patterns, FcPattern*, 0);
+ if (FcPatternGetBool(pattern, FC_AUTOHINT, 0, &i) == FcResultMatch) {
+ if (i != 0) {
+ cache->ft_load_flags |= FT_LOAD_FORCE_AUTOHINT;
+ }
+ }
+ if (FcPatternGetBool(pattern, FC_ANTIALIAS, 0, &i) == FcResultMatch) {
+ if (i == 0) {
+ cache->ft_load_flags |= FT_LOAD_MONOCHROME;
+#if HAVE_DECL_FT_RENDER_MODE_MONO
+ cache->ft_render_flags = FT_RENDER_MODE_MONO;
+#endif
+ }
+ }
+ if (FcPatternGetBool(pattern, FC_HINTING, 0, &i) == FcResultMatch) {
+ if (i == 0) {
+ cache->ft_load_flags |= FT_LOAD_NO_HINTING;
+ } else {
+ if (FcPatternGetBool(pattern, FC_AUTOHINT, 0,
+ &i) == FcResultMatch) {
+ if (i != 0) {
+ cache->ft_render_flags |=
+ FT_LOAD_FORCE_AUTOHINT;
+ }
+ }
+ if (FcPatternGetInteger(pattern, FC_HINT_STYLE, 0,
+ &i) == FcResultMatch) {
+ switch (i) {
+#if HAVE_DECL_FT_LOAD_NO_HINTING
+ case FC_HINT_NONE:
+ cache->ft_load_flags |=
+ FT_LOAD_NO_HINTING;
+ break;
+#endif
+#if HAVE_DECL_FT_RENDER_MODE_LIGHT
+ case FC_HINT_SLIGHT:
+ cache->ft_render_flags |=
+ FT_RENDER_MODE_LIGHT;
+ break;
+#endif
+#if HAVE_DECL_FT_RENDER_MODE_NORMAL
+ case FC_HINT_MEDIUM:
+ cache->ft_render_flags |=
+ FT_RENDER_MODE_NORMAL;
+ break;
+#endif
+#if HAVE_DECL_FT_RENDER_MODE_NORMAL
+ case FC_HINT_FULL:
+ cache->ft_render_flags |=
+ FT_RENDER_MODE_NORMAL;
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ /* Calculate average cell size using the first face. */
+ cache->width = 0;
+ cache->height = 0;
+ cache->ascent = 0;
+ count = 0;
+ for (i = 0; VTE_DRAW_SINGLE_WIDE_CHARACTERS[i] != '\0'; i++) {
+ face = _vte_glyph_cache_face_for_char(cache,
+ VTE_DRAW_SINGLE_WIDE_CHARACTERS[i]);
+ if (face == NULL) {
+ face = cache->faces->data;
+ }
+ error = FT_Load_Char((FT_Face) face,
+ VTE_DRAW_SINGLE_WIDE_CHARACTERS[i],
+ FT_LOAD_RENDER | cache->ft_load_flags);
+ if (error == 0) {
+ cache->width += face->glyph->bitmap.width;
+ if (face->size->metrics.ascender != 0) {
+ cache->height += face->size->metrics.ascender -
+ face->size->metrics.descender;
+ cache->ascent += face->size->metrics.ascender;
+ } else
+ if (face->glyph->metrics.height != 0) {
+ cache->height += face->glyph->metrics.height;
+ cache->ascent += face->glyph->metrics.height;
+ } else {
+ cache->height += face->glyph->bitmap.rows * 64;
+ cache->ascent += face->glyph->bitmap.rows * 64;
+ }
+ count++;
+ }
+ }
+ if (count > 0) {
+ cache->width = howmany(cache->width, count);
+ cache->height = howmany((cache->height / 64), count);
+ cache->ascent = howmany((cache->ascent / 64), count);
+ } else {
+ cache->width = 1;
+ cache->height = 1;
+ cache->ascent = 1;
+ }
+ width = 0;
+ for (i = 0; i < G_N_ELEMENTS(double_wide_characters); i++) {
+ face = _vte_glyph_cache_face_for_char(cache,
+ double_wide_characters[i]);
+ if (face == NULL) {
+ continue;
+ }
+ error = FT_Load_Char((FT_Face) face,
+ double_wide_characters[i],
+ FT_LOAD_RENDER | cache->ft_load_flags);
+ if (error == 0) {
+ width += face->glyph->bitmap.width;
+ count++;
+ }
+ }
+ if (count > 0) {
+ if (cache->width == width / count) {
+ cache->width /= 2;
+ }
+ }
+}
+
+static FT_Face
+_vte_glyph_cache_face_for_char(struct _vte_glyph_cache *cache, gunichar c)
+{
+ GList *iter;
+ for (iter = cache->faces; iter != NULL; iter = g_list_next(iter)) {
+ if (FT_Get_Char_Index((FT_Face) iter->data, c) != 0) {
+ return (FT_Face) iter->data;
+ }
+ }
+ return NULL;
+}
+
+gboolean
+_vte_glyph_cache_has_char(struct _vte_glyph_cache *cache, gunichar c)
+{
+ GList *iter;
+ gpointer p;
+
+ if ((p = g_tree_lookup(cache->cache, GINT_TO_POINTER(c))) != NULL) {
+ if (GPOINTER_TO_INT(p) == INVALID_GLYPH) {
+ return FALSE;
+ }
+ }
+
+ for (iter = cache->faces; iter != NULL; iter = g_list_next(iter)) {
+ if (FT_Get_Char_Index((FT_Face) iter->data, c) != 0) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static gunichar
+_vte_glyph_remap_char(struct _vte_glyph_cache *cache, gunichar origc)
+{
+ gunichar newc;
+
+ if (_vte_glyph_cache_has_char(cache, origc)) {
+ return origc;
+ }
+
+ switch (origc) {
+ case 0: /* NUL */
+ case 0x00A0: /* NO-BREAK SPACE */
+ newc = 0x0020; /* SPACE */
+ break;
+ case 0x2010: /* HYPHEN */
+ case 0x2011: /* NON-BREAKING HYPHEN */
+ case 0x2012: /* FIGURE DASH */
+ case 0x2013: /* EN DASH */
+ case 0x2014: /* EM DASH */
+ case 0x2212: /* MINUS SIGN */
+ newc = 0x002D; /* HYPHEN-MINUS */
+ break;
+ default:
+ newc = origc;
+ break;
+ }
+
+ if (_vte_glyph_cache_has_char(cache, newc)) {
+ return newc;
+ } else {
+ return origc;
+ }
+}
+
+const struct _vte_glyph *
+_vte_glyph_get(struct _vte_glyph_cache *cache, gunichar c)
+{
+ int error = 0;
+ GList *iter;
+ struct _vte_glyph *glyph = NULL;
+ FT_Face face;
+ gpointer p;
+ gint x, y, ooffset, ioffset;
+ guchar r, g, b, t;
+
+ g_return_val_if_fail(cache != NULL, NULL);
+
+ /* See if we already have a glyph for this character. */
+ if ((p = g_tree_lookup(cache->cache, GINT_TO_POINTER(c))) != NULL) {
+ if (GPOINTER_TO_INT(p) == INVALID_GLYPH) {
+ return NULL;
+ } else {
+ return p;
+ }
+ }
+
+ /* Search through all of the faces to find one which contains a glyph
+ * for this character. */
+ iter = cache->faces;
+ face = NULL;
+ while (iter != NULL) {
+ /* Check if the face contains a proper glyph. We do this
+ * separately because we don't want the "unknown glyph"
+ * glyph. */
+ if (FT_Get_Char_Index((FT_Face) iter->data, c) == 0) {
+ /* Try the next face. */
+ iter = g_list_next(iter);
+ face = NULL;
+ continue;
+ }
+ /* Try to load the character. */
+ error = FT_Load_Char((FT_Face) iter->data,
+ c,
+ cache->ft_load_flags);
+ if (error != 0) {
+ /* Try the next face. */
+ iter = g_list_next(iter);
+ face = NULL;
+ continue;
+ }
+ /* Try to render the character. */
+ error = FT_Render_Glyph(((FT_Face) iter->data)->glyph,
+ cache->ft_render_flags);
+ if (error != 0) {
+ /* Try the next face. */
+ iter = g_list_next(iter);
+ face = NULL;
+ continue;
+ }
+
+ /* Keep track of which face loaded it. */
+ face = iter->data;
+ break;
+ }
+
+ /* Bail if we weren't able to load the glyph. */
+ if (face == NULL) {
+ g_tree_insert(cache->cache, GINT_TO_POINTER(c),
+ GINT_TO_POINTER(INVALID_GLYPH));
+ return NULL;
+ }
+
+ /* Build a new glyph. */
+ glyph = g_malloc0(sizeof(struct _vte_glyph) +
+ face->glyph->bitmap.width *
+ face->glyph->bitmap.rows *
+ 4);
+ glyph->width = face->glyph->bitmap.width;
+ glyph->height = face->glyph->bitmap.rows;
+ glyph->skip = MAX((face->size->metrics.ascender >> 6) -
+ face->glyph->bitmap_top, 0);
+ glyph->bytes_per_pixel = 4;
+
+ memset(glyph->bytes, 0,
+ glyph->width * glyph->height * glyph->bytes_per_pixel);
+
+ for (y = 0; y < face->glyph->bitmap.rows; y++)
+ for (x = 0; x < face->glyph->bitmap.width; x++) {
+ ooffset = (y * glyph->width + x) * 4;
+ if (face->glyph->bitmap.pitch > 0) {
+ ioffset = y;
+ ioffset *= face->glyph->bitmap.pitch;
+ } else {
+ ioffset = face->glyph->bitmap.rows - (y + 1);
+ ioffset *= (-face->glyph->bitmap.pitch);
+ }
+ switch (face->glyph->bitmap.pixel_mode) {
+ case FT_PIXEL_MODE_MONO:
+ ioffset += (x / 8);
+ t = (face->glyph->bitmap.buffer[ioffset] << (x % 8));
+ r = g = b = (t >> 7) ? 0xff : 0;
+ break;
+ case FT_PIXEL_MODE_GRAY2:
+ ioffset += (x / 4);
+ t = (face->glyph->bitmap.buffer[ioffset] << ((x % 4) * 2));
+ r = g = b = CLAMP((t >> 6) * 0x55, 0, 0xff);
+ break;
+ case FT_PIXEL_MODE_GRAY4:
+ ioffset += (x / 2);
+ t = (face->glyph->bitmap.buffer[ioffset] << ((x % 2) * 4)) & 7;
+ r = g = b = CLAMP((t >> 4) * 0x25, 0, 0xff);
+ break;
+ case FT_PIXEL_MODE_GRAY:
+ ioffset += x;
+ r = g = b = face->glyph->bitmap.buffer[ioffset];
+ break;
+ case FT_PIXEL_MODE_LCD:
+ case FT_PIXEL_MODE_LCD_V:
+ ioffset += (x * 3);
+ r = face->glyph->bitmap.buffer[ioffset++];
+ g = face->glyph->bitmap.buffer[ioffset++];
+ b = face->glyph->bitmap.buffer[ioffset++];
+ break;
+ default:
+ r = g = b = 0;
+ g_assert_not_reached();
+ break;
+ }
+ if (face->glyph->bitmap.pitch > 0) {
+ g_assert(ioffset < ((y + 1) * face->glyph->bitmap.pitch));
+ } else {
+ g_assert(ioffset < ((y + 1) * -face->glyph->bitmap.pitch));
+ }
+ glyph->bytes[ooffset + 0] = r;
+ glyph->bytes[ooffset + 1] = g;
+ glyph->bytes[ooffset + 2] = b;
+ glyph->bytes[ooffset + 3] = 0xff;
+ }
+
+ /* Cache it. */
+ g_tree_insert(cache->cache, GINT_TO_POINTER(c), glyph);
+
+ return glyph;
+}
+
+void
+_vte_glyph_draw(struct _vte_glyph_cache *cache,
+ gunichar c, GdkColor *color,
+ gint x, gint y, gint columns,
+ enum vte_glyph_flags flags,
+ struct _vte_rgb_buffer *buffer)
+{
+ const struct _vte_glyph *glyph;
+ gint col, row, ioffset, ooffset, icol, ocol, ecol;
+ gint strikethrough, underline, underline2;
+ gint32 r, g, b, ar, ag, ab;
+ guchar *pixels;
+
+ if (cache == NULL) {
+ return;
+ }
+ glyph = _vte_glyph_get(cache, _vte_glyph_remap_char(cache, c));
+ if (glyph == NULL) {
+ return;
+ }
+
+ if (x > buffer->width) {
+ return;
+ }
+ if (y > buffer->height) {
+ return;
+ }
+
+ pixels = buffer->pixels;
+ r = color->red >> 8;
+ g = color->green >> 8;
+ b = color->blue >> 8;
+
+ if (cache->ascent > 0) {
+ strikethrough = cache->ascent >> 1;
+ underline = cache->ascent + 1;
+ underline2 = cache->ascent + 2;
+ } else {
+ strikethrough = MAX(0, cache->height >> 1);
+ underline = MAX(0, cache->height - 2);
+ underline2 = MAX(0, cache->height - 1);
+ }
+
+ icol = MAX(0, (glyph->width - (columns * cache->width)) >> 1);
+ ocol = MAX(0, ((columns * cache->width) - glyph->width) >> 1);
+
+_vte_glyph_draw_loop:
+
+ for (row = glyph->skip;
+ row < MIN(cache->height, glyph->skip + glyph->height);
+ row++) {
+ if (row + y >= buffer->height) {
+ break;
+ }
+ ooffset = (y + row) * buffer->stride +
+ ((x + ocol) * 3);
+ ioffset = (((row - glyph->skip) * glyph->width) + icol) * 4;
+ ecol = MIN(cache->width * columns, glyph->width);
+ for (col = 0; col < ecol; col++) {
+ if (col + x >= buffer->width) {
+ break;
+ }
+ ar = glyph->bytes[ioffset + 0];
+ ag = glyph->bytes[ioffset + 1];
+ ab = glyph->bytes[ioffset + 2];
+ ioffset += glyph->bytes_per_pixel;
+
+ if (flags & vte_glyph_dim) {
+ ar = ar >> 1;
+ ag = ag >> 1;
+ ab = ab >> 1;
+ }
+
+ switch (ar) {
+ case 0:
+ break;
+ case 0xff:
+ pixels[ooffset + 0] = r;
+ break;
+ default:
+ pixels[ooffset + 0] +=
+ (((r - pixels[ooffset + 0]) * ar) >> 8);
+ break;
+ }
+
+ switch (ag) {
+ case 0:
+ break;
+ case 0xff:
+ pixels[ooffset + 1] = g;
+ break;
+ default:
+ pixels[ooffset + 1] +=
+ (((g - pixels[ooffset + 1]) * ag) >> 8);
+ break;
+ }
+
+ switch (ab) {
+ case 0:
+ break;
+ case 0xff:
+ pixels[ooffset + 2] = b;
+ break;
+ default:
+ pixels[ooffset + 2] +=
+ (((b - pixels[ooffset + 2]) * ab) >> 8);
+ break;
+ }
+
+ ooffset += 3;
+ }
+ }
+
+ if (flags &
+ (vte_glyph_underline | vte_glyph_underline2 |
+ vte_glyph_strikethrough | vte_glyph_boxed)) {
+ for (col = 0; col < cache->width; col++) {
+ if ((flags & vte_glyph_strikethrough) &&
+ (strikethrough >= 0) &&
+ (strikethrough < cache->height)) {
+ ooffset = (y + strikethrough) * buffer->stride +
+ (x + col) * 3;
+ pixels[ooffset + 0] = r;
+ pixels[ooffset + 1] = g;
+ pixels[ooffset + 2] = b;
+ }
+ if ((flags & vte_glyph_underline) &&
+ (underline >= 0) &&
+ (underline < cache->height)) {
+ ooffset = (y + underline) * buffer->stride +
+ (x + col) * 3;
+ pixels[ooffset + 0] = r;
+ pixels[ooffset + 1] = g;
+ pixels[ooffset + 2] = b;
+ }
+ if ((flags & vte_glyph_underline2) &&
+ (underline2 >= 0) &&
+ (underline2 < cache->height)) {
+ ooffset = (y + underline2) * buffer->stride +
+ (x + col) * 3;
+ pixels[ooffset + 0] = r;
+ pixels[ooffset + 1] = g;
+ pixels[ooffset + 2] = b;
+ }
+ if (flags & vte_glyph_boxed) {
+ ooffset = y * buffer->stride + (x + col) * 3;
+ pixels[ooffset + 0] = r;
+ pixels[ooffset + 1] = g;
+ pixels[ooffset + 2] = b;
+ ooffset = (y + cache->height - 1) * buffer->stride +
+ (x + col) * 3;
+ pixels[ooffset + 0] = r;
+ pixels[ooffset + 1] = g;
+ pixels[ooffset + 2] = b;
+ }
+ }
+ }
+
+ if (flags & vte_glyph_bold) {
+ flags &= ~vte_glyph_bold;
+ pixels += 3;
+ goto _vte_glyph_draw_loop;
+ }
+}
+
+void
+_vte_glyph_draw_string(struct _vte_glyph_cache *cache,
+ const char *s, GdkColor *color,
+ gint x, gint y,
+ enum vte_glyph_flags flags,
+ struct _vte_rgb_buffer *buffer)
+{
+ gunichar c;
+ gint width;
+
+ if (y + cache->height > buffer->height) {
+ return;
+ }
+
+ while (*s != '\0') {
+ c = g_utf8_get_char(s);
+ width = 1; /* FIXME */
+ if (x + width * cache->width > buffer->width) {
+ break;
+ }
+ _vte_glyph_draw(cache, c, color, x, y, width, flags, buffer);
+ x += (width * cache->width);
+ s = g_utf8_next_char(s);
+ }
+}
diff --git a/src/vteglyph.h b/src/vteglyph.h
new file mode 100644
index 0000000..6629a9c
--- /dev/null
+++ b/src/vteglyph.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2002,2003 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef vte_vteglyph_h_included
+#define vte_vteglyph_h_included
+
+#ident "$Id$"
+
+#include <glib.h>
+#include "vtergb.h"
+
+#include <fontconfig/fontconfig.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+enum vte_glyph_flags {
+ vte_glyph_bold = 1 << 0,
+ vte_glyph_dim = 1 << 1,
+ vte_glyph_underline = 1 << 2,
+ vte_glyph_underline2 = 1 << 3,
+ vte_glyph_strikethrough = 1 << 4,
+ vte_glyph_boxed = 1 << 5,
+};
+
+#define vte_glyph_double_underline \
+ (vte_glyph_underline | vte_glyph_underline2)
+#define vte_glyph_all \
+ (vte_glyph_bold | vte_glyph_dim | \
+ vte_glyph_underline | vte_glyph_underline2 | \
+ vte_glyph_strikethrough | vte_glyph_boxed)
+
+struct _vte_glyph {
+ glong width;
+ glong height;
+ glong skip;
+ guchar bytes_per_pixel;
+ guchar bytes[1];
+};
+
+struct _vte_glyph_cache {
+ GArray *patterns;
+ GList *faces;
+ GTree *cache;
+ gint ft_load_flags;
+ gint ft_render_flags;
+ glong width, height, ascent;
+ FT_Library ft_library;
+};
+
+struct _vte_glyph_cache *_vte_glyph_cache_new(void);
+void _vte_glyph_cache_free(struct _vte_glyph_cache *cache);
+const FcPattern *_vte_glyph_cache_get_pattern(struct _vte_glyph_cache *cache);
+void _vte_glyph_cache_set_description(FcConfig *config,
+ struct _vte_glyph_cache *cache,
+ const PangoFontDescription *fontdesc);
+gboolean _vte_glyph_cache_has_char(struct _vte_glyph_cache *cache, gunichar c);
+const struct _vte_glyph *_vte_glyph_get(struct _vte_glyph_cache *cache,
+ gunichar c);
+void _vte_glyph_draw(struct _vte_glyph_cache *cache,
+ gunichar c, GdkColor *color,
+ gint x, gint y, gint columns,
+ enum vte_glyph_flags flags,
+ struct _vte_rgb_buffer *buffer);
+void _vte_glyph_draw_string(struct _vte_glyph_cache *cache,
+ const char *s, GdkColor *color,
+ gint x, gint y,
+ enum vte_glyph_flags flags,
+ struct _vte_rgb_buffer *buffer);
+
+#endif
diff --git a/src/vtepango.c b/src/vtepango.c
index ced2902..13cffcf 100644
--- a/src/vtepango.c
+++ b/src/vtepango.c
@@ -94,6 +94,18 @@ _vte_pango_destroy(struct _vte_draw *draw)
g_free(draw->impl_data);
}
+static GdkVisual *
+_vte_pango_get_visual(struct _vte_draw *draw)
+{
+ return gtk_widget_get_visual(draw->widget);
+}
+
+static GdkColormap *
+_vte_pango_get_colormap(struct _vte_draw *draw)
+{
+ return gtk_widget_get_colormap(draw->widget);
+}
+
static void
_vte_pango_start(struct _vte_draw *draw)
{
@@ -148,8 +160,7 @@ _vte_pango_set_background_color(struct _vte_draw *draw, GdkColor *color)
}
static void
-_vte_pango_set_background_pixbuf(struct _vte_draw *draw, GdkPixbuf *pixbuf,
- gboolean pan, gboolean scroll)
+_vte_pango_set_background_pixbuf(struct _vte_draw *draw, GdkPixbuf *pixbuf)
{
GdkColormap *colormap;
GdkPixmap *pixmap;
@@ -287,12 +298,12 @@ _vte_pango_set_text_font(struct _vte_draw *draw,
draw->width = howmany(draw->width, PANGO_SCALE);
draw->height = howmany(logical.height, PANGO_SCALE);
- draw->base = draw->height;
+ draw->ascent = draw->height;
#ifdef VTE_DEBUG
if (_vte_debug_on(VTE_DEBUG_MISC)) {
fprintf(stderr, "VtePango font metrics = %dx%d (%d).\n",
- draw->width, draw->height, draw->base);
+ draw->width, draw->height, draw->ascent);
}
#endif
}
@@ -310,9 +321,9 @@ _vte_pango_get_text_height(struct _vte_draw *draw)
}
static int
-_vte_pango_get_text_base(struct _vte_draw *draw)
+_vte_pango_get_text_ascent(struct _vte_draw *draw)
{
- return draw->base;
+ return draw->ascent;
}
static void
@@ -378,20 +389,6 @@ _vte_pango_fill_rectangle(struct _vte_draw *draw,
x, y, width, height);
}
-static gboolean
-_vte_pango_scroll(struct _vte_draw *draw, gint dx, gint dy)
-{
- struct _vte_pango_data *data;
- data = (struct _vte_pango_data*) draw->impl_data;
- if (GDK_IS_WINDOW(draw->widget->window)) {
- gdk_window_scroll(GDK_WINDOW(draw->widget->window), dx, dy);
- data->scrollx += dx;
- data->scrolly += dy;
- return TRUE;
- }
- return FALSE;
-}
-
static void
_vte_pango_set_scroll(struct _vte_draw *draw, gint x, gint y)
{
@@ -406,6 +403,8 @@ struct _vte_draw_impl _vte_draw_pango = {
_vte_pango_check,
_vte_pango_create,
_vte_pango_destroy,
+ _vte_pango_get_visual,
+ _vte_pango_get_colormap,
_vte_pango_start,
_vte_pango_end,
_vte_pango_set_background_color,
@@ -414,10 +413,9 @@ struct _vte_draw_impl _vte_draw_pango = {
_vte_pango_set_text_font,
_vte_pango_get_text_width,
_vte_pango_get_text_height,
- _vte_pango_get_text_base,
+ _vte_pango_get_text_ascent,
_vte_pango_draw_text,
_vte_pango_draw_rectangle,
_vte_pango_fill_rectangle,
- _vte_pango_scroll,
_vte_pango_set_scroll,
};
diff --git a/src/vtepangox.c b/src/vtepangox.c
new file mode 100644
index 0000000..1d765c6
--- /dev/null
+++ b/src/vtepangox.c
@@ -0,0 +1,466 @@
+/*
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "../config.h"
+
+#ifdef HAVE_PANGOX
+
+#include <sys/param.h>
+#include <stdio.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <pango/pango.h>
+#include "debug.h"
+#include "vtedraw.h"
+#include "vtepangox.h"
+
+#include <pango/pangox.h>
+#include <gdk/gdkx.h>
+
+struct _vte_pango_x_data
+{
+ GdkColor color;
+ GdkPixmap *pixmap;
+ gint pixmapw, pixmaph;
+ gint scrollx, scrolly;
+ PangoFontDescription *font;
+ PangoLayout *layout;
+ GdkGC *gc;
+ PangoContext *ctx;
+ Drawable drawable;
+ int x_offs, y_offs;
+};
+
+static gboolean
+_vte_pango_x_check(struct _vte_draw *draw, GtkWidget *widget)
+{
+ /* We can draw onto any widget. */
+ return TRUE;
+}
+
+static void
+_vte_pango_x_create(struct _vte_draw *draw, GtkWidget *widget)
+{
+ struct _vte_pango_x_data *data;
+
+ draw->impl_data = g_malloc(sizeof(struct _vte_pango_x_data));
+ data = (struct _vte_pango_x_data*) draw->impl_data;
+
+ data->color.red = 0;
+ data->color.green = 0;
+ data->color.blue = 0;
+ data->pixmap = NULL;
+ data->pixmapw = data->pixmaph = 0;
+ data->scrollx = data->scrolly = 0;
+ data->font = NULL;
+ data->layout = NULL;
+ data->gc = NULL;
+ data->ctx = NULL;
+}
+
+static void
+_vte_pango_x_destroy(struct _vte_draw *draw)
+{
+ struct _vte_pango_x_data *data;
+ data = (struct _vte_pango_x_data*) draw->impl_data;
+
+ data->scrollx = data->scrolly = 0;
+
+ if (GDK_IS_PIXMAP(data->pixmap)) {
+ g_object_unref(G_OBJECT(data->pixmap));
+ data->pixmap = NULL;
+ data->pixmapw = data->pixmaph = 0;
+ }
+ if (data->font != NULL) {
+ pango_font_description_free(data->font);
+ data->font = NULL;
+ }
+ if (PANGO_IS_LAYOUT(data->layout)) {
+ g_object_unref(G_OBJECT(data->layout));
+ data->layout = NULL;
+ }
+ if (GDK_IS_GC(data->gc)) {
+ g_object_unref(G_OBJECT(data->gc));
+ data->gc = NULL;
+ }
+ if (PANGO_IS_CONTEXT(data->ctx)) {
+ g_object_unref(G_OBJECT(data->ctx));
+ data->ctx = NULL;
+ }
+
+ memset(&data->color, 0, sizeof(data->color));
+
+ g_free(draw->impl_data);
+}
+
+static GdkVisual *
+_vte_pango_x_get_visual(struct _vte_draw *draw)
+{
+ return gtk_widget_get_visual(draw->widget);
+}
+
+static GdkColormap *
+_vte_pango_x_get_colormap(struct _vte_draw *draw)
+{
+ return gtk_widget_get_colormap(draw->widget);
+}
+
+static void
+_vte_pango_x_start(struct _vte_draw *draw)
+{
+ struct _vte_pango_x_data *data;
+ Display *display;
+ GdkDrawable *drawable;
+ int x_offs, y_offs;
+
+ data = (struct _vte_pango_x_data*) draw->impl_data;
+
+ display = gdk_x11_drawable_get_xdisplay(draw->widget->window);
+ if (PANGO_IS_CONTEXT(data->ctx)) {
+ g_object_unref(G_OBJECT(data->ctx));
+ }
+ data->ctx = pango_x_get_context(display);
+
+ if (PANGO_IS_LAYOUT(data->layout)) {
+ g_object_unref(G_OBJECT(data->layout));
+ }
+ data->layout = pango_layout_new(data->ctx);
+
+ if (data->font) {
+ pango_layout_set_font_description(data->layout, data->font);
+ }
+
+ if (GDK_IS_GC(data->gc)) {
+ g_object_unref(G_OBJECT(data->gc));
+ }
+ data->gc = gdk_gc_new(draw->widget->window);
+
+ gdk_rgb_find_color(gdk_drawable_get_colormap(draw->widget->window),
+ &data->color);
+
+ gdk_window_get_internal_paint_info(draw->widget->window, &drawable,
+ &x_offs, &y_offs);
+ data->drawable = gdk_x11_drawable_get_xid(drawable);
+ data->x_offs = x_offs;
+ data->y_offs = y_offs;
+}
+
+static void
+_vte_pango_x_end(struct _vte_draw *draw)
+{
+ struct _vte_pango_x_data *data;
+ data = (struct _vte_pango_x_data*) draw->impl_data;
+
+ data->drawable = -1;
+ data->x_offs = 0;
+ data->y_offs = 0;
+
+ if (PANGO_IS_LAYOUT(data->layout)) {
+ g_object_unref(G_OBJECT(data->layout));
+ }
+ data->layout = NULL;
+
+ if (GDK_IS_GC(data->gc)) {
+ g_object_unref(G_OBJECT(data->gc));
+ }
+ data->gc = NULL;
+
+ if (PANGO_IS_CONTEXT(data->ctx)) {
+ g_object_unref(G_OBJECT(data->ctx));
+ }
+ data->ctx = NULL;
+}
+
+static void
+_vte_pango_x_set_background_color(struct _vte_draw *draw, GdkColor *color)
+{
+ struct _vte_pango_x_data *data;
+ data = (struct _vte_pango_x_data*) draw->impl_data;
+ data->color = *color;
+}
+
+static void
+_vte_pango_x_set_background_pixbuf(struct _vte_draw *draw, GdkPixbuf *pixbuf)
+{
+ GdkColormap *colormap;
+ GdkPixmap *pixmap;
+ GdkBitmap *bitmap;
+ struct _vte_pango_x_data *data;
+
+ data = (struct _vte_pango_x_data*) draw->impl_data;
+ if (data->pixmap) {
+ g_object_unref(G_OBJECT(data->pixmap));
+ data->pixmap = NULL;
+ data->pixmapw = data->pixmaph = 0;
+ }
+ if ((pixbuf != NULL) &&
+ (gdk_pixbuf_get_width(pixbuf) > 0) &&
+ (gdk_pixbuf_get_height(pixbuf) > 0)) {
+ colormap = gdk_drawable_get_colormap(draw->widget->window);
+ gdk_pixbuf_render_pixmap_and_mask_for_colormap(pixbuf, colormap,
+ &pixmap, &bitmap,
+ 0);
+ if (bitmap) {
+ g_object_unref(G_OBJECT(bitmap));
+ }
+ if (pixmap) {
+ data->pixmap = pixmap;
+ data->pixmapw = gdk_pixbuf_get_width(pixbuf);
+ data->pixmaph = gdk_pixbuf_get_height(pixbuf);
+ }
+ }
+}
+
+static void
+_vte_pango_x_clear(struct _vte_draw *draw,
+ gint x, gint y, gint width, gint height)
+{
+ struct _vte_pango_x_data *data;
+ gint i, j, istart, jstart, h, w, xstop, ystop;
+
+ data = (struct _vte_pango_x_data*) draw->impl_data;
+
+ if ((data->pixmap == NULL) ||
+ (data->pixmapw == 0) ||
+ (data->pixmaph == 0)) {
+ gdk_gc_set_foreground(data->gc, &data->color);
+ gdk_draw_rectangle(draw->widget->window,
+ data->gc,
+ TRUE,
+ x, y, width, height);
+ return;
+ }
+
+ /* Determine the origin of the pixmap if x = y = 0. */
+ i = data->scrollx % data->pixmapw;
+ j = data->scrolly % data->pixmaph;
+
+ /* Adjust the drawing offsets. */
+ istart = (i + x) % data->pixmapw;
+ jstart = (j + y) % data->pixmaph;
+
+ /* Flood fill. */
+ xstop = x + width;
+ ystop = y + height;
+ j = jstart;
+ while (y < ystop) {
+ h = MIN(data->pixmaph - (j % data->pixmaph),
+ ystop - j);
+ i = istart;
+ while (x < xstop) {
+ w = MIN(data->pixmapw - (i % data->pixmapw),
+ xstop - i);
+ gdk_draw_drawable(draw->widget->window,
+ data->gc,
+ data->pixmap,
+ i, j,
+ x, y,
+ w, h);
+ x += w;
+ i = 0;
+ }
+ y += h;
+ j = 0;
+ }
+}
+
+static void
+_vte_pango_x_set_text_font(struct _vte_draw *draw,
+ const PangoFontDescription *fontdesc)
+{
+ GdkScreen *screen;
+ PangoContext *ctx;
+ PangoLayout *layout;
+ PangoRectangle ink, logical;
+ gunichar full_codepoints[] = {VTE_DRAW_DOUBLE_WIDE_CHARACTERS};
+ GString *full_string;
+ gint full_width;
+ int i;
+ struct _vte_pango_x_data *data;
+
+ data = (struct _vte_pango_x_data*) draw->impl_data;
+
+ screen = gdk_screen_get_default();
+ ctx = gdk_pango_context_get_for_screen(screen);
+ layout = pango_layout_new(ctx);
+ if (data->font != NULL) {
+ pango_font_description_free(data->font);
+ }
+ data->font = pango_font_description_copy(fontdesc);
+ pango_layout_set_font_description(layout, data->font);
+
+ /* Estimate for ASCII characters. */
+ pango_layout_set_text(layout,
+ VTE_DRAW_SINGLE_WIDE_CHARACTERS,
+ strlen(VTE_DRAW_SINGLE_WIDE_CHARACTERS));
+ pango_layout_get_extents(layout, &ink, &logical);
+ draw->width = logical.width;
+ draw->width = howmany(draw->width,
+ strlen(VTE_DRAW_SINGLE_WIDE_CHARACTERS));
+
+ /* Estimate for CJK characters. */
+ full_width = draw->width * 2;
+ full_string = g_string_new("");
+ for (i = 0; i < G_N_ELEMENTS(full_codepoints); i++) {
+ g_string_append_unichar(full_string, full_codepoints[i]);
+ }
+ pango_layout_set_text(layout, full_string->str, full_string->len);
+ pango_layout_get_extents(layout, &ink, &logical);
+ full_width = howmany(logical.width, G_N_ELEMENTS(full_codepoints));
+ g_string_free(full_string, TRUE);
+
+ /* If they're the same, then we have a screwy font. */
+ if (full_width == draw->width) {
+ draw->width /= 2;
+ }
+
+ g_object_unref(G_OBJECT(layout));
+
+ draw->width = howmany(draw->width, PANGO_SCALE);
+ draw->height = howmany(logical.height, PANGO_SCALE);
+ draw->ascent = draw->height;
+
+#ifdef VTE_DEBUG
+ if (_vte_debug_on(VTE_DEBUG_MISC)) {
+ fprintf(stderr, "VtePango font metrics = %dx%d (%d).\n",
+ draw->width, draw->height, draw->ascent);
+ }
+#endif
+}
+
+static int
+_vte_pango_x_get_text_width(struct _vte_draw *draw)
+{
+ return draw->width;
+}
+
+static int
+_vte_pango_x_get_text_height(struct _vte_draw *draw)
+{
+ return draw->height;
+}
+
+static int
+_vte_pango_x_get_text_ascent(struct _vte_draw *draw)
+{
+ return draw->ascent;
+}
+
+static void
+_vte_pango_x_draw_text(struct _vte_draw *draw,
+ struct _vte_draw_text_request *requests,
+ gsize n_requests,
+ GdkColor *color, guchar alpha)
+{
+ Display *display;
+ GC gc;
+ struct _vte_pango_x_data *data;
+ char buf[VTE_UTF8_BPC];
+ int i;
+ gsize length;
+ GdkColor wcolor;
+
+ data = (struct _vte_pango_x_data*) draw->impl_data;
+
+ wcolor = *color;
+ gdk_rgb_find_color(gdk_drawable_get_colormap(draw->widget->window),
+ &wcolor);
+ gdk_gc_set_foreground(data->gc, &wcolor);
+ display = gdk_x11_drawable_get_xdisplay(draw->widget->window);
+ gc = gdk_x11_gc_get_xgc(data->gc);
+
+ for (i = 0; i < n_requests; i++) {
+ length = g_unichar_to_utf8(requests[i].c, buf);
+ pango_layout_set_text(data->layout, buf, length);
+ pango_x_render_layout(display,
+ data->drawable,
+ gc,
+ data->layout,
+ requests[i].x - data->x_offs,
+ requests[i].y - data->y_offs);
+ }
+}
+
+static void
+_vte_pango_x_draw_rectangle(struct _vte_draw *draw,
+ gint x, gint y, gint width, gint height,
+ GdkColor *color, guchar alpha)
+{
+ struct _vte_pango_x_data *data;
+ GdkColor wcolor;
+
+ data = (struct _vte_pango_x_data*) draw->impl_data;
+
+ wcolor = *color;
+ gdk_rgb_find_color(gdk_drawable_get_colormap(draw->widget->window),
+ &wcolor);
+ gdk_gc_set_foreground(data->gc, &wcolor);
+
+ gdk_draw_rectangle(draw->widget->window, data->gc, FALSE,
+ x, y, width, height);
+}
+
+static void
+_vte_pango_x_fill_rectangle(struct _vte_draw *draw,
+ gint x, gint y, gint width, gint height,
+ GdkColor *color, guchar alpha)
+{
+ struct _vte_pango_x_data *data;
+ GdkColor wcolor;
+
+ data = (struct _vte_pango_x_data*) draw->impl_data;
+ wcolor = *color;
+ gdk_rgb_find_color(gdk_drawable_get_colormap(draw->widget->window),
+ &wcolor);
+ gdk_gc_set_foreground(data->gc, &wcolor);
+ gdk_draw_rectangle(draw->widget->window, data->gc, TRUE,
+ x, y, width, height);
+}
+
+static void
+_vte_pango_x_set_scroll(struct _vte_draw *draw, gint x, gint y)
+{
+ struct _vte_pango_x_data *data;
+ data = (struct _vte_pango_x_data*) draw->impl_data;
+ data->scrollx = x;
+ data->scrolly = y;
+}
+
+struct _vte_draw_impl _vte_draw_pango_x = {
+ "VtePangoX", "VTE_USE_PANGOX",
+ _vte_pango_x_check,
+ _vte_pango_x_create,
+ _vte_pango_x_destroy,
+ _vte_pango_x_get_visual,
+ _vte_pango_x_get_colormap,
+ _vte_pango_x_start,
+ _vte_pango_x_end,
+ _vte_pango_x_set_background_color,
+ _vte_pango_x_set_background_pixbuf,
+ _vte_pango_x_clear,
+ _vte_pango_x_set_text_font,
+ _vte_pango_x_get_text_width,
+ _vte_pango_x_get_text_height,
+ _vte_pango_x_get_text_ascent,
+ _vte_pango_x_draw_text,
+ _vte_pango_x_draw_rectangle,
+ _vte_pango_x_fill_rectangle,
+ _vte_pango_x_set_scroll,
+};
+
+#endif
diff --git a/src/vtepangox.h b/src/vtepangox.h
new file mode 100644
index 0000000..4f83146
--- /dev/null
+++ b/src/vtepangox.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef vte_vtepangox_h_included
+#define vte_vtepangox_h_included
+
+/* The interfaces in this file are subject to change at any time. */
+
+#ident "$Id$"
+
+#include "../config.h"
+#include "vtedraw.h"
+
+G_BEGIN_DECLS
+
+extern struct _vte_draw_impl _vte_draw_pango_x;
+
+G_END_DECLS
+
+#endif
diff --git a/src/vtergb.c b/src/vtergb.c
new file mode 100644
index 0000000..c0aba9b
--- /dev/null
+++ b/src/vtergb.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ident "$Id$"
+
+#include "../config.h"
+#include <gdk/gdk.h>
+#include <glib.h>
+#include <fontconfig/fontconfig.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include "vtergb.h"
+
+struct _vte_rgb_buffer_p {
+ guchar *pixels;
+ gint width, height, stride;
+ gint length;
+};
+
+struct _vte_rgb_buffer *
+_vte_rgb_buffer_new(gint width, gint height)
+{
+ struct _vte_rgb_buffer_p *ret;
+
+ ret = g_malloc0(sizeof(*ret));
+
+ width = MAX(width, 1);
+ height = MAX(height, 1);
+
+ ret->width = width;
+ ret->height = height;
+ ret->stride = width * 3;
+ ret->length = width * height * 3;
+ ret->pixels = g_malloc(ret->length);
+
+ return (struct _vte_rgb_buffer *) ret;
+}
+
+void
+_vte_rgb_buffer_free(struct _vte_rgb_buffer *buffer)
+{
+ struct _vte_rgb_buffer_p *buf = (struct _vte_rgb_buffer_p *) buffer;
+
+ g_free(buf->pixels);
+
+ buf->length = 0;
+ buf->stride = 0;
+ buf->height = 0;
+ buf->width = 0;
+ buf->pixels = NULL;
+
+ g_free(buf);
+}
+
+void
+_vte_rgb_buffer_resize(struct _vte_rgb_buffer *buffer,
+ gint minimum_width,
+ gint minimum_height)
+{
+ struct _vte_rgb_buffer_p *buf = (struct _vte_rgb_buffer_p *) buffer;
+ gssize size = minimum_width * minimum_height * 3;
+
+ if (size > buf->length) {
+ g_free(buf->pixels);
+ buf->length = size;
+ buf->pixels = g_malloc(buf->length);
+ }
+
+ buf->width = minimum_width;
+ buf->height = minimum_height;
+ buf->stride = buf->width * 3;
+}
+
+void
+_vte_rgb_draw_color_rgb(struct _vte_rgb_buffer *buffer,
+ gint x, gint y, gint width, gint height,
+ guchar r, guchar g, guchar b)
+{
+ gint row, rows, col, cols;
+ gint offset, dest, count;
+ guchar *pixels;
+
+ /* Perform a simple clipping check. */
+ if (x > buffer->width) {
+ return;
+ }
+ if (y > buffer->height) {
+ return;
+ }
+
+ /* Find the lower right corner. */
+ pixels = buffer->pixels;
+ rows = MIN(y + height, buffer->height);
+ cols = MIN(x + width, buffer->width);
+
+ /* If we had negative or nonsensical width or height, bail. */
+ if (rows <= y) {
+ return;
+ }
+ if (cols <= x) {
+ return;
+ }
+
+ /* Draw the first row by iteration. */
+ dest = y * buffer->stride + x * 3;
+ offset = dest;
+ for (col = x; col < cols; col++) {
+ pixels[dest++] = r;
+ pixels[dest++] = g;
+ pixels[dest++] = b;
+ }
+
+ /* Draw the other rows by copying the data. */
+ count = width * 3;
+ for (row = y + 1; row < rows; row++) {
+ dest = row * buffer->stride + x * 3;
+ memmove(pixels + dest, pixels + offset, count);
+ }
+}
+
+void
+_vte_rgb_draw_color(struct _vte_rgb_buffer *buffer,
+ gint x, gint y, gint width, gint height, GdkColor *color)
+{
+ guchar r, g, b;
+ r = MIN(color->red >> 8, 0xff);
+ g = MIN(color->green >> 8, 0xff);
+ b = MIN(color->blue >> 8, 0xff);
+ _vte_rgb_draw_color_rgb(buffer, x, y, width, height, r, g, b);
+}
+
+void
+_vte_rgb_draw_pixbuf(struct _vte_rgb_buffer *buffer,
+ gint x, gint y, gint width, gint height,
+ GdkPixbuf *pixbuf, gint xbias, gint ybias)
+{
+ struct _vte_rgb_buffer_p *buf = (struct _vte_rgb_buffer_p *) buffer;
+ gint row, col, rows, cols;
+ guchar bits, channels, *ipixels, *pixels;
+ gint ioffset, offset, istride, stride, iwidth, iheight, ix, iy, irange;
+
+ /* Find the stopping points. */
+ cols = MIN(x + width, buffer->width);
+ rows = MIN(y + height, buffer->height);
+ if (cols < x) {
+ return;
+ }
+ if (rows < y) {
+ return;
+ }
+
+ /* Check that we can handle the pixbuf format. */
+ bits = gdk_pixbuf_get_bits_per_sample(pixbuf);
+ g_assert(bits == 8);
+ channels = gdk_pixbuf_get_n_channels(pixbuf);
+
+ /* Get the addresses of the pixels and set things up. */
+ ipixels = gdk_pixbuf_get_pixels(pixbuf);
+ pixels = buf->pixels;
+ istride = gdk_pixbuf_get_rowstride(pixbuf);
+ stride = buf->stride;
+ iwidth = gdk_pixbuf_get_width(pixbuf);
+ iheight = gdk_pixbuf_get_height(pixbuf);
+ xbias %= iwidth;
+ ybias %= iheight;
+
+ /* Start at the first row of the pixbuf we want. */
+ iy = ybias;
+ row = y;
+ while (row < rows) {
+ /* If the source layout is the same as the output, we can
+ * use memcpy, otherwise we need to do it the slow way. */
+ if (channels == 3) {
+ /* Get the offset for this row, and find the
+ * first column. */
+ ix = xbias;
+ col = x;
+ while (col < cols) {
+ /* Calculate the destination, the number of
+ * pixels to copy, and the source location. */
+ irange = MIN(cols - col, iwidth - ix);
+ offset = row * stride + col * 3;
+ ioffset = iy * istride + ix * 3;
+ /* Copy a range of pixels . */
+ memcpy(pixels + offset,
+ ipixels + ioffset,
+ irange * 3);
+ /* Move on to the next range, wrapping
+ * if necessary. */
+ col += irange;
+ ix += irange;
+ ix %= iwidth;
+ }
+ /* Move on to the next row, wrapping if necessary. */
+ iy++;
+ iy %= iheight;
+ } else {
+ /* Get the offset for this row, and find the
+ * first column. */
+ ix = xbias;
+ offset = row * stride + x * 3;
+ col = x;
+ while (col < cols) {
+ ioffset = iy * istride + ix * channels;
+ /* Copy one pixel . */
+ pixels[offset++] = ipixels[ioffset++];
+ pixels[offset++] = ipixels[ioffset++];
+ pixels[offset++] = ipixels[ioffset++];
+ /* Move on to the next pixel, wrapping
+ * if necessary. */
+ ix++;
+ ix %= iwidth;
+ col++;
+ }
+ /* Move on to the next row, wrapping if necessary. */
+ iy++;
+ iy %= iheight;
+ }
+ row++;
+ }
+}
+
+void
+_vte_rgb_draw_on_drawable(GdkDrawable *drawable, GdkGC *gc,
+ gint x, gint y, gint width, gint height,
+ struct _vte_rgb_buffer *buffer,
+ gint xbias, gint ybias)
+{
+ g_return_if_fail(xbias + width <= buffer->width);
+ g_return_if_fail(ybias + height <= buffer->height);
+ g_return_if_fail((xbias + width) * 3 <= buffer->stride);
+ gdk_draw_rgb_image(drawable, gc, x, y, width, height,
+ GDK_RGB_DITHER_NORMAL,
+ buffer->pixels +
+ ybias * buffer->stride +
+ xbias * 3,
+ buffer->stride);
+}
+
+void
+_vte_rgb_buffer_clear(struct _vte_rgb_buffer *buffer)
+{
+ struct _vte_rgb_buffer_p *buf = (struct _vte_rgb_buffer_p *) buffer;
+ memset(buf->pixels, '\0', buf->length);
+}
diff --git a/src/vtergb.h b/src/vtergb.h
new file mode 100644
index 0000000..6685873
--- /dev/null
+++ b/src/vtergb.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef vte_vte_rgb_h_included
+#define vte_vte_rgb_h_included
+
+#ident "$Id$"
+
+#include <gdk/gdk.h>
+#include <glib.h>
+
+struct _vte_rgb_buffer {
+ guchar *pixels;
+ gint width, height, stride;
+};
+
+struct _vte_rgb_buffer *_vte_rgb_buffer_new(gint width, gint height);
+void _vte_rgb_buffer_free(struct _vte_rgb_buffer *buffer);
+void _vte_rgb_buffer_clear(struct _vte_rgb_buffer *buffer);
+void _vte_rgb_buffer_resize(struct _vte_rgb_buffer *buffer,
+ gint minimum_width, gint minimum_height);
+
+void _vte_rgb_draw_color_rgb(struct _vte_rgb_buffer *buffer,
+ gint x, gint y, gint width, gint height,
+ guchar r, guchar g, guchar b);
+void _vte_rgb_draw_color(struct _vte_rgb_buffer *buffer,
+ gint x, gint y, gint width, gint height,
+ GdkColor *color);
+void _vte_rgb_draw_pixbuf(struct _vte_rgb_buffer *buffer,
+ gint x, gint y, gint width, gint height,
+ GdkPixbuf *pixbuf, gint xbias, gint ybias);
+void _vte_rgb_draw_on_drawable(GdkDrawable *drawable, GdkGC *gc,
+ gint x, gint y, gint width, gint height,
+ struct _vte_rgb_buffer *buffer,
+ gint xbias, gint ybias);
+
+#endif
diff --git a/src/vteskel.c b/src/vteskel.c
index 2f409a3..3e11a29 100644
--- a/src/vteskel.c
+++ b/src/vteskel.c
@@ -74,6 +74,18 @@ _vte_skel_destroy(struct _vte_draw *draw)
g_free(draw->impl_data);
}
+static GdkVisual *
+_vte_skel_get_visual(struct _vte_draw *draw)
+{
+ return gtk_widget_get_visual(draw->widget);
+}
+
+static GdkColormap *
+_vte_skel_get_colormap(struct _vte_draw *draw)
+{
+ return gtk_widget_get_colormap(draw->widget);
+}
+
static void
_vte_skel_start(struct _vte_draw *draw)
{
@@ -99,12 +111,8 @@ _vte_skel_set_background_color(struct _vte_draw *draw, GdkColor *color)
}
static void
-_vte_skel_set_background_pixbuf(struct _vte_draw *draw, GdkPixbuf *pixbuf,
- gboolean pan, gboolean scroll)
+_vte_skel_set_background_pixbuf(struct _vte_draw *draw, GdkPixbuf *pixbuf)
{
- GdkColormap *colormap;
- GdkPixmap *pixmap;
- GdkBitmap *bitmap;
struct _vte_skel_data *data;
data = (struct _vte_skel_data*) draw->impl_data;
@@ -139,9 +147,9 @@ _vte_skel_get_text_height(struct _vte_draw *draw)
}
static int
-_vte_skel_get_text_base(struct _vte_draw *draw)
+_vte_skel_get_text_ascent(struct _vte_draw *draw)
{
- return draw->base;
+ return draw->ascent;
}
static void
@@ -171,14 +179,6 @@ _vte_skel_fill_rectangle(struct _vte_draw *draw,
data = (struct _vte_skel_data*) draw->impl_data;
}
-static gboolean
-_vte_skel_scroll(struct _vte_draw *draw, gint dx, gint dy)
-{
- struct _vte_skel_data *data;
- data = (struct _vte_skel_data*) draw->impl_data;
- return FALSE;
-}
-
static void
_vte_skel_set_scroll(struct _vte_draw *draw, gint x, gint y)
{
@@ -193,6 +193,8 @@ struct _vte_draw_impl _vte_draw_skel = {
_vte_skel_check,
_vte_skel_create,
_vte_skel_destroy,
+ _vte_skel_get_visual,
+ _vte_skel_get_colormap,
_vte_skel_start,
_vte_skel_end,
_vte_skel_set_background_color,
@@ -201,10 +203,9 @@ struct _vte_draw_impl _vte_draw_skel = {
_vte_skel_set_text_font,
_vte_skel_get_text_width,
_vte_skel_get_text_height,
- _vte_skel_get_text_base,
+ _vte_skel_get_text_ascent,
_vte_skel_draw_text,
_vte_skel_draw_rectangle,
_vte_skel_fill_rectangle,
- _vte_skel_scroll,
_vte_skel_set_scroll,
};
diff --git a/src/vtexft.c b/src/vtexft.c
index 1a5f322..29e62b0 100644
--- a/src/vtexft.c
+++ b/src/vtexft.c
@@ -327,6 +327,18 @@ _vte_xft_destroy(struct _vte_draw *draw)
g_free(data);
}
+static GdkVisual *
+_vte_xft_get_visual(struct _vte_draw *draw)
+{
+ return gtk_widget_get_visual(draw->widget);
+}
+
+static GdkColormap *
+_vte_xft_get_colormap(struct _vte_draw *draw)
+{
+ return gtk_widget_get_colormap(draw->widget);
+}
+
static void
_vte_xft_start(struct _vte_draw *draw)
{
@@ -501,7 +513,7 @@ _vte_xft_set_text_font(struct _vte_draw *draw,
draw->width = 1;
draw->height = 1;
- draw->base = 1;
+ draw->ascent = 1;
string = g_string_new("");
n = width = height = 0;
@@ -522,8 +534,8 @@ _vte_xft_set_text_font(struct _vte_draw *draw,
draw->width = howmany(width, n);
draw->height = (font != NULL) ?
font->ascent + font->descent : height;
- draw->base = (font != NULL) ?
- font->ascent : height;
+ draw->ascent = (font != NULL) ?
+ font->ascent : height;
}
/* Estimate a typical cell width by looking at double-width
* characters, and if it's the same as the single width, assume the
@@ -550,7 +562,7 @@ _vte_xft_set_text_font(struct _vte_draw *draw,
#ifdef VTE_DEBUG
if (_vte_debug_on(VTE_DEBUG_MISC)) {
fprintf(stderr, "VteXft font metrics = %dx%d (%d).\n",
- draw->width, draw->height, draw->base);
+ draw->width, draw->height, draw->ascent);
}
#endif
}
@@ -568,9 +580,9 @@ _vte_xft_get_text_height(struct _vte_draw *draw)
}
static int
-_vte_xft_get_text_base(struct _vte_draw *draw)
+_vte_xft_get_text_ascent(struct _vte_draw *draw)
{
- return draw->base;
+ return draw->ascent;
}
static void
@@ -602,7 +614,7 @@ _vte_xft_draw_text(struct _vte_draw *draw,
pad = CLAMP(pad / 2, 0, draw->width);
specs[j].x += pad;
}
- specs[j].y = requests[i].y - data->y_offs + draw->base;
+ specs[j].y = requests[i].y - data->y_offs + draw->ascent;
specs[j].ucs4 = requests[i].c;
j++;
} else {
@@ -687,14 +699,6 @@ _vte_xft_fill_rectangle(struct _vte_draw *draw,
}
}
-static gboolean
-_vte_xft_scroll(struct _vte_draw *draw, gint dx, gint dy)
-{
- struct _vte_xft_data *data;
- data = (struct _vte_xft_data*) draw->impl_data;
- return FALSE;
-}
-
static void
_vte_xft_set_scroll(struct _vte_draw *draw, gint x, gint y)
{
@@ -709,6 +713,8 @@ struct _vte_draw_impl _vte_draw_xft = {
_vte_xft_check,
_vte_xft_create,
_vte_xft_destroy,
+ _vte_xft_get_visual,
+ _vte_xft_get_colormap,
_vte_xft_start,
_vte_xft_end,
_vte_xft_set_background_color,
@@ -717,11 +723,10 @@ struct _vte_draw_impl _vte_draw_xft = {
_vte_xft_set_text_font,
_vte_xft_get_text_width,
_vte_xft_get_text_height,
- _vte_xft_get_text_base,
+ _vte_xft_get_text_ascent,
_vte_xft_draw_text,
_vte_xft_draw_rectangle,
_vte_xft_fill_rectangle,
- _vte_xft_scroll,
_vte_xft_set_scroll,
};
#endif
diff --git a/vte.pc.in b/vte.pc.in
index c37665e..416e102 100644
--- a/vte.pc.in
+++ b/vte.pc.in
@@ -6,6 +6,6 @@ includedir=@includedir@
Name: vte
Description: Vte terminal widget.
Version: @VERSION@
-Requires: glib-2.0 gobject-2.0 atk pango pangox gtk+-2.0 gdk-pixbuf-2.0 fontconfig xft >= 2.0
+Requires: @NEEDEDPACKAGES@
Libs: -L${libdir} -lvte @FT2_LIBS@ @OTHERLIBS@
Cflags: -I${includedir} @FT2_CFLAGS@
diff --git a/vte.spec b/vte.spec
index a3dfe3d..1eaf018 100644
--- a/vte.spec
+++ b/vte.spec
@@ -1,5 +1,5 @@
Name: vte
-Version: 0.11.0
+Version: 0.11.1
Release: 1
Summary: An experimental terminal emulator.
License: LGPL
@@ -93,6 +93,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/python*/site-packages/*.a
%{_libdir}/pkgconfig/*
%changelog
+* Wed Apr 9 2003 Nalin Dahyabhai <nalin@redhat.com> 0.11.1-1
+- rework drawing with Xft2 to use font sets
+- implement drawing with freetype using font sets
+
* Thu Jan 30 2003 Nalin Dahyabhai <nalin@redhat.com> 0.11.0-1
- start of experimental series