Condividi tramite


Disegno di testo da tipi di carattere diversi sulla stessa linea

Diversi stili di tipo all'interno di una famiglia di caratteri possono avere larghezze diverse. Ad esempio, gli stili grassetto e corsivo di una famiglia sono sempre più ampi dello stile romano per una dimensione punto specificata. Quando si visualizzano o si stampano diversi stili di tipo su una singola riga, è necessario tenere traccia della larghezza della riga per evitare che i caratteri vengano visualizzati o stampati l'uno sopra l'altro.

È possibile utilizzare due funzioni per recuperare la larghezza (o l'extent) del testo nel tipo di carattere corrente. La funzione GetTabbedTextExtent calcola la larghezza e l'altezza di una stringa di caratteri. Se la stringa contiene uno o più caratteri di tabulazione, la larghezza della stringa è basata su una matrice specificata di posizioni di tabulazione. La funzione GetTextExtentPoint32 calcola la larghezza e l'altezza di una riga di testo.

Quando necessario, il sistema sintetizza un tipo di carattere modificando le bitmap dei caratteri. Per sintetizzare un carattere in grassetto, il sistema disegna il carattere due volte: al punto iniziale e di nuovo un pixel a destra del punto iniziale. Per sintetizzare un carattere in corsivo, il sistema disegna due righe di pixel nella parte inferiore della cella di caratteri, sposta il punto iniziale un pixel a destra, disegna le due righe successive e continua fino a quando il carattere non viene disegnato. Spostando i pixel, ogni carattere sembra essere a destra. La quantità di shear è una funzione dell'altezza del carattere.

Un modo per scrivere una riga di testo contenente più tipi di carattere consiste nell'usare la funzione GetTextExtentPoint32 dopo ogni chiamata a TextOut e aggiungere la lunghezza a una posizione corrente. Nell'esempio seguente viene scritta la riga "This is a sample string". Using bold characters for "This is a", passa ai caratteri corsivi per "sample", quindi restituisce caratteri in grassetto per "string". Dopo aver stampato tutte le stringhe, ripristina i caratteri predefiniti del sistema.

int XIncrement; 
int YStart; 
TEXTMETRIC tm; 
HFONT hfntDefault, hfntItalic, hfntBold; 
SIZE sz; 
LPSTR lpszString1 = "This is a "; 
LPSTR lpszString2 = "sample "; 
LPSTR lpszString3 = "string."; 
HRESULT hr;
size_t * pcch;
 
// Create a bold and an italic logical font.  
 
hfntItalic = MyCreateFont(); 
hfntBold = MyCreateFont(); 
 
 
// Select the bold font and draw the first string  
// beginning at the specified point (XIncrement, YStart).  
 
XIncrement = 10; 
YStart = 50; 
hfntDefault = SelectObject(hdc, hfntBold); 
hr = StringCchLength(lpszString1, 11, pcch);
        if (FAILED(hr))
        {
        // TODO: write error handler 
        }
TextOut(hdc, XIncrement, YStart, lpszString1, *pcch); 
 
// Compute the length of the first string and add  
// this value to the x-increment that is used for the  
// text-output operation.  

hr = StringCchLength(lpszString1, 11, pcch);
        if (FAILED(hr))
        {
        // TODO: write error handler 
        } 
GetTextExtentPoint32(hdc, lpszString1, *pcch, &sz); 
XIncrement += sz.cx; 
 
// Retrieve the overhang value from the TEXTMETRIC  
// structure and subtract it from the x-increment.  
// (This is only necessary for non-TrueType raster  
// fonts.)  
 
GetTextMetrics(hdc, &tm); 
XIncrement -= tm.tmOverhang; 
 
// Select an italic font and draw the second string  
// beginning at the point (XIncrement, YStart).  
 
hfntBold = SelectObject(hdc, hfntItalic); 
GetTextMetrics(hdc, &tm); 
XIncrement -= tm.tmOverhang;
hr = StringCchLength(lpszString2, 8, pcch);
        if (FAILED(hr))
        {
        // TODO: write error handler 
        } 
TextOut(hdc, XIncrement, YStart, lpszString2, *pcch); 
 
// Compute the length of the second string and add  
// this value to the x-increment that is used for the  
// text-output operation.  

hr = StringCchLength(lpszString2, 8, pcch);
        if (FAILED(hr))
        {
        // TODO: write error handler 
        }  
GetTextExtentPoint32(hdc, lpszString2, *pcch, &sz); 
XIncrement += sz.cx; 
 
// Reselect the bold font and draw the third string  
// beginning at the point (XIncrement, YStart).  
 
SelectObject(hdc, hfntBold);
hr = StringCchLength(lpszString3, 8, pcch);
        if (FAILED(hr))
        {
        // TODO: write error handler 
        }  
TextOut(hdc, XIncrement - tm.tmOverhang, YStart, lpszString3, 
            *pcch); 
 
// Reselect the original font.  
 
SelectObject(hdc, hfntDefault); 
 
// Delete the bold and italic fonts.  
 
DeleteObject(hfntItalic); 
DeleteObject(hfntBold); 

In questo esempio la funzione GetTextExtentPoint32 inizializza i membri di una struttura SIZE con la lunghezza e l'altezza della stringa specificata. La funzione GetTextMetrics recupera l'overhang per il tipo di carattere corrente. Poiché l'overhang è zero se il tipo di carattere è TrueType, il valore dell'overhang non modifica il posizionamento della stringa. Per i tipi di carattere raster, tuttavia, è importante usare il valore dell'overhang.

L'overhang viene sottratto una sola volta dalla stringa in grassetto per avvicinare i caratteri successivi alla fine della stringa se il tipo di carattere è un tipo di carattere raster. Poiché l'overhang influisce sia sull'inizio che sulla fine della stringa corsiva in un tipo di carattere raster, i glifi iniziano a destra della posizione specificata e terminano a sinistra dell'endpoint dell'ultima cella di caratteri. La funzione GetTextExtentPoint32 recupera l'extent delle celle di caratteri, non l'extent dei glifi. Per tenere conto dell'overhang nella stringa corsivo raster, l'esempio sottrae l'overhang prima di posizionare la stringa e la sottrae nuovamente prima di posizionare i caratteri successivi.

La funzione SetTextJustification aggiunge spazio aggiuntivo ai caratteri di interruzione in una riga di testo. È possibile utilizzare la funzione GetTextExtentPoint per determinare l'estensione di una stringa, quindi sottrarre tale extent dalla quantità totale di spazio che la riga deve occupare e utilizzare la funzione SetTextJustification per distribuire lo spazio aggiuntivo tra i caratteri di interruzione nella stringa. La funzione SetTextCharacterExtra aggiunge spazio aggiuntivo a ogni cella di caratteri nel tipo di carattere selezionato, incluso il carattere di interruzione. È possibile utilizzare la funzione GetTextCharacterExtra per determinare la quantità corrente di spazio aggiuntivo da aggiungere alle celle di caratteri. L'impostazione predefinita è zero.

È possibile inserire caratteri con maggiore precisione usando la funzione GetCharWidth32 o GetCharABCWidths per recuperare le larghezze dei singoli caratteri in un tipo di carattere. La funzione GetCharABCWidths è più accurata rispetto alla funzione GetCharWidth32 , ma può essere usata solo con tipi di carattere TrueType.

La spaziatura ABC consente anche a un'applicazione di eseguire un allineamento del testo molto accurato. Ad esempio, quando l'applicazione a destra allinea un tipo di carattere romano raster senza utilizzare la spaziatura ABC, la larghezza di avanzamento viene calcolata come larghezza del carattere. Ciò significa che lo spazio vuoto a destra del glifo nella bitmap è allineato, non il glifo stesso. Usando le larghezze ABC, le applicazioni hanno maggiore flessibilità nella posizione e nella rimozione di spazi vuoti durante l'allineamento del testo, perché contengono informazioni che consentono di controllare correttamente la spaziatura intercattabile.