Xterm.js: Dessinez manuellement des glyphes aux pixels parfaits pour les caractĂšres Box Drawing et Block Elements

CrĂ©Ă© le 10 sept. 2019  Â·  24Commentaires  Â·  Source: xtermjs/xterm.js


DĂ©tails

  • Navigateur et version du navigateur: Chrome 76.0.3809.132 (64 bits), FireFox 69.0 (64 bits)
  • Version du systĂšme d'exploitation: Windows 7 Pro 64 bits
  • version xterm.js: ^ 3.14.5

Étapes à suivre pour reproduire

index.html:

<!doctype html>
<html>

<head>
    <link rel="stylesheet" href="node_modules/xterm/dist/xterm.css" />
    <script src="node_modules/xterm/dist/xterm.js"></script>
</head>

<body>
    <div id="terminal"></div>
    <script>
        var options = {
            rows: 30,
            cols: 80,
            fontFamily: '"Courier New", "DejaVu Sans Mono", "Everson Mono", FreeMono, "Andale Mono", monospace',
            fontSize: 12,
            convertEol: true
        };
        var term = new Terminal(options);
        term.open(document.getElementById('terminal'));

        term.write('           ╔═════════════════════════════════════════════════════════╕\n');
        term.write('           ║                                                         │\n');
        term.write('           ║              ╔═══════════════╊════════╀════════╗        │\n');
        term.write('           ║              ║               ║        │        ║        │\n');
        term.write('           ║              ║               ║        │        ║        │\n');
    </script>
</body>

</html>

image

Il y a plusieurs problÚmes liés mais cela n'aide pas:

https://github.com/xtermjs/xterm.js/issues/475
https://github.com/xtermjs/xterm.js/issues/992

arerenderer help wanted typenhancement

Commentaire le plus utile

J'ai fait quelques expériences avec le dessin manuel de certains personnages.
Page de démonstration: https://roguelike.solutions/xterm/xtermtest.html

Le code est approximatif, mais disponible ici: https://github.com/xtermjs/xterm.js/compare/master...guregu : box-drawing

Actuellement, il s'agit de deux parties, l'une est boxDrawingLineSegments qui emprunte un algorithme à iTerm2. Il définit 7 types de points d'ancrage verticaux et horizontaux arbitraires par cellule de caractÚre et trace des lignes ou des courbes qui leur correspondent. Cela fonctionne pour presque toutes les lignes de dessin de boßte, mais ne fonctionne pas pour les caractÚres en pointillés qui nécessitent plus de points d'ancrage. Avoir un contrÎle précis sur le dessin des lignes signifie également que nous n'avons pas besoin de couper horizontalement pour éviter les débordements. J'essaie de penser à une meilleure façon de les représenter qui fonctionnera également avec les lignes pointillées.
Peut-ĂȘtre qu'au lieu de diviser les cellules en 7 points quelque peu arbitraires, nous pouvons Ă  la place dĂ©finir des emplacements tels que «gauche», «centre», «centre moins n pixels devicePixelRatio», etc.
De plus, iTerm2 est GPL2 et j'ai essayĂ© de l'Ă©crire pour ĂȘtre aussi original que possible et Ă©viter les problĂšmes de licence, mais je ne sais pas oĂč la ligne figurative est dessinĂ©e ici. C'est une autre raison d'utiliser un algorithme original plus sophistiquĂ©. ConsidĂ©rez l'implĂ©mentation actuelle comme une preuve de concept.

Vient ensuite boxDrawingBoxes (nĂ©cessite un meilleur nom 😅) qui divise une cellule de caractĂšre en huitiĂšmes et remplit les rectangles qui leur correspondent. Cela suffit pour dessiner les caractĂšres du bloc solide, y compris les nouveaux du bloc Symbols for Legacy Computing. Cela devrait ĂȘtre suffisant pour prendre en charge les caractĂšres quadrants Ă©galement, mais pour prendre en charge les sextants, il faudra diviser les caractĂšres en sixiĂšmes. Permettre la dĂ©finition d'un diviseur serait suffisant pour prendre en charge la plupart des caractĂšres de type bloc.

Je ne prend pas encore en charge les caractĂšres polygonaux du bloc Symbols for Legacy Computing, mais l'utilisation de techniques similaires devrait fonctionner pour eux. Je ne sais pas trop comment dessiner les caractĂšres d'ombre comme les ° ░ ▓, mais peut-ĂȘtre qu'ils pourraient ĂȘtre spĂ©ciaux. Il y a aussi la question de savoir jusqu'oĂč nous voulons aller avec cela.

