Xterm.js: Suporta ligaduras de fontes

Criado em 8 set. 2017  ·  54Comentários  ·  Fonte: xtermjs/xterm.js

Suporte sendo removido em https://github.com/sourcelair/xterm.js/pull/938

Certamente ainda é possível, mas o renderizador precisa saber quais personagens juntar.

areapi arerenderer help wanted typenhancement

Comentários muito úteis

Acho que não estamos interessados ​​nas ligaduras regulares (na verdade, seria ruim habilitar ligaduras para li e outras), mas para coisas como == , !== , => e assim por diante. Aqui está uma boa lista de ligaduras suportadas pela fonte monospace fira code:
https://github.com/tonsky/FiraCode/blob/master/showcases/all_ligatures.png

Todos 54 comentários

Acho que não estamos interessados ​​nas ligaduras regulares (na verdade, seria ruim habilitar ligaduras para li e outras), mas para coisas como == , !== , => e assim por diante. Aqui está uma boa lista de ligaduras suportadas pela fonte monospace fira code:
https://github.com/tonsky/FiraCode/blob/master/showcases/all_ligatures.png

O que aconteceria se metade da ligadura fosse de uma cor diferente? Como você lidaria com isso?

@LoganDark isso funciona até mesmo com ligaduras normais? Ou eles estão separados quando são de cores diferentes?

Não e não.

Eu me pergunto se seria possível extrair código de renderização de txtjs, pois eles descobriram como renderizar ligaduras, embora eu ache que eles desenham o texto manualmente. http://txtjs.com/examples/Text/ligatures.html

@devsnek Não acho que seja um problema fazer a renderização do texto. O problema é saber qual caractere se junta para que eles possam ser desenhados juntos (atualmente "==" é desenhado como "=" e "=", não "==").

O @Tyriar não faria o renderizador de fontes cuidar disso sem nossa intervenção

@devsnek sim, mas cada célula na grade é desenhada individualmente com algumas exceções (emojis, caracteres unicode largos). Ligaduras precisam ser incluídas de alguma forma nessa lista. Veja https://github.com/sourcelair/xterm.js/pull/938 para mais contexto

@devsnek É VOCÊ

isenção de responsabilidade: completamente fora do tópico, apenas um comentário aleatório

@LoganDark isso funciona até mesmo com ligaduras normais? Ou eles estão separados quando são de cores diferentes?

Se vamos pela forma como outros emuladores lidar com eles, eles se separaram, se eles são de cores diferentes, como seria de esperar. Isso é quase um requisito, pois permite que os símbolos sejam representados corretamente por alguns marcadores de linguagem no ViM, por exemplo.

Acho que é inteiramente aceitável mostrar os símbolos individuais se o modo de renderização _não_ for o mesmo para todos os caracteres subjacentes.

@ Qix- Minha sugestão então seria desenhar todo o texto de uma vez e então colorir no post. Isso eliminaria quaisquer problemas com ligaduras e não exigiria a detecção de pares de ligaduras (embora quebrasse a compatibilidade com fontes de largura variável, ou mesmo fontes monoespaçadas que estão ligeiramente fora / não têm larguras inteiras)

As ligaduras multicoloridas do

Sim, eu não acho que ligaduras multicoloridas funcionariam. Também vai contra a forma como eles funcionam por baixo, onde um único glifo é desenhado no início, não vários.

Para esclarecer, isso é esperar por uma boa solução para detectar quais sequências de caracteres têm ligaduras. Para fazer isso corretamente, provavelmente envolveria um código de baixo nível que verifica os arquivos de fonte (e, portanto, precisaria ser um módulo de nó nativo e não funcionar para consumidores da web), não acho que essas informações sejam expostas na plataforma da web.

Agora que o hyper lançou 2.0.0 estável, talvez as soluções alternativas de ligadura precisem de uma prioridade mais alta.

Determinar os mapeamentos de glifos manualmente é um osso duro de roer. Pelo que eu posso dizer, fazer disso uma experiência decente exigiria o seguinte:

  1. Mapeie a família de fontes selecionada de volta para o arquivo / buffer contendo os dados reais da fonte (otf / ttf / woff / etc)
  2. Analise os dados da tabela GSUB da fonte e traduza isso em um conjunto sensato de regras para substituição de glifos
  3. Passe algum tipo de mapa ou função de mapeamento para o xterm para determinar o que renderizar para uma dada sequência de caracteres

