프린터 장치 글꼴 사용

프린터에 있는 글꼴은 애플리케이션 프로그램 코드에서 유용하고 사용하기 어려울 수 있습니다. 이 문서에서는 Win32 프린터 디바이스 컨텍스트에서 사용할 수 있는 프린터 상주 디바이스 글꼴을 확인하는 방법을 설명합니다. 또한 이 문서에서는 애플리케이션 코드에서 프린터 글꼴을 사용하려고 할 때 발생할 수 있는 몇 가지 문제에 대해서도 설명합니다.

원래 제품 버전: Win32 프린터 장치
원래 KB 번호: 201978

요약

대부분의 경우 소프트웨어 개발자는 운영 체제를 사용하여 그리기에 사용할 글꼴을 제공합니다. 이렇게 하려면 API(애플리케이션 프로그래밍 인터페이스) 또는 일반적인 글꼴 선택 대화 상자를 통해 운영 체제에서 제공하는 글꼴을 선택할 수 있습니다. 그러나 애플리케이션은 일반적으로 사용되는 특정 글꼴과 관련이 없으며 특정 요구 사항을 충족하며 사용자는 글꼴을 선호합니다. 이러한 요구 사항에는 다음이 포함됩니다.

  • 글꼴은 특정 크기여야 합니다.
  • 글꼴에는 문자(문자 모양이라고도 함)가 포함되어야 합니다.
  • 글꼴에는 특정 스타일이 있어야 합니다.

일반적으로 애플리케이션이 문서를 인쇄할 때 애플리케이션의 특정 작업 없이 프린터에서 글꼴(또는 이와 유사한 글꼴)이 사용됩니다. 이는 일반적으로 애플리케이션에 대한 올바른 결과이며 적절한 속도로 좋은 인쇄 결과를 생성합니다.

그러나 경우에 따라 애플리케이션 개발자는 대상 프린터에서 특정 글꼴만 선택해야 할 수 있습니다. 지금까지는 특정 서식을 가져오거나 인쇄 속도를 높이기 위해 영향 유형 프린터(예: 점 매트릭스 프린터)에 필요했습니다.

오늘날 대부분의 프린터는 래스터 장치로 근본적으로 설계되었으며 모든 문자 문자 모양만큼 효율적으로 용지의 모든 부분에 점(픽셀)을 그릴 수 있습니다. 대부분의 애플리케이션에서는 문자 문자 모양이 프린터 상주 정의에서 전체 양식으로 그려지거나 운영 체제에서 제공하는 픽셀 컬렉션으로 그려지는지 여부는 문제가 되지 않습니다. 그러나 프린터만 제공하는 글꼴을 계속 사용할 수 있습니다. 예를 들어 글꼴이 고유하고 운영 체제에서 유사한 대체 항목이 없거나 프린터에 글꼴 정의를 다운로드하는 오버헤드를 방지하려는 경우에 발생할 수 있습니다.

디바이스 글꼴

이 문서의 목적을 위해 디바이스 글꼴은 프린터 메모리에 영구적으로 또는 일시적으로 정의가 있는 모든 글꼴입니다. 이러한 디바이스 글꼴은 프린터의 페이지 래스터라이저 하드웨어를 통해 문자별로 주소를 지정할 수 있는 문자 문자 모양 정의를 제공하여 셰이프를 용지에 잉크로 붙입니다.

디바이스 글꼴은 다음 세 가지 기본 유형으로 분류할 수 있습니다.

  • True 디바이스 글꼴입니다. 이 문서에서는 프린터 하드웨어만 제공하고 프린터에서만 사용할 수 있는 글꼴입니다.

  • 디바이스 글꼴 대체. 운영 체제에 있고 프린터 하드웨어에서도 제공하는 글꼴입니다. 이 경우 프린터 하드웨어는 운영 체제의 글꼴을 대체할 수 있습니다.

  • 다운로드 가능한 글꼴입니다. 운영 체제에서 제공하지만 해당 정의를 프린터에 다운로드하고 프린터 하드웨어에서 직접 글꼴을 제공한 것처럼 프린터에서 사용할 수 있는 글꼴입니다.

다운로드 가능한 글꼴

운영 체제는 소프트 글꼴이라고도 하는 다운로드 가능한 글꼴을 제공합니다. 문서를 인쇄하면 글꼴에 대한 정의가 인쇄 작업의 일부로 제공됩니다. 프린터가 인쇄 작업을 처리할 때 글꼴 정의가 문서의 인쇄 페이지에 잉크로 삽입될 수 있도록 프린터 메모리에 글꼴 정의가 설치됩니다.

