]> code.delx.au - gnu-emacs/blobdiff - src/xfaces.c
(xfont_query_font): Adjusted for the change of
[gnu-emacs] / src / xfaces.c
index 0d91f433fced5d7913dd7a9123acb3504de6493d..efdb7b0a6607f5d80bda901a2d82a7fd6746c149 100644 (file)
@@ -246,6 +246,12 @@ Boston, MA 02110-1301, USA.  */
 #include "window.h"
 #include "intervals.h"
 
+#ifdef HAVE_WINDOW_SYSTEM
+#ifdef USE_FONT_BACKEND
+#include "font.h"
+#endif /* USE_FONT_BACKEND */
+#endif /* HAVE_WINDOW_SYSTEM */
+
 #ifdef HAVE_X_WINDOWS
 
 /* Compensate for a bug in Xos.h on some systems, on which it requires
@@ -537,6 +543,8 @@ static int merge_face_ref P_ ((struct frame *, Lisp_Object, Lisp_Object *,
                               int, struct named_merge_point *));
 static int set_lface_from_font_name P_ ((struct frame *, Lisp_Object,
                                         Lisp_Object, int, int));
+static void set_lface_from_font_and_fontset P_ ((struct frame *, Lisp_Object,
+                                                Lisp_Object, int, int));
 static Lisp_Object lface_from_face_name P_ ((struct frame *, Lisp_Object, int));
 static struct face *make_realized_face P_ ((Lisp_Object *));
 static char *best_matching_font P_ ((struct frame *, Lisp_Object *,
@@ -988,6 +996,9 @@ clear_face_cache (clear_fonts_p)
     {
       struct x_display_info *dpyinfo;
 
+#ifdef USE_FONT_BACKEND
+      if (! enable_font_backend)
+#endif /* USE_FONT_BACKEND */
       /* Fonts are common for frames on one display, i.e. on
         one X screen.  */
       for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
@@ -1249,6 +1260,10 @@ load_face_font (f, face)
   char *font_name;
   int needs_overstrike;
 
+#ifdef USE_FONT_BACKEND
+  if (enable_font_backend)
+    abort ();
+#endif /* USE_FONT_BACKEND */
   face->font_info_id = -1;
   face->font = NULL;
   face->font_name = NULL;
@@ -2188,6 +2203,58 @@ face_numeric_swidth (width)
 
 #ifdef HAVE_WINDOW_SYSTEM
 
+#ifdef USE_FONT_BACKEND
+static INLINE Lisp_Object
+face_symbolic_value (table, dim, font_prop)
+     struct table_entry *table;
+     int dim;
+     Lisp_Object font_prop;
+{
+  struct table_entry *p;
+  char *s = SDATA (SYMBOL_NAME (font_prop));
+  int low, mid, high, cmp;
+
+  low = 0;
+  high = dim - 1;
+
+  while (low <= high)
+    {
+      mid = (low + high) / 2;
+      cmp = strcmp (table[mid].name, s);
+
+      if (cmp < 0)
+       low = mid + 1;
+      else if (cmp > 0)
+       high = mid - 1;
+      else
+       return *table[mid].symbol;
+    }
+
+  return Qnil;
+}
+
+static INLINE Lisp_Object
+face_symbolic_weight (weight)
+     Lisp_Object weight;
+{
+  return face_symbolic_value (weight_table, DIM (weight_table), weight);
+}
+
+static INLINE Lisp_Object
+face_symbolic_slant (slant)
+     Lisp_Object slant;
+{
+  return face_symbolic_value (slant_table, DIM (slant_table), slant);
+}
+
+static INLINE Lisp_Object
+face_symbolic_swidth (width)
+     Lisp_Object width;
+{
+  return face_symbolic_value (swidth_table, DIM (swidth_table), width);
+}
+#endif /* USE_FONT_BACKEND */
+
 Lisp_Object
 split_font_name_into_vector (fontname)
      Lisp_Object fontname;