Fiz algumas pesquisas iniciais com o Fira Code (especificamente sua variante de fonte nerd) para tentar descobrir como cada etapa pode ser difícil. Eu ainda não decidi se estou me sentindo ambicioso o suficiente (ou me preocupo com ligaduras de fontes) para assumir isso, mas aqui está o que eu descobri para que o conhecimento não seja perdido:

  • Não há maneira que eu possa encontrar para buscar os dados da fonte usando APIs do navegador, então isso não funcionará como um recurso direto do xterm.js, mas mais provavelmente como um pacote / extensão separado com um gancho exposto por xterm.js

  • Mapear o nome CSS font-family de uma fonte de volta para seu arquivo de fonte no Windows é doloroso, mas parece factível. Até agora, a única maneira que encontrei é buscar tudo em %WINDIR%\Fonts e analisar todos os arquivos que encontrar (spoiler: é muito lento). Ainda não experimentei outras plataformas. (Observação: eu também tentei retirar o nome do registro, mas a nomenclatura não corresponde a algumas fontes, como as de fontes nerd. Eles usam uma família e subfamília "preferida" que não é incluída no nome do registro mas é usado no css font-family . Se você estiver curioso, a chave do registro está em HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts )

  • Há uma biblioteca chamada opentype.js que analisa completamente as tabelas de fontes OpenType e tem até uma função font.stringToGlyphs(str) que lida com ligaduras básicas, mas as ligaduras para Fira Code (e várias, senão todas as outras fontes de ligaduras comuns) use um recurso chamado alternativas contextuais que ainda não é suportado por opentype.js (listado em Planejado ). A tabela GSUB necessária é analisada em JSON para você, então, teoricamente, tudo o que falta é a interpretação dos dados da tabela.

  • As ligaduras Fira Code (e eu acho que outras) na verdade substituem os glifos originais por números iguais de glifos, em vez de um único extra largo (para manter as propriedades da fonte monoespaçada). Para uma string como ==> , a fonte acabará dizendo a você para substituí-la por dois caracteres "LIG" (essencialmente um espaço vazio), seguido pelo glifo real da ligadura, que ainda é tecnicamente apenas um espaço único personagem de largura. Apesar de ser ostensivamente de largura única, o caminho do último personagem se estende além do lado esquerdo da caixa delimitadora do personagem para cobrir o espaço ocupado pelos dois personagens LIG antes dele. Veja abaixo um visual (0 e 600 são os lados da caixa do personagem). Não sei se isso complica a tarefa do renderizador ou se teria que ser transformado antes de ser passado para o xterm.js, mas é algo a ter em conta.

image

  • Outro ponto negativo é determinar quando reavaliar a ligadura. Por exemplo, se eu digitar = quatro vezes consecutivas, o comportamento desejado seria ver um único igual, depois uma ligadura dupla igual, depois uma ligadura triplo igual e, em seguida, quatro sinais separados de igual. Na verdade, existem mapeamentos nas regras alternativas contextuais para limpar a ligadura (ou seja, se a entrada atual for '=' e os três caracteres anteriores forem '===', não remapearemos de forma alguma), mas teríamos para descobrir como aplicar essas regras.

  • OpenType é complicado. Reconheço que não sou um especialista em renderização de fontes, mas o número de variações possíveis que levam a diferentes tipos de renderização é bastante extenso. Sem uma biblioteca integrada que faça o mapeamento para nós, acho que a maneira mais razoável de atacar isso é incrementalmente. O Fira Code usa especificamente o Chaining Context Substitution Format 3 , mas tenho certeza de que há outras fontes populares que usam fontes diferentes. Como cada uma tem uma semântica ligeiramente diferente, provavelmente faz sentido começar com uma e partir daí.

@princjef Obrigado por compartilhar suas explorações, realmente úteis! Também tenho refletido sobre esse tópico há alguns dias e cheguei à seguinte conclusão:

  • A detecção de ligaduras em webfonts usando uma API integrada parece impossível (como você descreve)
  • Existem certas ligaduras que não fazem sentido em um terminal, mesmo se a fonte suportar (por exemplo, li )
  • Há um subconjunto muito pequeno de ligaduras que faz sentido ter suporte, ou seja, a maioria das ligaduras Fira Code.
  • Adicionar suporte para desenhar e limpar um caractere que se estende por várias células é muito difícil de implementar com nossa abordagem de renderização baseada em caractere único (CharAtlas).

