diff src/fontset.c @ 89811:d13626b05df3

(fontset_face): Handle fallback fonts correctly. (Ffontset_info): Return infomation about fallback fonts.
author Kenichi Handa <handa@m17n.org>
date Tue, 10 Feb 2004 11:30:55 +0000
parents 35a0a24752d3
children b17725d55ba2
line wrap: on
line diff
--- a/src/fontset.c	Tue Feb 10 11:30:01 2004 +0000
+++ b/src/fontset.c	Tue Feb 10 11:30:55 2004 +0000
@@ -152,8 +152,8 @@
 	realized from the default fontset, else nil.
 
    The 9th slot:
-	base: vector of fallback FONT-DEFs.
-	base: vector of fallback font vector.
+	base: Same as element value (but for fallback fonts).
+	realized: Likewise.
 
    All fontsets are recorded in the vector Vfontset_table.
 
@@ -285,7 +285,7 @@
 #define FONTSET_REPERTORY(fontset)	XCHAR_TABLE (fontset)->extras[6]
 #define FONTSET_DEFAULT(fontset)	XCHAR_TABLE (fontset)->extras[7]
 
-/* for both base and realized FONTSET  */
+/* For both base and realized fontset.  */
 #define FONTSET_FALLBACK(fontset)	XCHAR_TABLE (fontset)->extras[8]
 
 #define BASE_FONTSET_P(fontset)		(NILP (FONTSET_BASE (fontset)))
@@ -367,12 +367,12 @@
    replace with ELT, if ADD is `prepend', prepend ELT, otherwise,
    append ELT.  */
 
-#define FONTSET_ADD(fontset, range, elt, add)				   \
-  (NILP (add)								   \
-   ? (NILP (range)							   \
-      ? FONTSET_FALLBACK (fontset) = Fmake_vector (make_number (1), (elt)) \
-      : Fset_char_table_range ((fontset), (range),			   \
-			       Fmake_vector (make_number (1), (elt))))	   \
+#define FONTSET_ADD(fontset, range, elt, add)				     \
+  (NILP (add)								     \
+   ? (NILP (range)							     \
+      ? (FONTSET_FALLBACK (fontset) = Fmake_vector (make_number (1), (elt))) \
+      : Fset_char_table_range ((fontset), (range),			     \
+			       Fmake_vector (make_number (1), (elt))))	     \
    : fontset_add ((fontset), (range), (elt), (add)))
 
 static Lisp_Object
@@ -520,12 +520,11 @@
   FRAME_PTR f = XFRAME (FONTSET_FRAME (fontset));
 
   base_fontset = FONTSET_BASE (fontset);
-  elt = CHAR_TABLE_REF (fontset, c);
+  vec = CHAR_TABLE_REF (fontset, c);
+  if (EQ (vec, Qt))
+    goto try_fallback;
 
-  if (EQ (elt, Qt))
-    goto try_default;
-
-  if (NILP (elt))
+  if (NILP (vec))
     {
       /* We have not yet decided a face for C.  */
       Lisp_Object range;
@@ -534,21 +533,13 @@
 	return -1;
       elt = FONTSET_REF_AND_RANGE (base_fontset, c, from, to);
       range = Fcons (make_number (from), make_number (to));
-      vec = Qnil;
       if (NILP (elt))
 	{
-	  vec = FONTSET_FALLBACK (fontset);
-	  if (! NILP (vec))
-	    goto font_vector_ready;
-	  elt = FONTSET_FALLBACK (base_fontset);
-	  if (NILP (elt))
-	    {
-	      /* Record that we have no font for characters of this
-		 range.  */
-	      FONTSET_SET (fontset, range, Qt);
-	      goto try_default;
-	    }
-	  range = Qnil;
+	  /* Record that we have no font for characters of this
+	     range.  */
+	  vec = Qt;
+	  FONTSET_SET (fontset, range, vec);
+	  goto try_fallback;
 	}
       /* Build a vector [ -1 -1 nil NEW-ELT0 NEW-ELT1 NEW-ELT2 ... ],
 	 where the first -1 is to force reordering of NEW-ELTn,
@@ -564,15 +555,10 @@
 	  ASET (vec, 3 + i, tmp);
 	}
       /* Then store it in the fontset.  */
-      if (CONSP (range))
-	FONTSET_SET (fontset, range, vec);
-      else
-	FONTSET_FALLBACK (fontset) = vec;
+      FONTSET_SET (fontset, range, vec);
     }
-  else
-    vec = elt;
 
- font_vector_ready:
+ retry:
   if (XINT (AREF (vec, 0)) != charset_ordered_list_tick)
     /* The priority of charsets is changed after we selected a face
        for C last time.  */
@@ -679,6 +665,35 @@
       return XINT (AREF (elt, 0));
     }
 
+ try_fallback:
+  if (vec != FONTSET_FALLBACK (fontset))
+    {
+      vec = FONTSET_FALLBACK (fontset);
+      if (VECTORP (vec))
+	goto retry;
+      if (EQ (vec, Qt))
+	goto try_default;
+      elt = FONTSET_FALLBACK (base_fontset);
+      if (! NILP (elt))
+	{
+	  vec = Fmake_vector (make_number (ASIZE (elt) + 3), make_number (-1));
+	  ASET (vec, 2, Qnil);
+	  for (i = 0; i < ASIZE (elt); i++)
+	    {
+	      Lisp_Object tmp;
+
+	      tmp = Fmake_vector (make_number (3), Qnil);
+	      ASET (tmp, 2, AREF (elt, i));
+	      ASET (vec, 3 + i, tmp);
+	    }
+	  FONTSET_FALLBACK (fontset) = vec;	  
+	  goto retry;
+	}
+      /* Record that this fontset has no fallback fonts.  */
+      FONTSET_FALLBACK (fontset) = Qt;
+    }
+
+  /* Try the default fontset.  */
  try_default:
   if (! EQ (base_fontset, Vdefault_fontset))
     {
@@ -1682,11 +1697,9 @@
      Lisp_Object fontset, frame;
 {
   FRAME_PTR f;
-  Lisp_Object table, val, elt;
-  Lisp_Object *realized;
-  int n_realized = 0;
-  int fallback;
-  int c, i, j;
+  Lisp_Object *realized[2], fontsets[2], tables[2];
+  Lisp_Object val, elt;
+  int c, i, j, k;
 
   (*check_window_system_func) ();
 
@@ -1699,45 +1712,53 @@
 
   /* Recode fontsets realized on FRAME from the base fontset FONTSET
      in the table `realized'.  */
