]> code.delx.au - gnu-emacs/blobdiff - src/ftxfont.c
* keymap.c (syms_of_keymap): Construct exclude_keys in pure memory.
[gnu-emacs] / src / ftxfont.c
index 831b75c4d4b5a7aab3265d702cfae03dd00b4f79..1f97a94e94ff21085fc2a7c542730320818878dc 100644 (file)
@@ -1,15 +1,15 @@
 /* ftxfont.c -- FreeType font driver on X (without using XFT).
 /* ftxfont.c -- FreeType font driver on X (without using XFT).
-   Copyright (C) 2006 Free Software Foundation, Inc.
-   Copyright (C) 2006
+   Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007, 2008, 2009
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H13PRO009
 
 This file is part of GNU Emacs.
 
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H13PRO009
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,12 +17,11 @@ 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 General Public License
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <stdio.h>
 
 #include <config.h>
 #include <stdio.h>
+#include <setjmp.h>
 #include <X11/Xlib.h>
 
 #include "lisp.h"
 #include <X11/Xlib.h>
 
 #include "lisp.h"
@@ -40,43 +39,87 @@ Boston, MA 02110-1301, USA.  */
 static Lisp_Object Qftx;
 
 /* Prototypes for helper function.  */
 static Lisp_Object Qftx;
 
 /* Prototypes for helper function.  */
-static int ftxfont_create_gcs P_ ((FRAME_PTR, GC *,
-                                  unsigned long, unsigned long));
-static int ftxfont_draw_bitmap P_ ((FRAME_PTR, GC *, struct font *, unsigned,
-                                   int, int, XPoint *, int, int *n));
+static GC *ftxfont_get_gcs P_ ((FRAME_PTR, unsigned long, unsigned long));
+static int ftxfont_draw_bitmap P_ ((FRAME_PTR, GC, GC *, struct font *,
+                                   unsigned, int, int, XPoint *, int, int *,
+                                   int));
 static void ftxfont_draw_backgrond P_ ((FRAME_PTR, struct font *, GC,
                                        int, int, int));
 static void ftxfont_draw_backgrond P_ ((FRAME_PTR, struct font *, GC,
                                        int, int, int));
-static Font ftxfont_default_fid P_ ((FRAME_PTR));
 
 
-/* Create 6 GCs for antialiasing by interpolating colors FOREGROUND
-   and BACKGROUND.  GCS[0] is closest to BACKGROUND, and GCS[5] is
-   closest to FOREGROUND.  */
+struct ftxfont_frame_data
+{
+  /* Background and foreground colors.  */
+  XColor colors[2];
+  /* GCs interporationg the above colors.  gcs[0] is for a color
+   closest to BACKGROUND, and gcs[5] is for a color closest to
+   FOREGROUND.  */
+  GC gcs[6];
+  struct ftxfont_frame_data *next;
+};
 
 
-static int
-ftxfont_create_gcs (f, gcs, foreground, background)
+
+/* Return an array of 6 GCs for antialiasing.  */
+
+static GC *
+ftxfont_get_gcs (f, foreground, background)
      FRAME_PTR f;
      FRAME_PTR f;
