IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SDL Discussion :

Chargement de font avec SDL_RWFromMem


Sujet :

SDL

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Points : 1 053
    Points
    1 053
    Par défaut Chargement de font avec SDL_RWFromMem
    Salut à tous.
    Voila, je suis en train de créer mon petit wrapper C++ autour de SDL.
    J'ai un petit problème avec le chargement de fonts. Quand j'essaie de les charger depuis un fichier avec la fonction prévue pour tout fonctionne. Mais dés que j'essaie à partir de la mémoire, sdl semble me générer une structure TTF_Font érronée. Non pas que la fonction OpenFont me renvoie NULL, mais dés que j'essaie de faire un renderSolid() ou autre le programme plante. Voici ce à quoi ressemble mon code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    		vector<char> vec(size);
    		stream.read(&vec[0],size);
    		SDL_RWops* wop = SDL_RWFromMem(&vec[0],size);
    		if(wop == NULL)
    			throw exceptionSDL();
    		TTF_Font* cfont = TTF_OpenFontIndexRW(wop,true,ptsize,index);
    Quelques remarques:
    - En vérifiant avec un debuggeur, je peux voir que le vector contient exactement les même bytes que mon fichier.
    - Le fait qu'il s'agisse d'un vector n'est pas un problème non plus, j'ai déja utilisé la même astuce avec des images et ca fonctionne impecable, et j'ai aussi testé avec un char* tout simple.
    - Je suis certain que c'est bel et bien ce morceau de code qui pose problème puisque si je le remplace par un chargement classique d'une image à partir d'un fichier ca fonctionne parfaitement.
    - Le pointeur renvoye par OpenFontIndexRW n'est pas null.

    Bon, voila, si je pose cette question c'est que je commence vraiment à être désèspéré parceque je tourne en rond depuis des heures sans trouver l'erreur dans ce morceau de code minuscule, j'en viens à me demander si il ne s'agirait pas d'un bug de sdl_ttf. Merci à tous ceux qui me répondront.

  2. #2
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Es-tu sûr de ton code ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector<char> vec(size);
    Déclare un vecteur de caractères pas un vecteur d'un tampon de caractères...

    Cette nuance est primordiale vu que lorsque tu fais ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    stream.read(&vec[0],size);
    Cela va indéniablement lui posé un petit problème puisque vec[0] a été créé pour contenir un caractère pas size caractères...

    Jc

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Points : 1 053
    Points
    1 053
    Par défaut
    Je ne luis passe pas un caractère mais l'adresse du premier caractère de ma séquence (d'ailleurs ca aurait fait un warning à la compilation). Le constructeur de vector que j'apelle initialize la taille initiale du vecteur, pas sa capacité. Donc je ne vois pas ou peut être l'erreur, sans compter que ca fonctionne très bien avec les images et que le debuggeur m'affiche un vecteur de la bonne taille avec les bon octets (j'ai vérifié avec un editeur hexadécimal).

  4. #4
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Exact, donc la seule différence si les zones mémoires sont les mêmes c'est que dans la nouvelle version tu utilises plus de mémoire.

    Il est donc possible que tu provoques un conflit avec un dépassement mémoire précédent. Si les données sont exactement les mêmes entre le chargement d'un fichier et le chargement de la mémoire, il n'y a pas de raison que le reste change sauf dans le cas d'un débordement mémoire.

    Est-ce que tu arrives à faire un programme minimal compilable qui présente ce problème ?

    Jc

    PS: Désolé mais pour moi, rien ne prouve que vector mets toutes les données en contigü (donc vec[0] et vec[1] ne sont pas forcément l'un à côté de l'autre... Je ne l'ai pas vu écrit donc je n'en suis pas sûr, d'où ma remarque).

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Points : 1 053
    Points
    1 053
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    		char* vec = new char[size];
    		stream.read(vec,size);
    		SDL_RWops* wop = SDL_RWFromConstMem(vec,size);
    		if(wop == NULL)
    			throw exceptionSDL();
    		TTF_Font* cfont = TTF_OpenFontIndexRW(wop,true,ptsize,index);
    		delete vec;
    Resultat: exactement la même chose. Si ce n'est que c'est beaucoup moins clean car si jamais une exception est lancée la mémoire ne sera pas libérée. Qui plus est, le vector stocke toujours ses éléments de manière contigue, il n'y a que le deque qui ne le fait pas.
    Pour ce qui est du programme minimal, je vais jeter un coup d'oeil à ca.

  6. #6
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par zais_ethael
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    		char* vec = new char[size];
    		stream.read(vec,size);
    		SDL_RWops* wop = SDL_RWFromConstMem(vec,size);
    		if(wop == NULL)
    			throw exceptionSDL();
    		TTF_Font* cfont = TTF_OpenFontIndexRW(wop,true,ptsize,index);
    		delete vec;
    Resultat: exactement la même chose. Si ce n'est que c'est beaucoup moins clean car si jamais une exception est lancée la mémoire ne sera pas libérée. Qui plus est, le vector stocke toujours ses éléments de manière contigue, il n'y a que le deque qui ne le fait pas.
    Pour ce qui est du programme minimal, je vais jeter un coup d'oeil à ca.
    Je m'en doutais en effet. Je crains que le problème vienne plus d'un débordement mémoire qui provoque un comportement indéfini dans ton code.

    Un code minimal aidera à cerner le problème.
    Jc

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Points : 1 053
    Points
    1 053
    Par défaut
    Et ben en fait, ca n'a strictement rien à voir
    L'astuce, qui n'est pas du tout spécifiée dans la doc, est de ne surtout pas désallouer la zone mémoire. Voici un code qui expose clairement la marche à suivre (il est pas terrible pour la gestion d'erreurs mais ca ira):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
     
    #include <stdlib.h>
    #include <sdl.h>
    #include <sdl_ttf.h>
     
     
    int main(int argc, char** argv) {
    	SDL_Surface* surface;
    	TTF_Font* font;
    	SDL_Color c;
    	SDL_Rect src;
    	SDL_Rect dst;
    	SDL_Surface* texte;
    	FILE* thefile;
    	char* filecont;
    	int filesize;
    	SDL_RWops* wop;
     
    	SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
    	TTF_Init();
     
    	surface = SDL_SetVideoMode(640,480,32,SDL_HWSURFACE|SDL_DOUBLEBUF);
    	if(surface==NULL)
    		printf("surface pas initialisée\n");
     
    	thefile = fopen("COMIC.TTF","rb");
    	fseek(thefile,0,SEEK_END);
    	filesize=ftell(thefile);
    	fseek(thefile,0,SEEK_SET);
    	filecont=malloc(filesize);
    	fread(filecont,1,filesize,thefile);
    	wop=SDL_RWFromConstMem(filecont,filesize);
    	font = TTF_OpenFontRW(wop,1,40);
    	//Enlevez le commentaire et ca ne fonctionne plus.
    	//free(filecont);
     
    	c.b=255;
    	c.g=0;
    	c.r=255;
    	texte = TTF_RenderText_Solid(font,"salut le monde!!!",c);
    	if(texte==NULL)
    		printf("erreur à la création du texte\n");
     
    	src.x=0;
    	src.y=0;
    	src.w=texte->w;
    	src.h=texte->h;
    	dst.x=1;
    	dst.y=1;
    	dst.w=texte->w;
    	dst.h=texte->h;
    	if(SDL_BlitSurface(texte,&src,surface,&dst)<0)
    		printf("erreur au blit\n");
    	if(SDL_Flip(surface)<0)
    		printf("erreur au flip");
     
    	SDL_Delay(5*1000);
     
    	SDL_FreeSurface(surface);
    	TTF_CloseFont(font);
    	SDL_FreeSurface(texte);
     
    	TTF_Quit();
    	SDL_Quit();
    	return 0;
    }
    Donc, en un sens, c'était effectivement le vector qui posait problème .
    Par contre je me demande si le TTF_CloseFont va corectement la libérer cette mémoire... un truc que j'irais bien demander sur le site officiel.

  8. #8
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Effectivement, cela est étrange d'avoir laissé une implémentation ambigüe et une documentation aussi mal faite.

    Ok, en regardant les sources et la documentation de façon plus compléte, j'ai trouvé les explications :

    - Il ne faut pas désallouer la source jusqu'à la fermeture de ta police (ça tu l'avais trouvé)
    - Dépendant de la valeur du deuxième paramètre, lors de l'appel TTF_CloseFont, la zone mémoire pour le wop sera désallouée.
    - De toute façon, ton vecteur ne sera pas désalloué (ben oui, SDL ne peut pas savoir si cela provient d'une zone mémoire statique ou dynamique par exemple)

    Bref, dépendant si tu veux créer plusieurs polices avec le même wop, il faudrait mettre le deuxième paramètre à 0 et gérer la désallocation toi-même, soit faire un wop par police et donc le mettre à 1.

    C'est donc quelque chose à garder en tête,
    Jc

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Points : 1 053
    Points
    1 053
    Par défaut
    Ok, je ne vais pas avoir grand chose à modifier pour ca, mais il est vrai que ce type de fonctionnement est bien étrange. Qui plus est, dans le cas de l'ouverture d'un fichier je suppose que le fichier reste ouvert pendant toute la durée du programme, c'est pas ce qu'il y a de plus clean non plus.

  10. #10
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par zais_ethael
    Ok, je ne vais pas avoir grand chose à modifier pour ca, mais il est vrai que ce type de fonctionnement est bien étrange. Qui plus est, dans le cas de l'ouverture d'un fichier je suppose que le fichier reste ouvert pendant toute la durée du programme, c'est pas ce qu'il y a de plus clean non plus.
    C'est exact, il garde le descripteur ouvert mais il le ferme après lors du Close.

    Jc

Discussions similaires

  1. [HTML] chargement du fichier avec la balise <embed>
    Par dinozor29 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 5
    Dernier message: 06/10/2005, 12h11
  2. PB de chargement de combobox avec une requete
    Par bubu1905 dans le forum Bases de données
    Réponses: 9
    Dernier message: 23/03/2005, 16h14
  3. Réponses: 4
    Dernier message: 28/10/2004, 10h57
  4. chargement de texture avec la SDL
    Par Fry dans le forum OpenGL
    Réponses: 7
    Dernier message: 27/05/2004, 15h31
  5. Fonts avec c++ Builder
    Par Arnaud-h dans le forum C++Builder
    Réponses: 4
    Dernier message: 19/03/2004, 11h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo