Uso de fuentes de dispositivo de impresora

Las fuentes que están en impresoras a veces pueden ser útiles y difíciles de usar en el código del programa de aplicación. En este artículo se describe cómo determinar qué fuentes de dispositivo residentes en la impresora están disponibles para su uso en un contexto de dispositivo de impresora Win32. En el artículo también se describen varios problemas que pueden producirse al intentar usar esas fuentes de impresora en el código de la aplicación.

Versión original del producto: Dispositivo de impresora Win32
Número de KB original: 201978

Resumen

En la mayoría de los casos, un desarrollador de software se basa en el sistema operativo para proporcionar las fuentes que se usarán para su dibujo. Para ello, puede seleccionar una fuente proporcionada por el sistema operativo a través de la interfaz de programación de aplicaciones (API) o a través del cuadro de diálogo elegir fuente común. Sin embargo, la aplicación normalmente no se preocupa por la fuente determinada que se usa, solo cumple ciertos requisitos y el usuario prefiere la fuente. Entre estos requisitos se incluyen:

  • La fuente debe tener un tamaño determinado.
  • La fuente debe contener caracteres (también conocidos como glifos).
  • La fuente debe tener un estilo determinado.

Normalmente, cuando la aplicación imprime el documento, la fuente (o una fuente similar a él) se usa en la impresora sin ninguna acción concreta de la aplicación. Este es generalmente el resultado correcto para la aplicación, y esto genera buenos resultados impresos a velocidades razonables.

Sin embargo, a veces un desarrollador de aplicaciones puede tener que seleccionar solo una fuente específica de una impresora de destino. Históricamente, esto era necesario en las impresoras de tipo de impacto (por ejemplo, impresoras de matriz de puntos) para obtener cierto formato o para acelerar la impresión.

Hoy en día, la mayoría de las impresoras están diseñadas fundamentalmente como dispositivos ráster y pueden dibujar un punto (un píxel) en cualquier parte del papel de la manera más eficaz que todo un glifo de carácter. Para la mayoría de las aplicaciones, no es un problema si un glifo de caracteres se dibuja como un formulario completo de una definición residente en la impresora o se dibuja como una colección de píxeles que proporciona el sistema operativo. Sin embargo, es posible que quiera usar una fuente que solo proporcione la impresora. Por ejemplo, esto puede ocurrir porque la fuente es única y no tiene un sustituto similar en el sistema operativo o quizás porque quiere evitar la sobrecarga de descargar una definición de fuente en la impresora.

Fuentes del dispositivo

Para los fines de este artículo, las fuentes del dispositivo son cualquier fuente cuya definición existe de forma permanente o transitoria en la memoria de la impresora. Estas fuentes de dispositivo proporcionan una definición de glifo de caracteres que el hardware del rasterizador de páginas de la impresora puede abordar por carácter para aplicar lápiz a la forma en papel.

Las fuentes de dispositivo se pueden clasificar en tres tipos básicos:

  • Fuentes de dispositivo verdaderas. A efectos de este artículo, se trata de fuentes que solo proporciona el hardware de la impresora y que solo se pueden usar en la impresora.

  • Sustitución de fuentes del dispositivo. Fuentes que existen en el sistema operativo y que también proporciona el hardware de la impresora. En este caso, el hardware de la impresora puede sustituir las fuentes del sistema operativo.

  • Fuentes descargables. Fuentes que proporciona el sistema operativo pero cuya definición se puede descargar en la impresora y usarse en la impresora como si el hardware de la impresora proporcionase las fuentes directamente.

Fuentes descargables

El sistema operativo proporciona fuentes descargables, que también se conocen como fuentes temporales. Al imprimir un documento, la definición de la fuente se proporciona como parte del trabajo de impresión. Cuando la impresora procesa el trabajo de impresión, la definición de fuente se instala en la memoria de la impresora para que la definición de fuente se pueda escribir en la página impresa del documento.

