diff src/fontset.c @ 91231:29d8135e8f58

(fontset_add): New args charset_id and famliy. Caller changed. (load_font_get_repertory): Assume that font_spec is always a font-spec object. (fontset_find_font): Likewise. (Fset_fontset_font): Always store a font-spec object in a fontset.
author Kenichi Handa <handa@m17n.org>
date Thu, 13 Dec 2007 02:43:56 +0000
parents 3ce31df2ea58
children 6133244f82b7
line wrap: on
line diff
--- a/src/fontset.c	Thu Dec 13 01:33:14 2007 +0000
+++ b/src/fontset.c	Thu Dec 13 02:43:56 2007 +0000
@@ -116,8 +116,8 @@
 
    An element of a realized fontset is nil or t, or has this form:
 
-	[CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID
-	 PREFERRED-RFONT-DEF RFONT-DEF0 RFONT-DEF1 ...].
+	[CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-FAMILY
+	 RFONT-DEF0 RFONT-DEF1 ...].
 
    RFONT-DEFn (i.e. Realized FONT-DEF) has this form:
 
@@ -262,6 +262,7 @@
 /* Prototype declarations for static functions.  */
 static Lisp_Object fontset_add P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
 				    Lisp_Object));
+static void reorder_font_vector P_ ((Lisp_Object, int, Lisp_Object));
 static Lisp_Object fontset_font P_ ((Lisp_Object, int, struct face *, int));
 static Lisp_Object make_fontset P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
 static Lisp_Object fontset_pattern_regexp P_ ((Lisp_Object));
@@ -430,59 +431,92 @@
 }
 
 
-/* Update FONTSET_ELEMENT which has this form:
-	[CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-RFONT-DEF
+/* Update FONT-GROUP which has this form:
+	[CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-FAMILY
 	 RFONT-DEF0 RFONT-DEF1 ...].
    Reorder RFONT-DEFs according to the current order of charset
    (Vcharset_ordered_list), and update CHARSET-ORDERED-LIST-TICK to
    the latest value.  */
 
 static void
-reorder_font_vector (fontset_element)
-     Lisp_Object fontset_element;
+reorder_font_vector (font_group, charset_id, family)
+     Lisp_Object font_group;
+     int charset_id;
+     Lisp_Object family;
 {
   Lisp_Object list, *new_vec;
-  Lisp_Object font_def;
   int size;
   int *charset_id_table;
   int i, idx;
+  Lisp_Object preferred_by_charset, preferred_by_family;
 
-  ASET (fontset_element, 0, make_number (charset_ordered_list_tick));
-  size = ASIZE (fontset_element) - 3;
+  ASET (font_group, 0, make_number (charset_ordered_list_tick));
+  ASET (font_group, 1, make_number (charset_id));
+  ASET (font_group, 2, family);
+  size = ASIZE (font_group) - 3;
   if (size <= 1)
     /* No need to reorder VEC.  */
     return;
   charset_id_table = (int *) alloca (sizeof (int) * size);
   new_vec = (Lisp_Object *) alloca (sizeof (Lisp_Object) * size);
 
-  /* At first, extract ENCODING (a chaset ID) from each FONT-DEF.
-     FONT-DEF has this form:
-	[FACE-ID FONT-INDEX [ FONT-SPEC ENCODING REPERTORY ]] */
-  for (i = 0; i < size; i++)
+  /* At first, extract ENCODING (a chaset ID) from RFONT_DEF which
+     has this form:
+	[FACE-ID FONT-INDEX [ FONT-SPEC ENCODING REPERTORY ]]
+     In addtion, if RFONT_DEF is preferred by family or charset, store
+     it from the start of new_vec.  */
+  for (i = 0, idx = 0; i < size; i++)
     {
-      font_def = AREF (fontset_element, i + 3);
-      if (VECTORP (AREF (font_def, 2))
-	  && INTEGERP (AREF (AREF (font_def, 2), 1)))
-	charset_id_table[i] = XINT (AREF (AREF (font_def, 2), 1));
-      else
-	charset_id_table[i] = -1;
+      Lisp_Object rfont_def = AREF (font_group, i + 3);
+      Lisp_Object font_spec = AREF (AREF (rfont_def, 2), 0);
+      Lisp_Object this_family = AREF (font_spec, FONT_FAMILY_INDEX);
+      int id = XINT (AREF (AREF (rfont_def, 2), 1));
+      struct charset *charset = CHARSET_FROM_ID (id);
+
+      charset_id_table[i] = -1;
+      if (! NILP (this_family)
+	  && (fast_string_match_ignore_case (family, SYMBOL_NAME (this_family))
+	      >= 0))
+	{
+	  if (idx > 0)
+	    memmove (new_vec + 1, new_vec, sizeof (Lisp_Object) * idx);
+	  new_vec[0] = rfont_def;
+	  idx++;
+	  ASET (font_group, i + 3, Qnil);
+	}
+      else if (id == charset_id)
+	{
+	  new_vec[idx++] = rfont_def;
+	  ASET (font_group, i + 3, Qnil);
+	}
+      else if (! charset->supplementary_p)
+	charset_id_table[i] = id;
     }
 
-  /* Then, store FONT-DEFs in NEW_VEC in the correct order.  */
-  for (idx = 0, list = Vcharset_ordered_list;
-       idx < size && CONSP (list); list = XCDR (list))
+  /* Then, store the remaining RFONT-DEFs in NEW_VEC in the correct
+     order.  */
+  for (list = Vcharset_ordered_list; idx < size; list = XCDR (list))
     {
+      int id = XINT (XCAR (list));
+      struct charset *charset = CHARSET_FROM_ID (id);
+
+      if (charset->supplementary_p)
+	break;
       for (i = 0; i < size; i++)
-	if (charset_id_table[i] == XINT (XCAR (list)))
-	  new_vec[idx++] = AREF (fontset_element, i + 3);
+	if (charset_id_table[i] == XINT (XCAR (list))
+	    && ! NILP (AREF (font_group, i + 2)))
+	  {
+	    new_vec[idx++] = AREF (font_group, i + 3);
+	    ASET (font_group, i + 3, Qnil);
+	  }
     }
   for (i = 0; i < size; i++)
-    if (charset_id_table[i] < 0)
-      new_vec[idx++] = AREF (fontset_element, i + 3);
+    if (! NILP (AREF (font_group, i + 3)))
+      new_vec[idx++] = AREF (font_group, i + 3);
 
-  /* At last, update FONT-DEFs.  */
+  /* At last, update elements of FONT-GROUP.  */
   for (i = 0; i < size; i++)
-    ASET (fontset_element, i + 3, new_vec[i]);
+    ASET (font_group, i + 3, new_vec[i]);
 }
 
 