-     GC *gcs;
      unsigned long foreground, background;
 {
      unsigned long foreground, background;
 {
-  XColor colors[3];
+  XColor color;
   XGCValues xgcv;
   int i;
   XGCValues xgcv;
   int i;
+  struct ftxfont_frame_data *data = font_get_frame_data (f, &ftxfont_driver);
+  struct ftxfont_frame_data *prev = NULL, *this = NULL, *new;
 
 
-  colors[0].pixel = foreground;
-  colors[1].pixel = background;
+  if (data)
+    {
+      for (this = data; this; prev = this, this = this->next)
+       {
+         if (this->colors[0].pixel < background)
+           continue;
+         if (this->colors[0].pixel > background)
+           break;
+         if (this->colors[1].pixel < foreground)
+           continue;
+         if (this->colors[1].pixel > foreground)
+           break;
+         return this->gcs;
+       }
+    }
+
+  new = malloc (sizeof (struct ftxfont_frame_data));
+  if (! new)
+    return NULL;
+  new->next = this;
+  if (prev)
+    {
+      prev->next = new;
+    }
+  else if (font_put_frame_data (f, &ftxfont_driver, new) < 0)
+    {
+      free (new);
+      return NULL;
+    }
+
+  new->colors[0].pixel = background;
+  new->colors[1].pixel = foreground;
 
   BLOCK_INPUT;
 
   BLOCK_INPUT;
-  XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, 2);
+  XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), new->colors, 2);
   for (i = 1; i < 7; i++)
     {
   for (i = 1; i < 7; i++)
     {
-      colors[2].red = (colors[0].red * i + colors[1].red * (8 - i)) / 8;
-      colors[2].green = (colors[0].green * i + colors[1].green * (8 - i)) / 8;
-      colors[2].blue = (colors[0].blue * i + colors[1].blue * (8 - i)) / 8;
-      if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &colors[2]))
+      /* Interpolate colors linearly.  Any better algorithm?  */
+      color.red
+       = (new->colors[1].red * i + new->colors[0].red * (8 - i)) / 8;
+      color.green
+       = (new->colors[1].green * i + new->colors[0].green * (8 - i)) / 8;
+      color.blue
+       = (new->colors[1].blue * i + new->colors[0].blue * (8 - i)) / 8;
+      if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &color))
        break;
        break;
-      xgcv.foreground = colors[2].pixel;
-      gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                             GCForeground, &xgcv);
+      xgcv.foreground = color.pixel;
+      new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                                  GCForeground, &xgcv);
     }
   UNBLOCK_INPUT;
 
     }
   UNBLOCK_INPUT;
 
@@ -84,22 +127,28 @@ ftxfont_create_gcs (f, gcs, foreground, background)
     {
       BLOCK_INPUT;
       for (i--; i >= 0; i--)
     {
       BLOCK_INPUT;
       for (i--; i >= 0; i--)
-       XFreeGC (FRAME_X_DISPLAY (f), gcs[i]);
+       XFreeGC (FRAME_X_DISPLAY (f), new->gcs[i]);
       UNBLOCK_INPUT;
       UNBLOCK_INPUT;
-      return -1;
+      if (prev)
+       prev->next = new->next;
+      else if (data)
+       font_put_frame_data (f, &ftxfont_driver, new->next);
+      free (new);
+      return NULL;
     }
     }
-  return 0;
+  return new->gcs;
 }
 
 static int
 }
 
 static int
-ftxfont_draw_bitmap (f, gc, font, code, x, y, p, size, n)
+ftxfont_draw_bitmap (f, gc_fore, gcs, font, code, x, y, p, size, n, flush)
      FRAME_PTR f;
      FRAME_PTR f;
-     GC *gc;
+     GC gc_fore, *gcs;
      struct font *font;
      unsigned code;
      int x, y;
      XPoint *p;
      int size, *n;
      struct font *font;
      unsigned code;
      int x, y;
      XPoint *p;
      int size, *n;