TBH, não acho que valha a pena o esforço para apoiar as ligaduras no estado atual 😔

@mofux Na verdade, acho que encontrei uma maneira (um tanto palatável) de fazer as ligaduras renderizarem no xterm.js abordando-o de um ângulo diferente. De alguma forma, não percebi que a tela renderizará automaticamente as ligaduras para você em minhas investigações iniciais. Apoiar ligaduras torna-se uma questão de garantir que os caracteres relevantes sejam renderizados juntos.

Para esse fim, ajustei o renderizador de texto para renderizar caracteres com atributos idênticos (fg, bg, etc.) como um único grupo. Isso não renderizará todas as ligaduras corretamente (e pode renderizar algumas que não deveriam), mas deve renderizar uma ligadura em qualquer lugar que alguém espere ver uma. Aqui está uma captura de tela do NeoVIM no aplicativo de demonstração usando Fira Code (mostrado no Firefox, também funciona no Chrome, mas não no Edge):

image

Branch está aqui se as pessoas quiserem dar uma olhada: https://github.com/princjef/xterm.js/tree/ligature-support

Algumas notas sobre isso:

  • Não fiz nenhum benchmarking, mas aposto que isso não vai ser bom para o desempenho. Ao agrupar todos os caracteres do mesmo estilo, o atlas de caracteres basicamente é jogado pela janela, mesmo para lugares onde não há ligaduras (já que não sabemos onde eles estarão / não estarão). Quando eu renderizo vários caracteres juntos, eu apenas defini o código do caractere como Infinity para garantir que evitarei qualquer cache.
  • Provavelmente, existem alguns casos extremos em torno da largura e da sobreposição dos caracteres com os quais não estou lidando corretamente. Esta é principalmente uma prova de conceito neste momento.

Que tal renderizar o texto usando o atlas de caracteres e, em seguida, renderizá-lo em segundo plano como um bloco de texto enquanto estiver ocioso? Se os dois resultarem na mesma imagem, você pode jogar fora o texto combinado e voltar para o atlas. Ao dividir as sequências de texto no fundo, pode ser possível aprender quais sequências de texto são ligadas.

A parte complicada disso é que a renderização de uma ligadura depende não apenas dos caracteres substituídos pela ligadura, mas também de seu contexto. Por exemplo, '=== 1' deve representar os três sinais de igual como uma ligadura, mas '====' deve processar os mesmos três sinais de igual como caracteres separados. Não há limite para o tamanho desse contexto, portanto, seria difícil e provavelmente sujeito a erros determinar as regras de quando uma ligadura é renderizada apenas a partir de sua saída.

Uma abordagem mais confiável (mas menos portátil) é ter dicas sobre os intervalos de ligadura fornecidas por uma função separada que conhece os metadados da fonte. Então, tudo, exceto os intervalos fornecidos pela função externa, podem ser renderizados usando o atlas, enquanto os grupos fornecidos podem usar uma abordagem como a acima. Determinar as localizações das substituições dada uma linha de texto deve ser muito rápido, mas tem alguns dos problemas que eu detalhei anteriormente (principalmente velocidade / confiabilidade de encontrar a fonte certa na inicialização e complexidade de processamento de alternativas contextuais OpenType).

Seria razoável ter uma configuração para habilitar ligaduras, que grava
uma linha inteira de cada vez para o terminal? Parece que isso seria
garantir a renderização correta, e o desempenho atingido seria uma opção para
gente que se preocupa mais com ligaduras do que com velocidade.

No domingo, 22 de abril de 2018, 16:21 Jeff Principe [email protected] escreveu:

A parte complicada disso é que a renderização de uma ligadura é dependente
não apenas nos personagens substituídos pela ligadura, mas também em seu contexto.
Por exemplo, '=== 1' deve renderizar os três sinais de igual como uma ligadura, mas
'====' deve processar os mesmos três sinais de igual como caracteres separados.
Não há limite para o tamanho desse contexto, então seria difícil e
provavelmente sujeito a erros para determinar as regras de quando uma ligadura é processada
apenas de sua saída.

