Utiliser les polices de périphérique d’imprimante

Les polices qui se trouvent dans les imprimantes peuvent parfois être utiles et difficiles à utiliser dans le code du programme d’application. Cet article explique comment déterminer quelles polices d’appareil résident dans l’imprimante peuvent être utilisées dans un contexte de périphérique d’imprimante Win32. L’article décrit également plusieurs problèmes qui peuvent se produire lorsque vous essayez d’utiliser ces polices d’imprimante dans le code de l’application.

Version d’origine du produit : Périphérique d’imprimante Win32
Numéro de la base de connaissances d’origine : 201978

Résumé

Dans la plupart des cas, un développeur de logiciels s’appuie sur le système d’exploitation pour fournir les polices qui seront utilisées pour son dessin. Pour ce faire, vous pouvez sélectionner une police fournie par le système d’exploitation via l’interface de programmation d’application (API) ou via la boîte de dialogue Choisir une police courante. Toutefois, l’application n’est généralement pas concernée par la police particulière utilisée, mais elle répond à certaines exigences et l’utilisateur préfère la police. Ces exigences sont les suivantes :

  • La police doit avoir une certaine taille.
  • La police doit contenir des caractères (également appelés glyphes).
  • La police doit avoir un certain style.

En règle générale, lorsque l’application imprime le document, la police (ou une police qui lui ressemble) est utilisée sur l’imprimante sans aucune action particulière de la part de l’application. Il s’agit généralement du résultat correct pour l’application, ce qui produit de bons résultats imprimés à des vitesses raisonnables.

Toutefois, parfois, un développeur d’applications peut avoir à sélectionner uniquement une police spécifique à partir d’une imprimante cible. Historiquement, cela était nécessaire sur les imprimantes de type impact (par exemple, les imprimantes matricielles à points) pour obtenir une certaine mise en forme ou accélérer l’impression.

Aujourd’hui, la plupart des imprimantes sont fondamentalement conçues comme des dispositifs raster et peuvent dessiner un point (un pixel) sur n’importe quelle partie du papier aussi efficacement que tout un glyphe caractère. Pour la plupart des applications, il n’est pas question de savoir si un glyphe de caractères est dessiné sous forme entière à partir d’une définition de résident d’imprimante ou s’il est dessiné sous la forme d’une collection de pixels fourni par le système d’exploitation. Toutefois, vous pouvez toujours utiliser une police que seule l’imprimante fournit. Par exemple, cela peut se produire parce que la police est unique et n’a pas de substitut similaire dans le système d’exploitation ou peut-être parce que vous souhaitez éviter la surcharge liée au téléchargement d’une définition de police sur l’imprimante.

Polices d’appareil

Pour les besoins de cet article, les polices d’appareil sont toutes les polices dont la définition existe de manière permanente ou temporaire dans la mémoire de l’imprimante. Ces polices d’appareil fournissent une définition de glyphe de caractère qui peut être traitée par caractère par le matériel rastériseur de page de l’imprimante pour encrer la forme sur du papier.

Les polices d’appareil peuvent être classées en trois types de base :

  • Polices d’appareil vraies. Pour les besoins de cet article, il s’agit de polices que seul le matériel de l’imprimante fournit et que vous pouvez utiliser uniquement sur l’imprimante.

  • Substitution de police d’appareil. Polices qui existent dans le système d’exploitation et que le matériel de l’imprimante fournit également. Dans ce cas, le matériel de l’imprimante peut remplacer les polices du système d’exploitation.

  • Polices téléchargeables. Polices fournies par le système d’exploitation, mais dont la définition peut être téléchargée sur l’imprimante et utilisée sur l’imprimante comme si le matériel de l’imprimante fournissait les polices directement.

Polices téléchargeables

Le système d’exploitation fournit des polices téléchargeables, également appelées polices logicielles. Lorsque vous imprimez un document, la définition de la police est fournie dans le cadre du travail d’impression. Lorsque l’imprimante traite le travail d’impression, la définition de police est installée dans la mémoire de l’imprimante afin que la définition de police puisse être manuscrite sur la page imprimée du document.