어떤 사람들은 프린터가 글꼴의 문자 모양을 그리기 때문에 이러한 글꼴은 장치 글꼴이라고 주장합니다. 그러나 글꼴 정의를 다운로드하거나 비트맵을 통해 프린터에 문자 모양을 그릴 때 일부 오버헤드 또는 인쇄 작업 스풀 크기만 저장됩니다. 이 프로세스는 응용 프로그램에서 투명하게 수행되므로 운영 체제의 글꼴을 화면과 프린터에서 사용할 수 있습니다. 이 문서에서는 프린터만 제공하는 디바이스 글꼴을 사용하는 방법에 중점을 두므로 이 문서에서는 다운로드 가능한 글꼴을 사용하는 방법을 설명하지 않습니다.

디바이스 글꼴 대체

디바이스 글꼴 대체는 운영 체제에서 사용하는 글꼴 정의와 프린터에서 사용하는 두 가지 고유한 글꼴 정의가 있을 때 발생합니다. 즉, 애플리케이션은 화면의 문서에서 운영 체제의 글꼴을 선택하고 사용합니다. 문서를 인쇄할 때 프린터에서 제공하는 유사하게 정의된 글꼴을 사용하여 인쇄된 출력을 그립니다. 따라서 운영 체제의 글꼴이 프린터에서 프린터 정의 글꼴로 대체되었습니다.

일반적으로 일반적인 Windows TrueType 글꼴을 사용할 때 PostScript 프린터에서 발생합니다. 예를 들어 대부분의 PostScript 디바이스에서 Helvetica 글꼴에 대해 PostScript 글꼴 정의를 사용하여 일반적으로 인쇄되는 TrueType Arial 글꼴이 있습니다. 글꼴 이름이 다른 유사한 글꼴을 사용하여 대체의 예입니다. 이 경우 일반적으로 유사한 글꼴 정의가 실제 디바이스 글꼴로 노출되기 때문에 이 유사한 글꼴 정의를 직접 찾아 사용할 수 있습니다. 이 내용은 이 문서의 뒷부분에서 설명합니다.

프린터의 글꼴이 운영 체제에서 제공하는 글꼴과 이름이 같은 경우에도 디바이스 글꼴 대체가 발생합니다. 이는 일반적으로 Hewlett-Packard LaserJet 프린터와 같은 프린터에서 발생합니다. 이러한 프린터에는 일반적으로 Arial 및 Times New Roman과 같은 Windows 코어 글꼴의 자체 버전이 있습니다. 이러한 글꼴은 일반적으로 실제 디바이스 글꼴을 검색하여 찾을 수 있지만 프린터 드라이버가 자주 자체적으로 선택하거나 사용자 설정을 통해 운영 체제에서 제공하는 글꼴을 사용할지 여부를 선택하기 때문에 이러한 글꼴을 사용할 수 없는 경우도 있습니다.

True 디바이스 글꼴

실제 디바이스 글꼴은 프린터에 정의만 있는 글꼴입니다. 애플리케이션에서 이러한 글꼴을 사용할 수 있는 유일한 방법은 애플리케이션이 글꼴을 구체적으로 식별하고 프린터 디바이스 컨텍스트에서 사용할 수 있도록 만드는 것입니다.

디바이스에 대한 충분한 정보를 알고 있는 경우 디바이스 글꼴을 실현하는 구조로 논리 글꼴 설명을 LOGFONT 만들 수 있습니다. 특히 글꼴의 멤버, 멤버 및 문자 집합에 lfHeight 대한 lfFacename 올바른 정보를 제공하는 것이 중요합니다. 또한 멤버는 lfOutPrecision 비슷한 이름의 시스템 글꼴 대신 디바이스 글꼴을 선택하는 글꼴 매핑 프로세스에 영향을 주는 플래그를 포함 OUT_DEVICE_PRECIS 해야 합니다.

글꼴에 대한 설명을 알 수 없는 경우 글꼴을 열거하여 디바이스 글꼴을 검색할 수 있습니다. 프린터에서 지원하는 디바이스 글꼴 목록을 가져오려면 와 같은 EnumFontFamiliesEx글꼴 열거형 함수 중 하나를 사용합니다. 콜백 함수에 배치되는 애플리케이션 코드는 콜백 함수에 전달되는 데이터를 검사하여 디바이스 글꼴을 설명하는 글꼴 인스턴스를 확인할 수 있습니다.

실제 디바이스 글꼴 사용