Pour nettoyer le code, nous pourrions peut-ĂȘtre dĂ©finir une interface pour dessiner des segments, et ses implĂ©menteurs pourraient ĂȘtre des lignes, des courbes, des n-iĂšmes boĂźtes, etc. Tout cela est trĂšs expĂ©rimental, mais si cela semble ĂȘtre une bonne idĂ©e, je le serais heureux de contribuer (et d'ajouter le support du moteur de rendu WebGL).

Tous les 24 commentaires

Je pense que cela dépend de la police utilisée, je ne peux pas reproduire en utilisant le moteur de rendu canvas (par défaut).

@Tyriar comment puis-je partager les informations nécessaires?

Pouvez-vous essayer d'utiliser cette police ? Votre fontFamily et Hack fonctionnent tous les deux pour moi sur ma boĂźte Windows 10.

J'ai essayé ce qui suit sur ma machine Windows 10 64 bits domestique dans le navigateur Yandex (basé sur Chromium):

<!doctype html>
<html>

<head>
    <link rel='stylesheet' href='//cdn.jsdelivr.net/npm/[email protected]/build/web/hack.css'>
    <link rel="stylesheet" href="node_modules/xterm/dist/xterm.css" />
    <script src="node_modules/xterm/dist/xterm.js"></script>
</head>

<body>
    <div id="terminal"></div>
    <script>
        var options = {
            rows: 30,
            cols: 80,
            fontFamily: 'Hack',
            fontSize: 12,
            convertEol: true
        };
        var term = new Terminal(options);
        term.open(document.getElementById('terminal'));

        term.write('           ╔═════════════════════════════════════════════════════════╕\n');
        term.write('           ║                                                         │\n');
        term.write('           ║              ╔═══════════════╊════════╀════════╗        │\n');
        term.write('           ║              ║               ║        │        ║        │\n');
        term.write('           ║              ║               ║        │        ║        │\n');
    </script>
</body>

</html>

Voici le résultat:
image

La mĂȘme chose sur Chrome:
image

J'ai Ă©galement essayĂ© d'imprimer dans Visual Studio Code avec le nƓud:
image

FYI: Certains terminaux, y compris gnome-terminal (vte) et konsole dessinent manuellement les caractĂšres U + 2500..257F (ou mĂȘme jusqu'Ă  259F), plutĂŽt que de les retirer de la police, afin de fournir un look magnifiquement connectĂ©.

Par coïncidence, ces deux émulateurs ont adopté une approche technique assez similaire: définir l'apparence de (la plupart de) ces glyphes comme une image bitmap 5x5 avec des tailles de "pixels" inégales qui sont calculées à l'exécution en fonction de la taille de la police.

@egmontkob Lulz, je me souviens avoir fait de mĂȘme dans mon ancien Ă©mulateur. Je me suis toujours demandĂ© pourquoi xterm.js ne montre pas ce comportement, mais n'a jamais enquĂȘtĂ©.

@Tyriar J'ai juste fait quelques tests avec diffĂ©rentes polices avec chrome et FF avec ces rĂ©sultats - je vois dans chaque moteur avec chaque police rĂ©pertoriĂ©e dans la dĂ©mo un petit espace (testĂ© dans le canevas et le moteur de rendu DOM). L'espace lui-mĂȘme varie avec la taille de la police et la police elle-mĂȘme, FF est d'un pixel avec un Ă©cart plus grand (nous avons ce dĂ©calage de pixel dans FF Ă©galement Ă  d'autres endroits / problĂšmes).

Conclusion: Toutes mes polices testées montrent des espaces (de peu visibles à un espace important), donc je pense que les glyphes ne couvrent tout simplement pas complÚtement la hauteur (juste une supposition, n'ont pas inspecté les glyphes uniques avec un outil de police). Les différences d'espaces sont principalement liées au rendu de police qui essaie de l'arrondir / l'aligner sur une taille de police donnée.

De plus, je ne vois aucun Ă©cart dans vscode (pas mĂȘme le moindre, testĂ© avec mc ). Vous ne savez pas ce que vscode fait diffĂ©remment ici, peut-ĂȘtre qu'un correctif gĂ©nĂ©ral peut emprunter cela? En plus de dessiner nos propres glyphes comme suggĂ©rĂ© par @egmontkob, nous pourrions nous en tirer avec une approche plus simple pour DOM - dessinez simplement ces points de code en question avec une taille de police lĂ©gĂšrement plus grande. Pour les autres moteurs de rendu oĂč nous maintenons des Ă©tats de glyphe de canevas de toute façon , l'approche de

Peut-ĂȘtre que vscode (ou du moins ma configuration) a de la chance avec sa taille de police, sa famille, le niveau de zoom de la fenĂȘtre, etc.

nous pourrions nous en sortir avec une approche plus simple pour DOM - dessinez simplement les points de code en question avec une taille de police légÚrement plus grande

Nous ne devons pas et ne devrions pas couper les cellules dans le moteur de rendu DOM, donc je ne pense pas que ce soit une option.

À condition que cela n'ajoute pas trop de code * nous pourrions coder en dur nos propres glyphes pour ceux-ci 👍, ce serait bien si cela Ă©tait cohĂ©rent avec le moteur de rendu DOM.

* J'ai des doutes Ă  ce sujet

Maintenant que # 2572 a été marqué comme dup, ce bogue concerne définitivement U + 2500..257F "Box Drawing" et U + 2580..259F "Block Elements" aussi.

Gardez Ă©galement un Ɠil sur les prochains (Unicode 13) U + 1FB00 "Symboles for Legacy Computing" , voir par exemple VTE 189 .

@egmontkob Lol, je suppose que ces nouveaux glyphes sont également censés s'aligner parfaitement? Décidément, qui a besoin d'un moteur de rendu de polices, si on peut le faire à la dure ...

J'adorerais comprendre les raisons pour lesquelles aucune des polices ne fonctionne correctement. Mais je n'ai ni le temps ni la motivation pour enquĂȘter.

Une chose intéressante que cela pourrait faire que les polices ne pourraient pas est de remplir la cellule entiÚre lorsqu'une hauteur de ligne est spécifiée.

Comportement amusant supplémentaire (terminal vscode):
out3
Pour moi, changer les tailles de police, en utilisant la police hack mentionnĂ©e prĂ©cĂ©demment n'aide pas, l'espacement reste. Cependant, Ă  en juger par le gif ci-dessus, les caractĂšres de bloc semblent ĂȘtre placĂ©s de maniĂšre incorrecte. Il y a un espace de pixel en bas et la diffĂ©rence entre les blocs 7/8 et 8/8 (pleins) semble plus petite qu'entre les autres.

Sur macOS (Ă©cran Retina, devicePixelRatio = 2) + Chrome, l'utilisation de la police Hack me donne de petits Ă©carts verticaux comme celui-ci:
Screen Shot 2020-04-28 at 20 44 51
Mais aprÚs avoir fouillé, j'ai remarqué que transformer BaseRenderLayer._clipRow en un no-op les rend correctement:
Screen Shot 2020-04-28 at 20 44 40
ce qui me porte Ă  croire que cela pourrait ĂȘtre un problĂšme d'Ă©crĂȘtage.

@guregu, le moteur de rendu du canevas de par sa conception doit

Ceci est toujours marquĂ© comme une aide recherchĂ©e et peut-ĂȘtre que cela ne peut / devrait ĂȘtre fait que dans le moteur de rendu webgl, auquel cas il s'agirait de gĂ©rer ces caractĂšres particuliers spĂ©cialement lors du dessin du caractĂšre sur l'atlas de texture:

https://github.com/xtermjs/xterm.js/blob/45077d710627fb2aec61ac2dfc41879d8c32371e/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts#L304 -L306

FWIW J'ai réussi à le réparer sans déranger le clipping.
Le problĂšme n'Ă©tait pas l'Ă©crĂȘtage, mais l'utilisation de middle comme textBaseline provoquait un lĂ©ger dĂ©salignement.
Changer le textBaseline en bottom totalement résolu le problÚme pour moi.
Diff: https://github.com/xtermjs/xterm.js/compare/master...guregu : maĂźtre
Je peux envoyer un PR si ça a l'air bien, mais je ne suis pas sûr que ça va gùcher autre chose.

Y a-t-il une raison particuliÚre pour laquelle il a été défini sur middle auparavant?
J'ai remarqué qu'il définit le texte normal légÚrement plus bas, mais cela ressemble à la façon dont Terminal.app rend le texte.

Voici une capture d'écran du code en cours d'exécution depuis le début de ce PR sans le correctif:
Screen Shot 2020-04-28 at 22 29 03
Le voici avec le correctif appliqué:
Screen Shot 2020-04-28 at 22 24 19

@guregu auparavant, le moteur de rendu webgl utilisait top, mais il a fini par aligner le texte en haut:

image

Je crains que cela n'arrive si nous utilisons bottom

Voir https://github.com/xtermjs/xterm.js/issues/2613 , https://github.com/xtermjs/xterm.js/issues/2645 , https://github.com/microsoft/vscode/issues / 95813

Ce n'est pas non plus parfait mĂȘme en ignorant le problĂšme d'alignement du bas (notez les encoches sur la ligne horizontale):

image

Je pense que dessiner manuellement des glyphes parfaits est la voie Ă  suivre.

La sortie Btw @ nojus297 ressemble Ă  peu prĂšs Ă  un problĂšme de dĂ©calage de 0,5 px. Je suis tombĂ© sur des problĂšmes d'anticrĂ©nelage avec un dĂ©calage de 0,5 moi-mĂȘme l'autre jour, lorsque j'ai jouĂ© avec des soulignements bouclĂ©s auto-dessinĂ©s. Je ne sais pas si cela s'applique ici du tout (toujours pas utilisĂ© pour le code de rendu lol).

Est-ce que vous pourriez Ă©galement vĂ©rifier votre niveau de zoom pour vous assurer qu'il est 1. Devrions-nous peut-ĂȘtre le baisser de 0,5 px lorsque la taille de la police est Ă©trange? đŸ€”

J'ai pris des captures d'Ă©cran de mes modifications et de la version inchangĂ©e et j'ai exĂ©cutĂ© une diffĂ©rence dessus. Le texte normal est en fait exactement le mĂȘme. La seule diffĂ©rence rĂ©side dans les caractĂšres du dessin de la boĂźte.
download
(le magenta est la partie différente)

Fondamentalement, le nƓud de ce problĂšme est que, pour une raison quelconque, le texte qui occupe toute la hauteur d'une cellule est poussĂ© vers le haut de quelques pixels et coupĂ© lors de l'utilisation de middle comme textBaseline .
Il est facile de le vérifier si vous le mettez en surbrillance.
XTERM_BROKE
^ version non fixĂ©e, vous pouvez voir qu'il y a quelques pixels vides au bas de la ║

En ce qui concerne les encoches sur la ligne horizontale, Terminal.app semble avoir le mĂȘme problĂšme. C'est peut-ĂȘtre un problĂšme de police? Aucune idĂ©e.
Capture d'Ă©cran de Terminal.app:
Screen Shot 2020-04-29 at 0 02 04

Cependant, mĂȘme avec les changements, je vois encore des bizarreries, comme l'utilisation du curseur provoque l'apparition de minuscules encoches noires. Cela ne se produit pas sur les versions rĂ©elles. Peut-ĂȘtre liĂ© aux autres encoches?
Cela provient de xterm.js et se produit sur les versions modifiées et inchangées:
rendering-oddness

Quoi qu'il en soit, je suis d'accord pour que le rendu de ces personnages soit spécialement la voie à suivre. J'essaie juste de trouver la raison pour laquelle cela se produit en premier lieu.

J'ai demandĂ© Ă  des amis de tester mon correctif sur Windows et cela ne fait qu'empirer les choses 😅
On dirait un boßtier spécial, c'est le seul moyen infaillible. Désolé pour ça.
Le problĂšme du curseur est probablement un problĂšme distinct. Effacer tout le canevas pendant clearCursor le corrige. On dirait que le caractĂšre de dessin de boĂźte horizontale dessine un peu plus large que la largeur de la cellule?

@guregu merci de l'avoir regardé.

On dirait que le caractĂšre de dessin de boĂźte horizontale dessine un peu plus large que la largeur de la cellule?

Peut-ĂȘtre, nous permettons cela. Quelque chose qui peut fonctionner est de couper le glyphe de caractĂšre Ă  la taille d'une cellule uniquement pour ces caractĂšres de dessin de boĂźte?

J'ai fait quelques expériences avec le dessin manuel de certains personnages.
Page de démonstration: https://roguelike.solutions/xterm/xtermtest.html

Le code est approximatif, mais disponible ici: https://github.com/xtermjs/xterm.js/compare/master...guregu : box-drawing

Actuellement, il s'agit de deux parties, l'une est boxDrawingLineSegments qui emprunte un algorithme à iTerm2. Il définit 7 types de points d'ancrage verticaux et horizontaux arbitraires par cellule de caractÚre et trace des lignes ou des courbes qui leur correspondent. Cela fonctionne pour presque toutes les lignes de dessin de boßte, mais ne fonctionne pas pour les caractÚres en pointillés qui nécessitent plus de points d'ancrage. Avoir un contrÎle précis sur le dessin des lignes signifie également que nous n'avons pas besoin de couper horizontalement pour éviter les débordements. J'essaie de penser à une meilleure façon de les représenter qui fonctionnera également avec les lignes pointillées.
Peut-ĂȘtre qu'au lieu de diviser les cellules en 7 points quelque peu arbitraires, nous pouvons Ă  la place dĂ©finir des emplacements tels que «gauche», «centre», «centre moins n pixels devicePixelRatio», etc.
De plus, iTerm2 est GPL2 et j'ai essayĂ© de l'Ă©crire pour ĂȘtre aussi original que possible et Ă©viter les problĂšmes de licence, mais je ne sais pas oĂč la ligne figurative est dessinĂ©e ici. C'est une autre raison d'utiliser un algorithme original plus sophistiquĂ©. ConsidĂ©rez l'implĂ©mentation actuelle comme une preuve de concept.

Vient ensuite boxDrawingBoxes (nĂ©cessite un meilleur nom 😅) qui divise une cellule de caractĂšre en huitiĂšmes et remplit les rectangles qui leur correspondent. Cela suffit pour dessiner les caractĂšres du bloc solide, y compris les nouveaux du bloc Symbols for Legacy Computing. Cela devrait ĂȘtre suffisant pour prendre en charge les caractĂšres quadrants Ă©galement, mais pour prendre en charge les sextants, il faudra diviser les caractĂšres en sixiĂšmes. Permettre la dĂ©finition d'un diviseur serait suffisant pour prendre en charge la plupart des caractĂšres de type bloc.

Je ne prend pas encore en charge les caractĂšres polygonaux du bloc Symbols for Legacy Computing, mais l'utilisation de techniques similaires devrait fonctionner pour eux. Je ne sais pas trop comment dessiner les caractĂšres d'ombre comme les ° ░ ▓, mais peut-ĂȘtre qu'ils pourraient ĂȘtre spĂ©ciaux. Il y a aussi la question de savoir jusqu'oĂč nous voulons aller avec cela.

Pour nettoyer le code, nous pourrions peut-ĂȘtre dĂ©finir une interface pour dessiner des segments, et ses implĂ©menteurs pourraient ĂȘtre des lignes, des courbes, des n-iĂšmes boĂźtes, etc. Tout cela est trĂšs expĂ©rimental, mais si cela semble ĂȘtre une bonne idĂ©e, je le serais heureux de contribuer (et d'ajouter le support du moteur de rendu WebGL).

Tout cela est trĂšs expĂ©rimental, mais si cela semble ĂȘtre une bonne idĂ©e, je serais heureux de contribuer (et d'ajouter le support du moteur de rendu WebGL).

@guregu beau travail, une contribution serait gĂ©niale, il vous suffit de vous assurer qu'elle n'est pas trop dĂ©rivĂ©e de l'algorithme iTerm2 car la GPL2 est collante. Je suggĂ©rerais de ne faire cela que pour le moteur de rendu webgl (pas pour le canevas car il va ĂȘtre mis au rebut). DĂ©finitivement basĂ© les lignes sur devicePixelRatios afin que la largeur soit excellente sur tous les moniteurs.

mais l'utilisation de techniques similaires devrait fonctionner pour eux. Je ne sais pas comment dessiner les caractùres d'ombre comme les ° ░ ▓

Celles-ci devraient ĂȘtre relativement faciles Ă  faire, mais elles pourraient Ă©galement ĂȘtre facilement diffĂ©rĂ©es. Le problĂšme principal dans ce domaine est celui du solide.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

fabiospampinato picture fabiospampinato  Â·  4Commentaires

zhangjie2012 picture zhangjie2012  Â·  3Commentaires

jestapinski picture jestapinski  Â·  3Commentaires

kolbe picture kolbe  Â·  3Commentaires

jerch picture jerch  Â·  3Commentaires