Desenho de texto de fontes diferentes na mesma linha
Estilos de tipo diferentes dentro de uma família de fontes podem ter larguras diferentes. Por exemplo, estilos em negrito e itálico de uma família são sempre mais largos do que o estilo romano para um tamanho de ponto especificado. Ao exibir ou imprimir vários estilos de tipo em uma única linha, você deve acompanhar a largura da linha para evitar ter caracteres exibidos ou impressos em cima uns dos outros.
Você pode usar duas funções para recuperar a largura (ou extensão) do texto na fonte atual. A função GetTabbedTextExtent calcula a largura e a altura de uma cadeia de caracteres. Se a cadeia de caracteres contiver um ou mais caracteres de guia, a largura da cadeia de caracteres será baseada em uma matriz especificada de posições de parada de tabulação. A função GetTextExtentPoint32 calcula a largura e a altura de uma linha de texto.
Quando necessário, o sistema sintetiza uma fonte alterando os bitmaps de caractere. Para sintetizar um caractere em uma fonte em negrito, o sistema desenha o caractere duas vezes: no ponto de partida e, novamente, um pixel à direita do ponto de partida. Para sintetizar um caractere em uma fonte itálica, o sistema desenha duas linhas de pixels na parte inferior da célula de caracteres, move o ponto inicial um pixel para a direita, desenha as duas linhas seguintes e continua até que o caractere seja desenhado. Ao deslocar pixels, cada caractere parece estar sendo esculachado para a direita. A quantidade de tesoura é uma função da altura do caractere.
Uma maneira de escrever uma linha de texto que contém várias fontes é usar a função GetTextExtentPoint32 após cada chamada para TextOut e adicionar o comprimento a uma posição atual. O exemplo a seguir grava a linha "Esta é uma cadeia de caracteres de exemplo". Usando caracteres em negrito para "This is a", alterna para caracteres itálicos para "sample" e retorna para caracteres em negrito para "string". Depois de imprimir todas as cadeias de caracteres, ele restaura os caracteres padrão do 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);
Neste exemplo, a função GetTextExtentPoint32 inicializa os membros de uma estrutura SIZE com o comprimento e a altura da cadeia de caracteres especificada. A função GetTextMetrics recupera a saliência da fonte atual. Como a saliência será zero se a fonte for uma fonte TrueType, o valor de saliência não alterará o posicionamento da cadeia de caracteres. No entanto, para fontes raster, é importante usar o valor de saliência.
A saliência é subtraída da cadeia de caracteres em negrito uma vez, para aproximar os caracteres subsequentes do final da cadeia de caracteres se a fonte for uma fonte de raster. Como a saliência afeta o início e o fim da cadeia de caracteres itálica em uma fonte raster, os glifos começam à direita do local especificado e terminam à esquerda do ponto de extremidade da última célula de caracteres. (A função GetTextExtentPoint32 recupera a extensão das células de caractere, não a extensão dos glifos.) Para considerar a saliência na cadeia de caracteres itálica raster, o exemplo subtrai a saliência antes de colocar a cadeia de caracteres e subtrai-a novamente antes de colocar caracteres subsequentes.
A função SetTextJustification adiciona espaço extra aos caracteres de quebra em uma linha de texto. Você pode usar a função GetTextExtentPoint para determinar a extensão de uma cadeia de caracteres e subtrair essa extensão da quantidade total de espaço que a linha deve ocupar e usar a função SetTextJustification para distribuir o espaço extra entre os caracteres de quebra na cadeia de caracteres. A função SetTextCharacterExtra adiciona espaço extra a cada célula de caractere na fonte selecionada, incluindo o caractere de interrupção. (Você pode usar a função GetTextCharacterExtra para determinar a quantidade atual de espaço extra que está sendo adicionada às células de caracteres; a configuração padrão é zero.)
Você pode colocar caracteres com maior precisão usando a função GetCharWidth32 ou GetCharABCWidths para recuperar as larguras de caracteres individuais em uma fonte. A função GetCharABCWidths é mais precisa do que a função GetCharWidth32 , mas só pode ser usada com fontes TrueType.
O espaçamento ABC também permite que um aplicativo execute um alinhamento de texto muito preciso. Por exemplo, quando o aplicativo à direita alinha uma fonte romana de raster sem usar o espaçamento ABC, a largura avançada é calculada como a largura do caractere. Isso significa que o espaço em branco à direita do glifo no bitmap está alinhado, não o glifo em si. Usando larguras ABC, os aplicativos têm mais flexibilidade no posicionamento e remoção do espaço em branco ao alinhar o texto, pois têm informações que permitem controlar o espaçamento entre caracteres.