+     int flush;
 {
   struct font_bitmap bitmap;
   unsigned char *b;
 {
   struct font_bitmap bitmap;
   unsigned char *b;
@@ -107,29 +156,38 @@ ftxfont_draw_bitmap (f, gc, font, code, x, y, p, size, n)
 
   if (ftfont_driver.get_bitmap (font, code, &bitmap, size > 0x100 ? 1 : 8) < 0)
     return 0;
 
   if (ftfont_driver.get_bitmap (font, code, &bitmap, size > 0x100 ? 1 : 8) < 0)
     return 0;
-  for (i = 0, b = bitmap.buffer; i < bitmap.rows;
-       i++, b += bitmap.pitch)
+  if (size > 0x100)
     {
     {
-      if (size > 0x100)
+      for (i = 0, b = bitmap.buffer; i < bitmap.rows;
+          i++, b += bitmap.pitch)
        {
          for (j = 0; j < bitmap.width; j++)
            if (b[j / 8] & (1 << (7 - (j % 8))))
              {
                p[n[0]].x = x + bitmap.left + j;
                p[n[0]].y = y - bitmap.top + i;
        {
          for (j = 0; j < bitmap.width; j++)
            if (b[j / 8] & (1 << (7 - (j % 8))))
              {
                p[n[0]].x = x + bitmap.left + j;
                p[n[0]].y = y - bitmap.top + i;
-               if (++n[0] == 0x400)
+               if (++n[0] == size)
                  {
                    XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                  {
                    XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                                gc[0], p, size, CoordModeOrigin);
+                                gc_fore, p, size, CoordModeOrigin);
                    n[0] = 0;
                  }
              }
        }
                    n[0] = 0;
                  }
              }
        }
-      else
+      if (flush && n[0] > 0)
+       XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                    gc_fore, p, n[0], CoordModeOrigin);
+    }
+  else
+    {
+      for (i = 0, b = bitmap.buffer; i < bitmap.rows;
+          i++, b += bitmap.pitch)
        {
          for (j = 0; j < bitmap.width; j++)
            {
        {
          for (j = 0; j < bitmap.width; j++)
            {
-             int idx = (b[j] >> 5) - 1;
+             int idx = (bitmap.bits_per_pixel == 1
+                        ? ((b[j / 8] & (1 << (7 - (j % 8)))) ? 6 : -1)
+                        : (b[j] >> 5) - 1);
 
              if (idx >= 0)
                {
 
              if (idx >= 0)
                {
@@ -137,15 +195,26 @@ ftxfont_draw_bitmap (f, gc, font, code, x, y, p, size, n)
 
                  pp[n[idx]].x = x + bitmap.left + j;
                  pp[n[idx]].y = y - bitmap.top + i;
 
                  pp[n[idx]].x = x + bitmap.left + j;
                  pp[n[idx]].y = y - bitmap.top + i;
-                 if (++(n[idx]) == 0x100)
+                 if (++(n[idx]) == size)
                    {
                      XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                    {
                      XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                                  gc[idx], pp, size, CoordModeOrigin);
+                                  idx == 6 ? gc_fore : gcs[idx], pp, size,
+                                  CoordModeOrigin);
                      n[idx] = 0;
                    }
                }
            }
        }
                      n[idx] = 0;
                    }
                }
            }
        }
+      if (flush)
+       {
+         for (i = 0; i < 6; i++)
+           if (n[i] > 0)
+             XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                          gcs[i], p + 0x100 * i, n[i], CoordModeOrigin);
+         if (n[6] > 0)
+           XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                        gc_fore, p + 0x600, n[6], CoordModeOrigin);
+       }
     }
 
   if (ftfont_driver.free_bitmap)
     }
 
   if (ftfont_driver.free_bitmap)
@@ -167,41 +236,15 @@ ftxfont_draw_backgrond (f, font, gc, x, y, width)
                GCForeground | GCBackground, &xgcv);
   XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background);
   XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
                GCForeground | GCBackground, &xgcv);
   XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background);
   XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
-                 x, y - font->ascent, width, y + font->descent);
+                 x, y - FONT_BASE (font), width, FONT_HEIGHT (font));
   XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground);
 }
 
   XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground);
 }
 
-/* Return the default Font ID on frame F.  */
-
-static Font
-ftxfont_default_fid (f)
-     FRAME_PTR f;
-{
-  static int fid_known;
-  static Font fid;
-
-  if (! fid_known)
-    {
-      fid = XLoadFont (FRAME_X_DISPLAY (f), "fixed");
-      if (! fid)
-       {
-         fid = XLoadFont (FRAME_X_DISPLAY (f), "*");
-         if (! fid)
-           abort ();
-       }
-      fid_known = 1;
-    }
-  return fid;
-}
-
 /* Prototypes for font-driver methods.  */
 static Lisp_Object ftxfont_list P_ ((Lisp_Object, Lisp_Object));
 static Lisp_Object ftxfont_match P_ ((Lisp_Object, Lisp_Object));
 /* Prototypes for font-driver methods.  */
 static Lisp_Object ftxfont_list P_ ((Lisp_Object, Lisp_Object));
 static Lisp_Object ftxfont_match P_ ((Lisp_Object, Lisp_Object));
