From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: =?utf-8?Q?K=C3=A9vin_Le_Gouguec?= Newsgroups: gmane.emacs.devel Subject: Re: Order of fonts returned by list-fonts Date: Sun, 09 Jan 2022 20:43:49 +0100 Message-ID: <87ilusitje.fsf@gmail.com> References: <87r19hhm0f.fsf@gmail.com> <83o84kajzk.fsf@gnu.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="35023"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) Cc: emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sun Jan 09 20:45:44 2022 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1n6e8N-0008uQ-PQ for ged-emacs-devel@m.gmane-mx.org; Sun, 09 Jan 2022 20:45:43 +0100 Original-Received: from localhost ([::1]:49548 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1n6e8M-000396-JA for ged-emacs-devel@m.gmane-mx.org; Sun, 09 Jan 2022 14:45:42 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:60022) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1n6e6e-0001y0-HU for emacs-devel@gnu.org; Sun, 09 Jan 2022 14:43:56 -0500 Original-Received: from [2a00:1450:4864:20::42e] (port=40571 helo=mail-wr1-x42e.google.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1n6e6c-0002EK-85; Sun, 09 Jan 2022 14:43:56 -0500 Original-Received: by mail-wr1-x42e.google.com with SMTP id l10so22821635wrh.7; Sun, 09 Jan 2022 11:43:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version; bh=Iu7gMeVRU3LxFwPnFgvrKaja9CEb6zWEWwFoG2aBie4=; b=mUNuJcsWltTh47H/H/tFzrtgsGYheofO4SnKhoxeN1zWfsmRBXKFvTpEorsLxKy4x8 T7Li9WnEIR9My5wfSJ4SHMe5fgO4pORLyiH8Ivh/+n1WyPeoZSMQm1+PRjN7VqDxKAQp lrA8wMCXIKrnhzOVOn1Vh7xlgXrcSZNac+7541IwFAbKGiXudb6J6kRIgwGC2t0tg6H3 ckSzc8KfCEnODp94iFweVhiC3co/yvpE8TlXLd4lKUwSdao8TBSrqlEGF4ZPJ3CGkVY+ L3El74862FQTuQwvgh1BnFjqYbgYI+lPDxuxlBRTn3OC2Rda5TgBvtDiCo6Elw8hireY vCqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version; bh=Iu7gMeVRU3LxFwPnFgvrKaja9CEb6zWEWwFoG2aBie4=; b=Qvb3iSs4Ssy0/LJ2/xQ0jmsnU0SniLfC/t65gjhECJNZPDRfRK3kX0TqLVAJKkw5b8 zW8b32J/xFonnCKE20rTodncCSBJABSJJk8+bOi35kHu6i8UIjbiC9DCUhvhlO8IViGW lWLnWqFE3oNPhLSIEsG+uvm1Ec7sZUUzqYI/J9Gzc49P7w3vUmudVMpyMFHX7lic5OMn lIIExVvySRS8OV+aglgKhVpfntuxL7xnsbMV8n3z25/0y91yknm/K4bc8pMQkDGiiGaD 5pKJ9MP7Ai0fIFAbFKGVllwu8rDbDjSHdfQ+orQO0SrwiBLRfA27s545uUyq+wjCGWaw hIRA== X-Gm-Message-State: AOAM530Qt1Iqokk+pfkinMYsTp4SR3fAcpEBJ37wMx538HJD88MbrWdH 2C+m6buof/oAHh7CFrd2cwekOomuc/c= X-Google-Smtp-Source: ABdhPJyR+mNKoHnbQ6r0Sa7qKC+Ss+/FJuKHkBjAjpFZjOHvbM9oc4TL9e+D9DqcnJDtynEse3q28g== X-Received: by 2002:a05:6000:1846:: with SMTP id c6mr13553324wri.658.1641757431531; Sun, 09 Jan 2022 11:43:51 -0800 (PST) Original-Received: from amdahl30 ([2a01:e0a:253:fe0:2ef0:5dff:fed2:7b49]) by smtp.gmail.com with ESMTPSA id v1sm5714582wru.45.2022.01.09.11.43.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 09 Jan 2022 11:43:50 -0800 (PST) In-Reply-To: <83o84kajzk.fsf@gnu.org> (Eli Zaretskii's message of "Sun, 09 Jan 2022 19:37:19 +0200") X-Host-Lookup-Failed: Reverse DNS lookup failed for 2a00:1450:4864:20::42e (failed) Received-SPF: pass client-ip=2a00:1450:4864:20::42e; envelope-from=kevin.legouguec@gmail.com; helo=mail-wr1-x42e.google.com X-Spam_score_int: -12 X-Spam_score: -1.3 X-Spam_bar: - X-Spam_report: (-1.3 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:284507 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Eli Zaretskii writes: > This list is not the right place for discussions where you question > the correctness of low-level font-handling code in Emacs. Please > consider moving this to emacs-devel. Thanks, I'll try to tune my list-picking heuristic (it's pretty hairy, but I think the fault lies in the bit that says "unsure if bug or not =E2= =87=92 help-gnu-emacs"). >> My distro ships with Noto Color Emoji 13.1. I have installed version 14 >> under ~/.local/share/fonts. fc-match seems to prioritize the latter: >>=20 >> $ fc-match -f '%{fullname} %{file}\n' "Noto Color Emoji" >> > Noto Color Emoji /home/peniblec/.local/share/fonts/NotoColorEmoji.ttf >>=20 >> Emacs, however, seems to favour the former: >>=20 >> (find-font (font-spec :family "Noto Color Emoji")) >> > #> > normal normal 0 nil 100 0 ((:font-entity >> > "/usr/share/fonts/truetype/NotoColorEmoji.ttf" . 0))> >>=20 >> (list-fonts (font-spec :family "Noto Color Emoji")) >> > (#> > normal normal 0 nil 100 0 ((:font-entity >> > "/usr/share/fonts/truetype/NotoColorEmoji.ttf" . 0))>=20 >> > #> > normal normal 0 nil 100 0 ((:font-entity >> > "/home/peniblec/.local/share/fonts/NotoColorEmoji.ttf" . 0))>) >>=20 >> Could this be considered a bug? I didn't dig into the code yet, beside >> looking at font_list_entities (which led me to restart with >> EMACS_FONT_LOG set; unfortunately font-show-log doesn't have much to say >> about how font files are searched). > > As you've probably seen, font_list_entities calls the font driver's > 'list' method, and then reverses the resulting list. That is supposed > to produce the list of fonts in the same order in which the font > driver lists the fonts. Does that mean that Fontconfig produces > matching fonts with the best/newest/user-local one the last? (Mmm. Each time I've seen an nreverse (specifically, at the end of font_list_entities and ftfont_list), I've assumed it was because we had just iterated over something and accumulated results by Fcons'ing an item with an accumulator, so we had "inverted" the order of the thing we were iterating on, and nreverse restored the "original" order) > Does that mean that Fontconfig produces > matching fonts with the best/newest/user-local one the last? I haven't fully figured out what Fontconfig does nor why yet; I'm currently comparing what ftfont_list does vs. what fc-match does; the latter's code is somewhat straightforward: https://gitlab.freedesktop.org/fontconfig/fontconfig/-/raw/main/fc-match/fc= -match.c AFAICT (trying to keep it simple and high-level; apologies if I'm eliding important stuff, or if I've overlooked something), - fc-match.c creates a pattern, feeds it to FcConfigSubstitute and FcDefaultSubstitute, *then* to FcFontSort or FcFontMatch, and then creates an FcFontSet. - ftfont_list creates an FcPattern, feeds it to FcFontList, and we use what that returns. Not sure yet if the problem stems from not calling FcConfigSubstitute and FcDefaultSubstitute (ftfont_resolve_generic_family calls those, but IIUC only on temporary a FcPattern; there's also an #ifdef'd-out bit that calls FcConfigSubstitute) or from FcFontList. FWIW, I've attached snippets trying to reproduce various ways to use the Fontconfig API: - fontlist.c does more or less what ftfont_list does (I think), - fontmatch.c and fontsort.c do what fc-match and fc-match -a do. - fontsubstitute.c does like fontlist.c, but sneaks in calls to Fc*Substitute functions before calling FcFontList, Results: > fontlist > got 2 fonts > val 0: /usr/share/fonts/truetype/NotoColorEmoji.ttf > val 1: /home/peniblec/.local/share/fonts/NotoColorEmoji.ttf >=20 > fontmatch > got 1 fonts > val 0: /home/peniblec/.local/share/fonts/NotoColorEmoji.ttf >=20 > fontsort > got 3487 fonts > val 0: /home/peniblec/.local/share/fonts/NotoColorEmoji.ttf > val 1: /usr/share/fonts/truetype/NotoColorEmoji.ttf > (3485 more elided) >=20 > fontsubstitute > got 0 fonts I need to read more documentation to understand (1) how all those functions are supposed to work together (2) which of these exactly does or does not pay attention to the configured order (3) how exactly is this order configured: I'm very happy that fc-match seems to prioritize stuff in ~/.local/share/fonts, but I haven't read fonts-conf(5) attentively enough to explain why that is the case. (In the meantime, if someone reading this sees an obvious way to fix things, by all means, don't wait for me =F0=9F=99=83) --=-=-= Content-Type: text/x-chdr Content-Disposition: attachment; filename=dump.h #pragma once #include #include #include void dump_fontset(FcFontSet* fset) { size_t max = 2; printf("got %d fonts\n", fset->nfont); for (size_t i=0; infont && ifonts[i], FC_FILE, 0, &resultval) == FcResultMatch ); printf("val %zu: %s\n", i, resultval); } if (fset->nfont > max) printf("(%zu more elided)\n", fset->nfont-max); } --=-=-= Content-Type: text/x-csrc Content-Disposition: attachment; filename=fontlist.c #include #include #include #include "dump.h" int main() { FcResult result; assert(FcInit()); FcPattern* search = FcPatternCreate(); assert(search); FcValue searchval = { .type = FcTypeString, .u = { .s = "Noto Color Emoji" } }; assert( FcPatternAdd(search, FC_FAMILY, searchval, FcFalse) ); FcObjectSet* objs = FcObjectSetBuild(FC_FILE); assert(objs); FcFontSet* fset = FcFontList(NULL, search, objs); assert(fset); dump_fontset(fset); } --=-=-= Content-Type: text/x-csrc Content-Disposition: attachment; filename=fontmatch.c #include #include #include #include "dump.h" int main() { FcResult result; assert(FcInit()); FcPattern* search = FcPatternCreate(); assert(search); FcValue searchval = { .type = FcTypeString, .u = { .s = "Noto Color Emoji" } }; assert( FcPatternAdd(search, FC_FAMILY, searchval, FcFalse) ); FcObjectSet* objs = FcObjectSetBuild(FC_FILE); assert(objs); assert(FcConfigSubstitute(NULL, search, FcMatchPattern)); FcDefaultSubstitute(search); FcFontSet* fset = FcFontSetCreate(); assert(fset); FcPattern* match = FcFontMatch(NULL, search, &result); assert(result == FcResultMatch); FcFontSetAdd(fset, match); dump_fontset(fset); } --=-=-= Content-Type: text/x-csrc Content-Disposition: attachment; filename=fontsort.c #include #include #include #include "dump.h" int main() { FcResult result; assert(FcInit()); FcPattern* search = FcPatternCreate(); assert(search); FcValue searchval = { .type = FcTypeString, .u = { .s = "Noto Color Emoji" } }; assert( FcPatternAdd(search, FC_FAMILY, searchval, FcFalse) ); FcObjectSet* objs = FcObjectSetBuild(FC_FILE); assert(objs); assert(FcConfigSubstitute(NULL, search, FcMatchPattern)); FcDefaultSubstitute(search); FcFontSet* fset = FcFontSort(0, search, FcFalse, NULL, &result); assert(result == FcResultMatch); assert(fset); dump_fontset(fset); } --=-=-= Content-Type: text/x-csrc Content-Disposition: attachment; filename=fontsubstitute.c #include #include #include #include "dump.h" int main() { FcResult result; assert(FcInit()); FcPattern* search = FcPatternCreate(); assert(search); FcValue searchval = { .type = FcTypeString, .u = { .s = "Noto Color Emoji" } }; assert( FcPatternAdd(search, FC_FAMILY, searchval, FcFalse) ); FcObjectSet* objs = FcObjectSetBuild(FC_FILE); assert(objs); assert(FcConfigSubstitute(NULL, search, FcMatchPattern)); FcDefaultSubstitute(search); FcFontSet* fset = FcFontList(NULL, search, objs); assert(fset); dump_fontset(fset); } --=-=-= Content-Type: text/plain Content-Disposition: attachment; filename=makefile progs = $(patsubst \ %.c,%,$(wildcard *.c) \ ) .PHONY: run run: $(progs) @for p in $(progs) ; do echo $$p ; ./$$p ; echo ; done $(progs): %: %.c dump.h gcc $< -lfontconfig -o $@ --=-=-=--