*** empty log message ***
authorhanda <handa>
Thu, 18 Mar 2004 08:20:27 +0000 (08:20 +0000)
committerhanda <handa>
Thu, 18 Mar 2004 08:20:27 +0000 (08:20 +0000)
16 files changed:
example/ChangeLog
example/medit.c
src/ChangeLog
src/draw.c
src/face.c
src/face.h
src/font-flt.c
src/font-ft.c
src/font.c
src/font.h
src/fontset.c
src/input-gui.c
src/internal-gui.h
src/m17n-X.c
src/m17n-gui.c
src/m17n-gui.h

index b00eb49..83201e6 100644 (file)
@@ -1,4 +1,12 @@
-2004-03-12  Kenichi Handa  <handa@etlken2>
+2004-03-17  Kenichi Handa  <handa@m17n.org>
+
+       * medit.c (update_selection): Fix for the case that the selected
+       region is expanded to the opposite direction.
+       (ButtonMoveProc): Likewise.
+       (main): Use alloca instead of malloc for allocating menu names.
+       Free several memory areas and GCs.  Set control.anti_alias to 1.
+
+2004-03-12  Kenichi Handa  <handa@m17n.org>
 
        * medit.c (input_status_control): New variable.
        (input_status): Use input_status_control.
index cacfbcf..e4c4a97 100644 (file)
@@ -328,8 +328,8 @@ redraw (int y0, int y1, int clear, int scroll_bar)
   if (clear)
     CLEAR_AREA (0, y0, win_width, y1 - y0);
 
-  /* Find a line closest to y0.  The lihe is a cursor line if the
-     cursor is at the position above Y0, otherwise the top line.  */
+  /* Find a line closest to y0.  It is a cursor line if the cursor is
+     Y0, otherwise the top line.  */
   if (y0 >= cur.y0)
     line = &cur;
   else
@@ -498,28 +498,28 @@ update_selection ()
 
   if (from < top.from)
     {
-      GLYPH_INFO (bol (from, 0), from, info);
-      sel_start.ascent = -info.this.y;
-      sel_start.from = info.line_from;
-      sel_start.to = info.line_to;
-      TEXT_EXTENTS (from, top.from, rect);      
-      sel_start.y0 = - rect.height;
-      sel_start.y1 = sel_start.y0 + info.this.height;
+      int pos = bol (from, 0);
+
+      TEXT_EXTENTS (pos, top.from, rect);
+      sel_start.y0 = top.y0 - rect.height;
+      sel_start.ascent = - rect.y;
+      GLYPH_INFO (pos, from, info);
+      if (pos < info.line_from)
+       sel_start.y0 += - rect.y + info.y + info.this.y;
     }
   else
     {
       GLYPH_INFO (top.from, from, info);
       sel_start.y0 = top.ascent + info.y + info.this.y;
-      sel_start.y1 = sel_start.y0 + info.this.height;
-      sel_start.ascent = -info.this.y;
-      sel_start.from = info.line_from;
-      sel_start.to = info.line_to;
     }