-static struct font *ftxfont_open P_ ((FRAME_PTR, Lisp_Object, int));
+static Lisp_Object ftxfont_open P_ ((FRAME_PTR, Lisp_Object, int));
 static void ftxfont_close P_ ((FRAME_PTR, struct font *));
 static void ftxfont_close P_ ((FRAME_PTR, struct font *));
-static int ftxfont_prepare_face (FRAME_PTR, struct face *);
-static void ftxfont_done_face (FRAME_PTR, struct face *);
-
 static int ftxfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
 
 struct font_driver ftxfont_driver;
 static int ftxfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
 
 struct font_driver ftxfont_driver;
@@ -211,16 +254,11 @@ ftxfont_list (frame, spec)
      Lisp_Object frame;
      Lisp_Object spec;
 {
      Lisp_Object frame;
      Lisp_Object spec;
 {
-  Lisp_Object val = ftfont_driver.list (frame, spec);
+  Lisp_Object list = ftfont_driver.list (frame, spec), tail;
   
   
-  if (! NILP (val))
-    {
-      int i;
-
-      for (i = 0; i < ASIZE (val); i++)
-       ASET (AREF (val, i), FONT_TYPE_INDEX, Qftx);
-    }
-  return val;
+  for (tail = list; CONSP (tail); tail = XCDR (tail))
+    ASET (XCAR (tail), FONT_TYPE_INDEX, Qftx);
+  return list;
 }
 
 static Lisp_Object
 }
 
 static Lisp_Object
@@ -235,55 +273,21 @@ ftxfont_match (frame, spec)
   return entity;
 }
 
   return entity;
 }
 
-static struct font *
+static Lisp_Object
 ftxfont_open (f, entity, pixel_size)
      FRAME_PTR f;
      Lisp_Object entity;
      int pixel_size;
 {
 ftxfont_open (f, entity, pixel_size)
      FRAME_PTR f;
      Lisp_Object entity;
      int pixel_size;
 {
-  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  Lisp_Object font_object;
   struct font *font;
   struct font *font;
-  XFontStruct *xfont = malloc (sizeof (XFontStruct));
-  
-  if (! xfont)
-    return NULL;
-  font = ftfont_driver.open (f, entity, pixel_size);
-  if (! font)
-    {
-      free (xfont);
-      return NULL;
-    }
 
 
-  xfont->fid = ftxfont_default_fid (f);
-  xfont->ascent = font->ascent;
-  xfont->descent = font->descent;
-  xfont->max_bounds.width = font->font.size;
-  xfont->min_bounds.width = font->min_width;
-  font->font.font = xfont;
+  font_object = ftfont_driver.open (f, entity, pixel_size);
+  if (NILP (font_object))
+    return Qnil;
+  font = XFONT_OBJECT (font_object);
   font->driver = &ftxfont_driver;
   font->driver = &ftxfont_driver;
-
-  dpyinfo->n_fonts++;
-
-  /* Set global flag fonts_changed_p to non-zero if the font loaded
-     has a character with a smaller width than any other character
-     before, or if the font loaded has a smaller height than any other
-     font loaded before.  If this happens, it will make a glyph matrix
-     reallocation necessary.  */
-  if (dpyinfo->n_fonts == 1)
-    {
-      dpyinfo->smallest_font_height = font->font.height;
-      dpyinfo->smallest_char_width = font->min_width;
-      fonts_changed_p = 1;
-    }
-  else
-    {
-      if (dpyinfo->smallest_font_height > font->font.height)
-       dpyinfo->smallest_font_height = font->font.height, fonts_changed_p |= 1;
-      if (dpyinfo->smallest_char_width > font->min_width)
-       dpyinfo->smallest_char_width = font->min_width, fonts_changed_p |= 1;
-    }
-
-  return font;
+  return font_object;
 }
 
 static void
 }
 
 static void
