File:  [WindowsNT SDKs] / ntddk / src / print / pscript / fntmanag.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:31:12 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntddk-nov-1993, HEAD
Microsoft Windows NT Build 511 (DDK SDK) 11-01-1993

//--------------------------------------------------------------------------
//
// Module Name:  FNTMANAG.C
//
// Brief Description:  This module contains the PSCRIPT driver's
// DrvFontManagement function and related routines.
//
// Author:  Kent Settle (kentse)
// Created: 07-May-1993
//
// Copyright (c) 1993 Microsoft Corporation
//--------------------------------------------------------------------------

#include "stdlib.h"
#include <string.h>
#include "pscript.h"
#include "enable.h"
#include "winbase.h"

// declarations of external routines.

extern LONG iHipot(LONG, LONG);
extern DWORD PSFIXToBuffer(CHAR *, PS_FIX);

// declarations of routines residing within this module.

BOOL ForceLoadFont(PDEVDATA, FONTOBJ *, DWORD, HGLYPH *);
BOOL GrabFaceName(PDEVDATA, FONTOBJ *, CHAR *, DWORD);
PS_FIX GetPointSize(PDEVDATA, FONTOBJ *, XFORM *);
BOOL DownloadANSIBitmapFont(PDEVDATA, FONTOBJ *, HGLYPH *);
BOOL SendCharBitmap(PDEVDATA, FONTOBJ *, HGLYPH, DWORD, BOOL);

//--------------------------------------------------------------------------
// BOOL DrvFontManagement(pfo, iType, pvIn, cjIn, pvOut, cjOut)
// FONTOBJ    *pfo;
// DWORD       iType;
// PVOID       pvIn;
// DWORD       cjIn;
// PVOID       pvOut;
// DWORD       cjOut;
//
// This routine handles multiple font management related functions,
// depending on iType.
//
// Parameters:
//   pdev
//     Pointer to our DEVDATA structure.
//
// Returns:
//   This routine returns no value.
//
// History:
//   26-Apr-1991     -by-     Kent Settle     (kentse)
//  Wrote it.
//--------------------------------------------------------------------------

ULONG DrvFontManagement(pso, pfo, iType, cjIn, pvIn, cjOut, pvOut)
SURFOBJ    *pso;
FONTOBJ    *pfo;
DWORD       iType;
DWORD       cjIn;
PVOID       pvIn;
DWORD       cjOut;
PVOID       pvOut;
{
    PDEVDATA    pdev;

    // pso may be NULL if QUERYESCSUPPORT.

    if (iType != QUERYESCSUPPORT)
    {
        // get the pointer to our DEVDATA structure and make sure it is ours.

        pdev = (PDEVDATA) pso->dhpdev;

        if (bValidatePDEV(pdev) == FALSE)
        {
            RIP("PSCRIPT!DrvFontManagement: invalid pdev.\n");
            SetLastError(ERROR_INVALID_PARAMETER);
            return(FALSE);
        }
    }

    // handle the different cases.

    switch (iType)
    {
        case QUERYESCSUPPORT:
            // when querying escape support, the function in question is
            // passed in the ULONG passed in pvIn.

            switch (*(PULONG)pvIn)
            {
                case QUERYESCSUPPORT:
                case DOWNLOADFACE:
                case GETFACENAME:
                    return(1);

                default:
                    // return 0 if the escape in question is not supported.

		    return(0);
            }

        case DOWNLOADFACE:
            // call ForceLoadFont to do the work.

            return(ForceLoadFont(pdev, pfo, cjIn, (PHGLYPH)pvIn));

        case GETFACENAME:
            // call GrabFaceName to do the work.

            return(GrabFaceName(pdev, pfo, (CHAR *)pvOut, cjOut));

        default:
            return(FALSE);
    }
    return(TRUE);
}


