Como configuro o fallback de fontes de maneira robusta?

16

TL; DR: Qual é uma maneira simples de dizer com segurança: use o Consolas como a fonte padrão, o FreeMono para os caracteres não suportados pelo Consolas e o Symbola para os caracteres não suportados pelos dois?

Como minha fonte principal de programação não cobre todos os símbolos matemáticos de que preciso, configurei inicialmente o fallback da fonte, como mostrado abaixo:

(set-fontset-font t 'unicode (font-spec :name "FreeMono") nil 'append)
(set-fontset-font t 'unicode (font-spec :name "Symbola") nil 'append)

Infelizmente, isso também mudou a fonte de alguns dos caracteres que minha fonte principal suporta, então mudei para

(set-fontset-font t 'unicode (font-spec :name "Consolas") nil)
(set-fontset-font t 'unicode (font-spec :name "FreeMono") nil 'append)
(set-fontset-font t 'unicode (font-spec :name "Symbola") nil 'append)

Se meu entendimento estiver correto, isso deve garantir que os caracteres que Consolas não podem manipular sejam manipulados pelo FreeMono, a menos que o FreeMono não os possua, caso em que devem ser exibidos usando o Symbola. Também entendo que tfaz o mesmo que "fontset-default"acima.

Infelizmente, ainda havia casos em que a fonte correta não foi selecionada; Eu descobri que mudar para

(set-fontset-font t 'unicode (font-spec :name "Consolas") nil)
(set-fontset-font t 'unicode (font-spec :name "FreeMono") nil 'append)
(set-fontset-font t 'unicode (font-spec :name "Symbola") nil 'append)
(set-fontset-font "fontset-startup" 'unicode (font-spec :name "Consolas") nil)
(set-fontset-font "fontset-startup" 'unicode (font-spec :name "FreeMono") nil 'append)
(set-fontset-font "fontset-startup" 'unicode (font-spec :name "Symbola") nil 'append)

funcionou melhor, mas nem sempre: alterar o tamanho da fonte usando

(set-face-attribute 'default nil :height some-size)

fez com que os fallbacks fossem ignorados devido à criação de novos conjuntos de fontes.

Minha solução atual é fazer

(set-fontset-font fontset 'unicode (font-spec :name "Consolas") nil)
(set-fontset-font fontset 'unicode (font-spec :name "FreeMono") nil 'append)
(set-fontset-font fontset 'unicode (font-spec :name "Symbola") nil 'append)

em cada conjunto de fontes ( fontset-list), após cada alteração no tamanho da fonte.

Qual é a maneira correta de definir fallback de fonte?

Nota : para fins de teste, aqui estão alguns caracteres matemáticos: ℕ𝓟⧺×≠≥≤±¬∨∧∃∀λ⟿⟹⊥⊤⊢
Referências : Manual do Emacs sobre conjuntos de fontes e modificação de conjuntos de fontes

Clemente
fonte
2
Tenho um pensamento que realmente não resolve o seu problema, mas - se você precisa de símbolos matemáticos etc. para teoremas e documentos científicos, por que não usa o TeX e o AucTeX para isso? Isso tornaria desnecessário o aborrecimento com fallbacks de fontes do X (ou Mac ou Windows, dependendo do que você executa) e forneceria documentos e trechos de alta qualidade (por exemplo, para o modo organizacional).
uma reflexão tardia: uma fonte UTF-8 com um conjunto completo de caracteres deve remover completamente o seu problema (por exemplo, GNU Unifont) e, quando houver uma escolha entre a fonte sofisticada e os glifos necessários, eu escolheria a última.
2
@kuli Você é muito pessimista. Veja github.com/cpitclaudel/monospacifier
Ista
Não me lembro onde li, mas acredito que Eli Zaretskii respondeu a uma pergunta semelhante em algum lugar. Você está pensando fontsetda maneira errada. O Emacs, na verdade, não verifica cada caractere exibido, se uma fonte sabe como exibi-lo ou não. Isso seria muito computacionalmente intensivo. Portanto, não existe um mecanismo de "fallback" em si. Você deve definir sua fonte padrão e modificar o conjunto de fontes padrão manualmente em determinados intervalos para exibir usando fontes diferentes. Este procedimento é manual ou talvez o pacote unicodepossa ajudar.
GenaU
@GenaU Posso estar entendendo mal, mas o Emacs verifica; apenas nem todas as fontes, apenas as que aparecem em um conjunto de fontes.
Clément

Respostas:

0

Para quem não consegue ler a documentação do Emacs.

Seleção de fonte

Antes que o Emacs possa desenhar um caractere em uma exibição gráfica, ele deve selecionar uma "fonte" para esse caractere. Normalmente, o Emacs escolhe automaticamente uma fonte com base nas faces atribuídas a esse personagem - especificamente, os atributos de face ': família', ': peso', ': inclinação' e ': largura'. A escolha da fonte também depende do caractere a ser exibido; algumas fontes podem exibir apenas um conjunto limitado de caracteres. Se nenhuma fonte disponível atender exatamente aos requisitos, o Emacs procurará a "fonte correspondente mais próxima". As variáveis ​​nesta seção controlam como o Emacs faz essa seleção.

face-font-family-alternatives

Testado especificamente usando caracteres na pergunta, verificando caracteres com
describe-character. Cada personagem usa uma das fontes gratuitas: Consolas, FreeMono, Symbola. Definindo a fonte do quadro como Consola por set-frame-font.

Até o momento, 14 votos positivos, resposta com votos negativos, e a ciência da UE ainda não consegue resolver esse mistério.

Alexandr Karbivnichiy
fonte
Obrigado! Você considerou postar isso como uma resposta ao meu comentário acima, e não como uma resposta separada?
Clément
1
(Devo esclarecer que também testei no Emacs 26, e sua resposta parece não funcionar: usei (setq face-font-family-alternatives '(("Consolas" "FreeMono" "Symbola")))então M-x set-frame-font RET Consolas RET; os personagens usam uma mistura de símbolo de interface do usuário do console e do Segoe)
Clément
Testei no Manjaro Arch Linux esta sequência: ℕ𝓟⧺ × ≠ ≥≤ ± ±λ⟿⟹⊥⊤⊢; Não testei o que acontece se alguma fonte não estiver instalada. Isso pode ser possível. Como os nomes das fontes são inseridos manualmente, não de uma lista dos existentes.
Alexandr Karbivnichiy 17/01/19
Eu testei com todas as fontes da lista instaladas, em emacs -Q.
Clément
@ Clément emacs -Q opção impila bastante: --no-x-resources. Talvez o problema esteja nele. Para mim, os Consolas começam apenas com este caractere: "×". E os dois primeiros "ℕ𝓟" FreeMono e Symbola.
Alexandr Karbivnichiy
-1

M-x customize-variable face-font-family-alternatives

Há uma lista que se parece com:

(("Monospace" "courier" "fixed")
 ("Monospace Serif" "Courier 10 Pitch" "Consolas" "Courier Std" "FreeMono" "courier" "fixed")
 ("courier" "CMU Typewriter Text" "fixed")
 ("Sans Serif" "helv" "helvetica" "arial" "fixed")
 ("helv" "helvetica" "arial" "fixed"))

Adicione sua sequência na customizeinterface do buffer:

("Consolas" "FreeMono" "Symbola")

Se uma determinada família for especificada, mas não existir, essa variável especificará famílias de fontes alternativas para tentar. Cada elemento deve ter este formato:

 (FAMILY ALTERNATE-FAMILIES...)

Se FAMÍLIA for especificada, mas não disponível, o Emacs tentará as outras famílias indicadas em ALTERNATIVAS, uma por uma, até encontrar uma família que exista.

Como usar face-font-family-alternatives:

No seu buffer: M-x set-frame-font

Escolha uma fonte da lista. A fonte escolhida definirá qual sequência de pesquisa de fontes face-font-family-alternativesusar. Neste exemplo, Consolas .

Para verificar qual família de fontes foi usada para exibir um caractere: M-x describe-char

Alexandr Karbivnichiy
fonte
Obrigado! Mas acho que isso não responde à pergunta. AFAICT, a configuração que você sugeriu usará o FreeMono se a fonte do Consolas não estiver disponível, mas não usará o FreeMono para caracteres não suportados pelo Consolas.
Clément