root/src/haikufont.c

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

DEFINITIONS

This source file includes following definitions.
  1. haikufont_apply_registry
  2. haikufont_get_fallback_entity
  3. haikufont_get_cache
  4. haikufont_weight_to_lisp
  5. haikufont_lisp_to_weight
  6. haikufont_slant_to_lisp
  7. haikufont_lisp_to_slant
  8. haikufont_width_to_lisp
  9. haikufont_lisp_to_width
  10. haikufont_maybe_handle_special_family
  11. haikufont_pattern_to_entity
  12. haikufont_pattern_from_object
  13. haikufont_spec_or_entity_to_pattern
  14. haikufont_done_with_query_pattern
  15. haikufont_match
  16. haikufont_list
  17. haiku_bulk_encode
  18. haikufont_encode_char
  19. haikufont_open
  20. haikufont_close
  21. haikufont_prepare_face
  22. haikufont_glyph_extents
  23. haikufont_text_extents
  24. haikufont_shape
  25. haikufont_draw
  26. haikufont_list_family
  27. haikufont_filter_properties
  28. haikufont_should_quit_popup
  29. DEFUN
  30. DEFUN
  31. haiku_handle_font_change_event
  32. syms_of_haikufont_for_pdumper
  33. syms_of_haikufont

     1 /* Font support for Haiku windowing
     2 
     3 Copyright (C) 2021-2023 Free Software Foundation, Inc.
     4 
     5 This file is part of GNU Emacs.
     6 
     7 GNU Emacs is free software: you can redistribute it and/or modify
     8 it under the terms of the GNU General Public License as published by
     9 the Free Software Foundation, either version 3 of the License, or (at
    10 your option) any later version.
    11 
    12 GNU Emacs is distributed in the hope that it will be useful,
    13 but WITHOUT ANY WARRANTY; without even the implied warranty of
    14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15 GNU General Public License for more details.
    16 
    17 You should have received a copy of the GNU General Public License
    18 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    19 
    20 #include <config.h>
    21 
    22 #include "lisp.h"
    23 #include "dispextern.h"
    24 #include "composite.h"
    25 #include "blockinput.h"
    26 #include "charset.h"
    27 #include "frame.h"
    28 #include "window.h"
    29 #include "fontset.h"
    30 #include "haikuterm.h"
    31 #include "character.h"
    32 #include "coding.h"
    33 #include "font.h"
    34 #include "termchar.h"
    35 #include "pdumper.h"
    36 #include "haiku_support.h"
    37 
    38 #include <math.h>
    39 #include <stdlib.h>
    40 
    41 static Lisp_Object font_cache;
    42 
    43 #define METRICS_NCOLS_PER_ROW   (128)
    44 
    45 enum metrics_status
    46   {
    47     METRICS_INVALID = -1,    /* metrics entry is invalid */
    48   };
    49 
    50 #define METRICS_STATUS(metrics) ((metrics)->ascent + (metrics)->descent)
    51 #define METRICS_SET_STATUS(metrics, status) \
    52   ((metrics)->ascent = 0, (metrics)->descent = (status))
    53 
    54 static struct
    55 {
    56   /* registry name */
    57   const char *name;
    58   /* characters to distinguish the charset from the others */
    59   int uniquifier[6];
    60   /* additional constraint by language */
    61   const char *lang;
    62 } em_charset_table[] =
    63   { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
    64     { "iso8859-2", { 0x00A0, 0x010E }},
    65     { "iso8859-3", { 0x00A0, 0x0108 }},
    66     { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
    67     { "iso8859-5", { 0x00A0, 0x0401 }},
    68     { "iso8859-6", { 0x00A0, 0x060C }},
    69     { "iso8859-7", { 0x00A0, 0x0384 }},
    70     { "iso8859-8", { 0x00A0, 0x05D0 }},
    71     { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
    72     { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
    73     { "iso8859-11", { 0x00A0, 0x0E01 }},
    74     { "iso8859-13", { 0x00A0, 0x201C }},
    75     { "iso8859-14", { 0x00A0, 0x0174 }},
    76     { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
    77     { "iso8859-16", { 0x00A0, 0x0218}},
    78     { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
    79     { "big5-0", { 0x9C21 }, "zh-tw" },
    80     { "jisx0208.1983-0", { 0x4E55 }, "ja"},
    81     { "ksc5601.1985-0", { 0xAC00 }, "ko"},
    82     { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
    83     { "cns11643.1992-2", { 0x4E33, 0x7934 }},
    84     { "cns11643.1992-3", { 0x201A9 }},
    85     { "cns11643.1992-4", { 0x20057 }},
    86     { "cns11643.1992-5", { 0x20000 }},
    87     { "cns11643.1992-6", { 0x20003 }},
    88     { "cns11643.1992-7", { 0x20055 }},
    89     { "gbk-0", { 0x4E06 }, "zh-cn"},
    90     { "jisx0212.1990-0", { 0x4E44 }},
    91     { "jisx0213.2000-1", { 0xFA10 }, "ja"},
    92     { "jisx0213.2000-2", { 0xFA49 }},
    93     { "jisx0213.2004-1", { 0x20B9F }},
    94     { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
    95     { "tis620.2529-1", { 0x0E01 }, "th"},
    96     { "microsoft-cp1251", { 0x0401, 0x0490 }, "ru"},
    97     { "koi8-r", { 0x0401, 0x2219 }, "ru"},
    98     { "mulelao-1", { 0x0E81 }, "lo"},
    99     { "unicode-sip", { 0x20000 }},
   100     { "mulearabic-0", { 0x628 }},
   101     { "mulearabic-1", { 0x628 }},
   102     { "mulearabic-2", { 0x628 }},
   103     { NULL }
   104   };
   105 
   106 static void
   107 haikufont_apply_registry (struct haiku_font_pattern *pattern,
   108                           Lisp_Object registry)
   109 {
   110   char *str = SSDATA (SYMBOL_NAME (registry));
   111   USE_SAFE_ALLOCA;
   112   char *re = SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
   113   int i, j;
   114 
   115   for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
   116     {
   117       if (str[i] == '.')
   118         re[j++] = '\\';
   119       else if (str[i] == '*')
   120         re[j++] = '.';
   121       re[j] = str[i];
   122       if (re[j] == '?')
   123         re[j] = '.';
   124     }
   125   re[j] = '\0';
   126   AUTO_STRING_WITH_LEN (regexp, re, j);
   127   for (i = 0; em_charset_table[i].name; i++)
   128     if (fast_c_string_match_ignore_case
   129         (regexp, em_charset_table[i].name,
   130          strlen (em_charset_table[i].name)) >= 0)
   131       break;
   132   SAFE_FREE ();
   133   if (!em_charset_table[i].name)
   134     return;
   135   int *uniquifier = em_charset_table[i].uniquifier;
   136   int l;
   137 
   138   for (l = 0; uniquifier[l]; ++l);
   139 
   140   int *a = xmalloc (l * sizeof *a);
   141   for (l = 0; uniquifier[l]; ++l)
   142     a[l] = uniquifier[l];
   143 
   144   if (pattern->specified & FSPEC_WANTED)
   145     {
   146       int old_l = l;
   147       l += pattern->want_chars_len;
   148       a = xrealloc (a, l * sizeof *a);
   149       memcpy (&a[old_l], pattern->wanted_chars, (l - old_l) * sizeof *a);
   150       xfree (pattern->wanted_chars);
   151     }
   152 
   153   pattern->specified |= FSPEC_WANTED;
   154   pattern->want_chars_len = l;
   155   pattern->wanted_chars = a;
   156 
   157   if (em_charset_table[i].lang)
   158     {
   159       if (!strncmp (em_charset_table[i].lang, "zh", 2))
   160         {
   161           pattern->specified |= FSPEC_LANGUAGE;
   162           pattern->language = LANGUAGE_CN;
   163         }
   164       else if (!strncmp (em_charset_table[i].lang, "ko", 2))
   165         {
   166           pattern->specified |= FSPEC_LANGUAGE;
   167           pattern->language = LANGUAGE_KO;
   168         }
   169       else if (!strncmp (em_charset_table[i].lang, "ja", 2))
   170         {
   171           pattern->specified |= FSPEC_LANGUAGE;
   172           pattern->language = LANGUAGE_JP;
   173         }
   174     }
   175 
   176   return;
   177 }
   178 
   179 static Lisp_Object
   180 haikufont_get_fallback_entity (void)
   181 {
   182   Lisp_Object ent = font_make_entity ();
   183   ASET (ent, FONT_TYPE_INDEX, Qhaiku);
   184   ASET (ent, FONT_FOUNDRY_INDEX, Qhaiku);
   185   ASET (ent, FONT_FAMILY_INDEX, Qnil);
   186   ASET (ent, FONT_ADSTYLE_INDEX, Qnil);
   187   ASET (ent, FONT_REGISTRY_INDEX, Qiso10646_1);
   188   ASET (ent, FONT_SIZE_INDEX, make_fixnum (0));
   189   ASET (ent, FONT_AVGWIDTH_INDEX, make_fixnum (0));
   190   ASET (ent, FONT_SPACING_INDEX, make_fixnum (FONT_SPACING_MONO));
   191   FONT_SET_STYLE (ent, FONT_WIDTH_INDEX, Qnil);
   192   FONT_SET_STYLE (ent, FONT_WEIGHT_INDEX, Qnil);
   193   FONT_SET_STYLE (ent, FONT_SLANT_INDEX, Qnil);
   194 
   195   return ent;
   196 }
   197 
   198 static Lisp_Object
   199 haikufont_get_cache (struct frame *frame)
   200 {
   201   return font_cache;
   202 }
   203 
   204 static Lisp_Object
   205 haikufont_weight_to_lisp (int weight)
   206 {
   207   switch (weight)
   208     {
   209     case HAIKU_THIN:
   210       return Qthin;
   211     case HAIKU_EXTRALIGHT:
   212       return Qextra_light;
   213     case HAIKU_LIGHT:
   214       return Qlight;
   215     case HAIKU_SEMI_LIGHT:
   216       return Qsemi_light;
   217     case HAIKU_REGULAR:
   218       return Qnormal;
   219     case HAIKU_SEMI_BOLD:
   220       return Qsemi_bold;
   221     case HAIKU_BOLD:
   222       return Qbold;
   223     case HAIKU_EXTRA_BOLD:
   224       return Qextra_bold;
   225     case HAIKU_BOOK:
   226       return Qbook;
   227     case HAIKU_HEAVY:
   228       return Qheavy;
   229     case HAIKU_ULTRA_HEAVY:
   230       return Qultra_heavy;
   231     case HAIKU_BLACK:
   232       return Qblack;
   233     case HAIKU_MEDIUM:
   234       return Qmedium;
   235     }
   236   emacs_abort ();
   237 }
   238 
   239 static int
   240 haikufont_lisp_to_weight (Lisp_Object weight)
   241 {
   242   if (EQ (weight, Qthin))
   243     return HAIKU_THIN;
   244   if (EQ (weight, Qultra_light))
   245     return HAIKU_EXTRALIGHT;
   246   if (EQ (weight, Qextra_light))
   247     return HAIKU_EXTRALIGHT;
   248   if (EQ (weight, Qlight))
   249     return HAIKU_LIGHT;
   250   if (EQ (weight, Qsemi_light))
   251     return HAIKU_SEMI_LIGHT;
   252   if (EQ (weight, Qnormal) || EQ (weight, Qregular))
   253     return HAIKU_REGULAR;
   254   if (EQ (weight, Qsemi_bold))
   255     return HAIKU_SEMI_BOLD;
   256   if (EQ (weight, Qbold))
   257     return HAIKU_BOLD;
   258   if (EQ (weight, Qextra_bold))
   259     return HAIKU_EXTRA_BOLD;
   260   if (EQ (weight, Qultra_bold))
   261     return HAIKU_EXTRA_BOLD;
   262   if (EQ (weight, Qbook))
   263     return HAIKU_BOOK;
   264   if (EQ (weight, Qheavy))
   265     return HAIKU_HEAVY;
   266   if (EQ (weight, Qultra_heavy))
   267     return HAIKU_ULTRA_HEAVY;
   268   if (EQ (weight, Qblack))
   269     return HAIKU_BLACK;
   270   if (EQ (weight, Qmedium))
   271     return HAIKU_MEDIUM;
   272 
   273   return HAIKU_REGULAR;
   274 }
   275 
   276 static Lisp_Object
   277 haikufont_slant_to_lisp (enum haiku_font_slant slant)
   278 {
   279   switch (slant)
   280     {
   281     case NO_SLANT:
   282       emacs_abort ();
   283     case SLANT_ITALIC:
   284       return Qitalic;
   285     case SLANT_REGULAR:
   286       return Qnormal;
   287     case SLANT_OBLIQUE:
   288       return Qoblique;
   289     }
   290   emacs_abort ();
   291 }
   292 
   293 static enum haiku_font_slant
   294 haikufont_lisp_to_slant (Lisp_Object slant)
   295 {
   296   if (EQ (slant, Qitalic)
   297       || EQ (slant, Qreverse_italic))
   298     return SLANT_ITALIC;
   299   if (EQ (slant, Qoblique)
   300       || EQ (slant, Qreverse_oblique))
   301     return SLANT_OBLIQUE;
   302   if (EQ (slant, Qnormal) || EQ (slant, Qregular))
   303     return SLANT_REGULAR;
   304 
   305   return SLANT_REGULAR;
   306 }
   307 
   308 static Lisp_Object
   309 haikufont_width_to_lisp (enum haiku_font_width width)
   310 {
   311   switch (width)
   312     {
   313     case NO_WIDTH:
   314       emacs_abort ();
   315     case ULTRA_CONDENSED:
   316       return Qultra_condensed;
   317     case EXTRA_CONDENSED:
   318       return Qextra_condensed;
   319     case CONDENSED:
   320       return Qcondensed;
   321     case SEMI_CONDENSED:
   322       return Qsemi_condensed;
   323     case NORMAL_WIDTH:
   324       return Qnormal;
   325     case SEMI_EXPANDED:
   326       return Qsemi_expanded;
   327     case EXPANDED:
   328       return Qexpanded;
   329     case EXTRA_EXPANDED:
   330       return Qextra_expanded;
   331     case ULTRA_EXPANDED:
   332       return Qultra_expanded;
   333     }
   334 
   335   emacs_abort ();
   336 }
   337 
   338 static enum haiku_font_width
   339 haikufont_lisp_to_width (Lisp_Object lisp)
   340 {
   341   if (EQ (lisp, Qultra_condensed))
   342     return ULTRA_CONDENSED;
   343   if (EQ (lisp, Qextra_condensed))
   344     return EXTRA_CONDENSED;
   345   if (EQ (lisp, Qcondensed))
   346     return CONDENSED;
   347   if (EQ (lisp, Qsemi_condensed))
   348     return SEMI_CONDENSED;
   349   if (EQ (lisp, Qnormal) || EQ (lisp, Qregular))
   350     return NORMAL_WIDTH;
   351   if (EQ (lisp, Qexpanded))
   352     return EXPANDED;
   353   if (EQ (lisp, Qextra_expanded))
   354     return EXTRA_EXPANDED;
   355   if (EQ (lisp, Qultra_expanded))
   356     return ULTRA_EXPANDED;
   357 
   358   return NORMAL_WIDTH;
   359 }
   360 
   361 static int
   362 haikufont_maybe_handle_special_family (Lisp_Object family,
   363                                        struct haiku_font_pattern *ptn)
   364 {
   365   CHECK_SYMBOL (family);
   366 
   367   if (EQ (family, Qmonospace) || EQ (family, Qfixed) ||
   368       EQ (family, Qdefault))
   369     {
   370       BFont_populate_fixed_family (ptn);
   371       return 1;
   372     }
   373   else if (EQ (family, QSans_Serif))
   374     {
   375       BFont_populate_plain_family (ptn);
   376       return 1;
   377     }
   378   return 0;
   379 }
   380 
   381 static Lisp_Object
   382 haikufont_pattern_to_entity (struct haiku_font_pattern *ptn)
   383 {
   384   Lisp_Object entity, extras;
   385 
   386   entity = font_make_entity ();
   387   extras = Qnil;
   388 
   389   ASET (entity, FONT_TYPE_INDEX, Qhaiku);
   390   ASET (entity, FONT_FOUNDRY_INDEX, Qhaiku);
   391   ASET (entity, FONT_FAMILY_INDEX, Qdefault);
   392   ASET (entity, FONT_ADSTYLE_INDEX, Qnil);
   393   ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
   394   ASET (entity, FONT_SIZE_INDEX, make_fixnum (0));
   395   ASET (entity, FONT_AVGWIDTH_INDEX, make_fixnum (0));
   396   ASET (entity, FONT_SPACING_INDEX, make_fixnum (FONT_SPACING_MONO));
   397 
   398   /* FONT_EXTRA_INDEX in a font entity can contain a cons of two
   399      numbers (STYLE . IDX) under the key :indices that tell Emacs how
   400      to open a font.  */
   401   if (ptn->specified & FSPEC_INDICES)
   402     extras = Fcons (Fcons (QCindices,
   403                            Fcons (make_fixnum (ptn->family_index),
   404                                   make_fixnum (ptn->style_index))),
   405                     extras);
   406 
   407   if (ptn->specified & FSPEC_ANTIALIAS)
   408     extras = Fcons (Fcons (QCantialias,
   409                            ptn->use_antialiasing ? Qt : Qnil),
   410                     extras);
   411 
   412   ASET (entity, FONT_EXTRA_INDEX, extras);
   413 
   414   FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, Qnormal);
   415   FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX, Qnormal);
   416   FONT_SET_STYLE (entity, FONT_SLANT_INDEX, Qnormal);
   417 
   418   if (ptn->specified & FSPEC_FAMILY)
   419     ASET (entity, FONT_FAMILY_INDEX, intern (ptn->family));
   420   else
   421     ASET (entity, FONT_FAMILY_INDEX, Qdefault);
   422 
   423   if (ptn->specified & FSPEC_STYLE)
   424     ASET (entity, FONT_ADSTYLE_INDEX, intern (ptn->style));
   425   else
   426     {
   427       if (ptn->specified & FSPEC_WEIGHT)
   428         FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
   429                         haikufont_weight_to_lisp (ptn->weight));
   430       if (ptn->specified & FSPEC_SLANT)
   431         FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
   432                         haikufont_slant_to_lisp (ptn->slant));
   433       if (ptn->specified & FSPEC_WIDTH)
   434         FONT_SET_STYLE (entity, FONT_WIDTH_INDEX,
   435                         haikufont_width_to_lisp (ptn->width));
   436     }
   437 
   438   if (ptn->specified & FSPEC_SPACING)
   439     ASET (entity, FONT_SPACING_INDEX,
   440           make_fixnum (ptn->mono_spacing_p
   441                        ? FONT_SPACING_MONO
   442                        : FONT_SPACING_PROPORTIONAL));
   443 
   444   return entity;
   445 }
   446 
   447 static void
   448 haikufont_pattern_from_object (struct haiku_font_pattern *pattern,
   449                                Lisp_Object font_object)
   450 {
   451   Lisp_Object val;
   452 
   453   pattern->specified = 0;
   454 
   455   val = AREF (font_object, FONT_FAMILY_INDEX);
   456   if (!NILP (val))
   457     {
   458       pattern->specified |= FSPEC_FAMILY;
   459       strncpy ((char *) &pattern->family,
   460                SSDATA (SYMBOL_NAME (val)),
   461                sizeof pattern->family - 1);
   462       pattern->family[sizeof pattern->family - 1] = '\0';
   463     }
   464 
   465   val = AREF (font_object, FONT_ADSTYLE_INDEX);
   466   if (!NILP (val))
   467     {
   468       pattern->specified |= FSPEC_STYLE;
   469       strncpy ((char *) &pattern->style,
   470                SSDATA (SYMBOL_NAME (val)),
   471                sizeof pattern->style - 1);
   472       pattern->style[sizeof pattern->style - 1] = '\0';
   473     }
   474 
   475   val = FONT_WEIGHT_FOR_FACE (font_object);
   476   if (!NILP (val) && !EQ (val, Qunspecified))
   477     {
   478       pattern->specified |= FSPEC_WEIGHT;
   479       pattern->weight = haikufont_lisp_to_weight (val);
   480     }
   481 
   482   val = FONT_SLANT_FOR_FACE (font_object);
   483   if (!NILP (val) && !EQ (val, Qunspecified))
   484     {
   485       pattern->specified |= FSPEC_SLANT;
   486       pattern->slant = haikufont_lisp_to_slant (val);
   487     }
   488 
   489   val = FONT_WIDTH_FOR_FACE (font_object);
   490   if (!NILP (val) && !EQ (val, Qunspecified))
   491     {
   492       pattern->specified |= FSPEC_WIDTH;
   493       pattern->width = haikufont_lisp_to_width (val);
   494     }
   495 
   496   val = assq_no_quit (QCantialias,
   497                       AREF (font_object, FONT_EXTRA_INDEX));
   498   if (CONSP (val))
   499     {
   500       pattern->specified |= FSPEC_ANTIALIAS;
   501       pattern->use_antialiasing = !NILP (XCDR (val));
   502     }
   503 }
   504 
   505 static void
   506 haikufont_spec_or_entity_to_pattern (Lisp_Object ent, int list_p,
   507                                      struct haiku_font_pattern *ptn)
   508 {
   509   Lisp_Object tem;
   510   ptn->specified = 0;
   511 
   512   tem = AREF (ent, FONT_ADSTYLE_INDEX);
   513   if (!NILP (tem))
   514     {
   515       ptn->specified |= FSPEC_STYLE;
   516       strncpy ((char *) &ptn->style,
   517                SSDATA (SYMBOL_NAME (tem)),
   518                sizeof ptn->style - 1);
   519       ptn->style[sizeof ptn->style - 1] = '\0';
   520     }
   521 
   522   tem = FONT_SLANT_SYMBOLIC (ent);
   523   if (!NILP (tem) && !EQ (tem, Qunspecified))
   524     {
   525       ptn->specified |= FSPEC_SLANT;
   526       ptn->slant = haikufont_lisp_to_slant (tem);
   527     }
   528 
   529   tem = FONT_WEIGHT_SYMBOLIC (ent);
   530   if (!NILP (tem) && !EQ (tem, Qunspecified))
   531     {
   532       ptn->specified |= FSPEC_WEIGHT;
   533       ptn->weight = haikufont_lisp_to_weight (tem);
   534     }
   535 
   536   tem = FONT_WIDTH_SYMBOLIC (ent);
   537   if (!NILP (tem) && !EQ (tem, Qunspecified))
   538     {
   539       ptn->specified |= FSPEC_WIDTH;
   540       ptn->width = haikufont_lisp_to_width (tem);
   541     }
   542 
   543   tem = AREF (ent, FONT_SPACING_INDEX);
   544   if (!NILP (tem) && !EQ (tem, Qunspecified))
   545     {
   546       ptn->specified |= FSPEC_SPACING;
   547       ptn->mono_spacing_p = XFIXNUM (tem) != FONT_SPACING_PROPORTIONAL;
   548     }
   549 
   550   tem = AREF (ent, FONT_FAMILY_INDEX);
   551   if (!NILP (tem) && !EQ (tem, Qunspecified)
   552       && (list_p
   553           && !haikufont_maybe_handle_special_family (tem, ptn)))
   554     {
   555       ptn->specified |= FSPEC_FAMILY;
   556       strncpy ((char *) &ptn->family,
   557                SSDATA (SYMBOL_NAME (tem)),
   558                sizeof ptn->family - 1);
   559       ptn->family[sizeof ptn->family - 1] = '\0';
   560     }
   561 
   562   tem = assq_no_quit (QCscript, AREF (ent, FONT_EXTRA_INDEX));
   563   if (!NILP (tem))
   564     {
   565       tem = assq_no_quit (XCDR (tem), Vscript_representative_chars);
   566 
   567       if (CONSP (tem) && VECTORP (XCDR (tem)))
   568         {
   569           tem = XCDR (tem);
   570 
   571           int count = 0;
   572 
   573           for (int j = 0; j < ASIZE (tem); ++j)
   574             if (TYPE_RANGED_FIXNUMP (uint32_t, AREF (tem, j)))
   575               ++count;
   576 
   577           if (count)
   578             {
   579               ptn->specified |= FSPEC_NEED_ONE_OF;
   580               ptn->need_one_of_len = count;
   581               ptn->need_one_of = xmalloc (count * sizeof *ptn->need_one_of);
   582               count = 0;
   583               for (int j = 0; j < ASIZE (tem); ++j)
   584                 if (TYPE_RANGED_FIXNUMP (uint32_t, AREF (tem, j)))
   585                   {
   586                     ptn->need_one_of[j] = XFIXNAT (AREF (tem, j));
   587                     ++count;
   588                   }
   589             }
   590         }
   591       else if (CONSP (tem) && CONSP (XCDR (tem)))
   592         {
   593           int count = 0;
   594 
   595           for (Lisp_Object it = XCDR (tem); CONSP (it); it = XCDR (it))
   596             if (TYPE_RANGED_FIXNUMP (uint32_t, XCAR (it)))
   597               ++count;
   598 
   599           if (count)
   600             {
   601               ptn->specified |= FSPEC_WANTED;
   602               ptn->want_chars_len = count;
   603               ptn->wanted_chars = xmalloc (count * sizeof *ptn->wanted_chars);
   604               count = 0;
   605 
   606               for (tem = XCDR (tem); CONSP (tem); tem = XCDR (tem))
   607                 if (TYPE_RANGED_FIXNUMP (uint32_t, XCAR (tem)))
   608                   {
   609                     ptn->wanted_chars[count] = XFIXNAT (XCAR (tem));
   610                     ++count;
   611                   }
   612             }
   613         }
   614     }
   615 
   616   tem = assq_no_quit (QClang, AREF (ent, FONT_EXTRA_INDEX));
   617   if (CONSP (tem))
   618     {
   619       tem = XCDR (tem);
   620       if (EQ (tem, Qzh))
   621         {
   622           ptn->specified |= FSPEC_LANGUAGE;
   623           ptn->language = LANGUAGE_CN;
   624         }
   625       else if (EQ (tem, Qko))
   626         {
   627           ptn->specified |= FSPEC_LANGUAGE;
   628           ptn->language = LANGUAGE_KO;
   629         }
   630       else if (EQ (tem, Qjp))
   631         {
   632           ptn->specified |= FSPEC_LANGUAGE;
   633           ptn->language = LANGUAGE_JP;
   634         }
   635     }
   636 
   637   tem = assq_no_quit (QCantialias, AREF (ent, FONT_EXTRA_INDEX));
   638   if (CONSP (tem))
   639     {
   640       ptn->specified |= FSPEC_ANTIALIAS;
   641       ptn->use_antialiasing = !NILP (XCDR (tem));
   642     }
   643 
   644   tem = AREF (ent, FONT_REGISTRY_INDEX);
   645   if (SYMBOLP (tem))
   646     haikufont_apply_registry (ptn, tem);
   647 }
   648 
   649 static void
   650 haikufont_done_with_query_pattern (struct haiku_font_pattern *ptn)
   651 {
   652   if (ptn->specified & FSPEC_WANTED)
   653     xfree (ptn->wanted_chars);
   654 
   655   if (ptn->specified & FSPEC_NEED_ONE_OF)
   656     xfree (ptn->need_one_of);
   657 }
   658 
   659 static Lisp_Object
   660 haikufont_match (struct frame *f, Lisp_Object font_spec)
   661 {
   662   block_input ();
   663   Lisp_Object tem = Qnil;
   664   struct haiku_font_pattern ptn;
   665   haikufont_spec_or_entity_to_pattern (font_spec, 0, &ptn);
   666   ptn.specified &= ~FSPEC_FAMILY;
   667   struct haiku_font_pattern *found = BFont_find (&ptn);
   668   haikufont_done_with_query_pattern (&ptn);
   669   if (found)
   670     {
   671       tem = haikufont_pattern_to_entity (found);
   672       haiku_font_pattern_free (found);
   673     }
   674   unblock_input ();
   675   return !NILP (tem) ? tem : haikufont_get_fallback_entity ();
   676 }
   677 
   678 static Lisp_Object
   679 haikufont_list (struct frame *f, Lisp_Object font_spec)
   680 {
   681   Lisp_Object lst, tem;
   682   struct haiku_font_pattern ptn, *found, *pt;
   683 
   684   lst = Qnil;
   685 
   686   block_input ();
   687   /* Returning irrelevant results on receiving an OTF form will cause
   688      fontset.c to loop over and over, making displaying some
   689      characters very slow.  */
   690   tem = assq_no_quit (QCotf, AREF (font_spec, FONT_EXTRA_INDEX));
   691 
   692   if (CONSP (tem) && !NILP (XCDR (tem)))
   693     {
   694       unblock_input ();
   695       return Qnil;
   696     }
   697 
   698   haikufont_spec_or_entity_to_pattern (font_spec, 1, &ptn);
   699   found = BFont_find (&ptn);
   700   haikufont_done_with_query_pattern (&ptn);
   701   if (found)
   702     {
   703       for (pt = found; pt; pt = pt->next)
   704         lst = Fcons (haikufont_pattern_to_entity (pt), lst);
   705       haiku_font_pattern_free (found);
   706     }
   707   unblock_input ();
   708   return lst;
   709 }
   710 
   711 static void
   712 haiku_bulk_encode (struct haikufont_info *font_info, int block)
   713 {
   714   unsigned short *unichars = xmalloc (0x101 * sizeof (*unichars));
   715   unsigned int i, idx;
   716 
   717   block_input ();
   718 
   719   font_info->glyphs[block] = unichars;
   720   if (!unichars)
   721     emacs_abort ();
   722 
   723   for (idx = block << 8, i = 0; i < 0x100; idx++, i++)
   724     unichars[i] = idx;
   725   unichars[0x100] = 0;
   726 
   727 
   728   /* If the font contains the entire block, just store it.  */
   729   if (!BFont_have_char_block (font_info->be_font,
   730                               unichars[0], unichars[0xff]))
   731     {
   732       for (int i = 0; i < 0x100; ++i)
   733         if (!BFont_have_char_p (font_info->be_font, unichars[i]))
   734           unichars[i] = 0xFFFF;
   735     }
   736 
   737   unblock_input ();
   738 }
   739 
   740 static unsigned int
   741 haikufont_encode_char (struct font *font, int c)
   742 {
   743   struct haikufont_info *font_info = (struct haikufont_info *) font;
   744   unsigned char high = (c & 0xff00) >> 8, low = c & 0x00ff;
   745   unsigned short g;
   746 
   747   if (c > 0xFFFF)
   748     return FONT_INVALID_CODE;
   749 
   750   if (!font_info->glyphs[high])
   751     haiku_bulk_encode (font_info, high);
   752   g = font_info->glyphs[high][low];
   753   return g == 0xFFFF ? FONT_INVALID_CODE : g;
   754 }
   755 
   756 static Lisp_Object
   757 haikufont_open (struct frame *f, Lisp_Object font_entity, int pixel_size)
   758 {
   759   struct haikufont_info *font_info;
   760   struct haiku_font_pattern ptn;
   761   struct font *font;
   762   void *be_font;
   763   Lisp_Object font_object, extra, indices, antialias;
   764   int px_size, min_width, max_width;
   765   int avg_width, height, space_width, ascent;
   766   int descent, underline_pos, underline_thickness;
   767 
   768   if (XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)) != 0)
   769     pixel_size = XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX));
   770   else if (pixel_size == 0)
   771     {
   772       /* Try to resolve a suitable size for the font, if the font size
   773          has not already been specified.  First, if FRAME_FONT is set,
   774          use its size.  Otherwise, use 12, which is the default on
   775          Haiku.  */
   776 
   777       if (FRAME_FONT (f))
   778         pixel_size = FRAME_FONT (f)->pixel_size;
   779       else
   780         pixel_size = 12;
   781     }
   782 
   783   extra = AREF (font_entity, FONT_EXTRA_INDEX);
   784 
   785   indices = assq_no_quit (QCindices, extra);
   786   antialias = assq_no_quit (QCantialias, extra);
   787 
   788   if (CONSP (indices))
   789     indices = XCDR (indices);
   790 
   791   /* If the font's indices is already available, open the font using
   792      those instead.  */
   793 
   794   if (CONSP (indices) && FIXNUMP (XCAR (indices))
   795       && FIXNUMP (XCDR (indices)))
   796     {
   797       block_input ();
   798       be_font = be_open_font_at_index (XFIXNUM (XCAR (indices)),
   799                                        XFIXNUM (XCDR (indices)),
   800                                        pixel_size);
   801       unblock_input ();
   802 
   803       if (!be_font)
   804         return Qnil;
   805     }
   806   else
   807     {
   808       block_input ();
   809       haikufont_spec_or_entity_to_pattern (font_entity, 1, &ptn);
   810 
   811       if (BFont_open_pattern (&ptn, &be_font, pixel_size))
   812         {
   813           haikufont_done_with_query_pattern (&ptn);
   814           unblock_input ();
   815           return Qnil;
   816         }
   817 
   818       haikufont_done_with_query_pattern (&ptn);
   819       unblock_input ();
   820     }
   821 
   822   block_input ();
   823 
   824   font_object = font_make_object (VECSIZE (struct haikufont_info),
   825                                   font_entity, pixel_size);
   826 
   827   ASET (font_object, FONT_TYPE_INDEX, Qhaiku);
   828   font_info = (struct haikufont_info *) XFONT_OBJECT (font_object);
   829   font = (struct font *) font_info;
   830 
   831   if (!font)
   832     {
   833       unblock_input ();
   834       return Qnil;
   835     }
   836 
   837   font_info->be_font = be_font;
   838   font_info->glyphs = xzalloc (0x100 * sizeof *font_info->glyphs);
   839 
   840   if (CONSP (antialias))
   841     be_set_font_antialiasing (be_font, !NILP (XCDR (antialias)));
   842 
   843   font->pixel_size = 0;
   844   font->driver = &haikufont_driver;
   845   font->encoding_charset = -1;
   846   font->repertory_charset = -1;
   847   font->default_ascent = 0;
   848   font->vertical_centering = 0;
   849   font->baseline_offset = 0;
   850   font->relative_compose = 0;
   851 
   852   font_info->metrics = NULL;
   853   font_info->metrics_nrows = 0;
   854 
   855   BFont_metrics (be_font, &px_size, &min_width,
   856                  &max_width, &avg_width, &height,
   857                  &space_width, &ascent, &descent,
   858                  &underline_pos, &underline_thickness);
   859 
   860   font->pixel_size = px_size;
   861   font->min_width = min_width;
   862   font->max_width = max_width;
   863   font->average_width = avg_width;
   864   font->height = height;
   865   font->space_width = space_width;
   866   font->ascent = ascent;
   867   font->descent = descent;
   868   font->default_ascent = ascent;
   869   font->underline_position = underline_pos;
   870   font->underline_thickness = underline_thickness;
   871 
   872   font->vertical_centering = 0;
   873   font->baseline_offset = 0;
   874   font->relative_compose = 0;
   875 
   876   font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil);
   877 
   878   unblock_input ();
   879   return font_object;
   880 }
   881 
   882 static void
   883 haikufont_close (struct font *font)
   884 {
   885   struct haikufont_info *info = (struct haikufont_info *) font;
   886   int i;
   887 
   888   if (font_data_structures_may_be_ill_formed ())
   889     return;
   890 
   891   block_input ();
   892   if (info && info->be_font)
   893     BFont_close (info->be_font);
   894 
   895   for (i = 0; i < info->metrics_nrows; i++)
   896     {
   897       if (info->metrics[i])
   898         xfree (info->metrics[i]);
   899     }
   900 
   901   if (info->metrics)
   902     xfree (info->metrics);
   903 
   904   for (i = 0; i < 0x100; ++i)
   905     {
   906       if (info->glyphs[i])
   907         xfree (info->glyphs[i]);
   908     }
   909 
   910   xfree (info->glyphs);
   911   unblock_input ();
   912 }
   913 
   914 static void
   915 haikufont_prepare_face (struct frame *f, struct face *face)
   916 {
   917 
   918 }
   919 
   920 static void
   921 haikufont_glyph_extents (struct font *font, unsigned code,
   922                          struct font_metrics *metrics)
   923 {
   924   struct haikufont_info *info = (struct haikufont_info *) font;
   925 
   926   struct font_metrics *cache;
   927   int row, col;
   928 
   929   row = code / METRICS_NCOLS_PER_ROW;
   930   col = code % METRICS_NCOLS_PER_ROW;
   931   if (row >= info->metrics_nrows)
   932     {
   933       info->metrics =
   934         xrealloc (info->metrics,
   935                   sizeof (struct font_metrics *) * (row + 1));
   936       memset (info->metrics + info->metrics_nrows, 0,
   937               (sizeof (struct font_metrics *)
   938                * (row + 1 - info->metrics_nrows)));
   939       info->metrics_nrows = row + 1;
   940     }
   941 
   942   if (info->metrics[row] == NULL)
   943     {
   944       struct font_metrics *new;
   945       int i;
   946 
   947       new = xmalloc (sizeof (struct font_metrics) * METRICS_NCOLS_PER_ROW);
   948       for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
   949         METRICS_SET_STATUS (new + i, METRICS_INVALID);
   950       info->metrics[row] = new;
   951     }
   952   cache = info->metrics[row] + col;
   953 
   954   if (METRICS_STATUS (cache) == METRICS_INVALID)
   955     {
   956       unsigned char utf8[MAX_MULTIBYTE_LENGTH];
   957       memset (utf8, 0, MAX_MULTIBYTE_LENGTH);
   958       CHAR_STRING (code, utf8);
   959       int advance, lb, rb;
   960       BFont_char_bounds (info->be_font, (const char *) utf8, &advance, &lb, &rb);
   961 
   962       cache->lbearing = lb;
   963       cache->rbearing = rb;
   964       cache->width = advance;
   965       cache->ascent = font->ascent;
   966       cache->descent = font->descent;
   967     }
   968 
   969   if (metrics)
   970     *metrics = *cache;
   971 }
   972 
   973 static void
   974 haikufont_text_extents (struct font *font, const unsigned int *code,
   975                         int nglyphs, struct font_metrics *metrics)
   976 {
   977   int totalwidth = 0;
   978   memset (metrics, 0, sizeof (struct font_metrics));
   979 
   980   block_input ();
   981   for (int i = 0; i < nglyphs; i++)
   982     {
   983       struct font_metrics m;
   984       haikufont_glyph_extents (font, code[i], &m);
   985       if (metrics)
   986         {
   987           if (totalwidth + m.lbearing < metrics->lbearing)
   988             metrics->lbearing = totalwidth + m.lbearing;
   989           if (totalwidth + m.rbearing > metrics->rbearing)
   990             metrics->rbearing = totalwidth + m.rbearing;
   991           if (m.ascent > metrics->ascent)
   992             metrics->ascent = m.ascent;
   993           if (m.descent > metrics->descent)
   994             metrics->descent = m.descent;
   995         }
   996       totalwidth += m.width;
   997     }
   998 
   999   unblock_input ();
  1000 
  1001   if (metrics)
  1002     metrics->width = totalwidth;
  1003 }
  1004 
  1005 static Lisp_Object
  1006 haikufont_shape (Lisp_Object lgstring, Lisp_Object direction)
  1007 {
  1008   struct haikufont_info *font =
  1009     (struct haikufont_info *) CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
  1010   int *advance, *lb, *rb;
  1011   ptrdiff_t glyph_len, len, i, b_len;
  1012   Lisp_Object tem;
  1013   char *b;
  1014   uint32_t *mb_buf;
  1015 
  1016   glyph_len = LGSTRING_GLYPH_LEN (lgstring);
  1017   for (i = 0; i < glyph_len; ++i)
  1018     {
  1019       tem = LGSTRING_GLYPH (lgstring, i);
  1020 
  1021       if (NILP (tem))
  1022         break;
  1023     }
  1024 
  1025   len = i;
  1026 
  1027   if (INT_MAX / 2 < len)
  1028     memory_full (SIZE_MAX);
  1029 
  1030   block_input ();
  1031 
  1032   b_len = 0;
  1033   b = xmalloc (b_len);
  1034   mb_buf = alloca (len * sizeof *mb_buf);
  1035 
  1036   for (i = b_len; i < len; ++i)
  1037     {
  1038       uint32_t c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
  1039       mb_buf[i] = c;
  1040       unsigned char mb[MAX_MULTIBYTE_LENGTH];
  1041       int slen = CHAR_STRING (c, mb);
  1042 
  1043       b = xrealloc (b, b_len = (b_len + slen));
  1044       if (len == 1)
  1045         b[b_len - slen] = mb[0];
  1046       else
  1047         memcpy (b + b_len - slen, mb, slen);
  1048     }
  1049 
  1050   advance = alloca (len * sizeof *advance);
  1051   lb = alloca (len * sizeof *lb);
  1052   rb = alloca (len * sizeof *rb);
  1053 
  1054   eassert (font->be_font);
  1055   BFont_nchar_bounds (font->be_font, b, advance, lb, rb, len);
  1056   xfree (b);
  1057 
  1058   for (i = 0; i < len; ++i)
  1059     {
  1060       tem = LGSTRING_GLYPH (lgstring, i);
  1061       if (NILP (tem))
  1062         {
  1063           tem = LGLYPH_NEW ();
  1064           LGSTRING_SET_GLYPH (lgstring, i, tem);
  1065         }
  1066 
  1067       LGLYPH_SET_FROM (tem, i);
  1068       LGLYPH_SET_TO (tem, i);
  1069       LGLYPH_SET_CHAR (tem, mb_buf[i]);
  1070       LGLYPH_SET_CODE (tem, mb_buf[i]);
  1071 
  1072       LGLYPH_SET_WIDTH (tem, advance[i]);
  1073       LGLYPH_SET_LBEARING (tem, lb[i]);
  1074       LGLYPH_SET_RBEARING (tem, rb[i]);
  1075       LGLYPH_SET_ASCENT (tem, font->font.ascent);
  1076       LGLYPH_SET_DESCENT (tem, font->font.descent);
  1077     }
  1078 
  1079   unblock_input ();
  1080 
  1081   return make_fixnum (len);
  1082 }
  1083 
  1084 static int
  1085 haikufont_draw (struct glyph_string *s, int from, int to,
  1086                 int x, int y, bool with_background)
  1087 {
  1088   struct frame *f = s->f;
  1089   struct face *face = s->face;
  1090   struct font_info *info = (struct font_info *) s->font;
  1091   unsigned char mb[MAX_MULTIBYTE_LENGTH];
  1092   void *view = FRAME_HAIKU_VIEW (f);
  1093   unsigned long foreground, background;
  1094 
  1095   block_input ();
  1096   prepare_face_for_display (s->f, face);
  1097 
  1098   if (s->hl != DRAW_CURSOR)
  1099     {
  1100       foreground = s->face->foreground;
  1101       background = s->face->background;
  1102     }
  1103   else
  1104     haiku_merge_cursor_foreground (s, &foreground, &background);
  1105 
  1106   /* Presumably the draw lock is already held by
  1107      haiku_draw_glyph_string; */
  1108   if (with_background)
  1109     {
  1110       int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
  1111 
  1112       /* Font's global height and ascent values might be
  1113          preposterously large for some fonts.  We fix here the case
  1114          when those fonts are used for display of glyphless
  1115          characters, because drawing background with font dimensions
  1116          in those cases makes the display illegible.  There's only one
  1117          more call to the draw method with with_background set to
  1118          true, and that's in x_draw_glyph_string_foreground, when
  1119          drawing the cursor, where we have no such heuristics
  1120          available.  FIXME.  */
  1121       if (s->first_glyph->type == GLYPHLESS_GLYPH
  1122           && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
  1123               || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
  1124         height = ascent =
  1125           s->first_glyph->slice.glyphless.lower_yoff
  1126           - s->first_glyph->slice.glyphless.upper_yoff;
  1127 
  1128       haiku_draw_background_rect (s, s->face, x, y - ascent,
  1129                                   s->width, height);
  1130     }
  1131 
  1132   BView_SetHighColor (view, foreground);
  1133   BView_MovePenTo (view, x, y);
  1134   BView_SetFont (view, ((struct haikufont_info *) info)->be_font);
  1135 
  1136   if (from == to)
  1137     {
  1138       int len = CHAR_STRING (s->char2b[from], mb);
  1139       BView_DrawString (view, (char *) mb, len);
  1140     }
  1141   else
  1142     {
  1143       ptrdiff_t b_len = 0;
  1144       char *b = alloca ((to - from + 1) * MAX_MULTIBYTE_LENGTH);
  1145 
  1146       for (int idx = from; idx < to; ++idx)
  1147         {
  1148           int len = CHAR_STRING (s->char2b[idx], mb);
  1149           b_len += len;
  1150 
  1151           if (len == 1)
  1152             b[b_len - len] = mb[0];
  1153           else
  1154             memcpy (b + b_len - len, mb, len);
  1155         }
  1156 
  1157       BView_DrawString (view, b, b_len);
  1158     }
  1159 
  1160   unblock_input ();
  1161   return 1;
  1162 }
  1163 
  1164 static Lisp_Object
  1165 haikufont_list_family (struct frame *f)
  1166 {
  1167   Lisp_Object list = Qnil;
  1168   size_t length;
  1169   ptrdiff_t idx;
  1170   haiku_font_family_or_style *styles;
  1171 
  1172   block_input ();
  1173   styles = be_list_font_families (&length);
  1174   unblock_input ();
  1175 
  1176   if (!styles)
  1177     return list;
  1178 
  1179   block_input ();
  1180   for (idx = 0; idx < length; ++idx)
  1181     {
  1182       if (styles[idx][0])
  1183         list = Fcons (intern ((char *) &styles[idx]), list);
  1184     }
  1185 
  1186   free (styles);
  1187   unblock_input ();
  1188 
  1189   return list;
  1190 }
  1191 
  1192 /* List of boolean properties in font names accepted by this font
  1193    driver.  */
  1194 static const char *const haikufont_booleans[] =
  1195   {
  1196     ":antialias",
  1197     NULL,
  1198   };
  1199 
  1200 /* List of non-boolean properties.  Currently empty.  */
  1201 static const char *const haikufont_non_booleans[1];
  1202 
  1203 static void
  1204 haikufont_filter_properties (Lisp_Object font, Lisp_Object alist)
  1205 {
  1206   font_filter_properties (font, alist, haikufont_booleans,
  1207                           haikufont_non_booleans);
  1208 }
  1209 
  1210 struct font_driver const haikufont_driver =
  1211   {
  1212     .type = LISPSYM_INITIALLY (Qhaiku),
  1213     .case_sensitive = true,
  1214     .get_cache = haikufont_get_cache,
  1215     .list = haikufont_list,
  1216     .match = haikufont_match,
  1217     .draw = haikufont_draw,
  1218     .open_font = haikufont_open,
  1219     .close_font = haikufont_close,
  1220     .prepare_face = haikufont_prepare_face,
  1221     .encode_char = haikufont_encode_char,
  1222     .text_extents = haikufont_text_extents,
  1223     .shape = haikufont_shape,
  1224     .list_family = haikufont_list_family,
  1225     .filter_properties = haikufont_filter_properties,
  1226   };
  1227 
  1228 static bool
  1229 haikufont_should_quit_popup (void)
  1230 {
  1231   return !NILP (Vquit_flag);
  1232 }
  1233 
  1234 DEFUN ("x-select-font", Fx_select_font, Sx_select_font, 0, 2, 0,
  1235        doc: /* Read a font using a native dialog.
  1236 Return a font spec describing the font chosen by the user.
  1237 
  1238 FRAME is the frame on which to pop up the font chooser.  If omitted or
  1239 nil, it defaults to the selected frame.
  1240 If EXCLUDE-PROPORTIONAL is non-nil, exclude proportional fonts
  1241 in the font selection dialog.  */)
  1242   (Lisp_Object frame, Lisp_Object exclude_proportional)
  1243 {
  1244   struct frame *f;
  1245   struct font *font;
  1246   Lisp_Object font_object;
  1247   haiku_font_family_or_style family, style;
  1248   int rc, size, initial_family, initial_style, initial_size;
  1249   struct haiku_font_pattern pattern;
  1250   Lisp_Object lfamily, lweight, lslant, lwidth, ladstyle, lsize;
  1251   bool disable_antialiasing, initial_antialias;
  1252 
  1253   f = decode_window_system_frame (frame);
  1254 
  1255   if (popup_activated_p)
  1256     error ("Trying to use a menu from within a menu-entry");
  1257 
  1258   initial_style = -1;
  1259   initial_family = -1;
  1260   initial_size = -1;
  1261   initial_antialias = true;
  1262 
  1263   font = FRAME_FONT (f);
  1264 
  1265   if (font)
  1266     {
  1267       XSETFONT (font_object, font);
  1268 
  1269       haikufont_pattern_from_object (&pattern, font_object);
  1270       be_find_font_indices (&pattern, &initial_family,
  1271                             &initial_style);
  1272       haikufont_done_with_query_pattern (&pattern);
  1273 
  1274       initial_size = font->pixel_size;
  1275 
  1276       /* This field is safe to access even after
  1277          haikufont_done_with_query_pattern.  */
  1278       if (pattern.specified & FSPEC_ANTIALIAS)
  1279         initial_antialias = pattern.use_antialiasing;
  1280     }
  1281 
  1282   popup_activated_p++;
  1283   unrequest_sigio ();
  1284   rc = be_select_font (process_pending_signals,
  1285                        haikufont_should_quit_popup,
  1286                        &family, &style, &size,
  1287                        !NILP (exclude_proportional),
  1288                        initial_family, initial_style,
  1289                        initial_size, initial_antialias,
  1290                        &disable_antialiasing);
  1291   request_sigio ();
  1292   popup_activated_p--;
  1293 
  1294   if (!rc)
  1295     quit ();
  1296 
  1297   be_font_style_to_flags (style, &pattern);
  1298 
  1299   lfamily = build_string_from_utf8 (family);
  1300   lweight = (pattern.specified & FSPEC_WEIGHT
  1301              ? haikufont_weight_to_lisp (pattern.weight) : Qnil);
  1302   lslant = (pattern.specified & FSPEC_SLANT
  1303             ? haikufont_slant_to_lisp (pattern.slant) : Qnil);
  1304   lwidth = (pattern.specified & FSPEC_WIDTH
  1305             ? haikufont_width_to_lisp (pattern.width) : Qnil);
  1306   ladstyle = (pattern.specified & FSPEC_STYLE
  1307               ? intern (pattern.style) : Qnil);
  1308   lsize = (size >= 0 ? make_fixnum (size) : Qnil);
  1309 
  1310   if (disable_antialiasing)
  1311     return CALLN (Ffont_spec, QCfamily, lfamily,
  1312                   QCweight, lweight, QCslant, lslant,
  1313                   QCwidth, lwidth, QCadstyle, ladstyle,
  1314                   QCsize, lsize, QCantialias, Qnil);
  1315 
  1316   return CALLN (Ffont_spec, QCfamily, lfamily,
  1317                 QCweight, lweight, QCslant, lslant,
  1318                 QCwidth, lwidth, QCadstyle, ladstyle,
  1319                 QCsize, lsize);
  1320 }
  1321 
  1322 DEFUN ("font-get-system-normal-font", Ffont_get_system_normal_font,
  1323        Sfont_get_system_normal_font, 0, 0, 0,
  1324        doc: /* SKIP: real doc in xsettings.c.  */)
  1325   (void)
  1326 {
  1327   Lisp_Object value;
  1328   const char *name, *style;
  1329   struct haiku_font_pattern pattern;
  1330   Lisp_Object lfamily, lweight, lslant, lwidth, ladstyle;
  1331   int size;
  1332 
  1333   if (!be_lock_font_defaults ())
  1334     return Qnil;
  1335 
  1336   name = be_get_font_default (DEFAULT_FAMILY);
  1337   style = be_get_font_default (DEFAULT_STYLE);
  1338   size = be_get_font_size (DEFAULT_FAMILY);
  1339 
  1340   be_font_style_to_flags (style, &pattern);
  1341 
  1342   lfamily = build_string_from_utf8 (name);
  1343   lweight = (pattern.specified & FSPEC_WEIGHT
  1344              ? haikufont_weight_to_lisp (pattern.weight) : Qnil);
  1345   lslant = (pattern.specified & FSPEC_SLANT
  1346             ? haikufont_slant_to_lisp (pattern.slant) : Qnil);
  1347   lwidth = (pattern.specified & FSPEC_WIDTH
  1348             ? haikufont_width_to_lisp (pattern.width) : Qnil);
  1349   ladstyle = (pattern.specified & FSPEC_STYLE
  1350               ? intern (pattern.style) : Qnil);
  1351 
  1352   value = CALLN (Ffont_spec, QCfamily, lfamily,
  1353                  QCweight, lweight, QCslant, lslant,
  1354                  QCwidth, lwidth, QCadstyle, ladstyle,
  1355                  QCsize, make_fixnum (size));
  1356   be_unlock_font_defaults ();
  1357 
  1358   return value;
  1359 }
  1360 
  1361 DEFUN ("font-get-system-font", Ffont_get_system_font,
  1362        Sfont_get_system_font, 0, 0, 0,
  1363        doc: /* SKIP: real doc in xsettings.c.  */)
  1364   (void)
  1365 {
  1366   Lisp_Object value;
  1367   const char *name, *style;
  1368   struct haiku_font_pattern pattern;
  1369   Lisp_Object lfamily, lweight, lslant, lwidth, ladstyle;
  1370   int size;
  1371 
  1372   if (!be_lock_font_defaults ())
  1373     return Qnil;
  1374 
  1375   name = be_get_font_default (FIXED_FAMILY);
  1376   style = be_get_font_default (FIXED_STYLE);
  1377   size = be_get_font_size (FIXED_FAMILY);
  1378 
  1379   be_font_style_to_flags (style, &pattern);
  1380 
  1381   lfamily = build_string_from_utf8 (name);
  1382   lweight = (pattern.specified & FSPEC_WEIGHT
  1383              ? haikufont_weight_to_lisp (pattern.weight) : Qnil);
  1384   lslant = (pattern.specified & FSPEC_SLANT
  1385             ? haikufont_slant_to_lisp (pattern.slant) : Qnil);
  1386   lwidth = (pattern.specified & FSPEC_WIDTH
  1387             ? haikufont_width_to_lisp (pattern.width) : Qnil);
  1388   ladstyle = (pattern.specified & FSPEC_STYLE
  1389               ? intern (pattern.style) : Qnil);
  1390 
  1391   value = CALLN (Ffont_spec, QCfamily, lfamily,
  1392                  QCweight, lweight, QCslant, lslant,
  1393                  QCwidth, lwidth, QCadstyle, ladstyle,
  1394                  QCsize, make_fixnum (size));
  1395   be_unlock_font_defaults ();
  1396 
  1397   return value;
  1398 }
  1399 
  1400 void
  1401 haiku_handle_font_change_event (struct haiku_font_change_event *event,
  1402                                 struct input_event *ie)
  1403 {
  1404   ie->kind = CONFIG_CHANGED_EVENT;
  1405 
  1406   /* This is the name of the display.  */
  1407   ie->frame_or_window = XCAR (x_display_list->name_list_element);
  1408 
  1409   /* And this is the font that changed.  */
  1410   ie->arg = (event->what == FIXED_FAMILY
  1411              ? Qmonospace_font_name : Qfont_name);
  1412 }
  1413 
  1414 static void
  1415 syms_of_haikufont_for_pdumper (void)
  1416 {
  1417   register_font_driver (&haikufont_driver, NULL);
  1418 }
  1419 
  1420 void
  1421 syms_of_haikufont (void)
  1422 {
  1423   DEFSYM (QSans_Serif, "Sans Serif");
  1424   DEFSYM (Qfontsize, "fontsize");
  1425   DEFSYM (Qfixed, "fixed");
  1426   DEFSYM (Qplain, "plain");
  1427   DEFSYM (Qultra_light, "ultra-light");
  1428   DEFSYM (Qthin, "thin");
  1429   DEFSYM (Qreverse_italic, "reverse-italic");
  1430   DEFSYM (Qreverse_oblique, "reverse-oblique");
  1431   DEFSYM (Qmonospace, "monospace");
  1432   DEFSYM (Qultra_condensed, "ultra-condensed");
  1433   DEFSYM (Qextra_condensed, "extra-condensed");
  1434   DEFSYM (Qcondensed, "condensed");
  1435   DEFSYM (Qsemi_condensed, "semi-condensed");
  1436   DEFSYM (Qsemi_expanded, "semi-expanded");
  1437   DEFSYM (Qexpanded, "expanded");
  1438   DEFSYM (Qextra_expanded, "extra-expanded");
  1439   DEFSYM (Qultra_expanded, "ultra-expanded");
  1440   DEFSYM (Qregular, "regular");
  1441   DEFSYM (Qzh, "zh");
  1442   DEFSYM (Qko, "ko");
  1443   DEFSYM (Qjp, "jp");
  1444 
  1445   DEFSYM (QCindices, ":indices");
  1446 
  1447   DEFSYM (Qmonospace_font_name, "monospace-font-name");
  1448   DEFSYM (Qfont_name, "font-name");
  1449   DEFSYM (Qdynamic_setting, "dynamic-setting");
  1450 
  1451   DEFVAR_BOOL ("font-use-system-font", use_system_font,
  1452     doc: /* SKIP: real doc in xsettings.c.  */);
  1453   use_system_font = false;
  1454 
  1455 #ifdef USE_BE_CAIRO
  1456   Fput (Qhaiku, Qfont_driver_superseded_by, Qftcr);
  1457 #endif
  1458   pdumper_do_now_and_after_load (syms_of_haikufont_for_pdumper);
  1459 
  1460   font_cache = list (Qnil);
  1461   staticpro (&font_cache);
  1462 
  1463   defsubr (&Sx_select_font);
  1464   defsubr (&Sfont_get_system_normal_font);
  1465   defsubr (&Sfont_get_system_font);
  1466 
  1467   be_init_font_data ();
  1468 
  1469   /* This tells loadup to load dynamic-setting.el, which handles
  1470      config-changed events.  */
  1471   Fprovide (Qdynamic_setting, Qnil);
  1472 }

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