root/src/xfont.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xfont_get_pcm
  2. xfont_get_cache
  3. compare_font_names
  4. xfont_decode_coding_xlfd
  5. xfont_encode_coding_xlfd
  6. xfont_chars_supported
  7. xfont_supported_scripts
  8. xfont_list_pattern
  9. xfont_list
  10. xfont_match
  11. xfont_list_family
  12. xfont_open
  13. xfont_close
  14. xfont_prepare_face
  15. xfont_has_char
  16. xfont_encode_char
  17. xfont_text_extents
  18. xfont_draw
  19. xfont_check
  20. syms_of_xfont
  21. syms_of_xfont_for_pdumper

     1 /* xfont.c -- X core font driver.
     2    Copyright (C) 2006-2023 Free Software Foundation, Inc.
     3    Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
     4      National Institute of Advanced Industrial Science and Technology (AIST)
     5      Registration Number H13PRO009
     6 
     7 This file is part of GNU Emacs.
     8 
     9 GNU Emacs is free software: you can redistribute it and/or modify
    10 it under the terms of the GNU General Public License as published by
    11 the Free Software Foundation, either version 3 of the License, or (at
    12 your option) any later version.
    13 
    14 GNU Emacs is distributed in the hope that it will be useful,
    15 but WITHOUT ANY WARRANTY; without even the implied warranty of
    16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    17 GNU General Public License for more details.
    18 
    19 You should have received a copy of the GNU General Public License
    20 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    21 
    22 #include <config.h>
    23 #include <stdlib.h>
    24 #include <X11/Xlib.h>
    25 
    26 #include "lisp.h"
    27 #include "xterm.h"
    28 #include "frame.h"
    29 #include "blockinput.h"
    30 #include "character.h"
    31 #include "charset.h"
    32 #include "font.h"
    33 #include "pdumper.h"
    34 
    35 
    36 /* X core font driver.  */
    37 
    38 struct xfont_info
    39 {
    40   struct font font;
    41   Display *display;
    42   XFontStruct *xfont;
    43   unsigned x_display_id;
    44 };
    45 
    46 /* Prototypes of support functions.  */
    47 
    48 static XCharStruct *xfont_get_pcm (XFontStruct *, unsigned char2b);
    49 
    50 /* Get metrics of character CHAR2B in XFONT.  Value is null if CHAR2B
    51    is not contained in the font.  */
    52 
    53 static XCharStruct *
    54 xfont_get_pcm (XFontStruct *xfont, unsigned char2b)
    55 {
    56   /* The result metric information.  */
    57   XCharStruct *pcm = NULL;
    58   const unsigned char byte1 = char2b >> 8;
    59   const unsigned char byte2 = char2b & 0xFF;
    60 
    61   eassert (xfont);
    62 
    63   if (xfont->per_char != NULL)
    64     {
    65       if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
    66         {
    67           /* min_char_or_byte2 specifies the linear character index
    68              corresponding to the first element of the per_char array,
    69              max_char_or_byte2 is the index of the last character.  A
    70              character with non-zero byte1 is not in the font.
    71              A character with byte2 less than min_char_or_byte2 or
    72              greater max_char_or_byte2 is not in the font.  */
    73           if (byte1 == 0
    74               && byte2 >= xfont->min_char_or_byte2
    75               && byte2 <= xfont->max_char_or_byte2)
    76             pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
    77         }
    78       else
    79         {
    80           /* If either min_byte1 or max_byte1 are nonzero, both
    81              min_char_or_byte2 and max_char_or_byte2 are less than
    82              256, and the 2-byte character index values corresponding
    83              to the per_char array element N (counting from 0) are:
    84 
    85              byte1 = N/D + min_byte1
    86              byte2 = N\D + min_char_or_byte2
    87 
    88              where:
    89 
    90              D = max_char_or_byte2 - min_char_or_byte2 + 1
    91              / = integer division
    92              \ = integer modulus  */
    93           if (byte1 >= xfont->min_byte1
    94               && byte1 <= xfont->max_byte1
    95               && byte2 >= xfont->min_char_or_byte2
    96               && byte2 <= xfont->max_char_or_byte2)
    97             pcm = (xfont->per_char
    98                    + ((xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1)
    99                       * (byte1 - xfont->min_byte1))
   100                    + (byte2 - xfont->min_char_or_byte2));
   101         }
   102     }
   103   else
   104     {
   105       /* If the per_char pointer is null, all glyphs between the first
   106          and last character indexes inclusive have the same
   107          information, as given by both min_bounds and max_bounds.  */
   108       if (byte2 >= xfont->min_char_or_byte2
   109           && byte2 <= xfont->max_char_or_byte2)
   110         pcm = &xfont->max_bounds;
   111     }
   112 
   113   return ((pcm == NULL
   114            || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
   115           ? NULL : pcm);
   116 }
   117 
   118 Lisp_Object
   119 xfont_get_cache (struct frame *f)
   120 {
   121   Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
   122 
   123   return (dpyinfo->name_list_element);
   124 }
   125 
   126 static int
   127 compare_font_names (const void *name1, const void *name2)
   128 {
   129   char *const *n1 = name1;
   130   char *const *n2 = name2;
   131   return xstrcasecmp (*n1, *n2);
   132 }
   133 
   134 /* Decode XLFD as iso-8859-1 into OUTPUT, and return the byte length
   135    of the decoding result.  LEN is the byte length of XLFD, or -1 if
   136    XLFD is NULL terminated.  The caller must assure that OUTPUT is at
   137    least twice (plus 1) as large as XLFD.  */
   138 
   139 static ptrdiff_t
   140 xfont_decode_coding_xlfd (char *xlfd, int len, char *output)
   141 {
   142   char *p0 = xlfd, *p1 = output;
   143   int c;
   144 
   145   while (*p0)
   146     {
   147       c = *(unsigned char *) p0++;
   148       p1 += CHAR_STRING (c, (unsigned char *) p1);
   149       if (--len == 0)
   150         break;
   151     }
   152   *p1 = 0;
   153   return (p1 - output);
   154 }
   155 
   156 /* Encode XLFD from UTF-8 to iso-8859-1 destructively, and return the
   157    resulting byte length.  If XLFD contains unencodable character,
   158    return -1.  */
   159 
   160 static int
   161 xfont_encode_coding_xlfd (char *xlfd)
   162 {
   163   const unsigned char *p0 = (unsigned char *) xlfd;
   164   unsigned char *p1 = (unsigned char *) xlfd;
   165   int len = 0;
   166 
   167   while (*p0)
   168     {
   169       int c = string_char_advance (&p0);
   170 
   171       if (c >= 0x100)
   172         return -1;
   173       *p1++ = c;
   174       len++;
   175     }
   176   *p1 = 0;
   177   return len;
   178 }
   179 
   180 /* Check if CHARS (cons or vector) is supported by XFONT whose
   181    encoding charset is ENCODING (XFONT is NULL) or by a font whose
   182    registry corresponds to ENCODING and REPERTORY.
   183    Return true if supported.  */
   184 
   185 static bool
   186 xfont_chars_supported (Lisp_Object chars, XFontStruct *xfont,
   187                        struct charset *encoding, struct charset *repertory)
   188 {
   189   struct charset *charset = repertory ? repertory : encoding;
   190 
   191   if (CONSP (chars))
   192     {
   193       for (; CONSP (chars); chars = XCDR (chars))
   194         {
   195           int c = XFIXNUM (XCAR (chars));
   196           unsigned code = ENCODE_CHAR (charset, c);
   197 
   198           if (code == CHARSET_INVALID_CODE (charset))
   199             break;
   200           if (! xfont)
   201             continue;
   202           if (code >= 0x10000)
   203             break;
   204           if (! xfont_get_pcm (xfont, code))
   205             break;
   206         }
   207       return (NILP (chars));
   208     }
   209   else if (VECTORP (chars))
   210     {
   211       ptrdiff_t i;
   212 
   213       for (i = ASIZE (chars) - 1; i >= 0; i--)
   214         {
   215           int c = XFIXNUM (AREF (chars, i));
   216           unsigned code = ENCODE_CHAR (charset, c);
   217 
   218           if (code == CHARSET_INVALID_CODE (charset))
   219             continue;
   220           if (! xfont)
   221             break;
   222           if (code >= 0x10000)
   223             continue;
   224           if (xfont_get_pcm (xfont, code))
   225             break;
   226         }
   227       return (i >= 0);
   228     }
   229   return false;
   230 }
   231 
   232 /* A hash table recoding which font supports which scripts.  Each key
   233    is a vector of characteristic font properties FOUNDRY to WIDTH and
   234    ADDSTYLE, and each value is a list of script symbols.
   235 
   236    We assume that fonts that have the same value in the above
   237    properties supports the same set of characters on all displays.  */
   238 
   239 static Lisp_Object xfont_scripts_cache;
   240 
   241 /* Re-usable vector to store characteristic font properties.   */
   242 static Lisp_Object xfont_scratch_props;
   243 
   244 /* Return a list of scripts supported by the font of FONTNAME whose
   245    characteristic properties are in PROPS and whose encoding charset
   246    is ENCODING.  A caller must call BLOCK_INPUT in advance.  */
   247 
   248 static Lisp_Object
   249 xfont_supported_scripts (Display *display, char *fontname, Lisp_Object props,
   250                          struct charset *encoding)
   251 {
   252   Lisp_Object scripts;
   253 
   254   /* Two special cases to avoid opening rather big fonts.  */
   255   if (EQ (AREF (props, 2), Qja))
   256     return list2 (Qkana, Qhan);
   257   if (EQ (AREF (props, 2), Qko))
   258     return list1 (Qhangul);
   259   scripts = Fgethash (props, xfont_scripts_cache, Qt);
   260   if (EQ (scripts, Qt))
   261     {
   262       XFontStruct *xfont;
   263       Lisp_Object val;
   264 
   265       scripts = Qnil;
   266       xfont = XLoadQueryFont (display, fontname);
   267       if (xfont)
   268         {
   269           if (xfont->per_char)
   270             {
   271               for (val = Vscript_representative_chars; CONSP (val);
   272                    val = XCDR (val))
   273                 if (CONSP (XCAR (val)) && SYMBOLP (XCAR (XCAR (val))))
   274                   {
   275                     Lisp_Object script = XCAR (XCAR (val));
   276                     Lisp_Object chars = XCDR (XCAR (val));
   277 
   278                     if (xfont_chars_supported (chars, xfont, encoding, NULL))
   279                       scripts = Fcons (script, scripts);
   280                   }
   281             }
   282           XFreeFont (display, xfont);
   283         }
   284       if (EQ (AREF (props, 3), Qiso10646_1)
   285           && NILP (Fmemq (Qlatin, scripts)))
   286         scripts = Fcons (Qlatin, scripts);
   287       Fputhash (Fcopy_sequence (props), scripts, xfont_scripts_cache);
   288     }
   289   return scripts;
   290 }
   291 
   292 static Lisp_Object
   293 xfont_list_pattern (Display *display, const char *pattern,
   294                     Lisp_Object registry, Lisp_Object script)
   295 {
   296   Lisp_Object list = Qnil;
   297   Lisp_Object chars = Qnil;
   298   struct charset *encoding = NULL, *repertory = NULL;
   299   int i, limit, num_fonts;
   300   char **names;
   301   /* Large enough to decode the longest XLFD (255 bytes). */
   302   char buf[512];
   303 
   304   if (! NILP (registry)
   305       && font_registry_charsets (registry, &encoding, &repertory) < 0)
   306     /* Unknown REGISTRY, not supported.  */
   307     return Qnil;
   308   if (! NILP (script))
   309     {
   310       chars = assq_no_quit (script, Vscript_representative_chars);
   311       if (NILP (chars))
   312         /* We can't tell whether or not a font supports SCRIPT.  */
   313         return Qnil;
   314       chars = XCDR (chars);
   315       if (repertory)
   316         {
   317           if (! xfont_chars_supported (chars, NULL, encoding, repertory))
   318             return Qnil;
   319           script = Qnil;
   320         }
   321     }
   322 
   323   block_input ();
   324   x_catch_errors (display);
   325 
   326   for (limit = 512; ; limit *= 2)
   327     {
   328       names = XListFonts (display, pattern, limit, &num_fonts);
   329       if (x_had_errors_p (display))
   330         {
   331           /* This error is perhaps due to insufficient memory on X
   332              server.  Let's just ignore it.  */
   333           x_clear_errors (display);
   334           num_fonts = 0;
   335           break;
   336         }
   337       if (num_fonts < limit)
   338         break;
   339       XFreeFontNames (names);
   340     }
   341 
   342   if (num_fonts > 0)
   343     {
   344       char **indices = alloca (sizeof (char *) * num_fonts);
   345       Lisp_Object *props = XVECTOR (xfont_scratch_props)->contents;
   346       Lisp_Object scripts = Qnil, entity = Qnil;
   347 
   348       for (i = 0; i < ASIZE (xfont_scratch_props); i++)
   349         ASET (xfont_scratch_props, i, Qnil);
   350       for (i = 0; i < num_fonts; i++)
   351         indices[i] = names[i];
   352       qsort (indices, num_fonts, sizeof (char *), compare_font_names);
   353 
   354       /* Take one or two passes over the font list.  Do the second
   355          pass only if we really need it, i.e., only if the first pass
   356          found no fonts and skipped some scalable fonts.  */
   357       bool skipped_some_scalable_fonts = false;
   358       for (int i_pass = 0;
   359            (i_pass == 0
   360             || (i_pass == 1 && NILP (list) && skipped_some_scalable_fonts));
   361            i_pass++)
   362         for (i = 0; i < num_fonts; i++)
   363           {
   364             ptrdiff_t len;
   365 
   366             if (i > 0 && xstrcasecmp (indices[i - 1], indices[i]) == 0)
   367               continue;
   368             if (NILP (entity))
   369               entity = font_make_entity ();
   370             len = xfont_decode_coding_xlfd (indices[i], -1, buf);
   371             if (font_parse_xlfd (buf, len, entity) < 0)
   372               continue;
   373             ASET (entity, FONT_TYPE_INDEX, Qx);
   374             /* Avoid auto-scaled fonts.  */
   375             if (FIXNUMP (AREF (entity, FONT_DPI_INDEX))
   376                 && FIXNUMP (AREF (entity, FONT_AVGWIDTH_INDEX))
   377                 && XFIXNUM (AREF (entity, FONT_DPI_INDEX)) != 0
   378                 && XFIXNUM (AREF (entity, FONT_AVGWIDTH_INDEX)) == 0)
   379               continue;
   380             /* Avoid not-allowed scalable fonts.  */
   381             if (NILP (Vscalable_fonts_allowed))
   382               {
   383                 int size = 0;
   384 
   385                 if (FIXNUMP (AREF (entity, FONT_SIZE_INDEX)))
   386                   size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX));
   387                 else if (FLOATP (AREF (entity, FONT_SIZE_INDEX)))
   388                   size = XFLOAT_DATA (AREF (entity, FONT_SIZE_INDEX));
   389                 if (size == 0 && i_pass == 0)
   390                   {
   391                     skipped_some_scalable_fonts = true;
   392                     continue;
   393                   }
   394               }
   395             else if (CONSP (Vscalable_fonts_allowed))
   396               {
   397                 Lisp_Object tail;
   398 
   399                 for (tail = Vscalable_fonts_allowed; CONSP (tail);
   400                      tail = XCDR (tail))
   401                   {
   402                     Lisp_Object elt = XCAR (tail);
   403                     if (STRINGP (elt)
   404                         && (fast_c_string_match_ignore_case (elt, indices[i],
   405                                                              len)
   406                             >= 0))
   407                       break;
   408                   }
   409                 if (! CONSP (tail))
   410                   continue;
   411               }
   412 
   413             /* Avoid fonts of invalid registry.  */
   414             if (NILP (AREF (entity, FONT_REGISTRY_INDEX)))
   415               continue;
   416 
   417             /* Update encoding and repertory if necessary.  */
   418             if (! EQ (registry, AREF (entity, FONT_REGISTRY_INDEX)))
   419               {
   420                 registry = AREF (entity, FONT_REGISTRY_INDEX);
   421                 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
   422                   encoding = NULL;
   423               }
   424             if (! encoding)
   425               /* Unknown REGISTRY, not supported.  */
   426               continue;
   427             if (repertory)
   428               {
   429                 if (NILP (script)
   430                     || xfont_chars_supported (chars, NULL, encoding, repertory))
   431                   list = Fcons (entity, list), entity = Qnil;
   432                 continue;
   433               }
   434             if (memcmp (props, aref_addr (entity, FONT_FOUNDRY_INDEX),
   435                         word_size * 7)
   436                 || ! EQ (AREF (entity, FONT_SPACING_INDEX), props[7]))
   437               {
   438                 vcopy (xfont_scratch_props, 0,
   439                        aref_addr (entity, FONT_FOUNDRY_INDEX), 7);
   440                 ASET (xfont_scratch_props, 7, AREF (entity, FONT_SPACING_INDEX));
   441                 scripts = xfont_supported_scripts (display, indices[i],
   442                                                    xfont_scratch_props,
   443                                                    encoding);
   444               }
   445             if (NILP (script)
   446                 || ! NILP (Fmemq (script, scripts)))
   447               list = Fcons (entity, list), entity = Qnil;
   448           }
   449       XFreeFontNames (names);
   450     }
   451 
   452   x_uncatch_errors ();
   453   unblock_input ();
   454 
   455   FONT_ADD_LOG ("xfont-list", build_string (pattern), list);
   456   return list;
   457 }
   458 
   459 static Lisp_Object
   460 xfont_list (struct frame *f, Lisp_Object spec)
   461 {
   462   Display *display = FRAME_DISPLAY_INFO (f)->display;
   463   Lisp_Object registry, list, val, extra, script;
   464   int len;
   465   /* Large enough to contain the longest XLFD (255 bytes) in UTF-8.  */
   466   char name[512];
   467 
   468   extra = AREF (spec, FONT_EXTRA_INDEX);
   469   if (CONSP (extra))
   470     {
   471       val = assq_no_quit (QCotf, extra);
   472       if (! NILP (val))
   473         return Qnil;
   474       val = assq_no_quit (QClang, extra);
   475       if (! NILP (val))
   476         return Qnil;
   477     }
   478 
   479   registry = AREF (spec, FONT_REGISTRY_INDEX);
   480   len = font_unparse_xlfd (spec, 0, name, 512);
   481   if (len < 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
   482     return Qnil;
   483 
   484   val = assq_no_quit (QCscript, extra);
   485   script = CDR (val);
   486   list = xfont_list_pattern (display, name, registry, script);
   487   if (NILP (list) && NILP (registry))
   488     {
   489       /* Try iso10646-1 */
   490       char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
   491 
   492       if (r - name + 10 < 256)  /* 10 == strlen (iso10646-1) */
   493         {
   494           strcpy (r, "iso10646-1");
   495           list = xfont_list_pattern (display, name, Qiso10646_1, script);
   496         }
   497     }
   498   if (NILP (list) && ! NILP (registry))
   499     {
   500       /* Try alternate registries.  */
   501       Lisp_Object alter;
   502 
   503       if ((alter = Fassoc (SYMBOL_NAME (registry),
   504                            Vface_alternative_font_registry_alist,
   505                            Qnil),
   506            CONSP (alter)))
   507         {
   508           /* Pointer to REGISTRY-ENCODING field.  */
   509           char *r = name + len - SBYTES (SYMBOL_NAME (registry));
   510 
   511           for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
   512             if (STRINGP (XCAR (alter))
   513                 && ((r - name) + SBYTES (XCAR (alter))) < 256)
   514               {
   515                 lispstpcpy (r, XCAR (alter));
   516                 list = xfont_list_pattern (display, name, registry, script);
   517                 if (! NILP (list))
   518                   break;
   519               }
   520         }
   521     }
   522   if (NILP (list))
   523     {
   524       /* Try alias.  */
   525       val = assq_no_quit (QCname, AREF (spec, FONT_EXTRA_INDEX));
   526       if (CONSP (val) && STRINGP (XCDR (val)) && SBYTES (XCDR (val)) < 512)
   527         {
   528           memcpy (name, SDATA (XCDR (val)), SBYTES (XCDR (val)) + 1);
   529           if (xfont_encode_coding_xlfd (name) < 0)
   530             return Qnil;
   531           list = xfont_list_pattern (display, name, registry, script);
   532         }
   533     }
   534 
   535   return list;
   536 }
   537 
   538 static Lisp_Object
   539 xfont_match (struct frame *f, Lisp_Object spec)
   540 {
   541   Display *display = FRAME_DISPLAY_INFO (f)->display;
   542   Lisp_Object extra, val, entity;
   543   char name[512];
   544   XFontStruct *xfont;
   545   unsigned long value;
   546 
   547   extra = AREF (spec, FONT_EXTRA_INDEX);
   548   val = assq_no_quit (QCname, extra);
   549   if (! CONSP (val) || ! STRINGP (XCDR (val)))
   550     {
   551       if (font_unparse_xlfd (spec, 0, name, 512) < 0)
   552         return Qnil;
   553     }
   554   else if (SBYTES (XCDR (val)) < 512)
   555     memcpy (name, SDATA (XCDR (val)), SBYTES (XCDR (val)) + 1);
   556   else
   557     return Qnil;
   558   if (xfont_encode_coding_xlfd (name) < 0)
   559     return Qnil;
   560 
   561   block_input ();
   562   entity = Qnil;
   563   xfont = XLoadQueryFont (display, name);
   564   if (xfont)
   565     {
   566       if (XGetFontProperty (xfont, XA_FONT, &value))
   567         {
   568           char *s = XGetAtomName (display, (Atom) value);
   569 
   570           /* If DXPC (a Differential X Protocol Compressor)
   571              Ver.3.7 is running, XGetAtomName will return null
   572              string.  We must avoid such a name.  */
   573           if (*s)
   574             {
   575               ptrdiff_t len;
   576               entity = font_make_entity ();
   577               ASET (entity, FONT_TYPE_INDEX, Qx);
   578               len = xfont_decode_coding_xlfd (s, -1, name);
   579               if (font_parse_xlfd (name, len, entity) < 0)
   580                 entity = Qnil;
   581             }
   582           XFree (s);
   583         }
   584       XFreeFont (display, xfont);
   585     }
   586   unblock_input ();
   587 
   588   FONT_ADD_LOG ("xfont-match", spec, entity);
   589   return entity;
   590 }
   591 
   592 static Lisp_Object
   593 xfont_list_family (struct frame *f)
   594 {
   595   Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
   596   char **names;
   597   int num_fonts, i;
   598   Lisp_Object list;
   599   char const *last_family;
   600 #if defined GCC_LINT || defined lint
   601   last_family = "";
   602 #endif
   603   int last_len;
   604 
   605   block_input ();
   606   x_catch_errors (dpyinfo->display);
   607   names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
   608                       0x8000, &num_fonts);
   609   if (x_had_errors_p (dpyinfo->display))
   610     {
   611       /* This error is perhaps due to insufficient memory on X server.
   612          Let's just ignore it.  */
   613       x_clear_errors (dpyinfo->display);
   614       num_fonts = 0;
   615     }
   616 
   617   list = Qnil;
   618   for (i = 0, last_len = 0; i < num_fonts; i++)
   619     {
   620       char *p0 = names[i], *p1, buf[512];
   621       Lisp_Object family;
   622       int decoded_len;
   623 
   624       p0++;                     /* skip the leading '-' */
   625       while (*p0 && *p0 != '-') p0++; /* skip foundry */
   626       if (! *p0)
   627         continue;
   628       p1 = ++p0;
   629       while (*p1 && *p1 != '-') p1++; /* find the end of family */
   630       if (! *p1 || p1 == p0)
   631         continue;
   632       if (last_len == p1 - p0
   633           && memcmp (last_family, p0, last_len) == 0)
   634         continue;
   635       last_len = p1 - p0;
   636       last_family = p0;
   637 
   638       decoded_len = xfont_decode_coding_xlfd (p0, last_len, buf);
   639       family = font_intern_prop (p0, decoded_len, 1);
   640       if (NILP (assq_no_quit (family, list)))
   641         list = Fcons (family, list);
   642     }
   643 
   644   XFreeFontNames (names);
   645   x_uncatch_errors ();
   646   unblock_input ();
   647 
   648   return list;
   649 }
   650 
   651 static Lisp_Object
   652 xfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
   653 {
   654   Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
   655   Display *display = dpyinfo->display;
   656   char name[512];
   657   int len;
   658   unsigned long value;
   659   Lisp_Object registry;
   660   struct charset *encoding, *repertory;
   661   Lisp_Object font_object, fullname;
   662   struct font *font;
   663   XFontStruct *xfont;
   664 
   665   /* At first, check if we know how to encode characters for this
   666      font.  */
   667   registry = AREF (entity, FONT_REGISTRY_INDEX);
   668   if (font_registry_charsets (registry, &encoding, &repertory) < 0)
   669     {
   670       FONT_ADD_LOG ("  x:unknown registry", registry, Qnil);
   671       return Qnil;
   672     }
   673 
   674   if (XFIXNUM (AREF (entity, FONT_SIZE_INDEX)) != 0)
   675     pixel_size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX));
   676   else if (pixel_size == 0)
   677     {
   678       if (FRAME_FONT (f))
   679         pixel_size = FRAME_FONT (f)->pixel_size;
   680       else
   681         pixel_size = 14;
   682     }
   683   len = font_unparse_xlfd (entity, pixel_size, name, 512);
   684   if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
   685     {
   686       FONT_ADD_LOG ("  x:unparse failed", entity, Qnil);
   687       return Qnil;
   688     }
   689 
   690   block_input ();
   691   x_catch_errors (display);
   692   xfont = XLoadQueryFont (display, name);
   693   if (x_had_errors_p (display))
   694     {
   695       /* This error is perhaps due to insufficient memory on X server.
   696          Let's just ignore it.  */
   697       x_clear_errors (display);
   698       xfont = NULL;
   699     }
   700   else if (! xfont)
   701     {
   702       /* Some version of X lists:
   703            -misc-fixed-medium-r-normal--20-*-75-75-c-100-iso8859-1
   704            -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
   705          but can open only:
   706            -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
   707          and
   708            -misc-fixed-medium-r-normal--20-*-*-*-c-100-iso8859-1
   709          So, we try again with wildcards in RESX and RESY.  */
   710       Lisp_Object temp;
   711 
   712       temp = copy_font_spec (entity);
   713       ASET (temp, FONT_DPI_INDEX, Qnil);
   714       len = font_unparse_xlfd (temp, pixel_size, name, 512);
   715       if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
   716         {
   717           FONT_ADD_LOG ("  x:unparse failed", temp, Qnil);
   718           return Qnil;
   719         }
   720       xfont = XLoadQueryFont (display, name);
   721       if (x_had_errors_p (display))
   722         {
   723           /* This error is perhaps due to insufficient memory on X server.
   724              Let's just ignore it.  */
   725           x_clear_errors (display);
   726           xfont = NULL;
   727         }
   728     }
   729   fullname = Qnil;
   730   /* Try to get the full name of FONT.  */
   731   if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
   732     {
   733       char *p0, *p;
   734       int dashes = 0;
   735 
   736       p0 = p = XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
   737       /* Count the number of dashes in the "full name".
   738          If it is too few, this isn't really the font's full name,
   739          so don't use it.
   740          In X11R4, the fonts did not come with their canonical names
   741          stored in them.  */
   742       while (*p)
   743         {
   744           if (*p == '-')
   745             dashes++;
   746           p++;
   747         }
   748 
   749       if (dashes >= 13)
   750         {
   751           len = xfont_decode_coding_xlfd (p0, -1, name);
   752           fullname = Fdowncase (make_string (name, len));
   753         }
   754       XFree (p0);
   755     }
   756   x_uncatch_errors ();
   757   unblock_input ();
   758 
   759   if (! xfont)
   760     {
   761       FONT_ADD_LOG ("  x:open failed", build_string (name), Qnil);
   762       return Qnil;
   763     }
   764 
   765   font_object = font_make_object (VECSIZE (struct xfont_info),
   766                                   entity, pixel_size);
   767   ASET (font_object, FONT_TYPE_INDEX, Qx);
   768   if (STRINGP (fullname))
   769     {
   770       font_parse_xlfd (SSDATA (fullname), SBYTES (fullname), font_object);
   771       ASET (font_object, FONT_NAME_INDEX, fullname);
   772     }
   773   else
   774     {
   775       char buf[512];
   776 
   777       len = xfont_decode_coding_xlfd (name, -1, buf);
   778       ASET (font_object, FONT_NAME_INDEX, make_string (buf, len));
   779     }
   780   ASET (font_object, FONT_FULLNAME_INDEX, fullname);
   781   font = XFONT_OBJECT (font_object);
   782   ((struct xfont_info *) font)->xfont = xfont;
   783   ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
   784   ((struct xfont_info *) font)->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
   785   font->pixel_size = pixel_size;
   786   font->driver = &xfont_driver;
   787   font->encoding_charset = encoding->id;
   788   font->repertory_charset = repertory ? repertory->id : -1;
   789   font->ascent = xfont->ascent;
   790   font->descent = xfont->descent;
   791   font->height = font->ascent + font->descent;
   792   font->min_width = xfont->min_bounds.width;
   793   font->max_width = xfont->max_bounds.width;
   794   if (xfont->min_bounds.width == xfont->max_bounds.width)
   795     {
   796       /* Fixed width font.  */
   797       font->average_width = font->space_width = xfont->min_bounds.width;
   798     }
   799   else
   800     {
   801       XCharStruct *pcm;
   802       Lisp_Object val;
   803 
   804       pcm = xfont_get_pcm (xfont, 0x20);
   805       if (pcm)
   806         font->space_width = pcm->width;
   807       else
   808         font->space_width = 0;
   809 
   810       val = Ffont_get (font_object, QCavgwidth);
   811       if (FIXNUMP (val))
   812         font->average_width = XFIXNUM (val) / 10;
   813       if (font->average_width < 0)
   814         font->average_width = - font->average_width;
   815       else
   816         {
   817           if (font->average_width == 0
   818               && encoding->ascii_compatible_p)
   819             {
   820               int width = font->space_width, n = pcm != NULL;
   821 
   822               for (unsigned char2b = 33; char2b <= 126; ++char2b)
   823                 if ((pcm = xfont_get_pcm (xfont, char2b)) != NULL)
   824                   width += pcm->width, n++;
   825               if (n > 0)
   826                 font->average_width = width / n;
   827             }
   828           if (font->average_width == 0)
   829             /* No easy way other than this to get a reasonable
   830                average_width.  */
   831             font->average_width
   832               = (xfont->min_bounds.width + xfont->max_bounds.width) / 2;
   833         }
   834     }
   835 
   836   block_input ();
   837   font->underline_thickness
   838     = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
   839        ? (long) value : 0);
   840   font->underline_position
   841     = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
   842        ? (long) value : -1);
   843   font->baseline_offset
   844     = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
   845        ? (long) value : 0);
   846   font->relative_compose
   847     = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
   848        ? (long) value : 0);
   849   font->default_ascent
   850     = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
   851        ? (long) value : 0);
   852   unblock_input ();
   853 
   854   if (NILP (fullname))
   855     fullname = AREF (font_object, FONT_NAME_INDEX);
   856   font->vertical_centering
   857     = (STRINGP (Vvertical_centering_font_regexp)
   858        && (fast_string_match_ignore_case
   859            (Vvertical_centering_font_regexp, fullname) >= 0));
   860 
   861   return font_object;
   862 }
   863 
   864 static void
   865 xfont_close (struct font *font)
   866 {
   867   struct x_display_info *xdi;
   868   struct xfont_info *xfi = (struct xfont_info *) font;
   869 
   870   /* This function may be called from GC when X connection is gone
   871      (Bug#16093), and an attempt to free font resources on invalid
   872      display may lead to X protocol errors or segfaults.  Moreover,
   873      the memory referenced by 'Display *' pointer may be reused for
   874      the logically different X connection after the previous display
   875      connection was closed.  That's why we also check whether font's
   876      ID matches the one recorded in x_display_info for this display.
   877      See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=16069.  */
   878   if (xfi->xfont
   879       && ((xdi = x_display_info_for_display (xfi->display))
   880           && xfi->x_display_id == xdi->x_id))
   881     {
   882       block_input ();
   883       XFreeFont (xfi->display, xfi->xfont);
   884       unblock_input ();
   885       xfi->xfont = NULL;
   886     }
   887 }
   888 
   889 static void
   890 xfont_prepare_face (struct frame *f, struct face *face)
   891 {
   892   block_input ();
   893   XSetFont (FRAME_X_DISPLAY (f), face->gc,
   894             ((struct xfont_info *) face->font)->xfont->fid);
   895   unblock_input ();
   896 }
   897 
   898 static int
   899 xfont_has_char (Lisp_Object font, int c)
   900 {
   901   Lisp_Object registry = AREF (font, FONT_REGISTRY_INDEX);
   902   struct charset *encoding;
   903   struct charset *repertory = NULL;
   904 
   905   if (EQ (registry, Qiso10646_1))
   906     {
   907       encoding = CHARSET_FROM_ID (charset_unicode);
   908       /* We use a font of `ja' and `ko' adstyle only for a character
   909          in JISX0208 and KSC5601 charsets respectively.  */
   910       if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
   911           && charset_jisx0208 >= 0)
   912         repertory = CHARSET_FROM_ID (charset_jisx0208);
   913       else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
   914                && charset_ksc5601 >= 0)
   915         repertory = CHARSET_FROM_ID (charset_ksc5601);
   916     }
   917   else if (font_registry_charsets (registry, &encoding, &repertory) < 0)
   918     /* Unknown REGISTRY, not usable.  */
   919     return 0;
   920   if (ASCII_CHAR_P (c) && encoding->ascii_compatible_p)
   921     return 1;
   922   if (! repertory)
   923     return -1;
   924   return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
   925 }
   926 
   927 static unsigned
   928 xfont_encode_char (struct font *font, int c)
   929 {
   930   XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
   931   struct charset *charset;
   932   unsigned code;
   933 
   934   charset = CHARSET_FROM_ID (font->encoding_charset);
   935   code = ENCODE_CHAR (charset, c);
   936   if (code == CHARSET_INVALID_CODE (charset))
   937     return FONT_INVALID_CODE;
   938   if (font->repertory_charset >= 0)
   939     {
   940       charset = CHARSET_FROM_ID (font->repertory_charset);
   941       return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
   942               ? code : FONT_INVALID_CODE);
   943     }
   944   return (xfont_get_pcm (xfont, code) ? code : FONT_INVALID_CODE);
   945 }
   946 
   947 static void
   948 xfont_text_extents (struct font *font, const unsigned int *code,
   949                     int nglyphs, struct font_metrics *metrics)
   950 {
   951   XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
   952   int i, width = 0;
   953   bool first;
   954 
   955   for (i = 0, first = true; i < nglyphs; i++)
   956     {
   957       static XCharStruct *pcm;
   958 
   959       if (code[i] >= 0x10000)
   960         continue;
   961       pcm = xfont_get_pcm (xfont, code[i]);
   962       if (! pcm)
   963         continue;
   964       if (first)
   965         {
   966           metrics->lbearing = pcm->lbearing;
   967           metrics->rbearing = pcm->rbearing;
   968           metrics->ascent = pcm->ascent;
   969           metrics->descent = pcm->descent;
   970           first = false;
   971         }
   972       else
   973         {
   974           if (metrics->lbearing > width + pcm->lbearing)
   975             metrics->lbearing = width + pcm->lbearing;
   976           if (metrics->rbearing < width + pcm->rbearing)
   977             metrics->rbearing = width + pcm->rbearing;
   978           if (metrics->ascent < pcm->ascent)
   979             metrics->ascent = pcm->ascent;
   980           if (metrics->descent < pcm->descent)
   981             metrics->descent = pcm->descent;
   982         }
   983       width += pcm->width;
   984     }
   985 
   986   metrics->width = width;
   987 }
   988 
   989 static int
   990 xfont_draw (struct glyph_string *s, int from, int to, int x, int y,
   991             bool with_background)
   992 {
   993   XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
   994   Display *display = FRAME_X_DISPLAY (s->f);
   995   int len = to - from;
   996   GC gc = s->gc;
   997   int i;
   998 
   999   if (s->gc != s->face->gc)
  1000     {
  1001       block_input ();
  1002       XSetFont (display, gc, xfont->fid);
  1003       unblock_input ();
  1004     }
  1005 
  1006 #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
  1007   if (with_background
  1008       && FRAME_DISPLAY_INFO (s->f)->alpha_bits
  1009       && FRAME_CHECK_XR_VERSION (s->f, 0, 2))
  1010     {
  1011       x_xr_ensure_picture (s->f);
  1012 
  1013       if (FRAME_X_PICTURE (s->f) != None)
  1014         {
  1015           XRenderColor xc;
  1016           int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
  1017 
  1018           x_xr_apply_ext_clip (s->f, gc);
  1019           x_xrender_color_from_gc_background (s->f, gc, &xc,
  1020                                               s->hl != DRAW_CURSOR);
  1021           XRenderFillRectangle (FRAME_X_DISPLAY (s->f),
  1022                                 PictOpSrc, FRAME_X_PICTURE (s->f),
  1023                                 &xc, x, y - ascent, s->width, height);
  1024           x_xr_reset_ext_clip (s->f);
  1025           x_mark_frame_dirty (s->f);
  1026 
  1027           with_background = false;
  1028         }
  1029     }
  1030 #endif
  1031 
  1032   if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
  1033     {
  1034       USE_SAFE_ALLOCA;
  1035       char *str = SAFE_ALLOCA (len);
  1036       for (i = 0; i < len ; i++)
  1037         str[i] = s->char2b[from + i] & 0xFF;
  1038       block_input ();
  1039       if (with_background)
  1040         {
  1041           if (s->padding_p)
  1042             for (i = 0; i < len; i++)
  1043               XDrawImageString (display, FRAME_X_DRAWABLE (s->f),
  1044                                 gc, x + i, y, str + i, 1);
  1045           else
  1046             XDrawImageString (display, FRAME_X_DRAWABLE (s->f),
  1047                               gc, x, y, str, len);
  1048         }
  1049       else
  1050         {
  1051           if (s->padding_p)
  1052             for (i = 0; i < len; i++)
  1053               XDrawString (display, FRAME_X_DRAWABLE (s->f),
  1054                            gc, x + i, y, str + i, 1);
  1055           else
  1056             XDrawString (display, FRAME_X_DRAWABLE (s->f),
  1057                          gc, x, y, str, len);
  1058         }
  1059       unblock_input ();
  1060       SAFE_FREE ();
  1061       return s->nchars;
  1062     }
  1063 
  1064   block_input ();
  1065   if (with_background)
  1066     {
  1067       if (s->padding_p)
  1068         for (i = 0; i < len; i++)
  1069           {
  1070             const unsigned code = s->char2b[from + i];
  1071             const XChar2b char2b = { .byte1 = code >> 8,
  1072                                      .byte2 = code & 0xFF };
  1073             XDrawImageString16 (display, FRAME_X_DRAWABLE (s->f),
  1074                                 gc, x + i, y, &char2b, 1);
  1075           }
  1076       else
  1077         {
  1078           USE_SAFE_ALLOCA;
  1079           const unsigned *code = s->char2b + from;
  1080           XChar2b *char2b;
  1081           SAFE_NALLOCA (char2b, 1, len);
  1082           for (int i = 0; i < len; ++i)
  1083             char2b[i] = (XChar2b) { .byte1 = code[i] >> 8,
  1084                                     .byte2 = code[i] & 0xFF };
  1085           XDrawImageString16 (display, FRAME_X_DRAWABLE (s->f),
  1086                               gc, x, y, char2b, len);
  1087           SAFE_FREE ();
  1088         }
  1089     }
  1090   else
  1091     {
  1092       if (s->padding_p)
  1093         for (i = 0; i < len; i++)
  1094           {
  1095             const unsigned code = s->char2b[from + i];
  1096             const XChar2b char2b = { .byte1 = code >> 8,
  1097                                      .byte2 = code & 0xFF };
  1098             XDrawString16 (display, FRAME_X_DRAWABLE (s->f),
  1099                            gc, x + i, y, &char2b, 1);
  1100           }
  1101       else
  1102         {
  1103           USE_SAFE_ALLOCA;
  1104           const unsigned *code = s->char2b + from;
  1105           XChar2b *char2b;
  1106           SAFE_NALLOCA (char2b, 1, len);
  1107           for (int i = 0; i < len; ++i)
  1108             char2b[i] = (XChar2b) { .byte1 = code[i] >> 8,
  1109                                     .byte2 = code[i] & 0xFF };
  1110           XDrawString16 (display, FRAME_X_DRAWABLE (s->f),
  1111                          gc, x, y, char2b, len);
  1112           SAFE_FREE ();
  1113         }
  1114     }
  1115   unblock_input ();
  1116 
  1117   return len;
  1118 }
  1119 
  1120 static int
  1121 xfont_check (struct frame *f, struct font *font)
  1122 {
  1123   struct xfont_info *xfont = (struct xfont_info *) font;
  1124 
  1125   return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
  1126 }
  1127 
  1128 
  1129 static void syms_of_xfont_for_pdumper (void);
  1130 
  1131 struct font_driver const xfont_driver =
  1132   {
  1133     .type = LISPSYM_INITIALLY (Qx),
  1134     .get_cache = xfont_get_cache,
  1135     .list = xfont_list,
  1136     .match = xfont_match,
  1137     .list_family = xfont_list_family,
  1138     .open_font = xfont_open,
  1139     .close_font = xfont_close,
  1140     .prepare_face = xfont_prepare_face,
  1141     .has_char = xfont_has_char,
  1142     .encode_char = xfont_encode_char,
  1143     .text_extents = xfont_text_extents,
  1144     .draw = xfont_draw,
  1145     .check = xfont_check,
  1146   };
  1147 
  1148 void
  1149 syms_of_xfont (void)
  1150 {
  1151   staticpro (&xfont_scripts_cache);
  1152   xfont_scripts_cache = CALLN (Fmake_hash_table, QCtest, Qequal);
  1153   staticpro (&xfont_scratch_props);
  1154   xfont_scratch_props = make_nil_vector (8);
  1155   pdumper_do_now_and_after_load (syms_of_xfont_for_pdumper);
  1156 
  1157   DEFSYM (Qkana, "kana");
  1158   DEFSYM (Qhan, "han");
  1159   DEFSYM (Qhangul, "hangul");
  1160 }
  1161 
  1162 static void
  1163 syms_of_xfont_for_pdumper (void)
  1164 {
  1165   register_font_driver (&xfont_driver, NULL);
  1166 }

/* [<][>][^][v][top][bottom][index][help] */