Nous avons déjà vu au cours de certains exemples de ce Tutorial, comment effacer l'écran, afficher une ligne, ou comment sauvegarder puis restaurer l'écran...
Mais ce chapître va nous permettre d'aller une étape plus loin, puisqu'il va nous permettre de découvrir une partie des fonctions du TIOS permettant de réaliser simplement des affichages graphiques, en noir et blanc.
Nous avons déjà utilisé la fonction printf pour afficher du texte à l'écran... Mais nous allons voir, au cours de cette partie, qu'il y a d'autres possibilités, plus avancées.
Tout d'abord, rappelons rapidement que la fonction DrawStr permet d'afficher une chaîne de caractères à la position souhaitée sur l'écran ; voici son prototype :
Cela dit, pourquoi se limiter à la taille de police par défaut, qui, qui plus est, n'est pas toujours la même, puisqu'elle dépend souvent de ce que vous faisiez avant de lancer votre programme, de la façon dont il a été lancé, et de la plate-forme sur laquelle il s'exécute ?
En effet, le TIOS vous propose une fonction qui permet de déterminer quelle est la police actuellement sélectionnée ; voici son prototype :
A présent, principalement pour montrer qu'il existe d'autres fonctions, en voici deux qui peuvent vous être utiles.
Tout d'abord, la fonction DrawChar, qui permet d'afficher le caractère que vous voulez à la position que vous voulez ; voici son prototype :
Une autre fonction qui peut vous être utile, par exemple si vous souhaitez centrer une chaîne de caractères sur l'écran, est la fonction DrawStrWidth, dont le prototype est le suivant ; elle permet de déterminer la longueur d'une chaîne de caractère en fonction d'une des trois tailles de police que nous avons déjà évoqué :
A présent, nous allons voir quelques fonctions nous permettant d'afficher des graphismes simples à l'écran. Nous commencerons par une fonction permettant d'afficher des pixels, puis nous passerons à l'affichage de lignes.
Notez que les fonctions que nous verrons au cours de cette partie ne fonctionnent que si leurs coordonnées sont valides : vous ne devez pas essayer d'afficher quelque chose en dehors de l'écran avec ces fonctions ! Dans le cas contraire, votre programme risque de planter !
Nous verrons au cours de la partie suivante qu'il existe d'autres fonctions, pour lesquelle ce problème ne se pose pas.
Tout d'abord, commençons par afficher des pixels seuls. Pour cela, on utilise cette fonction :
Et voici un petit exemple :
Simple, n'est-ce pas ?
Souvenez-vous juste que les coordonnées doivent correspondre à des points valides, ce qui signifie que x doit varier entre 0 et 239 compris, et que y doit être compris entre 0 et 127 inclus.
A présent, nous allons voir comment il nous est possible d'afficher des lignes à l'écran. Puisque vous connaissez le nom de la fonction d'affichage de pixels, il devrait vous être relativement simple de deviner celui de la fonction de tracés de lignes, dont le prototype est le suivant :
Et voici un petit exemple de programme traçant trois lignes en utilisant des modes différents :
Les fonctions que nous venons d'étudier nous permettent déjà d'afficher quelques graphismes simples... Cela dit, nous devons, en les employant, prendre garde à ne pas dépasser de l'écran, sous peine de plantages de notre programme.
Pour remédier à ce problème, nous allons voir qu'il existe la notion de "clipping", et des fonctions utilisant ce principe.
"Clipper" un graphisme par rapport à une "zone de clipping" signifie ne conserver de ce graphisme que les parties qui se trouvent sur ladite zone de clipping.
Je pense que ceci sera plus compréhensible avec un exemple et un petit schéma...
Admettons que l'on veuille tracer une ligne entre deux points A et B. Ces deux points sont en dehors de la zone de clipping que l'on accepte, celle-ci étant souvent l'écran.
Etant donné qu'afficher des graphismes en dehors de l'écran peut provoquer un plantage de notre programme, il va nous falloir éliminer les portions de la ligne qui ne sont pas sur celui-ci, comme ceci :
La rectangle rouge correspond à notre zone de clipping ; les deux points A et B, les extrémités de la ligne, sont en dehors de celle-ci...
Le fait de clipper par rapport à notre zone de clipping aura pour effet d'éliminer les deux parties bleues de la ligne, ce qui nous permettra de ne conserver que la partie verte, que nous pourrons alors afficher sans danger.
Le TIOS nous fourni de nombreuses fonctions graphiques avec clipping. Nous n'en verrons que quelques unes, afin d'illustrer leur principe de fonctionnement, et je vous laisse vous reporter à la documentation pour toutes les connaître.
Certaines fonctions du TIOS travaillent avec une zone de clipping par défaut. C'est par exemple le cas de la fonction suivante, qui permet d'afficher un pixel :
Pour ces fonctions, la zone de clipping doit être fixée en utilisant la fonction SetCurClip, dont le prototype est le suivant :
Cette fonction prend en paramètre un pointeur sur une union de type SCR_RECT, qui est définie de la manière suivante :
Donc pour définir une zone de clipping pour les fonctions telles DrawClipPix, il nous est possible d'utiliser quelque chose comme ceci (Dans ce cas, on définit comme zone de clipping une surface correspondant à l'écran d'une TI-92+ ou v200 ; on aurait pu choisir d'autres valeurs, naturellement) :
Cela dit, si vous n'avez pas l'intention d'utiliser plusieurs fois votre variable que nous avons ici appelé "rect", vous pouvez, du fait que TIGCC est un compilateur GNU-C, utiliser ce type de syntaxe, plus concise :
En revanche, une bonne partie des fonctions de graph.h - la plupart, en fait - prennent la zone de clipping en paramètre, sous forme, ici aussi, d'une union de type SCR_RECT.
Par exemple, pour afficher un caractère, une élipse, ou un triangle, vous pourrez utiliser une des fonctions qui suit :
Et voici un petit exemple utilisant deux de ces fonctions :
La variable ScrRect est définie au niveau de TIGCC comme un pointeur sur un SCR_RECT faisant la taille de l'écran ; plus rapide à utiliser qu'à re-définir !
Et voici les captures d'écran correspondantes : sur la première, la zone de clipping est l'écran. Sur la seconde, elle est plus petite ; les graphismes sont donc "coupés" :
Ce qui nous montre toute l'efficacité du clipping.
Pour finir, deux dernières fonctions que je souhaite vous présenter ici :
Comme leurs noms respectifs l'indiquent, ces fonctions permettent d'afficher une ligne et un rectangle, avec clipping.
Leur particularité, qui explique qu'elles méritent de figurer ici est qu'elles prennent en paramètre un pointeur sur une struture de type WIN_RECT pour désigner les deux points constituant les extrémités de la droite, ou les deux coins supérieur gauche et inférieur droit du rectangle.
Cette structure est définie ainsi :
Comme pour les unions de type SCR_RECT, on peut utiliser deux types de syntaxe :
Tout d'abord, la syntaxe la plus "conventionnelle", si je puis dire :
Ou alors, en utilisant les cast-constructor du GNU-C :
Vous ne manquerez pas de noter que, une fois encore, on a utilisé ScrRect pour signifier que nous voulions utiliser tout l'écran comme zone de clipping.
Pour terminer ce chapitre, nous allons voir une série de fonctions dont le but est de nous permettre d'enregistrer ou d'afficher des images complètes.
Tout d'abord, nous allons voir comment encoder une image directement dans notre programme, afin de l'afficher par la suite.
La fonction que nous utiliserons au cours de cette partie pour afficher des images est BitmapPut ; son prototype est le suivant :
Le troisième argument attendu par cette fonction est un pointeur sur une struture de type BITMAP, définie comme ceci :
Cette structure correspond à un descripteur d'image : elle permet de mémoriser, en nombre de pixels, le nombre de lignes et le nombre de colonnes de l'image ; ces informations sont ensuite suivies des données de l'image elle-même, ligne par ligne, de gauche à droite.
Chaque pixel de l'image est encodé sous forme d'un bit, valant 1 si le pixel est noir et 0 sinon. Si la largeur de l'image n'est pas multiple de 8, les données des derniers octets de droite doivent être complétées par des 0, afin que l'on ait des octets complets.
Et voici un petit exemple où on déclare puis affiche une image de 16 pixels de coté :
Et une capture d'écran de notre programme lors de son exécution :
Notons que BitmapPut est surtout adaptée à l'affichage de grandes images : pour des images de 8x8, 16x16, ou 32x32, nous aurions plutôt tendance, en pratique, à utiliser des fonctions d'affichage de sprites, telles celles que nous étudierons plus loin au cours de ce tutorial.
A présent, nous allons voir comment sauvegarder une portion d'image affichée à l'écran, afin de pouvoir, par la suite, l'afficher avec BitmapPut, que nous avons déjà utilisé.
Pour enregistrer une portion d'image, nous utiliserons la fonction BitmapGet, dont le prototype est le suivant :
Cette fonction va sauvegarder les données contenues dans le rectangle décrit par son premier paramètre vers la zone mémoire sur laquelle pointera son second paramètre.
Cela signifie que nous allons avoir besoin d'une zone mémoire de taille suffisante... Pour calculer cette taille, nous allons utiliser la fonction BitmapSize, qui, elle aussi, prend en paramètre la zone de l'écran que l'on veut sauvegarder, et retourne le nombre d'octets dont nous allons avoir besoin :
Maintenant que nous connaissons la taille du bloc mémoire dont nous avons besoin pour sauvegarder notre portion d'image, nous pouvons, par exemple, l'allouer gràce à un malloc, puis, appeler BitmapGet, en lui passant en paramètre l'adresse de ce bloc mémoire.
Pour réafficher notre image, nous faisons comme plus haut. Voici un exemple illustrant mes propos :
Vous noterez que, comme nous l'avons appris un peu plus tôt, nous avons pensé à vérifier que l'allocation mémoire avait bien réussi, et nous n'avons pas oublié de libérer la mémoire allouée.
Etant donné que le programme que nous venons d'écrire sauvegarde une portion de l'écran, il peut être intéressant de savoir ce que celui-ci contenait au moment où j'ai exécuté le-dit programme :
Et voici l'affichage obtenu au cours de l'exécution de notre programme : on reconnait aisément la portion d'écran sauvegardée, et ré-affichée :
Naturellement, selon ce que vous avez d'affiché à l'écran au moment où vous lancez ce programme, il est probable que vous obteniez une sortie différente...
Notez aussi que le programme que j'ai choisi pour illustrer mes propos a été conçu pour une taille d'écran de TI-92+ ou de Voyage 200. Si vous avez une TI-89, je vous laisse le loisir de l'adapter - arrivé à ce niveau du Tutorial, vous devriez y parvenir sans difficulté.
Pour le dernier point de cette partie, nous allons voir comment afficher à l'écran le contenu d'un fichier de type "PIC" - les images du TIOS. Pour l'exemple, je vais utiliser une des images fournie avec txtrider (notez que les images de txtrider sont compressées ; il m'a donc fallu la décompresser auparavant). Voici comment elle apparait une fois affichée dans l'écran graph, et dans le VAR-LINK :
Pour afficher une image contenue dans un fichier PIC, nous allons utiliser une fonction fournie dans la FAQ de TIGCC. Tout simplement, cette fonction prend en paramètre le nom du fichier sous forme d'un SYM_STR, ce qui implique d'utiliser la macro SYMSTR pour l'obtenir depuis une chaine de caractères, ainsi que les coordonnées où l'on veut afficher l'image, et le mode dans lequel on veut réaliser la sortie écran.
Et voici un petit exemple utilisant la fonction show_picvar qui nous est proposée dans la documentation, qui affiche à l'écran l'image que je vous ai présenté un peu plus haut :
Et voici une capture d'écran prise pendant l'exécution du programme :
Naturellement, libre à vous de modifier cette fonction si vous souhaitez obtenir un comportement différent !
Le prochain chapitre va nous permettre de voir ce qu'est la "VAT", et comment s'en servir, voire la manipuler.
Plus loin au cours de ce tutorial, nous aurons l'occasion de revenir sur l'affichage de graphismes, que ce soit en niveaux de gris, ou en utilisant des sprites...