emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 1468eef301: Speed up opening fonts on Haiku


From: Po Lu
Subject: master 1468eef301: Speed up opening fonts on Haiku
Date: Thu, 5 May 2022 05:46:43 -0400 (EDT)

branch: master
commit 1468eef301a59346adc47ef19a740f4e2c3737a2
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Speed up opening fonts on Haiku
    
    * src/font.h (font_property_index): Note that some font drivers
    use the extra data in a font entity to store driver-specific
    information.
    
    * src/haiku_font_support.cc (BFont_find): Set font indices.
    (be_open_font_at_index): New function.
    (BFont_open_pattern): Clean up coding style.
    * src/haiku_support.h (enum haiku_font_specification)
    (struct haiku_font_pattern): New fields and specifications for
    indices.
    * src/haikufont.c (haikufont_pattern_to_entity, haikufont_open):
    Use indices to open fonts if available in the extra data.
---
 src/font.h                |   5 +-
 src/haiku_font_support.cc | 118 +++++++++++++++++++++++++++++++++++-----------
 src/haiku_support.h       |  48 +++++++++++++++++--
 src/haikufont.c           |  59 ++++++++++++++++++-----
 4 files changed, 183 insertions(+), 47 deletions(-)

diff --git a/src/font.h b/src/font.h
index 424616a4a1..06bd297ccb 100644
--- a/src/font.h
+++ b/src/font.h
@@ -155,8 +155,9 @@ enum font_property_index
     /* In a font-spec, the value is an alist of extra information of a
        font such as name, OpenType features, and language coverage.
        In addition, in a font-entity, the value may contain a pair
-       (font-entity . INFO) where INFO is extra information to identify
-       a font (font-driver dependent).  */
+       (font-entity . INFO) where INFO is extra information to
+       identify a font (font-driver dependent).  In a font-entity,
+       this holds font driver-specific information.  */
     FONT_EXTRA_INDEX,          /* alist                alist */
 
     /* This value is the length of font-spec vector.  */
diff --git a/src/haiku_font_support.cc b/src/haiku_font_support.cc
index 339634f01b..ca6aaf7120 100644
--- a/src/haiku_font_support.cc
+++ b/src/haiku_font_support.cc
@@ -574,18 +574,21 @@ BFont_find (struct haiku_font_pattern *pt)
   font_family name;
   font_style sname;
   uint32 flags;
-  int sty_count;
-  int fam_count = count_font_families ();
+  int sty_count, fam_count, si, fi;
+  struct haiku_font_pattern *p, *head, *n;
+  bool oblique_seen_p;
 