Certains soutiennent que, étant donné que l’imprimante dessine les glyphes de caractères de la police, ces polices sont des polices d’appareil. Toutefois, lorsqu’une définition de police est téléchargée ou qu’un glyphe est dessiné sur l’imprimante via une image bitmap, seule une certaine surcharge ou une taille de file d’attente de travail d’impression est enregistrée. Ce processus se produit de manière transparente pour l’application afin que la police du système d’exploitation puisse être utilisée sur l’écran et sur l’imprimante. Étant donné que cet article se concentre sur l’utilisation des polices d’appareil que seule l’imprimante fournit, cet article ne décrit pas comment utiliser des polices téléchargeables.

Substitution de police d’appareil

La substitution de police d’appareil se produit lorsqu’il existe deux définitions de police distinctes : une que le système d’exploitation utilise et une autre que l’imprimante utilise. Autrement dit, une application sélectionne et utilise une police dans le système d’exploitation dans un document à l’écran. Lorsque vous imprimez le document, la sortie imprimée est dessinée à l’aide de la police définie de la même façon que celle que l’imprimante fournit. Par conséquent, la police du système d’exploitation a été remplacée sur l’imprimante par la police définie par l’imprimante.

Cela se produit généralement sur les imprimantes PostScript lorsqu’une police Windows TrueType courante est utilisée. Par exemple, la police Arial TrueType est généralement imprimée à l’aide de la définition de police PostScript pour la police Helvetica sur la plupart des appareils PostScript. Il s’agit d’un exemple de substitution à l’aide d’une police similaire dont le nom de police est différent. Dans ce cas, vous pouvez généralement rechercher et utiliser cette définition de police similaire directement, car la définition de police similaire est également exposée en tant que police d’appareil vraie. Ceci est abordé plus loin dans cet article.

La substitution de police d’appareil se produit également lorsque la police de l’imprimante porte le même nom que la police que le système d’exploitation fournit. Cela se produit généralement sur des imprimantes telles que Hewlett-Packard des imprimantes LaserJet. Ces imprimantes ont généralement leurs propres versions des polices principales Windows, telles que Arial et Times New Roman. Bien que ces polices puissent également être trouvées en général en recherchant de vraies polices d’appareil, leur utilisation ne peut parfois pas être garantie, car les pilotes d’imprimante sélectionnent souvent eux-mêmes ou sélectionnent via les paramètres utilisateur s’il faut utiliser la police que le système d’exploitation fournit à la place.

Polices d’appareil vraies

Les polices d’appareil vraies sont celles qui n’ont qu’une définition sur l’imprimante. La seule façon pour une application d’utiliser ces polices consiste pour l’application à identifier spécifiquement la police et à la créer pour l’utiliser dans le contexte du périphérique d’imprimante.

Si vous connaissez suffisamment d’informations sur un appareil, vous pouvez créer une description de police logique dans une LOGFONT structure qui aboutira à la réalisation de la police d’appareil. En particulier, il est important de fournir les informations correctes pour le lfFacename membre, le lfHeight membre et le jeu de caractères de la police. En outre, le lfOutPrecision membre doit contenir un OUT_DEVICE_PRECIS indicateur pour influencer le processus de mappage des polices pour choisir des polices d’appareil au lieu de polices système nommées de manière similaire.

Si la description de la police n’est pas connue, vous pouvez énumérer les polices pour découvrir les polices d’appareil. Pour obtenir la liste des polices d’appareil que l’imprimante prend en charge, utilisez l’une des fonctions d’énumération de police telles que EnumFontFamiliesEx. Le code d’application placé dans la fonction de rappel peut examiner les données qui sont transmises à la fonction de rappel pour déterminer quelles instances de police décrivent une police d’appareil.

Utiliser des polices d’appareil vraies

Le processus d’utilisation d’une police d’appareil dans un contexte d’appareil d’imprimante suit les étapes générales suivantes :

  1. Identifiez les polices d’appareil véritables par l’énumération des polices dans un contexte de périphérique d’imprimante.
  2. Sélectionnez les polices qui sont réservées aux appareils, comme indiqué par les FontType indicateurs et par processus d’élimination.
  3. Utilisez des métriques spécifiques à l’imprimante MM_TEXT en mode de mappage pour placer avec précision le texte dessiné à l’aide de la police de l’appareil.

Énumérer les polices d’un contexte de périphérique d’imprimante