프린터 디바이스 컨텍스트에서 디바이스 글꼴을 사용하는 프로세스는 다음과 같은 일반적인 단계를 따릅니다.

  1. 프린터 디바이스 컨텍스트에서 글꼴을 열거하여 실제 디바이스 글꼴을 식별합니다.
  2. 플래그 및 제거 프로세스에 의해 표시된 FontType 대로 디바이스 전용인 글꼴을 선택합니다.
  3. 매핑 모드에서 프린터별 메트릭을 MM_TEXT 사용하여 디바이스 글꼴을 사용하여 그린 텍스트를 정확하게 배치합니다.

프린터 디바이스 컨텍스트의 글꼴 열거

디바이스 컨텍스트에서 사용할 수 있는 모든 글꼴을 열거하려면 Win32 API(애플리케이션 프로그래밍 인터페이스)의 콜백 함수와 EnumFontFamiliesEx 함수를 사용할 수 있습니다. 디바이스 컨텍스트에 대한 모든 글꼴을 열거하려면 두 번 호출 EnumFontFamiliesEx 해야 합니다. 먼저 글꼴 패밀리 목록을 가져오는 경우와 각 글꼴 패밀리에 있는 모든 고유 글꼴을 가져오는 두 번째 글꼴입니다.

프린터 디바이스 컨텍스트에서 모든 디바이스 글꼴을 찾으려면 프린터 디바이스 컨텍스트의 모든 글꼴을 열거해야 합니다. 각 글꼴이 콜백 함수에 전달되면 글꼴이 검사되어 디바이스 글꼴인지 확인합니다. 다음 샘플 코드의 PrinterDeviceFontEnumPrinterDeviceFontFamiliesEnum 콜백 함수는 이 작업을 수행합니다.

// Data structure to pass data through the font enumeration callbacks.
typedef struct PrintEnumFontData
{
    HDC             hPrinterDC;
    HDC             hEnumDC;
    int             curx, cury;
    ENUMLOGFONTEX   elf;
} PRINTENUMFONTDATA;

int CALLBACK PrinterDeviceFontEnum(
  ENUMLOGFONTEX *lpelfe,    // logical-font data
  NEWTEXTMETRICEX *lpntme,  // physical-font data
  DWORD FontType,           // type of font
  LPARAM lParam             // application-defined data
)
{
    // Crack the data out of the enumeration parameter.
    PRINTENUMFONTDATA *     ppeft = (PRINTENUMFONTDATA*) lParam;

    // Printing information
    TEXTMETRIC              tm;
    HFONT                   hfont, holdfont;
    int                     pagecx, pagecy;

    // Data to determine where this font came from
    ENUMEDFONT      df = { FontType, lpelfe };  // To look for a system version

    // What is the printable area of the page?
    pagecx = GetDeviceCaps(ppeft->hPrinterDC, HORZRES);
    pagecy = GetDeviceCaps(ppeft->hPrinterDC, VERTRES);

    // Is it a device font?
    // If it is, make sure that it is also not a TrueType font because
    // that is most likely a downloaded font.
    // Also, look for any system-provided fonts that are also
    // masquerading as printer device fonts. This implies that they will be
    // downloaded to the printer as is the case with Adobe Type 1 fonts.
    // If they are downloaded, you do not want to include them in this demonstration.
    if (FontType & DEVICE_FONTTYPE &&
        !(FontType & TRUETYPE_FONTTYPE) &&
        !IsSystemFont(&df))
    {
        TCHAR           Buffer[MAX_PATH];           // description of font
        LPTSTR          szFontType;                 // description of type
        LPTSTR          pStyle = "Regular";         // Fonts Style defaults to Regular

        // At this point in this code, the lpelfe parameter has been examined
        // and found to describe a printer device font.
        // Do something interesting with it as follows:

        // Build a sample string that describes the font.
        if (lpelfe->elfLogFont.lfItalic)
        {
            pStyle = "Italic";
            if (lpelfe->elfLogFont.lfWeight > FW_NORMAL)
                pStyle = "Bold Italic";
        }
        else if (lpelfe->elfLogFont.lfWeight > FW_NORMAL)
            pStyle = "Bold";

        // Determine if the font is scalable or a bitmap font.
        if (FontType & RASTER_FONTTYPE)
            szFontType = TEXT("Bitmap Font");
        else
        {
            // This is an instance of a scalable font, 
            // use 12 pt because it is easy to read.
            szFontType = TEXT("Scalable Font");
            lpelfe->elfLogFont.lfHeight = MulDiv(12, GetDeviceCaps(ppeft->hPrinterDC, LOGPIXELSY), 72);
            lpelfe->elfLogFont.lfWidth = 0;
        }

        // Skip all fonts after this font that are the same scale as the last one.
        // However, let different sizes of 'bitmap' fonts through.
        // This is a cheat that relies on enumeration order.
        // Really, you should keep a 'used' list and compare against the list.
        if (FontType & RASTER_FONTTYPE || !CompareLogFontEx(&ppeft->elf, lpelfe))
        {

            hfont = CreateFontIndirect(&lpelfe->elfLogFont);
            holdfont = (HFONT)SelectObject(ppeft->hPrinterDC, hfont);
            GetTextMetrics(ppeft->hPrinterDC, &tm);

            // If beyond bottom of page, get a new page.
            if (pagecy < ppeft->cury + tm.tmExternalLeading + tm.tmHeight)
            {
                EndPage(ppeft->hPrinterDC);
                StartPage(ppeft->hPrinterDC);
                ppeft->cury = 0;
            }

            // Draw our sample text.
            wsprintf(Buffer, "%s %s [%s]  FontType: %s", lpelfe->elfFullName, pStyle, lpelfe->elfScript, szFontType);
            ppeft->cury += tm.tmExternalLeading;
            TextOut(ppeft->hPrinterDC, ppeft->curx, ppeft->cury, Buffer, lstrlen(Buffer));
            ppeft->cury += tm.tmHeight;

            // Clean up.
            SelectObject(ppeft->hPrinterDC, holdfont);
            DeleteObject(hfont);

            // Make a note of the font that you used so that the next time
            // this callback is called, you can skip different scales of
            // the same font.
            CopyMemory(&ppeft->elf, lpelfe, sizeof(ENUMLOGFONTEX));
        }
    }
    // Otherwise, continue enumeration without doing anything with this
    // particular font.

    return 1;
}

