venerdì 22 gennaio 2010

Addio campo di testo!

Con questa frase Michael Baczynski intitola il suo post, dove va a descrivere i
suoi motivi per aver abbandonato il campo di testo nei momenti in cui gli serve
una scritta a video. Iniziamo dal principio, dall'articolo di Michael si evince
che ogni tanto gli serve poter scrivere a video delle informazioni, spesso di controllo,
con l'utilizzo del campo di testo la situazione si faceva complicata, quindi ha
studiato un modo per poter velocizzare questa operazione. La sua soluzione e' creare
una funzione che vada a disegnare del testo attraverso una serie di lineTo,
curveTo e moveTo. Per fare arrivare a questa soluzione Michael va
a convertire in formato EPS un font (ovvero vengono creati un file per ogni carattere
del font, ndr), creare un parser minimale che permetta di trasformare il file EPS
in una serie di comandi per disegno e il tutto incapsulato in una serie di funzioni
che ci rendono semplice la scrittura.



A questo punto ho ho provato a capire meglio come abbia fatto, dato che non ha rilasciato
nemmeno una riga di codice utile, utilizzando questo articolo come un simpatico
esercizio di programmazione.



Per prima cosa ho convertito il font scelto in una serie di file EPS (SCRIVERE COME!!!),
successivamente ho cercato una grammatica esistente per parsare i file ed poter
estrarre i dati interessanti, non esistendone una ho deciso di scriverla. Per fare
questo ho utilizzato Coco, un generatore di parser che mi ha creato codice C#, che
importato in un semplice programmino ho estratto le informazioni utili. Da notare
che le prime righe di un file EPS sono fisse, quindi per semplificare la grammatica
e quindi il riconoscimnto dei token ho ampliato il programma C# in modo che queste
righe superflue vengano eliminate.



Il primo problema incontrato nella generazione di codice AS, e' stato che i file
EPS utilizzano curve di bezier cubice, mentre in AS si utilizzano curve di Bezier
quadriche. Per risolvere questo problema ho chiesto documentazione a Michael, che
gentilmente mi ha mandato due link molto utili, il primo spiega semplicemente cosa
sono le curve di Bezier, mentre il secondo e' un tecnical report sulla creazione
delle curve. In quest'ultimo ho trovato in maniera grossolana la soluzione.



curva di bezier cubica.
Curca vi Bezier cubica.


curva di bezier quadrica.
Curva di Bezier quadrica.




Ogni volta che si incontra una curveTo nel file EPS si deve eseguire un piccolo
conto, per trovare il punto di ancoraggio corretto. Per fare cio' si calcola per
prima cosa la retta passante per il punto di inizio curva e il primo punto di ancoraggio
trovato nel file EPS.




Y = X * m + q e' l'equazione di una retta, quindi per calcolare una retta
passante per due punti per prima cosa mi calcolo il coefficente angolare m come




m = (Y2 - Y1) / (X2 - X1)



da qui andiamo a sostituire nella formula generale in uno dei due punti e calcoliamoci
q




q = Y1 - (X1 * m)


q = Y1 - (X1 * (Y2 - Y1) / (X2 - X1))



a questo punto applichiamo lo stesso ragionamento per trovare la seconda retta che
passera' per il secondo punto di ancoraggio e il punto dove andra' a finire la curva.




Ora abbiamo le due rette r1 e r2, non resta che calcolare il punto
di intersezione, anche qui la geometria piana ci viene in contro, quindi si trova
facilmente il punto di incontro P




Px = (qr1 - qr2) / (mr2 - mr1)


Py = mr1 (qr1 - qr2) / (mr2 - m21) +qr1



A questo punto P e' il nostro punto di ancoraggio per la curva di bezier
quadrica. Per quanto riguarda gli altri due comandi, moveTo e lineTo,
i parametri letti dal file sono gia' corretti, quindi basta semplicemente riscriverli.



Ora abbiamo tutto quello che ci serve per poter trasformare un carattere di un font
in una serie di fhiamate a funzioni per il disegno di questo, quindi non serve altro
che arricchire il nostro programma con una serie di stampe che ci permettano di
creare una classe AS che sia comoda da usare.



Nel mio programma accetto una lista di directory, e per ogniuna di esse creo una
classe al cui interno inserisco una fnzione per ogni carattere che intendo disegnare
e una funzione che prende in ingresso una stringa e per ogni carattere va a richiamare
la funzione corretta.



Qui potete scaricare la classe risultante per il font Arial.