//--------------------------------------------------------------------
// BOOL ForceLoadFont(pdev, pfo)
// PDEVDATA    pdev;
// FONTOBJ    *pfo;
//
// This routine downloads the specified font to the printer, no
// questions asked.
//
// History:
//   07-May-1993    -by-    Kent Settle     (kentse)
//  Wrote it.
//--------------------------------------------------------------------

BOOL ForceLoadFont(pdev, pfo, cjIn, phglyphs)
PDEVDATA    pdev;
FONTOBJ    *pfo;
DWORD       cjIn;
HGLYPH     *phglyphs;
{
    PNTFM       pntfm;
    BYTE       *pSoftFont;
    BOOL        bDeviceFont;
    XFORM       fontxform;
    PS_FIX      psfxScaleFactor;
    BOOL        bProcSet;

    // make sure we have our hglyph => ANSI translation table.
    // the table consists of 256 HGLYPHS, plus two WORDS at the
    // beginning.  The first WORD states whether to always download
    // the font, or just if it has not yet been done.  The second
    // WORD is simply padding for alignment.

    if (cjIn < (sizeof(HGLYPH) * 257))
    {
        RIP("PSCRIPT!ForceLoadFont: invalid cjIn.\n");
        SetLastError(ERROR_INVALID_PARAMETER);
        return(FALSE);
    }
    // get the point size, and fill in the font xform.

    psfxScaleFactor = GetPointSize(pdev, pfo, &fontxform);

    // is this a device font?

    bDeviceFont = (pfo->flFontType & DEVICE_FONTTYPE);

    // select the proper font name for the new font.  if this is a
    // device font, get the name from the NTFM structure.  if this
    // is a GDI font that we are caching, we will create a name for
    // it at the time we download it to the printer.

    if (bDeviceFont)
    {
        // get the font metrics for the specified font.

        pntfm = pdev->pfmtable[pfo->iFace - 1].pntfm;

// !!! NOTE NOTE the following assumption is invalid.  I need to look at the
// !!! first word of phglyph to decide whether to always download the font or
// !!! only download it if it has not yet been downloaded.

//!!! I am writing this with the assumption, that the application will worry
//!!! about printer memory.  In other words, I will just blindly download
//!!! a font when I am told to, and not worry about killing the printer.
//!!! Is this a valid assumption???

//!!! I am also assuming that I do not have to keep track of which fonts
//!!! have been downloaded.

        // if the font is a softfont, download it.

        if (pfo->iFace > pdev->cDeviceFonts)
        {
            pSoftFont = (BYTE *)pntfm + pntfm->loSoftFont;

            // we need to make sure that our header does not get downloaded
            // by bPSWrite

            // note whether or not the procset has already been sent.

            if (pdev->dwFlags & PDEV_PROCSET)
                bProcSet = TRUE;
            else
            {
                pdev->dwFlags |= PDEV_PROCSET;
                bProcSet = FALSE;
            }


            if (!bPSWrite(pdev, pSoftFont, pntfm->cjSoftFont))
            {
                RIP("PSCRIPT!SelectFont: downloading of softfont failed.\n");
                return(FALSE);
            }

            // if the procset was not sent, then clear the flag.

            if (!bProcSet)
                pdev->dwFlags &= ~PDEV_PROCSET;
        }
    }
    else // must be a GDI font we will be caching.
    {
        // we need to make sure that our header does not get downloaded
        // by DownloadANSIBitmapFont.

        // note whether or not the procset has already been sent.

        if (pdev->dwFlags & PDEV_PROCSET)
            bProcSet = TRUE;
        else
        {
            pdev->dwFlags |= PDEV_PROCSET;
            bProcSet = FALSE;
        }

//!!! the engine is not ready for outline fonts yet!!!  -kentse.
#if 0
        // if this font has not yet been downloaded to the printer,
        // do it now.

        if (pfo->flFontType & TRUETYPE_FONTTYPE)
        {
            // determine the point size.

            ulPointSize = (ETOL(fontxform.eM22 * 72000) /
                          pdev->psdm.dm.dmPrintQuality);

            if (ulPointSize < 10)
                DownloadANSIBitmapFont(pdev, pfo, phglyphs);
            else
                DownloadOutlineFont(pdev, pfo);
        }
        else if (pfo->flFontType & RASTER_FONTTYPE)
            DownloadANSIBitmapFont(pdev, pfo, phglyphs);
#endif
        if ( (pfo->flFontType & TRUETYPE_FONTTYPE) ||
             (pfo->flFontType & RASTER_FONTTYPE) )
            DownloadANSIBitmapFont(pdev, pfo, phglyphs);
        else
        {
            RIP("PSCRIPT!SelectFont: invalid pfo->flFontType.\n");
            return(FALSE);
        }

        // if the procset was not sent, then clear the flag.

        if (!bProcSet)
            pdev->dwFlags &= ~PDEV_PROCSET;
    }

    return(TRUE);
}