@@ -292,52 +296,6 @@ ftxfont_close (f, font)
      struct font *font;
 {
   ftfont_driver.close (f, font);
      struct font *font;
 {
   ftfont_driver.close (f, font);
-  FRAME_X_DISPLAY_INFO (f)->n_fonts--;
-}
-
-static int
-ftxfont_prepare_face (f, face)
-     FRAME_PTR f;
-     struct face *face;
-{
-  struct font *font = (struct font *) face->font_info;
-  GC gcs[6];
-  int i;
-
-  face->extra = NULL;
-
-  if (! font->scalable)
-    return 0;
-
-  if (ftxfont_create_gcs (f, gcs, face->foreground, face->background) < 0)
-    /* Give up antialiasing.  */
-    return 0;
-
-  face->extra = malloc (sizeof (GC) * 7);
-  if (! face->extra)
-    return -1;
-  for (i = 0; i < 6; i++)
-    ((GC *) face->extra)[i] = gcs[i];
-  ((GC *) face->extra)[i] = face->gc;
-  return 0;
-}
-
-static void
-ftxfont_done_face (f, face)
-     FRAME_PTR f;
-     struct face *face;
-{
-  if (face->extra)
-    {
-      int i;
-
-      BLOCK_INPUT;
-      for (i = 0; i < 6; i++)
-       XFreeGC (FRAME_X_DISPLAY (f), ((GC *) face->extra)[i]);
-      UNBLOCK_INPUT;
-      free (face->extra);
-      face->extra = NULL;
-    }
 }
 
 static int
 }
 
 static int
@@ -347,18 +305,18 @@ ftxfont_draw (s, from, to, x, y, with_background)
 {
   FRAME_PTR f = s->f;
   struct face *face = s->face;
 {
   FRAME_PTR f = s->f;
   struct face *face = s->face;
-  struct font *font = (struct font *) face->font_info;
+  struct font *font = s->font;
   XPoint p[0x700];
   int n[7];
   unsigned *code;
   int len = to - from;
   int i;
   GC *gcs;
   XPoint p[0x700];
   int n[7];
   unsigned *code;
   int len = to - from;
   int i;
   GC *gcs;
+  int xadvance;
 
   n[0] = n[1] = n[2] = n[3] = n[4] = n[5] = n[6] = 0;
 
   BLOCK_INPUT;
 
   n[0] = n[1] = n[2] = n[3] = n[4] = n[5] = n[6] = 0;
 
   BLOCK_INPUT;
-
   if (with_background)
     ftxfont_draw_backgrond (f, font, s->gc, x, y, s->width);
   code = alloca (sizeof (unsigned) * len);
   if (with_background)
     ftxfont_draw_backgrond (f, font, s->gc, x, y, s->width);
   code = alloca (sizeof (unsigned) * len);
@@ -366,46 +324,46 @@ ftxfont_draw (s, from, to, x, y, with_background)
     code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
               | XCHAR2B_BYTE2 (s->char2b + from + i));
 
     code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
               | XCHAR2B_BYTE2 (s->char2b + from + i));
 
-  gcs = face->extra;
-  if (gcs && face->gc != s->gc)
+  if (face->gc == s->gc)
+    {
+      gcs = ftxfont_get_gcs (f, face->foreground, face->background);
+    }
+  else
     {
     {
-      /* We are drawing for cursor or for mouse highlighting, and
-        can't use the prepared GCs.  */
       XGCValues xgcv;
       unsigned long mask = GCForeground | GCBackground;
 
       XGCValues xgcv;
       unsigned long mask = GCForeground | GCBackground;
 
-      gcs = alloca (sizeof (GC) * 7);
       XGetGCValues (FRAME_X_DISPLAY (f), s->gc, mask, &xgcv);
       XGetGCValues (FRAME_X_DISPLAY (f), s->gc, mask, &xgcv);
-      if (ftxfont_create_gcs (f, gcs, xgcv.foreground, xgcv.background) < 0)
-       gcs = NULL;
-      gcs[6] = s->gc;
+      gcs = ftxfont_get_gcs (f, xgcv.foreground, xgcv.background);
     }
 
     }
 
