Pour justifier ses DrawText()

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Pour justifier ses DrawText()

Message par graph100 »

J'en ai eu besoin alors j'ai codé une fonction DrawJustifiedText() qui permet de dessiner un texte mais en le justifiant,
un peu comme word.
Cette fonction est assez lente, cependant elle suffit pour un rendu sur image / sprite pour une utilisation plus tard.

si cela vous est utile :D :

Code : Tout sélectionner

;{ initialisation

w = 800
h = 600

If InitSprite() = 0 Or InitKeyboard() = 0
	End
EndIf

;}

;{ PROCEDURE

Structure JustifiedText
	text.s
	longueur.l
EndStructure

Procedure DrawJustifiedText(x.l, y.l, Text.s, largeur_de_justification.l, FrontColor.l = -1, BackColor.l = -1, coefficient_d_acceptation_de_retour_a_la_ligne.l = 5) ; Dessine un texte sur la surface de dessin, on appliquant une justification, retourne la hauteur du texte justifié
	
	;{ initialisation
	
	; on enlève une erreur possible
	If BackColor > -1 And FrontColor = -1 : FrontColor = 0 : EndIf
	
	y1 = y ; nécessaire pour retourner la hauteur de tout le texte écrit
	
	nb_ligne.l = CountString(Text, Chr(13)) + 1 ; nombre de ligne séparée par un chr(13)
	
	NewList mot.JustifiedText()
	taille_espace.l = TextWidth(" ")
	
	;}
	
	;{ on itère pour chaque ligne
	For a = 1 To nb_ligne
		partie$ = StringField(Text, a, Chr(13)) ; stockage de la ligne
		h.l = TextHeight(partie$) ; hauteur de la ligne courante
		
		nb_space.l = CountString(partie$, " ") + 1
		
		;{ initialisation de tout les paramètres
		ClearList(mot())
		
		largeur.l = 0
		largeur_space.l = 0
		;}
		
		;{ on itère pour chaque mot
		For b = 1 To nb_space
			tmp.JustifiedText\text = StringField(partie$, b, " ") ; stockage du mot en cours
			tmp\longueur = TextWidth(tmp\text) ; calcul de sa longueur graphique
			
			If ListSize(mot()) = 0 And tmp\longueur > largeur_de_justification
				;{ si il n'y a pas de mot en mémoire, et que le mot est trop long, alors on le stock pour le découper plus bas
				AddElement(mot())
				mot()\text = tmp\text
				mot()\longueur = tmp\longueur
				
				;}
				
			ElseIf largeur + taille_espace + tmp\longueur > largeur_de_justification
				;{ Si le mot courrant fait que la ligne ne tient plus dans la largeur de justification, alors on ecrit la ligne, et on stocke le mot courant pour la ligne suivante
				
				; définition de la taille des espaces
				If ListSize(mot()) > 1
					espace.l = (largeur_de_justification - largeur_space) / (ListSize(mot()) - 1)
				Else
					espace = taille_espace
				EndIf
				
				; içi on regarde le rapport de grandissement des nouveaux espaces par rapport aux normaux : en gros, si les espaces sont trop grand, on les remet à leur taille normal
				; et la ligne n'est pas justifié (mais sinon c'est moche), on peut régler ça avec le paramètre 'coefficient_d_acceptation_de_retour_a_la_ligne'
				If espace	/ taille_espace > coefficient_d_acceptation_de_retour_a_la_ligne : espace = taille_espace : EndIf
				
				curs = 0
				
				;{ on itère pour chaque mot à écrire
				ForEach mot()
					
					; on dessine la même chose, mais comme il faut tenir compte des paramètres optionnels de couleur, c'est la galère !
					; j'ai essayé d'émuler ça avec les valeurs par défaut de -1 et des IF partout...
					If FrontColor > -1 And BackColor = -1
						DrawText(x + curs, y, mot()\text, FrontColor)
					ElseIf BackColor > -1
						DrawText(x + curs, y, mot()\text, FrontColor, BackColor)
					Else
						DrawText(x + curs, y, mot()\text)
					EndIf
					
					; on avance le curseur
					curs = curs + mot()\longueur + espace
					
					;{ dessin du fond, si une couleur d'arrière plan est spécifiée
					;  (ce qui veux dire que comme je ne peux pas récupérer la couleur spécifiée par BackColor(#), il y aura des trous partout autour du texte si on ne spécifie pas de BackColor)
					If BackColor > -1 And ListIndex(mot()) + 1 <> ListSize(mot())
						Box(x + curs - espace, y, espace, h, BackColor)
					EndIf
					;}
					
				Next
				;}
				
				;{ initialisation d'une nouvelle ligne
				largeur = 0
				largeur_space = 0
				largeur = tmp\longueur
				largeur_space = largeur
				
				ClearList(mot())
				
				AddElement(mot())
				mot()\text = tmp\text
				mot()\longueur = tmp\longueur
				;}
				
				;{ on dessine la fin de ligne, si besoin
				If BackColor > -1
					Box(x + curs - espace, y, largeur_de_justification - curs + espace, h, BackColor)
				EndIf
				;}
				
				; incrémentation de l'ordonnée
				y = y + h
				
				;}
				
			Else
				;{ ajout de mots dans la mémoire, tant qu'ils ne dépassent pas de la justification
				
				If largeur = 0
					largeur = tmp\longueur
					largeur_space = largeur
				Else
					largeur = largeur + taille_espace + tmp\longueur
					largeur_space = largeur_space + tmp\longueur
				EndIf
				
				AddElement(mot())
				mot()\text = tmp\text
				mot()\longueur = tmp\longueur
				
				;}
			EndIf
			
			;{ boucle nécessaire pour s'occuper des mots trop long pour entrer sur une ligne
			Repeat
				If ListSize(mot()) = 1 And mot()\longueur > largeur_de_justification
					; on a donc un seul mot, trop grand pour une ligne
					
					mot$ = ""
					
					mot1$ = mot()\text
					
					;{ on test pour chaque nouvelle lettre du mot si ca rentre dans la ligne
					For c = 1 To Len(mot1$)
						mot$ = mot$ + Mid(mot1$, c, 1)
						
						If TextWidth(mot$ + "-") > largeur_de_justification
							;c - 1
							
							;{ on regarde si c'est la fin du mot, ou si faut mettre un tiret
							If c < Len(mot1$)
								If FrontColor > -1 And BackColor = -1
									DrawText(x, y, Mid(mot1$, 1, c) + "-", FrontColor)
								ElseIf BackColor > -1
									DrawText(x, y, Mid(mot1$, 1, c) + "-", FrontColor, BackColor)
								Else
									DrawText(x, y, Mid(mot1$, 1, c) + "-")
								EndIf
								
								DeleteElement(mot())
								
								AddElement(mot())
								
								mot()\text = Mid(mot1$, c + 1, Len(mot1$) - c)
								mot()\longueur = TextWidth(mot()\text)
								
								largeur = mot()\longueur
								largeur_space = mot()\longueur
							Else
								If FrontColor > -1 And BackColor = -1
									DrawText(x, y, Mid(mot1$, 1, c), FrontColor)
								ElseIf BackColor > -1
									DrawText(x, y, Mid(mot1$, 1, c), FrontColor, BackColor)
								Else
									DrawText(x, y, Mid(mot1$, 1, c))
								EndIf
								
								DeleteElement(mot())
								
								largeur = 0
							EndIf
							;}
							
							Break
						EndIf
						
					Next
					;}
					
					; incrémentation de l'ordonnée
					y = y + h
				EndIf
				
			Until largeur <= largeur_de_justification
			;}
			
		Next
		;}
		
		;{ on répète le code de tout à l'heure pour traiter les dernières lignes
		If ListSize(mot()) > 0
			
			If ListSize(mot()) > 1
				espace.l = (largeur_de_justification - largeur_space) / (ListSize(mot()) - 1)
			Else
				espace = taille_espace
			EndIf
			
			If espace	/ taille_espace > coefficient_d_acceptation_de_retour_a_la_ligne : espace = taille_espace : EndIf
			
			curs = 0
			
			ForEach mot()
				If FrontColor > -1 And BackColor = -1
					DrawText(x + curs, y, mot()\text, FrontColor)
				ElseIf BackColor > -1
					DrawText(x + curs, y, mot()\text, FrontColor, BackColor)
				Else
					DrawText(x + curs, y, mot()\text)
				EndIf
				
				curs = curs + mot()\longueur + espace
				
				If BackColor > -1 And ListIndex(mot()) + 1 <> ListSize(mot())
					Box(x + curs - espace, y, espace, h, BackColor)
				EndIf
				
			Next
			
			If BackColor > -1
				Box(x + curs - espace, y, largeur_de_justification - curs + espace, h, BackColor)
			EndIf
			
			y = y + h
		EndIf
		;}
		
	Next
	;}
	
	ProcedureReturn y - y1
EndProcedure

;}

;{ lancement de la fenetre et du screen

If OpenWindow(0, 0, 0, w, h, "Test : Texte justifié", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	If OpenWindowedScreen(WindowID(0), 0, 0, w, h, 0, 0, 0)
		
	EndIf
EndIf

text$ = "Les lapins sont présents un peu partout sur la planète et se répartissent en neuf genres, tous classés dans la famille des léporidés, avec leurs proches parents les lièvres. Ce ne sont donc pas des rongeurs mais des lagomorphes, une branche cousine qui comprend les lièvres, les lapins et les pikas." + Chr(13) + "Les « lapins » sont classées dans les genres suivants de la famille des Léporidae : Brachylagus, Bunolagus, Caprolagus, Nesolagus, Oryctolagus (lapin commun), Pentalagus, Poelagus, Pronolagus, Romerolagus ou Sylvilagus." + Chr(13) + "Sept de ces genres ne comprennent qu'une seule espèce, le genre Nesolagus comprend deux espèces, le genre Pronolagus en comprend trois et le genre Sylvilagus ou lapins d'Amérique, comprend quinze espèces, soit au moins 27 espèces différentes de lapins en tout."


;}


;{ boucle principale

Repeat
	event = WaitWindowEvent()
	
	ExamineKeyboard()
	
	;{ event clavier
	
	If KeyboardReleased(#PB_Key_Escape) : event = #PB_Event_CloseWindow : EndIf
	
	;}
	
	;{ dessin
	
	If StartDrawing(ScreenOutput())
		
		time = ElapsedMilliseconds()
		x = 50 : y = 25 : w = 250 : h = DrawJustifiedText(x, y, text$, w, 0, #White)
; 		Debug ElapsedMilliseconds() - time
		
		LineXY(x - 2, y - 2, x - 2, y + h + 2, #Red)
		LineXY(x + w + 2, y - 2, x + w + 2, y + h + 2, #Red)
		
		LineXY(x - 2, y - 2, x + w + 2, y - 2, #Red)
		LineXY(x - 2, y + h + 2, x + w + 2, y + h + 2, #Red)
		
		x = 350 : y = 300 : w = 400 : h = DrawJustifiedText(x, y, text$, w, 0, #White)
		
		LineXY(x - 2, y - 2, x - 2, y + h + 2, #Red)
		LineXY(x + w + 2, y - 2, x + w + 2, y + h + 2, #Red)
		
		LineXY(x - 2, y - 2, x + w + 2, y - 2, #Red)
		LineXY(x - 2, y + h + 2, x + w + 2, y + h + 2, #Red)
		
		x = 400 : y = 125 : w = 80 : h = DrawJustifiedText(x, y, "Test rapide pour être sûr du bon fonctionnement de la procedure", w, 0, #White, 10)
		
		LineXY(x - 2, y - 2, x - 2, y + h + 2, #Red)
		LineXY(x + w + 2, y - 2, x + w + 2, y + h + 2, #Red)
		
		LineXY(x - 2, y - 2, x + w + 2, y - 2, #Red)
		LineXY(x - 2, y + h + 2, x + w + 2, y + h + 2, #Red)
		
		StopDrawing()
	EndIf
	
	FlipBuffers()
	
	;}
	
Until event = #PB_Event_CloseWindow

;}


End
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Pour justifier ses DrawText()

Message par Le Soldat Inconnu »

Juste un petit soucis sur le fractionnement des mots avec un "-", j'ai le "-" à cheval sur la bordure
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Pour justifier ses DrawText()

Message par graph100 »

oui, c'est un soucis que je n'ai pas résolu :oops: je me suis dis que normalement ça arrive rarement, et que ça n'allais pas être un soucis majeur.
En fait, je ne vois pas bien comment résoudre le problème simplement, et sans causer des soucis en cas de justification trop petite (=0 par exemple)
Dans le code, si tu décommente le 'c-1', ça affiche correctement, mais si la justification est trop petite, il y a une boucle infinie ><

En gros j'ai fait l'autruche :mrgreen:
* tapez pas, j'le f'rais plus * :mrgreen:

Je vais me casser encore un peu la tête dessus
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Pour justifier ses DrawText()

Message par graph100 »

Bon, problème résolut.
Y retourner après s'être changé les idées résout pas mal de problème :mrgreen:

Code : Tout sélectionner

;{ initialisation

w = 800
h = 600

If InitSprite() = 0 Or InitKeyboard() = 0
	End
EndIf

;}

;{ PROCEDURE

Structure JustifiedText
	text.s
	longueur.l
EndStructure

Procedure DrawJustifiedText(x.l, y.l, Text.s, largeur_de_justification.l, FrontColor.l = -1, BackColor.l = -1, coefficient_d_acceptation_de_retour_a_la_ligne.l = 5) ; Dessine un texte sur la surface de dessin, on appliquant une justification, retourne la hauteur du texte justifié
	
	;{ initialisation
	
	; on enlève une erreur possible
	If BackColor > -1 And FrontColor = -1 : FrontColor = 0 : EndIf
	
	y1 = y ; nécessaire pour retourner la hauteur de tout le texte écrit
	
	nb_ligne.l = CountString(Text, Chr(13)) + 1 ; nombre de ligne séparée par un chr(13)
	
	NewList mot.JustifiedText()
	taille_espace.l = TextWidth(" ")
	
	;}
	
	;{ on itère pour chaque ligne
	For a = 1 To nb_ligne
		partie$ = StringField(Text, a, Chr(13)) ; stockage de la ligne
		h.l = TextHeight(partie$) ; hauteur de la ligne courante
		
		nb_space.l = CountString(partie$, " ") + 1
		
		;{ initialisation de tout les paramètres
		ClearList(mot())
		
		largeur.l = 0
		largeur_space.l = 0
		;}
		
		;{ on itère pour chaque mot
		For b = 1 To nb_space
			tmp.JustifiedText\text = StringField(partie$, b, " ") ; stockage du mot en cours
			tmp\longueur = TextWidth(tmp\text) ; calcul de sa longueur graphique
			
			If ListSize(mot()) = 0 And tmp\longueur > largeur_de_justification
				;{ si il n'y a pas de mot en mémoire, et que le mot est trop long, alors on le stock pour le découper plus bas
				AddElement(mot())
				mot()\text = tmp\text
				mot()\longueur = tmp\longueur
				
				;}
				
			ElseIf largeur + taille_espace + tmp\longueur > largeur_de_justification
				;{ Si le mot courrant fait que la ligne ne tient plus dans la largeur de justification, alors on ecrit la ligne, et on stocke le mot courant pour la ligne suivante
				
				; définition de la taille des espaces
				If ListSize(mot()) > 1
					espace.l = (largeur_de_justification - largeur_space) / (ListSize(mot()) - 1)
				Else
					espace = taille_espace
				EndIf
				
				; içi on regarde le rapport de grandissement des nouveaux espaces par rapport aux normaux : en gros, si les espaces sont trop grand, on les remet à leur taille normal
				; et la ligne n'est pas justifié (mais sinon c'est moche), on peut régler ça avec le paramètre 'coefficient_d_acceptation_de_retour_a_la_ligne'
				If espace	/ taille_espace > coefficient_d_acceptation_de_retour_a_la_ligne : espace = taille_espace : EndIf
				
				curs = 0
				
				;{ on itère pour chaque mot à écrire
				ForEach mot()
					
					; on dessine la même chose, mais comme il faut tenir compte des paramètres optionnels de couleur, c'est la galère !
					; j'ai essayé d'émuler ça avec les valeurs par défaut de -1 et des IF partout...
					If FrontColor > -1 And BackColor = -1
						DrawText(x + curs, y, mot()\text, FrontColor)
					ElseIf BackColor > -1
						DrawText(x + curs, y, mot()\text, FrontColor, BackColor)
					Else
						DrawText(x + curs, y, mot()\text)
					EndIf
					
					; on avance le curseur
					curs = curs + mot()\longueur + espace
					
					;{ dessin du fond, si une couleur d'arrière plan est spécifiée
					;  (ce qui veux dire que comme je ne peux pas récupérer la couleur spécifiée par BackColor(#), il y aura des trous partout autour du texte si on ne spécifie pas de BackColor)
					If BackColor > -1 And ListIndex(mot()) + 1 <> ListSize(mot())
						Box(x + curs - espace, y, espace, h, BackColor)
					EndIf
					;}
					
				Next
				;}
				
				;{ initialisation d'une nouvelle ligne
				largeur = 0
				largeur_space = 0
				largeur = tmp\longueur
				largeur_space = largeur
				
				ClearList(mot())
				
				AddElement(mot())
				mot()\text = tmp\text
				mot()\longueur = tmp\longueur
				;}
				
				;{ on dessine la fin de ligne, si besoin
				If BackColor > -1
					Box(x + curs - espace, y, largeur_de_justification - curs + espace, h, BackColor)
				EndIf
				;}
				
				; incrémentation de l'ordonnée
				y = y + h
				
				;}
				
			Else
				;{ ajout de mots dans la mémoire, tant qu'ils ne dépassent pas de la justification
				
				If largeur = 0
					largeur = tmp\longueur
					largeur_space = largeur
				Else
					largeur = largeur + taille_espace + tmp\longueur
					largeur_space = largeur_space + tmp\longueur
				EndIf
				
				AddElement(mot())
				mot()\text = tmp\text
				mot()\longueur = tmp\longueur
				
				;}
			EndIf
			
			;{ boucle nécessaire pour s'occuper des mots trop long pour entrer sur une ligne
			Repeat
				If ListSize(mot()) = 1 And mot()\longueur > largeur_de_justification
					; on a donc un seul mot, trop grand pour une ligne
					
					mot$ = ""
					
					mot1$ = mot()\text
					
					;{ on test pour chaque nouvelle lettre du mot si ca rentre dans la ligne
					For c = 1 To Len(mot1$)
						mot$ = mot$ + Mid(mot1$, c, 1)
						
						If TextWidth(mot$ + "-") > largeur_de_justification
							
							;{ correction (en fait c'était tout simple ><
							c - 1
							attention.b = #False
							
							If c = 0
								c + 1
								
								attention = #True
							EndIf
							;}
							
							;{ on regarde si c'est la fin du mot, ou si faut mettre un tiret
							If c < Len(mot1$)
								t1$ = Mid(mot1$, 1, c) + "-"
								
								len1 = TextWidth(t1$)
								
								If FrontColor > -1 And BackColor = -1
									DrawText(x, y, t1$, FrontColor)
								ElseIf BackColor > -1
									DrawText(x, y, t1$, FrontColor, BackColor)
								Else
									DrawText(x, y, t1$)
								EndIf
								
								If BackColor > -1 And attention = #False
									Box(x + len1, y, largeur_de_justification - len1, h, BackColor)
								EndIf
								
								DeleteElement(mot())
								
								AddElement(mot())
								
								mot()\text = Mid(mot1$, c + 1, Len(mot1$) - c)
								mot()\longueur = TextWidth(mot()\text)
								
								largeur = mot()\longueur
								largeur_space = mot()\longueur
							Else
								t1$ = Mid(mot1$, 1, c)
								
								len1 = TextWidth(t1$)
								
								If FrontColor > -1 And BackColor = -1
									DrawText(x, y, t1$, FrontColor)
								ElseIf BackColor > -1
									DrawText(x, y, t1$, FrontColor, BackColor)
								Else
									DrawText(x, y, t1$)
								EndIf
								
								If BackColor > -1 And attention = #False
									Box(x + len1, y, largeur_de_justification - len1, h, BackColor)
								EndIf
								
								DeleteElement(mot())
								
								largeur = 0
							EndIf
							;}
							
							Break
						EndIf
						
					Next
					;}
					
					; incrémentation de l'ordonnée
					y = y + h
				EndIf
				
			Until largeur <= largeur_de_justification
			;}
			
		Next
		;}
		
		;{ on répète le code de tout à l'heure pour traiter les dernières lignes
		If ListSize(mot()) > 0
			
			If ListSize(mot()) > 1
				espace.l = (largeur_de_justification - largeur_space) / (ListSize(mot()) - 1)
			Else
				espace = taille_espace
			EndIf
			
			If espace	/ taille_espace > coefficient_d_acceptation_de_retour_a_la_ligne : espace = taille_espace : EndIf
			
			curs = 0
			
			ForEach mot()
				If FrontColor > -1 And BackColor = -1
					DrawText(x + curs, y, mot()\text, FrontColor)
				ElseIf BackColor > -1
					DrawText(x + curs, y, mot()\text, FrontColor, BackColor)
				Else
					DrawText(x + curs, y, mot()\text)
				EndIf
				
				curs = curs + mot()\longueur + espace
				
				If BackColor > -1 And ListIndex(mot()) + 1 <> ListSize(mot())
					Box(x + curs - espace, y, espace, h, BackColor)
				EndIf
				
			Next
			
			If BackColor > -1
				Box(x + curs - espace, y, largeur_de_justification - curs + espace, h, BackColor)
			EndIf
			
			y = y + h
		EndIf
		;}
		
	Next
	;}
	
	ProcedureReturn y - y1
EndProcedure

;}

;{ lancement de la fenetre et du screen

If OpenWindow(0, 0, 0, w, h, "Test : Texte justifié", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	If OpenWindowedScreen(WindowID(0), 0, 0, w, h, 0, 0, 0)
		
	EndIf
EndIf

text$ = "Les lapins sont présents un peu partout sur la planète et se répartissent en neuf genres, tous classés dans la famille des léporidés, avec leurs proches parents les lièvres. Ce ne sont donc pas des rongeurs mais des lagomorphes, une branche cousine qui comprend les lièvres, les lapins et les pikas." + Chr(13) + "Les « lapins » sont classées dans les genres suivants de la famille des Léporidae : Brachylagus, Bunolagus, Caprolagus, Nesolagus, Oryctolagus (lapin commun), Pentalagus, Poelagus, Pronolagus, Romerolagus ou Sylvilagus." + Chr(13) + "Sept de ces genres ne comprennent qu'une seule espèce, le genre Nesolagus comprend deux espèces, le genre Pronolagus en comprend trois et le genre Sylvilagus ou lapins d'Amérique, comprend quinze espèces, soit au moins 27 espèces différentes de lapins en tout."


;}


;{ boucle principale

Repeat
	event = WaitWindowEvent()
	
	ExamineKeyboard()
	
	;{ event clavier
	
	If KeyboardReleased(#PB_Key_Escape) : event = #PB_Event_CloseWindow : EndIf
	
	;}
	
	;{ dessin
	
	If StartDrawing(ScreenOutput())
		
; 		time = ElapsedMilliseconds()
		x = 50 : y = 25 : w = 250 : h = DrawJustifiedText(x, y, text$, w, 0, #White)
; 		Debug ElapsedMilliseconds() - time
		
		LineXY(x - 2, y - 2, x - 2, y + h + 2, #Red)
		LineXY(x + w + 2, y - 2, x + w + 2, y + h + 2, #Red)
		
		LineXY(x - 2, y - 2, x + w + 2, y - 2, #Red)
		LineXY(x - 2, y + h + 2, x + w + 2, y + h + 2, #Red)
		
		x = 350 : y = 300 : w = 400 : h = DrawJustifiedText(x, y, text$, w, 0, #White)
		
		LineXY(x - 2, y - 2, x - 2, y + h + 2, #Red)
		LineXY(x + w + 2, y - 2, x + w + 2, y + h + 2, #Red)
		
		LineXY(x - 2, y - 2, x + w + 2, y - 2, #Red)
		LineXY(x - 2, y + h + 2, x + w + 2, y + h + 2, #Red)
		
		x = 400 : y = 125 : w = 80 : h = DrawJustifiedText(x, y, "Test rapide pour être sûr du bon fonctionnement de la procedure", w, 0, #White, 10)
		
		LineXY(x - 2, y - 2, x - 2, y + h + 2, #Red)
		LineXY(x + w + 2, y - 2, x + w + 2, y + h + 2, #Red)
		
		LineXY(x - 2, y - 2, x + w + 2, y - 2, #Red)
		LineXY(x - 2, y + h + 2, x + w + 2, y + h + 2, #Red)
		
		x = 780 : y = 10 : w = 5 : h = DrawJustifiedText(x, y, "Test rapide pour être sûr du bon fonctionnement de la procedure", w, 0, #White, 10)
		
		LineXY(x - 2, y - 2, x - 2, y + h + 2, #Red)
		LineXY(x + w + 2, y - 2, x + w + 2, y + h + 2, #Red)
		
		LineXY(x - 2, y - 2, x + w + 2, y - 2, #Red)
		LineXY(x - 2, y + h + 2, x + w + 2, y + h + 2, #Red)
		
		StopDrawing()
	EndIf
	
	FlipBuffers()
	
	;}
	
Until event = #PB_Event_CloseWindow

;}


End
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Pour justifier ses DrawText()

Message par Le Soldat Inconnu »

Joli :wink:
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Avatar de l’utilisateur
case
Messages : 1545
Inscription : lun. 10/sept./2007 11:13

Re: Pour justifier ses DrawText()

Message par case »

sympatoche, j'en avais fait un mais pas aussi approfondi
exemple de code avec ton texte

il ne gère pas la découpe de mots comme le tiens...

Code : Tout sélectionner

InitSprite()
Global main=OpenWindow(#PB_Any,0,0,640,480,"test")
OpenWindowedScreen(WindowID(main),0,0,640,480,0,0,0)
Declare justify(t$,w)
text$ = "Les lapins sont présents un peu partout sur la planète et se répartissent en neuf genres, tous classés dans la famille des léporidés, avec leurs proches parents les lièvres. Ce ne sont donc pas des rongeurs mais des lagomorphes, une branche cousine qui comprend les lièvres, les lapins et les pikas." + Chr(13) + "Les « lapins » sont classées dans les genres suivants de la famille des Léporidae : Brachylagus, Bunolagus, Caprolagus, Nesolagus, Oryctolagus (lapin commun), Pentalagus, Poelagus, Pronolagus, Romerolagus ou Sylvilagus." + Chr(13) + "Sept de ces genres ne comprennent qu'une seule espèce, le genre Nesolagus comprend deux espèces, le genre Pronolagus en comprend trois et le genre Sylvilagus ou lapins d'Amérique, comprend quinze espèces, soit au moins 27 espèces différentes de lapins en tout."
Repeat
   ev=WaitWindowEvent(0)
   StartDrawing(ScreenOutput())
   justify(text$,250)
   StopDrawing()
   FlipBuffers()
Until ev=#PB_Event_CloseWindow
Procedure justify(t$,w)
   pos=0 ; position dansle texte
   st=1  ; position de depart
   xp=0
   yp=0
   Repeat
      pos+1 ;position dans le texte +1
      ;
      ; test d'une cassure du texte possible , ponctuation, espace etc... 
      Select Mid(t$,pos,1)
         Case "."," ","-" ; cassure possible
            lastbreak=pos ; on garde la position
         Case Chr(13)
            DrawText(xp,yp,Mid(t$,st,pos-(st-1)))     ; affichage des caracteres restants
         yp+TextHeight(" ")                           ; ligne suivante
         xp=0                                         ; retour chariot
         st=pos+1             
      EndSelect      
      ;
      If TextWidth(Mid(t$,st,pos-(st-1)))>w           ; on depasse la taille limite         
         If Mid(t$,lastbreak,1)=" "                   ; le dernier breakpoint est sur un espace
            lastbreak-1                               ; on recule d'une case sinon l'espace sera compté dans les signes de la phrase
         EndIf
         pos=lastbreak                                ; on revien a la derniere fin de mot encore dans la taile de ligne
         temp$=Mid(t$,st,pos-(st-1))                  ; recuperation du troncon de phrase
         wosp=TextWidth(RemoveString(temp$," "))      ; taille en pixel tu texte sans espaces
         If CountString(temp$," ") >0 ; pas d'espaces 
            spacesize=(w-wosp)/CountString(temp$," ")  ; definition de la taille d'un espacement
         EndIf
         ;
         For k=1 To CountString(temp$," ")+1          ; boucle d'afichage du troncon de phrase
            word$=StringField(temp$,k," ")            ; recuperation du mot courant
            DrawText(xp,yp,word$,$ffffff)             ; affichage du mot
            xp+spacesize+TextWidth(word$)             ; ajout d'un espace apres le mot ainsi que la taille du mot actuel
         Next k                                      
         ;
         yp+TextHeight(" ")                           ; ligne suivante
         xp=0                                         ; retour chariot
         If Mid(t$,pos+1,1)=" "                       ; correction de la position sur le dernier 
            pos+1                                     ; breakpoint si celui ci etait un espace
         EndIf
         st=pos+1                                     ; on place le debut de la prochaine phrase sur le caractere suivant
   EndIf
Until pos=Len(t$)                                     ; jusqu'a ce qu'on arrive a la fin du texte
DrawText(xp,yp,Mid(t$,st,pos-(st-1)))                 ; affichage des caracteres restants
EndProcedure

ImageImage
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Pour justifier ses DrawText()

Message par Le Soldat Inconnu »

Ma version avec découpe de mot :mrgreen:
Le principe est totalement différent

Code : Tout sélectionner

; Auteur : Le Soldat Inconnu
; Version de PB : 4.5
;
; Explication du programme :
; Justification de texte

Procedure.s DrawJustifiedText(x.l, y.l, Width.l, Text.s, Color.l)
	Protected NewList Ligne.s()
	Protected Coupe.s, Caractere.s, Espace_Largeur.l, Espace_Justifie.f, Espace_Nombre.l, xx.f
	
	; Découpage du texte
	; On commence la première ligne
	AddElement(Ligne())
	
	For n = 1 To Len(Text) ; Pour tous les caractères
		Caractere.s = Mid(Text, n, 1)
		Select Caractere
			Case Chr(13)
				; Je fais rien avec ca, un passage de ligne d'un éditeur de texte, c'est chr(13) + chr(10)
			Case Chr(10) ; donc je m'occupe que du chr(10)
				Ligne() + Chr(10) ; Marqueur de fin de ligne normale utilisé pour le dessin du texte
				AddElement(Ligne()) ; on passe à la ligne suivante
			Default ; Sinon, pour les autres caractères
				Ligne() + Caractere ; J'ajoute le caractere à la ligne
				If TextWidth(Ligne()) > Width ; Si le texte est trop long
					
					For nn = Len(Ligne()) To 1 Step -1 ; On remonte au dernier espace
						Caractere.s = Mid(Ligne(), nn, 1)
						
						If Caractere = " " ; au premier espace
							Coupe.s = Right(Ligne(), Len(Ligne()) - nn)
							Ligne() = Left(Ligne(), nn)
							AddElement(Ligne()) ; on passe à la ligne suivante
							Ligne() = Coupe
							Break
						EndIf
						
						If nn = 1 ; On n'a pas trouvé d'espace, donc le mot est trop long et ne rentre pas dans la ligne, donc on met un tiret
							Caractere = ""
							Repeat
								Caractere = Right(Ligne(), 1) + Caractere ; on récupère le dernier caractère
								Ligne() = Left(Ligne(), Len(Ligne()) - 1) ; on supprime le dernier caractère
							Until TextWidth(Ligne() + "-") <= Width
							Ligne() + "-"
							AddElement(Ligne()) ; on passe à la ligne suivante
							Ligne() = Caractere
						EndIf
						
					Next
					
				EndIf
				
		EndSelect
	Next
	
	Espace_Largeur = TextWidth(" ") ; Largeur du caractère espace
	
	; Dessin du texte
	ForEach Ligne()
		If Right(Ligne(), 1) = Chr(10) ; Si on a une fin de ligne normale
			Ligne() = RTrim(Ligne(), Chr(10))
			Ligne() = RTrim(Ligne())
			DrawText(x, y, Ligne(), Color) ; On dessine le texte normalement
		Else ; Sinon, on dessine le texte justifié
			Ligne() = RTrim(Ligne())
			Espace_Nombre = CountString(Ligne(), " ") ; Nombre d'espace dans la ligne
			Espace_Justifie = (Width - TextWidth(Ligne()) + Espace_Largeur * Espace_Nombre) / Espace_Nombre ; Taille des espaces pour justifier le texte
			xx = x
			For n = 1 To Espace_Nombre + 1 ; Pour chaque mot
				Text = StringField(Ligne(), n, " ") ; Texte du mot
				DrawText(xx, y, Text, Color) ; Dessin du texte
				xx + TextWidth(Text) + Espace_Justifie ; On déplace la position de dessin au mot suivant
			Next
		EndIf
		y + TextHeight("A") ; Passage à la ligne suivante
	Next
	
EndProcedure

;- Début du programme

Restore ExempleDeTexte
For n = 1 To 7
	Read.s Ligne.s
	Texte.s + Ligne + Chr(10)
Next

;- Police par défaut de windows
FontID = GetStockObject_(#DEFAULT_GUI_FONT)

; Création de la fenêtre et de la GadgetList
If OpenWindow(0, 0, 0, 400, 400, "Texte justifié", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget) = 0 Or CreateGadgetList(WindowID(0)) = 0
	End
EndIf

CreateImage(0, 400, 400, 32 | #PB_Image_Transparent)
StartDrawing(ImageOutput(0))
	
	DrawingMode(#PB_2DDrawing_AlphaBlend | #PB_2DDrawing_Transparent)
	DrawingFont(FontID)
	
	Box(10, 20, 300, 400, $40000000)
	DrawJustifiedText(10, 20, 300, Texte, $FF000000)
	
	Box(320, 20, 30, 400, $40000000)
	DrawJustifiedText(320, 20, 30, Texte, $FF000000)
	
StopDrawing()
ImageGadget(0, 0, 0, 320, 320, ImageID(0))

Repeat
	Event = WaitWindowEvent()
	
Until Event = #PB_Event_CloseWindow

End

DataSection
	ExempleDeTexte:
		Data.s "PureBasic est un langage de programmation basé sur les règles du langage BASIC. Ses caractéristiques majeures sont :"
		Data.s ""
		Data.s "- Portabilité: PureBasic fonctionne actuellement pleinement sous Windows, AmigaOS et Linux."
		Data.s "- Rapidité: PureBasic est un véritable compilateur qui produit des exécutables compacts et optimisés."
		Data.s "- Simplicité: PureBasic utilise la syntaxe du langage BASIC, très répandue et simple à apprendre."
		Data.s ""
		Data.s "PureBasic a été conçu aussi bien pour les débutants que pour les programmeurs expérimentés. Nous avons consacré beaucoup de temps et d'efforts pour vous proposer un langage rapide, fiable et convivial. Malgré sa syntaxe de base simple et rapidement assimilable, les possibilités de PureBasic sont infinies, grâce à de nombreuses caractéristiques évoluées comme, entre autres, les pointeurs, structures, procédures, listes dynamiques, etc. Le programmeur expérimenté n'aura aucune difficulté à accéder aux structures du système d'exploitation et aux API's."
EndDataSection
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Pour justifier ses DrawText()

Message par Le Soldat Inconnu »

Case, je me suis permis de corriger un poil ton code.

J'ai supprimé le dernier espace de la ligne avec des RTrim, ensuite, j'ai passé la taille des espaces et la position en X en nombre flottant pour avoir une justification qui tombe toujours pile poil

Code : Tout sélectionner

InitSprite()
Global main=OpenWindow(#PB_Any,0,0,640,480,"test")
OpenWindowedScreen(WindowID(main),0,0,640,480,0,0,0)
Declare justify(t$,w)
text$ = "Les lapins sont présents un peu partout sur la planète et se répartissent en neuf genres, tous classés dans la famille des léporidés, avec leurs proches parents les lièvres. Ce ne sont donc pas des rongeurs mais des lagomorphes, une branche cousine qui comprend les lièvres, les lapins et les pikas." + Chr(13) + "Les « lapins » sont classées dans les genres suivants de la famille des Léporidae : Brachylagus, Bunolagus, Caprolagus, Nesolagus, Oryctolagus (lapin commun), Pentalagus, Poelagus, Pronolagus, Romerolagus ou Sylvilagus." + Chr(13) + "Sept de ces genres ne comprennent qu'une seule espèce, le genre Nesolagus comprend deux espèces, le genre Pronolagus en comprend trois et le genre Sylvilagus ou lapins d'Amérique, comprend quinze espèces, soit au moins 27 espèces différentes de lapins en tout."
Repeat
		ev=WaitWindowEvent(0)
		StartDrawing(ScreenOutput())
			justify(text$,250)
			Line(250, 0, 1, 480, $FFFFFF)
		StopDrawing()
		FlipBuffers()
Until ev=#PB_Event_CloseWindow
Procedure justify(t$,w)
		pos=0 ; position dans le texte
		st=1  ; position de depart
		xp.f=0
		yp=0
		Repeat
			pos+1 ;position dans le texte +1
			;
			; test d'une cassure du texte possible , ponctuation, espace etc... 
			Select Mid(t$,pos,1)
					Case "."," ","-" ; cassure possible
						lastbreak=pos ; on garde la position
					Case Chr(13)
						DrawText(xp,yp,Mid(t$,st,pos-(st-1)))     ; affichage des caracteres restants
					yp+TextHeight(" ")                           ; ligne suivante
					xp=0                                         ; retour chariot
					st=pos+1             
			EndSelect      
			;
			If TextWidth(Mid(t$,st,pos-(st-1)))>w           ; on depasse la taille limite         
					If Mid(t$,lastbreak,1)=" "                   ; le dernier breakpoint est sur un espace
						lastbreak-1                               ; on recule d'une case sinon l'espace sera compté dans les signes de la phrase
					EndIf
					pos=lastbreak                                ; on revien a la derniere fin de mot encore dans la taile de ligne
					temp$=Mid(t$,st,pos-(st-1))                  ; recuperation du troncon de phrase
					wosp=TextWidth(RemoveString(temp$," "))      ; taille en pixel tu texte sans espaces
					If CountString(RTrim(temp$)," ") >0 ; pas d'espaces 
						spacesize.f=(w-wosp)/CountString(RTrim(temp$)," ")  ; definition de la taille d'un espacement
					EndIf
					;
					For k=1 To CountString(temp$," ")+1          ; boucle d'afichage du troncon de phrase
						word$=StringField(temp$,k," ")            ; recuperation du mot courant
						DrawText(xp,yp,word$,$FFFFFF)             ; affichage du mot
						xp+spacesize+TextWidth(word$)             ; ajout d'un espace apres le mot ainsi que la taille du mot actuel
					Next k                                      
					;
					yp+TextHeight(" ")                           ; ligne suivante
					xp=0                                         ; retour chariot
					If Mid(t$,pos+1,1)=" "                       ; correction de la position sur le dernier 
						pos+1                                     ; breakpoint si celui ci etait un espace
					EndIf
					st=pos+1                                     ; on place le debut de la prochaine phrase sur le caractere suivant
		EndIf
Until pos=Len(t$)                                     ; jusqu'a ce qu'on arrive a la fin du texte
DrawText(xp,yp,Mid(t$,st,pos-(st-1)))                 ; affichage des caracteres restants
EndProcedure
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Pour justifier ses DrawText()

Message par Le Soldat Inconnu »

Oups, correction d'une erreur dans mon code :mrgreen: , il est 2 messages plus haut
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Pour justifier ses DrawText()

Message par graph100 »

@case :

C'est rigolo, il ne saute pas les lignes au mêmes endroits ;)
Sinon, la découpe des mots, c'est un petit plus, qui ne devrais en théorie pas servir, car il faut justifier, mais avec une largeur conséquente.
ton code a l'air beaucoup plus simple. ya l'idée de couper à la ponctuation, ça peut être pas mal.

@LSI : effectivement, le principe n'est pas le même, tu traite les caractères un par un ;)

Pour que ma fonction soit quasiment parfaite ( :mrgreen: ) il me faudrait résoudre le problème des backcolors et forecolors.
Comment faire pour récupérer leurs valeurs ? Es-ce possible (sans dessiner un truc et récupérer la couleur du point -_-)
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Avatar de l’utilisateur
case
Messages : 1545
Inscription : lun. 10/sept./2007 11:13

Re: Pour justifier ses DrawText()

Message par case »

Pour que ma fonction soit quasiment parfaite ( :mrgreen: ) il me faudrait résoudre le problème des backcolors et forecolors.
Comment faire pour récupérer leurs valeurs ? Es-ce possible (sans dessiner un truc et récupérer la couleur du point -_-)
back & front color ? je comprend pas ton problème tu les définis au début de ta procédure non ? pourquoi et d’où veux tu les récupérer ?
ImageImage
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Pour justifier ses DrawText()

Message par Le Soldat Inconnu »

Regarde mon code :), si tu supprimes l'attribut "Color" dans la procedure, il utilisera la couleur définie par FrontColor(


Allez, moi j'ai continué dans mon délire :mrgreen:
En imprimerie, quand il y a peu de mot sur une ligne, pour faire de la justification, il ajoute également des espaces entres chaque caractères, vous voyez ce que je veux dire ?
Alors j'ai codé ça :D Et je dois avouer que le résultat est vraiment chouette (en toute modestie :mrgreen: En tous cas, ça a occupé ma soirée, c'est déjà ça :wink: )

Code : Tout sélectionner

; Auteur : Le Soldat Inconnu
; Version de PB : 4.5
;
; Explication du programme :
; Justification de texte

Procedure.s DrawJustifiedText(x.l, y.l, Width.l, Text.s, Color.l)
	Protected NewList Ligne.s()
	Protected Coupe.s, Caractere.s, Espace_Largeur.l, Espace_Justifie.d, Espace_Nombre.l, xx.d, Caractere_Justifie.d, Mot.s
	
	; Découpage du texte
	; On commence la première ligne
	AddElement(Ligne())
	
	For n = 1 To Len(Text) ; Pour tous les caractères
		Caractere.s = Mid(Text, n, 1)
		Select Caractere
			Case Chr(13)
				; Je fais rien avec ca, un passage de ligne d'un éditeur de texte, c'est chr(13) + chr(10)
			Case Chr(10) ; donc je m'occupe que du chr(10)
				Ligne() + Chr(10) ; Marqueur de fin de ligne normale utilisé pour le dessin du texte
				AddElement(Ligne()) ; on passe à la ligne suivante
			Default ; Sinon, pour les autres caractères
				Ligne() + Caractere ; J'ajoute le caractere à la ligne
				If TextWidth(Ligne()) > Width ; Si le texte est trop long
					
					For nn = Len(Ligne()) To 1 Step -1 ; On remonte au dernier espace
						Caractere.s = Mid(Ligne(), nn, 1)
						
						If Caractere = " " ; au premier espace
							Coupe.s = Right(Ligne(), Len(Ligne()) - nn)
							Ligne() = Left(Ligne(), nn)
							AddElement(Ligne()) ; on passe à la ligne suivante
							Ligne() = Coupe
							Break
						EndIf
						
						If nn = 1 ; On n'a pas trouvé d'espace, donc le mot est trop long et ne rentre pas dans la ligne, donc on met un tiret
							Caractere = ""
							Repeat
								Caractere = Right(Ligne(), 1) + Caractere ; on récupère le dernier caractère
								Ligne() = Left(Ligne(), Len(Ligne()) - 1) ; on supprime le dernier caractère
							Until TextWidth(Ligne() + "-") <= Width
							Ligne() + "-"
							AddElement(Ligne()) ; on passe à la ligne suivante
							Ligne() = Caractere
						EndIf
						
					Next
					
				EndIf
				
		EndSelect
	Next
	
	Espace_Largeur = TextWidth(" ") ; Largeur du caractère espace
	
	; Dessin du texte
	ForEach Ligne()
		If Right(Ligne(), 1) = Chr(10) ; Si on a une fin de ligne normale
			Ligne() = RTrim(Ligne(), Chr(10))
			Ligne() = RTrim(Ligne())
			Debug Chr(34) + Ligne() + Chr(34)
			DrawText(x, y, Ligne(), Color) ; On dessine le texte normalement
			Debug Space(10) + "Ligne normale"
		Else ; Sinon, on dessine le texte justifié
			Ligne() = RTrim(Ligne())
			Debug Chr(34) + Ligne() + Chr(34)
			If Ligne()
				Espace_Nombre = CountString(Ligne(), " ") ; Nombre d'espace dans la ligne
				If Espace_Nombre > 0
					Espace_Justifie = (Width - TextWidth(Ligne()) + Espace_Largeur * Espace_Nombre) / Espace_Nombre ; Taille des espaces pour justifier le texte
					If Espace_Justifie > 3 * Espace_Largeur ; Si la largeur des espace devient trop grande, on espace également les caractères
						Caractere_Justifie = (Espace_Justifie - 3 * Espace_Largeur) * Espace_Nombre
						Caractere_Justifie / (Len(Ligne()) - 1)
						Debug Space(10) + "Espace entre caractère"
					Else
						Caractere_Justifie = 0
					EndIf
				ElseIf Len(Ligne()) > 1 ; Si il n'y a pas d'espace dans la ligne, on espace les caractères
					Caractere_Justifie = Width - TextWidth(Ligne())
					Caractere_Justifie / (Len(Ligne()) - 1)
					Debug Space(10) + "Espace entre caractère (Pas d'espace sur la ligne)"
				Else
					Caractere_Justifie = 0
				EndIf
				If Caractere_Justifie > Espace_Largeur ; Si l'espacement entre les caractères est trop grand, on l'annule
					Caractere_Justifie = 0
					Debug Space(10) + "Espace trop grand"
				ElseIf Caractere_Justifie > 0 ; On valide l'espace entre les caractères
					Espace_Justifie = 3 * Espace_Largeur
					Debug Space(10) + "Validation espace entre caractères"
				EndIf
				Debug Espace_Justifie
				Debug Caractere_Justifie
				xx = x
				For n = 1 To Espace_Nombre + 1 ; Pour chaque mot
					Mot = StringField(Ligne(), n, " ") ; Texte du mot
					If Caractere_Justifie = 0 ; Pas d'espacement entre chaque caractère
						DrawText(xx, y, Mot, Color) ; Dessin du mot complet
						xx + TextWidth(Mot) + Espace_Justifie ; On déplace la position de dessin au mot suivant
					Else ; Dessin avec espacement entre chaque caractère
						For nn = 1 To Len(Mot)
							Caractere = Mid(Mot, nn, 1)
							DrawText(xx, y, Caractere, Color) ; Dessin du caractère du mot
							xx + TextWidth(Caractere) + Caractere_Justifie
						Next
						xx + Espace_Justifie + Caractere_Justifie
					EndIf
					
				Next
			EndIf
		EndIf
		y + TextHeight("A") ; Passage à la ligne suivante
	Next
	
EndProcedure

;- Début du programme

Restore ExempleDeTexte
For n = 1 To 7
	Read.s Ligne.s
	Texte.s + Ligne + Chr(10)
Next

;- Police par défaut de windows
FontID = GetStockObject_(#DEFAULT_GUI_FONT)

; Création de la fenêtre et de la GadgetList
If OpenWindow(0, 0, 0, 400, 400, "Texte justifié", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget) = 0 Or CreateGadgetList(WindowID(0)) = 0
	End
EndIf

CreateImage(0, 400, 400, 32 | #PB_Image_Transparent)
StartDrawing(ImageOutput(0))
	
	DrawingMode(#PB_2DDrawing_AlphaBlend | #PB_2DDrawing_Transparent)
	DrawingFont(FontID)
	
	Box(10, 20, 300, 400, $40000000)
	DrawJustifiedText(10, 20, 300, Texte, $FF000000)
	
	Box(320, 20, 30, 400, $40000000)
	DrawJustifiedText(320, 20, 30, Texte, $FF000000)
	
StopDrawing()
ImageGadget(0, 0, 0, 320, 320, ImageID(0))

Repeat
	Event = WaitWindowEvent()
	
Until Event = #PB_Event_CloseWindow

End

DataSection
	ExempleDeTexte:
		Data.s "PureBasic est un langage de programmation basé sur les règles du langage BASIC. Ses caractéristiques majeures sont :"
		Data.s ""
		Data.s "- Portabilité: PureBasic fonctionne actuellement pleinement sous Windows, AmigaOS et Linux."
		Data.s "- Rapidité: PureBasic est un véritable compilateur qui produit des exécutables compacts et optimisés."
		Data.s "- Simplicité: PureBasic utilise la syntaxe du langage BASIC, très répandue et simple à apprendre."
		Data.s ""
		Data.s "PureBasic a été conçu aussi bien pour les débutants que pour les programmeurs expérimentés. Nous avons consacré beaucoup de temps et d'efforts pour vous proposer un langage rapide, fiable et convivial. Malgré sa syntaxe de base simple et rapidement assimilable, les possibilités de PureBasic sont infinies, grâce à de nombreuses caractéristiques évoluées comme, entre autres, les pointeurs, structures, procédures, listes dynamiques, etc. Le programmeur expérimenté n'aura aucune difficulté à accéder aux structures du système d'exploitation et aux API's."
EndDataSection
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Pour justifier ses DrawText()

Message par graph100 »

Je veux parler du backcolor !

si on veux utiliser une couleur d'arrière plan, ça va être très très moche :!

regardez l'exemple suivant :

Code : Tout sélectionner

;{ initialisation

w = 800
h = 600

If InitSprite() = 0 Or InitKeyboard() = 0
	End
EndIf

;}

;{ PROCEDURE

Structure JustifiedText
	text.s
	longueur.l
EndStructure

Procedure DrawJustifiedText(x.l, y.l, Text.s, largeur_de_justification.l, FrontColor.l = -1, BackColor.l = -1, coefficient_d_acceptation_de_retour_a_la_ligne.l = 5) ; Dessine un texte sur la surface de dessin, on appliquant une justification, retourne la hauteur du texte justifié
	
	;{ initialisation
	
	; on enlève une erreur possible
	If BackColor > -1 And FrontColor = -1 : FrontColor = 0 : EndIf
	
	y1 = y ; nécessaire pour retourner la hauteur de tout le texte écrit
	
	nb_ligne.l = CountString(Text, Chr(13)) + 1 ; nombre de ligne séparée par un chr(13)
	
	NewList mot.JustifiedText()
	taille_espace.l = TextWidth(" ")
	
	;}
	
	;{ on itère pour chaque ligne
	For a = 1 To nb_ligne
		partie$ = StringField(Text, a, Chr(13)) ; stockage de la ligne
		h.l = TextHeight(partie$) ; hauteur de la ligne courante
		
		nb_space.l = CountString(partie$, " ") + 1
		
		;{ initialisation de tout les paramètres
		ClearList(mot())
		
		largeur.l = 0
		largeur_space.l = 0
		;}
		
		;{ on itère pour chaque mot
		For b = 1 To nb_space
			tmp.JustifiedText\text = StringField(partie$, b, " ") ; stockage du mot en cours
			tmp\longueur = TextWidth(tmp\text) ; calcul de sa longueur graphique
			
			If ListSize(mot()) = 0 And tmp\longueur > largeur_de_justification
				;{ si il n'y a pas de mot en mémoire, et que le mot est trop long, alors on le stock pour le découper plus bas
				AddElement(mot())
				mot()\text = tmp\text
				mot()\longueur = tmp\longueur
				
				;}
				
			ElseIf largeur + taille_espace + tmp\longueur > largeur_de_justification
				;{ Si le mot courrant fait que la ligne ne tient plus dans la largeur de justification, alors on ecrit la ligne, et on stocke le mot courant pour la ligne suivante
				
				; définition de la taille des espaces
				If ListSize(mot()) > 1
					espace.l = (largeur_de_justification - largeur_space) / (ListSize(mot()) - 1)
				Else
					espace = taille_espace
				EndIf
				
				; içi on regarde le rapport de grandissement des nouveaux espaces par rapport aux normaux : en gros, si les espaces sont trop grand, on les remet à leur taille normal
				; et la ligne n'est pas justifié (mais sinon c'est moche), on peut régler ça avec le paramètre 'coefficient_d_acceptation_de_retour_a_la_ligne'
				If espace	/ taille_espace > coefficient_d_acceptation_de_retour_a_la_ligne : espace = taille_espace : EndIf
				
				curs = 0
				
				;{ on itère pour chaque mot à écrire
				ForEach mot()
					
					; on dessine la même chose, mais comme il faut tenir compte des paramètres optionnels de couleur, c'est la galère !
					; j'ai essayé d'émuler ça avec les valeurs par défaut de -1 et des IF partout...
					If FrontColor > -1 And BackColor = -1
						DrawText(x + curs, y, mot()\text, FrontColor)
					ElseIf BackColor > -1
						DrawText(x + curs, y, mot()\text, FrontColor, BackColor)
					Else
						DrawText(x + curs, y, mot()\text)
					EndIf
					
					; on avance le curseur
					curs = curs + mot()\longueur + espace
					
					;{ dessin du fond, si une couleur d'arrière plan est spécifiée
					;  (ce qui veux dire que comme je ne peux pas récupérer la couleur spécifiée par BackColor(#), il y aura des trous partout autour du texte si on ne spécifie pas de BackColor)
					If BackColor > -1 And ListIndex(mot()) + 1 <> ListSize(mot())
						Box(x + curs - espace, y, espace, h, BackColor)
					EndIf
					;}
					
				Next
				;}
				
				;{ initialisation d'une nouvelle ligne
				largeur = 0
				largeur_space = 0
				largeur = tmp\longueur
				largeur_space = largeur
				
				ClearList(mot())
				
				AddElement(mot())
				mot()\text = tmp\text
				mot()\longueur = tmp\longueur
				;}
				
				;{ on dessine la fin de ligne, si besoin
				If BackColor > -1
					Box(x + curs - espace, y, largeur_de_justification - curs + espace, h, BackColor)
				EndIf
				;}
				
				; incrémentation de l'ordonnée
				y = y + h
				
				;}
				
			Else
				;{ ajout de mots dans la mémoire, tant qu'ils ne dépassent pas de la justification
				
				If largeur = 0
					largeur = tmp\longueur
					largeur_space = largeur
				Else
					largeur = largeur + taille_espace + tmp\longueur
					largeur_space = largeur_space + tmp\longueur
				EndIf
				
				AddElement(mot())
				mot()\text = tmp\text
				mot()\longueur = tmp\longueur
				
				;}
			EndIf
			
			;{ boucle nécessaire pour s'occuper des mots trop long pour entrer sur une ligne
			Repeat
				If ListSize(mot()) = 1 And mot()\longueur > largeur_de_justification
					; on a donc un seul mot, trop grand pour une ligne
					
					mot$ = ""
					
					mot1$ = mot()\text
					
					;{ on test pour chaque nouvelle lettre du mot si ca rentre dans la ligne
					For c = 1 To Len(mot1$)
						mot$ = mot$ + Mid(mot1$, c, 1)
						
						If TextWidth(mot$ + "-") > largeur_de_justification
							
							;{ correction (en fait c'était tout simple ><
							c - 1
							attention.b = #False
							
							If c = 0
								c + 1
								
								attention = #True
							EndIf
							;}
							
							;{ on regarde si c'est la fin du mot, ou si faut mettre un tiret
							If c < Len(mot1$)
								t1$ = Mid(mot1$, 1, c) + "-"
								
								len1 = TextWidth(t1$)
								
								If FrontColor > -1 And BackColor = -1
									DrawText(x, y, t1$, FrontColor)
								ElseIf BackColor > -1
									DrawText(x, y, t1$, FrontColor, BackColor)
								Else
									DrawText(x, y, t1$)
								EndIf
								
								If BackColor > -1 And attention = #False
									Box(x + len1, y, largeur_de_justification - len1, h, BackColor)
								EndIf
								
								DeleteElement(mot())
								
								AddElement(mot())
								
								mot()\text = Mid(mot1$, c + 1, Len(mot1$) - c)
								mot()\longueur = TextWidth(mot()\text)
								
								largeur = mot()\longueur
								largeur_space = mot()\longueur
							Else
								t1$ = Mid(mot1$, 1, c)
								
								len1 = TextWidth(t1$)
								
								If FrontColor > -1 And BackColor = -1
									DrawText(x, y, t1$, FrontColor)
								ElseIf BackColor > -1
									DrawText(x, y, t1$, FrontColor, BackColor)
								Else
									DrawText(x, y, t1$)
								EndIf
								
								If BackColor > -1 And attention = #False
									Box(x + len1, y, largeur_de_justification - len1, h, BackColor)
								EndIf
								
								DeleteElement(mot())
								
								largeur = 0
							EndIf
							;}
							
							Break
						EndIf
						
					Next
					;}
					
					; incrémentation de l'ordonnée
					y = y + h
				EndIf
				
			Until largeur <= largeur_de_justification
			;}
			
		Next
		;}
		
		;{ on répète le code de tout à l'heure pour traiter les dernières lignes
		If ListSize(mot()) > 0
			
			If ListSize(mot()) > 1
				espace.l = (largeur_de_justification - largeur_space) / (ListSize(mot()) - 1)
			Else
				espace = taille_espace
			EndIf
			
			If espace	/ taille_espace > coefficient_d_acceptation_de_retour_a_la_ligne : espace = taille_espace : EndIf
			
			curs = 0
			
			ForEach mot()
				If FrontColor > -1 And BackColor = -1
					DrawText(x + curs, y, mot()\text, FrontColor)
				ElseIf BackColor > -1
					DrawText(x + curs, y, mot()\text, FrontColor, BackColor)
				Else
					DrawText(x + curs, y, mot()\text)
				EndIf
				
				curs = curs + mot()\longueur + espace
				
				If BackColor > -1 And ListIndex(mot()) + 1 <> ListSize(mot())
					Box(x + curs - espace, y, espace, h, BackColor)
				EndIf
				
			Next
			
			If BackColor > -1
				Box(x + curs - espace, y, largeur_de_justification - curs + espace, h, BackColor)
			EndIf
			
			y = y + h
		EndIf
		;}
		
	Next
	;}
	
	ProcedureReturn y - y1
EndProcedure

;}

;{ lancement de la fenetre et du screen

If OpenWindow(0, 0, 0, w, h, "Test : Texte justifié", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	If OpenWindowedScreen(WindowID(0), 0, 0, w, h, 0, 0, 0)
		
	EndIf
EndIf

text$ = "Les lapins sont présents un peu partout sur la planète et se répartissent en neuf genres, tous classés dans la famille des léporidés, avec leurs proches parents les lièvres. Ce ne sont donc pas des rongeurs mais des lagomorphes, une branche cousine qui comprend les lièvres, les lapins et les pikas." + Chr(13) + "Les « lapins » sont classées dans les genres suivants de la famille des Léporidae : Brachylagus, Bunolagus, Caprolagus, Nesolagus, Oryctolagus (lapin commun), Pentalagus, Poelagus, Pronolagus, Romerolagus ou Sylvilagus." + Chr(13) + "Sept de ces genres ne comprennent qu'une seule espèce, le genre Nesolagus comprend deux espèces, le genre Pronolagus en comprend trois et le genre Sylvilagus ou lapins d'Amérique, comprend quinze espèces, soit au moins 27 espèces différentes de lapins en tout."


;}


;{ boucle principale

Repeat
	event = WaitWindowEvent()
	
	ExamineKeyboard()
	
	;{ event clavier
	
	If KeyboardReleased(#PB_Key_Escape) : event = #PB_Event_CloseWindow : EndIf
	
	;}
	
	;{ dessin
	
	If StartDrawing(ScreenOutput())
		
		FrontColor(#Green)
		BackColor(#Blue)
		
		Box(10, 10, 10, 10)
		
; 		time = ElapsedMilliseconds()
		x = 50 : y = 25 : w = 250 : h = DrawJustifiedText(x, y, text$, w)
; 		Debug ElapsedMilliseconds() - time
		
		LineXY(x - 2, y - 2, x - 2, y + h + 2, #Red)
		LineXY(x + w + 2, y - 2, x + w + 2, y + h + 2, #Red)
		
		LineXY(x - 2, y - 2, x + w + 2, y - 2, #Red)
		LineXY(x - 2, y + h + 2, x + w + 2, y + h + 2, #Red)
		
		x = 350 : y = 300 : w = 400 : h = DrawJustifiedText(x, y, text$, w, 0, #White)
		
		LineXY(x - 2, y - 2, x - 2, y + h + 2, #Red)
		LineXY(x + w + 2, y - 2, x + w + 2, y + h + 2, #Red)
		
		LineXY(x - 2, y - 2, x + w + 2, y - 2, #Red)
		LineXY(x - 2, y + h + 2, x + w + 2, y + h + 2, #Red)
		
		x = 400 : y = 125 : w = 80 : h = DrawJustifiedText(x, y, "Test rapide pour être sûr du bon fonctionnement de la procedure", w, 0, #White, 10)
		
		LineXY(x - 2, y - 2, x - 2, y + h + 2, #Red)
		LineXY(x + w + 2, y - 2, x + w + 2, y + h + 2, #Red)
		
		LineXY(x - 2, y - 2, x + w + 2, y - 2, #Red)
		LineXY(x - 2, y + h + 2, x + w + 2, y + h + 2, #Red)
		
		x = 780 : y = 10 : w = 5 : h = DrawJustifiedText(x, y, "Test rapide pour être sûr du bon fonctionnement de la procedure", w, 0, #White, 10)
		
		LineXY(x - 2, y - 2, x - 2, y + h + 2, #Red)
		LineXY(x + w + 2, y - 2, x + w + 2, y + h + 2, #Red)
		
		LineXY(x - 2, y - 2, x + w + 2, y - 2, #Red)
		LineXY(x - 2, y + h + 2, x + w + 2, y + h + 2, #Red)
		
		StopDrawing()
	EndIf
	
	FlipBuffers()
	
	;}
	
Until event = #PB_Event_CloseWindow

;}


End
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Pour justifier ses DrawText()

Message par graph100 »

Aie ! je suis tombé sur un soucis de taille : la transparence avec les images -_-

L'arrière plan du texte ne rend pas pareil que les box !!
Pourtant la doc de pure dis bien que :
Aide de PureBasic a écrit :#PB_2DDrawing_AlphaBlend
Les opérations de dessin seront fusionnées avec le fond en utilisant le canal alpha pour gérer la transparence de chaque pixel. RGBA() peut être utilisé pour définir une couleur qui intègre un degré de transparence pour les commandes comme FrontColor(), Box(), DrawText() etc.

Code : Tout sélectionner

w = 500
h = 500


res = CreateImage(#PB_Any, w, h, 32 | #PB_Image_Transparent)

If StartDrawing(ImageOutput(res))
	DrawingMode(#PB_2DDrawing_AlphaChannel)
	
	Box(0, 0, w, h, RGBA(0, 0, 0, 0))
	
	DrawingMode(#PB_2DDrawing_AlphaBlend)
	
	For a = 0 To 50
		Circle(Random(w), Random(h), Random(20) + 5, Random(RGBA(Random(255), Random(255), Random(255), Random(255))))
	Next
	
	
	Box(10, 210, 150, 20, RGBA(0, 0, 0, 255))
	
	color = RGBA(238, 0, 250, 180)
	
	Box(10, 230, 150, 20, color)
	DrawText(10, 250, "TEST #######     #", RGBA(0, 0, 0, 255), color)
	
	StopDrawing()
	
EndIf

OpenWindow(0, 0, 0, w, h, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
ImageGadget(0, 0, 0, w, h, ImageID(res))

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow

End
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Pour justifier ses DrawText()

Message par Le Soldat Inconnu »

ah oui :( Faut poster le bug sur le forum anglais.

Personnellement, je n'utilise jamais de fond sur mes textes alors je n'avais pas remarquer ce soucis
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Répondre