Pour énumérer toutes les polices disponibles dans un contexte d’appareil, vous pouvez utiliser les fonctions de rappel et la EnumFontFamiliesEx fonction à partir de l’interface de programmation d’application (API) Win32. Pour énumérer toutes les polices d’un contexte d’appareil, vous devez appeler EnumFontFamiliesEx deux fois : d’abord pour obtenir la liste des familles de polices, et une deuxième fois pour obtenir toutes les polices distinctes qui se trouvent dans chaque famille de polices.

Pour rechercher toutes les polices d’appareil sur un contexte de périphérique d’imprimante, vous devez énumérer toutes les polices du contexte de périphérique d’imprimante. Lorsque chaque police est passée aux fonctions de rappel, la police est examinée pour déterminer s’il s’agit d’une police d’appareil. Les PrinterDeviceFontEnum fonctions de rappel et PrinterDeviceFontFamiliesEnum dans l’exemple de code suivant effectuent cette opération.

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

Vous pouvez voir dans l’exemple de code où la EnumFontFamiliesEx fonction est appelée deux fois. Le premier appel est effectué dans la PrintDeviceFontList fonction . Le deuxième appel se trouve dans la PrinterDeviceFontFamiliesEnum fonction de rappel.

PrintDeviceFontList est la fonction de niveau supérieur. PrintDeviceFontList effectue deux tâches en démarrant un travail d’impression sur le contexte du périphérique d’imprimante, puis en appelant le premier appel à EnumFontFamiliesEx pour démarrer le processus d’énumération de polices. Selon la documentation du Kit de développement logiciel (SDK) de plateforme, lorsque vous définissez le membre de lfCharSet la LOGFONT structure sur la DEFAULT_CHARSET valeur, EnumFontFamiliesEx énumère toutes les familles de polices. Une fois l’énumération de police terminée, le code termine la tâche de gestion des travaux d’impression en appelant la EndDoc méthode .

La PrinterDeviceFontFamiliesEnum fonction de rappel est appelée pour chaque famille de polices par la EnumFontFamiliesEx fonction . Dans cette fonction de rappel, le code filtre initialement les familles de polices pour rechercher uniquement les polices d’appareil marquées par le FontType paramètre . Il filtre également toutes les polices marquées comme TrueType car ces polices sont susceptibles d’être des polices téléchargeables. Pour les familles de polices qui sont considérées comme des polices d’appareil, la EnumFontFamiliesEx fonction est appelée à nouveau, mais reçoit la ENUMLOGFONTEX structure reçue par la fonction de rappel. L’utilisation du paramètre de rappel comme paramètre d’entrée pour le deuxième appel de fonction d’énumération entraîne la deuxième énumération à répertorier toutes les polices distinctes de cette famille de polices.

Sélectionner des polices d’appareil

Vous pouvez utiliser certains critères des polices de périphérique d’imprimante pour distinguer ces polices des autres polices énumérées. Plus précisément, recherchez la DEVICE_FONTTYPE valeur dans le paramètre DWORD de la FontType fonction de rappel. Presque toutes les polices qui sont transmises à la fonction de rappel avec cette valeur définie sont des polices d’appareil pour le contexte de périphérique d’imprimante (à l’exception des polices Adobe).

Dans l’exemple de code, la PrinterDeviceFontEnum fonction de rappel est appelée par la deuxième énumération pour chaque police distincte de la famille de polices. La PrinterDeviceFontEnum fonction de rappel effectue trois tâches :

  • Utilise à nouveau les critères de police d’appareil pour vous assurer que la fonction traite uniquement les polices reconnues comme polices d’appareil.

  • Recherche la police à l’aide d’une autre énumération de polices pour voir si la police d’appareil est également utilisée dans le contexte de l’appareil d’écran du système.

  • Imprime un exemple de police sur le travail d’impression en cours de création pour illustrer l’utilisation de la police. Cette fonction de rappel utilise une fonction nommée IsSystemFont, qui fait partie de l’exemple de code suivant :

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

Cette fonction détecte quand une police qui est marquée comme police d’appareil mais qui n’est pas une police d’appareil vraie (selon la définition de cet article). Cela se produit lorsque les polices Adobe sont installées dans le système via Adobe Type Manager ou via le rastériseur Adobe natif présent dans Windows 2000 ou Windows XP.