@@ -3229,6 +3296,9 @@ check_lface_attrs (attrs)
   xassert (UNSPECIFIEDP (attrs[LFACE_FONT_INDEX])
           || IGNORE_DEFFACE_P (attrs[LFACE_FONT_INDEX])
           || NILP (attrs[LFACE_FONT_INDEX])
+#ifdef USE_FONT_BACKEND
+          || FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])
+#endif /* USE_FONT_BACKEND */
           || STRINGP (attrs[LFACE_FONT_INDEX]));
   xassert (UNSPECIFIEDP (attrs[LFACE_FONTSET_INDEX])
           || STRINGP (attrs[LFACE_FONTSET_INDEX]));
@@ -3467,6 +3537,7 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
 
   /* If FONTNAME is actually a fontset name, get ASCII font name of it.  */
   fontset = fs_query_fontset (fontname, 0);
+
   if (fontset > 0)
     font_name = SDATA (fontset_ascii (fontset));
   else if (fontset == 0)
@@ -3559,6 +3630,88 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
   return 1;
 }
 
+#ifdef USE_FONT_BACKEND
+/* Set font-related attributes of Lisp face LFACE from FONT-OBJECT and
+   FONTSET.  If FORCE_P is zero, set only unspecified attributes of
+   LFACE.  The exceptions are `font' and `fontset' attributes.  They
+   are set regardless of FORCE_P.  */
+
+static void
+set_lface_from_font_and_fontset (f, lface, font_object, fontset, force_p)
+     struct frame *f;
+     Lisp_Object lface, font_object;
+     int fontset;
+     int force_p;
+{
+  struct font *font = XSAVE_VALUE (font_object)->pointer;
+  Lisp_Object entity = font->entity;
+  Lisp_Object val;
+
+  /* Set attributes only if unspecified, otherwise face defaults for
+     new frames would never take effect.  If the font doesn't have a
+     specific property, set a normal value for that.  */
+
+  if (force_p || UNSPECIFIEDP (LFACE_FAMILY (lface)))
+    {
+      Lisp_Object foundry = AREF (entity, FONT_FOUNDRY_INDEX);
+      Lisp_Object family = AREF (entity, FONT_FAMILY_INDEX);
+
+      if (! NILP (foundry))
+       {
+         if (! NILP (family))
+           val = concat3 (SYMBOL_NAME (foundry), build_string ("-"),
+                          SYMBOL_NAME (family));
+         else
+           val = concat2 (SYMBOL_NAME (foundry), build_string ("-*"));
+       }
+      else
+       {
+         if (! NILP (family))
+           val = SYMBOL_NAME (family);
+         else
+           val = build_string ("*");
+       }
+      LFACE_FAMILY (lface) = val;
+    }
+
+  if (force_p || UNSPECIFIEDP (LFACE_HEIGHT (lface)))
+    {
+      int pt = pixel_point_size (f, font->pixel_size * 10);
+
+      xassert (pt > 0);
+      LFACE_HEIGHT (lface) = make_number (pt);
+    }
+
+  if (force_p || UNSPECIFIEDP (LFACE_AVGWIDTH (lface)))
+    LFACE_AVGWIDTH (lface) = make_number (font->font.average_width);
+
+  if (force_p || UNSPECIFIEDP (LFACE_WEIGHT (lface)))
+    {
+      Lisp_Object weight = font_symbolic_weight (entity);
+
+      val = NILP (weight) ? Qnormal : face_symbolic_weight (weight);
+      LFACE_WEIGHT (lface) = ! NILP (val) ? val : weight;
+    }
+  if (force_p || UNSPECIFIEDP (LFACE_SLANT (lface)))
+    {
+      Lisp_Object slant = font_symbolic_slant (entity);
+
+      val = NILP (slant) ? Qnormal : face_symbolic_slant (slant);
+      LFACE_SLANT (lface) = ! NILP (val) ? val : slant;
+    }
+  if (force_p || UNSPECIFIEDP (LFACE_SWIDTH (lface)))
+    {
+      Lisp_Object width = font_symbolic_width (entity);
+
+      val = NILP (width) ? Qnormal : face_symbolic_swidth (width);
+      LFACE_SWIDTH (lface) = ! NILP (val) ? val : width;
+    }
+
+  LFACE_FONT (lface) = font_object;
+  LFACE_FONTSET (lface) = fontset_name (fontset);
+}
+#endif /* USE_FONT_BACKEND */
+
 #endif /* HAVE_WINDOW_SYSTEM */
 
 
@@ -4396,6 +4549,48 @@ FRAME 0 means change the face on all frames, and change the default
          else
            f = check_x_frame (frame);
 