Algunos argumentan que, dado que la impresora está dibujando los glifos de caracteres de la fuente, estas fuentes son fuentes de dispositivo. Sin embargo, cuando se descarga una definición de fuente o cuando se dibuja un glifo en la impresora a través de un mapa de bits, solo se guarda algún tamaño de cola de trabajo de impresión o sobrecarga. Este proceso se produce de forma transparente en la aplicación para que la fuente del sistema operativo se pueda usar en la pantalla y en la impresora. Dado que este artículo se centra en cómo usar fuentes de dispositivo que solo proporciona la impresora, en este artículo no se describe cómo usar fuentes descargables.

Sustitución de fuentes de dispositivo

La sustitución de fuentes de dispositivo se produce cuando hay dos definiciones de fuentes distintas: una que usa el sistema operativo y otra que usa la impresora. Es decir, una aplicación selecciona y usa una fuente en el sistema operativo en un documento de la pantalla. Al imprimir el documento, la salida impresa se dibuja mediante la fuente definida de forma similar que proporciona la impresora. Por lo tanto, la fuente del sistema operativo se ha sustituido en la impresora por la fuente definida por la impresora.

Esto suele ocurrir en impresoras PostScript cuando se usa una fuente TrueType común de Windows. Un ejemplo de esto es la fuente TrueType Arial que normalmente se imprime mediante la definición de fuente PostScript para la fuente Helvetica en la mayoría de los dispositivos PostScript. Este es un ejemplo de una sustitución mediante una fuente similar cuyo nombre de fuente es diferente. En este caso, normalmente puede buscar y usar esta definición de fuente similar directamente porque la definición de fuente similar también se expone como una fuente de dispositivo verdadera. Esto se describe más adelante en este artículo.

La sustitución de fuentes del dispositivo también se produce cuando la fuente de la impresora tiene el mismo nombre que la fuente que proporciona el sistema operativo. Esto suele ocurrir en impresoras como Hewlett-Packard impresoras LaserJet. Esas impresoras suelen tener sus propias versiones de las fuentes principales de Windows, como Arial y Times New Roman. Aunque estas fuentes también se pueden encontrar normalmente buscando fuentes de dispositivo verdaderas, su uso a veces no se puede garantizar porque los controladores de impresora suelen seleccionar por sí mismos o seleccionar a través de la configuración del usuario si usar la fuente que proporciona el sistema operativo en su lugar.

Fuentes de dispositivo verdaderas

Las fuentes de dispositivo verdaderas son aquellas que solo tienen una definición en la impresora. La única manera de que una aplicación pueda usar estas fuentes es que la aplicación identifique específicamente la fuente y la cree para usarla en el contexto del dispositivo de impresora.

Si sabe suficiente información sobre un dispositivo, puede crear una descripción de fuente lógica en una LOGFONT estructura que dará lugar a la realización de la fuente del dispositivo. En concreto, es importante proporcionar la información correcta para el lfFacename miembro, el lfHeight miembro y el juego de caracteres de la fuente. Además, el lfOutPrecision miembro debe contener una OUT_DEVICE_PRECIS marca para influir en el proceso de asignación de fuentes para elegir fuentes de dispositivo en lugar de fuentes del sistema con nombre similar.

Si no se conoce la descripción de la fuente, puede enumerar fuentes para detectar fuentes de dispositivo. Para obtener una lista de fuentes de dispositivo compatibles con la impresora, use una de las funciones de enumeración de fuentes, como EnumFontFamiliesEx. El código de aplicación que se coloca en la función de devolución de llamada puede examinar los datos que se entregan a la función de devolución de llamada para determinar qué instancias de fuente describen una fuente de dispositivo.

Uso de fuentes de dispositivo verdaderas

El proceso de usar una fuente de dispositivo en un contexto de dispositivo de impresora sigue estos pasos generales:

  1. Identifique las fuentes de dispositivo verdaderas mediante la enumeración de las fuentes en un contexto de dispositivo de impresora.
  2. Seleccione fuentes que solo sean de dispositivo como se indica en las FontType marcas y en el proceso de eliminación.
  3. Use métricas específicas de la impresora en el MM_TEXT modo de asignación para colocar con precisión el texto que se dibuja mediante la fuente del dispositivo.

Enumeración de las fuentes de un contexto de dispositivo de impresora