//--------------------------------------------------------------------
// BOOL GrabFaceName(pdev, pfo, pbuffer, cb)
// PDEVDATA    pdev;
// FONTOBJ    *pfo;
// CHAR       *pbuffer;
// DWORD       cb;
//
// This routine returns the driver's internal facename (ie the name
// which is sent to the printer) to the caller.  pbuffer, is filled
// in with the face name, being sure to not write more than cb bytes
// to the buffer.
//
// History:
//   07-May-1993    -by-    Kent Settle     (kentse)
//  Wrote it.
//--------------------------------------------------------------------

BOOL GrabFaceName(pdev, pfo, pbuffer, cb)
PDEVDATA    pdev;
FONTOBJ    *pfo;
CHAR       *pbuffer;
DWORD       cb;
{
    PNTFM       pntfm;
    BOOL        bDeviceFont;
    PIFIMETRICS pifi;
    XFORM       fontxform;
    PS_FIX      psfxScaleFactor;
    PWSTR       pwstr;
    DWORD       cTmp;
    CHAR        szFaceName[MAX_STRING];
    PSZ         pszFaceName;

    // get the point size, and fill in the font xform.

    psfxScaleFactor = GetPointSize(pdev, pfo, &fontxform);

    // is this a device font?

    bDeviceFont = (pfo->flFontType & DEVICE_FONTTYPE);

    // select the proper font name for the new font.  if this is a
    // device font, get the name from the NTFM structure.  if this
    // is a GDI font that we are caching, we will create a name for
    // it at the time we download it to the printer.

    if (bDeviceFont)
    {
        // get the font metrics for the specified font.

        pntfm = pdev->pfmtable[pfo->iFace - 1].pntfm;

        // copy the font name to the buffer.

        strncpy(pbuffer, (char *)pntfm + pntfm->loszFontName, cb);
    }
    else // must be a GDI font we will be caching.
    {
        if ( (pfo->flFontType & TRUETYPE_FONTTYPE) ||
             (pfo->flFontType & RASTER_FONTTYPE) )
        {
            // create the ASCII name for this font which will get used
            // to select this font in the printer.

            if (!(pifi = FONTOBJ_pifi(pfo)))
            {
                RIP("PSCRIPT!SelectFont: pifi failed.\n");
                return(FALSE);
            }

            pwstr = (PWSTR)((BYTE *)pifi + pifi->dpwszFaceName);
            cTmp = wcslen(pwstr);

            // get the font name from the UNICODE font name.

            memset(szFaceName, 0, sizeof(szFaceName));
            pszFaceName = szFaceName;

            while (cTmp--)
            {
                *pszFaceName = (CHAR)*pwstr++;

                // replace any spaces in the font name with underscores.

                if (*pszFaceName == ' ')
                    *pszFaceName = '_';

                // replace any parens in the font name with asterisks.

                if ((*pszFaceName == '(') || (*pszFaceName == ')'))
                    *pszFaceName = '*';

                // point to the next character.

                *pszFaceName++;
            }

            // add the point size to the font name, so we can distinguish
            // different point sizes of the same font.

            cTmp = PSFIXToBuffer(pszFaceName, psfxScaleFactor);

            // update the buffer pointer.

            pszFaceName += cTmp;

            // output the NULL terminator.

            *pszFaceName = '\0';

            // copy to the output buffer.

            strncpy(pbuffer, szFaceName, cb);
        }
        else
        {
            RIP("PSCRIPT!GrabFaceName: invalid pfo->flFontType.\n");
            return(FALSE);
        }
    }
}


