|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.