Lorsque cela se produit, la police est en fait une police fournie par le système qui est téléchargée sur l’imprimante, ce qui se produit parfois avec les polices TrueType. Malheureusement, il n’existe aucun indicateur que vous pouvez utiliser dans Windows 98, Windows Millennium Edition (Me), Windows 2000 et Windows XP qui indique que la police est une police Adobe que le système fournit (contrairement aux polices TrueType, qui incluent un indicateur). Il existe une indication dans le membre de ntmFlags la NEWTEXTMETRIC structure, mais elle n’est disponible que dans Windows 2000 et versions ultérieures. Par conséquent, le code doit recourir à un processus d’élimination. La police est supprimée lorsque IsSystemFontdetermines la police de l’appareil est fournie à la fois par le contexte de périphérique d’écran et par le contexte du périphérique d’imprimante.

Pour éviter les exemples répétitieux d’une police qui s’adapte, le code note également lorsqu’une police candidate a déjà été utilisée. L’implémentation spécifique de ceci s’appuie sur l’ordre d’énumération des polices pour voir quand les énumérations séquentielles d’une police sont la même police, mais dans une échelle différente. Pour supprimer les polices qui ne sont qu’une échelle différente, le code utilise la CompareLogFontEx fonction .

Remarque

La documentation relative à la programmation des systèmes d’exploitation Windows n’indique pas que les instances de police qui diffèrent uniquement par l’échelle seront énumérées de manière séquentielle. L’exemple de code utilise cette technique, car l’énumération a été considérée comme fonctionnant de cette façon, et la réduction du nombre de lignes d’exemple sur la page imprimée n’est pas une fonctionnalité critique du code de démonstration. Si vous souhaitez vous appuyer sur l’élimination des différentes échelles de la même police, vous devez conserver une structure de données des polices d’appareil utilisées. Le programme doit ensuite case activée la police actuellement énumérée par rapport à cette structure de données.

Polices scalables et bitmap

Il existe deux types de polices d’appareil qui peuvent être énumérés sur les imprimantes :

  • Polices bitmap ou raster
  • Polices évolutives

Les polices bitmap sont des polices qui ont une définition de glyphe de caractères de taille fixe. Les polices évolutives sont des polices qui ont une définition mathématique dans l’imprimante afin qu’elles puissent être dessinées à n’importe quelle taille. En d’autres termes, leur taille est mise à l’échelle.

L’exemple classique d’une police bitmap est Courier 10 caractères par pouce (cpi). Comme son nom l’indique, cette police est une conservation de la transition des machines à écrire aux imprimantes de type impact. Elle est appelée police bitmap, car la définition la plus courante de la police se trouvait dans une image bitmap ROM d’une imprimante de matrice de points.

Vous trouverez des exemples de polices évolutives résidant dans l’imprimante dans la plupart des imprimantes PostScript où il existe généralement un ensemble standard de polices PostScript telles que Helvetica et Times.

Les polices d’appareil qui ne sont pas évolutives ont un bit défini dans le FontType paramètre de la fonction de rappel. Ce bit est représenté par le symbole RASTER_FONTTYPE dans le Kit de développement logiciel (SDK). Si le FontType paramètre de la fonction de rappel n’a pas la RASTER_FONTTYPEbit valeur définie, la police est une police évolutive. Pour obtenir un exemple montrant comment déterminer cela, consultez la PrinterDeviceFontEnum fonction de rappel de l’exemple de code.

Dessiner les polices d’appareil

Une fois que les polices qui sont des polices d’appareil sont trouvées, l’exemple les utilise dans le contexte de périphérique d’imprimante sur lequel l’énumération a été effectuée. Les polices d’appareil sont utilisées comme les autres polices en créant une description logique avec la CreateFontIndirect fonction . Cet appel de fonction est passé au LOGFONT qui a été passé à la fonction de rappel d’énumération de polices. HFONT Une fois le est créé, il est utilisé dans le contexte du périphérique d’imprimante en le sélectionnant dans le contexte de l’appareil avec l’appel de fonctionSelectObject.