+#ifdef USE_FONT_BACKEND
+         if (enable_font_backend
+             && !UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+           {
+             int fontset;
+
+             if (EQ (attr, QCfontset))
+               {
+                 Lisp_Object fontset_name = Fquery_fontset (value, Qnil);
+
+                 if (NILP (fontset_name))
+                   signal_error ("Invalid fontset name", value);
+                 LFACE_FONTSET (lface) = value;
+               }
+             else
+               {
+                 Lisp_Object font_object;
+
+                 if (FONT_OBJECT_P (value))
+                   {
+                     font_object = value;
+                     fontset = FRAME_FONTSET (f);
+                   }
+                 else
+                   {
+                     CHECK_STRING (value);
+
+                     fontset = fs_query_fontset (value, 0);
+                     if (fontset >= 0)
+                       value = fontset_ascii (fontset);
+                     else
+                       fontset = FRAME_FONTSET (f);
+                     font_object = font_open_by_name (f, SDATA (value));
+                     if (NILP (font_object))
+                       signal_error ("Invalid font", value);
+                   }
+                 set_lface_from_font_and_fontset (f, lface, font_object,
+                                                  fontset, 1);
+               }
+           }
+         else
+#endif /* USE_FONT_BACKEND */
          if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
            {
              CHECK_STRING (value);
@@ -4592,6 +4787,23 @@ set_font_frame_param (frame, lface)
 
       if (STRINGP (LFACE_FONT (lface)))
        font_name = LFACE_FONT (lface);
+#ifdef USE_FONT_BACKEND
+      else if (enable_font_backend)
+       {
+         /* We set FONT_NAME to a font-object.  */
+         if (FONT_OBJECT_P (LFACE_FONT (lface)))
+           font_name = LFACE_FONT (lface);
+         else
+           {
+             font_name = font_find_for_lface (f, &AREF (lface, 0), Qnil);
+             if (NILP (font_name))
+               error ("No font matches the specified attribute");
+             font_name = font_open_for_lface (f, &AREF (lface, 0), font_name);
+             if (NILP (font_name))
+               error ("No font matches the specified attribute");
+           }
+       }
+#endif
       else
        {
          /* Choose a font name that reflects LFACE's attributes and has
@@ -5063,10 +5275,12 @@ Default face attributes override any local face attributes.  */)
   gvec = XVECTOR (global_lface)->contents;
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
     if (! UNSPECIFIEDP (gvec[i]))
-      if (IGNORE_DEFFACE_P (gvec[i]))
-       lvec[i] = Qunspecified;
-      else
-       lvec[i] = gvec[i];
+      {
+       if (IGNORE_DEFFACE_P (gvec[i]))
+         lvec[i] = Qunspecified;
+       else
+         lvec[i] = gvec[i];
+      }
 
   return Qnil;
 }
@@ -5355,6 +5569,10 @@ free_realized_face (f, face)
            free_face_fontset (f, face);
          if (face->gc)
            {
+#ifdef USE_FONT_BACKEND
+             if (enable_font_backend && face->font_info)
+               font_done_for_face (f, face);
+#endif /* USE_FONT_BACKEND */
              x_free_gc (f, face->gc);
              face->gc = 0;
            }
@@ -5416,6 +5634,10 @@ prepare_face_for_display (f, face)
        }
 #endif
       face->gc = x_create_gc (f, mask, &xgcv);
+#ifdef USE_FONT_BACKEND
+      if (enable_font_backend && face->font)
+       font_prepare_for_face (f, face);
+#endif /* USE_FONT_BACKEND */
       UNBLOCK_INPUT;
     }
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -5522,6 +5744,10 @@ clear_face_gcs (c)
          struct face *face = c->faces_by_id[i];
          if (face && face->gc)
            {
+#ifdef USE_FONT_BACKEND
+             if (enable_font_backend && face->font_info)
+               font_done_for_face (c->f, face);
+#endif /* USE_FONT_BACKEND */
              x_free_gc (c->f, face->gc);
              face->gc = 0;
            }
@@ -5848,6 +6074,43 @@ lookup_non_ascii_face (f, font_id, base_face)
 
   return face->id;
 }