Para enumerar todas las fuentes que están disponibles en un contexto de dispositivo, puede usar funciones de devolución de llamada y la EnumFontFamiliesEx función desde la interfaz de programación de aplicaciones (API) de Win32. Para enumerar todas las fuentes de un contexto de dispositivo, debe llamar dos EnumFontFamiliesEx veces: primero para obtener una lista de familias de fuentes y una segunda vez para obtener todas las fuentes distintas que se encuentran en cada familia de fuentes.

Para buscar todas las fuentes de dispositivo en un contexto de dispositivo de impresora, debe enumerar todas las fuentes del contexto del dispositivo de impresora. Cuando cada fuente se pasa a las funciones de devolución de llamada, se examina la fuente para determinar si es una fuente de dispositivo. Las PrinterDeviceFontEnum funciones de devolución de llamada y PrinterDeviceFontFamiliesEnum del código de ejemplo siguiente realizan esta operación.

// 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;
}

Puede ver en el código de ejemplo donde se llama a la EnumFontFamiliesEx función dos veces. La primera llamada se realiza en la PrintDeviceFontList función . La segunda llamada está en la función de devolución de PrinterDeviceFontFamiliesEnum llamada.

PrintDeviceFontList es la función de nivel superior. PrintDeviceFontList realiza dos tareas iniciando un trabajo de impresión en el contexto del dispositivo de impresora y, a continuación, invocando la primera llamada a para EnumFontFamiliesEx iniciar el proceso de enumeración de fuentes. Según la documentación del Kit de desarrollo de software de plataforma (SDK), al establecer el miembro de lfCharSet la LOGFONT estructura en el DEFAULT_CHARSET valor, EnumFontFamiliesEx enumera todas las familias de fuentes. Una vez completada la enumeración de fuentes, el código completa la tarea de administración del trabajo de impresión llamando al EndDoc método .

La PrinterDeviceFontFamiliesEnum función llama a la función de devolución de llamada para cada familia de EnumFontFamiliesEx fuentes. En esa función de devolución de llamada, el código muestra inicialmente las familias de fuentes para buscar solo las fuentes del dispositivo marcadas por el FontType parámetro . También muestra las fuentes marcadas como TrueType porque es probable que esas fuentes sean fuentes descargables. Para las familias de fuentes que se consideran fuentes de dispositivo, se vuelve a llamar a la EnumFontFamiliesEx función, pero se pasa la ENUMLOGFONTEX estructura que recibió la función de devolución de llamada. El uso del parámetro de devolución de llamada como parámetro de entrada a la segunda llamada de función de enumeración hace que la segunda enumeración muestre todas las fuentes distintas de esa familia de fuentes.

Seleccionar fuentes de dispositivo

Puede usar ciertos criterios de fuentes de dispositivo de impresora para distinguir estas fuentes de cualquier otra fuente que se enumere. En concreto, busque el valor en el DEVICE_FONTTYPE parámetro DWORD de la FontType función de devolución de llamada. Casi todas las fuentes que se entregan a la función de devolución de llamada con este valor establecido son fuentes de dispositivo para el contexto del dispositivo de impresora (excepto con fuentes de Adobe).

En el código de ejemplo, la segunda enumeración llama a la PrinterDeviceFontEnum función de devolución de llamada para cada fuente distinta de la familia de fuentes. La PrinterDeviceFontEnum función de devolución de llamada realiza tres tareas:

  • Usa de nuevo los criterios de fuente del dispositivo para asegurarse de que la función solo procesa fuentes reconocidas como fuentes de dispositivo.

  • Busca la fuente mediante otra enumeración de fuentes para ver si la fuente del dispositivo también se usa en el contexto del dispositivo de pantalla del sistema.

  • Imprime un ejemplo de la fuente en el trabajo de impresión que se está creando para mostrar el uso de la fuente. Esta función de devolución de llamada usa una función denominada IsSystemFont, que forma parte del código de ejemplo siguiente:

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;
}

Esta función detecta cuándo una fuente que está marcada como fuente de dispositivo pero no es una fuente de dispositivo verdadera (según la definición de este artículo). Esto ocurre cuando las fuentes de Adobe se instalan en el sistema a través de Adobe Type Manager o a través del rasterizador nativo de Adobe que está presente en Windows 2000 o Windows XP.