+  sel_start.ascent = -info.this.y;
+  sel_start.y1 = sel_start.y0 + info.this.height;
+  sel_start.from = info.line_from;
+  sel_start.to = info.line_to;
 
   if (to <= sel_start.to)
     {
       sel_end = sel_start;
-      to = bol (to - 1, 1) - 1;
       if (to >= sel_end.to)
        {
          GLYPH_INFO (sel_start.from, to, info);
@@ -529,7 +529,6 @@ update_selection ()
     }
   else
     {
-      to = bol (to - 1, 1) - 1;
       GLYPH_INFO (sel_start.from, to, info);
       sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.this.y;
       sel_end.y1 = sel_end.y0 + info.this.height;
@@ -1143,25 +1142,61 @@ ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
 
       if (cursor.from == from)
        {
-         /* Start position of selection changed.  */
-         select_region (pos, to);
-         if (pos > from)
-           /* Shrunken.  Previous selection face must be cleared.  */
-           redraw (start_y0, sel_start.y1, 1, 0);
+         /* Starting position changed.  */
+         if (pos <= from)
+           {
+             /* Enlarged.  We can simply overdraw.  */
+             select_region (pos, to);
+             redraw (sel_start.y0, start_y1, 0, 0);
+           }
+         else if (pos < to)
+           {
+             /* Shrunken.  Previous selection face must be cleared.  */
+             select_region (pos, to);
+             redraw (start_y0, sel_start.y1, 1, 0);
+           }
+         else if (pos == to)
+           {
+             /* Shrunken to zero.  */
+             XtDisownSelection (w, XA_PRIMARY, CurrentTime);
+             mtext_detach_property (selection);
+             redraw (start_y0, end_y1, 1, 0);
+           }
          else
-           /* Enlarged.  We can simply overdraw.  */
-           redraw (sel_start.y0, start_y1, 0, 0);
+           {
+             /* Full update is necessary.  */
+             select_region (to, pos);
+             redraw (start_y0, sel_end.y1, 1, 0);
+           }
        }
       else
        {
-         /* End position of selection changed.  */
-         select_region (from, pos);
-         if (pos < to)
-           /* Shrunken.  Previous selection face must be cleared.  */
-           redraw (sel_end.y0, end_y1, 1, 0);
+         /* Ending position changed.  */
+         if (pos < from)
+           {
+             /* Full update is necessary.  */
+             select_region (pos, from);
+             redraw (sel_start.y0, end_y1, 1, 0);
+           }
+         else if (pos == from)
+           {
+             /* Shrunken to zero.  */
+             XtDisownSelection (w, XA_PRIMARY, CurrentTime);
+             mtext_detach_property (selection);
+             redraw (start_y0, end_y1, 1, 0);
+           }
+         else if (pos < to)
+           {
+             /* Shrunken.  Previous selection face must be cleared.  */
+             select_region (from, pos);
+             redraw (sel_end.y0, end_y1, 1, 0);
+           }
          else
-           /* Enlarged.  We can simply overdraw.  */
-           redraw (end_y0, sel_end.y1, 0, 0);
+           {
+             /* Enlarged.  We can simply overdraw.  */
+             select_region (from, pos);
+             redraw (end_y0, sel_end.y1, 0, 0);
+           }
        }
     }
   else
@@ -2585,7 +2620,7 @@ main (int argc, char **argv)
       for (i = 0; i < 11; i++)
        if (plist[i])
          {
-           char *name = malloc (9);
+           char *name = alloca (9);
 
            sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
            if (i == 10)
@@ -2652,6 +2687,7 @@ main (int argc, char **argv)
   memset (&control, 0, sizeof control);
   control.two_dimensional = 1;
   control.enable_bidi = 1;
+  control.anti_alias = 1;
   control.min_line_ascent = font_ascent;
   control.min_line_descent = font_descent;
   control.max_line_width = win_width;
@@ -2675,7 +2711,6 @@ main (int argc, char **argv)
   for (i = 0; i < num_input_methods; i++)
     minput_close_im (input_method_table[i]);
   m17n_object_unref (frame);
-
   m17n_object_unref (mt);
   m17n_object_unref (face_xxx_large);
   m17n_object_unref (face_box);
@@ -2693,7 +2728,13 @@ main (int argc, char **argv)
   M17N_FINI ();
 
   free (fontset_name);
+  free (filename);
+  free (input_method_table);
+  free (InputMethodMenus);
 
+  XFreeGC (display, mono_gc);
+  XFreeGC (display, mono_gc_inv);
+  XFreeGC (display, gc_inv);
   XtUninstallTranslations (form);
   XtUninstallTranslations (TextWidget);
   XtDestroyWidget (ShellWidget);
index 1c53be1..a033bd1 100644 (file)
@@ -1,4 +1,105 @@
-2004-03-16  Kenichi Handa  <handa@etlken2>
+2004-03-18  Kenichi Handa  <handa@m17n.org>
+
+       * draw.c (Mdepth): New variable.
+       (visual_order): Delete unused local var `pos'.
+       (compose_glyph_string): Fix for the case that gstring->glyphs is
+       realloced.  Stop generating glyphs at TO.  Fix handling of
+       control charaters.
+       (layout_glyphs): Get metrics of all glyphs in advance.  Set
+       lbearing and rbearing of base of composition glyph correctly.
+       Handle left-overhang glyphs correctly.
+       (alloc_gstring): New arg frame.  Set gstring->anti_alias.  Caller
+       changed.
+       (dump_combining_code): Change the defualt off_x character to ".".
+       (mdraw__init): Initialize Mdepth.
+
+       * face.c (work_gstring): New variable
+       (mface__init): Initialize work_gstring.
+       (mface__fini): Free work_gstring.glyphs.
+       (mface__realize): Don't handle videomode property here.  Adjusted
+       for the change of mfont__get_metric.
+       (mface__for_chars): Adjusted for the change of mfont__get_metric.
+
+       * face.h (enum face_gc): Moved to m17n-X.c.
+
+       * font.h (struct MFontDriver): Arguments of find_metric changed.
+       (mfont__select): Prototype adjusted.
+       (mfont__get_metric): Likewise.
+       (mfont__ft_drive_otf): Likewise.
+       (mfont__flt_run): Likewise.
+       
+       * font.c (mfont__select): New argument layouter.  If layouter is
+       different in the registered font, make a new copy of realized
+       font.
+       (mfont__get_metric): Argument changed.  Get metrics of multiple
+       glyphs.
+       (mfont_find): Call mfont__select with layouter as Mnil.
+
+       * font-flt.c (FontLayoutContext): New member rfont.
+       (run_otf): Adjusted for the change of mfont__ft_drive_otf.
+       (mfont__flt_run): Argument changed.  Initialize ctx.rfont.
+
+       * font-ft.c (ft_find_metric): Arguments changed.  Get metrics of
+       multiple glyphs.
+       (NUM_POINTS): New macro.
+       (MPointTable): New type.
+       (ft_render): Use mwin__draw_points instead of mwin__draw_bitmap.
+       (mfont__ft_drive_otf): New argument rfont.
+
+       * fontset.c (realize_font_group): Adjusted for the changed of
+       mfont__select.
+       (check_fontset_element): This function deleted.
+
+       * input-gui.c (adjust_window_and_draw): Locate a preedit window
+       off the parent window if the preedit text is zero length.
+
+       * internal-gui.h (struct MFrame): New members foreground,
+       background, videomode, font.
+       (struct MGlyphString): New member anti_alias.
+       (MDrawPoint): New type.
+       (mwin__draw_bitmap): Prototype deleted.
+       (mwin__draw_points): Prototype added.
+
+       * m17n-gui.h (MDrawControl): New member anti_alias.
+
+       * m17n-gui.c (free_frame): Free frame->font.
+       (mframe): Set the fontset of frame->face to the default fontset.
+
+       * m17n-X.c (RGB_GC): New type.
+       (enum gc_index): Renamed from enum face_gc.  Member names changed.
+       (GCInfo): New typel
+       (struct MWDevice): Members foreground and background deleted.  New
+       member scratch_gc, gc_list.
+       (DEFAULT_FONT, FALLBACK_FONT): New macros.
+       (free_device): Free GCs in device->gc_list.
+       (get_rgb_gc): New function.
+       (get_gc): Renamed and argument changed from get_color.
+       (get_gc_for_anti_alias): New function.
+       (xfont_find_metric): Arguments changed.  Get metrics of multiple
+       glyphs.
+       (set_region): Argument changed.  Caller changed.
+       (xfont_render): Allways set a font in gc.
+       (x_error_handler, x_io_error_handler): Define only if
+       X_SET_ERROR_HANDLER is defined.
+       (mwin__open_device): Create device->scratch_gc.  Set members
+       foreground, background, and videomode of frame.  Call
+       XSetErrorHandler and XSetIOErrorHandler only if
+       X_SET_ERROR_HANDLER is defined.
+       (struct gc_list): Deleted.
+       (REGISTER_GC, UNREGISTER_GC): These macros deleted.
+       (mwin__realize_face): Adjusted for the change of the format of
+       rface->info and the charge of set_region.
+       (mwin__free_realized_face, mwin__fill_space, mwin__draw_hline)
+       (mwin__draw_box): Likewise.
+       (mwin__draw_bitmap): This function deleted.
+       (mwin__draw_points): New function.
+       (mwin__verify_region): Adjusted for the change of the format of
+       rface->info and the charge of set_region.
+       (mwin__create_window): Inherit backgound pixel from parent.
+       (mwin__dump_gc): Adjusted for the change of the format of
+       rface->info.
+
+2004-03-16  Kenichi Handa  <handa@m17n.org>
 
        * m17n-X.c (mwin__parse_event): Fix handling of modifier keys.
 
 
        * input-gui.c (win_create_ic): Enable bidi in status control.
 
-       * draw.c (visual_order): Avoid re-ordering only combining glyphs.
+       * draw.c (visual_order): Avoid re-ordering of combining glyphs only.
 
 2004-03-09  Kenichi Handa  <handa@m17n.org>
 
index 869a709..aee3180 100644 (file)
@@ -79,6 +79,8 @@ static MSymbol Mlatin, Minherited;
 /* Special categories */
 static MSymbol McatCc, McatCf;
 
+static MSymbol Mdepth;
+
 \f
 /* Glyph-string composer.  */
 
@@ -169,7 +171,6 @@ visual_order (MGlyphString *gstring)
     {
       int j = indices[i];
       int k = idx[j];
-      int pos = glyphs[k].pos;
 
       glyphs[k].bidi_level = levels[j];
 #ifdef HAVE_FRIBIDI
@@ -236,6 +237,7 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
   int non_ascii_found;
   int size = gstring->control.fixed_width;
   int i, limit;
+  int last;
 
   MLIST_RESET (gstring);
   gstring->from = from;
@@ -251,7 +253,7 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
   APPEND_GLYPH (gstring, g_tmp);
 
   stop = face_change = charset_change = language_change = pos = from;
-  g = gstring->glyphs + gstring->used;
+  last = 0;
   non_ascii_found = 0;
   while (1)
     {
@@ -279,13 +281,15 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
            this_script = script;
        }
 
-      if (pos == stop || script != this_script || g->type != g_tmp.type)
+      if (pos == stop || script != this_script
+         || MGLYPH (last)->type != g_tmp.type)
        {
+         g = MGLYPH (last);
          if (non_ascii_found && g->type == GLYPH_CHAR)
            while (g < gstring->glyphs + gstring->used)
              g = mface__for_chars (script, language, charset,
                                    g, gstring->glyphs + gstring->used, size);
-         g = gstring->glyphs + gstring->used;
+         last = gstring->used;
          non_ascii_found = 0;
          script = this_script;
          if (pos == to)
@@ -312,7 +316,9 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
                                         language, charset, size)
                       : default_rface);
            }
-         stop = language_change;
+         stop = to;
+         if (stop > language_change)
+           stop = language_change;
          if (stop > charset_change)
            stop = charset_change;
          if (face_change < stop)
@@ -328,12 +334,12 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
        non_ascii_found = 1;
       else if (g_tmp.type == GLYPH_CHAR && (c <= 32 || c == 127))
        {
-         g_tmp.c = '^';
+         g_tmp.code = '^';
          APPEND_GLYPH (gstring, g_tmp);
          if (c < ' ')
-           g_tmp.c += 0x40;
+           g_tmp.code = g_tmp.c + 0x40;
          else
-           g_tmp.c = '?';
+           g_tmp.code = '?';
        }
       APPEND_GLYPH (gstring, g_tmp);
       if (c == '\n'
@@ -385,9 +391,7 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
                   i++, g++)
                if (g->rface->rfont != this->rface->rfont)
                  g->code = code;
-             i = mfont__flt_run (gstring, start, i,
-                                 this->rface->rfont->layouter,
-                                 this->rface->ascii_rface);
+             i = mfont__flt_run (gstring, start, i, this->rface);
            }
          else
            {
@@ -482,6 +486,8 @@ layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
   g_physical_descent = gstring->physical_descent;
   g_width = g_lbearing = g_rbearing = 0;
 
+  mfont__get_metric (gstring, from, to);
+
   while (g < last_g)
     {
       MGlyph *base = g++;
@@ -489,7 +495,6 @@ layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
       int size = rfont->font.property[MFONT_SIZE];
       int width, lbearing, rbearing;
 
-      mfont__get_metric (rfont, base);
       if (g == last_g || ! g->combining_code)
        {
          /* No combining.  */
@@ -549,7 +554,6 @@ layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
              else if (end < g->to)
                end = g->to;
                
-             mfont__get_metric (rfont, g);
              g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
              if (g->xoff < left)
                left = g->xoff;
@@ -580,6 +584,8 @@ layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
 
          base->ascent = - top;
          base->descent = bottom;
+         base->lbearing = lbearing;
+         base->rbearing = rbearing;
          if (left < - base->width)
            {
              base->xoff = - base->width - left;
@@ -1138,7 +1144,8 @@ render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
       rect.x += rect.width;
       if (rect.x < x + width)
        {
-         while (g != gend && x + width - gend[-1].width >= rect.x)
+         while (g != gend
+                && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
            {
              width -= (--gend)->width;
              while (! gend->enabled && g != gend)
@@ -1354,7 +1361,8 @@ free_gstring (void *object)
 static MGlyphString scratch_gstring;
 
 static MGlyphString *
-alloc_gstring (MText *mt, int pos, MDrawControl *control, int line, int y)
+alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
+              int line, int y)
 {
   MGlyphString *gstring;
 
@@ -1377,6 +1385,10 @@ alloc_gstring (MText *mt, int pos, MDrawControl *control, int line, int y)
     (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
   else
     gstring->width_limit = control->max_line_width;
+  gstring->anti_alias = control->anti_alias;
+  if (gstring->anti_alias
+      && (unsigned) mwin__device_get_prop (frame->device, Mdepth) < 8)
+    gstring->anti_alias = 0;
   return gstring;
 }
 
@@ -1502,7 +1514,7 @@ get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
          beg = pos;
          end = to;
        }
-      gstring = alloc_gstring (mt, beg, control, line, y);
+      gstring = alloc_gstring (frame, mt, beg, control, line, y);
       compose_glyph_string (frame, mt, beg, end, gstring);
       layout_glyph_string (frame, gstring);
       end = gstring->to;
@@ -1516,7 +1528,8 @@ get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
          while (gst->to < end)
            {
              line++, y += gst->height;
-             gst->next = alloc_gstring (mt, gst->from, control, line, y);
+             gst->next = alloc_gstring (frame, mt, gst->from, control,
+                                        line, y);
              gst->next->top = gstring;
              compose_glyph_string (frame, mt, gst->to, end, gst->next);
              gst = gst->next;
@@ -1638,7 +1651,7 @@ dump_combining_code (int code)
   else if (off_y < 0)
     sprintf (work + 2, "%d", off_y);
   else if (off_x == 0)
-    sprintf (work + 2, "-");
+    sprintf (work + 2, ".");
   p = work + strlen (work);
   if (off_x > 0)
     sprintf (p, ">%d", off_x);
@@ -1692,6 +1705,7 @@ mdraw__init ()
 
   McatCc = msymbol ("Cc");
   McatCf = msymbol ("Cf");
+  Mdepth = msymbol ("depth");
 
   MbidiR = msymbol ("R");
   MbidiAL = msymbol ("AL");
index e1a2bc5..7c7df8b 100644 (file)
@@ -386,6 +386,8 @@ deserialize_face (MPlist *plist)
   return face;
 }
 
+static MGlyphString work_gstring;
+
 \f
 
 /* Internal API */
@@ -515,6 +517,11 @@ mface__init ()
   mface_yellow->property[MFACE_FOREGROUND] = (void *) msymbol ("yellow");
   mface_magenta = mface ();
   mface_magenta->property[MFACE_FOREGROUND] = (void *) msymbol ("magenta");
+
+  work_gstring.glyphs = malloc (sizeof (MGlyph) * 2);
+  work_gstring.size = 2;
+  work_gstring.used = 0;
+  work_gstring.inc = 1;
   return 0;
 }
 
@@ -544,6 +551,8 @@ mface__fini ()
   M17N_OBJECT_UNREF (mface_cyan);
   M17N_OBJECT_UNREF (mface_yellow);
   M17N_OBJECT_UNREF (mface_magenta);
+  free (work_gstring.glyphs);
+
   mdebug__report_object ("Face", &face_table);
 }
 
@@ -585,15 +594,6 @@ mface__realize (MFrame *frame, MFace **faces, int num,
       merged_face.property[MFACE_SIZE] = (void *) font_size;
     }
 
-  if ((MSymbol) merged_face.property[MFACE_VIDEOMODE] == Mreverse)
-    {
-      MSymbol foreground = (MSymbol) merged_face.property[MFACE_FOREGROUND];
-      MSymbol background = (MSymbol) merged_face.property[MFACE_BACKGROUND];
-
-      merged_face.property[MFACE_FOREGROUND] = background;
-      merged_face.property[MFACE_BACKGROUND] = foreground;
-    }
-
   rface = find_realized_face (frame, &merged_face, NULL);
   if (rface && rface->tick == tick)
     return rface->ascii_rface;
@@ -617,12 +617,14 @@ mface__realize (MFrame *frame, MFace **faces, int num,
     {
       rface->rfont = rfont;
       g.otf_encoded = 0;
-      mfont__get_metric (rfont, &g);
-      rface->space_width = g.width;
-      g.code = MCHAR_INVALID_CODE;
-      mfont__get_metric (rface->rfont, &g);
-      rface->ascent = g.ascent;
-      rface->descent = g.descent;
+      work_gstring.glyphs[0] = g;
+      work_gstring.glyphs[0].rface = rface;
+      work_gstring.glyphs[1].code = MCHAR_INVALID_CODE;
+      work_gstring.glyphs[1].rface = rface;
+      mfont__get_metric (&work_gstring, 0, 2);
+      rface->space_width = work_gstring.glyphs[0].width;
+      rface->ascent = work_gstring.glyphs[1].ascent;
+      rface->descent = work_gstring.glyphs[1].descent;
     }
   else
     {
@@ -673,12 +675,11 @@ mface__for_chars (MSymbol script, MSymbol language, MSymbol charset,
       *rface = *from_g->rface->ascii_rface;
       rface->rfont = rfont;
       {
-       MGlyph tmp;
-
-       tmp.code = MCHAR_INVALID_CODE;
-       mfont__get_metric (rfont, &tmp);
-       rface->ascent = tmp.ascent;
-       rface->descent = tmp.descent;
+       work_gstring.glyphs[0].code = MCHAR_INVALID_CODE;
+       work_gstring.glyphs[0].rface = rface;
+       mfont__get_metric (&work_gstring, 0, 1);
+       rface->ascent = work_gstring.glyphs[0].ascent;
+       rface->descent = work_gstring.glyphs[0].descent;
       }
       mwin__realize_face (rface);
       mplist_add (from_g->rface->frame->realized_face_list, Mt, rface);
index 9ab1d16..a174631 100644 (file)
@@ -67,19 +67,6 @@ struct MFace
 };
 
 
-enum face_gc
-  {
-    MFACE_GC_NORMAL,
-    MFACE_GC_INVERSE,
-    MFACE_GC_SCRATCH,
-    MFACE_GC_HLINE,
-    MFACE_GC_BOX_TOP,
-    MFACE_GC_BOX_BOTTOM,
-    MFACE_GC_BOX_LEFT,
-    MFACE_GC_BOX_RIGHT,
-    MFACE_GCS
-  };
-
 /** A realized face is registered in MFrame->face_list, thus it does
     not have to be a managed object.  */
 
index b93c5c4..b49e97d 100644 (file)
@@ -912,6 +912,7 @@ typedef struct
   int cluster_end_pos;
   int combining_code;
   int left_padding;
+  MRealizedFont *rfont;
 } FontLayoutContext;
 
 static int run_command (int depth,
@@ -1069,7 +1070,7 @@ run_otf (int depth,
 #ifdef HAVE_OTF
   int gidx = gstring->used;
 
-  to = mfont__ft_drive_otf (gstring, from, to,
+  to = mfont__ft_drive_otf (gstring, from, to, ctx->rfont,
                            otf_cmd->script, otf_cmd->langsys,
                            otf_cmd->gsub_features, otf_cmd->gpos_features);
   if (gidx < gstring->used)
@@ -1256,8 +1257,7 @@ mfont__flt_encode_char (MSymbol layouter_name, int c)
 }
 
 int
-mfont__flt_run (MGlyphString *gstring, int from, int to,
-               MSymbol layouter_name, MRealizedFace *ascii_rface)
+mfont__flt_run (MGlyphString *gstring, int from, int to, MRealizedFace *rface)
 {
   int stage_idx = 0;
   int gidx;
@@ -1266,7 +1266,9 @@ mfont__flt_run (MGlyphString *gstring, int from, int to,
   MCharTable *table;
   int encoded_len;
   int match_indices[NMATCH];
+  MSymbol layouter_name = rface->rfont->layouter;
   MFontLayoutTable *layouter = get_font_layout_table (layouter_name);
+  MRealizedFace *ascii_rface = rface->ascii_rface;
   FontLayoutStage *stage;
   int from_pos, to_pos;
   MGlyph dummy;
@@ -1284,6 +1286,7 @@ mfont__flt_run (MGlyphString *gstring, int from, int to,
 
   /* Setup CTX.  */
   memset (&ctx, 0, sizeof ctx);
+  ctx.rfont = rface->rfont;
   table = MPLIST_VAL (layouter);
   layouter = MPLIST_NEXT (layouter);
   stage = (FontLayoutStage *) MPLIST_VAL (layouter);
index 98a54ea..8878356 100644 (file)
@@ -261,7 +261,7 @@ build_font_list ()
 static MRealizedFont *ft_select (MFrame *, MFont *, MFont *, int);
 static int ft_open (MRealizedFont *);
 static void ft_close (MRealizedFont *);
-static void ft_find_metric (MRealizedFont *, MGlyph *);
+static void ft_find_metric (MRealizedFont *, MGlyphString *, int, int);
 static unsigned ft_encode_char (MRealizedFont *, int, unsigned);
 static void ft_render (MDrawWindow, int, int, MGlyphString *,
                       MGlyph *, MGlyph *, int, MDrawRegion);
@@ -400,39 +400,54 @@ ft_close (MRealizedFont *rfont)
 /* The FreeType font driver function FIND_METRIC.  */
 
 static void
-ft_find_metric (MRealizedFont *rfont, MGlyph *g)
+ft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
+               int from, int to)
 {
   MFTInfo *ft_info = (MFTInfo *) rfont->info;
   FT_Face ft_face = ft_info->ft_face;
+  MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
+  FT_Int32 load_flags = FT_LOAD_RENDER;
 
-  if (g->code == MCHAR_INVALID_CODE)
+  if (! gstring->anti_alias)
     {
-      unsigned unitsPerEm = ft_face->units_per_EM;
-      int size = rfont->font.property[MFONT_SIZE] / 10;
-
-      g->lbearing = 0;
-      g->rbearing = ft_face->max_advance_width * size / unitsPerEm;
-      g->width = ft_face->max_advance_width * size / unitsPerEm;
-      g->ascent = ft_face->ascender * size / unitsPerEm;
-      g->descent = (- ft_face->descender) * size / unitsPerEm;
+#ifdef FT_LOAD_TARGET_MONO
+      load_flags |= FT_LOAD_TARGET_MONO;
+#else
+      load_flags |= FT_LOAD_MONOCHROME;
+#endif
     }
-  else
-    {
-      FT_Glyph_Metrics *metrics;
-      FT_UInt code;
 
-      if (g->otf_encoded)
-       code = g->code;
+  for (; g != gend; g++)
+    {
+      if (g->code == MCHAR_INVALID_CODE)
+       {
+         unsigned unitsPerEm = ft_face->units_per_EM;
+         int size = rfont->font.property[MFONT_SIZE] / 10;
+
+         g->lbearing = 0;
+         g->rbearing = ft_face->max_advance_width * size / unitsPerEm;
+         g->width = ft_face->max_advance_width * size / unitsPerEm;
+         g->ascent = ft_face->ascender * size / unitsPerEm;
+         g->descent = (- ft_face->descender) * size / unitsPerEm;
+       }
       else
-       code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
+       {
+         FT_Glyph_Metrics *metrics;
+         FT_UInt code;
 
-      FT_Load_Glyph (ft_face, code, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
-      metrics = &ft_face->glyph->metrics;
-      g->lbearing = metrics->horiBearingX >> 6;
-      g->rbearing = (metrics->horiBearingX + metrics->width) >> 6;
-      g->width = metrics->horiAdvance >> 6;
-      g->ascent = metrics->horiBearingY >> 6;
-      g->descent = (metrics->height - metrics->horiBearingY) >> 6;
+         if (g->otf_encoded)
+           code = g->code;
+         else
+           code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
+
+         FT_Load_Glyph (ft_face, code, FT_LOAD_RENDER);
+         metrics = &ft_face->glyph->metrics;
+         g->lbearing = (metrics->horiBearingX >> 6);
+         g->rbearing = (metrics->horiBearingX + metrics->width) >> 6;
+         g->width = metrics->horiAdvance >> 6;
+         g->ascent = metrics->horiBearingY >> 6;
+         g->descent = (metrics->height - metrics->horiBearingY) >> 6;
+       }
     }
 }
 
@@ -464,56 +479,127 @@ ft_encode_char (MRealizedFont *rfont, int c, unsigned ignored)
 
 /* The FreeType font driver function RENDER.  */
 
+#define NUM_POINTS 0x1000
+
+typedef struct {
+  MDrawPoint points[NUM_POINTS];
+  MDrawPoint *p;
+} MPointTable;
+
 static void
 ft_render (MDrawWindow win, int x, int y,
           MGlyphString *gstring, MGlyph *from, MGlyph *to,
           int reverse, MDrawRegion region)
 {
-  MRealizedFace *rface;
-  MFrame *frame;
+  MRealizedFace *rface = from->rface;
+  MFrame *frame = rface->frame;
   MFTInfo *ft_info;
   FT_Face ft_face = NULL;
+  FT_Int32 load_flags = FT_LOAD_RENDER;
   MGlyph *g;
+  int i, j;
+  MPointTable point_table[8];
 
   if (from == to)
     return;
 
+  if (! gstring->anti_alias)
+    {
+#ifdef FT_LOAD_TARGET_MONO
+      load_flags |= FT_LOAD_TARGET_MONO;
+#else
+      load_flags |= FT_LOAD_MONOCHROME;
+#endif
+    }
+
   /* It is assured that the all glyphs in the current range use the
      same realized face.  */
-  rface = from->rface;
-  frame = rface->frame;
   ft_info = (MFTInfo *) rface->rfont->info;
   ft_face = ft_info->ft_face;
 
-  g = from;
-  while (g < to)
+  for (i = 0; i < 8; i++)
+    point_table[i].p = point_table[i].points;
+
+  for (g = from; g < to; x += g++->width)
     {
-      if (g->type == GLYPH_CHAR)
-       {
-         FT_UInt code;
+      FT_UInt code;
+      unsigned char *bmp;
+      int intensity;
+      MPointTable *ptable;
+      int xoff, yoff;
 
-         if (g->otf_encoded)
-           code = g->code;
-         else
-           code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
-#ifdef FT_LOAD_TARGET_MONO
-         FT_Load_Glyph (ft_face, code, FT_LOAD_RENDER | FT_LOAD_TARGET_MONO);
-#else
-         FT_Render_Glyph (ft_face->glyph, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
-#endif
-         mwin__draw_bitmap (frame, win, rface, reverse,
-                            x + ft_face->glyph->bitmap_left + g->xoff,
-                            y - ft_face->glyph->bitmap_top + g->yoff,
-                            ft_face->glyph->bitmap.width,
-                            ft_face->glyph->bitmap.rows,
-                            ft_face->glyph->bitmap.pitch,
-                            ft_face->glyph->bitmap.buffer,
-                            region);
+      if (g->otf_encoded)
+       code = g->code;
+      else
+       code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
+      FT_Load_Glyph (ft_face, code, load_flags);
+      yoff = y - ft_face->glyph->bitmap_top + g->yoff;
+      bmp = ft_face->glyph->bitmap.buffer;
+      if (gstring->anti_alias)
+       for (i = 0; i < ft_face->glyph->bitmap.rows;
+            i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
+         {
+           xoff = x + ft_face->glyph->bitmap_left + g->xoff;
+           for (j = 0; j < ft_face->glyph->bitmap.width; j++, xoff++)
+             {
+               intensity = bmp[j] >> 5;
+               if (intensity)
+                 {
+                   ptable = point_table + intensity;
+                   ptable->p->x = xoff;
+                   ptable->p->y = yoff;
+                   ptable->p++;
+                   if (ptable->p - ptable->points == NUM_POINTS)
+                     {
+                       mwin__draw_points (frame, win, rface,
+                                          reverse ? 7 - intensity : intensity,
+                                          ptable->points, NUM_POINTS, region);
+                       ptable->p = ptable->points;
+                     }
+                 }
+             }
+         }
+      else
+       for (i = 0; i < ft_face->glyph->bitmap.rows;
+            i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
+         {
+           xoff = x + ft_face->glyph->bitmap_left + g->xoff;
+           for (j = 0; j < ft_face->glyph->bitmap.width; j++, xoff++)
+             {
+               intensity = bmp[j / 8] & (1 << (7 - (j % 8)));
+               if (intensity)
+                 {
+                   ptable = point_table;
+                   ptable->p->x = xoff;
+                   ptable->p->y = yoff;
+                   ptable->p++;
+                   if (ptable->p - ptable->points == NUM_POINTS)
+                     {
+                       mwin__draw_points (frame, win, rface,
+                                          reverse ? 0 : 7,
+                                          ptable->points, NUM_POINTS, region);
+                       ptable->p = ptable->points;
+                     }             
+                 }
+             }
        }
-      x += g++->width;
     }
 
-  return;
+  if (gstring->anti_alias)
+    {
+      for (i = 1; i < 8; i++)
+       if (point_table[i].p != point_table[i].points)
+         mwin__draw_points (frame, win, rface, reverse ? 7 - i : i,
+                            point_table[i].points,
+                            point_table[i].p - point_table[i].points, region);
+    }
+  else
+    {
+      if (point_table[0].p != point_table[0].points)
+       mwin__draw_points (frame, win, rface, reverse ? 0 : 7,
+                          point_table[0].points,
+                          point_table[0].p - point_table[0].points, region);
+    }
 }
 
 \f
@@ -579,6 +665,7 @@ mfont__ft_fini ()
 
 int
 mfont__ft_drive_otf (MGlyphString *gstring, int from, int to,
+                    MRealizedFont *rfont,
                     MSymbol script, MSymbol langsys, 
                     MSymbol gsub_features, MSymbol gpos_features)
 {
@@ -598,7 +685,7 @@ mfont__ft_drive_otf (MGlyphString *gstring, int from, int to,
   if (len == 0)
     return from;
 
-  ft_info = (MFTInfo *) gstring->glyphs[from].rface->rfont->info;
+  ft_info = (MFTInfo *) rfont->info;
   if (ft_info->otf_flag < 0)
     goto simple_copy;
   otf = ft_info->otf;
index 645f8e8..fa39508 100644 (file)
@@ -776,11 +776,12 @@ mfont__set_spec_from_plist (MFont *spec, MPlist *plist)
 }
 
 MRealizedFont *
-mfont__select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
+mfont__select (MFrame *frame, MFont *spec, MFont *request, int limited_size,
+              MSymbol layouter)
 {
   MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
   MPlist *realized_font_list;
-  MRealizedFont *best_font[MFONT_TYPE_MAX];
+  MRealizedFont *best_font[MFONT_TYPE_MAX], *best;
   int best_index;
   int i;
   int mdebug_mask = MDEBUG_FONT;
@@ -790,15 +791,29 @@ mfont__select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
 
   MPLIST_DO (realized_font_list, frame->realized_font_list)
     {
-      MRealizedFont *best = MPLIST_VAL (realized_font_list);
-
+      best = MPLIST_VAL (realized_font_list);
       if (MPLIST_KEY (realized_font_list) == registry
          && ! memcmp (&best->spec, spec, sizeof (MFont))
          && ! memcmp (&best->request, request, sizeof (MFont)))
-       return best;
+       {
+         if (best->layouter != layouter)
+           {
+             MRealizedFont *copy;
+
+             MSTRUCT_MALLOC (copy, MERROR_FONT);
+             *copy = *best;
+             copy->layouter = layouter;
+             if (copy->info)
+               M17N_OBJECT_REF (copy->info);
+             mplist_add (frame->realized_font_list, registry, copy);
+             best = copy;
+           }
+         return best;
+       }
     }
 
   MDEBUG_PUSH_TIME ();
+  best = NULL;
   best_index = -1;
   for (i = 0; i < MFONT_TYPE_MAX; i++)
     {
@@ -809,13 +824,13 @@ mfont__select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
                      : NULL);
       if (best_font[i]
          && (best_index < 0
-             || best_font[best_index]->score > best_font[i]->score))
+             || best_font[best_index]->score < best_font[i]->score))
        best_index = i;
     }
   for (i = 0; i < MFONT_TYPE_MAX; i++)
     {
       if (i == best_index)
-       mplist_add (frame->realized_font_list, registry, best_font[i]);
+       best = best_font[i];
       else if (best_font[i])
        free (best_font[i]);
     }
@@ -830,18 +845,21 @@ mfont__select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
          font.property[i] = request->property[i];
       gen_font_name (buf2, &font);
 
-      if (best_index >= 0)
+      if (best)
        MDEBUG_PRINT_TIME ("FONT", 
                           (stderr, " to select <%s> from <%s>.",
-                           gen_font_name (buf1,
-                                          &best_font[best_index]->font),
+                           gen_font_name (buf1, &best->font),
                            buf2));
       else
        MDEBUG_PRINT_TIME ("FONT", (stderr, " to fail to find <%s>.", buf2));
       MDEBUG_POP_TIME ();
     }
 
-  return (best_index >= 0 ? best_font[best_index] : NULL);
+  if (! best)
+    return NULL;
+  best->layouter = layouter;
+  mplist_add (frame->realized_font_list, registry, best);
+  return best;
 }
 
 
@@ -957,9 +975,22 @@ mfont__encode_char (MRealizedFont *rfont, int c)
 }
 
 void
-mfont__get_metric (MRealizedFont *rfont, MGlyph *g)
+mfont__get_metric (MGlyphString *gstring, int from, int to)
 {
-  (rfont->driver->find_metric) (rfont, g);
+  MGlyph *from_g = MGLYPH (from), *to_g = MGLYPH (to), *g;
+  MRealizedFont *rfont = from_g->rface->rfont;
+
+  for (g = from_g; g != to_g; g++)
+    if (g->rface->rfont != rfont)
+      {
+       int idx = GLYPH_INDEX (g);
+
+       (rfont->driver->find_metric) (rfont, gstring, from, idx);
+       from_g = g;
+       rfont = g->rface->rfont;
+       from = idx;
+      }
+  (rfont->driver->find_metric) (rfont, gstring, from, GLYPH_INDEX (g));
 }
 
 
@@ -1542,7 +1573,7 @@ mfont_find (MFrame *frame, MFont *spec, int *score, int limited_size)
   MFONT_INIT (&spec_copy);
   spec_copy.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY];
 
-  rfont = mfont__select (frame, &spec_copy, spec, limited_size);
+  rfont = mfont__select (frame, &spec_copy, spec, limited_size, Mnil);
   if (!rfont)
     return NULL;
   if (score)
index 6c77228..b96e11c 100644 (file)
@@ -169,7 +169,9 @@ struct MFontDriver
   /** Close a font specified by RFONT.   */
   void (*close) (MRealizedFont *rfont);
 
-  void (*find_metric) (MRealizedFont *rfont, MGlyph *g);
+  /** Set metrics of glyphs in GSTRING from FROM to TO.  */
+  void (*find_metric) (MRealizedFont *rfont, MGlyphString *gstring,
+                      int from, int to);
 
   /** Encode C into the glyph code the font.  CODE is a code point of
       C in rfont->encoder->encoding_charset.  If the font has no glyph
@@ -202,6 +204,7 @@ extern int mfont__ft_init ();
 extern void mfont__ft_fini ();
 
 extern int mfont__ft_drive_otf (MGlyphString *gstring, int from, int to,
+                               MRealizedFont *rfont,
                                MSymbol script, MSymbol langsys,
                                MSymbol gsub_features, MSymbol gpos_features);
 extern int mfont__ft_decode_otf (MGlyph *g);
@@ -227,13 +230,14 @@ extern int mfont__encodable_p (MRealizedFont *rfont, MSymbol layouter_name,
 extern unsigned mfont__encode_char (MRealizedFont *rfont, int c);
 
 extern MRealizedFont *mfont__select (MFrame *frame, MFont *spec,
-                                    MFont *request, int limitted_size);
+                                    MFont *request, int limitted_size,
+                                    MSymbol layouter);
 
 extern int mfont__open (MRealizedFont *rfont);
 
 extern void mfont__close (MRealizedFont *rfont);
 
-extern void mfont__get_metric (MRealizedFont *rfont, MGlyph *g);
+extern void mfont__get_metric (MGlyphString *gstring, int from, int to);
 
 extern void mfont__set_property (MFont *font, enum MFontProperty key,
                                 MSymbol val);
@@ -248,6 +252,6 @@ extern void mfont__set_spec (MFont *font,
 extern unsigned mfont__flt_encode_char (MSymbol layouter_name, int c);
 
 extern int mfont__flt_run (MGlyphString *gstring, int from, int to,
-                          MSymbol layouter_name, MRealizedFace *ascii_rface);
+                          MRealizedFace *rface);
 
 #endif /* _M17N_FONT_H_ */
index af938ae..6f922ec 100644 (file)
@@ -307,14 +307,13 @@ realize_font_group (MFrame *frame, MFont *request, MPlist *font_group,
   mplist_set (font_group, Mnil, NULL);
   MPLIST_DO (pl, plist)
     {
+      MSymbol layouter = MPLIST_KEY (pl);
       MRealizedFont *rfont = mfont__select (frame, MPLIST_VAL (pl), request,
-                                           size);
+                                           size,
+                                           layouter == Mt ? Mnil : layouter);
 
       if (rfont)
        {
-         rfont->layouter = MPLIST_KEY (pl);
-         if (rfont->layouter == Mt)
-           rfont->layouter = Mnil;
          MPLIST_DO (p, font_group)
            if (((MRealizedFont *) (MPLIST_VAL (p)))->score > rfont->score)
              break;
@@ -323,28 +322,6 @@ realize_font_group (MFrame *frame, MFont *request, MPlist *font_group,
     }
 }
 
-int
-check_fontset_element (MFrame *frame, MPlist *element, MGlyph *g, int size)
-{
-  MRealizedFont *rfont = (MRealizedFont *) MPLIST_VAL (element);
-
-  if (! rfont)
-    /* We have already failed to select this font.  */
-    return 0;
-  if (! rfont->frame)
-    {
-      rfont = mfont__select (frame, &rfont->spec, &rfont->request, size);
-      free (MPLIST_VAL (element));
-      MPLIST_VAL (element) = rfont;
-      if (! rfont)
-       /* No font matches this spec.  */
-       return 0;
-    }
-
-  g->code = mfont__encode_char (rfont, g->c);
-  return (g->code != MCHAR_INVALID_CODE);
-}
-
 \f
 
 /* Internal API */
index 52f589b..b9a32f9 100644 (file)
@@ -221,16 +221,24 @@ adjust_window_and_draw (MFrame *frame, MInputContext *ic, MText *mt, int type)
     physical.x = win_ic_info->client.geometry.width - physical.width;
   if (type == 0)
     {
-      if (y0 > - ic->spot.ascent)
+      if (len <= 1)
        {
-         physical.height += y0 + ic->spot.ascent;
-         y0 = - ic->spot.ascent;
+         physical.height = physical.width = 1;
+         physical.x = physical.y = -1;
        }
-      if (y1 < ic->spot.descent)
+      else
        {
-         physical.height += ic->spot.descent - y1;
+         if (y0 > - ic->spot.ascent)
+           {
+             physical.height += y0 + ic->spot.ascent;
+             y0 = - ic->spot.ascent;
+           }
+         if (y1 < ic->spot.descent)
+           {
+             physical.height += ic->spot.descent - y1;
+           }
+         physical.y = yoff + ic->spot.y + y0;
        }
-      physical.y = yoff + ic->spot.y + y0;
     }
   else if (type == 1)
     {
index c50d936..656bfb6 100644 (file)
@@ -41,6 +41,10 @@ struct MFrame
       with the frame.  */
   MWDevice *device;
 
+  MSymbol foreground, background, videomode;
+
+  MFont *font;
+
   /** The default face of the frame.  */
   MFace *face;
 
@@ -77,7 +81,7 @@ enum glyph_type
     GLYPH_TYPE_MAX
   };
 
-struct MGlyph
+typedef struct
 {
   int pos, to;
   int c;
@@ -93,9 +97,7 @@ struct MGlyph
   unsigned bidi_level : 6;
   enum glyph_type type : 3;
   int combining_code;
-};
-
-typedef struct MGlyph MGlyph;
+} MGlyph;
 
 struct MGlyphString
 {
@@ -113,6 +115,10 @@ struct MGlyphString
   /* Members to keep temporary data while layouting.  */
   short sub_width, sub_lbearing, sub_rbearing;
 
+  /* Copied for <control>.anti_alias but never set if the frame's
+     depth is less than 8.  */
+  unsigned anti_alias : 1;
+
   MDrawControl control;
 
   MDrawRegion region;
@@ -182,6 +188,11 @@ typedef struct MGlyphString MGlyphString;
 
 typedef struct MFontDriver MFontDriver;
 
+typedef struct
+{
+  short x, y;
+} MDrawPoint;
+
 extern int mfont__init ();
 extern void mfont__fini ();
 
@@ -229,11 +240,9 @@ extern void mwin__draw_box (MFrame *frame, MDrawWindow win,
                            MGlyph *g, int x, int y, int width,
                            MDrawRegion region);
 
-extern void mwin__draw_bitmap (MFrame *frame, MDrawWindow win,
-                              MRealizedFace *rface, int reverse,
-                              int x, int y,
-                              int width, int height, int row_bytes,
-                              unsigned char *bmp,
+extern void mwin__draw_points (MFrame *frame, MDrawWindow win,
+                              MRealizedFace *rface,
+                              int intensity, MDrawPoint *points, int num,
                               MDrawRegion region);
 
 extern MDrawRegion mwin__region_from_rect (MDrawMetric *rect);
index 28654c5..c821e72 100644 (file)
@@ -84,6 +84,35 @@ typedef struct
 /* Anchor of the chain of MDisplayInfo objects.  */
 static MPlist *display_info_list;
 
+
+/* Color value and the corresponding GC.  */
+typedef struct
+{
+  unsigned int rgb;           /* (red << 16) | (green << 8) | blue */
+  GC gc;
+} RGB_GC;
+
+enum gc_index
+  {
+    GC_INVERSE,
+    GC_NORMAL = GC_INVERSE + 7,
+    GC_HLINE,
+    GC_BOX_TOP,
+    GC_BOX_BOTTOM,
+    GC_BOX_LEFT,
+    GC_BOX_RIGHT,
+    GC_MAX
+  };
+
+typedef struct
+{
+  int rgb_fore;
+  int rgb_back;
+  /* The first 8 elements are indexed by an intensity for
+     anti-aliasing.  The 2nd to 7th are created on demand.  */
+  GC gc[GC_MAX];
+} GCInfo;
+
 struct MWDevice
 {
   /* Common header for the m17n object.  */
@@ -99,7 +128,7 @@ struct MWDevice
 
   Colormap cmap;
 
-  unsigned long foreground, background;
+  GC scratch_gc;
 
   /** List of pointers to realized faces on the frame.  */
   MPlist *realized_face_list;
@@ -107,6 +136,8 @@ struct MWDevice
   /** List of pointers to realized fontsets on the frame.  */
   MPlist *realized_fontset_list;
 
+  /** List of XColors vs GCs on the frame.  */
+  MPlist *gc_list;
 };
 
 static MPlist *device_list;
@@ -116,6 +147,17 @@ static MSymbol M_iso8859_1, M_iso10646_1;
 #define FRAME_DISPLAY(frame) (frame->device->display_info->display)
 #define FRAME_SCREEN(frame) (frame->device->screen_num)
 
+#define DEFAULT_FONT "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1"
+#define FALLBACK_FONT "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1"
+
+typedef struct
+{
+  String font;
+  String foreground;
+  String background;
+  Boolean reverse_video;
+} AppData, *AppDataPtr;
+
 static void
 free_display_info (void *object)
 {
@@ -182,6 +224,15 @@ free_device (void *object)
     mface__free_realized ((MRealizedFace *) mplist_value (plist));
   M17N_OBJECT_UNREF (device->realized_face_list);
 
+  MPLIST_DO (plist, device->gc_list)
+    {
+      XFreeGC (device->display_info->display,
+              ((RGB_GC *) MPLIST_VAL (plist))->gc);
+      free (MPLIST_VAL (plist));
+    }
+  M17N_OBJECT_UNREF (device->gc_list);
+  XFreeGC (device->display_info->display, device->scratch_gc);
+
   XFreePixmap (device->display_info->display, device->drawable);
   M17N_OBJECT_UNREF (device->display_info);
   free (object);
@@ -238,22 +289,102 @@ find_modifier_bits (MDisplayInfo *disp_info)
   XFreeModifiermap (mods);
 }
 
-static unsigned long
-get_color (Display *display, Colormap cmap,
-          MSymbol color_name, MSymbol default_name,
-          unsigned long default_pixel)
+static RGB_GC *
+get_rgb_gc (MWDevice *device, XColor *xcolor)
+{
+  int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8)
+            | (xcolor->blue >> 8));
+  MPlist *plist;
+  RGB_GC *rgb_gc;
+  unsigned long valuemask = GCForeground;
+  XGCValues values;
+
+  MPLIST_DO (plist, device->gc_list)
+    {
+      rgb_gc = MPLIST_VAL (plist);
+
+      if (rgb_gc->rgb == rgb)
+       return rgb_gc;
+      if (rgb_gc->rgb > rgb)
+       break;
+    }
+
+  if (! XAllocColor (device->display_info->display, device->cmap, xcolor))
+    return NULL;
+
+  rgb_gc = malloc (sizeof (RGB_GC));
+  rgb_gc->rgb = rgb;
+  values.foreground = xcolor->pixel;
+  rgb_gc->gc = XCreateGC (device->display_info->display,
+                         device->drawable, valuemask, &values);
+  mplist_push (plist, Mt, rgb_gc);
+  return rgb_gc;
+}
+
+static GC
+get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret)
 {
-  XColor exact_def;
+  MWDevice *device = frame->device;
+  XColor xcolor;
+  RGB_GC *rgb_gc;
 
-  if (XParseColor (display, cmap, msymbol_name (color_name), &exact_def)
-      && XAllocColor (display, cmap, &exact_def))
-    return exact_def.pixel;
+  if (color == Mnil)
+    {
+      if (frame->rface)
+       goto no_color;
+      color = for_foreground ? frame->foreground : frame->background;
+    }
+  if (! XParseColor (FRAME_DISPLAY (frame), device->cmap,
+                    msymbol_name (color), &xcolor))
+    goto no_color;
+  rgb_gc = get_rgb_gc (device, &xcolor);
+  if (! rgb_gc)
+    goto no_color;
+  if (rgb_ret)
+    *rgb_ret = rgb_gc->rgb;
+  return rgb_gc->gc;
+
+ no_color:
+  {
+    GCInfo *info = frame->rface->info;
+    GC gc;
+    int rgb;
+
+    if (for_foreground)
+      rgb = info->rgb_fore, gc = info->gc[GC_NORMAL];
+    else
+      rgb = info->rgb_back, gc = info->gc[GC_INVERSE];
+    if (rgb_ret)
+      *rgb_ret = rgb;
+    return gc;
+  }
+}
 
-  if (XParseColor (display, cmap, msymbol_name (default_name), &exact_def)
-      && XAllocColor (display, cmap, &exact_def))
-    return exact_def.pixel;
+static GC
+get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
+{
+  int rgb_fore, rgb_back;
+  XColor xcolor;
+  RGB_GC *rgb_gc;
+  GC gc;
 
-  return default_pixel;
+  if (info->gc[intensity])
+    return info->gc[intensity];
+
+  rgb_fore = info->rgb_fore, rgb_back = info->rgb_back;
+  xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity
+                + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8;
+  xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity
+                  + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8;
+  xcolor.blue = (((rgb_fore & 0xFF) * intensity
+                 + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8;
+  rgb_gc = get_rgb_gc (device, &xcolor);
+  if (rgb_gc)
+    gc = rgb_gc->gc;
+  else
+    gc =get_gc_for_anti_alias (device, info,
+                              intensity < 4 ? intensity - 1 : intensity + 1);
+  return (info->gc[intensity] = gc);
 }
 
 \f
@@ -447,7 +578,7 @@ build_font_list (MFrame *frame, MSymbol family, MSymbol registry,
 static MRealizedFont *xfont_select (MFrame *, MFont *, MFont *, int);
 static int xfont_open (MRealizedFont *);
 static void xfont_close (MRealizedFont *);
-static void xfont_find_metric (MRealizedFont *, MGlyph *);
+static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
 static unsigned xfont_encode_char (MRealizedFont *, int, unsigned);
 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
                          MGlyph *, MGlyph *, int, MDrawRegion);
@@ -598,68 +729,73 @@ xfont_close (MRealizedFont *rfont)
 /* The X font driver function FIND_METRIC.  */
 
 static void
-xfont_find_metric (MRealizedFont *rfont, MGlyph *g)
+xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
+                  int from, int to)
 {
-  XCharStruct *pcm = NULL;
   MXFontInfo *xfont = (MXFontInfo *) rfont->info;
   XFontStruct *f = xfont->f;
-  int byte1, byte2;
+  MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
 
-  if (g->code == MCHAR_INVALID_CODE)
+  for (; g != gend; g++)
     {
-      g->lbearing = f->max_bounds.lbearing;
-      g->rbearing = f->max_bounds.rbearing;
-      g->width = f->max_bounds.width;
-      g->ascent = f->ascent;
-      g->descent = f->descent;
-      return;
-    }
-
-  byte1 = g->code >> 8;
-  byte2 = g->code & 0xFF;
-
-  if (f->per_char != NULL)
-    {
-      if (f->min_byte1 == 0 && f->max_byte1 == 0)
+      if (g->code == MCHAR_INVALID_CODE)
        {
-         if (byte1 == 0
-             && byte2 >= f->min_char_or_byte2
-             && byte2 <= f->max_char_or_byte2)
-           pcm = f->per_char + byte2 - f->min_char_or_byte2;
+         g->lbearing = f->max_bounds.lbearing;
+         g->rbearing = f->max_bounds.rbearing;
+         g->width = f->max_bounds.width;
+         g->ascent = f->ascent;
+         g->descent = f->descent;
        }
       else
        {
-         if (byte1 >= f->min_byte1
-             && byte1 <= f->max_byte1
-             && byte2 >= f->min_char_or_byte2
-             && byte2 <= f->max_char_or_byte2)
+         int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
+         XCharStruct *pcm = NULL;
+
+         if (f->per_char != NULL)
            {
-             pcm = (f->per_char
-                    + ((f->max_char_or_byte2-f->min_char_or_byte2 + 1)
-                       * (byte1 - f->min_byte1))
-                    + (byte2 - f->min_char_or_byte2));
+             if (f->min_byte1 == 0 && f->max_byte1 == 0)
+               {
+                 if (byte1 == 0
+                     && byte2 >= f->min_char_or_byte2
+                     && byte2 <= f->max_char_or_byte2)
+                   pcm = f->per_char + byte2 - f->min_char_or_byte2;
+               }
+             else
+               {
+                 if (byte1 >= f->min_byte1
+                     && byte1 <= f->max_byte1
+                     && byte2 >= f->min_char_or_byte2
+                     && byte2 <= f->max_char_or_byte2)
+                   {
+                     pcm = (f->per_char
+                            + ((f->max_char_or_byte2-f->min_char_or_byte2 + 1)
+                               * (byte1 - f->min_byte1))
+                            + (byte2 - f->min_char_or_byte2));
+                   }
+               }
            }
-       }
-    }
 
-  if (pcm)
-    {
-      g->lbearing = pcm->lbearing;
-      g->rbearing = pcm->rbearing;
-      g->width = pcm->width;
-      g->ascent = pcm->ascent;
-      g->descent = pcm->descent;
-    }
-  else
-    {
-      /* If the per_char pointer is null, all glyphs between the first
-        and last character indexes inclusive have the same
-        information, as given by both min_bounds and max_bounds.  */
-      g->lbearing = 0;
-      g->rbearing = f->max_bounds.width;
-      g->width = f->max_bounds.width;
-      g->ascent = f->ascent;
-      g->descent = f->descent;
+         if (pcm)
+           {
+             g->lbearing = pcm->lbearing;
+             g->rbearing = pcm->rbearing;
+             g->width = pcm->width;
+             g->ascent = pcm->ascent;
+             g->descent = pcm->descent;
+           }
+         else
+           {
+             /* If the per_char pointer is null, all glyphs between
+                the first and last character indexes inclusive have
+                the same information, as given by both min_bounds and
+                max_bounds.  */
+             g->lbearing = 0;
+             g->rbearing = f->max_bounds.width;
+             g->width = f->max_bounds.width;
+             g->ascent = f->ascent;
+             g->descent = f->descent;
+           }
+       }
     }
 }
 
@@ -717,16 +853,14 @@ xfont_encode_char (MRealizedFont *rfont, int c, unsigned code)
 }
 
 static GC
-set_region (Display *display, MRealizedFace *rface, GC gc, MDrawRegion region)
+set_region (MFrame *frame, GC gc, MDrawRegion region)
 {
-  GC gc1;
-  XRectangle xrect;
+  unsigned long valuemask = GCForeground;
 
-  XClipBox (region, &xrect);  
-  gc1 = ((GC *) rface->info)[MFACE_GC_SCRATCH];
-  XCopyGC (display, gc, GCFont | GCForeground | GCBackground, gc1);
-  XSetRegion (display, gc1, region);
-  return gc1;
+  XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
+          frame->device->scratch_gc);
+  XSetRegion (FRAME_DISPLAY (frame), frame->device->scratch_gc, region);
+  return frame->device->scratch_gc;
 }
 
 /* The X font driver function RENDER.  */
@@ -738,8 +872,7 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
   MRealizedFace *rface = from->rface;
   Display *display;
   XChar2b *code;
-  GC *gcs = rface->info;
-  GC gc = gcs[reverse ? MFACE_GC_INVERSE : MFACE_GC_NORMAL];
+  GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
   MGlyph *g;
   int i;
 
@@ -751,7 +884,8 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
   display = FRAME_DISPLAY (rface->frame);
 
   if (region)
-    gc = set_region (display, rface, gc, region);
+    gc = set_region (rface->frame, gc, region);
+  XSetFont (display, gc, ((MXFontInfo *) (rface->rfont->info))->f->fid);
 
   if (from->code == MCHAR_INVALID_CODE)
     {
@@ -1017,7 +1151,7 @@ xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
 
 \f
 
-#if 1
+#ifdef X_SET_ERROR_HANDLER
 static int
 x_error_handler (Display *display, XErrorEvent *error)
 {
@@ -1064,15 +1198,6 @@ mwin__fini ()
   M17N_OBJECT_UNREF (device_list);
 }
 
-typedef struct
-{
-  String font;
-  String foreground;
-  String background;
-  Boolean reverse_video;
-} AppData, *AppDataPtr;
-
-
 int
 mwin__parse_font_name (char *name, MFont *font)
 {
@@ -1155,6 +1280,7 @@ mwin__open_device (MFrame *frame, MPlist *param)
   XWindowAttributes attr;
   unsigned depth = 0;
   MPlist *plist;
+  AppData app_data;
 
   if (param)
     for (plist = param; (key = mplist_key (plist)) != Mnil;
@@ -1253,6 +1379,9 @@ mwin__open_device (MFrame *frame, MPlist *param)
     M17N_OBJECT_REF (device);
   else
     {
+      unsigned long valuemask = GCForeground;
+      XGCValues values;
+
       M17N_OBJECT (device, free_device, MERROR_WIN);
       device->display_info = disp_info;
       device->screen_num = screen_num;
@@ -1264,8 +1393,10 @@ mwin__open_device (MFrame *frame, MPlist *param)
       device->cmap = cmap;
       device->realized_face_list = mplist ();
       device->realized_fontset_list = mplist ();
-      device->foreground = BlackPixel (display, screen_num);
-      device->background = WhitePixel (display, screen_num);
+      device->gc_list = mplist ();
+      values.foreground = BlackPixel (display, screen_num);
+      device->scratch_gc = XCreateGC (display, device->drawable,
+                                     valuemask, &values);
     }
 
   frame->realized_font_list = disp_info->realized_font_list;
@@ -1274,11 +1405,9 @@ mwin__open_device (MFrame *frame, MPlist *param)
 
   if (widget)
     {
-      AppData app_data;
       XtResource resources[] = {
        { XtNfont, XtCFont, XtRString, sizeof (String),
-         XtOffset (AppDataPtr, font), XtRString,
-         "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1" },
+         XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
        { XtNforeground, XtCForeground, XtRString, sizeof (String),
          XtOffset (AppDataPtr, foreground), XtRString, "black" },
        { XtNbackground, XtCBackground, XtRString, sizeof (String),
@@ -1286,62 +1415,60 @@ mwin__open_device (MFrame *frame, MPlist *param)
        { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
          XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
       };
-      MFace *face = NULL;
-      MFont font;
-      char **names;
-      int nfonts;
 
       XtGetApplicationResources (widget, &app_data,
                                 resources, XtNumber (resources), NULL, 0);
-      names = XListFonts (display, app_data.font, 1, &nfonts);
-      if (nfonts == 1)
-       {
-         if (mwin__parse_font_name (names[0], &font) >= 0)
-           face = mface_from_font (&font);
-         else
-           {
-             /* The font name does not conform to XLFD.  Try to open the
-                font and get XA_FONT property.  */
-             XFontStruct *xfont = XLoadQueryFont (display, names[0]);
+      frame->foreground = msymbol (app_data.foreground);
+      frame->background = msymbol (app_data.background);
+      frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
+    }
+  else
+    {
+      app_data.font = DEFAULT_FONT;
+      frame->foreground = msymbol ("black");
+      frame->background = msymbol ("white");
+      frame->videomode = Mnormal;
+    }
 
-             if (xfont)
-               {
-                 unsigned long value;
-                 char *name;
+  frame->font = mfont ();
+  {
+    int nfonts;
+    char **names = XListFonts (display, app_data.font, 1, &nfonts);
 
-                 if (XGetFontProperty (xfont, XA_FONT, &value)
-                     && (name = ((char *)
-                                 XGetAtomName (display, (Atom) value))))
-                   {
-                     if (mwin__parse_font_name (name, &font) >= 0)
-                       face = mface_from_font (&font);
-                   }
-                 XFreeFont (display, xfont);
-               }
-           }
-         XFreeFontNames (names);
-       }
+    if (nfonts > 0)
+      {
+       if (mwin__parse_font_name (names[0], frame->font) < 0)
+         {
+           /* The font name does not conform to XLFD.  Try to open the
+              font and get XA_FONT property.  */
+           XFontStruct *xfont = XLoadQueryFont (display, names[0]);
+
+           nfonts = 0;
+           if (xfont)
+             {
+               unsigned long value;
+               char *name;
+
+               if (XGetFontProperty (xfont, XA_FONT, &value)
+                   && (name = ((char *)
+                               XGetAtomName (display, (Atom) value))))
+                 {
+                   if (mwin__parse_font_name (name, frame->font) >= 0)
+                     nfonts = 1;
+                 }
+               XFreeFont (display, xfont);
+             }
+         }
+       XFreeFontNames (names);
+      }
+    if (! nfonts)
+      mwin__parse_font_name (FALLBACK_FONT, frame->font);
+  }
 
-      if (app_data.reverse_video == True)
-       {
-         if (! face)
-           face = mface ();
-         mface_put_prop (face, Mvideomode, Mreverse);
-       }
-      if (face)
-       {
-         mplist_push (param, Mface, face);
-         M17N_OBJECT_UNREF (face);
-       }
-      device->foreground
-       = get_color (display, cmap, msymbol (app_data.foreground), Mnil,
-                    device->foreground);
-      device->background
-       = get_color (display, cmap, msymbol (app_data.background), Mnil,
-                    device->background);
-    }
+#ifdef X_SET_ERROR_HANDLER
   XSetErrorHandler (x_error_handler);
-  /* XSetIOErrorHandler (x_io_error_handler); */
+  XSetIOErrorHandler (x_io_error_handler);
+#endif
 
   return device;
 }
@@ -1367,155 +1494,77 @@ mwin__device_get_prop (MWDevice *device, MSymbol key)
   return NULL;
 }
 
-struct {
-  int size, inc, used;
-  GC *gc_table;
-} gc_list;
-
-#define REGISTER_GC(gc)                                        \
-  do {                                                 \
-    if (! gc_list.size)                                        \
-      MLIST_INIT1 (&gc_list, gc_table, 100);           \
-    MLIST_APPEND1 (&gc_list, gc_table, gc, MERROR_WIN);        \
-  } while (0)
-
-
-#define UNREGISTER_GC(gc)                      \
-  do {                                         \
-    int j;                                     \
-    for (j = 0; j < gc_list.used; j++)         \
-      if (gc_list.gc_table[j] == gc)           \
-       gc_list.gc_table[j] = (GC) NULL;        \
-  } while (0)
-
-
 void
 mwin__realize_face (MRealizedFace *rface)
 {
-  MFrame *frame = rface->frame;
-  MWDevice *device = frame->device;
-  Display *display = FRAME_DISPLAY (frame);
-  XGCValues values;
-  int mask = GCForeground | GCBackground;
-  MSymbol foreground = rface->face.property[MFACE_FOREGROUND];
-  MSymbol background = rface->face.property[MFACE_BACKGROUND];
-  MFaceHLineProp *hline = rface->hline;
-  MFaceBoxProp *box = rface->box;
-  MFaceHookFunc func = (MFaceHookFunc) rface->face.property[MFACE_HOOK_FUNC];
-  MSymbol default_foreground
-    = (MSymbol) mface_get_prop (frame->face, Mforeground);
-  MSymbol default_background
-    = (MSymbol) mface_get_prop (frame->face, Mbackground);
-  GC *gcs;
-  unsigned long pixel;
-
-  MTABLE_CALLOC (gcs, MFACE_GCS, MERROR_WIN);
-
-  values.foreground = get_color (display, device->cmap, foreground,
-                                default_foreground, device->foreground);
-  values.background = get_color (display, device->cmap, background,
-                                default_background, device->background);
-  if (rface->face.property[MFACE_VIDEOMODE] == Mreverse)
-    pixel = values.foreground,
-      values.foreground = values.background,
-      values.background = pixel;
-
-  if (rface->rfont
-      && rface->rfont->font.property[MFONT_TYPE] - 1 == MFONT_TYPE_WIN)
+  MFrame *frame;
+  MSymbol foreground, background, videomode;
+  MFaceHLineProp *hline;
+  MFaceBoxProp *box;
+  MFaceHookFunc func;
+  GCInfo *info;
+
+  if (rface != rface->ascii_rface)
     {
-      values.font = ((MXFontInfo *) (rface->rfont->info))->f->fid;
-      mask |= GCFont;
+      rface->info = rface->ascii_rface->info;
+      return;
     }
 
-  gcs[MFACE_GC_NORMAL] = XCreateGC (display, device->drawable, mask, &values);
-  REGISTER_GC (gcs[MFACE_GC_NORMAL]);
-
-  gcs[MFACE_GC_SCRATCH] = XCreateGC (display, device->drawable, mask, &values);
-  REGISTER_GC (gcs[MFACE_GC_SCRATCH]);
-
-  pixel = values.foreground;
-  values.foreground = values.background;
-  values.background = pixel;
-  gcs[MFACE_GC_INVERSE] = XCreateGC (display, device->drawable, mask, &values);
-  REGISTER_GC (gcs[MFACE_GC_INVERSE]);
-  values.background = values.foreground;
-  values.foreground = pixel;
+  frame = rface->frame;
+  MSTRUCT_CALLOC (info, MERROR_WIN);
 
-  mask &= ~GCFont;
+  foreground = rface->face.property[MFACE_FOREGROUND];
+  background = rface->face.property[MFACE_BACKGROUND];
+  videomode = rface->face.property[MFACE_VIDEOMODE];
+  if (! videomode)
+    videomode = frame->videomode;
+  if (videomode != Mreverse)
+    {
+      info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
+      info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
+    }
+  else
+    {
+      info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
+      info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
+    }
 
-  if (rface == rface->ascii_rface)
+  hline = rface->hline;
+  if (hline)
     {
-      /* This realized face is for ASCII.  Setup GCs for hline and
-        box.  */
-      if (hline && hline->color != foreground)
-       {
-         values.foreground
-           = get_color (display, device->cmap, hline->color,
-                        default_foreground, device->foreground);
-         gcs[MFACE_GC_HLINE]
-           = XCreateGC (display, device->drawable, mask, &values);
-         REGISTER_GC (gcs[MFACE_GC_HLINE]);
-         values.foreground = pixel;
-       }
+      if (hline->color)
+       info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
+      else
+       info->gc[GC_HLINE] = info->gc[GC_NORMAL];
+    }
 
-      if (box)
-       {
-         if (box->color_top)
-           {
-             values.foreground
-               = get_color (display, device->cmap, box->color_top,
-                            default_foreground, device->foreground);
-             gcs[MFACE_GC_BOX_TOP]
-               = XCreateGC (display, device->drawable, mask, &values);
-             REGISTER_GC (gcs[MFACE_GC_BOX_TOP]);
-           }
+  box = rface->box;
+  if (box)
+    {
+      if (box->color_top)
+       info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
+      else
+       info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
 
-         if (box->color_left
-             && box->color_left != box->color_top)
-           {
-             values.foreground
-               = get_color (display, device->cmap, box->color_left,
-                            default_foreground, device->foreground);
-             gcs[MFACE_GC_BOX_LEFT]
-               = XCreateGC (display, device->drawable, mask, &values);
-             REGISTER_GC (gcs[MFACE_GC_BOX_LEFT]);
-           }
+      if (box->color_left && box->color_left != box->color_top)
+       info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
+      else
+       info->gc[GC_BOX_LEFT] = info->gc[GC_NORMAL];
 
-         if (box->color_right
-             && box->color_right != box->color_top)
-           {
-             values.foreground
-               = get_color (display, device->cmap, box->color_right,
-                            default_foreground, device->foreground);
-             gcs[MFACE_GC_BOX_RIGHT]
-               = XCreateGC (display, device->drawable, mask, &values);
-             REGISTER_GC (gcs[MFACE_GC_BOX_RIGHT]);
-           }
+      if (box->color_bottom && box->color_bottom != box->color_top)
+       info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
+      else
+       info->gc[GC_BOX_BOTTOM] = info->gc[GC_NORMAL];
 
-         if (box->color_bottom
-             && box->color_bottom != box->color_top)
-           {
-             values.foreground
-               = get_color (display, device->cmap, box->color_bottom,
-                            default_foreground, device->foreground);
-             gcs[MFACE_GC_BOX_BOTTOM]
-               = XCreateGC (display, device->drawable, mask, &values);
-             REGISTER_GC (gcs[MFACE_GC_BOX_BOTTOM]);
-           }
-       }
+      if (box->color_right && box->color_right != box->color_top)
+       info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
+      else
+       info->gc[GC_BOX_RIGHT] = info->gc[GC_NORMAL];
     }
-  else
-    {
-      /* This realized face is not for ASCII.  GCs for hline and box
-        are shared with that of the corresponding ASCII face.  */
-      GC *ascii_gcs = rface->ascii_rface->info;
-      int i;
 
-      for (i = MFACE_GC_HLINE; i < MFACE_GCS; i++)
-       gcs[i] = ascii_gcs[i];
-    }
+  rface->info = info;
 
-  rface->info = gcs;
+  func = (MFaceHookFunc) rface->face.property[MFACE_HOOK_FUNC];
   if (func)
     (func) (&(rface->face), rface->info, rface->face.property[MFACE_HOOK_ARG]);
 }
@@ -1524,18 +1573,8 @@ mwin__realize_face (MRealizedFace *rface)
 void
 mwin__free_realized_face (MRealizedFace *rface)
 {
-  GC *gcs = rface->info;
-  enum face_gc limit
-    = rface == rface->ascii_rface ? MFACE_GCS : MFACE_GC_HLINE;
-  int i;
-
-  for (i = 0; i < limit; i++)
-    if (gcs[i])
-      {
-       UNREGISTER_GC (gcs[i]);
-       XFreeGC (FRAME_DISPLAY (rface->frame), gcs[i]);
-      }            
-  free (gcs);
+  if (rface == rface->ascii_rface)
+    free (rface->info);
 }
 
 
@@ -1544,11 +1583,10 @@ mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
                  int reverse,
                  int x, int y, int width, int height, MDrawRegion region)
 {
-  GC *gcs = rface->info;
-  GC gc = gcs[reverse ? MFACE_GC_NORMAL : MFACE_GC_INVERSE];
+  GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
 
   if (region)
-    gc = set_region (FRAME_DISPLAY (frame), rface, gc, region);
+    gc = set_region (frame, gc, region);
 
   XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
                  x, y, width, height);
@@ -1561,8 +1599,8 @@ mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
                 int x, int y, int width, MDrawRegion region)
 {
   enum MFaceHLineType type = rface->hline->type;
-  GC *gcs = rface->info;
-  GC gc;
+  GCInfo *info = rface->info;
+  GC gc = gc = info->gc[GC_HLINE];
   int i;
 
   y = (type == MFACE_HLINE_BOTTOM
@@ -1572,15 +1610,8 @@ mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
        : type == MFACE_HLINE_STRIKE_THROUGH
        ? y - ((gstring->ascent + gstring->descent) / 2)
        : y - gstring->text_ascent);
-  if (reverse)
-    gc = gcs[MFACE_GC_INVERSE];
-  else if (gcs[MFACE_GC_HLINE])
-    gc = gcs[MFACE_GC_HLINE];
-  else
-    gc = gcs[MFACE_GC_NORMAL];
-
   if (region)
-    gc = set_region (FRAME_DISPLAY (frame), rface, gc, region);
+    gc = set_region (frame, gc, region);
 
   for (i = 0; i < rface->hline->width; i++)
     XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
@@ -1595,7 +1626,7 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
   Display *display = FRAME_DISPLAY (frame);
   MRealizedFace *rface = g->rface;
   MFaceBoxProp *box = rface->box;
-  GC *gcs = rface->info;
+  GCInfo *info = rface->info;
   GC gc_top, gc_left, gc_right, gc_btm;
   int y0, y1;
   int i;
@@ -1605,14 +1636,13 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
   y1 = y + (gstring->text_descent
            + rface->box->inner_vmargin + rface->box->width - 1);
 
-  gc_top = gcs[MFACE_GC_BOX_TOP];
-  if (! gc_top)
-    gc_top = gcs[MFACE_GC_NORMAL];
+  gc_top = info->gc[GC_BOX_TOP];
   if (region)
-    gc_top = set_region (FRAME_DISPLAY (frame), rface, gc_top, region);
-  gc_btm = gcs[MFACE_GC_BOX_BOTTOM];
-  if (! gc_btm)
+    gc_top = set_region (frame, gc_top, region);
+  if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
     gc_btm = gc_top;
+  else
+    gc_btm = info->gc[GC_BOX_BOTTOM];
 
   if (g->type == GLYPH_BOX)
     {
@@ -1628,19 +1658,22 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
        XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
 
       /* Draw the bottom side.  */
-      if (region)
-       gc_btm = set_region (display, rface, gc_btm, region);
+      if (region && gc_btm != gc_top)
+       gc_btm = set_region (frame, gc_btm, region);
       for (i = 0; i < box->width; i++)
        XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
 
       if (g->left_padding > 0)
        {
          /* Draw the left side.  */
-         gc_left = gcs[MFACE_GC_BOX_LEFT];
-         if (! gc_left)
+         if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
            gc_left = gc_top;
-         else if (region)
-           gc_left = set_region (display, rface, gc_left, region);
+         else
+           {
+             gc_left = info->gc[GC_BOX_LEFT];
+             if (region)
+               gc_left = set_region (frame, gc_left, region);
+           }
          for (i = 0; i < rface->box->width; i++)
            XDrawLine (display, (Window) win, gc_left,
                       x0 + i, y0 + i, x0 + i, y1 - i);
@@ -1648,11 +1681,14 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
       else
        {
          /* Draw the right side.  */
-         gc_right = gcs[MFACE_GC_BOX_RIGHT];
-         if (! gc_right)
+         if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
            gc_right = gc_top;
-         else if (region)
-           gc_right = set_region (display, rface, gc_right, region);
+         else
+           {
+             gc_right = info->gc[GC_BOX_RIGHT];
+             if (region)
+               gc_right = set_region (frame, gc_right, region);
+           }
          for (i = 0; i < rface->box->width; i++)
            XDrawLine (display, (Window) win, gc_right,
                       x1 - i, y0 + i, x1 - i, y1 - i);
@@ -1666,8 +1702,8 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
                   x, y0 + i, x + width - 1, y0 + i);
 
       /* Draw the bottom side.  */
-      if (region)
-       gc_btm = set_region (display, rface, gc_btm, region);
+      if (region && gc_btm != gc_top)
+       gc_btm = set_region (frame, gc_btm, region);
       for (i = 0; i < box->width; i++)
        XDrawLine (display, (Window) win, gc_btm,
                   x, y1 - i, x + width - 1, y1 - i);
@@ -1675,6 +1711,7 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
 }
 
 
+#if 0
 void
 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
                   int reverse, int x, int y,
@@ -1683,17 +1720,35 @@ mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
 {
   Display *display = FRAME_DISPLAY (frame);
   int i, j;
-  GC *gcs = rface->info;
-  GC gc = gcs[reverse ? MFACE_GC_INVERSE : MFACE_GC_NORMAL];
+  GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
 
   if (region)
-    gc = set_region (FRAME_DISPLAY (frame), rface, gc, region);
+    gc = set_region (frame, gc, region);
 
   for (i = 0; i < height; i++, bmp += row_bytes)
     for (j = 0; j < width; j++)
       if (bmp[j / 8] & (1 << (7 - (j % 8))))
        XDrawPoint (display, (Window) win, gc, x + j, y + i);
 }
+#endif
+
+void
+mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
+                  int intensity, MDrawPoint *points, int num,
+                  MDrawRegion region)
+{
+  GCInfo *info = rface->info;
+  GC gc;
+
+  if (! (gc = info->gc[intensity]))
+    gc = info->gc[intensity] = get_gc_for_anti_alias (frame->device, info,
+                                                     intensity);
+  if (region)
+    gc = set_region (frame, gc, region);
+
+  XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
+              (XPoint *) points, num, CoordModeOrigin);
+}
 
 
 MDrawRegion
@@ -1781,35 +1836,31 @@ mwin__dump_region (MDrawRegion region)
 void
 mwin__verify_region (MFrame *frame, MDrawRegion region)
 {
-  set_region (FRAME_DISPLAY (frame), frame->rface,
-             ((GC *) frame->rface->info)[MFACE_GC_NORMAL], region);
+  set_region (frame, ((GCInfo *) frame->rface->info)->gc[GC_NORMAL], region);
 }
 
 MDrawWindow
 mwin__create_window (MFrame *frame, MDrawWindow parent)
 {
-  MWDevice *device = frame->device;
   Display *display = FRAME_DISPLAY (frame);
-  int screen = FRAME_SCREEN (frame);
   Window win;
   XWMHints wm_hints = { InputHint, False };
   XClassHint class_hints = { "M17N-IM", "m17n-im" };
-  XSetWindowAttributes attrs;
+  XWindowAttributes win_attrs;
+  XSetWindowAttributes set_attrs;
   unsigned long mask;
-  MSymbol background = mface_get_prop (frame->face, Mbackground);
-
-  attrs.background_pixel = get_color (display, device->cmap,
-                                     background, background,
-                                     WhitePixel (display, screen));
-  attrs.backing_store = Always;
-  attrs.override_redirect = True;
-  attrs.save_under = True;
-  mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
+
   if (! parent)
-    parent = (MDrawWindow) RootWindow (display, screen);
+    parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
+  XGetWindowAttributes (display, (Window) parent, &win_attrs);
+  set_attrs.background_pixel = win_attrs.backing_pixel;
+  set_attrs.backing_store = Always;
+  set_attrs.override_redirect = True;
+  set_attrs.save_under = True;
+  mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
   win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
                       CopyFromParent, InputOutput, CopyFromParent,
-                      mask, &attrs);
+                      mask, &set_attrs);
   XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
                    NULL, &wm_hints, &class_hints);
   XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
@@ -2034,12 +2085,12 @@ mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
   unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
   XGCValues values;
   Display *display = FRAME_DISPLAY (frame);
-  GC *gcs = rface->info;
+  GCInfo *info = rface->info;
   int i;
 
-  for (i = 0; i <= MFACE_GC_SCRATCH; i++)
+  for (i = 0; i <= GC_INVERSE; i++)
     {
-      XGetGCValues (display, gcs[i], valuemask, &values);
+      XGetGCValues (display, info->gc[i], valuemask, &values);
       fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
               values.foreground, values.background);
       fprintf (stderr, "\n");
index 2c3c011..a56873f 100644 (file)
@@ -76,6 +76,7 @@ free_frame (void *object)
 
   M17N_OBJECT_UNREF (frame->face);
   mwin__close_device ((MFrame *) object);
+  free (frame->font);
   free (object);
 }
 
@@ -313,7 +314,9 @@ mframe (MPlist *plist)
       MERROR (MERROR_WIN, NULL);
     }
 
-  frame->face = mface_copy (mface__default);
+  frame->face = mface_from_font (frame->font);
+  frame->face->property[MFACE_FONTSET] = mfontset (NULL);
+  M17N_OBJECT_REF (mface__default->property[MFACE_FONTSET]);
   if (plist)
     for (; (key = mplist_key (plist)) != Mnil; plist = mplist_next (plist))
       if (key == Mface)
index ba9adf6..9be293e 100644 (file)
@@ -438,6 +438,10 @@ typedef struct
       implemented.  */
   unsigned fixed_width : 1;
 
+  /***en If nonzero, draw glyphs with anti-aliasing if a backend font
+      driver supports it.  */
+  unsigned anti_alias : 1;
+
   /***en If nonzero, the values are minimum line ascent and descent
       pixels.  */
   unsigned int min_line_ascent;