+
+#ifdef USE_FONT_BACKEND
+int
+face_for_font (f, font, base_face)
+     struct frame *f;
+     struct font *font;
+     struct face *base_face;
+{
+  struct face_cache *cache = FRAME_FACE_CACHE (f);
+  unsigned hash;
+  int i;
+  struct face *face;
+
+  xassert (cache != NULL);
+  base_face = base_face->ascii_face;
+  hash = lface_hash (base_face->lface);
+  i = hash % FACE_CACHE_BUCKETS_SIZE;
+
+  for (face = cache->buckets[i]; face; face = face->next)
+    {
+      if (face->ascii_face == face)
+       continue;
+      if (face->ascii_face == base_face
+         && face->font_info == (struct font_info *) font)
+       return face->id;
+    }
+
+  /* If not found, realize a new face.  */
+  face = realize_non_ascii_face (f, -1, base_face);
+  face->font = font->font.font;
+  face->font_info = (struct font_info *) font;
+  face->font_info_id = 0;
+  face->font_name = font->font.full_name;
+  return face->id;
+}
+#endif /* USE_FONT_BACKEND */
+
 #endif /* HAVE_WINDOW_SYSTEM */
 
 /* Return the face id of the realized face for named face SYMBOL on
@@ -6449,6 +6712,10 @@ Value is ORDER.  */)
       free_all_realized_faces (Qnil);
     }
 
+#ifdef USE_FONT_BACKEND
+  font_update_sort_order (font_sort_order);
+#endif /* USE_FONT_BACKEND */
+
   return Qnil;
 }
 