@@ -493,6 +527,8 @@
    If REPERTORY is nil, generate a char-table representing the font
    repertory by looking into the font itself.  */
 
+extern Lisp_Object QCname;
+
 static int
 load_font_get_repertory (f, face, font_def, fontset)
      FRAME_PTR f;
@@ -503,8 +539,14 @@
   char *font_name;
   struct font_info *font_info;
   int charset;
+  Lisp_Object font_spec, name;
 
-  font_name = choose_face_font (f, face->lface, AREF (font_def, 0), NULL);
+  font_spec = AREF (font_def, 0);
+  name = Ffont_get (font_spec, QCname);
+  if (! NILP (name))
+    font_name = choose_face_font (f, face->lface, name, NULL);
+  else
+    font_name = choose_face_font (f, face->lface, font_spec, NULL);
   charset = XINT (AREF (font_def, 1));
   if (! (font_info = fs_load_font (f, font_name, charset)))
     return -1;
@@ -535,7 +577,7 @@
    If no proper font is found for C, return Qnil.
    ID is a charset-id that must be preferred, or -1 meaning no
    preference.
-   If FALLBACK if nonzero, search only fallback fonts.  */
+   If FALLBACK is nonzero, search only fallback fonts.  */
 
 static Lisp_Object
 fontset_find_font (fontset, c, face, id, fallback)
