summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2022-05-05 09:46:05 +0000
committerPo Lu <luangruo@yahoo.com>2022-05-05 09:46:05 +0000
commit1468eef301a59346adc47ef19a740f4e2c3737a2 (patch)
treeee16c08d185100385231849da505310cf6e9ff5e
parent30caeb789659441f8feb76b24f3d0b1f60125085 (diff)
downloademacs-1468eef301a59346adc47ef19a740f4e2c3737a2.tar.gz
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.
-rw-r--r--src/font.h5
-rw-r--r--src/haiku_font_support.cc118
-rw-r--r--src/haiku_support.h48
-rw-r--r--src/haikufont.c59
4 files changed, 183 insertions, 47 deletions
diff --git a/src/font.h b/src/font.h
index 424616a4a1e..06bd297ccb2 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 339634f01be..ca6aaf71204 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 63ba7260506..0fe2af3329a 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 d18c1a393a0..f8cf45284d0 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,