@@ -6529,6 +6796,12 @@ better_font_p (values, font1, font2, compare_pt_p, avgwidth)
 {
   int i;
 
+  /* Any font is better than no font.  */
+  if (! font1)
+    return 0;
+  if (! font2)
+    return 1;
+
   for (i = 0; i < DIM (font_sort_order); ++i)
     {
       int xlfd_idx = font_sort_order[i];
@@ -6779,29 +7052,19 @@ best_matching_font (f, attrs, fonts, nfonts, width_ratio, needs_overstrike)
   if (needs_overstrike)
     *needs_overstrike = 0;
 
-  /* Start with the first non-scalable font in the list.  */
-  for (i = 0; i < nfonts; ++i)
-    if (!font_scalable_p (fonts + i))
-      break;
+  best = NULL;
 
   /* Find the best match among the non-scalable fonts.  */
-  if (i < nfonts)
-    {
-      best = fonts + i;
-
-      for (i = 1; i < nfonts; ++i)
-       if (!font_scalable_p (fonts + i)
-           && better_font_p (specified, fonts + i, best, 1, avgwidth))
-         {
-           best = fonts + i;
+  for (i = 0; i < nfonts; ++i)
+    if (!font_scalable_p (fonts + i)
+       && better_font_p (specified, fonts + i, best, 1, avgwidth))
+      {
+       best = fonts + i;
 
-           exact_p = exact_face_match_p (specified, best, avgwidth);
-           if (exact_p)
-             break;
-         }
-    }
-  else
-    best = NULL;
+       exact_p = exact_face_match_p (specified, best, avgwidth);
+       if (exact_p)
+         break;
+      }
 
   /* Unless we found an exact match among non-scalable fonts, see if
      we can find a better match among scalable fonts.  */
@@ -6825,8 +7088,7 @@ best_matching_font (f, attrs, fonts, nfonts, width_ratio, needs_overstrike)
       for (i = 0; i < nfonts; ++i)
        if (font_scalable_p (fonts + i))
          {
-           if (best == NULL
-               || better_font_p (specified, fonts + i, best, 0, 0)
+           if (better_font_p (specified, fonts + i, best, 0, 0)
                || (!non_scalable_has_exact_height_p
                    && !better_font_p (specified, best, fonts + i, 0, 0)))
              {
@@ -6834,23 +7096,27 @@ best_matching_font (f, attrs, fonts, nfonts, width_ratio, needs_overstrike)
                best = fonts + i;
              }
          }
+    }
 
-      if (needs_overstrike)
-       {
-         enum xlfd_weight want_weight = specified[XLFD_WEIGHT];
-         enum xlfd_weight got_weight = best->numeric[XLFD_WEIGHT];
+  /* We should have found SOME font.  */
+  if (best == NULL)
+    abort ();
 
-         if (want_weight > XLFD_WEIGHT_MEDIUM && want_weight > got_weight)
-           {
-             /* We want a bold font, but didn't get one; try to use
-                overstriking instead to simulate bold-face.  However,
-                don't overstrike an already-bold fontn unless the
-                desired weight grossly exceeds the available weight.  */
-             if (got_weight > XLFD_WEIGHT_MEDIUM)
-               *needs_overstrike = (got_weight - want_weight) > 2;
-             else
-               *needs_overstrike = 1;
-           }
+  if (! exact_p && needs_overstrike)
+    {
+      enum xlfd_weight want_weight = specified[XLFD_WEIGHT];
+      enum xlfd_weight got_weight = best->numeric[XLFD_WEIGHT];
+
+      if (want_weight > XLFD_WEIGHT_MEDIUM && want_weight > got_weight)
+       {
+         /* We want a bold font, but didn't get one; try to use
+            overstriking instead to simulate bold-face.  However,
+            don't overstrike an already-bold fontn unless the
+            desired weight grossly exceeds the available weight.  */
+         if (got_weight > XLFD_WEIGHT_MEDIUM)
+           *needs_overstrike = (got_weight - want_weight) > 2;
+         else
+           *needs_overstrike = 1;
        }
     }
 
@@ -7177,12 +7443,27 @@ realize_default_face (f)
 #ifdef HAVE_WINDOW_SYSTEM
   if (FRAME_WINDOW_P (f))
     {
+#ifdef USE_FONT_BACKEND
+      if (enable_font_backend)
+       {
+         frame_font = font_find_object (FRAME_FONT_OBJECT (f));
+         xassert (FONT_OBJECT_P (frame_font));
+         set_lface_from_font_and_fontset (f, lface, frame_font,
+                                          FRAME_FONTSET (f),
+                                          f->default_face_done_p);
+       }
+      else
+       {
+#endif /* USE_FONT_BACKEND */
       /* Set frame_font to the value of the `font' frame parameter.  */
       frame_font = Fassq (Qfont, f->param_alist);
       xassert (CONSP (frame_font) && STRINGP (XCDR (frame_font)));
       frame_font = XCDR (frame_font);
       set_lface_from_font_name (f, lface, frame_font,
                                 f->default_face_done_p, 1);
+#ifdef USE_FONT_BACKEND
+       }
+#endif /* USE_FONT_BACKEND */
       f->default_face_done_p = 1;
     }
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -7253,6 +7534,16 @@ realize_default_face (f)
   check_lface (lface);
   bcopy (XVECTOR (lface)->contents, attrs, sizeof attrs);
   face = realize_face (c, attrs, DEFAULT_FACE_ID);
+
+#ifdef HAVE_WINDOW_SYSTEM
+#ifdef HAVE_X_WINDOWS
+  if (face->font != FRAME_FONT (f))
+    /* As the font specified for the frame was not acceptable as a
+       font for the default face (perhaps because auto-scaled fonts
+       are rejected), we must adjust the frame font.  */
+    x_set_font (f, build_string (face->font_name), Qnil);
+#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
   return 1;
 }
 
@@ -7413,6 +7704,9 @@ realize_x_face (cache, attrs)
     {
       face->font = default_face->font;
       face->font_info_id = default_face->font_info_id;
+#ifdef USE_FONT_BACKEND
+      face->font_info = default_face->font_info;
+#endif /* USE_FONT_BACKEND */
       face->font_name = default_face->font_name;
       face->fontset
        = make_fontset_for_ascii_face (f, default_face->fontset, face);
@@ -7435,8 +7729,16 @@ realize_x_face (cache, attrs)
        fontset = default_face->fontset;
       if (fontset == -1)
        abort ();
+#ifdef USE_FONT_BACKEND
+      if (enable_font_backend)
+       font_load_for_face (f, face);
+      else
+#endif /* USE_FONT_BACKEND */
       load_face_font (f, face);
-      face->fontset = make_fontset_for_ascii_face (f, fontset, face);
+      if (face->font)
+       face->fontset = make_fontset_for_ascii_face (f, fontset, face);
+      else
+       face->fontset = -1;
     }
 
   /* Load colors, and set remaining attributes.  */