@@ -556,16 +598,46 @@
     vec = FONTSET_FALLBACK (fontset);
   if (NILP (vec))
     {
-      /* We have not yet decided a font for C.  */
       Lisp_Object range;
 
+      /* We have not yet decided a font for C.  */
       if (! face)
 	return Qnil;
       if (! fallback)
-	elt = FONTSET_REF_AND_RANGE (base_fontset, c, from, to);
+	{
+	  elt = FONTSET_REF_AND_RANGE (base_fontset, c, from, to);
+	  range = Fcons (make_number (from), make_number (to));
+	  if (EQ (base_fontset, Vdefault_fontset))
+	    {
+	      Lisp_Object script = CHAR_TABLE_REF (Vchar_script_table, c);
+
+	      if (! NILP (script))
+		{
+		  Lisp_Object font_spec = Ffont_spec (0, NULL);
+	      
+		  ASET (font_spec, FONT_REGISTRY_INDEX, Qiso10646_1);
+		  ASET (font_spec, FONT_EXTRA_INDEX,
+			Fcons (Fcons (QCscript, script), Qnil));
+		  if (NILP (elt))
+		    elt = Fvector (1, &font_spec);
+		  else
+		    {
+		      Lisp_Object args[2], tmp;
+
+		      args[0] = elt;
+		      tmp = Fmake_vector (make_number (3), Qnil);
+		      ASET (tmp, 0, font_spec);
+		      ASET (tmp, 1, CHARSET_SYMBOL_ID (Qunicode_bmp));
+		      args[1] = Fvector (1, &tmp);
+		      elt = Fvconcat (2, args);
+		    }
+		}
+	    }
+	}
       else
-	elt = FONTSET_FALLBACK (base_fontset);
-      range = Fcons (make_number (from), make_number (to));
+	{
+	  elt = FONTSET_FALLBACK (base_fontset);
+	}
       if (NILP (elt))
 	{
 	  /* Qt means we have no font for characters of this range.  */
@@ -576,99 +648,42 @@
 	  /* Build a vector [ -1 -1 nil NEW-ELT0 NEW-ELT1 NEW-ELT2 ... ],
 	     where the first -1 is to force reordering of NEW-ELTn,
 	     NEW-ELTn is [nil nil AREF (elt, n) nil].  */
-#ifdef USE_FONT_BACKEND
-	  if (! fallback
-	      && enable_font_backend
-	      && EQ (base_fontset, Vdefault_fontset))
-	    /* Extra one element is for an automatically added
-	       font-def specifying only a script.  */
-	    vec = Fmake_vector (make_number (ASIZE (elt) + 4), Qnil);
-	  else
-#endif	/* not USE_FONT_BACKEND */
-	    vec = Fmake_vector (make_number (ASIZE (elt) + 3), Qnil);
+	  vec = Fmake_vector (make_number (ASIZE (elt) + 3), Qnil);
 	  ASET (vec, 0, make_number (-1));
 	  ASET (vec, 1, make_number (-1));
 	  for (i = 0; i < ASIZE (elt); i++)
 	    {
 	      Lisp_Object tmp;
-
 	      tmp = Fmake_vector (make_number (5), Qnil);
 	      ASET (tmp, 2, AREF (elt, i));
-	      ASET (vec, 3 + i, tmp);
+	      ASET (vec, i + 3, tmp);
 	    }
-#ifdef USE_FONT_BACKEND
-	  if (! fallback
-	      && enable_font_backend
-	      && EQ (base_fontset, Vdefault_fontset))
-	    {
-	      Lisp_Object script, font_spec;
-
-	      script = CHAR_TABLE_REF (Vchar_script_table, c);
-	      if (NILP (script))
-		script = intern ("latin");
-	      font_spec = Ffont_spec (0, NULL);
-	      ASET (font_spec, FONT_REGISTRY_INDEX, Qiso10646_1);
-	      ASET (font_spec, FONT_EXTRA_INDEX,
-		    Fcons (Fcons (QCscript, script), Qnil));
-	      font_def = Fmake_vector (make_number (3), Qnil);
-	      ASET (font_def, 0, font_spec);
-	      elt = Fmake_vector (make_number (5), Qnil);
-	      ASET (elt, 2, font_def);
-	      ASET (vec, 3 + i, elt);
-	    }
-#endif	/* USE_FONT_BACKEND */
-
-	  /* Then store it in the fontset.  */
-	  if (! fallback)
-	    FONTSET_SET (fontset, range, vec);
-	  else
-	    FONTSET_FALLBACK (fontset) = vec;
 	}
+      /* Then store it in the fontset.  */
+      if (! fallback)
+	FONTSET_SET (fontset, range, vec);
+      else
+	FONTSET_FALLBACK (fontset) = vec;
     }
   if (EQ (vec, Qt))
     return Qnil;
 