int CALLBACK PrinterDeviceFontFamiliesEnum(
  ENUMLOGFONTEX *lpelfe,    // logical-font data
  NEWTEXTMETRICEX *lpntme,  // physical-font data
  DWORD FontType,           // type of font
  LPARAM lParam             // application-defined data
)
{
    PRINTENUMFONTDATA * ppeft = (PRINTENUMFONTDATA*) lParam;

    ZeroMemory(&ppeft->elf, sizeof(ppeft->elf));

    // Is it a device font?
    // If it is, make sure that it is also not a TrueType font because
    // that is most likely a downloaded font.
    if (FontType & DEVICE_FONTTYPE && !(FontType & (TRUETYPE_FONTTYPE)))
    {

        // Enumerate all of the font instances that are part of this
        // font family.
        return EnumFontFamiliesEx(ppeft->hEnumDC,
            &lpelfe->elfLogFont,
            (FONTENUMPROC)PrinterDeviceFontEnum,
            lParam,
            0);
    }

    // Otherwise, if you are not interested in this particular font, 
    // continue enumeration so that you can find more.
    return 1;
}

BOOL CALLBACK AbortProc(HDC hdc, int iError)
/*
    This minimal AbortProc implementation stops the print
    job when an error occurs.
 */
{
    if (iError)
        return FALSE;
    return TRUE;
}

BOOL PrintDeviceFontList(HDC hPrinterDC)
{
    int ret;
    LOGFONT             lf;     // Describes the start of the font enumeration
    PRINTENUMFONTDATA peft =
    {
        hPrinterDC,             // Device Context on which to print
        hPrinterDC,             // Device Context to enumerate
        0, 0,                   // Current print location
        NULL                    // Last device font that is used to print
    };
    DOCINFO di;                 // Description of the print job

    // Start the print job.
    ZeroMemory(&di, sizeof(di));
    di.cbSize = sizeof(di);
    di.lpszDocName = TEXT("Printer Font List");

    // Set a minimal AbortProc because there should always be one.
    ret = SetAbortProc(hPrinterDC, (ABORTPROC) AbortProc);
    if (ret < 1) return false;

    ret = StartDoc(hPrinterDC, &di);
    if (ret < 1) return false;

    ret = StartPage(hPrinterDC);
    if (ret < 1)
    {
        AbortDoc(hPrinterDC);
        return false;
    }

    // Enumerate everything to start, weed out non-device fonts, 
    // and then print non-device fonts during enumeration.
    ZeroMemory(&lf, sizeof(lf));
    lf.lfCharSet = DEFAULT_CHARSET;

    // Call the enumeration with your callback function that prints
    // the device fonts that it finds.
    ret = EnumFontFamiliesEx(hPrinterDC,
        &lf,
        (FONTENUMPROC)PrinterDeviceFontFamiliesEnum,
        (LPARAM)&peft,
        0);

    // The value 1 is returned by the callback functions to continue
    // the enumeration. When the enumeration completes, EnumFontFamiliesEx
    // returns the last value that the callback returns.
    // Therefore, you succeed if you get 1. Let it print.
    if (ret == 1)
    {
        EndPage(hPrinterDC);
        EndDoc(hPrinterDC);
        return true;
    }

    // Otherwise, exit because you failed somewhere in the process.
    AbortDoc(hPrinterDC);
    return false;
}