-  realized = (Lisp_Object *) alloca (sizeof (Lisp_Object)
-				     * ASIZE (Vfontset_table));
-  for (i = 0; i < ASIZE (Vfontset_table); i++)
+  realized[0] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
+					* ASIZE (Vfontset_table));
+  for (i = j = 0; i < ASIZE (Vfontset_table); i++)
     {
       elt = FONTSET_FROM_ID (i);
       if (!NILP (elt)
 	  && EQ (FONTSET_BASE (elt), fontset)
 	  && EQ (FONTSET_FRAME (elt), frame))
-	realized[n_realized++] = elt;
+	realized[0][j++] = elt;
     }
+  realized[0][j] = Qnil;
 
+  realized[1] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
+					* ASIZE (Vfontset_table));
+  for (i = j = 0; ! NILP (realized[0][i]); i++)
+    {
+      elt = FONTSET_DEFAULT (realized[0][i]);
+      if (! NILP (elt))
+	realized[1][j++] = elt;
+    }
+  realized[1][j] = Qnil;
 
-  table = Fmake_char_table (Qfontset_info, Qnil);
-  XCHAR_TABLE (table)->extras[0] = Fmake_char_table (Qnil, Qnil);
+  tables[0] = Fmake_char_table (Qfontset_info, Qnil);
+  tables[1] = Fmake_char_table (Qnil, Qnil);
+  XCHAR_TABLE (tables[0])->extras[0] = tables[1];
+  fontsets[0] = fontset;
+  fontsets[1] = Vdefault_fontset;
+
   /* Accumulate information of the fontset in TABLE.  The format of
      each element is ((FONT-SPEC OPENED-FONT ...) ...).  */
-  for (fallback = 0; fallback <= 1; fallback++)
+  for (k = 0; k <= 1; k++)
     {
-      Lisp_Object this_fontset, this_table;
-
-      if (! fallback)
-	{
-	  this_fontset = fontset;
-	  this_table = table;
-	}
-      else
-	{
-	  this_fontset = Vdefault_fontset;
-	  this_table = XCHAR_TABLE (table)->extras[0];
-#if 0
-	  for (i = 0; i < n_realized; i++)
-	    realized[i] = FONTSET_DEFAULT (realized[i]);
-#endif
-	}
-      for (c = 0; c <= MAX_5_BYTE_CHAR; )
+      for (c = 0; c <= MAX_CHAR; )
 	{
 	  int from, to;
 
-	  val = char_table_ref_and_range (this_fontset, c, &from, &to);
+	  if (c <= MAX_5_BYTE_CHAR)
+	    {
+	      val = char_table_ref_and_range (fontsets[k], c, &from, &to);
+	      if (to > MAX_5_BYTE_CHAR)
+		to = MAX_5_BYTE_CHAR;
+	    }
+	  else
+	    {
+	      val = FONTSET_FALLBACK (fontsets[k]);
+	      to = MAX_CHAR;
+	    }
 	  if (VECTORP (val))
 	    {
 	      Lisp_Object alist;
@@ -1748,12 +1769,13 @@
 	      alist = Fnreverse (alist);
 
 	      /* Then store opend font names to cdr of each elements.  */
-	      for (i = 0; i < n_realized; i++)
+	      for (i = 0; ! NILP (realized[k][i]); i++)
 		{
-		  if (NILP (realized[i]))
-		    continue;
-		  val = FONTSET_REF (realized[i], c);
-		  if (NILP (val))
+		  if (c <= MAX_5_BYTE_CHAR)
+		    val = FONTSET_REF (realized[k][i], c);
+		  else
+		    val = FONTSET_FALLBACK (realized[k][i]);
+		  if (! VECTORP (val))
 		    continue;
 		  /* VAL is [int int int [FACE-ID FONT-INDEX FONT-DEF] ...].
 		     If a font of an element is already opened,
@@ -1779,13 +1801,16 @@
 		  }
 
 	      /* Store ALIST in TBL for characters C..TO.  */
-	      char_table_set_range (this_table, c, to, alist);
+	      if (c <= MAX_5_BYTE_CHAR)
+		char_table_set_range (tables[k], c, to, alist);
+	      else
+		XCHAR_TABLE (tables[k])->defalt = alist;
 	    }
 	  c = to + 1;
 	}
     }
 
-  return table;
+  return tables[0];
 }