Uma abordagem mais confiável (mas menos portátil) é ter dicas sobre
intervalos de ligadura fornecidos por uma função separada que conhece a fonte
metadados. Então tudo, exceto os intervalos fornecidos pela função externa
podem ser renderizados usando o atlas, enquanto os grupos dados podem usar um
abordagem como a acima. Determinando os locais de substituições
dada uma linha de texto deve ser bem rápido, mas tem alguns dos problemas que
detalhado anteriormente (principalmente velocidade / confiabilidade de encontrar a fonte certa em
inicialização e complexidade de processamento de alternativas contextuais OpenType).

-
Você está recebendo isto porque está inscrito neste tópico.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/xtermjs/xterm.js/issues/958#issuecomment-383420281 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAKyryMlayIQijY32GpWBmpvCUi13Wfbks5trRBigaJpZM4PRej6
.

@princjef Uau, suas edições são tão fáceis de seguir e parece que o xterm pode suportar ligaduras com o renderizador. O truque é descobrir como mapear as regras. Isso me dá esperança.

@princjef grande investigação!

Não há maneira que eu possa encontrar para buscar os dados da fonte usando APIs do navegador, então isso não funcionará como um recurso direto do xterm.js, mas mais provavelmente como um pacote / extensão separado com um gancho exposto por xterm.js

@princjef Eu vejo um eventual suporte de ligadura vivendo como:

  • some-magical-package : um módulo de nó nativo puxa informações de fonte nativa, mapeando strings de fonte da web para os arquivos, se possível. Isso pode ser feito em AsyncWorker para reduzir o impacto no desempenho. Não é grande coisa se isso for feito preguiçosamente e na primeira inicialização levar vários segundos para fazer a varredura e atualizar.
  • xtermjs/xterm-ligature-support : Um addon que depende do nó e usa some-magical-package para obter e armazenar em cache informações sobre a fonte. Este addon pode fazer uma varredura sempre que fontes não reconhecidas são detectadas no diretório de fontes e expulsar fontes quando são removidas. Espero algo assim como a API aproximada:

    /** Returns a list of characters to be drawn together */
    export function getLigatures(fontFamily: string): string[] { ... }
    

Existem certas ligaduras que não fazem sentido em um terminal, mesmo se a fonte suportar (por exemplo, li)

@mofux Não tenho certeza se precisamos nos preocupar com isso? Se o usuário solicitar ligaduras, não deveríamos renderizar todas elas?

Adicionar suporte para desenhar e limpar um caractere que se estende por várias células é muito difícil de implementar com nossa abordagem de renderização baseada em caractere único (CharAtlas).

@mofux Devemos ser capazes de adicionar facilmente uma função para desenhar um conjunto de caracteres adjacentes juntos.

@princjef : Não fiz nenhum benchmarking, mas aposto que não vai ser bom para o desempenho.

@wavebeem : Seria razoável ter uma configuração para habilitar ligaduras, que grava uma linha inteira de uma vez no terminal?

Espero anular quase completamente as melhorias de desempenho que vêm com o uso do canvas. Além disso, quero manter o número de opções no mínimo, devemos tentar chegar a um lugar onde as ligaduras funcionem quando um complemento for incluído para adicionar suporte.

Também com relação ao desempenho, provavelmente estarei trabalhando para adicionar uma opção de renderização DOM substituta nos próximos meses, pois há muitas coisas que podem dar errado com o suporte de GPU no Chromium. Consulte https://github.com/xtermjs/xterm.js/issues/1360. As ligaduras funcionarão imediatamente neste modo.

Que tal renderizar o texto usando o atlas de caracteres e, em seguida, renderizá-lo em segundo plano como um bloco de texto enquanto estiver ocioso? Se os dois resultarem na mesma imagem, você pode jogar fora o texto combinado e voltar para o atlas.

@ j-f1 isso é mais difícil do que parece. Mesmo que os caracteres sejam processados ​​da mesma forma, o segundo será diferente, pois o espaçamento no atlas de caracteres é diferente (os caracteres são sempre desenhados em um número redondo). Nós precisaríamos renderizar muito mais para que isso funcionasse e muitos pixels de diffing, o que é caro.

@Tyriar Acho que o design geral que você descreveu faz sentido. Nós _podemos_ conseguir fazer algo que não dependa do código nativo para encontrar as fontes em some-magical-package , mas definitivamente dependerá da plataforma / sistema de arquivos. Eu comecei a brincar com a análise das substituições alternativas contextuais, mas é difícil dizer quanto mais será necessário para acertar.