-  if (gcs)
+  if (gcs)
     {
     {
-      /* We are drawing with a bitmap font which doesn't use
-        antialiasing.  */
+      if (s->num_clips)
+       for (i = 0; i < 6; i++)
+         XSetClipRectangles (FRAME_X_DISPLAY (f), gcs[i], 0, 0,
+                             s->clip, s->num_clips, Unsorted);
+
       for (i = 0; i < len; i++)
       for (i = 0; i < len; i++)
-       x += ftxfont_draw_bitmap (f, &s->gc, font, code[i], x, y,
-                                 p, 0x700, n);
-      if (n[0] > 0)
-       XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                    s->gc, p, n[0], CoordModeOrigin);
+       {
+         xadvance = ftxfont_draw_bitmap (f, s->gc, gcs, font, code[i], x, y,
+                                         p, 0x100, n, i + 1 == len);
+         x += (s->padding_p ? 1 : xadvance);
+       }
+      if (s->num_clips)
+       for (i = 0; i < 6; i++)
+         XSetClipMask (FRAME_X_DISPLAY (f), gcs[i], None);
     }
   else
     {
     }
   else
     {
-      /* We are drawing with a scalable font which use
-        antialiasing.  */
+      /* We can't draw with antialiasing.
+        s->gc should already have a proper clipping setting. */
       for (i = 0; i < len; i++)
       for (i = 0; i < len; i++)
-       x += ftxfont_draw_bitmap (f, gcs, font, code[i], x, y,
-                                 p, 0x100, n);
-      for (i = 0; i < 7; i++)
-       if (n[i] > 0)
-         XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                      gcs[i], p + 0x100 * i, n[i], CoordModeOrigin);
-      if (face->gc != s->gc)
-       for (i = 0; i < 6; i++)
-         XFreeGC (FRAME_X_DISPLAY (f), gcs[i]);
+       {
+         xadvance = ftxfont_draw_bitmap (f, s->gc, NULL, font, code[i], x, y,
+                                         p, 0x700, n, i + 1 == len);
+         x += (s->padding_p ? 1 : xadvance);
+       }
     }
 
   UNBLOCK_INPUT;
     }
 
   UNBLOCK_INPUT;
@@ -413,6 +371,28 @@ ftxfont_draw (s, from, to, x, y, with_background)
   return len;
 }
 
   return len;
 }
 
+static int
+ftxfont_end_for_frame (f)
+     FRAME_PTR f;
+{
+  struct ftxfont_frame_data *data = font_get_frame_data (f, &ftxfont_driver);
+  
+  BLOCK_INPUT;
+  while (data)
+    {
+      struct ftxfont_frame_data *next = data->next;
+      int i;
+      
+      for (i = 0; i < 6; i++)
+       XFreeGC (FRAME_X_DISPLAY (f), data->gcs[i]);
+      free (data);
+      data = next;
+    }
+  UNBLOCK_INPUT;
+  font_put_frame_data (f, &ftxfont_driver, NULL);
+  return 0;
+}
+
 \f
 
 void
 \f
 
 void
@@ -426,10 +406,8 @@ syms_of_ftxfont ()
   ftxfont_driver.match = ftxfont_match;
   ftxfont_driver.open = ftxfont_open;
   ftxfont_driver.close = ftxfont_close;
   ftxfont_driver.match = ftxfont_match;
   ftxfont_driver.open = ftxfont_open;
   ftxfont_driver.close = ftxfont_close;
-  ftxfont_driver.prepare_face = ftxfont_prepare_face;
-  ftxfont_driver.done_face = ftxfont_done_face;
   ftxfont_driver.draw = ftxfont_draw;
   ftxfont_driver.draw = ftxfont_draw;
-
+  ftxfont_driver.end_for_frame = ftxfont_end_for_frame;
   register_font_driver (&ftxfont_driver, NULL);
 }
 
   register_font_driver (&ftxfont_driver, NULL);
 }