From 55ac90d9647c5e27aec8f93796d79be21167a856 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Tue, 17 Jan 2023 19:48:42 +0100 Subject: libfonts_do_decoded_font_descriptions_match: check charset subset coverage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- libfonts.h | 2 +- libfonts_do_decoded_font_descriptions_match.c | 67 ++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/libfonts.h b/libfonts.h index 11e4ea4..e20152f 100644 --- a/libfonts.h +++ b/libfonts.h @@ -1625,7 +1625,7 @@ struct libfonts_font_description { * inclusive ranges included the subset. A range will either be a * decimal integer, or an two decimal integers separated by a "-" * (the left-hand side will be strictly less than the right-hand side). - * All ranges will be disjunction, and have a non-zero distance. + * All ranges will be disjunctive, and have a non-zero distance. * * The library will take care of converting hexadecimal numbers (prefixed * with "0x") to decimal, removing leading zeroes, converting "_" to "-", diff --git a/libfonts_do_decoded_font_descriptions_match.c b/libfonts_do_decoded_font_descriptions_match.c index 776ca4f..a6b0fb9 100644 --- a/libfonts_do_decoded_font_descriptions_match.c +++ b/libfonts_do_decoded_font_descriptions_match.c @@ -19,9 +19,74 @@ X(average_width, equal) _\ X(charset_registry, equal) _\ X(charset_encoding, equal) _\ - X(charset_subset, equal) /* TODO desc shall match spec if spec is a subset of desc */ + X(charset_subset, super) +static const char * +read_uint32(uint32_t *restrict nump, const char *s) +{ + uint32_t r; + for (r = 0; isdigit(*s); s++) + r = r * 10 + (uint32_t)(*s & 15); + *nump = r; + return s; +} + +static int +super(const char *desc, const char *spec) +{ + uint32_t dl = 0, dh = 0, sl = 0, sh = 0; + int have_d = 0, have_s = 0; + + if (!spec || !desc) + return 1; + + while (*desc && *spec) { + if (!have_d) { + have_d = 1; + if (!isdigit(*desc)) + return 0; + desc = read_uint32(&dl, desc); + if (desc[0] == '-' && isdigit(desc[1])) + desc = read_uint32(&dh, desc); + else + dh = dl; + if (*desc) { + if (*desc != ' ') + return 0; + desc++; + } + } + + if (!have_s) { + have_s = 1; + if (!isdigit(*spec)) + return 0; + spec = read_uint32(&sl, spec); + if (spec[0] == '-' && isdigit(spec[1])) + spec = read_uint32(&sh, spec); + else + sh = sl; + if (*spec) { + if (*spec != ' ') + return 0; + spec++; + } + } + + if (sl < dl) + return 0; + else if (sl > dh) + have_d = 0; + else if (sh > dh) + return 0; + else + have_s = 0; + } + + return !*spec; +} + static int equal(const char *desc, const char *spec) { -- cgit v1.2.3-70-g09d2