Properly sort results for partial font specs

* src/sfntfont.c (sfntfont_compare_font_entities): New function.
(sfntfont_list): Sort matching font entities by the number of
fields set, and mention why.
This commit is contained in:
Po Lu 2024-01-13 09:51:59 +08:00
parent 8b7a6d7b6d
commit 4edb77132d

View file

@ -1939,13 +1939,51 @@ sfntfont_desc_to_entity (struct sfnt_font_desc *desc, int instance)
return entity;
}
/* Return whether fewer fields inside the font entity A are set than
there are set inside the font entity B. */
static Lisp_Object
sfntfont_compare_font_entities (Lisp_Object a, Lisp_Object b)
{
ptrdiff_t count_a, count_b, i;
count_a = 0;
count_b = 0;
for (i = 0; i < FONT_ENTITY_MAX; ++i)
{
if (!NILP (AREF (a, i)))
count_a++;
}
for (i = 0; i < FONT_ENTITY_MAX; ++i)
{
if (!NILP (AREF (b, i)))
count_b++;
}
return count_a < count_b ? Qt : Qnil;
}
/* Function that compares two font entities to return whether fewer
fields are set within the first than in the second. */
static union Aligned_Lisp_Subr Scompare_font_entities =
{
{
{ PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS), },
{ .a2 = sfntfont_compare_font_entities, },
2, 2, "sfntfont_compare_font_entities", {0}, lisp_h_Qnil,
},
};
/* Return a list of font-entities matching the specified
FONT_SPEC. */
Lisp_Object
sfntfont_list (struct frame *f, Lisp_Object font_spec)
{
Lisp_Object matching, tem;
Lisp_Object matching, tem, compare_font_entities;
struct sfnt_font_desc *desc;
int i, rc, instances[100];
@ -1982,9 +2020,16 @@ sfntfont_list (struct frame *f, Lisp_Object font_spec)
matching);
}
}
unblock_input ();
/* Sort matching by the number of fields set inside each element, so
that values of FONT_SPECs that leave a number of fields
unspecified will yield a list with the closest matches (that is
to say, those whose fields are precisely as specified by the
caller) ordered first. */
XSETSUBR (compare_font_entities, &Scompare_font_entities.s);
matching = Fsort (matching, compare_font_entities);
return matching;
}