//--------------------------------------------------------------------
// PS_FIX GetPointSize(pdev, pfo, pxform)
// PDEVDATA    pdev;
// FONTOBJ    *pfo;
// XFORM      *pxform;
//
// This routine returns the point size for the specified font.
//
// History:
//   11-May-1993    -by-    Kent Settle     (kentse)
//  Broke out into a separate routine.
//--------------------------------------------------------------------

PS_FIX GetPointSize(pdev, pfo, pxform)
PDEVDATA    pdev;
FONTOBJ    *pfo;
XFORM      *pxform;
{
    XFORMOBJ   *pxo;
    ULONG       ulComplex;
    BOOL        bDeviceFont;
    POINTFIX    ptfx;
    POINTL      ptl;
    FIX         fxVector;
    IFIMETRICS *pifi;
    PS_FIX      psfxPointSize;

    // get the Notional to Device transform.  this is needed to
    // determine the point size.

    pxo = FONTOBJ_pxoGetXform(pfo);

    if (pxo == NULL)
    {
        RIP("PSCRIPT!GrabFaceName: pxo == NULL.\n");
        return((PS_FIX)-1);
    }

    ulComplex = XFORMOBJ_iGetXform(pxo, pxform);

    bDeviceFont = (pfo->flFontType & DEVICE_FONTTYPE);

    // determine the notional space point size of the new font.

    if (bDeviceFont)
    {
        // PSCRIPT font's em height is hardcoded to be 1000 (see quryfont.c).

        pdev->cgs.fwdEmHeight = ADOBE_FONT_UNITS;
    }
    else
    {
        // If its not a device font, we'll have to call back and ask.

        if (!(pifi = FONTOBJ_pifi(pfo)))
        {
            RIP("PSCRIPT!SelectFont: pifi failed.\n");
            return((PS_FIX)-1);
        }

        pdev->cgs.fwdEmHeight = pifi->fwdUnitsPerEm;
    }

    // apply the notional to device transform.

    ptl.x = 0;
    ptl.y = pdev->cgs.fwdEmHeight;

    XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl, &ptfx);

    // now get the length of the vector.

    fxVector = iHipot(ptfx.x, ptfx.y);

    // make it a PS_FIX 24.8 number.

    fxVector <<= 4;

    psfxPointSize = (PS_FIX)(MulDiv(fxVector, PS_RESOLUTION,
                                   pdev->psdm.dm.dmPrintQuality));

    return(psfxPointSize);
}

//--------------------------------------------------------------------
// BOOL DownloadANSIBitmapFont(pdev, pfo, phglyphs)
// PDEVDATA    pdev;
// FONTOBJ    *pfo;
// HGLYPH     *phglyphs;
//
// This routine downloads the font definition for the given bitmap font,
// if it has not already been done.  The font is downloaded as an
// Adobe Type 3 font.
//
// This routine return TRUE if the font is successfully, or has already
// been, downloaded to the printer.  It returns FALSE if it fails.
//
// History:
//   13-May-1993    -by-    Kent Settle     (kentse)
//  Wrote it.
//--------------------------------------------------------------------