함수가 두 번 호출되는 EnumFontFamiliesEx 샘플 코드에서 볼 수 있습니다. 첫 번째 호출은 함수에서 이루어집니다 PrintDeviceFontList . 두 번째 호출은 콜백 함수에 PrinterDeviceFontFamiliesEnum 있습니다.

PrintDeviceFontList 는 최상위 함수입니다. PrintDeviceFontList 는 프린터 디바이스 컨텍스트에서 인쇄 작업을 시작한 다음 에 대한 첫 번째 호출 EnumFontFamiliesEx 을 호출하여 글꼴 열거 프로세스를 시작하여 두 작업을 수행합니다. SDK(Platform Software Development Kit) 설명서에 따르면 구조체의 lfCharSet 멤버를 값 EnumFontFamiliesEx 으로 DEFAULT_CHARSET 설정 LOGFONT 하면 모든 글꼴 패밀리가 열거됩니다. 글꼴 열거가 완료되면 코드는 메서드를 호출 EndDoc 하여 인쇄 작업 관리 작업을 완료합니다.

PrinterDeviceFontFamiliesEnum 콜백 함수는 함수에 의해 각 글꼴 패밀리에 대해 호출됩니다EnumFontFamiliesEx. 해당 콜백 함수에서 코드는 처음에 글꼴 패밀리를 차단하여 매개 변수로 FontType 표시된 디바이스 글꼴만 찾습니다. 또한 해당 글꼴이 다운로드 가능한 글꼴일 가능성이 높기 때문에 로 TrueType 표시된 모든 글꼴을 차단합니다. 디바이스 글꼴로 간주되는 글꼴 패밀리의 EnumFontFamiliesEx 경우 함수가 다시 호출되지만 콜백 함수가 받은 구조체가 전달 ENUMLOGFONTEX 됩니다. 콜백 매개 변수를 두 번째 열거형 함수 호출에 대한 입력 매개 변수로 사용하면 두 번째 열거형이 해당 글꼴 패밀리의 모든 고유 글꼴을 나열합니다.

디바이스 글꼴 선택

프린터 장치 글꼴의 특정 조건을 사용하여 이러한 글꼴을 열거된 다른 글꼴과 구분할 수 있습니다. 특히 콜백 함수의 DWORD 매개 변수에서 FontType 값을 찾 DEVICE_FONTTYPE 습니다. 이 값이 설정된 콜백 함수에 전달되는 거의 모든 글꼴은 프린터 디바이스 컨텍스트에 대한 디바이스 글꼴입니다(Adobe 글꼴 제외).

샘플 코드 PrinterDeviceFontEnum 에서 콜백 함수는 글꼴 패밀리의 각 고유 글꼴에 대한 두 번째 열거형에 의해 호출됩니다. 콜백 함수는 PrinterDeviceFontEnum 다음 세 가지 작업을 수행합니다.

  • 디바이스 글꼴 조건을 다시 사용하여 함수가 디바이스 글꼴로 인식되는 글꼴만 처리하도록 합니다.

  • 다른 글꼴 열거형을 사용하여 글꼴을 검색하여 디바이스 글꼴이 시스템의 화면 디바이스 컨텍스트에서도 사용되는지 확인합니다.

  • 글꼴의 사용을 보여주기 위해 생성되는 인쇄 작업에 글꼴 샘플을 인쇄합니다. 이 콜백 함수는 다음 샘플 코드의 일부인 라는 IsSystemFont함수를 사용합니다.