-  if (XINT (AREF (vec, 0)) != charset_ordered_list_tick)
-    /* The priority of charsets is changed after we selected a face
-       for C last time.  */
-    reorder_font_vector (vec);
-
-  if (id < 0)
-    i = 3;
-  else
-    {
-      struct charset *charset = CHARSET_FROM_ID (id);
-
-      if (charset->supplementary_p)
-	i = 3;
-      else if (id == XFASTINT (AREF (vec, 1)))
-	i = 2;
-      else
-	{
-	  ASET (vec, 1, make_number (id));
-	  for (i = 3; i < ASIZE (vec); i++)
-	    if (id == XFASTINT (AREF (AREF (AREF (vec, i), 2), 1)))
-	      break;
-	  if (i < ASIZE (vec))
-	    {
-	      ASET (vec, 2, AREF (vec, i));
-	      i = 2;
-	    }
-	  else
-	    {
-	      ASET (vec, 2, Qnil);
-	      i = 3;
-	    }
-	}
-    }
+  if (XINT (AREF (vec, 0)) != charset_ordered_list_tick
+      || XINT (AREF (vec, 1)) != id
+      || NILP (Fequal (AREF (vec, 2), face->lface[LFACE_FAMILY_INDEX])))
+    /* We have just created VEC,
+       or the charset priorities were changed,
+       or the preferred charset was changed,
+       or the preferred family was changed.  */
+    reorder_font_vector (vec, id, face->lface[LFACE_FAMILY_INDEX]);
 
   /* Find the first available font in the vector of RFONT-DEF.  */
-  for (; i < ASIZE (vec); i++)
+  for (i = 3; i < ASIZE (vec); i++)
     {
       elt = AREF (vec, i);
       if (NILP (elt))
 	continue;
-      /* ELT == [ FACE-ID FONT-INDEX FONT-DEF OPENED-FONT-NAME ] */
+      /* ELT == [ FACE-ID FONT-INDEX FONT-DEF ... ] */
       if (INTEGERP (AREF (elt, 1)) && XINT (AREF (elt, 1)) < 0)
 	/* We couldn't open this font last time.  */
 	continue;
@@ -725,22 +740,6 @@
 	      Lisp_Object font_spec = AREF (font_def, 0);
 	      Lisp_Object font_entity;
 
-	      if (! FONT_SPEC_P (font_spec))
-		{
-		  /* FONT_SPEC is FONT-NAME or (FAMILY . REGISTRY).  */
-		  font_spec = Ffont_spec (0, NULL);
-		  if (STRINGP (AREF (font_def, 0)))
-		    font_merge_old_spec (AREF (font_def, 0), Qnil, Qnil,
-					 font_spec);
-		  else
-		    {
-		      Lisp_Object family = AREF (AREF (font_def, 0), 0);
-		      Lisp_Object registry = AREF (AREF (font_def, 0), 5);;
-
-		      font_merge_old_spec (Qnil, family, registry, font_spec);
-		    }
-		  ASET (font_def, 0, font_spec);
-		}
 	      font_entity = font_find_for_lface (f, face->lface, font_spec, c);
 	      if (NILP (font_entity))
 		continue;
@@ -1623,12 +1622,6 @@
     {
       if (! FONT_SPEC_P (font_spec))
 	Fsignal (Qfont, list2 (build_string ("invalid font-spec"), font_spec));
-      family = Ffont_get (font_spec, QCfamily);
-      if (! NILP (family) && SYMBOLP (family))
-	family = SYMBOL_NAME (family);
-      registry = Ffont_get (font_spec, QCregistry);
-      if (! NILP (registry) && SYMBOLP (registry))
-	registry = SYMBOL_NAME (registry);
     }
   else if (CONSP (font_spec))
     {
@@ -1651,14 +1644,22 @@
     }
   else
     {
+      Lisp_Object args[2];
+
       CHECK_STRING (font_spec);
-      font_spec = Fdowncase (font_spec);
+      args[0] = QCname;
+      args[1] = font_spec;
+      font_spec = Ffont_spec (2, args);
     }
 
-  if (STRINGP (font_spec))
-    encoding = find_font_encoding (font_spec);
-  else
-    encoding = find_font_encoding (concat2 (family, registry));
+  family = AREF (font_spec, FONT_FAMILY_INDEX);
+  if (! NILP (family) && SYMBOLP (family))
+    family = SYMBOL_NAME (family);
+  registry = AREF (font_spec, FONT_REGISTRY_INDEX);
+  if (! NILP (registry) && SYMBOLP (registry))
+    registry = SYMBOL_NAME (registry);
+
+  encoding = find_font_encoding (concat2 (family, registry));
   if (NILP (encoding))
     encoding = Qascii;