-  for (int fi = 0; fi < fam_count; ++fi)
+  fam_count = count_font_families ();
+
+  for (fi = 0; fi < fam_count; ++fi)
     {
       if (get_font_family (fi, &name, &flags) == B_OK)
        {
          sty_count = count_font_styles (name);
-         if (!sty_count &&
-             font_family_style_matches_p (name, NULL, flags, pt))
+         if (!sty_count
+             && font_family_style_matches_p (name, NULL, flags, pt))
            {
-             struct haiku_font_pattern *p = new struct haiku_font_pattern;
+             p = new struct haiku_font_pattern;
              p->specified = 0;
              p->oblique_seen_p = 1;
              haiku_font_fill_pattern (p, name, NULL, flags);
@@ -598,11 +601,11 @@ BFont_find (struct haiku_font_pattern *pt)
            }
          else if (sty_count)
            {
-             for (int si = 0; si < sty_count; ++si)
+             for (si = 0; si < sty_count; ++si)
                {
-                 int oblique_seen_p = 0;
-                 struct haiku_font_pattern *head = r;
-                 struct haiku_font_pattern *p = NULL;
+                 oblique_seen_p = 0;
+                 head = r;
+                 p = NULL;
 
                  if (get_font_style (name, si, &sname, &flags) == B_OK)
                    {
@@ -611,8 +614,18 @@ BFont_find (struct haiku_font_pattern *pt)
                          p = new struct haiku_font_pattern;
                          p->specified = 0;
                          haiku_font_fill_pattern (p, name, (char *) &sname, 
flags);
-                         if (p->specified & FSPEC_SLANT &&
-                             ((p->slant == SLANT_OBLIQUE) || (p->slant == 
SLANT_ITALIC)))
+
+                         /* Add the indices to this font now so we
+                            won't have to loop over each font in
+                            order to open it later.  */
+
+                         p->specified |= FSPEC_INDICES;
+                         p->family_index = fi;
+                         p->style_index = si;
+
+                         if (p->specified & FSPEC_SLANT
+                             && (p->slant == SLANT_OBLIQUE
+                                 || p->slant == SLANT_ITALIC))
                            oblique_seen_p = 1;
 
                          p->next = r;
@@ -627,9 +640,7 @@ BFont_find (struct haiku_font_pattern *pt)
                    p->last = NULL;
 
                  for (; head; head = head->last)
-                   {
-                     head->oblique_seen_p = oblique_seen_p;
-                   }
+                   head->oblique_seen_p = oblique_seen_p;
                }
            }
        }
@@ -642,13 +653,18 @@ BFont_find (struct haiku_font_pattern *pt)
   if (!(pt->specified & FSPEC_SLANT))
     {
       /* r->last is invalid from here onwards.  */
-      for (struct haiku_font_pattern *p = r; p;)
+      for (p = r; p;)
        {
          if (!p->oblique_seen_p)
            {
-             struct haiku_font_pattern *n = new haiku_font_pattern;
+             n = new haiku_font_pattern;
              *n = *p;
+
              n->slant = SLANT_OBLIQUE;
+
+             /* Opening a font by its indices doesn't provide enough
+                information to synthesize the oblique font later.  */
+             n->specified &= ~FSPEC_INDICES;
              p->next = n;
              p = p->next_family;
            }
@@ -660,26 +676,68 @@ BFont_find (struct haiku_font_pattern *pt)
   return r;
 }
 
+/* Find and open a font with the family at FAMILY and the style at
+   STYLE, and set its size to SIZE.  Value is NULL if opening the font
+   failed.  */
+void *
+be_open_font_at_index (int family, int style, float size)
+{
+  font_family family_name;
+  font_style style_name;
+  uint32 flags;
+  status_t rc;
+  BFont *font;
+
+  rc = get_font_family (family, &family_name, &flags);
+
+  if (rc != B_OK)
+    return NULL;
+
+  rc = get_font_style (family_name, style, &style_name, &flags);
+
+  if (rc != B_OK)
+    return NULL;
+
+  font = new BFont;
+
+  rc = font->SetFamilyAndStyle (family_name, style_name);
+
+  if (rc != B_OK)
+    {
+      delete font;
+      return NULL;
+    }
+
+  font->SetSize (size);
+  font->SetEncoding (B_UNICODE_UTF8);
+  font->SetSpacing (B_BITMAP_SPACING);
+  return font;
+}
+
 /* Find and open a font matching the pattern PAT, which must have its
    family set.  */
 int
 BFont_open_pattern (struct haiku_font_pattern *pat, void **font, float size)
 {
-  int sty_count;
+  int sty_count, si, code;
   font_family name;
   font_style sname;
+  BFont *ft;
   uint32 flags = 0;
+  struct haiku_font_pattern copy;
+
   if (!(pat->specified & FSPEC_FAMILY))
     return 1;
+
   strncpy (name, pat->family, sizeof name - 1);
   name[sizeof name - 1] = '\0';
 
   sty_count = count_font_styles (name);
 
-  if (!sty_count &&
-      font_family_style_matches_p (name, NULL, flags, pat, 1))
+  if (!sty_count
+      && font_family_style_matches_p (name, NULL, flags, pat, 1))
     {
-      BFont *ft = new BFont;
+      ft = new BFont;
       ft->SetSize (size);
       ft->SetEncoding (B_UNICODE_UTF8);
       ft->SetSpacing (B_BITMAP_SPACING);
@@ -694,12 +752,13 @@ BFont_open_pattern (struct haiku_font_pattern *pat, void 
**font, float size)
     }
   else if (sty_count)
     {
-      for (int si = 0; si < sty_count; ++si)
+      for (si = 0; si < sty_count; ++si)
        {
-         if (get_font_style (name, si, &sname, &flags) == B_OK &&
-             font_family_style_matches_p (name, (char *) &sname, flags, pat))
+         if (get_font_style (name, si, &sname, &flags) == B_OK
+             && font_family_style_matches_p (name, (char *) &sname,
+                                             flags, pat))
            {
-             BFont *ft = new BFont;
+             ft = new BFont;
              ft->SetSize (size);
              ft->SetEncoding (B_UNICODE_UTF8);
              ft->SetSpacing (B_BITMAP_SPACING);
@@ -709,6 +768,7 @@ BFont_open_pattern (struct haiku_font_pattern *pat, void 
**font, float size)
                  delete ft;
                  return 1;
                }
+
              *font = (void *) ft;
              return 0;
            }
@@ -717,12 +777,14 @@ BFont_open_pattern (struct haiku_font_pattern *pat, void 
**font, float size)
 
   if (pat->specified & FSPEC_SLANT && pat->slant == SLANT_OBLIQUE)
     {
-      struct haiku_font_pattern copy = *pat;
+      copy = *pat;
       copy.slant = SLANT_REGULAR;
-      int code = BFont_open_pattern (&copy, font, size);
+      code = BFont_open_pattern (&copy, font, size);
+
       if (code)
        return code;
-      BFont *ft = (BFont *) *font;
+
+      ft = (BFont *) *font;
       /* XXX Font measurements don't respect shear.  Haiku bug?
         This apparently worked in BeOS.
         ft->SetShear (100.0); */
diff --git a/src/haiku_support.h b/src/haiku_support.h
index 63ba726050..0fe2af3329 100644
--- a/src/haiku_support.h
+++ b/src/haiku_support.h
@@ -246,6 +246,7 @@ enum haiku_font_specification
     FSPEC_NEED_ONE_OF = 1 << 6,
     FSPEC_WIDTH              = 1 << 7,
     FSPEC_LANGUAGE    = 1 << 8,
+    FSPEC_INDICES     = 1 << 9,
   };
 
 typedef char haiku_font_family_or_style[64];
@@ -300,25 +301,61 @@ enum haiku_font_weight
 
 struct haiku_font_pattern
 {
+  /* Bitmask indicating which fields are set.  */
   int specified;
+
+  /* The next font in this list.  */
   struct haiku_font_pattern *next;
-  /* The next two fields are only temporarily used during the font
-     discovery process! Do not rely on them being correct outside
-     BFont_find.  */
+
+  /* The last font in the list during font lookup.  */
   struct haiku_font_pattern *last;
+
+  /* The next font in the list whose family differs from this one.
+     Only valid during font lookup.  */
   struct haiku_font_pattern *next_family;
+
+  /* The family of the font.  */
   haiku_font_family_or_style family;
+
+  /* The style of the font.  */
   haiku_font_family_or_style style;
+
+  /* Whether or the font is monospace.  */
   int mono_spacing_p;
-  int want_chars_len;
-  int need_one_of_len;
+
+  /* The slant of the font.  */
   enum haiku_font_slant slant;
+
+  /* The width of the font.  */
   enum haiku_font_width width;
+
+  /* The language of the font.  Used during font lookup.  */
   enum haiku_font_language language;
+
+  /* The weight of the font.  */
   enum haiku_font_weight weight;
+
+  /* List of characters that must be present in the font for the match
+     to succeed.  */
   int *wanted_chars;
+
+  /* The number of characters in `wanted_chars'.  */
+  int want_chars_len;
+
+  /* List of characters.  The font must fullfill at least one of
+     them for the match to succeed.  */
   int *need_one_of;
 
+  /* The number of characters in `need_one_of'.  */
+  int need_one_of_len;
+
+  /* The index of the family of the font this pattern represents.  */
+  int family_index;
+
+  /* The index of the style of the font this pattern represents.  */
+  int style_index;
+
+  /* Temporary field used during font enumeration.  */
   int oblique_seen_p;
 };
 
@@ -635,6 +672,7 @@ extern bool be_use_subpixel_antialiasing (void);
 extern const char *be_find_setting (const char *);
 extern haiku_font_family_or_style *be_list_font_families (size_t *);
 extern void be_font_style_to_flags (char *, struct haiku_font_pattern *);
+extern void *be_open_font_at_index (int, int, float);
 extern int be_get_ui_color (const char *, uint32_t *);
 
 extern void BMessage_delete (void *);
diff --git a/src/haikufont.c b/src/haikufont.c
index d18c1a393a..f8cf45284d 100644
--- a/src/haikufont.c
+++ b/src/haikufont.c
@@ -381,7 +381,9 @@ haikufont_maybe_handle_special_family (Lisp_Object family,
 static Lisp_Object
 haikufont_pattern_to_entity (struct haiku_font_pattern *ptn)
 {
-  Lisp_Object ent = font_make_entity ();
+  Lisp_Object ent;
+
+  ent = font_make_entity ();
   ASET (ent, FONT_TYPE_INDEX, Qhaiku);
   ASET (ent, FONT_FOUNDRY_INDEX, Qhaiku);
   ASET (ent, FONT_FAMILY_INDEX, Qdefault);
@@ -390,6 +392,14 @@ haikufont_pattern_to_entity (struct haiku_font_pattern 
*ptn)
   ASET (ent, FONT_SIZE_INDEX, make_fixnum (0));
   ASET (ent, FONT_AVGWIDTH_INDEX, make_fixnum (0));
   ASET (ent, FONT_SPACING_INDEX, make_fixnum (FONT_SPACING_MONO));
+
+  /* FONT_EXTRA_INDEX in a font entity can be a cons of two numbers
+     (STYLE . IDX) that tell Emacs how to open a font.  */
+  if (ptn->specified & FSPEC_INDICES)
+    ASET (ent, FONT_EXTRA_INDEX,
+         Fcons (make_fixnum (ptn->family_index),
+                make_fixnum (ptn->style_index)));
+
   FONT_SET_STYLE (ent, FONT_WIDTH_INDEX, Qnormal);
   FONT_SET_STYLE (ent, FONT_WEIGHT_INDEX, Qnormal);
   FONT_SET_STYLE (ent, FONT_SLANT_INDEX, Qnormal);
@@ -722,10 +732,11 @@ haikufont_open (struct frame *f, Lisp_Object font_entity, 
int x)
   struct haiku_font_pattern ptn;
   struct font *font;
   void *be_font;
-  Lisp_Object font_object;
-  Lisp_Object tem;
+  Lisp_Object font_object, tem, extra;
+  int px_size, min_width, max_width,
+    avg_width, height, space_width, ascent,
+    descent, underline_pos, underline_thickness;
 
-  block_input ();
   if (x <= 0)
     {
       /* Get pixel size from frame instead.  */
@@ -733,19 +744,47 @@ haikufont_open (struct frame *f, Lisp_Object font_entity, 
int x)
       x = NILP (tem) ? 0 : XFIXNAT (tem);
     }
 
-  haikufont_spec_or_entity_to_pattern (font_entity, 1, &ptn);
+  extra = AREF (font_entity, FONT_EXTRA_INDEX);
+
+  /* If the font's indices is already available, open the font using
+     those instead.  */
+
+  if (CONSP (extra) && FIXNUMP (XCAR (extra))
+      && FIXNUMP (XCDR (extra)))
+    {
+      block_input ();
+      be_font = be_open_font_at_index (XFIXNUM (XCAR (extra)),
+                                      XFIXNUM (XCDR (extra)), x);
+      unblock_input ();
 
-  if (BFont_open_pattern (&ptn, &be_font, x))
+      if (!be_font)
+       return Qnil;
+    }
+  else
     {
+      block_input ();
+      haikufont_spec_or_entity_to_pattern (font_entity, 1, &ptn);
+
+      if (BFont_open_pattern (&ptn, &be_font, x))
+       {
+         haikufont_done_with_query_pattern (&ptn);
+         unblock_input ();
+         return Qnil;
+       }
+
       haikufont_done_with_query_pattern (&ptn);
       unblock_input ();
-      return Qnil;
     }
 
-  haikufont_done_with_query_pattern (&ptn);
+  block_input ();
 
+  /* `font_make_object' tries to treat the extra data as an alist.
+     There is never any real data here, so clear that field.  */
+
+  ASET (font_entity, FONT_EXTRA_INDEX, Qnil);
   font_object = font_make_object (VECSIZE (struct haikufont_info),
                                  font_entity, x);
+  ASET (font_entity, FONT_EXTRA_INDEX, extra);
 
   ASET (font_object, FONT_TYPE_INDEX, Qhaiku);
   font_info = (struct haikufont_info *) XFONT_OBJECT (font_object);
@@ -772,10 +811,6 @@ haikufont_open (struct frame *f, Lisp_Object font_entity, 
int x)
   font_info->metrics = NULL;
   font_info->metrics_nrows = 0;
 
-  int px_size, min_width, max_width,
-    avg_width, height, space_width, ascent,
-    descent, underline_pos, underline_thickness;
-
   BFont_metrics (be_font, &px_size, &min_width,
                 &max_width, &avg_width, &height,
                 &space_width, &ascent, &descent,



reply via email to

[Prev in Thread] Current Thread [Next in Thread]