BOOL CompareLogFontEx(
  CONST ENUMLOGFONTEX * Destination,   // copy destination
  CONST ENUMLOGFONTEX * Source  // memory block
)
/*
    Returns true if the two ENUMLOGFONTEX buffers compare.
    Return false if the two buffers differ in someway as described by the 
    criteria below.
*/
{

    // Compare the string descriptions:
    if (lstrcmpi((LPCTSTR )Destination->elfFullName, (LPCTSTR )Source->elfFullName) != 0)
        return false;
    if (lstrcmpi((LPCTSTR )Destination->elfScript, (LPCTSTR )Source->elfScript) != 0)
        return false;
    if (lstrcmpi((LPCTSTR )Destination->elfStyle, (LPCTSTR )Source->elfStyle) != 0)
        return false;

    // Height and Width are not compared because they will change
    // based upon the device on which the font is enumerated.
    //  LONG lfHeight;
    //  LONG lfWidth;

    // Compare the LOGFONT properties:
    //  LONG lfEscapement;
    if (Destination->elfLogFont.lfEscapement != Source->elfLogFont.lfEscapement) return false;
    //  LONG lfOrientation;
    if (Destination->elfLogFont.lfOrientation != Source->elfLogFont.lfOrientation) return false;
    //  LONG lfWeight;
    if (Destination->elfLogFont.lfWeight != Source->elfLogFont.lfWeight) return false;
    //  BYTE lfItalic;
    if (Destination->elfLogFont.lfItalic != Source->elfLogFont.lfItalic) return false;
    //  BYTE lfUnderline;
    if (Destination->elfLogFont.lfUnderline != Source->elfLogFont.lfUnderline) return false;
    //  BYTE lfStrikeOut;
    if (Destination->elfLogFont.lfStrikeOut != Source->elfLogFont.lfStrikeOut) return false;
    //  BYTE lfCharSet;
    if (Destination->elfLogFont.lfCharSet != Source->elfLogFont.lfCharSet) return false;
    //  BYTE lfOutPrecision;
    if (Destination->elfLogFont.lfOutPrecision != Source->elfLogFont.lfOutPrecision) return false;
    //  BYTE lfClipPrecision;
    if (Destination->elfLogFont.lfClipPrecision != Source->elfLogFont.lfClipPrecision) return false;
    //  BYTE lfQuality;
    if (Destination->elfLogFont.lfQuality != Source->elfLogFont.lfQuality) return false;
    //  BYTE lfPitchAndFamily;
    if (Destination->elfLogFont.lfPitchAndFamily != Source->elfLogFont.lfPitchAndFamily) return false;
    //  TCHAR lfFaceName[LF_FACESIZE];
    if (lstrcmpi((LPCTSTR )Destination->elfLogFont.lfFaceName, (LPCTSTR )Source->elfLogFont.lfFaceName) != 0) return false;

    // Conclusion: the two LOGFONT enumeration buffers are comparable.
    return true;
}

typedef struct structEnumedFont
{
    DWORD FontType;
    ENUMLOGFONTEX * elfx;
} ENUMEDFONT;

int CALLBACK FindSystemFontEnum(
  ENUMLOGFONTEX *lpelfe,    // logical-font data
  NEWTEXTMETRICEX *lpntme,  // physical-font data
  DWORD FontType,           // type of font
  LPARAM lParam             // application-defined data
)
{
    ENUMEDFONT  *   pdf  = (ENUMEDFONT *)lParam;
    ENUMLOGFONTEX * lpelfeSrc = pdf->elfx;

    lpelfe->elfLogFont.lfHeight = lpelfeSrc->elfLogFont.lfHeight;
    lpelfe->elfLogFont.lfWidth = lpelfeSrc->elfLogFont.lfWidth;

if (CompareLogFontEx(lpelfeSrc, lpelfe) && FontType == pdf->FontType)
        return 0;       // System font found. Stop enumeration.
        return 1;
}

BOOL IsSystemFont(ENUMEDFONT *pdf)
/*
    Utility function that takes a font that is enumerated from a printer device
    that is in the pdf parameter and that looks for it on a Screen Device
    Context to conclude that the font passed in that came from the 
    printer is really supplied by the system.
 */
{
    HDC hScreenDC = GetDC(NULL);    // Get the screen device context.

    // If the enumeration stops by returning zero (0),
    // the font was found on the screen device context so it is a
    // system-supplied font.
    BOOL fFound = !EnumFontFamiliesEx(hScreenDC,
        &pdf->elfx->elfLogFont,
        (FONTENUMPROC)FindSystemFontEnum,
        (LPARAM)pdf,
        0);

    // Cleanup
    ReleaseDC(NULL, hScreenDC);
    return fFound;
}

이 함수는 디바이스 글꼴로 표시되지만 실제 디바이스 글꼴이 아닌 글꼴을 검색합니다(이 문서의 정의에 따라). Adobe 글꼴이 Adobe Type Manager 또는 Windows 2000 또는 Windows XP에 있는 네이티브 Adobe 래스터라이저를 통해 시스템에 설치될 때 발생합니다.

