동일한 줄의 다른 글꼴에서 텍스트 그리기
글꼴 패밀리 내의 다른 형식 스타일은 너비가 다를 수 있습니다. 예를 들어 패밀리의 굵게 및 기울임꼴 스타일은 지정된 포인트 크기의 로마 스타일보다 항상 넓습니다. 한 줄에 여러 형식 스타일을 표시하거나 인쇄하는 경우 문자가 서로 위에 표시되거나 인쇄되지 않도록 줄 너비를 추적해야 합니다.
두 함수를 사용하여 현재 글꼴에서 텍스트의 너비(또는 익스텐트)를 검색할 수 있습니다. GetTabbedTextExtent 함수는 문자열의 너비와 높이를 계산합니다. 문자열에 하나 이상의 탭 문자가 포함된 경우 문자열의 너비는 지정된 탭 중지 위치 배열을 기반으로 합니다. GetTextExtentPoint32 함수는 텍스트 줄의 너비와 높이를 계산합니다.
필요한 경우 시스템은 문자 비트맵을 변경하여 글꼴을 합성합니다. 굵은 글꼴로 문자를 합성하기 위해 시스템은 시작점에서 문자를 두 번 그리고 시작점 오른쪽에 한 픽셀을 다시 그립니다. 기울임꼴 글꼴로 문자를 합성하기 위해 시스템은 문자 셀 아래쪽에 두 개의 픽셀 행을 그리고, 시작점을 오른쪽으로 한 픽셀 이동하고, 다음 두 행을 그리고, 문자가 그려질 때까지 계속됩니다. 픽셀을 이동하면 각 문자가 오른쪽으로 전단된 것처럼 보입니다. 전단의 양은 문자 높이의 함수입니다.
여러 글꼴이 포함된 텍스트 줄을 작성하는 한 가지 방법은 TextOut을 호출할 때마다 GetTextExtentPoint32 함수를 사용하고 현재 위치에 길이를 추가하는 것입니다. 다음 예제에서는 "This is a"에 굵은 문자를 사용하여 "This is a"라는 줄을 쓰고 "sample"의 기울임꼴 문자로 전환한 다음 "string"에 대해 굵은 문자로 돌아갑니다. 모든 문자열을 인쇄한 후 시스템 기본 문자를 복원합니다.
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);
이 예제에서 GetTextExtentPoint32 함수는 지정된 문자열의 길이와 높이를 사용하여 SIZE 구조체의 멤버를 초기화합니다. GetTextMetrics 함수는 현재 글꼴의 오버행을 검색합니다. 글꼴이 TrueType 글꼴이면 오버행이 0이므로 오버행 값은 문자열 배치를 변경하지 않습니다. 그러나 래스터 글꼴의 경우 오버행 값을 사용하는 것이 중요합니다.
글꼴이 래스터 글꼴인 경우 후속 문자를 문자열 끝에 더 가깝게 만들기 위해 굵은 문자열에서 오버행을 한 번 뺍니다. 오버행은 래스터 글꼴에서 기울임꼴 문자열의 시작과 끝에 모두 영향을 주므로 문자 모양은 지정된 위치의 오른쪽에서 시작되고 마지막 문자 셀의 엔드포인트 왼쪽에서 끝납니다. (GetTextExtentPoint32 함수는 문자 모양 범위가 아니라 문자 셀의 범위를 검색합니다.) 래스터 기울임꼴 문자열의 오버행을 설명하기 위해 예제에서는 문자열을 배치하기 전에 오버행을 빼고 후속 문자를 배치하기 전에 다시 뺍니다.
SetTextJustification 함수는 텍스트 줄의 나누기 문자에 추가 공간을 추가합니다. GetTextExtentPoint 함수를 사용하여 문자열의 범위를 확인한 다음 줄이 차지해야 하는 총 공간 크기에서 해당 범위를 빼고 SetTextJustification 함수를 사용하여 문자열의 나누기 문자 간에 추가 공간을 분산할 수 있습니다. SetTextCharacterExtra 함수는 중단 문자를 포함하여 선택한 글꼴의 모든 문자 셀에 추가 공간을 추가합니다. (GetTextCharacterExtra 함수를 사용하여 문자 셀에 추가되는 현재 추가 공간의 양을 확인할 수 있습니다. 기본 설정은 0입니다.)
GetCharWidth32 또는 GetCharABCWidths 함수를 사용하여 글꼴에서 개별 문자의 너비를 검색하여 전체 자릿수가 더 높은 문자를 배치할 수 있습니다. GetCharABCWidths 함수는 GetCharWidth32 함수보다 더 정확하지만 TrueType 글꼴에서만 사용할 수 있습니다.
ABC 간격을 사용하면 애플리케이션이 매우 정확한 텍스트 맞춤을 수행할 수도 있습니다. 예를 들어 애플리케이션이 ABC 간격을 사용하지 않고 래스터 로마 글꼴을 오른쪽에 맞추면 사전 너비가 문자 너비로 계산됩니다. 즉, 비트맵의 문자 모양 오른쪽에 있는 공백이 문자 모양 자체가 아니라 정렬됩니다. ABC 너비를 사용하여 애플리케이션은 텍스트를 정렬할 때 공백의 배치 및 제거에 더 많은 유연성을 제공합니다. 이는 문자 간 간격을 세밀하게 제어할 수 있는 정보가 있기 때문입니다.