Les métriques de la police de l’appareil sont obtenues via l’appel de GetTextMetrics fonction. Il est préférable d’utiliser les contextes de périphérique d’imprimante à l’aide du MM_TEXT mode de mappage, qui est le mode de mappage par défaut pour un contexte d’appareil. Lorsque vous utilisez le MM_TEXT mode de mappage, vous évitez les erreurs mathématiques qui peuvent se produire pendant le processus de conversion d’unités d’autres modes de mappage.

Lorsque vous utilisez une police d’appareil dans un contexte d’appareil d’imprimante, vous devez veiller à ne pas transporter les métriques de la police et les chaînes vers d’autres contextes d’appareil. Cela est vrai, en particulier pour les contextes des périphériques de mémoire. Par définition, un contexte de périphérique mémoire n’est pas le travail d’impression, mais est une mémoire tampon temporaire de graphiques raster et ne peut donc pas utiliser de police d’appareil.

Il existe une autre considération importante lorsque vous utilisez des polices de périphérique d’imprimante : vous ne pouvez pas fournir un aperçu de type What-You-See-Is-What-You-Get de la tâche d’impression. De toute évidence, les polices qui résident dans le matériel de l’imprimante ne peuvent pas être dessinées sur l’écran. Le plus proche de l’aperçu de la tâche d’impression est de trouver une police fournie par le système qui a les caractéristiques générales d’une police de périphérique d’imprimante, puis de dessiner les glyphes de cette police à l’écran à l’aide de la ExtTextOut fonction pour simuler l’emplacement des glyphes de caractères sur la page imprimée.

Problèmes d’utilisation des polices d’appareil

Vous pouvez rencontrer les problèmes suivants lorsque vous utilisez des polices d’appareil :

  • Il existe une police de périphérique, mais le pilote d’imprimante ne l’énumère pas.

    Il existe deux raisons pour lesquelles vous ne pouvez pas trouver une police d’appareil en énumérant les polices disponibles pour une utilisation sur un contexte de périphérique d’imprimante :

    • Le pilote d’imprimante a été écrit pour exclure cette police de périphérique pour une raison quelconque.
    • Le pilote d’imprimante énumère la police, mais la police n’est pas correctement marquée dans le FontType paramètre comme police de périphérique.
  • Il existe des polices système qui semblent énumérer en tant que polices d’appareil.

    Ce problème se produit lorsqu’une police fournie par le système est téléchargée sur une imprimante.

    Lorsque cela se produit avec les polices TrueType, la fonction de rappel d’énumération de police reçoit un appel avec et TRUETYPE_FONTTYPE les DEVICE_FONTTYPE bits définis sur le FontType paramètre . Cela est géré dans l’exemple de code en n’incluant aucune police contenant ces combinaisons de bits.

    Cela se produit également avec les polices Adobe PostScript installées dans le système et téléchargées sur l’imprimante. Une façon de différencier ces polices des autres polices d’appareil consiste à les rechercher à la fois dans un contexte de périphérique d’écran système et dans le contexte du périphérique d’imprimante. Si la même police peut être énumérée sur les deux contextes d’appareil, la police est probablement téléchargée sur l’imprimante lorsqu’elle est utilisée sur le contexte du périphérique d’imprimante.

  • Mon pilote d’imprimante énumère plusieurs polices d’appareil évolutives, mais elles semblent être identiques, à l’exception de leurs tailles.

    De nombreux pilotes d’imprimante énumèrent une police évolutive en fournissant plusieurs instances différentes de la même police avec des tailles différentes. Cela est géré dans l’exemple de code en comparant les différentes instances de ces polices qui sont supposées être évolutives à l’aide de la CompareLogFontEx fonction .

    Remarque

    Lorsque le FontType paramètre de la fonction de rappel a la RASTER_FONTTYPEbit valeur définie, les énumérations multiples fournissent des descriptions d’instances spécifiques des polices non évolutives pour chaque taille. Chaque rappel énumère les seules tailles dans lesquelles cette police est disponible.

  • Certaines imprimantes ne semblent pas avoir de polices d’appareil.

    C’est vrai. Certaines imprimantes, à savoir les imprimantes de type jet d’encre, ne fournissent pas de polices d’appareil. Ces imprimantes sont strictement des périphériques raster et n’ont donc pas de définitions de polices résidentes dans l’imprimante.