BOOL DownloadANSIBitmapFont(pdev, pfo, phglyphs)
PDEVDATA    pdev;
FONTOBJ    *pfo;
HGLYPH     *phglyphs;
{
    DLFONT     *pDLFont;
    DWORD       i;
    DWORD       cDownloadedFonts;
    DWORD       cTmp;
    HGLYPH     *phg;
    GLYPHDATA  *pglyphdata;
    POINTL      ptlTL, ptlBR, ptl1;
    PIFIMETRICS pifi;
    CHAR        szFaceName[MAX_STRING];
    PSZ         pszFaceName;
    PWSTR       pwstr;
    LONG        EmHeight;
    XFORMOBJ   *pxo;
    POINTFIX    ptfx;
    PS_FIX      psfxPointSize;
    XFORM       fontxform;
    HGLYPH      hgDefault;

    // search through our list of downloaded GDI fonts to see if the
    // current font has already been downloaded to the printer.

    pDLFont = pdev->cgs.pDLFonts;

    cDownloadedFonts = min(pdev->cgs.cDownloadedFonts, pdev->iDLFonts);

    for (i = 0; i < cDownloadedFonts; i++)
    {
        // is this entry the one we are looking for?  simply return if so.

        if (pDLFont->iUniq == pfo->iUniq)
        {
            // update the fontname and size in our current graphics state.

            strcpy(pdev->cgs.szFont, pDLFont->strFont);
            pdev->cgs.lidFont = pDLFont->iUniq;

            return(TRUE);
        }

        pDLFont++;
    }

    // we did not find that this font has been downloaded yet, so we must
    // do it now.

    // if we have reached our downloaded font threshold, then
    // we will surround ever textout call with a save/restore.

    if (cDownloadedFonts >= pdev->iDLFonts)
    {
        ps_save(pdev, FALSE);
        pdev->cgs.dwFlags |= CGS_DLFONTTHRESHOLD;
        cDownloadedFonts = pdev->iDLFonts;
    }

    pDLFont = pdev->cgs.pDLFonts;
    pDLFont += cDownloadedFonts;

    memset(pDLFont, 0, sizeof(DLFONT));

    pDLFont->iFace = pfo->iFace;
    pDLFont->iUniq = pfo->iUniq;

    // if we have made it this far, we should simply be able to
    // download the font now.

    // we will be downloading an Adobe TYPE 3 font.

    // allocate a dictionary for the font.

    PrintString(pdev, "9 dict dup begin\n");

    // set FontType to 3 indicating user defined font.

    PrintString(pdev, "/FontType 3 def\n");

    // get a pointer to our array of HGLYPHS.  remember to skip over the
    // first two WORDS.

    phg = phglyphs + 1;

//!!! for now - assuming first hglyph is the default one.

    hgDefault = *phg;

    // run through the array, looking at the bounding box for each
    // glyph, in order to create the bounding box for the entire
    // font.

    ptlTL.x = ADOBE_FONT_UNITS;
    ptlTL.y = ADOBE_FONT_UNITS;
    ptlBR.x = 0;
    ptlBR.y = 0;

    for (i = 0; i < 256; i++)
    {
        // get the GLYPHDATA structure for each glyph.

        if (!(cTmp = FONTOBJ_cGetGlyphs(pfo, FO_GLYPHBITS, 1, phg, (PVOID *)&pglyphdata)))
        {
            RIP("PSCRIPT!DownloadANSIBitmapFont: cGetGlyphs failed.\n");
            return(FALSE);
        }

        ptlTL.x = min(ptlTL.x, pglyphdata->rclInk.left);
        ptlTL.y = min(ptlTL.y, pglyphdata->rclInk.top);
        ptlBR.x = max(ptlBR.x, pglyphdata->rclInk.right);
        ptlBR.y = max(ptlBR.y, pglyphdata->rclInk.bottom);

        // point to the next glyph handle.

        phg++;
    }

    // get the IFIMETRICS for the font.

    if (!(pifi = FONTOBJ_pifi(pfo)))
    {
        RIP("PSCRIPT!DownloadANSIBitmapFont: pifi failed.\n");
        return(FALSE);
    }

    // get the Notional to Device transform.  this is needed to
    // determine the point size.

    pxo = FONTOBJ_pxoGetXform(pfo);

    if (pxo == NULL)
    {
        RIP("PSCRIPT!DownloadANSIBitmapFont: pxo == NULL.\n");
        return(FALSE);
    }

    // apply the notional to device transform.

    ptl1.x = 0;
    ptl1.y = pifi->fwdUnitsPerEm;

    XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx);

    // now get the length of the vector.

    EmHeight = FXTOL(iHipot(ptfx.x, ptfx.y));

    // we have filled in the GLYPHPOS for each glyph in the font.
    // reset the pointer to the first glyph.

    PrintString(pdev, "/FontMatrix [1 ");
    PrintDecimal(pdev, 1, EmHeight);
    PrintString(pdev, " div 0 0 1 ");
    PrintDecimal(pdev, 1, EmHeight);
    PrintString(pdev, " div 0 0] def\n");

    // define the bounding box for the font, defined in 1 unit
    // character space (since FontMatrix = identity).

    PrintString(pdev, "/FontBBox [");
    PrintDecimal(pdev, 4, ptlTL.x, ptlTL.y, ptlBR.x, ptlBR.y);
    PrintString(pdev, " ] def\n");

    // allocate array for encoding vector, then initialize
    // all characters in encoding vector with '.notdef'.

    PrintString(pdev, "/Encoding 256 array def\n");
    PrintString(pdev, "0 1 255 {Encoding exch /.notdef put} for\n");

    // allocate space to store the HGLYPH<==>character code mapping.

    if (!(pDLFont->phgVector = (HGLYPH *)HeapAlloc(pdev->hheap, 0,
                      sizeof(HGLYPH) * 256)))
    {
        RIP("PSCRIPT!DownloadANSIBitmapFont: HeapAlloc for phgVector failed.\n");
        return(FALSE);
    }

    // reset pointer to our array of HGLYPHS.  remember to skip over the
    // first two WORDS.

    phg = phglyphs + 1;

    // fill in the HGLYPH encoding vector, and output
    // the encoding vector to the printer.  leave the first position for
    // the .notdef character.

    pDLFont->cGlyphs = 256;
    memcpy(pDLFont->phgVector, phg, 256 * sizeof(HGLYPH));

    PrintString(pdev, "Encoding\n");

    for (i = 1; i < 256; i++)
    {
        PrintString(pdev, "dup ");
        PrintDecimal(pdev, 1, i);
        PrintString(pdev, " /c");
        PrintDecimal(pdev, 1, i);
        PrintString(pdev, " put\n");
    }

    // under level 1 of PostScript, the 'BuildChar' procedure is called
    // every time a character from the font is constructed.  under
    // level 2, 'BuildGlyph' is called instead.  therefore, we will
    // define a 'BuildChar' procedure, which basically calls
    // 'BuildGlyph'.  this will provide us support for both level 1
    // and level 2 of PostScript.

    // define the 'BuildGlyph' procedure.  start by getting the
    // character name and the font dictionary from the stack.

    PrintString(pdev, "/BuildGlyph {0 begin /cn exch def /fd exch def\n");

    // retrieve the character information from the CharData (CD)
    // dictionary.

    PrintString(pdev, "/CI fd /CD get cn get def\n");

    // get the width and the bounding box from the CharData.
    // remember to divide the width by 16.

    PrintString(pdev, "/wx CI 0 get def /cbb CI 1 4 getinterval def\n");

    // enable each character to be cached.

    PrintString(pdev, "wx 0 cbb aload pop setcachedevice\n");

    // get the width and height of the bitmap, set invert bool to true
    // specifying reverse image.

    PrintString(pdev, "CI 5 get CI 6 get true\n");

    // insert x and y translation components into general imagemask
    // matrix.

    PrintString(pdev, "[1 0 0 -1 0 0] dup 4 CI 7 get put dup 5 CI 8 get put\n");

    // get hex string bitmap, convert into procedure, then print
    // the bitmap image.

    PrintString(pdev, "CI 9 1 getinterval cvx imagemask end } def\n");

    // create local storage for 'BuildGlyph' procedure.

    PrintString(pdev, "/BuildGlyph load 0 5 dict put\n");

    // the semantics of 'BuildChar' differ from 'BuildGlyph' in the
    // following way:  'BuildChar' is called with the font dictionary
    // and character code on the stack, 'BuildGlyph' is called with
    // the font dictionary and character name on the stack.  the
    // following 'BuildChar' procedure calls 'BuildGlyph', and retains
    // compatiblity with level 1 PostScript.

    PrintString(pdev, "/BuildChar {1 index /Encoding get exch get\n");
    PrintString(pdev, "1 index /BuildGlyph get exec} bind def\n");

    // now create a dictionary containing information on each character.

    PrintString(pdev, "/CD 256 dict def CD begin\n");

    // send out the definition of the default (.notdef) character.

    if (!SendCharBitmap(pdev, pfo, *phg++, 0, TRUE))
    {
        RIP("PSCRIPT!DownloadANSIBitmapFont: SendCharBitmap failed.\n");
        HeapFree(pdev->hheap, 0, (PVOID)pDLFont->phgVector);
        return(FALSE);
    }

    for (i = 1; i < 256; i++)
    {
        // don't send out duplicates of the .notdef definition.

        if (*phg != hgDefault)
        {
            if (!SendCharBitmap(pdev, pfo, *phg, i, FALSE))
            {
                RIP("PSCRIPT!DownloadANSIBitmapFont: SendCharBitmap failed.\n");
                HeapFree(pdev->hheap, 0, (PVOID)pDLFont->phgVector);
                return(FALSE);
            }
        }

        // point to the next HGLYPH.

        phg++;
    }

    // close the definition of the font.

    PrintString(pdev, "end\n");

    // create a unique ID for the font, then name it.

    pwstr = (PWSTR)((BYTE *)pifi + pifi->dpwszFaceName);
    cTmp = wcslen(pwstr);

    // get the font name from the UNICODE font name.

    memset(szFaceName, 0, sizeof(szFaceName));
    pszFaceName = szFaceName;

    while (cTmp--)
    {
        *pszFaceName = (CHAR)*pwstr++;

        // replace any spaces in the font name with underscores.

        if (*pszFaceName == ' ')
            *pszFaceName = '_';

        // replace any parens in the font name with asterisks.

        if ((*pszFaceName == '(') || (*pszFaceName == ')'))
            *pszFaceName = '*';

        // point to the next character.

        *pszFaceName++;
    }

    // add the point size to the font name, so we can distinguish
    // different point sizes of the same font.

    // NOTE  Grab a new point size here, rather than reading if from
    // the CGS.  This is necessary to support DrvDownloadFace.

    psfxPointSize = GetPointSize(pdev, pfo, &fontxform);

    cTmp = PSFIXToBuffer(pszFaceName, psfxPointSize);

    // update the buffer pointer.

    pszFaceName += cTmp;

    // output the NULL terminator.

    *pszFaceName = '\0';

    // output the unique id, which, in a postscript printer, can
    // be in the range from 0 to 16777215.

    PrintString(pdev, "/UniqueID ");
    PrintDecimal(pdev, 1, (pfo->iUniq & 0xFFFFF));

    PrintString(pdev, " def end pop /");
    PrintString(pdev, szFaceName);
    PrintString(pdev, " exch definefont pop\n");

    // update the fontname in our current graphics state.

    strcpy(pdev->cgs.szFont, szFaceName);

    // update information for this downloaded font.

    strcpy(pDLFont->strFont, szFaceName);
    pDLFont->psfxScaleFactor = psfxPointSize;

    // update the downloaded font counter.

    pdev->cgs.cDownloadedFonts++;
}