이 경우 글꼴은 실제로 프린터에 다운로드되는 시스템 제공 글꼴로, 때로는 TrueType 글꼴에서 발생합니다. 아쉽게도 Windows 98, Windows Millennium Edition(Me), Windows 2000 및 Windows XP에서 사용할 수 있는 플래그는 없습니다. 이 플래그는 시스템에서 제공하는 Adobe 글꼴임을 나타냅니다(플래그가 포함된 TrueType 글꼴과 달리). 구조체의 ntmFlags 멤버에 NEWTEXTMETRIC 표시가 있지만 Windows 2000 이상에서만 사용할 수 있습니다. 따라서 코드는 제거 프로세스에 의존해야 합니다. 화면 디바이스 컨텍스트와 프린터 디바이스 컨텍스트에서 디바이스 글꼴을 제공하면 글꼴이 제거 IsSystemFontdetermines 됩니다.

크기가 조정되는 글꼴의 반복적인 샘플을 방지하기 위해 코드는 후보 글꼴이 이미 사용된 시점도 적어 줍니다. 이 의 특정 구현은 글꼴의 순차적 열거형이 동일한 글꼴이지만 다른 배율로 표시되는 경우를 확인하기 위해 글꼴의 열거 순서를 사용합니다. 다른 눈금에 불과한 글꼴을 제거하려면 코드에서 함수를 CompareLogFontEx 사용합니다.

참고

Windows 운영 체제 프로그래밍 설명서에는 규모에 따라 다른 글꼴 인스턴스가 순차적으로 열거된다는 내용이 명시되어 있지 않습니다. 이 코드 샘플은 열거형이 이런 방식으로 작동하는 것으로 표시되고 인쇄된 페이지의 샘플 줄 수가 감소하는 것이 데모 코드의 중요한 기능이 아니기 때문에 이 기술을 사용합니다. 동일한 글꼴의 다른 배율을 제거하는 데 의존하려면 사용되는 디바이스 글꼴의 데이터 구조를 유지해야 합니다. 그런 다음 프로그램은 해당 데이터 구조에 대해 현재 열거된 글꼴을 검사 합니다.

확장 가능한 글꼴과 비트맵 글꼴 비교

프린터에서 열거할 수 있는 두 가지 유형의 디바이스 글꼴이 있습니다.

  • 비트맵 또는 래스터 글꼴
  • 확장 가능한 글꼴

비트맵 글꼴은 고정 크기의 문자 문자 모양 정의가 있는 글꼴입니다. 확장 가능한 글꼴은 프린터에 수학 기반 정의가 있는 글꼴이므로 어떤 크기로든 그릴 수 있습니다. 즉, 크기가 조정됩니다.

비트맵 글꼴의 전형적인 예는 cpi(인치당 Courier 10자)입니다. 이름에서 알 수 있듯이 이 글꼴은 타자기에서 임팩트 형식 프린터로의 전환에서 보류됩니다. 글꼴의 가장 일반적인 정의가 점 행렬 프린터의 ROM 비트맵 이미지에 있으므로 비트맵 글꼴이라고 합니다.

확장 가능한 프린터 상주 글꼴의 예는 일반적으로 Helvetica 및 Times와 같은 PostScript 글꼴의 표준 집합이 있는 대부분의 PostScript 프린터에서 찾을 수 있습니다.

확장할 수 없는 디바이스 글꼴에는 콜백 함수의 매개 변수에 FontType 설정된 비트가 있습니다. 해당 비트는 SDK의 기호 RASTER_FONTTYPE 로 표시됩니다. 콜백 함수에 FontType 대한 매개 변수에 집합이 RASTER_FONTTYPEbit 없는 경우 글꼴은 확장 가능한 글꼴입니다. 이를 확인하는 방법에 대한 예제는 샘플 코드의 PrinterDeviceFontEnum 콜백 함수를 참조하세요.

디바이스 글꼴 그리기

디바이스 글꼴인 글꼴을 찾은 후 샘플에서는 열거형이 수행된 프린터 디바이스 컨텍스트에서 해당 글꼴을 사용합니다. 디바이스 글꼴은 함수를 사용하여 논리적 설명을 만들어 다른 글꼴과 CreateFontIndirect 매우 유사하게 사용됩니다. 이 함수 호출은 글꼴 열거형 콜백 함수에 전달된 를 전달 LOGFONT 합니다. HFONT 를 만든 후에는 함수 호출을 사용하여 디바이스 컨텍스트로 선택하여 프린터 디바이스 컨텍스트에서 SelectObject 사용됩니다.

디바이스 글꼴에 대한 메트릭은 함수 호출을 GetTextMetrics 통해 가져옵니다. 디바이스 컨텍스트의 기본 매핑 모드인 매핑 모드를 사용하여 MM_TEXT 프린터 디바이스 컨텍스트에서 작동하는 것이 가장 좋습니다. 매핑 모드를 MM_TEXT 사용하는 경우 다른 매핑 모드의 단위 변환 프로세스 중에 발생할 수 있는 수학 오류를 방지할 수 있습니다.