Também acho que precisaremos de uma interface ligeiramente diferente para some-magical-package :

export function getSubstitutionRanges(fontFamily: string, text: string): Promise<[number, number][]>;

As regras para determinar as próprias ligaduras são complicadas e embutidas na própria fonte. Em vez de passar os próprios dados da fonte e colocar o fardo de interpretá-los no xterm.js, eu deixaria isso para a outra lib e faria com que ela dissesse ao xterm.js quais caracteres devem ser renderizados juntos. Os aspectos de lookahead / lookbehind do contexto também complicam a análise. Por exemplo, '===' mapeia para uma ligadura, mas não se for seguida por outro sinal de igual.

Outra observação sobre o conceito de intervalos de substituição: não há um delineamento claro dos limites de uma única ligadura pelo que posso dizer (pelo menos ao usar alternativas contextuais). Existem apenas sequências de substituições aplicadas a caracteres individuais. Eu descobri alguns truques para descobrir os limites se você tiver ligaduras consecutivas, mas provavelmente não é à prova de falhas. Provavelmente, eu erraria ao tratar acidentalmente duas ligaduras como uma, em vez de separá-las acidentalmente, uma vez que elas ainda deveriam ser renderizadas corretamente se renderizadas todas juntas como um único grupo. O único problema real é aplicar estilos heterogêneos a ele.

O único problema real é aplicar estilos heterogêneos a ele.

Apenas não faça isso. Passe cada string de estilo contínuo para a função separadamente. Você pode fazer uma exceção para o texto sublinhado se o sublinhado for desenhado separadamente.

Podemos conseguir fazer algo que não depende do código nativo

👍

As regras para determinar as próprias ligaduras são complicadas e embutidas na própria fonte. Em vez de passar os próprios dados da fonte e colocar o fardo de interpretá-los no xterm.js, eu deixaria isso para a outra lib e faria com que ela dissesse ao xterm.js quais caracteres devem ser renderizados juntos.

@princjef isso soa ainda melhor, quanto menos o xterm.js fizer nesta área, melhor.

O único problema real é aplicar estilos heterogêneos a ele.

Acho que nada mais tenta fazer isso, devemos apenas adicionar ligaduras para textos que usam o mesmo estilo.

Isso parece possível do lado da fonte. Tenho um código que analisa com êxito todas as ligaduras do Fira Code e fornece os intervalos certos para os caracteres combinarem. Se as pessoas tiverem uma ou duas outras fontes para as quais estejam procurando suporte, posso tentar verificá-las também. Até agora, implementei apenas os tipos de substituição de que precisava para o Fira Code, portanto, alguma variedade seria bem-vinda para exercer os outros tipos de substituição.

Ainda preciso descobrir a parte da pesquisa de fontes. Vou me concentrar nisso a seguir. Existem alguns pacotes por aí, mas todos eles parecem estar cheios de bugs ou mal mantidos

@princjef Se você quiser verificar outras fontes, estou usando Iosevka .

Tudo bem, criei um pacote chamado font-ligatures (também conhecido some-magical-package ) e alguns pacotes associados para que possamos encontrar com eficiência a fonte certa e, em seguida, descobrir onde estão as ligaduras para uma determinada entrada de texto.

Passei algum tempo otimizando o processo de localização da fonte. Em um Surface Pro 4 com ~ 150 fontes ttf / otf, posso obter os metadados de todas as fontes em 300-400ms. É principalmente vinculado a E / S e pode ser chutado para o fundo nos primeiros ciclos de renderização enquanto carrega, mas deve ser rápido o suficiente para ser carregado no momento em que um pty for inicializado e cuspir algum texto. Depois de carregado, podemos acionar um render para atualizar qualquer texto que já esteja presente. Isso pode ser repetido sempre que a fonte mudar ou podemos armazenar a lista completa na primeira vez (eu busco a lista completa no início de qualquer maneira).

Quanto ao mapeamento de ligaduras em si, a biblioteca pega uma string e retorna metadados sobre as ligaduras de fontes, incluindo os grupos de caracteres que devem ser renderizados juntos. O CI inclui testes para cada ligadura em Fira Code, Iosevka e Monoid, então estou razoavelmente confiante de que ele faz o processamento corretamente para os tipos de substituição que realiza (embora tenha certeza de que existem algumas fontes por aí que usam outros tipos que Não implementei).

