This uses XFT's native font character-coverage API when looking up a font to
use for a given character set. Stephen had some doubts about using this, and
I think they're worth revisiting when we have a decent language-tagging
infrastructure in place within XEmacs, but for the moment, they give,
effectively, equivalent functionality to what we have under native X11
without major acrobatics.
I've also omitted the CCL charset translation when XFT is in place; I quote
from the comment beside this:
/* There's no need to special-case charsets that use CCL conversion
here. XFT gives us access to a _unified_ character set, so _there
is no difference_ between a Windows 1251 CYRILLIC CAPITAL LETTER
ES and an ISO 8859-5 CYRILLIC CAPITAL LETTER ES, because they
both map to the same code point in the UCS.
If there were any indication that the Mule charset CCL conversion
were used for some other purpose than something orthogonal to the
iso-8859-5 --> non-ISO-2022 conversion, there would be grounds
for reconsidering this. */
Also, don't abort when we don't get a good Unicode translation for a
character. We don't enforce that every character set has to have a Unicode
translation at the moment. Stephen, did you load etc/HELLO with your
previous patch at all? :-)
(Note, I’m not applying this, nor considering doing so. If you’ve written
this functionality already, Stephen, that’s cool.)
src/ChangeLog addition:
2005-01-17 Aidan Kehoe <kehoea(a)parhasard.net>
* charset.h: Include a fontconfig header file, declare
fc_charset_from_mule_charset.
* objects-x.c (x_find_charset_font): Call
fc_charset_from_mule_charset, use its result when looking up the
XFT font to use for a given Mule charset.
* redisplay-x.c (separate_textual_runs): Abort less on interesting
Mule character sets.
* unicode.c (fc_charset_from_mule_charset): Added. Uses a static
array of length NUM_LEADING_BYTES to cache the Mule charsets'
FcCharSet objects.
xemacs-sjt-xft source patch:
Diff command: cvs -q diff -u
Files affected: src/unicode.c src/redisplay-x.c src/objects-x.c src/charset.h
Index: src/charset.h
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/charset.h,v
retrieving revision 1.9
diff -u -r1.9 charset.h
--- src/charset.h 2004/11/04 23:06:16 1.9
+++ src/charset.h 2005/01/17 23:13:15
@@ -549,4 +549,12 @@
#endif /* MULE */
+#ifdef USE_XFT
+
+#include <fontconfig/fontconfig.h>
+
+FcCharSet *fc_charset_from_mule_charset(Lisp_Object charset);
+
+#endif /* USE_XFT */
+
#endif /* INCLUDED_charset_h_ */
Index: src/objects-x.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/objects-x.c,v
retrieving revision 1.26.2.5
diff -u -r1.26.2.5 objects-x.c
--- src/objects-x.c 2004/12/11 05:16:25 1.26.2.5
+++ src/objects-x.c 2005/01/17 23:13:20
@@ -1035,11 +1035,46 @@
and FcInitBringUpToDate() here? */
{
FcChar8 *lang = "en";
+ FcCharSet *fccharset = NULL;
fcc = FcConfigGetCurrent ();
patternxft = FcNameParse (patternext);
+
+ if (debug_xft > 0)
+ {
+ stderr_out ("finding a charset font for mule charset id %i\n",
+ XCHARSET_ID(charset));
+ }
+
+ fccharset = fc_charset_from_mule_charset(charset);
+ if (NULL != fccharset)
+ {
+ if (debug_xft > 0)
+ {
+ stderr_out ("got a result from fc_charset_from_mule_charset, "
+ "it's %p", fccharset);
+ }
+ FcPatternAddCharSet(patternxft, FC_CHARSET, fccharset);
+ }
+ else
+ {
+ if (debug_xft > 0)
+ {
+ stderr_out ("Got NULL from fc_charset_from_mule_charset--does "
+ "this Mule charset have a Unicode mapping table at"
+ " all?");
+ }
+ }
+
/* #### Next four return FcBool, but what does the return mean? */
/* #### There's probably a way to do this with FcCharsets, but isn't
- the language approach better in the long run? */
+ the language approach better in the long run?
+
+ It's certainly better in the long run, but that would involve me
+ finishing the UCS-as-the-internal-coding code, and the
+ infrastructure for passing up language information from a coding
+ system. So, stick with the FcCharSet approach until that's in
+ place. -- aidan, 2005-01-17 */
+
/* #### can we regression test this, or does it break too early? */
if (debug_xft > 0)
stderr_out ("FcNameParse'ed name is %s\n",
@@ -1048,32 +1083,11 @@
if (debug_xft > 0)
stderr_out ("FcConfigSubstitute'ed name is %s\n",
FcNameUnparse (patternxft));
+
FcDefaultSubstitute (patternxft);
if (debug_xft > 0)
stderr_out ("FcDefaultSubstitute'ed name is %s\n",
FcNameUnparse (patternxft));
- if (EQ (charset, Fget_charset (intern ("katakana-jisx0201")))
- || EQ (charset, Fget_charset (intern ("japanese-jisx0208")))
- || EQ (charset, Fget_charset (intern ("japanese-jisx0212"))))
- {
- if (debug_xft > 0)
- stderr_out ("checking if %s handles Japanese\n", patternext);
- lang = "ja";
- }
- else if (EQ (charset, Fget_charset (intern ("ascii"))))
- {
- if (debug_xft > 0)
- stderr_out ("checking if %s handles English\n", patternext);
- lang = "en";
- }
- else
- {
- /* #### is this the right way to make a warning? */
- warn_when_safe_lispobj (intern ("xft"), Qwarning,
- list2 (build_string ("unknown charset"),
- charset));
- /* default to "en" */
- }
patternxft = FcFontMatch (fcc, patternxft, &fcresult);
/* #### stderr_out crashed in the next block; why?
Index: src/redisplay-x.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/redisplay-x.c,v
retrieving revision 1.39.2.2
diff -u -r1.39.2.2 redisplay-x.c
--- src/redisplay-x.c 2004/12/10 06:43:50 1.39.2.2
+++ src/redisplay-x.c 2005/01/17 23:13:26
@@ -172,7 +172,7 @@
MULE is not defined */
int runs_so_far = 0;
int i;
-#ifdef MULE
+#if defined(MULE) && !defined(USE_XFT)
struct ccl_program char_converter;
int need_ccl_conversion = 0;
#endif
@@ -209,13 +209,15 @@
runs_so_far++;
prev_charset = charset;
#ifdef MULE
+#ifndef USE_XFT
{
Lisp_Object ccl_prog = XCHARSET_CCL_PROGRAM (charset);
if ((!NILP (ccl_prog))
&& (setup_ccl_program (&char_converter, ccl_prog) >= 0))
need_ccl_conversion = 1;
}
-#endif
+#endif /* !USE_XFT */
+#endif /* MULE */
}
#ifndef USE_XFT
@@ -255,10 +257,33 @@
XftChar16 xftchar16 = 0xFFFD; /* unsigned short */
int unicode = ichar_to_unicode (ch);
if (unicode < 0)
- abort(); /* #### serious error, tables are corrupt */
+ {
+ /* abort(); */ /* #### serious error, tables are corrupt
+
+ Umm, Not necessarily, a charset exists without
+ a Unicode mapping table, that's not the end of
+ the world. */
+
+ unicode = 0xFFFD;
+ }
+#if 0
+ /* There's no need to special-case charsets that use CCL conversion
+ here. XFT gives us access to a _unified_ character set, so _there
+ is no difference_ between a Windows 1251 CYRILLIC CAPITAL LETTER
+ ES and an ISO 8859-5 CYRILLIC CAPITAL LETTER ES, because they
+ both map to the same code point in the UCS.
+
+ If there were any indication that the Mule charset CCL conversion
+ were used for some other purpose than something orthogonal to the
+ iso-8859-5 --> non-ISO-2022 conversion, there would be grounds
+ for reconsidering this. */
+
else if (need_ccl_conversion)
- /* #### maybe we should just ignore this and hope the font wins? */
- unicode = 0xFFFD; /* REPLACEMENT CHARACTER, can't represent */
+ {
+ /* #### maybe we should just ignore this and hope the font wins? */
+ unicode = 0xFFFD; /* REPLACEMENT CHARACTER, can't represent */
+ }
+#endif
else if (unicode > 65535)
unicode = 0xFFFD; /* REPLACEMENT CHARACTER, can't represent */
else
Index: src/unicode.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/unicode.c,v
retrieving revision 1.23
diff -u -r1.23 unicode.c
--- src/unicode.c 2004/11/04 23:06:58 1.23
+++ src/unicode.c 2005/01/17 23:13:33
@@ -2385,6 +2385,102 @@
return 0;
#endif
}
+#ifdef USE_XFT
+
+extern int debug_xft;
+
+/* Making the FcCharSet objects available to Lisp would just be mad. So,
+ this array isn't available to it. */
+
+FcCharSet *leading_byte_to_fc_charset[NUM_LEADING_BYTES];
+
+#define XFT_DEBUG_DUMP(...) do { \
+ if (debug_xft > 0) { stderr_out(__VA_ARGS__); }} while (0)
+#define XFT_ASSERT(ARG) assert(ARG)
+
+FcCharSet *
+fc_charset_from_mule_charset(Lisp_Object charset)
+{
+ FcCharSet *fc_charset;
+ FcBool fcadd_ret;
+
+ int cache_table_index, charset_dim, i, j,
+ **to_unicode_branch, *to_unicode_leaf;
+
+ void *to_unicode_table;
+
+ XFT_DEBUG_DUMP("mule Charset is %p, doing a fontconfig lookup\n",
+ (void *)charset);
+
+ if (NULL == (void *)charset)
+ {
+ XFT_DEBUG_DUMP("charset was null, returning null\n");
+ return NULL;
+ }
+
+ cache_table_index = XCHARSET_LEADING_BYTE(charset) - MIN_LEADING_BYTE;
+ charset_dim = XCHARSET_DIMENSION(charset);
+
+ if (NULL != leading_byte_to_fc_charset[cache_table_index])
+ {
+ XFT_DEBUG_DUMP("succeeded looking up charset, %p, id %d\n",
+ (void *)charset, cache_table_index + MIN_LEADING_BYTE);
+ /* We got a cache hit--cool, pass it up. */
+ return leading_byte_to_fc_charset[cache_table_index];
+ }
+
+ /* Pull the mapping to unicode from the character set. */
+ to_unicode_table = XCHARSET_TO_UNICODE_TABLE(charset);
+ if (NULL == to_unicode_table ||
+ (1 == charset_dim && to_unicode_blank_1 == (int *)to_unicode_table) ||
+ (2 == charset_dim && to_unicode_blank_2 == (int **)to_unicode_table))
+ {
+ XFT_DEBUG_DUMP("unicode table was null, or blank. returning null.");
+ return NULL;
+ }
+
+ fc_charset = FcCharSetCreate();
+ XFT_ASSERT(fc_charset);
+
+ if (1 == charset_dim)
+ {
+ to_unicode_leaf = to_unicode_table;
+ for (i = 0; i < 96; ++i)
+ {
+ if (-1 != to_unicode_leaf[i])
+ {
+ fcadd_ret = FcCharSetAddChar(fc_charset, to_unicode_leaf[i]);
+ XFT_ASSERT(fcadd_ret);
+ }
+ }
+ XFT_DEBUG_DUMP("1-dimensional charset, made FcCharSet, returning it");
+ return leading_byte_to_fc_charset[cache_table_index] = fc_charset;
+ }
+
+ XFT_ASSERT(2 == charset_dim);
+
+ to_unicode_branch = to_unicode_table;
+
+ for (j = 0; j < 96; ++j)
+ {
+ to_unicode_leaf = to_unicode_branch[j];
+ if (to_unicode_blank_1 != to_unicode_leaf)
+ {
+ for (i = 0; i < 96; ++i)
+ {
+ if (-1 != to_unicode_leaf[i])
+ {
+ fcadd_ret = FcCharSetAddChar(fc_charset, to_unicode_leaf[i]);
+ XFT_ASSERT(fcadd_ret);
+ }
+ }
+ }
+ }
+ XFT_DEBUG_DUMP("Two dimensional charset, made FcCharSet, returning it.");
+ return leading_byte_to_fc_charset[cache_table_index] = fc_charset;
+}
+
+#endif /* USE_XFT */
/************************************************************************/
--
“Ah come on now Ted, a Volkswagen with a mind of its own, driving all over
the place and going mad, if that’s not scary I don’t know what is.”