//--------------------------------------------------------------------
// BOOL SendCharBitmap(pdev, pfo, hglyph, index, bnotdef);
// PDEVDATA    pdev;
// FONTOBJ    *pfo;
// HGLYPH      hglyph;
// DWORD       index;
// BOOL        bnotdef;
//
// This routine downloads the character bitmap definition to the printer.
//
// This routine return TRUE for success, FALSE otherwise.
//
// History:
//   13-May-1993    -by-    Kent Settle     (kentse)
//  Broke out of DownloadANSIBitmapFont.
//--------------------------------------------------------------------

BOOL SendCharBitmap(pdev, pfo, hglyph, index, bnotdef)
PDEVDATA    pdev;
FONTOBJ    *pfo;
HGLYPH      hglyph;
DWORD       index;
BOOL        bnotdef;
{
    DWORD       cTmp;
    GLYPHDATA  *pglyphdata;
    PS_FIX      psfxXtrans, psfxYtrans;
    BYTE       *pjBits;
    DWORD       j;
    LONG        cjWidth;

    // get the GLYPHDATA structure for each glyph.

    if (!(cTmp = FONTOBJ_cGetGlyphs(pfo, FO_GLYPHBITS, 1, &hglyph,
                                    (PVOID *)&pglyphdata)))
    {
        RIP("PSCRIPT!SendCharBitmap: cGetGlyphs failed.\n");
        return(FALSE);
    }

    // the first number in the character description is the width
    // in 1 unit font space.  the next four numbers are the bounding
    // box in 1 unit font space.  the next two numbers are the width
    // and height of the bitmap.  the next two numbers are the x and
    // y translation values for the matrix given to imagemask.
    // this is followed by the bitmap itself.

    // first, output the character name.

    if (bnotdef)
        PrintString(pdev, "/.notdef");
    else
    {
        PrintString(pdev, "/c");
        PrintDecimal(pdev, 1, index);
    }

    // output the character description array.  the width and
    // bounding box need to be normalized to 1 unit font space.

    // the width will be sent to the printer as the actual width
    // multiplied by 16 so as not to lose any precision when
    // normalizing.

    PrintString(pdev, " [");
    PrintPSFIX(pdev, 1, (pglyphdata->fxD << 4));
    PrintString(pdev, " ");
    PrintDecimal(pdev, 4, pglyphdata->rclInk.left,
                 -pglyphdata->rclInk.top, pglyphdata->rclInk.right,
                 -pglyphdata->rclInk.bottom);
    PrintString(pdev, " ");

    // output the width and height of the bitmap itself.

    PrintDecimal(pdev, 2, pglyphdata->gdf.pgb->sizlBitmap.cx,
                 pglyphdata->gdf.pgb->sizlBitmap.cy);
    PrintString(pdev, " ");

    // output the translation values for the transform matrix.
    // the x component is usually the equivalent of the left
    // sidebearing in pixels.  the y component is always the height
    // of the bitmap minus any displacement factor (such as for characters
    // with descenders.  both components have .5 subtracted from the original
    // values to avoid roundoff errors.

    psfxXtrans = ETOPSFX((FLOAT)FXTOLROUND(-pglyphdata->fxA) - 0.5);
    psfxYtrans = ETOPSFX(-(FLOAT)pglyphdata->gdf.pgb->ptlOrigin.y - 0.5);

    PrintPSFIX(pdev, 2, psfxXtrans, psfxYtrans);
    PrintString(pdev, "\n<");

    // now output the bits.  calculate how many bytes each source scanline
    // contains.  remember that the bitmap will be padded to 32bit bounds.

    // protect ourselves.

    if ((pglyphdata->gdf.pgb->sizlBitmap.cx < 1) ||
        (pglyphdata->gdf.pgb->sizlBitmap.cy < 1))
    {
        RIP("PSCRIPT!SendCharBitmap: Invalid glyphdata!!!.\n");
        return(FALSE);
    }

    pjBits = pglyphdata->gdf.pgb->aj;

    for (j = 0; j < (DWORD)pglyphdata->gdf.pgb->sizlBitmap.cy; j++)
    {
        cjWidth = (LONG)(pglyphdata->gdf.pgb->sizlBitmap.cx + 7) >> 3;
        vHexOut(pdev, pjBits, cjWidth);
        pjBits += cjWidth;
    }

    PrintString(pdev, ">]def\n");

    return(TRUE);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.