No entanto, não perdi tempo otimizando / ajustando a análise da ligadura. Fiz alguns testes rápidos e parece que analisar ligaduras leva de 2 a 20 ms para uma corda de comprimento moderado (leia-se: 1 linha). Ainda há muito espaço para otimizar, então não estou muito preocupado no momento. Eu queria principalmente mostrar isso para demonstrar a interface e permitir que as pessoas chutassem os pneus, se quisessem.

Parece muito legal @princjef! O que você acha sobre adicionar testes ao Fira Code para 0xc0ffee , 0x1234 e 17x32 ? (O x transforma em um sinal de tempos nesses)

@princjef incrível!

Fiz alguns testes rápidos e parece que a análise de ligaduras leva de 2 a 20 ms para uma corda de comprimento moderado (leia: 1 linha)

Você pode me apontar alguns dos códigos críticos que verificam isso?

@ j-f1 Sim, esses também funcionam: https://github.com/princjef/font-ligatures/blob/master/src/index.spec.ts#L136 -L137

@Tyriar Acabei de adicionar um benchmark básico com o qual você pode brincar. o padrão de chamada se parece com node bench/lines.js <font-name> <input-text> [iterations] . Você também pode passar uma string de várias linhas ou expandir um arquivo de entrada para o texto e ele percorrerá as linhas para tentar evitar otimizações irrealistas de executar a mesma entrada repetidamente.

Enquanto escrevia isso, percebi que mesmo quando uso várias linhas diferentes de entrada, ainda ocorre um aumento significativo de desempenho após a primeira execução. Para entradas de aproximadamente 10 caracteres, estou vendo médias de uma fração de milissegundo para Iosevka e um pouco mais de meio milissegundo para Fira Code. Ou estou acertando um caso especial ou o Turbofan está funcionando como mágica. Ainda não é eficiente o suficiente para ser usado no estado em que se encontra, mas começarei a me concentrar nas otimizações de desempenho a seguir (nesse ponto provavelmente também adicionarei um benchmark melhor para ter uma ideia das melhorias).

Algumas notas:

  • Devido à forma como as substituições funcionam, eu esperaria que o tempo de execução escalasse linearmente com o tamanho da entrada, embora eu não tenha verificado isso
  • Devido ao número de ligaduras e à maneira como as substituições funcionam, o Fira Code é muito mais intensivo para analisar do que Iosevka ou Monoid. Eu regularmente vejo que leva de 5 a 10 vezes mais tempo para executar o Fira Code do que Iosevka.
  • Fontes sem ligaduras são executadas com muito mais rapidez e podem ser otimizadas. Se não houver alternativas contextuais na fonte, posso fazer uma saída rápida com um conjunto de resultados vazio (ou podemos apenas ignorar a chamada em um nível superior).

