1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2025-01-01 11:14:55 +00:00

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.
This commit is contained in:
Po Lu 2022-05-05 09:46:05 +00:00
parent 30caeb7896
commit 1468eef301
4 changed files with 183 additions and 47 deletions

View File

@ -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. */

View File

@ -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); */

View File

@ -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 *);

View File

@ -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 (BFont_open_pattern (&ptn, &be_font, x))
/* 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 (!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,