Cuando esto ocurre, la fuente es realmente una fuente proporcionada por el sistema que se descarga en la impresora, que a veces se produce con fuentes TrueType. Desafortunadamente, no hay ninguna marca que pueda usar en Windows 98, Windows Millennium Edition (Me), Windows 2000 y Windows XP que indique que la fuente es una fuente de Adobe que proporciona el sistema (a diferencia de las fuentes TrueType, que incluyen una marca). Hay una indicación en el miembro de ntmFlags la NEWTEXTMETRIC estructura, pero esto solo está disponible en Windows 2000 y versiones posteriores. Por lo tanto, el código debe recurrir a un proceso de eliminación. La fuente se quita cuando IsSystemFontdetermines el contexto del dispositivo de pantalla y el contexto del dispositivo de impresora proporcionan la fuente del dispositivo.

Para evitar ejemplos repetitivos de una fuente que se escala, el código también anota cuándo ya se ha usado una fuente candidata. La implementación específica de esto se basa en el orden de enumeración de las fuentes para ver cuándo las enumeraciones secuenciales de una fuente son la misma fuente pero en una escala diferente. Para quitar fuentes que solo son una escala diferente, el código usa la CompareLogFontEx función .

Nota:

La documentación para programar sistemas operativos Windows no indica que las instancias de fuente que difieren solo por escala se enumerarán secuencialmente. El ejemplo de código usa esta técnica porque se ha visto que la enumeración funciona de esta manera y la reducción del número de líneas de ejemplo en la página impresa no es una característica crítica del código de demostración. Si quiere basarse en la eliminación de diferentes escalas de la misma fuente, debe mantener una estructura de datos de las fuentes del dispositivo que se usan. A continuación, el programa debe comprobar la fuente enumerada actualmente en esa estructura de datos.

Fuentes escalables frente a mapas de bits

Hay dos tipos de fuentes de dispositivo que se pueden enumerar en impresoras:

  • Fuentes de mapa de bits o ráster
  • Fuentes escalables

Las fuentes de mapa de bits son fuentes que tienen una definición de glifo de caracteres de un tamaño fijo. Las fuentes escalables son fuentes que tienen una definición basada en matemáticas en la impresora para que se puedan dibujar en cualquier tamaño. En otras palabras, su tamaño se escala.

El ejemplo clásico de una fuente de mapa de bits es Courier de 10 caracteres por pulgada (cpi). Como su nombre indica, esta fuente es un retención de la transición de las máquinas de escribir a las impresoras de tipo de impacto. Se denomina fuente de mapa de bits porque la definición más común de la fuente se encontraba en una imagen de mapa de bits ROM de una impresora de matriz de puntos.

Puede encontrar ejemplos de fuentes escalables y residentes en impresoras en la mayoría de las impresoras PostScript, donde normalmente hay un conjunto estándar de fuentes PostScript, como Helvetica y Times.

Las fuentes de dispositivo que no son escalables tienen un bit que se establece en el FontType parámetro de la función de devolución de llamada. Ese bit se representa mediante el símbolo RASTER_FONTTYPE del SDK. Si el FontType parámetro de la función de devolución de llamada no tiene establecido RASTER_FONTTYPEbit , la fuente es una fuente escalable. Para obtener un ejemplo de cómo determinar esto, vea la PrinterDeviceFontEnum función de devolución de llamada del código de ejemplo.

Dibujar las fuentes del dispositivo

Una vez encontradas las fuentes que son fuentes de dispositivo, el ejemplo las usa en el contexto del dispositivo de impresora en el que se realizó la enumeración. Las fuentes de dispositivo se usan de forma muy similar a otras fuentes mediante la creación de una descripción lógica con la CreateFontIndirect función . Esta llamada a función se pasa a la LOGFONT función de devolución de llamada de enumeración de fuentes. HFONT Una vez creado, se usa en el contexto del dispositivo de impresora seleccionándolo en el contexto del dispositivo con la SelectObject llamada de función.

