Annotation of ntddk/src/print/pscript/fntmanag.c, revision 1.1.1.1

1.1       root        1: //--------------------------------------------------------------------------
                      2: //
                      3: // Module Name:  FNTMANAG.C
                      4: //
                      5: // Brief Description:  This module contains the PSCRIPT driver's
                      6: // DrvFontManagement function and related routines.
                      7: //
                      8: // Author:  Kent Settle (kentse)
                      9: // Created: 07-May-1993
                     10: //
                     11: // Copyright (c) 1993 Microsoft Corporation
                     12: //--------------------------------------------------------------------------
                     13: 
                     14: #include "stdlib.h"
                     15: #include <string.h>
                     16: #include "pscript.h"
                     17: #include "enable.h"
                     18: #include "winbase.h"
                     19: 
                     20: // declarations of external routines.
                     21: 
                     22: extern LONG iHipot(LONG, LONG);
                     23: extern DWORD PSFIXToBuffer(CHAR *, PS_FIX);
                     24: 
                     25: // declarations of routines residing within this module.
                     26: 
                     27: BOOL ForceLoadFont(PDEVDATA, FONTOBJ *, DWORD, HGLYPH *);
                     28: BOOL GrabFaceName(PDEVDATA, FONTOBJ *, CHAR *, DWORD);
                     29: PS_FIX GetPointSize(PDEVDATA, FONTOBJ *, XFORM *);
                     30: BOOL DownloadANSIBitmapFont(PDEVDATA, FONTOBJ *, HGLYPH *);
                     31: BOOL SendCharBitmap(PDEVDATA, FONTOBJ *, HGLYPH, DWORD, BOOL);
                     32: 
                     33: //--------------------------------------------------------------------------
                     34: // BOOL DrvFontManagement(pfo, iType, pvIn, cjIn, pvOut, cjOut)
                     35: // FONTOBJ    *pfo;
                     36: // DWORD       iType;
                     37: // PVOID       pvIn;
                     38: // DWORD       cjIn;
                     39: // PVOID       pvOut;
                     40: // DWORD       cjOut;
                     41: //
                     42: // This routine handles multiple font management related functions,
                     43: // depending on iType.
                     44: //
                     45: // Parameters:
                     46: //   pdev
                     47: //     Pointer to our DEVDATA structure.
                     48: //
                     49: // Returns:
                     50: //   This routine returns no value.
                     51: //
                     52: // History:
                     53: //   26-Apr-1991     -by-     Kent Settle     (kentse)
                     54: //  Wrote it.
                     55: //--------------------------------------------------------------------------
                     56: 
                     57: ULONG DrvFontManagement(pso, pfo, iType, cjIn, pvIn, cjOut, pvOut)
                     58: SURFOBJ    *pso;
                     59: FONTOBJ    *pfo;
                     60: DWORD       iType;
                     61: DWORD       cjIn;
                     62: PVOID       pvIn;
                     63: DWORD       cjOut;
                     64: PVOID       pvOut;
                     65: {
                     66:     PDEVDATA    pdev;
                     67: 
                     68:     // pso may be NULL if QUERYESCSUPPORT.
                     69: 
                     70:     if (iType != QUERYESCSUPPORT)
                     71:     {
                     72:         // get the pointer to our DEVDATA structure and make sure it is ours.
                     73: 
                     74:         pdev = (PDEVDATA) pso->dhpdev;
                     75: 
                     76:         if (bValidatePDEV(pdev) == FALSE)
                     77:         {
                     78:             RIP("PSCRIPT!DrvFontManagement: invalid pdev.\n");
                     79:             SetLastError(ERROR_INVALID_PARAMETER);
                     80:             return(FALSE);
                     81:         }
                     82:     }
                     83: 
                     84:     // handle the different cases.
                     85: 
                     86:     switch (iType)
                     87:     {
                     88:         case QUERYESCSUPPORT:
                     89:             // when querying escape support, the function in question is
                     90:             // passed in the ULONG passed in pvIn.
                     91: 
                     92:             switch (*(PULONG)pvIn)
                     93:             {
                     94:                 case QUERYESCSUPPORT:
                     95:                 case DOWNLOADFACE:
                     96:                 case GETFACENAME:
                     97:                     return(1);
                     98: 
                     99:                 default:
                    100:                     // return 0 if the escape in question is not supported.
                    101: 
                    102:                    return(0);
                    103:             }
                    104: 
                    105:         case DOWNLOADFACE:
                    106:             // call ForceLoadFont to do the work.
                    107: 
                    108:             return(ForceLoadFont(pdev, pfo, cjIn, (PHGLYPH)pvIn));
                    109: 
                    110:         case GETFACENAME:
                    111:             // call GrabFaceName to do the work.
                    112: 
                    113:             return(GrabFaceName(pdev, pfo, (CHAR *)pvOut, cjOut));
                    114: 
                    115:         default:
                    116:             return(FALSE);
                    117:     }
                    118:     return(TRUE);
                    119: }
                    120: 
                    121: 
                    122: //--------------------------------------------------------------------
                    123: // BOOL ForceLoadFont(pdev, pfo)
                    124: // PDEVDATA    pdev;
                    125: // FONTOBJ    *pfo;
                    126: //
                    127: // This routine downloads the specified font to the printer, no
                    128: // questions asked.
                    129: //
                    130: // History:
                    131: //   07-May-1993    -by-    Kent Settle     (kentse)
                    132: //  Wrote it.
                    133: //--------------------------------------------------------------------
                    134: 
                    135: BOOL ForceLoadFont(pdev, pfo, cjIn, phglyphs)
                    136: PDEVDATA    pdev;
                    137: FONTOBJ    *pfo;
                    138: DWORD       cjIn;
                    139: HGLYPH     *phglyphs;
                    140: {
                    141:     PNTFM       pntfm;
                    142:     BYTE       *pSoftFont;
                    143:     BOOL        bDeviceFont;
                    144:     XFORM       fontxform;
                    145:     PS_FIX      psfxScaleFactor;
                    146:     BOOL        bProcSet;
                    147: 
                    148:     // make sure we have our hglyph => ANSI translation table.
                    149:     // the table consists of 256 HGLYPHS, plus two WORDS at the
                    150:     // beginning.  The first WORD states whether to always download
                    151:     // the font, or just if it has not yet been done.  The second
                    152:     // WORD is simply padding for alignment.
                    153: 
                    154:     if (cjIn < (sizeof(HGLYPH) * 257))
                    155:     {
                    156:         RIP("PSCRIPT!ForceLoadFont: invalid cjIn.\n");
                    157:         SetLastError(ERROR_INVALID_PARAMETER);
                    158:         return(FALSE);
                    159:     }
                    160:     // get the point size, and fill in the font xform.
                    161: 
                    162:     psfxScaleFactor = GetPointSize(pdev, pfo, &fontxform);
                    163: 
                    164:     // is this a device font?
                    165: 
                    166:     bDeviceFont = (pfo->flFontType & DEVICE_FONTTYPE);
                    167: 
                    168:     // select the proper font name for the new font.  if this is a
                    169:     // device font, get the name from the NTFM structure.  if this
                    170:     // is a GDI font that we are caching, we will create a name for
                    171:     // it at the time we download it to the printer.
                    172: 
                    173:     if (bDeviceFont)
                    174:     {
                    175:         // get the font metrics for the specified font.
                    176: 
                    177:         pntfm = pdev->pfmtable[pfo->iFace - 1].pntfm;
                    178: 
                    179: // !!! NOTE NOTE the following assumption is invalid.  I need to look at the
                    180: // !!! first word of phglyph to decide whether to always download the font or
                    181: // !!! only download it if it has not yet been downloaded.
                    182: 
                    183: //!!! I am writing this with the assumption, that the application will worry
                    184: //!!! about printer memory.  In other words, I will just blindly download
                    185: //!!! a font when I am told to, and not worry about killing the printer.
                    186: //!!! Is this a valid assumption???
                    187: 
                    188: //!!! I am also assuming that I do not have to keep track of which fonts
                    189: //!!! have been downloaded.
                    190: 
                    191:         // if the font is a softfont, download it.
                    192: 
                    193:         if (pfo->iFace > pdev->cDeviceFonts)
                    194:         {
                    195:             pSoftFont = (BYTE *)pntfm + pntfm->loSoftFont;
                    196: 
                    197:             // we need to make sure that our header does not get downloaded
                    198:             // by bPSWrite
                    199: 
                    200:             // note whether or not the procset has already been sent.
                    201: 
                    202:             if (pdev->dwFlags & PDEV_PROCSET)
                    203:                 bProcSet = TRUE;
                    204:             else
                    205:             {
                    206:                 pdev->dwFlags |= PDEV_PROCSET;
                    207:                 bProcSet = FALSE;
                    208:             }
                    209: 
                    210: 
                    211:             if (!bPSWrite(pdev, pSoftFont, pntfm->cjSoftFont))
                    212:             {
                    213:                 RIP("PSCRIPT!SelectFont: downloading of softfont failed.\n");
                    214:                 return(FALSE);
                    215:             }
                    216: 
                    217:             // if the procset was not sent, then clear the flag.
                    218: 
                    219:             if (!bProcSet)
                    220:                 pdev->dwFlags &= ~PDEV_PROCSET;
                    221:         }
                    222:     }
                    223:     else // must be a GDI font we will be caching.
                    224:     {
                    225:         // we need to make sure that our header does not get downloaded
                    226:         // by DownloadANSIBitmapFont.
                    227: 
                    228:         // note whether or not the procset has already been sent.
                    229: 
                    230:         if (pdev->dwFlags & PDEV_PROCSET)
                    231:             bProcSet = TRUE;
                    232:         else
                    233:         {
                    234:             pdev->dwFlags |= PDEV_PROCSET;
                    235:             bProcSet = FALSE;
                    236:         }
                    237: 
                    238: //!!! the engine is not ready for outline fonts yet!!!  -kentse.
                    239: #if 0
                    240:         // if this font has not yet been downloaded to the printer,
                    241:         // do it now.
                    242: 
                    243:         if (pfo->flFontType & TRUETYPE_FONTTYPE)
                    244:         {
                    245:             // determine the point size.
                    246: 
                    247:             ulPointSize = (ETOL(fontxform.eM22 * 72000) /
                    248:                           pdev->psdm.dm.dmPrintQuality);
                    249: 
                    250:             if (ulPointSize < 10)
                    251:                 DownloadANSIBitmapFont(pdev, pfo, phglyphs);
                    252:             else
                    253:                 DownloadOutlineFont(pdev, pfo);
                    254:         }
                    255:         else if (pfo->flFontType & RASTER_FONTTYPE)
                    256:             DownloadANSIBitmapFont(pdev, pfo, phglyphs);
                    257: #endif
                    258:         if ( (pfo->flFontType & TRUETYPE_FONTTYPE) ||
                    259:              (pfo->flFontType & RASTER_FONTTYPE) )
                    260:             DownloadANSIBitmapFont(pdev, pfo, phglyphs);
                    261:         else
                    262:         {
                    263:             RIP("PSCRIPT!SelectFont: invalid pfo->flFontType.\n");
                    264:             return(FALSE);
                    265:         }
                    266: 
                    267:         // if the procset was not sent, then clear the flag.
                    268: 
                    269:         if (!bProcSet)
                    270:             pdev->dwFlags &= ~PDEV_PROCSET;
                    271:     }
                    272: 
                    273:     return(TRUE);
                    274: }
                    275: 
                    276: 
                    277: //--------------------------------------------------------------------
                    278: // BOOL GrabFaceName(pdev, pfo, pbuffer, cb)
                    279: // PDEVDATA    pdev;
                    280: // FONTOBJ    *pfo;
                    281: // CHAR       *pbuffer;
                    282: // DWORD       cb;
                    283: //
                    284: // This routine returns the driver's internal facename (ie the name
                    285: // which is sent to the printer) to the caller.  pbuffer, is filled
                    286: // in with the face name, being sure to not write more than cb bytes
                    287: // to the buffer.
                    288: //
                    289: // History:
                    290: //   07-May-1993    -by-    Kent Settle     (kentse)
                    291: //  Wrote it.
                    292: //--------------------------------------------------------------------
                    293: 
                    294: BOOL GrabFaceName(pdev, pfo, pbuffer, cb)
                    295: PDEVDATA    pdev;
                    296: FONTOBJ    *pfo;
                    297: CHAR       *pbuffer;
                    298: DWORD       cb;
                    299: {
                    300:     PNTFM       pntfm;
                    301:     BOOL        bDeviceFont;
                    302:     PIFIMETRICS pifi;
                    303:     XFORM       fontxform;
                    304:     PS_FIX      psfxScaleFactor;
                    305:     PWSTR       pwstr;
                    306:     DWORD       cTmp;
                    307:     CHAR        szFaceName[MAX_STRING];
                    308:     PSZ         pszFaceName;
                    309: 
                    310:     // get the point size, and fill in the font xform.
                    311: 
                    312:     psfxScaleFactor = GetPointSize(pdev, pfo, &fontxform);
                    313: 
                    314:     // is this a device font?
                    315: 
                    316:     bDeviceFont = (pfo->flFontType & DEVICE_FONTTYPE);
                    317: 
                    318:     // select the proper font name for the new font.  if this is a
                    319:     // device font, get the name from the NTFM structure.  if this
                    320:     // is a GDI font that we are caching, we will create a name for
                    321:     // it at the time we download it to the printer.
                    322: 
                    323:     if (bDeviceFont)
                    324:     {
                    325:         // get the font metrics for the specified font.
                    326: 
                    327:         pntfm = pdev->pfmtable[pfo->iFace - 1].pntfm;
                    328: 
                    329:         // copy the font name to the buffer.
                    330: 
                    331:         strncpy(pbuffer, (char *)pntfm + pntfm->loszFontName, cb);
                    332:     }
                    333:     else // must be a GDI font we will be caching.
                    334:     {
                    335:         if ( (pfo->flFontType & TRUETYPE_FONTTYPE) ||
                    336:              (pfo->flFontType & RASTER_FONTTYPE) )
                    337:         {
                    338:             // create the ASCII name for this font which will get used
                    339:             // to select this font in the printer.
                    340: 
                    341:             if (!(pifi = FONTOBJ_pifi(pfo)))
                    342:             {
                    343:                 RIP("PSCRIPT!SelectFont: pifi failed.\n");
                    344:                 return(FALSE);
                    345:             }
                    346: 
                    347:             pwstr = (PWSTR)((BYTE *)pifi + pifi->dpwszFaceName);
                    348:             cTmp = wcslen(pwstr);
                    349: 
                    350:             // get the font name from the UNICODE font name.
                    351: 
                    352:             memset(szFaceName, 0, sizeof(szFaceName));
                    353:             pszFaceName = szFaceName;
                    354: 
                    355:             while (cTmp--)
                    356:             {
                    357:                 *pszFaceName = (CHAR)*pwstr++;
                    358: 
                    359:                 // replace any spaces in the font name with underscores.
                    360: 
                    361:                 if (*pszFaceName == ' ')
                    362:                     *pszFaceName = '_';
                    363: 
                    364:                 // replace any parens in the font name with asterisks.
                    365: 
                    366:                 if ((*pszFaceName == '(') || (*pszFaceName == ')'))
                    367:                     *pszFaceName = '*';
                    368: 
                    369:                 // point to the next character.
                    370: 
                    371:                 *pszFaceName++;
                    372:             }
                    373: 
                    374:             // add the point size to the font name, so we can distinguish
                    375:             // different point sizes of the same font.
                    376: 
                    377:             cTmp = PSFIXToBuffer(pszFaceName, psfxScaleFactor);
                    378: 
                    379:             // update the buffer pointer.
                    380: 
                    381:             pszFaceName += cTmp;
                    382: 
                    383:             // output the NULL terminator.
                    384: 
                    385:             *pszFaceName = '\0';
                    386: 
                    387:             // copy to the output buffer.
                    388: 
                    389:             strncpy(pbuffer, szFaceName, cb);
                    390:         }
                    391:         else
                    392:         {
                    393:             RIP("PSCRIPT!GrabFaceName: invalid pfo->flFontType.\n");
                    394:             return(FALSE);
                    395:         }
                    396:     }
                    397: }
                    398: 
                    399: 
                    400: //--------------------------------------------------------------------
                    401: // PS_FIX GetPointSize(pdev, pfo, pxform)
                    402: // PDEVDATA    pdev;
                    403: // FONTOBJ    *pfo;
                    404: // XFORM      *pxform;
                    405: //
                    406: // This routine returns the point size for the specified font.
                    407: //
                    408: // History:
                    409: //   11-May-1993    -by-    Kent Settle     (kentse)
                    410: //  Broke out into a separate routine.
                    411: //--------------------------------------------------------------------
                    412: 
                    413: PS_FIX GetPointSize(pdev, pfo, pxform)
                    414: PDEVDATA    pdev;
                    415: FONTOBJ    *pfo;
                    416: XFORM      *pxform;
                    417: {
                    418:     XFORMOBJ   *pxo;
                    419:     ULONG       ulComplex;
                    420:     BOOL        bDeviceFont;
                    421:     POINTFIX    ptfx;
                    422:     POINTL      ptl;
                    423:     FIX         fxVector;
                    424:     IFIMETRICS *pifi;
                    425:     PS_FIX      psfxPointSize;
                    426: 
                    427:     // get the Notional to Device transform.  this is needed to
                    428:     // determine the point size.
                    429: 
                    430:     pxo = FONTOBJ_pxoGetXform(pfo);
                    431: 
                    432:     if (pxo == NULL)
                    433:     {
                    434:         RIP("PSCRIPT!GrabFaceName: pxo == NULL.\n");
                    435:         return((PS_FIX)-1);
                    436:     }
                    437: 
                    438:     ulComplex = XFORMOBJ_iGetXform(pxo, pxform);
                    439: 
                    440:     bDeviceFont = (pfo->flFontType & DEVICE_FONTTYPE);
                    441: 
                    442:     // determine the notional space point size of the new font.
                    443: 
                    444:     if (bDeviceFont)
                    445:     {
                    446:         // PSCRIPT font's em height is hardcoded to be 1000 (see quryfont.c).
                    447: 
                    448:         pdev->cgs.fwdEmHeight = ADOBE_FONT_UNITS;
                    449:     }
                    450:     else
                    451:     {
                    452:         // If its not a device font, we'll have to call back and ask.
                    453: 
                    454:         if (!(pifi = FONTOBJ_pifi(pfo)))
                    455:         {
                    456:             RIP("PSCRIPT!SelectFont: pifi failed.\n");
                    457:             return((PS_FIX)-1);
                    458:         }
                    459: 
                    460:         pdev->cgs.fwdEmHeight = pifi->fwdUnitsPerEm;
                    461:     }
                    462: 
                    463:     // apply the notional to device transform.
                    464: 
                    465:     ptl.x = 0;
                    466:     ptl.y = pdev->cgs.fwdEmHeight;
                    467: 
                    468:     XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl, &ptfx);
                    469: 
                    470:     // now get the length of the vector.
                    471: 
                    472:     fxVector = iHipot(ptfx.x, ptfx.y);
                    473: 
                    474:     // make it a PS_FIX 24.8 number.
                    475: 
                    476:     fxVector <<= 4;
                    477: 
                    478:     psfxPointSize = (PS_FIX)(MulDiv(fxVector, PS_RESOLUTION,
                    479:                                    pdev->psdm.dm.dmPrintQuality));
                    480: 
                    481:     return(psfxPointSize);
                    482: }
                    483: 
                    484: //--------------------------------------------------------------------
                    485: // BOOL DownloadANSIBitmapFont(pdev, pfo, phglyphs)
                    486: // PDEVDATA    pdev;
                    487: // FONTOBJ    *pfo;
                    488: // HGLYPH     *phglyphs;
                    489: //
                    490: // This routine downloads the font definition for the given bitmap font,
                    491: // if it has not already been done.  The font is downloaded as an
                    492: // Adobe Type 3 font.
                    493: //
                    494: // This routine return TRUE if the font is successfully, or has already
                    495: // been, downloaded to the printer.  It returns FALSE if it fails.
                    496: //
                    497: // History:
                    498: //   13-May-1993    -by-    Kent Settle     (kentse)
                    499: //  Wrote it.
                    500: //--------------------------------------------------------------------
                    501: 
                    502: BOOL DownloadANSIBitmapFont(pdev, pfo, phglyphs)
                    503: PDEVDATA    pdev;
                    504: FONTOBJ    *pfo;
                    505: HGLYPH     *phglyphs;
                    506: {
                    507:     DLFONT     *pDLFont;
                    508:     DWORD       i;
                    509:     DWORD       cDownloadedFonts;
                    510:     DWORD       cTmp;
                    511:     HGLYPH     *phg;
                    512:     GLYPHDATA  *pglyphdata;
                    513:     POINTL      ptlTL, ptlBR, ptl1;
                    514:     PIFIMETRICS pifi;
                    515:     CHAR        szFaceName[MAX_STRING];
                    516:     PSZ         pszFaceName;
                    517:     PWSTR       pwstr;
                    518:     LONG        EmHeight;
                    519:     XFORMOBJ   *pxo;
                    520:     POINTFIX    ptfx;
                    521:     PS_FIX      psfxPointSize;
                    522:     XFORM       fontxform;
                    523:     HGLYPH      hgDefault;
                    524: 
                    525:     // search through our list of downloaded GDI fonts to see if the
                    526:     // current font has already been downloaded to the printer.
                    527: 
                    528:     pDLFont = pdev->cgs.pDLFonts;
                    529: 
                    530:     cDownloadedFonts = min(pdev->cgs.cDownloadedFonts, pdev->iDLFonts);
                    531: 
                    532:     for (i = 0; i < cDownloadedFonts; i++)
                    533:     {
                    534:         // is this entry the one we are looking for?  simply return if so.
                    535: 
                    536:         if (pDLFont->iUniq == pfo->iUniq)
                    537:         {
                    538:             // update the fontname and size in our current graphics state.
                    539: 
                    540:             strcpy(pdev->cgs.szFont, pDLFont->strFont);
                    541:             pdev->cgs.lidFont = pDLFont->iUniq;
                    542: 
                    543:             return(TRUE);
                    544:         }
                    545: 
                    546:         pDLFont++;
                    547:     }
                    548: 
                    549:     // we did not find that this font has been downloaded yet, so we must
                    550:     // do it now.
                    551: 
                    552:     // if we have reached our downloaded font threshold, then
                    553:     // we will surround ever textout call with a save/restore.
                    554: 
                    555:     if (cDownloadedFonts >= pdev->iDLFonts)
                    556:     {
                    557:         ps_save(pdev, FALSE);
                    558:         pdev->cgs.dwFlags |= CGS_DLFONTTHRESHOLD;
                    559:         cDownloadedFonts = pdev->iDLFonts;
                    560:     }
                    561: 
                    562:     pDLFont = pdev->cgs.pDLFonts;
                    563:     pDLFont += cDownloadedFonts;
                    564: 
                    565:     memset(pDLFont, 0, sizeof(DLFONT));
                    566: 
                    567:     pDLFont->iFace = pfo->iFace;
                    568:     pDLFont->iUniq = pfo->iUniq;
                    569: 
                    570:     // if we have made it this far, we should simply be able to
                    571:     // download the font now.
                    572: 
                    573:     // we will be downloading an Adobe TYPE 3 font.
                    574: 
                    575:     // allocate a dictionary for the font.
                    576: 
                    577:     PrintString(pdev, "9 dict dup begin\n");
                    578: 
                    579:     // set FontType to 3 indicating user defined font.
                    580: 
                    581:     PrintString(pdev, "/FontType 3 def\n");
                    582: 
                    583:     // get a pointer to our array of HGLYPHS.  remember to skip over the
                    584:     // first two WORDS.
                    585: 
                    586:     phg = phglyphs + 1;
                    587: 
                    588: //!!! for now - assuming first hglyph is the default one.
                    589: 
                    590:     hgDefault = *phg;
                    591: 
                    592:     // run through the array, looking at the bounding box for each
                    593:     // glyph, in order to create the bounding box for the entire
                    594:     // font.
                    595: 
                    596:     ptlTL.x = ADOBE_FONT_UNITS;
                    597:     ptlTL.y = ADOBE_FONT_UNITS;
                    598:     ptlBR.x = 0;
                    599:     ptlBR.y = 0;
                    600: 
                    601:     for (i = 0; i < 256; i++)
                    602:     {
                    603:         // get the GLYPHDATA structure for each glyph.
                    604: 
                    605:         if (!(cTmp = FONTOBJ_cGetGlyphs(pfo, FO_GLYPHBITS, 1, phg, (PVOID *)&pglyphdata)))
                    606:         {
                    607:             RIP("PSCRIPT!DownloadANSIBitmapFont: cGetGlyphs failed.\n");
                    608:             return(FALSE);
                    609:         }
                    610: 
                    611:         ptlTL.x = min(ptlTL.x, pglyphdata->rclInk.left);
                    612:         ptlTL.y = min(ptlTL.y, pglyphdata->rclInk.top);
                    613:         ptlBR.x = max(ptlBR.x, pglyphdata->rclInk.right);
                    614:         ptlBR.y = max(ptlBR.y, pglyphdata->rclInk.bottom);
                    615: 
                    616:         // point to the next glyph handle.
                    617: 
                    618:         phg++;
                    619:     }
                    620: 
                    621:     // get the IFIMETRICS for the font.
                    622: 
                    623:     if (!(pifi = FONTOBJ_pifi(pfo)))
                    624:     {
                    625:         RIP("PSCRIPT!DownloadANSIBitmapFont: pifi failed.\n");
                    626:         return(FALSE);
                    627:     }
                    628: 
                    629:     // get the Notional to Device transform.  this is needed to
                    630:     // determine the point size.
                    631: 
                    632:     pxo = FONTOBJ_pxoGetXform(pfo);
                    633: 
                    634:     if (pxo == NULL)
                    635:     {
                    636:         RIP("PSCRIPT!DownloadANSIBitmapFont: pxo == NULL.\n");
                    637:         return(FALSE);
                    638:     }
                    639: 
                    640:     // apply the notional to device transform.
                    641: 
                    642:     ptl1.x = 0;
                    643:     ptl1.y = pifi->fwdUnitsPerEm;
                    644: 
                    645:     XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx);
                    646: 
                    647:     // now get the length of the vector.
                    648: 
                    649:     EmHeight = FXTOL(iHipot(ptfx.x, ptfx.y));
                    650: 
                    651:     // we have filled in the GLYPHPOS for each glyph in the font.
                    652:     // reset the pointer to the first glyph.
                    653: 
                    654:     PrintString(pdev, "/FontMatrix [1 ");
                    655:     PrintDecimal(pdev, 1, EmHeight);
                    656:     PrintString(pdev, " div 0 0 1 ");
                    657:     PrintDecimal(pdev, 1, EmHeight);
                    658:     PrintString(pdev, " div 0 0] def\n");
                    659: 
                    660:     // define the bounding box for the font, defined in 1 unit
                    661:     // character space (since FontMatrix = identity).
                    662: 
                    663:     PrintString(pdev, "/FontBBox [");
                    664:     PrintDecimal(pdev, 4, ptlTL.x, ptlTL.y, ptlBR.x, ptlBR.y);
                    665:     PrintString(pdev, " ] def\n");
                    666: 
                    667:     // allocate array for encoding vector, then initialize
                    668:     // all characters in encoding vector with '.notdef'.
                    669: 
                    670:     PrintString(pdev, "/Encoding 256 array def\n");
                    671:     PrintString(pdev, "0 1 255 {Encoding exch /.notdef put} for\n");
                    672: 
                    673:     // allocate space to store the HGLYPH<==>character code mapping.
                    674: 
                    675:     if (!(pDLFont->phgVector = (HGLYPH *)HeapAlloc(pdev->hheap, 0,
                    676:                       sizeof(HGLYPH) * 256)))
                    677:     {
                    678:         RIP("PSCRIPT!DownloadANSIBitmapFont: HeapAlloc for phgVector failed.\n");
                    679:         return(FALSE);
                    680:     }
                    681: 
                    682:     // reset pointer to our array of HGLYPHS.  remember to skip over the
                    683:     // first two WORDS.
                    684: 
                    685:     phg = phglyphs + 1;
                    686: 
                    687:     // fill in the HGLYPH encoding vector, and output
                    688:     // the encoding vector to the printer.  leave the first position for
                    689:     // the .notdef character.
                    690: 
                    691:     pDLFont->cGlyphs = 256;
                    692:     memcpy(pDLFont->phgVector, phg, 256 * sizeof(HGLYPH));
                    693: 
                    694:     PrintString(pdev, "Encoding\n");
                    695: 
                    696:     for (i = 1; i < 256; i++)
                    697:     {
                    698:         PrintString(pdev, "dup ");
                    699:         PrintDecimal(pdev, 1, i);
                    700:         PrintString(pdev, " /c");
                    701:         PrintDecimal(pdev, 1, i);
                    702:         PrintString(pdev, " put\n");
                    703:     }
                    704: 
                    705:     // under level 1 of PostScript, the 'BuildChar' procedure is called
                    706:     // every time a character from the font is constructed.  under
                    707:     // level 2, 'BuildGlyph' is called instead.  therefore, we will
                    708:     // define a 'BuildChar' procedure, which basically calls
                    709:     // 'BuildGlyph'.  this will provide us support for both level 1
                    710:     // and level 2 of PostScript.
                    711: 
                    712:     // define the 'BuildGlyph' procedure.  start by getting the
                    713:     // character name and the font dictionary from the stack.
                    714: 
                    715:     PrintString(pdev, "/BuildGlyph {0 begin /cn exch def /fd exch def\n");
                    716: 
                    717:     // retrieve the character information from the CharData (CD)
                    718:     // dictionary.
                    719: 
                    720:     PrintString(pdev, "/CI fd /CD get cn get def\n");
                    721: 
                    722:     // get the width and the bounding box from the CharData.
                    723:     // remember to divide the width by 16.
                    724: 
                    725:     PrintString(pdev, "/wx CI 0 get def /cbb CI 1 4 getinterval def\n");
                    726: 
                    727:     // enable each character to be cached.
                    728: 
                    729:     PrintString(pdev, "wx 0 cbb aload pop setcachedevice\n");
                    730: 
                    731:     // get the width and height of the bitmap, set invert bool to true
                    732:     // specifying reverse image.
                    733: 
                    734:     PrintString(pdev, "CI 5 get CI 6 get true\n");
                    735: 
                    736:     // insert x and y translation components into general imagemask
                    737:     // matrix.
                    738: 
                    739:     PrintString(pdev, "[1 0 0 -1 0 0] dup 4 CI 7 get put dup 5 CI 8 get put\n");
                    740: 
                    741:     // get hex string bitmap, convert into procedure, then print
                    742:     // the bitmap image.
                    743: 
                    744:     PrintString(pdev, "CI 9 1 getinterval cvx imagemask end } def\n");
                    745: 
                    746:     // create local storage for 'BuildGlyph' procedure.
                    747: 
                    748:     PrintString(pdev, "/BuildGlyph load 0 5 dict put\n");
                    749: 
                    750:     // the semantics of 'BuildChar' differ from 'BuildGlyph' in the
                    751:     // following way:  'BuildChar' is called with the font dictionary
                    752:     // and character code on the stack, 'BuildGlyph' is called with
                    753:     // the font dictionary and character name on the stack.  the
                    754:     // following 'BuildChar' procedure calls 'BuildGlyph', and retains
                    755:     // compatiblity with level 1 PostScript.
                    756: 
                    757:     PrintString(pdev, "/BuildChar {1 index /Encoding get exch get\n");
                    758:     PrintString(pdev, "1 index /BuildGlyph get exec} bind def\n");
                    759: 
                    760:     // now create a dictionary containing information on each character.
                    761: 
                    762:     PrintString(pdev, "/CD 256 dict def CD begin\n");
                    763: 
                    764:     // send out the definition of the default (.notdef) character.
                    765: 
                    766:     if (!SendCharBitmap(pdev, pfo, *phg++, 0, TRUE))
                    767:     {
                    768:         RIP("PSCRIPT!DownloadANSIBitmapFont: SendCharBitmap failed.\n");
                    769:         HeapFree(pdev->hheap, 0, (PVOID)pDLFont->phgVector);
                    770:         return(FALSE);
                    771:     }
                    772: 
                    773:     for (i = 1; i < 256; i++)
                    774:     {
                    775:         // don't send out duplicates of the .notdef definition.
                    776: 
                    777:         if (*phg != hgDefault)
                    778:         {
                    779:             if (!SendCharBitmap(pdev, pfo, *phg, i, FALSE))
                    780:             {
                    781:                 RIP("PSCRIPT!DownloadANSIBitmapFont: SendCharBitmap failed.\n");
                    782:                 HeapFree(pdev->hheap, 0, (PVOID)pDLFont->phgVector);
                    783:                 return(FALSE);
                    784:             }
                    785:         }
                    786: 
                    787:         // point to the next HGLYPH.
                    788: 
                    789:         phg++;
                    790:     }
                    791: 
                    792:     // close the definition of the font.
                    793: 
                    794:     PrintString(pdev, "end\n");
                    795: 
                    796:     // create a unique ID for the font, then name it.
                    797: 
                    798:     pwstr = (PWSTR)((BYTE *)pifi + pifi->dpwszFaceName);
                    799:     cTmp = wcslen(pwstr);
                    800: 
                    801:     // get the font name from the UNICODE font name.
                    802: 
                    803:     memset(szFaceName, 0, sizeof(szFaceName));
                    804:     pszFaceName = szFaceName;
                    805: 
                    806:     while (cTmp--)
                    807:     {
                    808:         *pszFaceName = (CHAR)*pwstr++;
                    809: 
                    810:         // replace any spaces in the font name with underscores.
                    811: 
                    812:         if (*pszFaceName == ' ')
                    813:             *pszFaceName = '_';
                    814: 
                    815:         // replace any parens in the font name with asterisks.
                    816: 
                    817:         if ((*pszFaceName == '(') || (*pszFaceName == ')'))
                    818:             *pszFaceName = '*';
                    819: 
                    820:         // point to the next character.
                    821: 
                    822:         *pszFaceName++;
                    823:     }
                    824: 
                    825:     // add the point size to the font name, so we can distinguish
                    826:     // different point sizes of the same font.
                    827: 
                    828:     // NOTE  Grab a new point size here, rather than reading if from
                    829:     // the CGS.  This is necessary to support DrvDownloadFace.
                    830: 
                    831:     psfxPointSize = GetPointSize(pdev, pfo, &fontxform);
                    832: 
                    833:     cTmp = PSFIXToBuffer(pszFaceName, psfxPointSize);
                    834: 
                    835:     // update the buffer pointer.
                    836: 
                    837:     pszFaceName += cTmp;
                    838: 
                    839:     // output the NULL terminator.
                    840: 
                    841:     *pszFaceName = '\0';
                    842: 
                    843:     // output the unique id, which, in a postscript printer, can
                    844:     // be in the range from 0 to 16777215.
                    845: 
                    846:     PrintString(pdev, "/UniqueID ");
                    847:     PrintDecimal(pdev, 1, (pfo->iUniq & 0xFFFFF));
                    848: 
                    849:     PrintString(pdev, " def end pop /");
                    850:     PrintString(pdev, szFaceName);
                    851:     PrintString(pdev, " exch definefont pop\n");
                    852: 
                    853:     // update the fontname in our current graphics state.
                    854: 
                    855:     strcpy(pdev->cgs.szFont, szFaceName);
                    856: 
                    857:     // update information for this downloaded font.
                    858: 
                    859:     strcpy(pDLFont->strFont, szFaceName);
                    860:     pDLFont->psfxScaleFactor = psfxPointSize;
                    861: 
                    862:     // update the downloaded font counter.
                    863: 
                    864:     pdev->cgs.cDownloadedFonts++;
                    865: }
                    866: 
                    867: 
                    868: //--------------------------------------------------------------------
                    869: // BOOL SendCharBitmap(pdev, pfo, hglyph, index, bnotdef);
                    870: // PDEVDATA    pdev;
                    871: // FONTOBJ    *pfo;
                    872: // HGLYPH      hglyph;
                    873: // DWORD       index;
                    874: // BOOL        bnotdef;
                    875: //
                    876: // This routine downloads the character bitmap definition to the printer.
                    877: //
                    878: // This routine return TRUE for success, FALSE otherwise.
                    879: //
                    880: // History:
                    881: //   13-May-1993    -by-    Kent Settle     (kentse)
                    882: //  Broke out of DownloadANSIBitmapFont.
                    883: //--------------------------------------------------------------------
                    884: 
                    885: BOOL SendCharBitmap(pdev, pfo, hglyph, index, bnotdef)
                    886: PDEVDATA    pdev;
                    887: FONTOBJ    *pfo;
                    888: HGLYPH      hglyph;
                    889: DWORD       index;
                    890: BOOL        bnotdef;
                    891: {
                    892:     DWORD       cTmp;
                    893:     GLYPHDATA  *pglyphdata;
                    894:     PS_FIX      psfxXtrans, psfxYtrans;
                    895:     BYTE       *pjBits;
                    896:     DWORD       j;
                    897:     LONG        cjWidth;
                    898: 
                    899:     // get the GLYPHDATA structure for each glyph.
                    900: 
                    901:     if (!(cTmp = FONTOBJ_cGetGlyphs(pfo, FO_GLYPHBITS, 1, &hglyph,
                    902:                                     (PVOID *)&pglyphdata)))
                    903:     {
                    904:         RIP("PSCRIPT!SendCharBitmap: cGetGlyphs failed.\n");
                    905:         return(FALSE);
                    906:     }
                    907: 
                    908:     // the first number in the character description is the width
                    909:     // in 1 unit font space.  the next four numbers are the bounding
                    910:     // box in 1 unit font space.  the next two numbers are the width
                    911:     // and height of the bitmap.  the next two numbers are the x and
                    912:     // y translation values for the matrix given to imagemask.
                    913:     // this is followed by the bitmap itself.
                    914: 
                    915:     // first, output the character name.
                    916: 
                    917:     if (bnotdef)
                    918:         PrintString(pdev, "/.notdef");
                    919:     else
                    920:     {
                    921:         PrintString(pdev, "/c");
                    922:         PrintDecimal(pdev, 1, index);
                    923:     }
                    924: 
                    925:     // output the character description array.  the width and
                    926:     // bounding box need to be normalized to 1 unit font space.
                    927: 
                    928:     // the width will be sent to the printer as the actual width
                    929:     // multiplied by 16 so as not to lose any precision when
                    930:     // normalizing.
                    931: 
                    932:     PrintString(pdev, " [");
                    933:     PrintPSFIX(pdev, 1, (pglyphdata->fxD << 4));
                    934:     PrintString(pdev, " ");
                    935:     PrintDecimal(pdev, 4, pglyphdata->rclInk.left,
                    936:                  -pglyphdata->rclInk.top, pglyphdata->rclInk.right,
                    937:                  -pglyphdata->rclInk.bottom);
                    938:     PrintString(pdev, " ");
                    939: 
                    940:     // output the width and height of the bitmap itself.
                    941: 
                    942:     PrintDecimal(pdev, 2, pglyphdata->gdf.pgb->sizlBitmap.cx,
                    943:                  pglyphdata->gdf.pgb->sizlBitmap.cy);
                    944:     PrintString(pdev, " ");
                    945: 
                    946:     // output the translation values for the transform matrix.
                    947:     // the x component is usually the equivalent of the left
                    948:     // sidebearing in pixels.  the y component is always the height
                    949:     // of the bitmap minus any displacement factor (such as for characters
                    950:     // with descenders.  both components have .5 subtracted from the original
                    951:     // values to avoid roundoff errors.
                    952: 
                    953:     psfxXtrans = ETOPSFX((FLOAT)FXTOLROUND(-pglyphdata->fxA) - 0.5);
                    954:     psfxYtrans = ETOPSFX(-(FLOAT)pglyphdata->gdf.pgb->ptlOrigin.y - 0.5);
                    955: 
                    956:     PrintPSFIX(pdev, 2, psfxXtrans, psfxYtrans);
                    957:     PrintString(pdev, "\n<");
                    958: 
                    959:     // now output the bits.  calculate how many bytes each source scanline
                    960:     // contains.  remember that the bitmap will be padded to 32bit bounds.
                    961: 
                    962:     // protect ourselves.
                    963: 
                    964:     if ((pglyphdata->gdf.pgb->sizlBitmap.cx < 1) ||
                    965:         (pglyphdata->gdf.pgb->sizlBitmap.cy < 1))
                    966:     {
                    967:         RIP("PSCRIPT!SendCharBitmap: Invalid glyphdata!!!.\n");
                    968:         return(FALSE);
                    969:     }
                    970: 
                    971:     pjBits = pglyphdata->gdf.pgb->aj;
                    972: 
                    973:     for (j = 0; j < (DWORD)pglyphdata->gdf.pgb->sizlBitmap.cy; j++)
                    974:     {
                    975:         cjWidth = (LONG)(pglyphdata->gdf.pgb->sizlBitmap.cx + 7) >> 3;
                    976:         vHexOut(pdev, pjBits, cjWidth);
                    977:         pjBits += cjWidth;
                    978:     }
                    979: 
                    980:     PrintString(pdev, ">]def\n");
                    981: 
                    982:     return(TRUE);
                    983: }

unix.superglobalmegacorp.com

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