Comecei a rastrear o aspecto de desempenho em um problema no pacote que criei (https://github.com/princjef/font-ligatures/issues/2). Aqui estão os números iniciais copiados de lá para algumas configurações (todos os números são vezes em ms). As primeiras cinco colunas de número são por linha de entrada e as duas últimas são por caractere. A penúltima coluna é a que estou prestando mais atenção. Estou atirando por aproximadamente 0,5 microssegundos por caractere (0,0005 em milissegundos):

NAME | AVG | STDEV | 5% | 50% | 95% | AVG (CHAR) | STDEV (CHAR)
----------------------- | ------- | --------- | ------ | -------- | ------- | ------------- | ----------------
Código Fira: code.txt | 5,9570 | 12,6951 | 0,5270 | 5,1020 | 12,2330 | 0,1443531 | 0,2091743
Código Fira: noLigatures.txt | 12,1932 | 3,4402 | 8.1420 | 12,1205 | 15,5900 | 0.1321094 | 0,0334362
Iosevka: code.txt | 0,5571 | 1,4722 | 0,0485 | 0,3215 | 1,6155 | 0,0135005 | 0,0333483
Iosevka: noLigatures.txt | 0,7476 | 0,4230 | 0,4365 | 0,6030 | 1,7725 | 0,0080998 | 0,0044501
Monóide: code.txt | 0,8896 | 1,6637 | 0,0910 | 0,6625 | 1,9225 | 0,0215566 | 0,0482166
Monoid: noLigatures.txt | 1,6661 | 0,6935 | 1.0695 | 1,4450 | 2,6910 | 0,0180521 | 0,0071922
Ubuntu Mono: code.txt | 0,0402 | 0,3935 | 0,0080 | 0,0220 | 0,0605 | 0,0009735 | 0,0090228
Ubuntu Mono: noLigatures.txt | 0,0356 | 0,0644 | 0,0120 | 0,0280 | 0,0805 | 0,0003858 | 0,0006891

Agora que existem bons dados de linha de base, teremos uma ideia melhor dos ganhos obtidos com cada ajuste de desempenho.

@Tyriar , você tem uma preferência sobre onde reside o pacote xterm-ligature-support e como ele chega lá?

Parece que você está pensando que ele deve ir para xtermjs org (o que parece razoável para mim), mas não tenho a capacidade de criar / enviar para um repositório na org. Você prefere colocá-lo em um repo sob meu usuário que é migrado para a organização ou deseja criar um stub repo para o qual eu possa enviar um PR?

Do ponto de vista da revisão, faz sentido finalizar o # 1460 primeiro, então sem pressa, mas quero descobrir onde despejar o código quando estiver pronto.

@princjef Eu criei https://github.com/xtermjs/xterm-ligature-support e dei a você acesso de administrador. Suponho que você já viu como os outros addons funcionam, mas este será o primeiro addon externo oficial. Portanto, use os complementos internos e https://github.com/CoderPad/xterm-webfont como referência para implementação 😄

Vou verificar o PR em breve 👍

Postou uma atualização no repositório vscode neste https://github.com/microsoft/vscode/issues/34103 , aqui está o trabalho restante antes de podermos chamá-lo de fechado em xterm.js:

  • Integre xtermjs / xterm-addon-ligatures ao repositório xtermjs / xterm.js , isso permitirá a publicação automatizada e garantirá que os testes continuem sendo aprovados
  • Conecte as ligaduras na demonstração
  • Configure alguns testes de titereiro que verificam em todos os renderizadores (dom, canvas, webgl) se as ligaduras estão funcionando
  • Diminua as dependências o máximo possível

Obrigado por todo o trabalho duro aqui a todos! 😄 👍

Se eu puder perguntar, @Tyriar , há algum plano para suporte ao navegador da web?

Também vi que isso poderia funcionar no navegador, mas seria muito lento. Se eu puder perguntar, quão lenta era essa versão que funcionava no navegador?

Obrigado!

@ torch2424 Não acho que seja possível com a forma como os renderizadores funcionam, já que o suporte da ligadura depende da análise do arquivo de fonte (sem um

@Tyriar Obrigado pela resposta rápida!

Isso é lamentável, mas foi mais agradável de se ter. Estamos considerando uma versão eletrônica, então talvez a tenhamos como um recurso incluído 😄 Obrigado!

Hmm, acho que deveria ser possível, usando um webfont e carregando os mesmos arquivos de fonte (urgh) em domínios JS para extrair os dados de ligadura. Não tenho certeza se isso é viável / vale a pena fazer dessa maneira, pois a extração da ligadura é uma grande mossa no desempenho. Não tenho certeza sobre o uso do mem, um arquivo de fonte pode ficar muito grande, talvez @princjef tenha aqui alguns números sobre o comportamento do tempo de execução?

Já faz um tempo desde que eu olhei para isso, mas minha lembrança é que não havia APIs embutidas para extrair informações de fontes brutas no navegador, mesmo para fontes da web.

Se você tivesse que carregar manualmente sua própria fonte da web de um arquivo e injetar separadamente o conteúdo do mesmo arquivo no código para analisar ligaduras, é teoricamente factível sem ter que desistir das otimizações de cache de glifo no renderizador. Dito isso, o complemento existente não foi projetado com esse caso de uso em mente porque requer mais coordenação e fiação manual do que o caso sem navegador.

Não tenho certeza se isso é viável / vale a pena fazer dessa maneira, pois a extração da ligadura é uma grande mossa no desempenho. Não tenho certeza sobre o uso de mem, um arquivo de fonte pode ficar muito grande

Isso definitivamente pode ser um problema para certas fontes. O pacote de processamento de ligadura é altamente otimizado para eficiência de pesquisa / detecção, o que, por enquanto, custa mais tempo de carregamento e consumo de memória. Isso vai variar substancialmente de fonte para fonte, mas é uma boa consideração a ter em mente.

Mesmo que a extração de informações de ligadura fosse possível, a API da web usa pontos de código de texto / caractere, enquanto as ligaduras dentro da fonte usam índices de glifo específicos da fonte que não podem ser passados ​​diretamente para as APIs da web para desenho.

@princjef Obrigado pelo

@khaledhosny A ideia era mais sobre obter as informações de ligadura das fontes em JS enquanto ainda trabalhava com pontos de código e deixava o renderizador de fontes do navegador fazer as coisas de baixo nível (visto que usa as mesmas fontes). Não tenho certeza se a extração de glifo e a própria renderização seriam possíveis feitas exclusivamente em JS (lol, um renderizador de fonte baseado em JS? Mesmo se isso fosse factível, imho teria um desempenho muito ruim).

Atualização sobre isso, acabei de mesclar o complemento de ligaduras na base de código (https://github.com/xtermjs/xterm.js/pull/2847), pode ainda estar um pouco quebrado, mas é difícil dizer sem a configuração de testes de integração ( https://github.com/xtermjs/xterm.js/issues/2896).

Atualmente o addon é executado apenas em um navegador + node runtime (ou seja, electron), eu vim com uma proposta que espero funcionar apenas no navegador, o que nos permitiria eliminar o node deps e trazê-lo para o VS Code (https: / /github.com/microsoft/vscode/issues/34103). Está etiquetado com procura de ajuda se alguém quiser experimentar https://github.com/xtermjs/xterm.js/issues/2897.

Devemos analisar o uso da API Font Access (atualmente em teste de origem) para o complemento de ligaduras.

Estou usando o ttyd, que compartilha o terminal na web e usa o xterm.js. como você pode ver na imagem abaixo, os ícones não são carregados corretamente. eles são visíveis no terminal original. mas na web eles estão faltando.

image

@UziTech oh uau, isso parece incrível! Acho que qualquer trabalho que seja feito nesta área deve ser pensado para o futuro, para que possamos aproveitá-lo com a API de acesso a fontes.

@UziTech @Tyriar @princjef
Acho que o código para a API de acesso a fontes pode ser colocado em pacotes de font-ligatures .
Depois de detectar se o processo está no navegador ou nó / elétron, ele pode decidir se deve chamar a API de acesso à fonte ou usar o método atual.

Eu criei uma prova de conceito de hacky e a coloquei em execução na demonstração em
Screenshot 2021-01-17 at 18 39 27

Você pode experimentar depois de habilitar #font-access em chrome://flags (precisa atualizar uma vez depois de permitir o acesso às fontes)

Posso tentar abrir os pr's se isso parecer bom para você.

Depois de detectar se o processo está no navegador ou nó / elétron, ele pode decidir se deve chamar a API de acesso à fonte ou usar o método atual.

Acabaremos tendo problemas com esta solução, pois os projetos que são apenas da web terão problemas para empacotar os deps do nó. Não tenho uma resposta para isso, mas também acho que devemos inverter os padrões (eventualmente?) E usar como padrão o acesso à fonte se a detecção do recurso for bem-sucedida, caso contrário, fallback.

Também foi um ótimo trabalho fazê-lo funcionar! Isso é incrível 😍

Podemos require eles após a detecção do recurso somente se necessário.
E projetos dependentes apenas da web podem marcá-los como externos durante o empacotamento.

Podemos ter a API de acesso à fonte como padrão, uma vez que esteja disponível em todos os navegadores, eu acho.

👍 Posso estar pensando demais sobre a preocupação do bundler, pois você mencionou que há soluções alternativas. Espero que descontinuemos / eliminemos a opção Electron assim que o acesso à fonte for ativado no Electron de qualquer maneira.

@Tyriar, podemos lançar o complemento ligaduras com a atualização do localizador de fontes em breve?

@UziTech [email protected] deve ter isso, eu criei um lembrete para aumentar a versão para 4.10 https://github.com/xtermjs/xterm.js/issues/3220

Abri um pr princjef / font-ligatures # 22 como a primeira etapa para fazer isso

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

fabiospampinato picture fabiospampinato  ·  4Comentários

Mlocik97-issues picture Mlocik97-issues  ·  3Comentários

jestapinski picture jestapinski  ·  3Comentários

Tyriar picture Tyriar  ·  4Comentários

LB-J picture LB-J  ·  3Comentários