Las métricas de la fuente del dispositivo se obtienen a través de la GetTextMetrics llamada de función. Es mejor trabajar en contextos de dispositivo de impresora mediante el MM_TEXT modo de asignación, que es el modo de asignación predeterminado para un contexto de dispositivo. Cuando se usa el MM_TEXT modo de asignación, se evitan errores matemáticos que pueden producirse durante el proceso de conversión unitaria de otros modos de asignación.

Al usar una fuente de dispositivo en un contexto de dispositivo de impresora, debe tener cuidado de no transportar las métricas de la fuente y las cadenas a otros contextos de dispositivo. Esto se aplica especialmente a los contextos de dispositivo de memoria. Por definición, un contexto de dispositivo de memoria no es el trabajo de impresión, sino que es un búfer de memoria temporal de gráficos ráster y, por lo tanto, no puede usar una fuente de dispositivo.

Hay otra consideración importante cuando se usan fuentes de dispositivo de impresora: no se puede proporcionar una vista previa de tipo What-You-See-Is-What-You-Get del trabajo de impresión. Claramente, las fuentes que residen en el hardware de la impresora no se pueden dibujar en la pantalla. Lo más cercano que puede llegar a obtener una vista previa del trabajo de impresión es encontrar una fuente proporcionada por el sistema que tenga las características generales de una fuente de dispositivo de impresora y, a continuación, dibujar los glifos de esa fuente en la pantalla mediante la ExtTextOut función para simular la colocación de los glifos de caracteres en la página impresa.

Problemas al usar fuentes de dispositivo

Puede experimentar los siguientes problemas al usar fuentes de dispositivo:

  • Hay una fuente de dispositivo, pero el controlador de impresora no la enumera.

    Hay dos razones por las que no puede encontrar una fuente de dispositivo enumerando las fuentes disponibles para su uso en un contexto de dispositivo de impresora:

    • El controlador de impresora se escribió para excluir esa fuente del dispositivo por algún motivo.
    • El controlador de impresora enumera la fuente, pero la fuente no está marcada correctamente en el FontType parámetro como fuente de dispositivo.
  • Hay fuentes del sistema que parecen enumerarse como fuentes de dispositivo.

    Este problema se produce cuando se descarga una fuente proporcionada por el sistema en una impresora.

    Cuando esto ocurre con fuentes TrueType, la función de devolución de llamada de enumeración de fuentes recibe una llamada con TRUETYPE_FONTTYPE y los DEVICE_FONTTYPE bits establecidos en el FontType parámetro . Esto se controla en el código de ejemplo al no incluir ninguna fuente que contenga estas combinaciones de bits.

    Esto también ocurre con las fuentes de Adobe PostScript instaladas en el sistema que se descargan en la impresora. Una manera de diferenciar estas fuentes de las otras fuentes de dispositivo es buscarlas tanto en un contexto de dispositivo de pantalla del sistema como en el contexto del dispositivo de impresora. Si se puede enumerar la misma fuente en ambos contextos de dispositivo, es probable que la fuente se descargue en la impresora cuando se use en el contexto del dispositivo de impresora.

  • Mi controlador de impresora enumera varias fuentes de dispositivo escalables, pero parecen ser las mismas excepto por sus tamaños.

    Muchos controladores de impresora enumeran una fuente escalable proporcionando varias instancias diferentes de la misma fuente con tamaños diferentes. Esto se controla en el código de ejemplo comparando las distintas instancias de esas fuentes que se supone que son escalables mediante la CompareLogFontEx función .

    Nota:

    Cuando el FontType parámetro de la función de devolución de llamada tiene el RASTER_FONTTYPEbit conjunto, las varias enumeraciones proporcionan descripciones de instancias específicas de las fuentes no escalables para cada tamaño. Cada devolución de llamada enumera los únicos tamaños en los que esa fuente está disponible.

  • Algunas impresoras parecen no tener fuentes de dispositivo.

    Si esto es verdadero: Algunas impresoras, es decir, impresoras de tipo jet de lápiz, no proporcionan fuentes de dispositivo. Estas impresoras son dispositivos estrictamente ráster y, por lo tanto, no tienen definiciones de fuentes residentes en la impresora.