Annotation of ntddk/src/print/pscript/fntmanag.c, revision 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.