프린터 디바이스 컨텍스트에서 디바이스 글꼴을 사용하는 경우 글꼴 및 문자열에 대한 메트릭을 다른 디바이스 컨텍스트로 전송하지 않도록 주의해야 합니다. 이는 특히 메모리 디바이스 컨텍스트의 경우 그렇습니다. 정의에 따르면 메모리 디바이스 컨텍스트는 인쇄 작업이 아니지만 래스터 그래픽의 임시 메모리 버퍼이므로 디바이스 글꼴을 사용할 수 없습니다.

프린터 장치 글꼴을 사용하는 경우 또 다른 중요한 고려 사항이 있습니다. 인쇄 작업의 What-You-See-Is-What-You-Get 형식 미리 보기를 제공할 수 없습니다. 분명히 프린터 하드웨어에 있는 글꼴은 화면에 그릴 수 없습니다. 인쇄 작업을 미리 볼 수 있는 가장 가까운 방법은 프린터 장치 글꼴의 일반적인 특성을 가진 시스템 제공 글꼴을 찾은 다음, 함수를 사용하여 ExtTextOut 인쇄된 페이지에 문자 문자 모양 배치를 시뮬레이션하여 화면에 해당 글꼴의 문자 모양을 그리는 것입니다.

디바이스 글꼴 사용 문제

디바이스 글꼴을 사용할 때 다음과 같은 문제가 발생할 수 있습니다.

  • 디바이스 글꼴이 있지만 프린터 드라이버에서 열거하지 않습니다.

    프린터 디바이스 컨텍스트에서 사용할 수 있는 글꼴을 열거하여 디바이스 글꼴을 찾을 수 없는 두 가지 이유가 있습니다.

    • 프린터 드라이버는 어떤 이유로 해당 디바이스 글꼴을 제외하도록 작성되었습니다.
    • 프린터 드라이버가 글꼴을 열거하지만 글꼴이 매개 변수에 FontType 디바이스 글꼴로 제대로 표시되지 않습니다.
  • 디바이스 글꼴로 열거되는 시스템 글꼴이 있습니다.

    이 문제는 시스템 제공 글꼴을 프린터에 다운로드할 때 발생합니다.

    TrueType 글꼴에서 이 문제가 발생하면 글꼴 열거형 콜백 함수는 매개 변수에 설정된 및 DEVICE_FONTTYPE 비트와 함께 TRUETYPE_FONTTYPE 호출을 FontType 받습니다. 이러한 비트 조합을 포함하는 글꼴을 포함하지 않음으로써 샘플 코드에서 처리됩니다.

    이 문제는 프린터에 다운로드되는 시스템에 설치된 Adobe PostScript 글꼴에서도 발생합니다. 이러한 글꼴을 다른 디바이스 글꼴과 구별하는 한 가지 방법은 시스템 화면 디바이스 컨텍스트와 프린터 디바이스 컨텍스트 모두에서 해당 글꼴을 찾는 것입니다. 두 장치 컨텍스트에서 동일한 글꼴을 열거할 수 있는 경우 프린터 디바이스 컨텍스트에서 사용할 때 글꼴이 프린터에 다운로드될 수 있습니다.

  • 프린터 드라이버가 여러 확장 가능한 디바이스 글꼴을 열거하지만 크기를 제외하고 동일하게 표시됩니다.

    많은 프린터 드라이버는 크기가 다른 동일한 글꼴의 여러 다른 인스턴스를 제공하여 확장 가능한 글꼴을 열거합니다. 이 작업은 함수를 사용하여 확장 가능한 것으로 추정되는 해당 글꼴의 다양한 인스턴스를 비교하여 샘플 코드에서 CompareLogFontEx 처리됩니다.

    참고

    콜백 함수에 FontType 대한 매개 변수에 집합이 있는 경우 여러 열거형은 RASTER_FONTTYPEbit 각 크기에 대해 확장할 수 없는 글꼴의 특정 인스턴스에 대한 설명을 제공합니다. 각 콜백은 해당 글꼴을 사용할 수 있는 유일한 크기를 열거합니다.

  • 일부 프린터에는 디바이스 글꼴이 없는 것 같습니다.

    이는 사실입니다. 잉크 제트 형식 프린터와 같은 일부 프린터는 디바이스 글꼴을 제공하지 않습니다. 이러한 프린터는 엄격하게 래스터 디바이스이므로 프린터 상주 글꼴 정의가 없습니다.