Curvare la linea di testo in un oggetto Image

Da Gambas-it.org - Wikipedia.

Una soluzione per ottenere un testo curvato lungo una ideale circonferenza, potrebbe essere quella di creare tante piccoli oggetti di tipo Image per quante sono le lettere alfabetiche o le sillabe. [Nota 1]
Ciascuna lettera o sillaba verrebbe quindi disegnata in uno di quegli oggetti Image.
Infine tali oggetti Image verrebbero adeguatamente ruotati in modo perpendicolare al raggio della circonferenza (o dell'arco) e disegnati/fusi in un Oggetto Image principale più grande, per formare il testo completo e apparentemente curvato.

Mostriamo un esempio pratico:

Private Const GRADI_INIZIO As Float = 250.0
Private Const CURVATURA As Float = 8.0
Private Const FONT_NOME As String = "Liberation Mono"
Private Const FONT_DIM As Float = 20


Public Sub Form_Open()

 Dim pb As PictureBox
 Dim bb As Byte[]
 Dim s As String
 Dim fo As Font
 Dim an As Float
 Dim ii As Image[]
 Dim b As Byte
 Dim i, im As Image
 Dim x, y, x_a, y_o, r As Short
 
 Me.Show
 
 With Me
   .Center
   .W = 600
   .H = 600
   .Arrangement = Arrange.Fill
 End With
 
 With pb = New PictureBox(Me)
   .X = 0
   .Y = 0
 End With
 
' Imposta il testo da disegnare:
' Carica ogni carattere del testo In un vettore Byte[] per poter estrarre di ciascuno il valore.
 bb = Byte[].FromString("Questo è un testo qualsiasi")
 
' Imposta il punto (sulla base dei gradi) della circonferenza da dove cominciare (in senso orario) a disegnare le lettere:
 an = GRADI_INIZIO
 
 ii = New Image[]
 
 For b = 0 To bb.Max
' Verifica innanzitutto se il carattere è accentato (carattere ASCII speciale):
   If bb[b] > 127 Then
' Se è un carattere accentato, per riottenerlo nell'Image, combina i due valori che lo compongono:
     s = Chr(bb[b]) & Chr(bb[b + 1])
     Inc b
   Else
     s = Chr(bb[b])
   Endif
' Definisce le dimensioni dell'immagine, che conterrà la lettera alfabetica, dalle specificità del carattere:
   With fo = New Font
' Si impostano solo le proprietà della Classe "Font" che potrebbero influire sulla reale dimensione del carattere:
     .Name = FONT_NOME
     .Size = FONT_DIM
     .Bold = True
' Crea un oggetto "Image" per contenere il disegno di una lettera alfabetica:
     i = New Image(.TextWidth(s), .TextHeight(s), Color.Transparent, gb.Standard)
   End With
   With Paint
     .Begin(i)
     .Font.Name = fo.Name
     .Font.Size = fo.Size
     .Font.Bold = True
     .Brush = .Color(Color.Red)
     .DrawText(s, 0, 0, i.W, i.H, Align.Normal)
     .End
   End With
' Ruota l'immagine in senso orario:
   i = i.Rotate(Rad(-an))
   ii.Push(i)
' Imposta il valore relativo alla rotazione della prossima immagine contenente un carattere:
   an += CURVATURA
 Next 
 
 x_a = pb.W / 2    ' Rappresenta la distanza X dal punto 0 (angolo in alto a sinistra) dell'Image principale
 y_o = pb.H / 2    ' Rappresenta la distanza Y dal punto 0 (angolo in alto a sinistra) dell'Image principale
 r = 200           ' Rappresenta la lunghezza del raggio (la distanza di ogni immagine-lettera dal centro)
 
' Crea l'Oggetto "Image" ove saranno disegnate le singole immagini dei caratteri per ricreare il testo ruotato:
 im = New Image(pb.W, pb.H, Color.Yellow, gb.Standard)
 
' Imposta il punto (sulla base dei gradi) della circonferenza da dove cominciare (in senso orario) a disegnare le singole Image nella Image "im" superficie principale:
 an = GRADI_INIZIO - 90.0
 
 For b = 0 To ii.Max
' Imposta la curvatura delle singole Image dei caratteri:
   x = x_a + r * Cos(Rad(an)) 
   y = y_o + r * Sin(Rad(an))
   With Paint
     .Begin(im)
     .DrawImage(ii[b], x, y, ii[b].W, ii[b].H, 1.0, Null)
     .End
   End With
' Imposta la distanza delle singole immagini dei caratteri fra esse (avanza lungo la curva del testo definendola):
   an += CURVATURA
 Next
 
 pb.Image = im

End


Note

[1] Vedere anche questa pagina: Curvare il testo in una DrawingArea