|
|
1.1 root 1: //--------------------------------------------------------------------------
2: //
3: // Module Name: TEXTOUT.C
4: //
5: // Brief Description: This module contains the PSCRIPT driver's DrvTextOut
6: // function and related routines.
7: //
8: // Author: Kent Settle (kentse)
9: // Created: 12-Feb-1991
10: //
11: // 26-Mar-1992 Thu 23:29:37 updated -by- Daniel Chou (danielc)
12: // Add another parameter to bDoClipObj() so it also return the bounding
13: // rectangle to the clip region for halftone purpose.
14: //
15: // Copyright (c) 1991 - 1992 Microsoft Corporation
16: //--------------------------------------------------------------------------
17:
18: #include "stdlib.h"
19: #include <string.h>
20: #include "pscript.h"
21: #include "enable.h"
22: #include "mapping.h"
23: #include "resource.h"
24:
25: extern HMODULE ghmodDrv; // GLOBAL MODULE HANDLE.
26:
27: extern TT_FONT_MAPPING TTFamilyTable[]; // tables.h.
28: extern TT_FONT_MAPPING TTFontTable[]; // tables.h.
29: extern BOOL DrvCommonPath(PDEVDATA, PATHOBJ *);
30: extern VOID ps_show(PDEVDATA, STROBJ *, FLONG, TEXTDATA *);
31: extern DWORD PSFIXToBuffer(CHAR *, PS_FIX);
32: extern PS_FIX GetPointSize(PDEVDATA, FONTOBJ *, XFORM *);
33:
34: #ifdef INDEX_PAL
35: extern ULONG PSMonoPalette[];
36: extern ULONG PSColorPalette[];
37: #endif
38:
39: PSZ apszRemapCode[] =
40: {
41: "/reencode {findfont begin currentdict d length dict begin {",
42: "1 index /FID ne {def} {pop pop} ifelse} forall /FontName exch def",
43: "d length 0 ne {/Encoding Encoding 256 array copy def 0 exch {",
44: "d type /nametype eq {Encoding 2 index 2 index put pop 1 add",
45: "}{exch pop} ifelse} forall} if pop currentdict d end end",
46: "/FontName get exch definefont pop} bd",
47: NULL
48: } ;
49:
50: typedef struct
51: {
52: WCHAR wc; // UNICODE code point.
53: POINTL ptlpgp; // pointl as defined by GLYPHPOS structs.
54: POINTFIX ptfxorg; // pointfix as defined by original font.
55: } TEXTDELTA;
56:
57: #define MAX_LINE_LENGTH 70
58:
59: // macro for scaling between TrueType and Adobe fonts.
60:
61: #define TTTOADOBE(x) (((x) * ADOBE_FONT_UNITS) / pifi->fwdUnitsPerEm)
62:
63: // declaration of routines residing in this module.
64:
65: BOOL bDoClipObj(PDEVDATA, CLIPOBJ *, RECTL *, RECTL *, BOOL *, BOOL *, DWORD);
66: BOOL DrawGlyphs(PDEVDATA, DWORD, GLYPHPOS *, FONTOBJ *, STROBJ *, TEXTDATA *, PWSZ);
67: BOOL RemapDeviceChar(PDEVDATA, PCHAR, STROBJ *, FLONG, BOOL, TEXTDATA *);
68: BOOL RemapUnicodeChar(PDEVDATA, PWCHAR, STROBJ *, FLONG, BOOL, TEXTDATA *);
69: BOOL RemapGDIChar(PDEVDATA, STROBJ *, GLYPHPOS *, DLFONT *, BOOL *, FLONG, TEXTDATA *);
70: BOOL SelectFont(PDEVDATA, FONTOBJ *, TEXTDATA *);
71: VOID RemapFont(PDEVDATA, STROBJ *, FLONG, BOOL, TEXTDATA *);
72: VOID CharBitmap(PDEVDATA, GLYPHPOS *);
73: BOOL DownloadBitmapFont(PDEVDATA, FONTOBJ *);
74: BOOL DownloadOutlineFont(PDEVDATA, FONTOBJ *);
75: BOOL SetFontRemap(PDEVDATA, DWORD);
76: BOOL QueryFontRemap(PDEVDATA, DWORD);
77: DWORD SubstituteIFace(PDEVDATA, FONTOBJ *);
78: LONG iHipot(LONG, LONG);
79: BOOL IsJustifiedText(PDEVDATA, FONTOBJ *, STROBJ *, POINTPSFX *,
80: POINTPSFX *, TEXTDATA *);
81: BOOL FillDeltaArray(PDEVDATA, FONTOBJ *, GLYPHPOS *, STROBJ *, TEXTDELTA *,
82: DWORD, PWSZ);
83: PWSTR GetUnicodeString(PDEVDATA, FONTOBJ *, STROBJ *);
84: VOID ConstructUCString(GLYPHPOS *, PUCMap, DWORD, PWSTR);
85: BOOL GetDeviceWidths(PDEVDATA, FONTOBJ *, GLYPHDATA *, HGLYPH);
86:
87: //--------------------------------------------------------------------------
88: // BOOL DrvTextOut (pso, pstro, pfo, pco, prclExtra, prclOpaque, pboFore,
89: // pboOpaque, pptBrushOrg, mix)
90: // SURFOBJ *pso;
91: // STROBJ *pstro;
92: // FONTOBJ *pfo;
93: // CLIPOBJ *pco;
94: // RECTL *prclExtra;
95: // RECTL *prclOpaque;
96: // BRUSHOBJ *pboFore;
97: // BRUSHOBJ *pboOpaque;
98: // POINTL *pptlBrushOrg;
99: // MIX mix;
100: //
101: // The graphics engine will call this routine to render a set of glyphs at
102: // specified positions. In order to make things clear, we will make a short
103: // mathematical detour. The parameters of the function unambiguously divides
104: // the entire set of device space pixels into three proper subsets denoted
105: // foreground, background, and transparent. When the text is rendered to the
106: // surface, the foreground pixels are rendered with a foreground brush, the
107: // background pixels the background brush, and the transparent pixels are left
108: // untouched. The foreground pixels are defined by first forming the union of
109: // all the glyph pixels with the pixels of the extra rectangles, then
110: // intersecting the result with the pixels of the clipping region. The set
111: // of pixels comprising the extra rectangles are defined by (up to) three
112: // rectangles pointed to by prclExt. These rectangles are used to simulate
113: // effects like underlining and strike through glyphs. The background set of
114: // pixels is defined as the intersection of three sets: (1) the pixels of the
115: // background rectangle; (2) the complement of the foreground; (3) the
116: // clipping region. Any pixels that are not part of either the foreground or
117: // background sets are defined to be transparent. The input parameters to
118: // DrvTextOut define two sets of pixels foreground and opaque. The driver must
119: // render the surface so that the result is identical to a process where the
120: // opaque pixels are rendered first with the opaque brush, then the foreground
121: // pixels are rendered with the foreground brush. Each of these operations is
122: // limited by clipping. The foreground set of pixels is defined to be the
123: // union of the pixels of the glyphs and the pixels of the "extra" rectangles
124: // at prclExtra. These extra rectangles are used to simulate strike-through or
125: // underlines. The opaque pixels are defined by the opaque rectangle at
126: // prclOpaque. The foreground and opaque pixels are regarded as a screen
127: // through which color is brushed onto the surface. The glyphs of the font
128: // do not have color in themselves. The input parameters to DrvTextOut
129: // define the set of glyph pixels, the set of extra rectangles, the opaque
130: // rectangle, and the clipping region. It is the responsibility of the driver
131: // to calculate and then render the set of foreground and opaque pixels.
132: //
133: // Parameters:
134: // pso
135: // Pointer to a SURFOBJ.
136: //
137: // pstro
138: // Pointer to a STROBJ. This defines the glyphs to be rendered and the
139: // positions where they are to be placed.
140: //
141: // pfo
142: // Pointer to a FONTOBJ. This is used to retrieve information about the
143: // font and its glyphs.
144: //
145: // pco
146: // Pointer to a CLIPOBJ. This defines the clipping region through which
147: // all rendering must be done. No pixels can be affected outside the
148: // clipping region.
149: //
150: // prclExtra
151: // Pointer to a null terminated array of rectangles. These rectangles
152: // are bottom right exclusive. The pixels of the rectangles are to be
153: // combined with the pixels of the glyphs to produce the foreground
154: // pixels. The extra rectangles are used to simulate underlining or strike
155: // out. If prclExtra is NULL then there are no extra rectangles to be
156: // rendered. If the prclExtra is not NULL then the rectangles are read
157: // until a null rectangle is reached. A null rectangle has both coordinates
158: // of both points set to zero.
159: //
160: // prclOpaque
161: // Pointer to a single opaque rectangle. This rectangle is bottom
162: // right exclusive. Pixels within this rectangle (that are not foreground
163: // and not clipped) are to be rendered with the opaque brush. If this
164: // argument is NULL then no opaque pixels are to be rendered.
165: //
166: // pboFore
167: // Pointer to the brush object to be used for the foreground pixels.
168: // The fill pattern is defined by this brush. A GDI service,
169: // BRUSHOBJ_pvDevBrush, is provided to find the device's realization of
170: // the brush.
171: //
172: // pboOpaque
173: // Pointer to the brush object for the opaque pixels. Both the foreground
174: // and background mix modes for this brush are assumed to be overpaint.
175: //
176: // pptlBrushOrg
177: // Pointer to a POINTL defining the brush origin for both brushes.
178: //
179: // mix
180: // Foreground and background raster operations (mix modes) for pboFore.
181: //
182: // Returns:
183: // TRUE if successful. Otherwise FALSE, and an error code is logged.
184: //
185: // History:
186: // 12-Feb-1991 -by- Kent Settle (kentse)
187: // Wrote it.
188: //--------------------------------------------------------------------------
189:
190: BOOL DrvTextOut(
191: SURFOBJ *pso,
192: STROBJ *pstro,
193: FONTOBJ *pfo,
194: CLIPOBJ *pco,
195: PRECTL prclExtra,
196: PRECTL prclOpaque,
197: BRUSHOBJ *pboFore,
198: BRUSHOBJ *pboOpaque,
199: PPOINTL pptlOrg,
200: MIX mix)
201: {
202: PDEVDATA pdev;
203: BOOL bMore;
204: DEVBRUSH *pBrush;
205: RECTL rclBounds;
206: FONTINFO fi;
207: DWORD cGlyphs;
208: GLYPHPOS *pgp;
209: BOOL bClipping;
210: TEXTDATA *pdata;
211: BOOL bFirstClipPass;
212: ULONG ulColor;
213: ULONG *pulColors;
214:
215: // make sure we have been given valid pointers.
216:
217: if ((pso == (SURFOBJ *)NULL) || (pstro == (STROBJ *)NULL) ||
218: (pfo == (FONTOBJ *)NULL) || (pco == (CLIPOBJ *)NULL))
219: {
220: RIP("PSCRIPT!DrvTextOut: NULL pointer passed in.\n");
221: SetLastError(ERROR_INVALID_PARAMETER);
222: return(FALSE);
223: }
224:
225: // get the pointer to our DEVDATA structure and make sure it is ours.
226:
227: pdev = (PDEVDATA) pso->dhpdev;
228:
229: if (bValidatePDEV(pdev) == FALSE)
230: {
231: RIP("PSCRIPT!DrvTextOut: invalid PDEV.");
232: SetLastError(ERROR_INVALID_PARAMETER);
233: return(FALSE);
234: }
235:
236: // make sure we have been given a valid font.
237:
238: if ( (pfo->flFontType & DEVICE_FONTTYPE) &&
239: (pfo->iFace > (pdev->cDeviceFonts + pdev->cSoftFonts)) )
240: {
241: RIP("PSCRIPT!DrvTextOut: invalid iFace.\n");
242: SetLastError(ERROR_INVALID_PARAMETER);
243: return(FALSE);
244: }
245:
246: // allocate and initialize a TEXTDATA structure.
247:
248: if (!(pdata = (TEXTDATA *)HeapAlloc(pdev->hheap, 0, sizeof(TEXTDATA))))
249: {
250: RIP("PSCRIPT!DrvTextOut: HeapAlloc for TEXTDATA failed.");
251: return(FALSE);
252: }
253:
254: pdata->iFace = pfo->iFace;
255: pdata->bFontSubstitution = FALSE;
256: pdata->ptSpace.x = 0;
257: pdata->ptSpace.y = 0;
258: pdata->ptNonSpace.x = 0;
259: pdata->ptNonSpace.y = 0;
260:
261: if ((pfo->flFontType & TRUETYPE_FONTTYPE) &&
262: (pdev->psdm.dwFlags & PSDEVMODE_FONTSUBST))
263: {
264: if (pdata->iFace = SubstituteIFace(pdev, pfo))
265: pdata->bFontSubstitution = TRUE;
266: else
267: pdata->iFace = pfo->iFace;
268: }
269:
270: pdata->bDeviceFont = (pdata->bFontSubstitution ||
271: (pfo->flFontType & DEVICE_FONTTYPE) );
272:
273: pdata->bJustification = IsJustifiedText(pdev, pfo, pstro, &pdata->ptSpace,
274: &pdata->ptNonSpace, pdata);
275:
276: // clear the font download threshold flag.
277:
278: pdev->cgs.dwFlags &= ~CGS_DLFONTTHRESHOLD;
279:
280: // select the current font in the printer from the given FONTOBJ.
281:
282: if (!SelectFont(pdev, pfo, pdata))
283: {
284: #if DBG
285: DbgPrint("PSCRIPT!DrvTextOut: SelectFont failed.\n");
286: #endif
287: HeapFree(pdev->hheap, 0, (PVOID)pdata);
288: return(FALSE);
289: }
290:
291: // handle the clip object passed in.
292: bFirstClipPass = TRUE;
293:
294: bClipping = bDoClipObj(pdev, pco, NULL, NULL, NULL,
295: &bFirstClipPass, MAX_CLIP_RECTS);
296:
297: if (bClipping)
298: ps_clip(pdev, TRUE);
299:
300: // output the Opaque rectangle if necessary. this is a background
301: // rectangle that goes behind the foreground text, therefore, send
302: // it to the printer before the text.
303:
304: if (prclOpaque)
305: {
306: // define the opaque rectangle in the printer.
307:
308: ps_newpath(pdev);
309: ps_box(pdev, prclOpaque);
310:
311: // call the driver's filling routine. this routine will do the
312: // right thing with the brush.
313:
314: if (!ps_patfill(pdev, pso, (FLONG)FP_WINDINGMODE, pboOpaque, pptlOrg, mix,
315: prclOpaque, FALSE, FALSE))
316: {
317: HeapFree(pdev->hheap, 0, (PVOID)pdata);
318: return(FALSE);
319: }
320: }
321:
322: // output the text color to draw with.
323:
324: #ifdef INDEX_PAL
325: // just output solid color if there is one.
326:
327: if ((pdev->pntpd->flFlags & COLOR_DEVICE) &&
328: (pdev->psdm.dm.dmColor == DMCOLOR_COLOR))
329: pulColors = PSColorPalette;
330: else
331: pulColors = PSMonoPalette;
332:
333: if (pboFore->iSolidColor != NOT_SOLID_COLOR)
334: {
335: ps_setrgbcolor(pdev, (PALETTEENTRY *)pulColors + pboFore->iSolidColor);
336: }
337: else
338: {
339: // get the device brush to draw with.
340:
341: pBrush = (DEVBRUSH *)BRUSHOBJ_pvGetRbrush(pboFore);
342:
343: if (!pBrush)
344: {
345: #if DBG
346: DbgPrint("DrvTextOut: NULL pBrush.\n");
347: #endif
348: // something is wrong! let's print some black text.
349:
350: ulColor = RGB_BLACK;
351: ps_setrgbcolor(pdev, (PALETTEENTRY *)&ulColor);
352: }
353: else
354: {
355: if (pBrush->iSolidColor == NOT_SOLID_COLOR)
356: {
357: // get the foreground color.
358:
359: ps_setrgbcolor(pdev, ((PALETTEENTRY *)pulColors +
360: *(ULONG *)((PBYTE)pBrush + pBrush->offsetXlate +
361: sizeof(ULONG))));
362: }
363: else
364: {
365: ps_setrgbcolor(pdev, (PALETTEENTRY *)&pBrush->iSolidColor);
366: }
367: }
368: }
369: #else
370: if (pboFore->iSolidColor == NOT_SOLID_COLOR)
371: {
372: // this is not a solid brush, so get a pointer to the
373: // realized brush.
374:
375: #if DBG
376: DbgPrint("DrvTextOut: non-solid text brush, defaulting to black.\n");
377: #endif
378: ulColor = RGB_BLACK;
379: ps_setrgbcolor(pdev, (BGR_PAL_ENTRY *)&ulColor);
380: }
381: else
382: {
383: // we have a solid brush, so simply output the line color.
384:
385: ps_setrgbcolor(pdev, (BGR_PAL_ENTRY *)&pboFore->iSolidColor);
386: }
387: #endif
388:
389:
390: // get some information about the font.
391:
392: FONTOBJ_vGetInfo(pfo, sizeof(FONTINFO), &fi);
393:
394: // get the GLYPHPOS's, directly or indirectly.
395:
396: if (pstro->pgp)
397: {
398: if (!DrawGlyphs(pdev, pstro->cGlyphs, pstro->pgp, pfo, pstro, pdata, pstro->pwszOrg))
399: {
400: RIP("PSCRIPT!DrvTextOut: DrawGlyphs failed.\n");
401: HeapFree(pdev->hheap, 0, (PVOID)pdata);
402: return(FALSE);
403: }
404: }
405: else
406: {
407: PWSZ pwszCur = pstro->pwszOrg;
408:
409: // prepare to enumerate the string properly.
410:
411: STROBJ_vEnumStart(pstro);
412:
413: // now draw the text.
414:
415: do
416: {
417: bMore = STROBJ_bEnum(pstro, &cGlyphs, &pgp);
418:
419: if (!DrawGlyphs(pdev, cGlyphs, pgp, pfo, pstro, pdata, pwszCur))
420: {
421: RIP("PSCRIPT!DrvTextOut: DrawGlyphs failed.\n");
422: HeapFree(pdev->hheap, 0, (PVOID)pdata);
423: return(FALSE);
424: }
425:
426: pwszCur += cGlyphs;
427:
428: } while (bMore);
429: }
430: // invalidate the current position so it will get updated next time.
431:
432: pdev->cgs.ptlCurPos.x = -1;
433: pdev->cgs.ptlCurPos.y = -1;
434:
435: // output the extra rectangles if necessary. These rectangles are
436: // bottom right exclusive. the pels of the rectangles are to be
437: // combined with the pixels of the glyphs to produce the foreground
438: // pels. the extra rectangles are used to simulate underlining or
439: // strikeout.
440:
441: if (prclExtra)
442: {
443: // output a newpath command to the printer.
444:
445: ps_newpath(pdev);
446:
447: // set up bounding rectangle.
448:
449: rclBounds = *prclExtra;
450:
451: // output each Extra rectangle until we find the terminating
452: // retangle with all NULL coordinates.
453:
454: while ((prclExtra->right != prclExtra->left) ||
455: (prclExtra->top != prclExtra->bottom) ||
456: (prclExtra->right != 0L) ||
457: (prclExtra->top != 0L))
458: {
459: ps_box(pdev, prclExtra);
460:
461: // update the bounding rectangle if necessary.
462:
463: if (prclExtra->left < rclBounds.left)
464: rclBounds.left = prclExtra->left;
465: if (prclExtra->right > rclBounds.right)
466: rclBounds.right = prclExtra->right;
467: if (prclExtra->top < rclBounds.top)
468: rclBounds.top = prclExtra->top;
469: if (prclExtra->bottom > rclBounds.bottom)
470: rclBounds.bottom = prclExtra->bottom;
471:
472: prclExtra++;
473: }
474:
475: // call the driver's filling routine. this routine will do the
476: // right thing with the brush.
477:
478: if (!ps_patfill(pdev, pso, (FLONG)FP_WINDINGMODE, pboFore, pptlOrg, mix,
479: &rclBounds, FALSE, FALSE))
480: {
481: HeapFree(pdev->hheap, 0, (PVOID)pdata);
482: return(FALSE);
483: }
484: }
485:
486: if (bClipping)
487: ps_restore(pdev, TRUE);
488:
489: // if we have hit the downloaded font threshold, then we are doing
490: // a save/restore around every textout call.
491:
492: if (pdev->cgs.dwFlags & CGS_DLFONTTHRESHOLD)
493: ps_restore(pdev, FALSE);
494:
495: // free up memory.
496:
497: HeapFree(pdev->hheap, 0, (PVOID)pdata);
498:
499: return(TRUE);
500: }
501:
502: //--------------------------------------------------------------------------
503: // BOOL bDoClipObj(pdev, pco, prclClipBound, pbMoreClipping,
504: // pbFirstPass, cRectLimit)
505: // PDEVDATA pdev;
506: // CLIPOBJ *pco;
507: // RECTL *prclClipBound;
508: // BOOL *pbMoreClipping;
509: // BOOL *pbFirstPass;
510: // DWORD cRectLimit;
511: //
512: // This routine will determine the clipping region as defined in pco, and
513: // send the appropriate commands to the printer to set the clip region
514: // in the printer.
515: //
516: // Parameters:
517: // pdev
518: // Pointer to our DEVDATA structure.
519: //
520: // pco
521: // Pointer to a CLIPOBJ. This defines the clipping region through which
522: // all rendering must be done. No pixels can be affected outside the
523: // clipping region.
524: //
525: // bBitblt
526: // True if called from bitblt function
527: //
528: // prclBound
529: // If not NULL then it return the bounding rectangle for the clipping
530: // region, the returning rclBound only valid if return value is TRUE.
531: //
532: // Returns:
533: // This routine returns TRUE if a clippath was sent to the printer,
534: // otherwise FALSE.
535: //
536: // History:
537: // 26-Mar-1992 Thu 23:33:58 updated -by- Daniel Chou (danielc)
538: // add prclBound to accumulate the bounding rectangle for the clipping
539: // region.
540: //
541: // 12-Feb-1991 -by- Kent Settle (kentse)
542: // Wrote it.
543: //--------------------------------------------------------------------------
544:
545: BOOL bDoClipObj(pdev, pco, prclClipBound, prclTarget, pbMoreClipping,
546: pbFirstPass, cRectLimit)
547: PDEVDATA pdev;
548: CLIPOBJ *pco;
549: RECTL *prclClipBound;
550: RECTL *prclTarget;
551: BOOL *pbMoreClipping;
552: BOOL *pbFirstPass;
553: DWORD cRectLimit;
554: {
555: short iComplex;
556: ENUMRECTS buffer;
557: BOOL bMore;
558: ULONG cRects;
559: RECTL rclClipBound;
560:
561: // assume all clipping will be done within this one call.
562:
563: if (pbMoreClipping)
564: *pbMoreClipping = FALSE;
565:
566: if (pco == NULL)
567: return(FALSE);
568:
569: iComplex = (short)pco->iDComplexity;
570:
571: switch(iComplex)
572: {
573: case DC_TRIVIAL:
574: // in this case, there is no clipping. Therefore, we have
575: // no commands to send to the printer.
576:
577: return (FALSE);
578:
579: case DC_RECT:
580: // check to see if the target rectangle fits inside the clip
581: // rectangle. if it does, don't do clipping.
582:
583: if (prclTarget)
584: {
585: if ((pco->rclBounds.left <= prclTarget->left) &&
586: (pco->rclBounds.top <= prclTarget->top) &&
587: (pco->rclBounds.right >= prclTarget->right) &&
588: (pco->rclBounds.bottom >= prclTarget->bottom))
589: {
590: // I see no reason to clip this, do you?
591:
592: return(FALSE);
593: }
594: }
595:
596: // in this case, we are clipping to a single rectangle.
597: // get it from the CLIPOBJ, then send it to the printer.
598:
599: buffer.arcl[0] = pco->rclBounds;
600:
601: // send a newpath command, then the clip rectangle to
602: // the printer. TRUE means to do a gsave, not a save command.
603:
604: if (!ps_save(pdev, TRUE))
605: return(FALSE);
606:
607: ps_newpath(pdev);
608: ps_box(pdev, &buffer.arcl[0]);
609:
610: if (prclClipBound)
611: *prclClipBound = buffer.arcl[0]; // this is the bound
612:
613: break;
614:
615: case DC_COMPLEX:
616: // in this case, we are clipping to a complex clip region.
617: // enumerate the clip region from the CLIPOBJ, and send the
618: // entire clip region to the printer.
619:
620: //
621: // 26-Mar-1992 Thu 23:49:59 updated -by- Daniel Chou (danielc)
622: //
623: // Initialize the empty bound then acculate it later,
624: //
625: // !!!! This may changed, we need to check with engine guys to
626: // see if you can just pick up the clip region bounding
627: // rectangle from pco->rclBounds, if so we need to deleted
628: // all accumulation codes.
629: //
630:
631: if (prclClipBound)
632: {
633: rclClipBound.top =
634: rclClipBound.left = 0x7fffffffL;
635: rclClipBound.right =
636: rclClipBound.bottom = 0;
637: }
638:
639: // send a newpath command to the printer.
640:
641: if (!ps_save(pdev, TRUE))
642: return(FALSE);
643:
644: ps_newpath(pdev);
645:
646: // set up to enumerate the clip region, but just do this once.
647:
648: if (*pbFirstPass == TRUE)
649: {
650: cRects = CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
651: *pbFirstPass = FALSE;
652: }
653:
654: // now get each clipping rectangle from the engine, and
655: // send it down to the printer.
656:
657: bMore = TRUE;
658:
659: cRects = 0;
660:
661: while(bMore)
662: {
663: bMore = CLIPOBJ_bEnum(pco, sizeof(buffer), &buffer.c);
664:
665: if (buffer.c == 0)
666: {
667: bMore = FALSE;
668: break;
669: }
670:
671: ps_box(pdev, &buffer.arcl[0]);
672:
673: if (prclClipBound)
674: {
675: if (rclClipBound.top > buffer.arcl[0].top)
676: rclClipBound.top = buffer.arcl[0].top;
677:
678: if (rclClipBound.left > buffer.arcl[0].left)
679: rclClipBound.left = buffer.arcl[0].left;
680:
681: if (rclClipBound.right < buffer.arcl[0].right)
682: rclClipBound.right = buffer.arcl[0].right;
683:
684: if (rclClipBound.bottom < buffer.arcl[0].bottom)
685: rclClipBound.bottom = buffer.arcl[0].bottom;
686: }
687:
688: if (pbMoreClipping)
689: {
690: cRects++;
691: if (cRects >= cRectLimit)
692: {
693: *pbMoreClipping = TRUE;
694: break;
695: }
696: }
697: }
698:
699: // now intersect our new complex region with the existing
700: // clipping region.
701:
702: if (prclClipBound)
703: *prclClipBound = rclClipBound;
704:
705: break;
706:
707: default:
708: // if we get here, we have been passed an invalid pco->iDComplexity.
709: // in this case, we will RIP, then treat as trivial clipping case.
710:
711: RIP("vDoClipObj: invalid pco->iDComplexity.\n");
712: }
713:
714: return(TRUE);
715: }
716:
717:
718: //--------------------------------------------------------------------------
719: // BOOL DrawGlyphs(pdev, cGlyphs, pgp, pfo, pstro, pdata, pwsz)
720: // PDEVDATA pdev;
721: // DWORD cGlyphs;
722: // GLYPHPOS *pgp;
723: // FONTOBJ *pfo;
724: // STROBJ *pstro;
725: // TEXTDATA *pdata;
726: // PWSZ pwsz;
727: //
728: // This routine will output the given glyph at the given position.
729: //
730: // Parameters:
731: // pdev
732: // Pointer to our DEVDATA structure.
733: //
734: // Returns:
735: // This routine returns no value.
736: //
737: // History:
738: // 26-Apr-1991 -by- Kent Settle (kentse)
739: // Wrote it.
740: //--------------------------------------------------------------------------
741:
742: BOOL DrawGlyphs(pdev, cGlyphs, pgp, pfo, pstro, pdata, pwsz)
743: PDEVDATA pdev;
744: DWORD cGlyphs;
745: GLYPHPOS *pgp;
746: FONTOBJ *pfo;
747: STROBJ *pstro;
748: TEXTDATA *pdata;
749: PWSZ pwsz;
750: {
751: DWORD cTmp;
752: PS_FIX psfxWidth, psfxHeight;
753: DLFONT *pDLFont;
754: BOOL bString;
755: DWORD i;
756: FLONG flAccel;
757: PWSTR pwstrString;
758:
759: // get a local copy of the accelerators to munge with.
760:
761: flAccel = pstro->flAccel;
762:
763: // if we have a TrueType font, and we are doing font substitution,
764: // ignore the SO_FLAG_DEFAULT_PLACEMENT flag. ie, let the engine tell
765: // us where to place each character.
766:
767: if (pdata->bFontSubstitution)
768: flAccel &= ~SO_FLAG_DEFAULT_PLACEMENT;
769:
770: if (cGlyphs != 0)
771: {
772: // position the first character of the string.
773:
774: ps_moveto(pdev, &pgp->ptl);
775:
776: // if we have non-standard spacing for the device font,
777: // output an array of character widths, and push the
778: // current point on the stack for use in the kshow command.
779:
780: if (!(flAccel & SO_FLAG_DEFAULT_PLACEMENT))
781: {
782: cTmp = cGlyphs - 1;
783:
784: // we need to handle the different STROBJ accelerators
785: // here. these accelerators only affect us if the font
786: // is not using the default placement.
787:
788: if (flAccel & SO_HORIZONTAL)
789: {
790: if (pdata->bJustification && (cGlyphs > 1))
791: {
792: // if we did the justification calculations and found
793: // that the justification widths were zero, do nothing
794: // here.
795:
796: if ((pdata->ptSpace.x != 0) || (pdata->ptNonSpace.x != 0))
797: {
798: PrintPSFIX(pdev, 2, pdata->ptSpace.x, pdata->ptSpace.y);
799: PrintString(pdev, " 8#040 ");
800: PrintPSFIX(pdev, 2, pdata->ptNonSpace.x, pdata->ptNonSpace.y);
801: PrintString(pdev, "\n");
802: }
803: }
804: else
805: {
806: // set up to output array of widths in reverse order,
807: // since we will get them off the stack.
808:
809: pgp += cGlyphs - 1;
810:
811: #if 0
812: //!!! This is just plain wrong!!! -kentse.
813: // deal with fixed pitch fonts.
814:
815: if (pstro->ulCharInc)
816: {
817: // we have a fixed pitch font, and the fixed
818: // character increment can be found in pstro->ulCharInc.
819:
820: lCharInc = (LONG)pstro->ulCharInc;
821:
822: if (flAccel & SO_REVERSED)
823: lCharInc *= -1;
824:
825: // output the increment value.
826:
827: PrintDecimal(pdev, 1, lCharInc);
828: PrintString(pdev, " ");
829: }
830: else // must be a proportional font.
831: {
832: // output the character width for each glyph.
833:
834: i = 0;
835: while (cTmp--)
836: {
837: psfxWidth = X72DPI(pgp->ptl.x) - X72DPI((pgp - 1)->ptl.x);
838: pgp--;
839: PrintPSFIX(pdev, 1, psfxWidth);
840: PrintString(pdev, " ");
841:
842: // make it readable.
843:
844: if (i++ == 10)
845: {
846: PrintString(pdev, "\n");
847: i = 0;
848: }
849: }
850: }
851: #endif
852: // output the character width for each glyph.
853:
854: i = 0;
855: while (cTmp--)
856: {
857: psfxWidth = X72DPI(pgp->ptl.x) - X72DPI((pgp - 1)->ptl.x);
858: pgp--;
859: PrintPSFIX(pdev, 1, psfxWidth);
860: PrintString(pdev, " ");
861:
862: // make it readable.
863:
864: if (i++ == 10)
865: {
866: PrintString(pdev, "\n");
867: i = 0;
868: }
869: }
870: }
871: }
872:
873: else if (flAccel & SO_VERTICAL)
874: {
875: // set up to output array of widths in reverse order,
876: // since we will get them off the stack.
877:
878: pgp += cGlyphs - 1;
879:
880: #if 0
881: //!!! this is just plain wrong!!! -kentse.
882: // deal with fixed pitch fonts.
883:
884: if (pstro->ulCharInc)
885: {
886: // we have a fixed pitch font, and the fixed
887: // character increment can be found in pstro->ulCharInc.
888:
889: lCharInc = (LONG)pstro->ulCharInc;
890:
891: if (flAccel & SO_REVERSED)
892: lCharInc *= -1;
893:
894: // output the increment value.
895:
896: PrintDecimal(pdev, 1, lCharInc);
897: PrintString(pdev, " ");
898: }
899: else // must be a proportional font.
900: {
901: // output the character width for each glyph.
902:
903: while (cTmp--)
904: {
905: psfxHeight = X72DPI(pgp->ptl.y) - X72DPI((pgp - 1)->ptl.y);
906: pgp--;
907: PrintPSFIX(pdev, 1, psfxHeight);
908: PrintString(pdev, " ");
909: }
910: }
911: #endif
912: // output the character width for each glyph.
913:
914: while (cTmp--)
915: {
916: psfxHeight = X72DPI(pgp->ptl.y) - X72DPI((pgp - 1)->ptl.y);
917: pgp--;
918: PrintPSFIX(pdev, 1, psfxHeight);
919: PrintString(pdev, " ");
920: }
921: }
922: else // the general case.
923: {
924: // in the general case, we are printing a string which
925: // does not use the default character spacing, and is
926: // not horizontal or vertical. in this case, we must
927: // do a moveto and a show command for every character.
928:
929: if (pdata->bDeviceFont)
930: {
931: // it should be noted that pwstrString is only used
932: // if substitution is on, so we do not have to worry
933: // about the fact that pstro->pwszOrg is not filled
934: // in for device fonts. we do not use the pstro->pwszOrg
935: // directly because the STROBJ_bEnum may be "chunking"
936: // the data. therefore we will use the current pos.
937: // string pointer passed in. it is the caller's
938: // responsibility to keep this current.
939:
940: pwstrString = pwsz;
941:
942: while (cGlyphs--)
943: {
944: ps_moveto(pdev, &pgp->ptl);
945:
946: // output a left paren to open the string.
947:
948: PrintString(pdev, "(");
949:
950: // output each character of the string to the printer.
951: // if we are doing font substitution then we are substituting
952: // a device font for a truetype font. it is assumed that
953: // the hglyphs for the truetype font are the unicode character
954: // codes.
955:
956: if (pdata->bFontSubstitution)
957: {
958: if (!(RemapUnicodeChar(pdev, pwstrString++, pstro,
959: flAccel, FALSE, pdata)))
960: {
961: RIP("PSCRIPT!DrawGlyphs: RemapUnicodeChar failed.\n");
962: return(FALSE);
963: }
964: }
965: else
966: {
967: if (!(RemapDeviceChar(pdev, (CHAR *)&pgp->hg, pstro,
968: flAccel, FALSE, pdata)))
969: {
970: RIP("PSCRIPT!DrawGlyphs: RemapDeviceChar failed.\n");
971: return(FALSE);
972: }
973: }
974:
975: // close the string and send out the show command,
976: // abreviated by 't'.
977:
978: PrintString(pdev, ")t\n");
979:
980: // point to the next character.
981:
982: pgp++;
983: }
984:
985: }
986: else // must be a GDI font.
987: {
988: // get a pointer to our downloaded font structure for this
989: // font.
990:
991: pDLFont = pdev->cgs.pDLFonts;
992:
993: for (i = 0; i < pdev->iDLFonts; i++)
994: {
995: // is this entry the one we are looking for?
996:
997: if (pDLFont->iUniq == pfo->iUniq)
998: break;
999:
1000: pDLFont++;
1001: }
1002:
1003: while (cGlyphs--)
1004: {
1005: ps_moveto(pdev, &pgp->ptl);
1006:
1007: // output a left paren to open the string.
1008:
1009: PrintString(pdev, "(");
1010:
1011: // set a flag stating that we are now within a string.
1012:
1013: bString = TRUE;
1014:
1015: // output each character of the string to the printer.
1016:
1017: if (!(RemapGDIChar(pdev, pstro, pgp, pDLFont, &bString,
1018: flAccel, pdata)))
1019: {
1020: RIP("PSCRIPT!DrawGlyphs: RemapGDIChar failed.\n");
1021: return(FALSE);
1022: }
1023:
1024: // close the string and send out the show command,
1025: // abreviated by 't'.
1026:
1027: PrintString(pdev, ")t\n");
1028:
1029: // point to the next character.
1030:
1031: pgp++;
1032: }
1033: }
1034: }
1035:
1036: if ((pstro->cGlyphs != 1) && (!pdata->bJustification) &&
1037: ((flAccel & SO_HORIZONTAL) || (flAccel & SO_VERTICAL)))
1038: {
1039: // pgp should now point back to where it did before
1040: // we entered this if statement.
1041:
1042: PrintString(pdev, "a\n"); // 'a' is abrev for currentpoint.
1043: }
1044: } // end of !SO_FLAG_DEFAULT_PLACEMENT.
1045:
1046: if ((flAccel & SO_FLAG_DEFAULT_PLACEMENT) ||
1047: (flAccel & SO_HORIZONTAL) ||
1048: (flAccel & SO_VERTICAL))
1049: {
1050: // output a left paren to open the string.
1051:
1052: PrintString(pdev, "(");
1053:
1054: // set a flag stating that we are NOT within a string, until
1055: // the first character is actually output. this is necessary
1056: // to prevent problems in the HORIZONTAL and VERTICAL cases,
1057: // when remapping a font.
1058:
1059: bString = FALSE;
1060:
1061: if (pdata->bDeviceFont)
1062: {
1063: // output each character of the string to the printer.
1064: // if we are doing font substitution then we are substituting
1065: // a device font for a truetype font. it is assumed that
1066: // the hglyphs for the truetype font are the unicode character
1067: // codes.
1068:
1069: if (pdata->bFontSubstitution)
1070: {
1071:
1072: pwstrString = pwsz;
1073:
1074: // output the first character of the string, then
1075: // set the flag stating that we have actually
1076: // sent out a character. this prevents us from
1077: // setting the flag within the loop.
1078:
1079: if (!(RemapUnicodeChar(pdev, pwstrString++, pstro,
1080: flAccel, bString, pdata)))
1081: {
1082: RIP("PSCRIPT!DrawGlyphs: RemapUnicodeChar failed.\n");
1083: return(FALSE);
1084: }
1085:
1086: // set the flag stating that we have actually printed
1087: // a character.
1088:
1089: bString = TRUE;
1090: cGlyphs--;
1091:
1092: while (cGlyphs--)
1093: {
1094: if (!(RemapUnicodeChar(pdev, pwstrString++, pstro,
1095: flAccel, bString, pdata)))
1096: {
1097: RIP("PSCRIPT!DrawGlyphs: RemapUnicodeChar failed.\n");
1098: return(FALSE);
1099: }
1100:
1101: // point to the next character.
1102:
1103: pgp++;
1104: }
1105: }
1106: else
1107: {
1108: // output the first character of the string, then
1109: // set the flag stating that we have actually
1110: // sent out a character. this prevents us from
1111: // setting the flag within the loop.
1112:
1113: if (!(RemapDeviceChar(pdev, (CHAR *)&pgp->hg, pstro, flAccel,
1114: bString, pdata)))
1115: {
1116: RIP("PSCRIPT!DrawGlyphs: RemapDeviceChar failed.\n");
1117: return(FALSE);
1118: }
1119:
1120: // set the flag stating that we have actually printed
1121: // a character.
1122:
1123: bString = TRUE;
1124: cGlyphs--;
1125:
1126: // point to the next character.
1127:
1128: pgp++;
1129:
1130: while (cGlyphs--)
1131: {
1132: if (!(RemapDeviceChar(pdev, (CHAR *)&pgp->hg, pstro, flAccel,
1133: bString, pdata)))
1134: {
1135: RIP("PSCRIPT!DrawGlyphs: RemapDeviceChar failed.\n");
1136: return(FALSE);
1137: }
1138:
1139: // point to the next character.
1140:
1141: pgp++;
1142: }
1143: }
1144: }
1145: else // must be a GDI font.
1146: {
1147: // get a pointer to our downloaded font structure for this
1148: // font.
1149:
1150: pDLFont = pdev->cgs.pDLFonts;
1151:
1152: for (i = 0; i < pdev->iDLFonts; i++)
1153: {
1154: // is this entry the one we are looking for?
1155:
1156:
1157: if (pDLFont->iUniq == pfo->iUniq)
1158: break;
1159:
1160: pDLFont++;
1161: }
1162:
1163: // in the GDI font case, bString simply means we have
1164: // begun a string, not necessaryly output a character.
1165:
1166: bString = TRUE;
1167:
1168: while (cGlyphs--)
1169: {
1170: if (!(RemapGDIChar(pdev, pstro, pgp, pDLFont, &bString,
1171: flAccel, pdata)))
1172: {
1173: RIP("PSCRIPT!DrawGlyphs: RemapGDIChar failed.\n");
1174: return(FALSE);
1175: }
1176:
1177: // point to the next character.
1178:
1179: pgp++;
1180: }
1181: }
1182:
1183: if (bString)
1184: ps_show(pdev, pstro, flAccel, pdata);
1185: }
1186: }
1187:
1188: return(TRUE);
1189: }
1190:
1191:
1192: //--------------------------------------------------------------------
1193: // BOOL RemapDeviceChar(pdev, pChar, pstro, flAccel, bString, pdata)
1194: // PDEVDATA pdev;
1195: // PCHAR pChar;
1196: // STROBJ *pstro;
1197: // FLONG flAccel;
1198: // BOOL bString;
1199: // TEXTDATA *pdata;
1200: //
1201: // This routine is passed a pointer to a PostScript character code.
1202: // This routine will output the proper string to the printer, representing
1203: // the specified character code. '(', ')' and '\' are preceded by a
1204: // backslash. Characters which do not require a font remapping are
1205: // output directly. All other characters are output with there octal
1206: // representation of their character code.
1207: //
1208: // Return:
1209: // This routine returns TRUE for success, FALSE for failure.
1210: //
1211: // History:
1212: // 26-Apr-1991 -by- Kent Settle (kentse)
1213: // Wrote it.
1214: // 14-Nov-1991 -by- Kent Settle [kentse]
1215: // re-wrote it (got rid of text buffer).
1216: //--------------------------------------------------------------------
1217:
1218: BOOL RemapDeviceChar(pdev, pChar, pstro, flAccel, bString, pdata)
1219: PDEVDATA pdev;
1220: PCHAR pChar;
1221: STROBJ *pstro;
1222: FLONG flAccel;
1223: BOOL bString;
1224: TEXTDATA *pdata;
1225: {
1226: PUCMap pmap;
1227: BYTE jChar;
1228: BOOL bFound;
1229: CHAR Buffer[4];
1230: CHAR *pBuffer;
1231:
1232: // format each character for output to the printer.
1233:
1234: pBuffer = Buffer;
1235:
1236: switch(*pChar)
1237: {
1238: case '(':
1239: case ')':
1240: case '\\':
1241: // precede each of the following characters with a backslash,
1242: // then output to printer.
1243:
1244: *pBuffer++ = '\\';
1245: *pBuffer = *pChar;
1246: if (!bPSWrite(pdev, Buffer, 2))
1247: {
1248: RIP("PSCRIPT!RemapDeviceChar: bPSWrite failed.\n");
1249: return(FALSE);
1250: }
1251: break;
1252:
1253: default:
1254: // at this point we should check to see if the high
1255: // bit of the usPSValue in mapping.h is set. if it
1256: // is, remap the font, then output character. otherwise,
1257: // just output character.
1258:
1259: // get local pointer to mapping table for current font.
1260:
1261: pmap = pdev->cgs.pmap;
1262:
1263: // assume character not found in font.
1264:
1265: bFound = FALSE;
1266:
1267: while (pmap->szChar)
1268: {
1269: // search for the matching code in mapping.h. remember
1270: // that the high bit is used to indicate the font needs
1271: // to be remapped. so ignore the high bit while checking
1272: // for a character match.
1273:
1274: if (*pChar == (CHAR)pmap->usPSValue)
1275: {
1276: bFound = TRUE;
1277:
1278: // now check the high bit of the character code in
1279: // mapping.h. if it is set, we need to remap the
1280: // font for this character.
1281:
1282: jChar = *pChar;
1283:
1284: if ((pmap->usPSValue & 0x8000) || (jChar > 0x7F))
1285: {
1286: if (pmap->usPSValue & 0x8000)
1287: {
1288: // remap the font here.
1289:
1290: RemapFont(pdev, pstro, flAccel, bString, pdata);
1291: }
1292:
1293: // we have an extended character. convert the
1294: // non-printable ASCII to backslash octal, and
1295: // output to printer.
1296:
1297: *pBuffer++ = '\\';
1298: *pBuffer++ = (BYTE)((jChar >> 6) + '0');
1299: jChar &= 63;
1300: *pBuffer++ = (BYTE)((jChar >> 3) + '0');
1301: *pBuffer = (BYTE)((jChar & 7) + '0');
1302:
1303: if (!bPSWrite(pdev, Buffer, 4))
1304: {
1305: RIP("PSCRIPT!RemapDeviceChar: bPSWrite failed.\n");
1306: return(FALSE);
1307: }
1308: }
1309: else
1310: {
1311: // simply write out the character.
1312:
1313: *pBuffer = *pChar;
1314:
1315: if (!bPSWrite(pdev, Buffer, 1))
1316: {
1317: RIP("PSCRIPT!RemapDeviceChar: bPSWrite failed.\n");
1318: return(FALSE);
1319: }
1320: }
1321:
1322: break;
1323: }
1324:
1325: // point to the next character in mapping.h.
1326:
1327: pmap++;
1328: } // while.
1329:
1330: // if the character was not found in the font, output
1331: // a period.
1332:
1333: if (!bFound)
1334: {
1335: *pBuffer = '.';
1336:
1337: if (!bPSWrite(pdev, Buffer, 1))
1338: {
1339: RIP("PSCRIPT!RemapDeviceChar: bPSWrite failed.\n");
1340: return(FALSE);
1341: }
1342: }
1343:
1344: break;
1345: } // switch.
1346:
1347: return(TRUE);
1348: }
1349:
1350:
1351: //--------------------------------------------------------------------
1352: // BOOL RemapUnicodeChar(pdev, pWChar, pstro, flAccel, bString, pdata)
1353: // PDEVDATA pdev;
1354: // PWCHAR pWChar;
1355: // STROBJ *pstro;
1356: // FLONG flAccel;
1357: // BOOL bString;
1358: // TEXTDATA *pdata;
1359: //
1360: // This routine is passed a pointer to a UNICODE character code.
1361: // This routine will output the proper string to the printer, representing
1362: // the specified character code. '(', ')' and '\' are preceded by a
1363: // backslash. Characters which do not require a font remapping are
1364: // output directly. All other characters are output with there octal
1365: // representation of their character code.
1366: //
1367: // Return:
1368: // This routine returns TRUE for success, FALSE for failure.
1369: //
1370: // History:
1371: // 27-Sep-1992 -by- Kent Settle (kentse)
1372: // Wrote it.
1373: //--------------------------------------------------------------------
1374:
1375: BOOL RemapUnicodeChar(pdev, pWChar, pstro, flAccel, bString, pdata)
1376: PDEVDATA pdev;
1377: PWCHAR pWChar;
1378: STROBJ *pstro;
1379: FLONG flAccel;
1380: BOOL bString;
1381: TEXTDATA *pdata;
1382: {
1383: PUCMap pmap;
1384: BYTE jChar;
1385: BOOL bFound;
1386: CHAR Buffer[4];
1387: CHAR *pBuffer;
1388: CHAR *pChar;
1389:
1390: // begin by finding the UNICODE character code in our mapping table.
1391:
1392: pmap = pdev->cgs.pmap;
1393:
1394: // assume character is NOT found in the font.
1395:
1396: bFound = FALSE;
1397:
1398: while (pmap->szChar)
1399: {
1400: if (*pWChar == pmap->usUCValue)
1401: {
1402: bFound = TRUE;
1403: break;
1404: }
1405:
1406: // this was not the character we wanted, check the next one.
1407:
1408: pmap++;
1409: }
1410:
1411: // if the character was not found, output a period.
1412:
1413: pBuffer = Buffer;
1414:
1415: if (!bFound)
1416: {
1417: *pBuffer = '.';
1418:
1419: if (!bPSWrite(pdev, Buffer, 1))
1420: {
1421: RIP("PSCRIPT!RemapUnicodeChar: bPSWrite failed.\n");
1422: return(FALSE);
1423: }
1424:
1425: return(TRUE);
1426: }
1427:
1428: // now that we have found the UNICODE character code, get the
1429: // corresponding PostScript character code.
1430:
1431: pChar = (CHAR *)&pmap->usPSValue;
1432:
1433: // output the character to the printer in its proper format.
1434:
1435: switch(*pChar)
1436: {
1437: case '(':
1438: case ')':
1439: case '\\':
1440: // precede each of the following characters with a backslash,
1441: // then output to printer.
1442:
1443: *pBuffer++ = '\\';
1444: *pBuffer = *pChar;
1445: if (!bPSWrite(pdev, Buffer, 2))
1446: {
1447: RIP("PSCRIPT!RemapUnicodeChar: bPSWrite failed.\n");
1448: return(FALSE);
1449: }
1450: break;
1451:
1452: default:
1453: // at this point we should check to see if the high
1454: // bit of the usPSValue in mapping.h is set. if it
1455: // is, remap the font, then output character. otherwise,
1456: // just output character.
1457:
1458: jChar = *pChar;
1459:
1460: if ((pmap->usPSValue & 0x8000) || (jChar > 0x7F))
1461: {
1462: if (pmap->usPSValue & 0x8000)
1463: {
1464: // remap the font here.
1465:
1466: RemapFont(pdev, pstro, flAccel, bString, pdata);
1467: }
1468:
1469: // we have an extended character. convert the
1470: // non-printable ASCII to backslash octal, and
1471: // output to printer.
1472:
1473: *pBuffer++ = '\\';
1474: *pBuffer++ = (BYTE)((jChar >> 6) + '0');
1475: jChar &= 63;
1476: *pBuffer++ = (BYTE)((jChar >> 3) + '0');
1477: *pBuffer = (BYTE)((jChar & 7) + '0');
1478:
1479: if (!bPSWrite(pdev, Buffer, 4))
1480: {
1481: RIP("PSCRIPT!RemapUnicodeChar: bPSWrite failed.\n");
1482: return(FALSE);
1483: }
1484: }
1485: else
1486: {
1487: // simply write out the character.
1488:
1489: *pBuffer = *pChar;
1490:
1491: if (!bPSWrite(pdev, Buffer, 1))
1492: {
1493: RIP("PSCRIPT!RemapUnicodeChar: bPSWrite failed.\n");
1494: return(FALSE);
1495: }
1496: }
1497: } // switch
1498:
1499: return(TRUE);
1500: }
1501:
1502:
1503: //--------------------------------------------------------------------
1504: // BOOL RemapGDIChar(pdev, pstro, pgp, pDLFont, pbString, flAccel, pdata)
1505: // PDEVDATA pdev;
1506: // STROBJ *pstro;
1507: // GLYPHPOS *pgp;
1508: // DLFONT *pDLFont;
1509: // BOOL *pbString;
1510: // FLONG flAccel;
1511: // TEXTDATA *pdata;
1512: //
1513: // This routine is passed a pointer to a GLYPHPOS structure.
1514: // This routine will output the proper string to the printer, representing
1515: // the specified character code. '(', ')' and '\' are preceded by a
1516: // backslash. Characters which are located within the downloaded font are
1517: // output directly. Any other character will cause the current string
1518: // to be closed, and a show command to be issued. Then the current character
1519: // will be drawn, either by bitblt or a path.
1520: //
1521: // Return:
1522: // This routine returns TRUE for success, FALSE for failure.
1523: //
1524: // History:
1525: // 27-Mar-1992 -by- Kent Settle (kentse)
1526: // Wrote it.
1527: //--------------------------------------------------------------------
1528:
1529: BOOL RemapGDIChar(pdev, pstro, pgp, pDLFont, pbString, flAccel, pdata)
1530: PDEVDATA pdev;
1531: STROBJ *pstro;
1532: GLYPHPOS *pgp;
1533: DLFONT *pDLFont;
1534: BOOL *pbString;
1535: FLONG flAccel;
1536: TEXTDATA *pdata;
1537: {
1538: BOOL bFound;
1539: CHAR Buffer[4];
1540: CHAR *pBuffer;
1541: DWORD i;
1542: HGLYPH hglyph;
1543: HGLYPH *phg;
1544: BYTE jCurrent;
1545:
1546: // point to internal buffer to build character code into.
1547:
1548: pBuffer = Buffer;
1549:
1550: // get the handle for the current glyph. then find the corresponding
1551: // character code, as defined in the downloaded font.
1552:
1553: bFound = FALSE;
1554: hglyph = pgp->hg;
1555:
1556: #if DBG
1557: if (hglyph == HGLYPH_INVALID)
1558: {
1559: RIP("PSCRIPT!RemapGDIChar: hglyph is zero, we're hosed.\n");
1560: return(FALSE);
1561: }
1562: #endif
1563:
1564: phg = pDLFont->phgVector;
1565:
1566: for (i = 0; i < pDLFont->cGlyphs; i++)
1567: {
1568: if (*phg == hglyph)
1569: {
1570: bFound = TRUE;
1571: break;
1572: }
1573:
1574: phg++;
1575: }
1576:
1577: // i contains the character code for the printer, assuming it was
1578: // found in the downloaded font.
1579:
1580: jCurrent = (BYTE)i;
1581:
1582: // if the character was found in the downloaded font, we will be
1583: // outputting it as part of a string. otherwise, we will be drawing
1584: // it via imagemask or as a path.
1585:
1586: if (bFound)
1587: {
1588: // the character is part of the downloaded font. so output the
1589: // character code as part of a string. we must, however, check
1590: // to see if a string already exists to add it to, or if we must
1591: // start a new one.
1592:
1593: if (*pbString == FALSE)
1594: {
1595: // we are not in the middle of a string, so we must begin
1596: // a new one.
1597:
1598: ps_moveto(pdev, &pgp->ptl);
1599:
1600: // output a left paren to open the string.
1601:
1602: PrintString(pdev, "(");
1603: }
1604:
1605: // we are now guaranteed to be in the middle of a string, so
1606: // simply output the character code.
1607:
1608: switch(jCurrent)
1609: {
1610: case '(':
1611: case ')':
1612: case '\\':
1613: // precede each of the following characters with a backslash,
1614: // then output to printer.
1615:
1616: *pBuffer++ = '\\';
1617: *pBuffer = jCurrent;
1618: if (!bPSWrite(pdev, Buffer, 2))
1619: {
1620: RIP("PSCRIPT!RemapGDIChar: bPSWrite failed.\n");
1621: return(FALSE);
1622: }
1623: break;
1624:
1625: default:
1626: // if the character code is within the printable ASCII
1627: // range, simply write out the character. otherwise,
1628: // we need to output the three digit octal character code.
1629:
1630: if ((jCurrent >= 0x20) && (jCurrent <= 0x7F))
1631: {
1632: if (!bPSWrite(pdev, &jCurrent, 1))
1633: {
1634: RIP("PSCRIPT!RemapGDIChar: bPSWrite failed.\n");
1635: return(FALSE);
1636: }
1637: }
1638: else
1639: {
1640: // convert the non-printable ASCII to backslash octal,
1641: // and output to the printer.
1642:
1643: *pBuffer++ = '\\';
1644: *pBuffer++ = (BYTE)((jCurrent >> 6) + '0');
1645: jCurrent &= 63;
1646: *pBuffer++ = (BYTE)((jCurrent >> 3) + '0');
1647: *pBuffer = (BYTE)((jCurrent & 7) + '0');
1648:
1649: if (!bPSWrite(pdev, Buffer, 4))
1650: {
1651: RIP("PSCRIPT!RemapGDIChar: bPSWrite failed.\n");
1652: return(FALSE);
1653: }
1654: }
1655: break;
1656: } // end of switch.
1657:
1658: // set the flag stating that we are now within a string.
1659:
1660: *pbString = TRUE;
1661: }
1662: else // character not found in downloaded font.
1663: {
1664: // the character is NOT part of the downloaded font. so we must
1665: // actually draw the character. we must, however, check to see
1666: // if an open string already exists in the printer, and close it
1667: // if it does.
1668:
1669: if (*pbString)
1670: {
1671: // we are in the middle of a string, so we must end it before
1672: // we can draw the current character.
1673:
1674: ps_show(pdev, pstro, flAccel, pdata);
1675: }
1676:
1677: // we are now ready to draw the character.
1678:
1679: //!!! for now only bitmap fonts are supported. we will support vector
1680: //!!! fonts whenever the engine does. -kentse.
1681:
1682: CharBitmap(pdev, pgp);
1683:
1684: // set the flag stating that we are now NOT within a string.
1685:
1686: *pbString = FALSE;
1687: }
1688:
1689: return(TRUE);
1690: }
1691:
1692: //--------------------------------------------------------------------
1693: // BOOL SelectFont(pdev, pfo, pdata)
1694: // PDEVDATA pdev;
1695: // FONTOBJ *pfo;
1696: // TEXTDATA *pdata;
1697: //
1698: // This routine selects the font specified in the FONTOBJ, and selects
1699: // it as the current font in the printer. If the specified font is
1700: // already the current font in the printer, then this routine does
1701: // nothing.
1702: //
1703: // History:
1704: // 15-Jul-1992 -by- Kent Settle (kentse)
1705: // Added Font Substitution support.
1706: // 27-Feb-1992 -by- Kent Settle (kentse)
1707: // Added support for downloading, ie caching, GDI fonts.
1708: // 20-Feb-1992 -by- Kent Settle (kentse)
1709: // Added support for softfonts.
1710: // 26-Apr-1991 -by- Kent Settle (kentse)
1711: // Wrote it.
1712: //--------------------------------------------------------------------
1713:
1714: BOOL SelectFont(pdev, pfo, pdata)
1715: PDEVDATA pdev;
1716: FONTOBJ *pfo;
1717: TEXTDATA *pdata;
1718: {
1719: PNTFM pntfm;
1720: BYTE *pSoftFont;
1721: DWORD cDownloadedFonts;
1722: DLFONT *pDLFont;
1723: PS_FIX psfxM11, psfxM12, psfxM21, psfxM22, psfxtmp;
1724: XFORM *pxform;
1725:
1726: // do not select the font in the printer if it is currently selected,
1727: // including the same point size.
1728:
1729: if (pfo->iUniq == pdev->cgs.lidFont)
1730: return(TRUE);
1731:
1732: // get the point size, and fill in the font xform.
1733:
1734: pdev->cgs.psfxScaleFactor = GetPointSize(pdev, pfo, &pdev->cgs.FontXform);
1735:
1736: #if DBG
1737: if (pdev->cgs.psfxScaleFactor == 0)
1738: RIP("PSCRIPT!SelectFont: Zero point size!\n");
1739: #endif
1740:
1741: // do not select the font into the printer if it is a GDI font that
1742: // we will not be caching. according to the DDI spec, if pfo->iUniq
1743: // is zero, the GDI font should not be cached.
1744:
1745: if (!pdata->bDeviceFont && (pfo->iUniq == 0))
1746: {
1747: #if DBG
1748: DbgPrint("A non-cached GDI font made it to SelectFont, should it have?\n");
1749: #endif
1750: return(TRUE);
1751: }
1752:
1753: // select the proper font name for the new font. if this is a
1754: // device font, get the name from the NTFM structure. if this
1755: // is a GDI font that we are caching, we will create a name for
1756: // it at the time we download it to the printer.
1757:
1758: if (pdata->bDeviceFont)
1759: {
1760: // get the font metrics for the specified font.
1761:
1762: pntfm = pdev->pfmtable[pdata->iFace - 1].pntfm;
1763:
1764: // if the font is a softfont, and it has not yet been downloaded,
1765: // download it.
1766:
1767: if ((pdata->iFace > pdev->cDeviceFonts) &&
1768: !((BYTE)pdev->cgs.pSFArray[pdata->iFace >> 3] &
1769: (BYTE)(1 << (pdata->iFace & 0x07))))
1770: {
1771: pSoftFont = (BYTE *)pntfm + pntfm->loSoftFont;
1772:
1773: // if we have reached our downloaded font threshold, then
1774: // we will surround ever textout call with a save/restore.
1775:
1776: cDownloadedFonts = min(pdev->cgs.cDownloadedFonts, pdev->iDLFonts);
1777:
1778: if (cDownloadedFonts == pdev->iDLFonts)
1779: {
1780: ps_save(pdev, FALSE);
1781: pdev->cgs.dwFlags |= CGS_DLFONTTHRESHOLD;
1782: }
1783:
1784: if (!bPSWrite(pdev, pSoftFont, pntfm->cjSoftFont))
1785: {
1786: RIP("PSCRIPT!SelectFont: downloading of softfont failed.\n");
1787: return(FALSE);
1788: }
1789:
1790: // set the bit saying this font has been downloaded.
1791:
1792: (BYTE)pdev->cgs.pSFArray[pdata->iFace >> 3] |=
1793: (BYTE)(1 << (pdata->iFace & 0x07));
1794:
1795: // if we have hit our limit of Fonts we can download, simply overwrite
1796: // the last one with the new one. this is to try to conserve on
1797: // memory consumption.
1798:
1799: pDLFont = pdev->cgs.pDLFonts;
1800: pDLFont += cDownloadedFonts;
1801:
1802: pDLFont->iFace = pdata->iFace;
1803: pDLFont->iUniq = pfo->iUniq;
1804: pDLFont->cGlyphs = 0;
1805: pDLFont->phgVector = NULL;
1806:
1807: pdev->cgs.cDownloadedFonts++;
1808: }
1809:
1810: // select the font in the printer.
1811:
1812: strcpy(pdev->cgs.szFont, (char *)pntfm + pntfm->loszFontName);
1813: }
1814: else // must be a GDI font we will be caching.
1815: {
1816: //!!! the engine is not ready for outline fonts yet!!! -kentse.
1817: #if 0
1818: // if this font has not yet been downloaded to the printer,
1819: // do it now.
1820:
1821: if (pfo->flFontType & TRUETYPE_FONTTYPE)
1822: {
1823: // determine the point size.
1824:
1825: ulPointSize = (ETOL(pdev->cgs.FontXform.eM22 * 72000) /
1826: pdev->psdm.dm.dmPrintQuality);
1827:
1828: if (ulPointSize < 10)
1829: DownloadBitmapFont(pdev, pfo);
1830: else
1831: DownloadOutlineFont(pdev, pfo);
1832: }
1833: else if (pfo->flFontType & RASTER_FONTTYPE)
1834: DownloadBitmapFont(pdev, pfo);
1835: #endif
1836: if ( (pfo->flFontType & TRUETYPE_FONTTYPE) ||
1837: (pfo->flFontType & RASTER_FONTTYPE) )
1838: DownloadBitmapFont(pdev, pfo);
1839: else
1840: {
1841: RIP("PSCRIPT!SelectFont: invalid pfo->flFontType.\n");
1842: return(FALSE);
1843: }
1844: }
1845:
1846: // select the proper font, depending on whether or not the
1847: // font in question has been reencoded. also, output a scalefont
1848: // command if only scaling is ocurring, otherwise output a
1849: // makefont command.
1850:
1851: #if 0
1852: PrintPSFIX(pdev, 1, pdev->cgs.psfxScaleFactor);
1853:
1854: if (QueryFontRemap(pdev, pfo->iUniq))
1855: PrintString(pdev, " /_");
1856: else
1857: PrintString(pdev, " /");
1858:
1859: PrintString(pdev, pdev->cgs.szFont);
1860: PrintString(pdev, " SF\n");
1861: #endif
1862:
1863: pxform = &pdev->cgs.FontXform;
1864:
1865: if
1866: (
1867: ((pxform->eM11 == pxform->eM22) &&
1868: (pxform->eM12 == 0) &&
1869: (pxform->eM21 == 0) &&
1870: !((*((ULONG *)&pxform->eM11)) & 0x80000000)) // if positive
1871: ||
1872: ((pfo->flFontType & TRUETYPE_FONTTYPE) && !pdata->bFontSubstitution) // all scaling done already by tt driver
1873: )
1874: {
1875: PrintPSFIX(pdev, 1, pdev->cgs.psfxScaleFactor);
1876:
1877: if (QueryFontRemap(pdev, pfo->iUniq))
1878: PrintString(pdev, " /_");
1879: else
1880: PrintString(pdev, " /");
1881:
1882: PrintString(pdev, pdev->cgs.szFont);
1883: PrintString(pdev, " SF\n");
1884: }
1885: else
1886: {
1887: // normalize the font transform by the emheight;
1888:
1889: psfxtmp = pdev->cgs.fwdEmHeight * PS_FIX_RESOLUTION;
1890:
1891: psfxM11 = (LONG)((pdev->cgs.FontXform.eM11 * (FLOAT)psfxtmp) /
1892: pdev->psdm.dm.dmPrintQuality);
1893: psfxM12 = (LONG)((pdev->cgs.FontXform.eM12 * (FLOAT)psfxtmp) /
1894: pdev->psdm.dm.dmPrintQuality);
1895: psfxM21 = (LONG)((pdev->cgs.FontXform.eM21 * (FLOAT)psfxtmp) /
1896: pdev->psdm.dm.dmPrintQuality);
1897: psfxM22 = (LONG)((pdev->cgs.FontXform.eM22 * (FLOAT)psfxtmp) /
1898: pdev->psdm.dm.dmPrintQuality);
1899:
1900: PrintString(pdev, "[");
1901: PrintPSFIX(pdev, 6, psfxM11, -psfxM12, -psfxM21, psfxM22,0,0);
1902:
1903: if (QueryFontRemap(pdev, pfo->iUniq))
1904: PrintString(pdev, "] /_");
1905: else
1906: PrintString(pdev, "] /");
1907:
1908: PrintString(pdev, pdev->cgs.szFont);
1909: PrintString(pdev, " MF\n");
1910: }
1911:
1912: // update the font in our current graphics state.
1913:
1914: pdev->cgs.lidFont = pfo->iUniq;
1915:
1916: // if we have a device font, point to the appropriate mapping table
1917: // in mapping.h.
1918:
1919: if (pdata->bDeviceFont)
1920: {
1921: if (!strcmp((char *)pntfm + pntfm->loszFontName, "Symbol"))
1922: pdev->cgs.pmap = SymbolMap;
1923: else if (!strcmp((char *)pntfm + pntfm->loszFontName, "ZapfDingbats"))
1924: pdev->cgs.pmap = DingbatsMap;
1925: else
1926: pdev->cgs.pmap = LatinMap;
1927: }
1928:
1929: return(TRUE);
1930: }
1931:
1932:
1933: //--------------------------------------------------------------------
1934: // VOID RemapFont(pdev, pstro, flAccel, bString, pdata)
1935: // PDEVDATA pdev;
1936: // STROBJ *pstro;
1937: // FLONG flAccel;
1938: // BOOL bString;
1939: // TEXTDATA *pdata;
1940: //
1941: // This routine is only called if we have a character which does not
1942: // have the standard PostScript character code. This is determined
1943: // by checking the high bit of the usPSValue in the proper table in
1944: // mapping.h. If necessary, this routine will download a new
1945: // encoding vector. It will then reencode the current font to the
1946: // new encoding vector.
1947: //
1948: // History:
1949: // 12-Sep-1991 -by- Kent Settle (kentse)
1950: // Wrote it.
1951: //--------------------------------------------------------------------
1952:
1953: VOID RemapFont(pdev, pstro, flAccel, bString, pdata)
1954: PDEVDATA pdev;
1955: STROBJ *pstro;
1956: FLONG flAccel;
1957: BOOL bString;
1958: TEXTDATA *pdata;
1959: {
1960: int i;
1961: PSZ *pszEncode;
1962: PSZ pszVector;
1963: int cbLength;
1964: PUCMap pmap;
1965: BOOL bFound;
1966: FLONG flEncoding;
1967: BOOL bRemapDone = FALSE;
1968: XFORM *pxform;
1969: PS_FIX psfxM11, psfxM12, psfxM21, psfxM22, psfxtmp;
1970:
1971: //!!! All this font remapping stuff gets blown away by a gsave/grestore
1972: //!!! which is done from DrvTextout when clipping. Perhaps move flags from
1973: //!!! CGS to PDEV.
1974:
1975: // if the font remapping header has not been downloaded to the
1976: // printer, do it now. this header is sent at most once per job.
1977:
1978: if (!(pdev->dwFlags & PDEV_FONTREDEFINED))
1979: {
1980: // we are in the middle of outputting a string. close
1981: // the current string and output a show command to the
1982: // printer, output the remapping, then begin a new string.
1983:
1984: ps_show(pdev, pstro, flAccel, pdata);
1985: bRemapDone = TRUE;
1986:
1987: pszEncode = apszRemapCode;
1988: while (*pszEncode)
1989: {
1990: PrintString(pdev, (PSZ)*pszEncode++);
1991: PrintString(pdev, "\n");
1992: }
1993:
1994: pdev->dwFlags |= PDEV_FONTREDEFINED;
1995: }
1996:
1997: // select the proper encoding vector to download.
1998:
1999: if (pdev->cgs.pmap == SymbolMap)
2000: {
2001: pszVector = "SYMENC";
2002: flEncoding = PDEV_SYMENCODED;
2003: }
2004: else if (pdev->cgs.pmap == DingbatsMap)
2005: {
2006: pszVector = "DINGENC";
2007: flEncoding = PDEV_DINGENCODED;
2008: }
2009: else
2010: {
2011: pszVector = "LATENC";
2012: flEncoding = PDEV_LATINENCODED;
2013: }
2014:
2015: // define the new font encoding if it has not already been done.
2016:
2017: if ((pdev->dwFlags & flEncoding) == 0)
2018: {
2019: if (!bRemapDone)
2020: {
2021: // we are in the middle of outputting a string. close
2022: // the current string and output a show command to the
2023: // printer, output the remapping, then begin a new string.
2024:
2025: ps_show(pdev, pstro, flAccel, pdata);
2026: bRemapDone = TRUE;
2027: }
2028:
2029: // download the new encoding vector. just to make things readable,
2030: // let's limit the line length.
2031:
2032: cbLength = 0;
2033:
2034: PrintString(pdev, "/");
2035: PrintString(pdev, pszVector);
2036: PrintString(pdev, " [0\n");
2037:
2038: // PostScript fonts containg 256 characters. for each character,
2039: // do a lookup in the appropriate mapping table in mapping.h to
2040: // get the ASCII name of the character to output in the encoding
2041: // vector. if the character is not found in the encoding vector,
2042: // output ".notdef" for that character.
2043:
2044: for (i = 0; i < 256; i++)
2045: {
2046: if (cbLength > MAX_LINE_LENGTH)
2047: {
2048: // skip to the next line.
2049:
2050: PrintString(pdev, "\n");
2051: cbLength = 0;
2052: }
2053:
2054: // get local pointer to mapping table for current font.
2055:
2056: pmap = pdev->cgs.pmap;
2057:
2058: // assume character not found in font.
2059:
2060: bFound = FALSE;
2061:
2062: while (pmap->szChar)
2063: {
2064: // search for the matching code in mapping.h. remember
2065: // that the high bit is used to indicate the font needs
2066: // to be remapped. so ignore the high bit while checking
2067: // for a character match.
2068:
2069: if ((CHAR)i == (CHAR)pmap->usPSValue)
2070: {
2071: bFound = TRUE;
2072:
2073: PrintString(pdev, "/");
2074: PrintString(pdev, pmap->szChar);
2075:
2076: cbLength += (strlen(pmap->szChar) + 1);
2077: break;
2078: }
2079:
2080: // point to the next character in mapping.h.
2081:
2082: pmap++;
2083: } // while.
2084:
2085: // if the character was not found in the font, output .notdef.
2086:
2087: if (!bFound)
2088: {
2089: PrintString(pdev, "/.notdef");
2090: cbLength += 8;
2091: }
2092: }
2093:
2094: // we are done downloading the encoding vector.
2095:
2096: PrintString(pdev, "\n]def\n");
2097:
2098: // mark that this encoding vector is now defined in the printer.
2099:
2100: pdev->dwFlags |= flEncoding;
2101: }
2102:
2103: // output the PostScript commands to reencode the current font
2104: // using the proper encoding vector, if the current font has
2105: // not already been reencoded.
2106:
2107: if (!QueryFontRemap(pdev, pdev->cgs.lidFont))
2108: {
2109: if (!bRemapDone)
2110: {
2111: // we are in the middle of outputting a string. close
2112: // the current string and output a show command to the
2113: // printer, output the remapping, then begin a new string.
2114:
2115: ps_show(pdev, pstro, flAccel, pdata);
2116: bRemapDone = TRUE;
2117: }
2118:
2119: PrintString(pdev, pszVector);
2120: PrintString(pdev, " /_");
2121: PrintString(pdev, pdev->cgs.szFont);
2122: PrintString(pdev, " /");
2123: PrintString(pdev, pdev->cgs.szFont);
2124: PrintString(pdev, " reencode\n");
2125:
2126: // select the newly reencoded font.
2127:
2128: pxform = &pdev->cgs.FontXform;
2129:
2130: if
2131: (
2132: (pxform->eM11 == pxform->eM22) &&
2133: (pxform->eM12 == 0) &&
2134: (pxform->eM21 == 0) &&
2135: !((*((ULONG *)&pxform->eM11)) & 0x80000000) // if positive
2136: )
2137: {
2138: PrintPSFIX(pdev, 1, pdev->cgs.psfxScaleFactor);
2139: PrintString(pdev, " /_");
2140: PrintString(pdev, pdev->cgs.szFont);
2141: PrintString(pdev, " SF\n");
2142: }
2143: else
2144: {
2145: // normalize the font transform by the emheight;
2146:
2147: psfxtmp = pdev->cgs.fwdEmHeight * PS_FIX_RESOLUTION;
2148:
2149: psfxM11 = (LONG)((pdev->cgs.FontXform.eM11 * (FLOAT)psfxtmp) /
2150: pdev->psdm.dm.dmPrintQuality);
2151: psfxM12 = (LONG)((pdev->cgs.FontXform.eM12 * (FLOAT)psfxtmp) /
2152: pdev->psdm.dm.dmPrintQuality);
2153: psfxM21 = (LONG)((pdev->cgs.FontXform.eM21 * (FLOAT)psfxtmp) /
2154: pdev->psdm.dm.dmPrintQuality);
2155: psfxM22 = (LONG)((pdev->cgs.FontXform.eM22 * (FLOAT)psfxtmp) /
2156: pdev->psdm.dm.dmPrintQuality);
2157:
2158: PrintString(pdev, "[");
2159: PrintPSFIX(pdev, 6, psfxM11, -psfxM12, -psfxM21, psfxM22,0,0);
2160:
2161: PrintString(pdev, "] /_");
2162: PrintString(pdev, pdev->cgs.szFont);
2163: PrintString(pdev, " MF\n");
2164: }
2165:
2166: // set a flag saying that the current font has been reencoded.
2167:
2168: SetFontRemap(pdev, pdev->cgs.lidFont);
2169: }
2170:
2171: // if any remapping was done, start a new string.
2172:
2173: if (bRemapDone)
2174: {
2175: if ((flAccel == 0) || (flAccel & SO_FLAG_DEFAULT_PLACEMENT))
2176: PrintString(pdev, "(");
2177: else if ((flAccel & SO_HORIZONTAL) || (flAccel & SO_VERTICAL))
2178: {
2179: // if we have a vertical or horizontal, non default spacing,
2180: // case, and we have just remapped a font, and we have actuall
2181: // printed at least one character within the string, then we need
2182: // to get rid of the with between the last character printed, then
2183: // get the current position on the stack before we begin our
2184: // string.
2185:
2186: if (pdata->bJustification)
2187: {
2188: // if we did the justification calculations and found
2189: // that the justification widths were zero, do nothing
2190: // here.
2191:
2192: if ((pdata->ptSpace.x != 0) || (pdata->ptNonSpace.x != 0))
2193: {
2194: PrintPSFIX(pdev, 2, pdata->ptSpace.x, pdata->ptSpace.y);
2195: PrintString(pdev, " 8#040 ");
2196: PrintPSFIX(pdev, 2, pdata->ptNonSpace.x, pdata->ptNonSpace.y);
2197: PrintString(pdev, "\n");
2198: }
2199:
2200: PrintString(pdev, "(");
2201: }
2202: else if (bString)
2203: PrintString(pdev, "pop a (");
2204: else
2205: {
2206: if(pstro->cGlyphs != 1)
2207: PrintString(pdev, "a (");
2208: else
2209: PrintString(pdev, "(");
2210: }
2211: }
2212: }
2213: }
2214:
2215:
2216: //--------------------------------------------------------------------
2217: // VOID CharBitmap(pdev, pgp)
2218: // PDEVDATA pdev;
2219: // GLYPHPOS *pgp;
2220: //
2221: // This routine downloads the bitmap for the given character to
2222: // the printer.
2223: //
2224: // History:
2225: // 26-Sep-1991 -by- Kent Settle (kentse)
2226: // Wrote it.
2227: //--------------------------------------------------------------------
2228:
2229: VOID CharBitmap(pdev, pgp)
2230: PDEVDATA pdev;
2231: GLYPHPOS *pgp;
2232: {
2233: POINTPSFX ptpsfx;
2234: int cjWidth;
2235: int i;
2236: BYTE *pjBits;
2237: LONG cx, cy;
2238:
2239: // adjust the (x, y) coordinates to adjust for displacement of
2240: // character origin from bitmap origin.
2241:
2242: pgp->ptl.x += pgp->pgdf->pgb->ptlOrigin.x;
2243: pgp->ptl.y += pgp->pgdf->pgb->ptlOrigin.y;
2244:
2245: // position the image on the page, remembering to flip the image
2246: // from top to bottom.
2247:
2248: ptpsfx.x = X72DPI(pgp->ptl.x);
2249: ptpsfx.y = Y72DPI(pgp->ptl.y);
2250:
2251: // output PostScript user coordinates to the printer.
2252:
2253: PrintString(pdev, "save ");
2254: PrintPSFIX(pdev, 2, ptpsfx.x, ptpsfx.y);
2255: PrintString(pdev, " translate\n");
2256:
2257: // scale the image.
2258: //!!! I do not know how this ever worked if it did. [Bodind]
2259:
2260: // cx = pgp->pgdf->pgb->aj[0];
2261:
2262: // cy = pgp->pgdf->pgb->aj[1];
2263:
2264:
2265: cx = pgp->pgdf->pgb->sizlBitmap.cx;
2266: cy = pgp->pgdf->pgb->sizlBitmap.cy;
2267:
2268: ptpsfx.x = (cx * PS_FIX_RESOLUTION) / pdev->psdm.dm.dmPrintQuality;
2269: ptpsfx.y = (cy * PS_FIX_RESOLUTION) / pdev->psdm.dm.dmPrintQuality;
2270:
2271: PrintPSFIX(pdev, 2, ptpsfx.x, ptpsfx.y);
2272: PrintString(pdev, " scale\n");
2273:
2274: // output the image operator and the scan data. true means to
2275: // paint the '1' bits with the foreground color.
2276:
2277: PrintDecimal(pdev, 2, cx, cy);
2278: PrintString(pdev, " true [");
2279: PrintDecimal(pdev, 1, cx);
2280: PrintString(pdev, " 0 0 ");
2281: PrintDecimal(pdev, 1, -cy);
2282: PrintString(pdev, " 0 0]\n{<");
2283:
2284: // how wide is the destination in bytes? postscript bitmaps are padded
2285: // to 8bit boundaries.
2286:
2287: cjWidth = (cx + 7) >> 3;
2288:
2289: //!!! this seems to be wrong, do not know why it ever worked if it did
2290: //!!! [bodind]
2291: // pjBits = (BYTE *)&pgp->pgdf->pgb->aj[2];
2292:
2293:
2294: pjBits = pgp->pgdf->pgb->aj;
2295:
2296: for (i = 0; i < cy; i++)
2297: {
2298: // output each scanline to the printer.
2299:
2300: vHexOut(pdev, pjBits, cjWidth);
2301: pjBits += cjWidth;
2302: }
2303:
2304: PrintString(pdev, ">} im restore\n");
2305: }
2306:
2307:
2308: //--------------------------------------------------------------------
2309: // BOOL DownloadBitmapFont(pdev, pfo)
2310: // PDEVDATA pdev;
2311: // FONTOBJ *pfo;
2312: //
2313: // This routine downloads the font definition for the given bitmap font,
2314: // if it has not already been done. The font is downloaded as an
2315: // Adobe Type 3 font.
2316: //
2317: // This routine return TRUE if the font is successfully, or has already
2318: // been, downloaded to the printer. It returns FALSE if it fails.
2319: //
2320: // History:
2321: // 27-Feb-1992 -by- Kent Settle (kentse)
2322: // Wrote it.
2323: //--------------------------------------------------------------------
2324:
2325: BOOL DownloadBitmapFont(pdev, pfo)
2326: PDEVDATA pdev;
2327: FONTOBJ *pfo;
2328: {
2329: DLFONT *pDLFont;
2330: DWORD i, j;
2331: DWORD cDownloadedFonts;
2332: DWORD cGlyphs, cTmp;
2333: HGLYPH *phg;
2334: HGLYPH *phgSave;
2335: GLYPHDATA *pglyphdata;
2336: POINTL ptlTL, ptlBR, ptl1;
2337: PIFIMETRICS pifi;
2338: PS_FIX psfxXtrans, psfxYtrans;
2339: CHAR szFaceName[MAX_STRING];
2340: PSZ pszFaceName;
2341: PWSTR pwstr;
2342: LONG cjWidth;
2343: BYTE *pjBits;
2344: LONG EmHeight;
2345: XFORMOBJ *pxo;
2346: POINTFIX ptfx;
2347: PS_FIX psfxPointSize;
2348: XFORM fontxform;
2349:
2350: // search through our list of downloaded GDI fonts to see if the
2351: // current font has already been downloaded to the printer.
2352:
2353: pDLFont = pdev->cgs.pDLFonts;
2354:
2355: cDownloadedFonts = min(pdev->cgs.cDownloadedFonts, pdev->iDLFonts);
2356:
2357: for (i = 0; i < cDownloadedFonts; i++)
2358: {
2359: // is this entry the one we are looking for? simply return if so.
2360:
2361: if (pDLFont->iUniq == pfo->iUniq)
2362: {
2363: // update the fontname and size in our current graphics state.
2364:
2365: strcpy(pdev->cgs.szFont, pDLFont->strFont);
2366: pdev->cgs.lidFont = pDLFont->iUniq;
2367:
2368: return(TRUE);
2369: }
2370:
2371: pDLFont++;
2372: }
2373:
2374: // we did not find that this font has been downloaded yet, so we must
2375: // do it now.
2376:
2377: // if we have reached our downloaded font threshold, then
2378: // we will surround ever textout call with a save/restore.
2379:
2380: if (cDownloadedFonts >= pdev->iDLFonts)
2381: {
2382: ps_save(pdev, FALSE);
2383: pdev->cgs.dwFlags |= CGS_DLFONTTHRESHOLD;
2384: cDownloadedFonts = pdev->iDLFonts;
2385: }
2386:
2387: pDLFont = pdev->cgs.pDLFonts;
2388: pDLFont += cDownloadedFonts;
2389:
2390: memset(pDLFont, 0, sizeof(DLFONT));
2391:
2392: pDLFont->iFace = pfo->iFace;
2393: pDLFont->iUniq = pfo->iUniq;
2394:
2395: // if we have made it this far, we should simply be able to
2396: // download the font now.
2397:
2398: // we will be downloading an Adobe TYPE 3 font.
2399:
2400: // allocate a dictionary for the font.
2401:
2402: PrintString(pdev, "9 dict d begin\n");
2403:
2404: // set FontType to 3 indicating user defined font.
2405:
2406: PrintString(pdev, "/FontType 3 def\n");
2407:
2408: // allocate memory for and get the handles for each glyph of the font.
2409:
2410: if (!(cGlyphs = FONTOBJ_cGetAllGlyphHandles(pfo, NULL)))
2411: {
2412: RIP("PSCRIPT!DownloadBitmapFont: cGetAllGlyphHandles failed.\n");
2413: return(FALSE);
2414: }
2415:
2416: if (!(phg = (HGLYPH *)HeapAlloc(pdev->hheap, 0, sizeof(HGLYPH) * cGlyphs)))
2417: {
2418: RIP("PSCRIPT!DownloadBitmapFont: HeapAlloc failed.\n");
2419: return(FALSE);
2420: }
2421:
2422: phgSave = phg;
2423:
2424: cTmp = FONTOBJ_cGetAllGlyphHandles(pfo, phg);
2425:
2426: ASSERTPS(cTmp == cGlyphs, "PSCRIPT!DownloadBitmapFont: inconsistent cGlyphs\n");
2427:
2428: // how many characters will we define in this font?
2429: // keep in mind that we can only do 256 at a time.
2430: // remember to leave room for the .notdef character.
2431:
2432: cGlyphs = min(255, cGlyphs);
2433:
2434: // run through the array, looking at the bounding box for each
2435: // glyph, in order to create the bounding box for the entire
2436: // font.
2437:
2438: ptlTL.x = ADOBE_FONT_UNITS;
2439: ptlTL.y = ADOBE_FONT_UNITS;
2440: ptlBR.x = 0;
2441: ptlBR.y = 0;
2442:
2443: for (i = 0; i < cGlyphs; i++)
2444: {
2445: // get the GLYPHDATA structure for each glyph.
2446:
2447: if (!(cTmp = FONTOBJ_cGetGlyphs(pfo, FO_GLYPHBITS, 1, phg, (PVOID *)&pglyphdata)))
2448: {
2449: RIP("PSCRIPT!DownloadBitmapFont: cGetGlyphs failed.\n");
2450: HeapFree(pdev->hheap, 0, (PVOID)phgSave);
2451: return(FALSE);
2452: }
2453:
2454: ptlTL.x = min(ptlTL.x, pglyphdata->rclInk.left);
2455: ptlTL.y = min(ptlTL.y, pglyphdata->rclInk.top);
2456: ptlBR.x = max(ptlBR.x, pglyphdata->rclInk.right);
2457: ptlBR.y = max(ptlBR.y, pglyphdata->rclInk.bottom);
2458:
2459: // point to the next glyph handle.
2460:
2461: phg++;
2462: }
2463:
2464: // get the IFIMETRICS for the font.
2465:
2466: if (!(pifi = FONTOBJ_pifi(pfo)))
2467: {
2468: RIP("PSCRIPT!DownloadBitmapFont: pifi failed.\n");
2469: HeapFree(pdev->hheap, 0, (PVOID)phgSave);
2470: return(FALSE);
2471: }
2472:
2473: // get the Notional to Device transform. this is needed to
2474: // determine the point size.
2475:
2476: pxo = FONTOBJ_pxoGetXform(pfo);
2477:
2478: if (pxo == NULL)
2479: {
2480: RIP("PSCRIPT!DownloadBitmapFont: pxo == NULL.\n");
2481: return(FALSE);
2482: }
2483:
2484: // apply the notional to device transform.
2485:
2486: ptl1.x = 0;
2487: ptl1.y = pifi->fwdUnitsPerEm;
2488:
2489: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx);
2490:
2491: // now get the length of the vector.
2492:
2493: EmHeight = FXTOL(iHipot(ptfx.x, ptfx.y));
2494:
2495: // we have filled in the GLYPHPOS for each glyph in the font.
2496: // reset the pointer to the first glyph.
2497:
2498: phg = phgSave;
2499:
2500: PrintString(pdev, "/FontMatrix [1 ");
2501: PrintDecimal(pdev, 1, EmHeight);
2502: PrintString(pdev, " div 0 0 1 ");
2503: PrintDecimal(pdev, 1, EmHeight);
2504: PrintString(pdev, " div 0 0] def\n");
2505:
2506: // define the bounding box for the font, defined in 1 unit
2507: // character space (since FontMatrix = identity).
2508:
2509: PrintString(pdev, "/FontBBox [");
2510: PrintDecimal(pdev, 4, ptlTL.x, ptlTL.y, ptlBR.x, ptlBR.y);
2511: PrintString(pdev, " ] def\n");
2512:
2513: // allocate array for encoding vector, then initialize
2514: // all characters in encoding vector with '.notdef'.
2515:
2516: PrintString(pdev, "/Encoding 256 array def\n");
2517: PrintString(pdev, "0 1 255 {Encoding exch /.notdef put} for\n");
2518:
2519: // allocate space to store the HGLYPH<==>character code mapping.
2520:
2521: if (!(pDLFont->phgVector = (HGLYPH *)HeapAlloc(pdev->hheap, 0,
2522: sizeof(HGLYPH) * cGlyphs)))
2523: {
2524: RIP("PSCRIPT!DownloadBitmapFont: HeapAlloc for phgVector failed.\n");
2525: HeapFree(pdev->hheap, 0, (PVOID)phgSave);
2526: return(FALSE);
2527: }
2528:
2529: // fill in the HGLYPH encoding vector, and output
2530: // the encoding vector to the printer.
2531:
2532: pDLFont->cGlyphs = cGlyphs;
2533: memcpy(pDLFont->phgVector, phg, cGlyphs * sizeof(HGLYPH));
2534:
2535: PrintString(pdev, "Encoding\n");
2536:
2537: for (i = 0; i < cGlyphs; i++)
2538: {
2539: PrintString(pdev, "d ");
2540: PrintDecimal(pdev, 1, i);
2541: PrintString(pdev, " /c");
2542: PrintDecimal(pdev, 1, i);
2543: PrintString(pdev, " p\n");
2544: }
2545:
2546: // under level 1 of PostScript, the 'BuildChar' procedure is called
2547: // every time a character from the font is constructed. under
2548: // level 2, 'BuildGlyph' is called instead. therefore, we will
2549: // define a 'BuildChar' procedure, which basically calls
2550: // 'BuildGlyph'. this will provide us support for both level 1
2551: // and level 2 of PostScript.
2552:
2553: // define the 'BuildGlyph' procedure. start by getting the
2554: // character name and the font dictionary from the stack.
2555:
2556: PrintString(pdev, "/BuildGlyph {0 begin /cn ed /fd ed\n");
2557:
2558: // retrieve the character information from the CharData (CD)
2559: // dictionary.
2560:
2561: PrintString(pdev, "/CI fd /CD get cn get def\n");
2562:
2563: // get the width and the bounding box from the CharData.
2564: // remember to divide the width by 16.
2565:
2566: PrintString(pdev, "/wx CI 0 get def /cbb CI 1 4 getinterval def\n");
2567:
2568: // enable each character to be cached.
2569:
2570: PrintString(pdev, "wx 0 cbb aload pop setcachedevice\n");
2571:
2572: // get the width and height of the bitmap, set invert bool to true
2573: // specifying reverse image.
2574:
2575: PrintString(pdev, "CI 5 get CI 6 get true\n");
2576:
2577: // insert x and y translation components into general imagemask
2578: // matrix.
2579:
2580: PrintString(pdev, "[1 0 0 -1 0 0] d 4 CI 7 get p d 5 CI 8 get p\n");
2581:
2582: // get hex string bitmap, convert into procedure, then print
2583: // the bitmap image.
2584:
2585: PrintString(pdev, "CI 9 1 getinterval cvx im end } def\n");
2586:
2587: // create local storage for 'BuildGlyph' procedure.
2588:
2589: PrintString(pdev, "/BuildGlyph load 0 5 dict put\n");
2590:
2591: // the semantics of 'BuildChar' differ from 'BuildGlyph' in the
2592: // following way: 'BuildChar' is called with the font dictionary
2593: // and character code on the stack, 'BuildGlyph' is called with
2594: // the font dictionary and character name on the stack. the
2595: // following 'BuildChar' procedure calls 'BuildGlyph', and retains
2596: // compatiblity with level 1 PostScript.
2597:
2598: PrintString(pdev, "/BuildChar {1 index /Encoding get exch get\n");
2599: PrintString(pdev, "1 index /BuildGlyph get exec} bind def\n");
2600:
2601: // now create a dictionary containing information on each character.
2602:
2603: PrintString(pdev, "/CD ");
2604: PrintDecimal(pdev, 1, cGlyphs + 1);
2605: PrintString(pdev, " dict def CD begin\n");
2606:
2607: for (i = 0; i < cGlyphs; i++)
2608: {
2609: // get the GLYPHDATA structure for each glyph.
2610:
2611: if (!(cTmp = FONTOBJ_cGetGlyphs(pfo, FO_GLYPHBITS, 1, phg, (PVOID *)&pglyphdata)))
2612: {
2613: RIP("PSCRIPT!DownloadBitmapFont: cGetGlyphs failed.\n");
2614: HeapFree(pdev->hheap, 0, (PVOID)phgSave);
2615: HeapFree(pdev->hheap, 0, (PVOID)pDLFont->phgVector);
2616: return(FALSE);
2617: }
2618:
2619: // the first number in the character description is the width
2620: // in 1 unit font space. the next four numbers are the bounding
2621: // box in 1 unit font space. the next two numbers are the width
2622: // and height of the bitmap. the next two numbers are the x and
2623: // y translation values for the matrix given to imagemask.
2624: // this is followed by the bitmap itself.
2625:
2626: // first, output the character name.
2627:
2628: PrintString(pdev, "/c");
2629: PrintDecimal(pdev, 1, i);
2630:
2631: // output the character description array. the width and
2632: // bounding box need to be normalized to 1 unit font space.
2633:
2634: // the width will be sent to the printer as the actual width
2635: // multiplied by 16 so as not to lose any precision when
2636: // normalizing.
2637:
2638: PrintString(pdev, " [");
2639: PrintPSFIX(pdev, 1, (pglyphdata->fxD << 4));
2640: PrintString(pdev, " ");
2641: PrintDecimal(pdev, 4, pglyphdata->rclInk.left,
2642: -pglyphdata->rclInk.top, pglyphdata->rclInk.right,
2643: -pglyphdata->rclInk.bottom);
2644: PrintString(pdev, " ");
2645:
2646: // output the width and height of the bitmap itself.
2647:
2648: PrintDecimal(pdev, 2, pglyphdata->gdf.pgb->sizlBitmap.cx,
2649: pglyphdata->gdf.pgb->sizlBitmap.cy);
2650: PrintString(pdev, " ");
2651:
2652: // output the translation values for the transform matrix.
2653: // the x component is usually the equivalent of the left
2654: // sidebearing in pixels. the y component is always the height
2655: // of the bitmap minus any displacement factor (such as for characters
2656: // with descenders.
2657:
2658: psfxXtrans = -pglyphdata->gdf.pgb->ptlOrigin.x << 8;
2659: psfxYtrans = -pglyphdata->gdf.pgb->ptlOrigin.y << 8;
2660:
2661: PrintPSFIX(pdev, 2, psfxXtrans, psfxYtrans);
2662: PrintString(pdev, "\n<");
2663:
2664: // now output the bits. calculate how many bytes each source scanline
2665: // contains. remember that the bitmap will be padded to 32bit bounds.
2666:
2667: // protect ourselves.
2668:
2669: if ((pglyphdata->gdf.pgb->sizlBitmap.cx < 1) ||
2670: (pglyphdata->gdf.pgb->sizlBitmap.cy < 1))
2671: {
2672: RIP("PSCRIPT!DownloadBitmapFont: Invalid glyphdata!!!.\n");
2673: return(FALSE);
2674: }
2675:
2676: pjBits = pglyphdata->gdf.pgb->aj;
2677:
2678: for (j = 0; j < (DWORD)pglyphdata->gdf.pgb->sizlBitmap.cy; j++)
2679: {
2680: cjWidth = (LONG)(pglyphdata->gdf.pgb->sizlBitmap.cx + 7) >> 3;
2681: vHexOut(pdev, pjBits, cjWidth);
2682: pjBits += cjWidth;
2683: }
2684:
2685: PrintString(pdev, ">]def\n");
2686:
2687: // point to the next glyph handle.
2688:
2689: phg++;
2690: }
2691:
2692: // don't forget the .notdef character.
2693:
2694: PrintString(pdev, "/.notdef [.24 0 0 0 1 1 0 0 <>]def end\n");
2695:
2696: // create a unique ID for the font, then name it.
2697:
2698: pwstr = (PWSTR)((BYTE *)pifi + pifi->dpwszFaceName);
2699: cTmp = wcslen(pwstr);
2700:
2701: // get the font name from the UNICODE font name.
2702:
2703: memset(szFaceName, 0, sizeof(szFaceName));
2704: pszFaceName = szFaceName;
2705:
2706: while (cTmp--)
2707: {
2708: *pszFaceName = (CHAR)*pwstr++;
2709:
2710: // replace any spaces in the font name with underscores.
2711:
2712: if (*pszFaceName == ' ')
2713: *pszFaceName = '_';
2714:
2715: // replace any parens in the font name with asterisks.
2716:
2717: if ((*pszFaceName == '(') || (*pszFaceName == ')'))
2718: *pszFaceName = '*';
2719:
2720: // point to the next character.
2721:
2722: *pszFaceName++;
2723: }
2724:
2725: // add the point size to the font name, so we can distinguish
2726: // different point sizes of the same font.
2727:
2728: // NOTE Grab a new point size here, rather than reading if from
2729: // the CGS. This is necessary to support DrvDownloadFace.
2730:
2731: psfxPointSize = GetPointSize(pdev, pfo, &fontxform);
2732:
2733: cTmp = PSFIXToBuffer(pszFaceName, psfxPointSize);
2734:
2735: // update the buffer pointer.
2736:
2737: pszFaceName += cTmp;
2738:
2739: // output the NULL terminator.
2740:
2741: *pszFaceName = '\0';
2742:
2743: // output the unique id, which, in a postscript printer, can
2744: // be in the range from 0 to 16777215.
2745:
2746: PrintString(pdev, "/UniqueID ");
2747: PrintDecimal(pdev, 1, (pfo->iUniq & 0xFFFFF));
2748:
2749: PrintString(pdev, " def end pop /");
2750: PrintString(pdev, szFaceName);
2751: PrintString(pdev, " exch definefont pop\n");
2752:
2753: // update the fontname in our current graphics state.
2754:
2755: strcpy(pdev->cgs.szFont, szFaceName);
2756:
2757: // update information for this downloaded font.
2758:
2759: strcpy(pDLFont->strFont, szFaceName);
2760: pDLFont->psfxScaleFactor = psfxPointSize;
2761:
2762: // update the downloaded font counter.
2763:
2764: pdev->cgs.cDownloadedFonts++;
2765:
2766: // free up some memory.
2767:
2768: if (phgSave)
2769: HeapFree(pdev->hheap, 0, (PVOID)phgSave);
2770: }
2771:
2772:
2773: //--------------------------------------------------------------------
2774: // BOOL DownloadOutlineFont(pdev, pfo)
2775: // PDEVDATA pdev;
2776: // FONTOBJ *pfo;
2777: //
2778: // This routine downloads the font definition for the given bitmap font,
2779: // if it has not already been done. The font is downloaded as an
2780: // Adobe Type 3 font.
2781: //
2782: // This routine return TRUE if the font is successfully, or has already
2783: // been, downloaded to the printer. It returns FALSE if it fails.
2784: //
2785: // History:
2786: // 27-Feb-1992 -by- Kent Settle (kentse)
2787: // Wrote it.
2788: //--------------------------------------------------------------------
2789:
2790: BOOL DownloadOutlineFont(pdev, pfo)
2791: PDEVDATA pdev;
2792: FONTOBJ *pfo;
2793: {
2794: DLFONT *pDLFont;
2795: DWORD i;
2796: DWORD cDownloadedFonts;
2797: DWORD cGlyphs, cTmp;
2798: HGLYPH *phg;
2799: HGLYPH *phgSave;
2800: GLYPHDATA *pglyphdata;
2801: POINTL ptlTL, ptlBR;
2802: PIFIMETRICS pifi;
2803: LONG iCharWidth;
2804: CHAR szFaceName[MAX_STRING];
2805: PSZ pszFaceName;
2806: PWSTR pwstr;
2807:
2808: // search through our list of downloaded GDI fonts to see if the
2809: // current font has already been downloaded to the printer.
2810:
2811: pDLFont = pdev->cgs.pDLFonts;
2812:
2813: cDownloadedFonts = min(pdev->cgs.cDownloadedFonts, pdev->iDLFonts);
2814:
2815: for (i = 0; i < pdev->iDLFonts; i++)
2816: {
2817: // is this entry the one we are looking for? simply return if so.
2818:
2819: if (pDLFont->iUniq == pfo->iUniq)
2820: {
2821: // update the fontname and size in our current graphics state.
2822:
2823: strcpy(pdev->cgs.szFont, pDLFont->strFont);
2824: pdev->cgs.psfxScaleFactor = pDLFont->psfxScaleFactor;
2825: pdev->cgs.lidFont = pDLFont->iUniq;
2826:
2827: return(TRUE);
2828: }
2829:
2830: pDLFont++;
2831: }
2832:
2833: // we did not find that this font has been downloaded yet, so we must
2834: // do it now.
2835:
2836: // if we have reached our downloaded font threshold, then
2837: // we will surround ever textout call with a save/restore.
2838:
2839: if (cDownloadedFonts == pdev->iDLFonts)
2840: {
2841: ps_save(pdev, FALSE);
2842: pdev->cgs.dwFlags |= CGS_DLFONTTHRESHOLD;
2843: cDownloadedFonts--;
2844: }
2845:
2846: pDLFont = pdev->cgs.pDLFonts;
2847: pDLFont += cDownloadedFonts;
2848:
2849: // free up the memory for the hglyph array for the old font.
2850:
2851: if (pDLFont->phgVector)
2852: {
2853: HeapFree(pdev->hheap, 0, (PVOID)pDLFont->phgVector);
2854: pDLFont->phgVector = (HGLYPH *)NULL;
2855: }
2856:
2857: memset(pDLFont, 0, sizeof(DLFONT));
2858:
2859: pDLFont->iFace = pfo->iFace;
2860: pDLFont->iUniq = pfo->iUniq;
2861:
2862: // if we have made it this far, we should simply be able to
2863: // download the font now.
2864:
2865: // we will be downloading an Adobe TYPE 3 font.
2866:
2867: // allocate a dictionary for the font.
2868:
2869: PrintString(pdev, "10 dict d begin\n");
2870:
2871: // set FontType to 3 indicating user defined font.
2872:
2873: PrintString(pdev, "/FontType 3 def\n");
2874:
2875: // all font coordinate systems will be defined in units of 1000.
2876: // specify a FontMatrix which transforms the 1000 unit font to a
2877: // 1 unit font.
2878:
2879: PrintString(pdev, "/FontMatrix [.001 0 0 .001 0 0] def\n");
2880:
2881: // allocate memory for and get the handles for each glyph of the font.
2882:
2883: if (!(cGlyphs = FONTOBJ_cGetAllGlyphHandles(pfo, NULL)))
2884: {
2885: RIP("PSCRIPT!DownloadOutlineFont: cGetAllGlyphHandles failed.\n");
2886: return(FALSE);
2887: }
2888:
2889: if (!(phg = (HGLYPH *)HeapAlloc(pdev->hheap, 0, sizeof(HGLYPH) * cGlyphs)))
2890: {
2891: RIP("PSCRIPT!DownloadOutlineFont: HeapAlloc failed.\n");
2892: return(FALSE);
2893: }
2894:
2895: phgSave = phg;
2896:
2897: cTmp = FONTOBJ_cGetAllGlyphHandles(pfo, phg);
2898:
2899: ASSERTPS(cTmp == cGlyphs, "PSCRIPT!DownloadOutlineFont: inconsistent cGlyphs\n");
2900:
2901: // how many characters will we define in this font?
2902: // keep in mind that we can only do 256 at a time.
2903: // remember to leave room for the .notdef character.
2904:
2905: cGlyphs = min(255, cGlyphs);
2906:
2907: // get the IFIMETRICS for the font, used in TTTOADOBE.
2908:
2909: if (!(pifi = FONTOBJ_pifi(pfo)))
2910: {
2911: RIP("PSCRIPT!DownloadOutlineFont: pifi failed.\n");
2912: HeapFree(pdev->hheap, 0, (PVOID)phg);
2913: return(FALSE);
2914: }
2915:
2916: // run through the array, looking at the bounding box for each
2917: // glyph, in order to create the bounding box for the entire
2918: // font.
2919:
2920: ptlTL.x = ADOBE_FONT_UNITS;
2921: ptlTL.y = ADOBE_FONT_UNITS;
2922: ptlBR.x = 0;
2923: ptlBR.y = 0;
2924:
2925: for (i = 0; i < cGlyphs; i++)
2926: {
2927: // get the GLYPHDATA structure for each glyph.
2928:
2929: if (!(cTmp = FONTOBJ_cGetGlyphs(pfo, FO_PATHOBJ, 1, phg, (PVOID *)&pglyphdata)))
2930: {
2931: RIP("PSCRIPT!DownloadOutlineFont: cGetGlyphs failed.\n");
2932: HeapFree(pdev->hheap, 0, (PVOID)phgSave);
2933: return(FALSE);
2934: }
2935:
2936: ptlTL.x = min(ptlTL.x, TTTOADOBE(pglyphdata->rclInk.left));
2937: ptlTL.y = min(ptlTL.y, TTTOADOBE(pglyphdata->rclInk.top));
2938: ptlBR.x = max(ptlBR.x, TTTOADOBE(pglyphdata->rclInk.right));
2939: ptlBR.y = max(ptlBR.y, TTTOADOBE(pglyphdata->rclInk.bottom));
2940:
2941: // point to the next glyph handle.
2942:
2943: phg++;
2944: }
2945:
2946: // we have filled in the GLYPHPOS for each glyph in the font.
2947: // reset the pointer to the first glyph.
2948:
2949: phg = phgSave;
2950:
2951: // define the bounding box for the font.
2952:
2953: PrintString(pdev, "/FontBBox [");
2954: PrintDecimal(pdev, 4, ptlTL.x, ptlTL.y, ptlBR.x, ptlBR.y);
2955: PrintString(pdev, "] def\n");
2956:
2957: // allocate array for encoding vector, then initialize
2958: // all characters in encoding vector with '.notdef'.
2959:
2960: PrintString(pdev, "/Encoding 256 array def\n");
2961: PrintString(pdev, "0 1 255 {Encoding exch /.notdef p} for\n");
2962:
2963: // allocate space to store the HGLYPH<==>character code mapping.
2964:
2965: if (!(pDLFont->phgVector = (HGLYPH *)HeapAlloc(pdev->hheap, 0,
2966: sizeof(HGLYPH) * cGlyphs)))
2967: {
2968: RIP("PSCRIPT!DownloadOutlineFont: HeapAlloc for phgVector failed.\n");
2969: HeapFree(pdev->hheap, 0, (PVOID)phg);
2970: return(FALSE);
2971: }
2972:
2973: // initialize array.
2974:
2975: pDLFont->cGlyphs = cGlyphs;
2976:
2977: // fill in the HGLYPH encoding vector, and output
2978: // the encoding vector to the printer.
2979:
2980: memcpy(pDLFont->phgVector, phg, cGlyphs * sizeof(HGLYPH));
2981:
2982: PrintString(pdev, "Encoding\n");
2983:
2984: for (i = 0; i < cGlyphs; i++)
2985: {
2986: PrintString(pdev, "d ");
2987: PrintDecimal(pdev, 1, i);
2988: PrintString(pdev, " /c");
2989: PrintDecimal(pdev, 1, i);
2990: PrintString(pdev, " p\n");
2991: }
2992:
2993: // under level 1 of PostScript, the 'BuildChar' procedure is called
2994: // every time a character from the font is constructed. under
2995: // level 2, 'BuildGlyph' is called instead. therefore, we will
2996: // define a 'BuildChar' procedure, which basically calls
2997: // 'BuildGlyph'. this will provide us support for both level 1
2998: // and level 2 of PostScript.
2999:
3000: // define the 'BuildGlyph' procedure. start by getting the
3001: // character name and the font dictionary from the stack.
3002:
3003: PrintString(pdev, "/BuildGlyph {0 begin /cn ed /fd ed\n");
3004:
3005: // retrieve the character information from the CharData (CD)
3006: // dictionary.
3007:
3008: PrintString(pdev, "/CI fd /CD get cn get def\n");
3009:
3010: // get the width and the bounding box from the CharData.
3011:
3012: PrintString(pdev, "/wx CI 0 get def /cbb CI 1 4 getinterval def\n");
3013:
3014: // enable each character to be cached.
3015:
3016: PrintString(pdev, "wx 0 cbb aload pop setcachedevice\n");
3017:
3018: // get the procedure for rendering the character and execute it.
3019:
3020: PrintString(pdev, "CI 5 get exec end } def\n");
3021:
3022: // create local storage for 'BuildGlyph' procedure.
3023:
3024: PrintString(pdev, "/BuildGlyph load 0 5 dict p\n");
3025:
3026: // the semantics of 'BuildChar' differ from 'BuildGlyph' in the
3027: // following way: 'BuildChar' is called with the font dictionary
3028: // and character code on the stack, 'BuildGlyph' is called with
3029: // the font dictionary and character name on the stack. the
3030: // following 'BuildChar' procedure calls 'BuildGlyph', and retains
3031: // compatiblity with level 1 PostScript.
3032:
3033: PrintString(pdev, "/BuildChar {1 index /Encoding get exch get\n");
3034: PrintString(pdev, "1 index /BuildGlyph get exec} bd\n");
3035:
3036: // now create a dictionary containing information on each character.
3037:
3038: PrintString(pdev, "/CD ");
3039: PrintDecimal(pdev, 1, cGlyphs + 1);
3040: PrintString(pdev, " dict def CD begin\n");
3041:
3042: for (i = 0; i < cGlyphs; i++)
3043: {
3044: // get the GLYPHDATA structure for each glyph.
3045:
3046: DbgPrint("calling cGetGlyphs.\n");
3047: DbgBreakPoint();
3048:
3049: if (!(cTmp = FONTOBJ_cGetGlyphs(pfo, FO_PATHOBJ, 1, phg, (PVOID *)&pglyphdata)))
3050: {
3051: RIP("PSCRIPT!DownloadOutlineFont: cGetGlyphs failed.\n");
3052: HeapFree(pdev->hheap, 0, (PVOID)phgSave);
3053: return(FALSE);
3054: }
3055:
3056: // the first number in the character description is the width
3057: // in 1000 unit font space. the next four numbers are the bounding
3058: // box in 1000 unit font space. these are followed by the
3059: // procedure used to draw the character itself.
3060:
3061: // first, output the character name.
3062:
3063: PrintString(pdev, "/c");
3064: PrintDecimal(pdev, 1, i);
3065:
3066: // output the character description array.
3067:
3068: // the width will be sent to the printer as the actual width
3069: // multiplied by 16 so as not to lose any percision when
3070: // normalizing.
3071:
3072: iCharWidth = TTTOADOBE((LONG)pglyphdata->fxD);
3073:
3074: ptlTL.x = TTTOADOBE(pglyphdata->rclInk.left);
3075: ptlTL.y = TTTOADOBE(pglyphdata->rclInk.top);
3076: ptlBR.x = TTTOADOBE(pglyphdata->rclInk.right);
3077: ptlBR.y = TTTOADOBE(pglyphdata->rclInk.bottom);
3078:
3079: // remember to flip over the y coordinates.
3080:
3081: PrintString(pdev, " [");
3082: PrintDecimal(pdev, 5, iCharWidth, ptlTL.x, -ptlTL.y, ptlBR.x, -ptlBR.y);
3083:
3084: // output the procedure to draw the character itself.
3085:
3086: PrintString (pdev, " {");
3087: DrvCommonPath(pdev, pglyphdata->gdf.ppo);
3088: PrintString(pdev, "fill }]def\n");
3089:
3090: // point to the next glyph handle.
3091:
3092: phg++;
3093: }
3094:
3095: // don't forget the .notdef character.
3096:
3097: PrintString(pdev, "/.notdef [0 0 0 0 0 {}]def end\n");
3098:
3099: // create a unique ID for the font, then name it.
3100:
3101: pwstr = (PWSTR)((BYTE *)pifi + pifi->dpwszFaceName);
3102: cTmp = wcslen(pwstr);
3103:
3104: // get the font name from the UNICODE font name.
3105:
3106: pszFaceName = szFaceName;
3107:
3108: while (cTmp--)
3109: {
3110: *pszFaceName = (CHAR)*pwstr++;
3111:
3112: // replace any spaces in the font name with underscores.
3113:
3114: if (*pszFaceName == ' ')
3115: *pszFaceName = '_';
3116:
3117: // replace any parens in the font name with asterisks.
3118:
3119: if ((*pszFaceName == '(') || (*pszFaceName == ')'))
3120: *pszFaceName = '*';
3121:
3122: // point to the next character.
3123:
3124: *pszFaceName++;
3125: }
3126:
3127: // NULL terminate the font name.
3128:
3129: *pszFaceName = '\0';
3130:
3131: // output the unique id, which, in a postscript printer, can
3132: // be in the range from 0 to 16777215.
3133:
3134: PrintString(pdev, "/UniqueID ");
3135: PrintDecimal(pdev, 1, (pfo->iUniq & 0xFFFFF));
3136:
3137: PrintString(pdev, " def end pop /");
3138: PrintString(pdev, szFaceName);
3139: PrintString(pdev, " exch definefont pop\n");
3140:
3141: // update the fontname in our current graphics state.
3142:
3143: strcpy(pdev->cgs.szFont, szFaceName);
3144:
3145: // update the downloaded font counter.
3146:
3147: pdev->cgs.cDownloadedFonts++;
3148:
3149: // free up some memory.
3150:
3151: if (phgSave)
3152: HeapFree(pdev->hheap, 0, (PVOID)phgSave);
3153: }
3154:
3155:
3156: //--------------------------------------------------------------------
3157: // BOOL SetFontRemap(pdev, iFontID)
3158: // PDEVDATA pdev;
3159: // DWORD iFontID;
3160: //
3161: // This routine adds the specified font to the list of remapped fonts.
3162: //
3163: // This routine return TRUE for success, FALSE otherwise.
3164: //
3165: // History:
3166: // 11-Jun-1992 -by- Kent Settle (kentse)
3167: // Wrote it.
3168: //--------------------------------------------------------------------
3169:
3170: BOOL SetFontRemap(pdev, iFontID)
3171: PDEVDATA pdev;
3172: DWORD iFontID;
3173: {
3174: FREMAP *pfremap;
3175:
3176: // add the specified font id to the list of remapped fonts.
3177:
3178: pfremap = &pdev->cgs.FontRemap;
3179:
3180: // find the end of the list.
3181:
3182: if (pfremap->pNext)
3183: {
3184: while (pfremap->pNext)
3185: pfremap = (PFREMAP)pfremap->pNext;
3186:
3187: // allocate the next entry in the list.
3188:
3189: if (!(pfremap->pNext = (struct _FREMAP *)HeapAlloc(pdev->hheap, 0, sizeof(FREMAP))))
3190: {
3191: RIP("PSCRIPT!SetFontRemap: HeapAlloc failed.\n");
3192: return(FALSE);
3193: }
3194:
3195: pfremap = (PFREMAP)pfremap->pNext;
3196: }
3197:
3198: // now that we have found the last entry in the list, fill it in.
3199:
3200: pfremap->iFontID = iFontID;
3201: pfremap->pNext = NULL;
3202:
3203: return(TRUE);
3204: }
3205:
3206:
3207: //--------------------------------------------------------------------
3208: // BOOL QueryFontRemap(pdev, iFontID)
3209: // PDEVDATA pdev;
3210: // DWORD iFontID;
3211: //
3212: // This routine scans the list of remapped fonts.
3213: //
3214: // This routine return TRUE if iFontID is found, FALSE otherwise.
3215: //
3216: // History:
3217: // 11-Jun-1992 -by- Kent Settle (kentse)
3218: // Wrote it.
3219: //--------------------------------------------------------------------
3220:
3221: BOOL QueryFontRemap(pdev, iFontID)
3222: PDEVDATA pdev;
3223: DWORD iFontID;
3224: {
3225: FREMAP *pfremap;
3226:
3227: // add the specified font id to the list of remapped fonts.
3228:
3229: pfremap = &pdev->cgs.FontRemap;
3230:
3231: // search the list for iFontID.
3232:
3233: do
3234: {
3235: // return TRUE if we have found the font.
3236:
3237: if (pfremap->iFontID == iFontID)
3238: return(TRUE);
3239:
3240: // we have not found the font, point to the next entry.
3241:
3242: pfremap = (PFREMAP)pfremap->pNext;
3243:
3244: } while (pfremap);
3245:
3246: // we did not find the font.
3247:
3248: return(FALSE);
3249: }
3250:
3251:
3252: //--------------------------------------------------------------------
3253: // DWORD SubstituteIFace(pdev, pfo)
3254: // PDEVDATA pdev;
3255: // FONTOBJ *pfo;
3256: //
3257: // This routine takes the TrueType font specified by pfo, and returns
3258: // the iFace of the device font to substitute. This routine returns
3259: // zero if no font is found for substitution.
3260: //
3261: // History:
3262: // 14-Jul-1992 -by- Kent Settle (kentse)
3263: // Wrote it.
3264: //--------------------------------------------------------------------
3265:
3266: DWORD SubstituteIFace(pdev, pfo)
3267: PDEVDATA pdev;
3268: FONTOBJ *pfo;
3269: {
3270: DWORD iFace = 0;
3271: DWORD iTmp;
3272: CHAR strDevFont[MAX_FONT_NAME];
3273: WCHAR wstrDevFont[MAX_FONT_NAME];
3274: PSTR pstrDevFont;
3275: PWSTR pwstrDevFont;
3276: IFIMETRICS *pifiTT;
3277: DWORD cTmp;
3278: PWSTR pwstr, pwstrTT;
3279: PNTFM pntfm;
3280: BOOL bFound;
3281:
3282: #if DBG
3283: // make sure we have a TrueType font.
3284:
3285: if (!(pfo->flFontType & TRUETYPE_FONTTYPE))
3286: {
3287: DbgPrint("PSCRIPT!SubstituteIFace: Trying to substitute for non-TT font.\n");
3288: return(0);
3289: }
3290:
3291: // make sure we are supposed to be doing font substitution.
3292:
3293: if (!(pdev->psdm.dwFlags & PSDEVMODE_FONTSUBST))
3294: {
3295: DbgPrint("PSCRIPT!SubstituteIFace: not supposed to font substitute.\n");
3296: return(0);
3297: }
3298: #endif
3299:
3300: // get the TrueType font name from the IFIMETRICS structure.
3301:
3302: if (!(pifiTT = FONTOBJ_pifi(pfo)))
3303: {
3304: RIP("PSCRIPT!SubstituteIFace: FONTOBJ_pifiTT failed.\n");
3305: return(0);
3306: }
3307:
3308: pwstrTT = (PWSTR)((BYTE *)pifiTT + pifiTT->dpwszFaceName);
3309:
3310: // now search the font substitution table for a matching TrueType font.
3311: // the substitution table is in the following format: a NULL terminated
3312: // UNICODE TrueType font name followed by the matching NULL terminated
3313: // device font name. this sequence is repeated until a double NULL
3314: // terminator ends the table.
3315:
3316: pwstr = pdev->pTTSubstTable;
3317: bFound = FALSE;
3318:
3319: while (*pwstr)
3320: {
3321: if (!(wcscmp(pwstr, pwstrTT)))
3322: {
3323: // we found the TrueType font, now get the matching device font.
3324:
3325: pwstr += (wcslen(pwstr) + 1);
3326: wcsncpy(wstrDevFont, pwstr,
3327: (sizeof(wstrDevFont) / sizeof(wstrDevFont[0])));
3328: bFound = TRUE;
3329: break;
3330: }
3331: else
3332: {
3333: // this was not the font in question. skip over both font names.
3334:
3335: pwstr += (wcslen(pwstr) + 1);
3336: pwstr += (wcslen(pwstr) + 1);
3337: }
3338: }
3339:
3340: // if we could not get a corresponding device font for any reason,
3341: // simply return zero for the iFace.
3342:
3343: if (!bFound)
3344: return(0);
3345:
3346: // get an ANSI version of the font name.
3347:
3348: cTmp = wcslen(wstrDevFont);
3349: cTmp++;
3350:
3351: pwstrDevFont = wstrDevFont;
3352: pstrDevFont = strDevFont;
3353:
3354: while (cTmp--)
3355: *pstrDevFont++ = (CHAR)*pwstrDevFont++;
3356:
3357: *pstrDevFont = '\0';
3358:
3359: // at this point we have a mapping between a TrueType font name,
3360: // and a device font name. we need to determine the iFace of
3361: // the font name.
3362:
3363: for (iTmp = 1; iTmp <= (pdev->cDeviceFonts + pdev->cSoftFonts); iTmp++)
3364: {
3365: // get the font metrics for the specified font.
3366:
3367: pntfm = pdev->pfmtable[iTmp - 1].pntfm;
3368:
3369: // see if it is the font family we are looking for. if it is,
3370: // select it into the current graphics state, and return its iFace.
3371:
3372: if (!strcmp(strDevFont, ((char *)pntfm + pntfm->loszFontName)))
3373: {
3374: // select the device font in the current graphics state.
3375:
3376: strcpy(pdev->cgs.szFont, strDevFont);
3377: iFace = iTmp;
3378: break;
3379: }
3380: }
3381:
3382: // return the iFace of the device font to the caller.
3383:
3384: return(iFace);
3385: }
3386:
3387:
3388:
3389: //--------------------------------------------------------------------
3390: // ULONG DrvGetGlyphMode(dhpdev, pfo, iMode)
3391: // DHPDEV dhpdev;
3392: // FONTOBJ *pfo;
3393: // ULONG iMode;
3394: //
3395: // This routine returns to the engine, the type of font caching the
3396: // engine should do.
3397: //
3398: // History:
3399: // 22-Jul-1992 -by- Kent Settle (kentse)
3400: // Wrote it.
3401: //--------------------------------------------------------------------
3402:
3403: ULONG DrvGetGlyphMode(dhpdev, pfo)
3404: DHPDEV dhpdev;
3405: FONTOBJ *pfo;
3406: {
3407: return(SO_MONOBITMAP);
3408: // return(SO_GLYPHHANDLES);
3409: }
3410:
3411:
3412:
3413: //--------------------------------------------------------------------
3414: // LONG iHipot(x, y)
3415: // LONG x;
3416: // LONG y;
3417: //
3418: // This routine returns the hypoteneous of a right triangle.
3419: //
3420: // FORMULA:
3421: // use sq(x) + sq(y) = sq(hypo);
3422: // start with MAX(x, y),
3423: // use sq(x + 1) = sq(x) + 2x + 1 to incrementally get to the
3424: // target hypotenouse.
3425: //
3426: // History:
3427: // 10-Feb-1993 -by- Kent Settle (kentse)
3428: // Stole from RASDD.
3429: // 21-Aug-1991 -by- Lindsay Harris (lindsayh)
3430: // Cleaned up UniDrive version, added comments etc.
3431: //--------------------------------------------------------------------
3432:
3433: LONG iHipot(x, y)
3434: LONG x;
3435: LONG y;
3436: {
3437: register int hypo; /* Value to calculate */
3438: register int delta; /* Used in the calculation loop */
3439:
3440: int target; /* Loop limit factor */
3441:
3442: // quick exit for frequent trivial cases [bodind]
3443:
3444: if (x == 0)
3445: {
3446: return ((y > 0) ? y : -y);
3447: }
3448:
3449: if (y == 0)
3450: {
3451: return ((x > 0) ? x : -x);
3452: }
3453:
3454: if (x < 0)
3455: x = -x;
3456:
3457: if (y < 0)
3458: y = -y;
3459:
3460: if(x > y)
3461: {
3462: hypo = x;
3463: target = y * y;
3464: }
3465: else
3466: {
3467: hypo = y;
3468: target = x * x;
3469: }
3470:
3471: for (delta = 0; delta < target; hypo++)
3472: delta += hypo << 1 + 1;
3473:
3474: return hypo;
3475: }
3476:
3477:
3478: //--------------------------------------------------------------------------
3479: // BOOL IsJustifiedText(pdev, pfo, pstro, pptSpace, pptNonSpace, pdata)
3480: // PDEVDATA pdev;
3481: // FONTOBJ *pfo;
3482: // STROBJ *pstro;
3483: // POINTPSFX *pptSpace;
3484: // POINTPSFX *pptNonSpace;
3485: // TEXTDATA *pdata;
3486: //
3487: // This routine analyzes the string defined in pstro. If the spacing after
3488: // each non-space character is the same (with in 1), and the spacing after
3489: // each space character is the same, this routine will fill in the
3490: // POINTPSFX for each value, and return TRUE, otherwise it returns FALSE.
3491: //
3492: // History:
3493: // 31-Mar-1993 -by- Kent Settle (kentse)
3494: // Wrote it.
3495: //--------------------------------------------------------------------------
3496:
3497:
3498: BOOL IsJustifiedText(pdev, pfo, pstro, pptSpace, pptNonSpace, pdata)
3499: PDEVDATA pdev;
3500: FONTOBJ *pfo;
3501: STROBJ *pstro;
3502: POINTPSFX *pptSpace;
3503: POINTPSFX *pptNonSpace;
3504: TEXTDATA *pdata;
3505: {
3506: DWORD i;
3507: TEXTDELTA *pdelta;
3508: TEXTDELTA *pdeltaSave;
3509: POINTFIX ptfxSpace, ptfxNonSpace, ptfxTmp;
3510: POINTFIX ptfxSExtra, ptfxNSExtra;
3511: GLYPHPOS *pgp;
3512: WCHAR wcSpace;
3513: FLONG flAccel;
3514: LONG cSpace, cNonSpace, denom;
3515: DWORD cGlyphs;
3516: BOOL bMore;
3517: PWSZ pwszOrg;
3518:
3519: flAccel = pstro->flAccel;
3520:
3521: // currently, just handle horizontal text. justification for a string
3522: // with one character makes no sense. and, justification is
3523: // obviously not happening, if we are using default placement.
3524: // finally, we must individually place the characters if substitution
3525: // is in effect, because it is the only way we have of getting the
3526: // true character widths.
3527:
3528: if ((!(flAccel & SO_HORIZONTAL)) || (pstro->cGlyphs <= 1) ||
3529: (flAccel & SO_FLAG_DEFAULT_PLACEMENT) || pdata->bFontSubstitution)
3530: return(FALSE);
3531:
3532: // now the ugly part. we must go through the string a character at a
3533: // time, comparing the widths given in the pstro with the actual font
3534: // character widths. if the difference is the same for each space
3535: // character, and the same for each non-space character, then
3536: // justification, as we know it, is in effect.
3537:
3538: // first start off by allocating an array of TEXTDELTAs, so we can fill
3539: // them in with the deltas between each character.
3540:
3541: if (!(pdelta = (TEXTDELTA *)HeapAlloc(pdev->hheap, 0,
3542: (sizeof(TEXTDELTA) * (pstro->cGlyphs - 1)))))
3543: {
3544: #if DBG
3545: DbgPrint("PSCRIPT!IsJustifiedText: HeapAlloc for pdelta failed.\n");
3546: #endif
3547: return(FALSE);
3548: }
3549:
3550: pdeltaSave = pdelta;
3551:
3552: // get the original UNICODE string.
3553:
3554: if (pfo->flFontType & DEVICE_FONTTYPE)
3555: pwszOrg = GetUnicodeString(pdev, pfo, pstro);
3556: else
3557: pwszOrg = pstro->pwszOrg;
3558:
3559: // fill in the TEXTDELTA structures.
3560:
3561: if (pstro->pgp)
3562: {
3563: if (!FillDeltaArray(pdev, pfo, pstro->pgp, pstro, pdelta, pstro->cGlyphs, pwszOrg))
3564: {
3565: RIP("PSCRIPT!IsJustifiedText: FillDeltaArray failed.\n");
3566: HeapFree(pdev->hheap, 0, (PVOID)pdeltaSave);
3567: return(FALSE);
3568: }
3569: }
3570: else
3571: {
3572: // prepare to enumerate the string properly.
3573:
3574: STROBJ_vEnumStart(pstro);
3575:
3576: // now draw the text.
3577:
3578: do
3579: {
3580: bMore = STROBJ_bEnum(pstro, &cGlyphs, &pgp);
3581:
3582: if (!FillDeltaArray(pdev, pfo, pgp, pstro, pdelta, cGlyphs, pwszOrg))
3583: {
3584: RIP("PSCRIPT!IsJustifiedText: FillDeltaArray failed.\n");
3585: HeapFree(pdev->hheap, 0, (PVOID)pdeltaSave);
3586: return(FALSE);
3587: }
3588:
3589: pdelta += cGlyphs;
3590: pwszOrg += cGlyphs;
3591:
3592: } while (bMore);
3593: }
3594:
3595: // reset pointer to first structure.
3596:
3597: pdelta = pdeltaSave;
3598:
3599: // get the unicode value for the space character.
3600:
3601: MultiByteToWideChar(CP_ACP, 0, (LPCSTR)" ", 1, (LPWSTR)&wcSpace, 1);
3602:
3603: // now get the widths of the characters themselves.
3604:
3605: ptfxSpace.x = -1;
3606: ptfxNonSpace.x = -1;
3607: ptfxSExtra.x = 0;
3608: ptfxSExtra.y = 0;
3609: ptfxNSExtra.x = 0;
3610: ptfxNSExtra.y = 0;
3611: cSpace = 0;
3612: cNonSpace = 0;
3613:
3614: for (i = 0; i < (pstro->cGlyphs - 1); i++)
3615: {
3616: ptfxTmp.x = abs(pdelta->ptfxorg.x - LTOFX(pdelta->ptlpgp.x));
3617: ptfxTmp.y = abs(pdelta->ptfxorg.y - LTOFX(pdelta->ptlpgp.y));
3618:
3619: if (pdelta->wc == wcSpace)
3620: {
3621: if (ptfxSpace.x == -1)
3622: {
3623: ptfxSpace = ptfxTmp;
3624: ptfxSExtra.x = LTOFX(pdelta->ptlpgp.x) - pdelta->ptfxorg.x;
3625: ptfxSExtra.y = LTOFX(pdelta->ptlpgp.y) - pdelta->ptfxorg.y;
3626: }
3627: else
3628: {
3629: if ((abs(ptfxSpace.x - ptfxTmp.x) > LTOFX(1)) ||
3630: (abs(ptfxSpace.y - ptfxTmp.y) > LTOFX(1)))
3631: {
3632: HeapFree(pdev->hheap, 0, (PVOID)pdeltaSave);
3633: return(FALSE);
3634: }
3635:
3636: ptfxSExtra.x += (LTOFX(pdelta->ptlpgp.x) - pdelta->ptfxorg.x);
3637: ptfxSExtra.y += (LTOFX(pdelta->ptlpgp.y) - pdelta->ptfxorg.y);
3638: }
3639:
3640: cSpace++;
3641: }
3642: else // non spacing character.
3643: {
3644: if (ptfxNonSpace.x == -1)
3645: {
3646: ptfxNonSpace = ptfxTmp;
3647: ptfxNSExtra.x = LTOFX(pdelta->ptlpgp.x) - pdelta->ptfxorg.x;
3648: ptfxNSExtra.y = LTOFX(pdelta->ptlpgp.y) - pdelta->ptfxorg.y;
3649: }
3650: else
3651: {
3652: if ((abs(ptfxNonSpace.x - ptfxTmp.x) > LTOFX(1)) ||
3653: (abs(ptfxNonSpace.y - ptfxTmp.y) > LTOFX(1)))
3654: {
3655: HeapFree(pdev->hheap, 0, (PVOID)pdeltaSave);
3656: return(FALSE);
3657: }
3658:
3659: ptfxNSExtra.x += (LTOFX(pdelta->ptlpgp.x) - pdelta->ptfxorg.x);
3660: ptfxNSExtra.y += (LTOFX(pdelta->ptlpgp.y) - pdelta->ptfxorg.y);
3661: }
3662:
3663: cNonSpace++;
3664: }
3665:
3666: pdelta++;
3667: }
3668:
3669: // fill in the justification amounts.
3670:
3671: if (cSpace == 0)
3672: {
3673: pptSpace->x = 0;
3674: pptSpace->y = 0;
3675: }
3676: else
3677: {
3678: denom = pdev->psdm.dm.dmPrintQuality * cSpace;
3679:
3680: pptSpace->x = ((ptfxSExtra.x << 4) * PS_RESOLUTION) / denom;
3681: pptSpace->y = ((ptfxSExtra.y << 4) * PS_RESOLUTION) / denom;
3682: }
3683:
3684: if (cNonSpace == 0)
3685: {
3686: pptNonSpace->x = 0;
3687: pptNonSpace->y = 0;
3688: }
3689: else
3690: {
3691: denom = pdev->psdm.dm.dmPrintQuality * cNonSpace;
3692:
3693: pptNonSpace->x = ((ptfxNSExtra.x << 4) * PS_RESOLUTION) / denom;
3694: pptNonSpace->y = ((ptfxNSExtra.y << 4) * PS_RESOLUTION) / denom;
3695: }
3696:
3697: // free some memory.
3698:
3699: HeapFree(pdev->hheap, 0, (PVOID)pdeltaSave);
3700:
3701: return(TRUE);
3702: }
3703:
3704:
3705: //--------------------------------------------------------------------------
3706: // BOOL FillDeltaArray(pdev, pfo, pgp, pstro, pdelta, cGlyphs, pwsz)
3707: // PDEVDATA pdev;
3708: // FONTOBJ *pfo;
3709: // GLYPHPOS *pgp;
3710: // STROBJ *pstro;
3711: // TEXTDELTA *pdelta;
3712: // DWORD cGlyphs;
3713: // PWSZ pwsz;
3714: //
3715: // This routine fills in the given TEXTDELTA array from the given STROBJ.
3716: //
3717: // History:
3718: // 31-Mar-1993 -by- Kent Settle (kentse)
3719: // Wrote it.
3720: //--------------------------------------------------------------------------
3721:
3722: BOOL FillDeltaArray(pdev, pfo, pgp, pstro, pdelta, cGlyphs, pwsz)
3723: PDEVDATA pdev;
3724: FONTOBJ *pfo;
3725: GLYPHPOS *pgp;
3726: STROBJ *pstro;
3727: TEXTDELTA *pdelta;
3728: DWORD cGlyphs;
3729: PWSZ pwsz;
3730: {
3731: DWORD i;
3732: GLYPHDATA *pglyphdata;
3733: DWORD cReturned;
3734: GLYPHDATA glyphdata;
3735:
3736: if (!pwsz)
3737: {
3738: #if DBG
3739: DbgPrint("PSCRIPT!FillDeltaArray: NULL pwsz.\n");
3740: #endif
3741: return(FALSE);
3742: }
3743:
3744: // initialize pglyphdata for device font case.
3745:
3746: pglyphdata = &glyphdata;
3747:
3748: // fill in the TEXTDELTA structures.
3749:
3750: for (i = 0; i < (cGlyphs - 1); i++)
3751: {
3752: // get the UNICODE code point.
3753:
3754: pdelta->wc = *pwsz++;
3755:
3756: // get the delta vector as defined by the GLYPHPOS.
3757:
3758: pdelta->ptlpgp.x = (pgp + 1)->ptl.x - pgp->ptl.x;
3759: pdelta->ptlpgp.y = (pgp + 1)->ptl.y - pgp->ptl.y;
3760:
3761: if (pfo->flFontType & DEVICE_FONTTYPE)
3762: {
3763: if (!GetDeviceWidths(pdev, pfo, &glyphdata, pgp->hg))
3764: {
3765: RIP("PSCRIPT!FillDeltaArray: GetDeviceWidth failed.\n");
3766: return(FALSE);
3767: }
3768: }
3769: else
3770: {
3771: // now get the delta vector for the glyph itself.
3772:
3773: if (!(cReturned = FONTOBJ_cGetGlyphs(pfo, FO_GLYPHBITS, 1,
3774: &pgp->hg,
3775: (PVOID *)&pglyphdata)))
3776: {
3777: RIP("PSCRIPT!FillDeltaArray: cGetGlyphs failed.\n");
3778: return(FALSE);
3779: }
3780: }
3781:
3782: pdelta->ptfxorg.x = pglyphdata->ptqD.x.HighPart;
3783: pdelta->ptfxorg.y = pglyphdata->ptqD.y.HighPart;
3784:
3785: pgp++;
3786: pdelta++;
3787: }
3788:
3789: return(TRUE);
3790: }
3791:
3792:
3793: //--------------------------------------------------------------------------
3794: // PWSTR GetUnicodeString(pdev, pfo, pstro)
3795: // PDEVDATA pdev;
3796: // FONTOBJ *pfo;
3797: // STROBJ *pstro;
3798: //
3799: // This routine allocates a UNICODE string, and fills it is from the pstro.
3800: // This routine is ONLY called for device fonts.
3801: //
3802: // History:
3803: // 10-May-1993 -by- Kent Settle (kentse)
3804: // Wrote it.
3805: //--------------------------------------------------------------------------
3806:
3807: PWSTR GetUnicodeString(pdev, pfo, pstro)
3808: PDEVDATA pdev;
3809: FONTOBJ *pfo;
3810: STROBJ *pstro;
3811: {
3812: PWSTR pwstr, pwstrSave;
3813: BOOL bMore;
3814: PUCMap pmap;
3815: PNTFM pntfm;
3816: DWORD cGlyphs;
3817: GLYPHPOS *pgp;
3818:
3819: // allocate the UNICODE string, leaving room for NULL terminator.
3820:
3821: if (!(pwstr = (PWSTR)HeapAlloc(pdev->hheap, 0,
3822: ((pstro->cGlyphs + 1) * sizeof(WCHAR)))))
3823: {
3824: RIP("PSCRIPT!GetUnicodeString: HeapAlloc for pwstr failed.\n");
3825: return((PWSTR)NULL);
3826: }
3827:
3828: pwstrSave = pwstr;
3829:
3830: // prepare to enumerate the string.
3831:
3832: STROBJ_vEnumStart(pstro);
3833:
3834: // get the GLYPHPOS structure for each glyph. from that, get the
3835: // HGLYPH. from that, get the UNICODE codepoint, and jam that into
3836: // our allocate UNICODE string.
3837:
3838: // get the font metrics for the specified font.
3839:
3840: pntfm = pdev->pfmtable[pfo->iFace - 1].pntfm;
3841:
3842: // get local pointer to mapping table for current font.
3843:
3844: if (!strcmp((char *)pntfm + pntfm->loszFontName, "Symbol"))
3845: pmap = SymbolMap;
3846: else if (!strcmp((char *)pntfm + pntfm->loszFontName, "ZapfDingbats"))
3847: pmap = DingbatsMap;
3848: else
3849: pmap = LatinMap;
3850:
3851: if (pstro->pgp)
3852: ConstructUCString(pstro->pgp, pmap, pstro->cGlyphs, pwstr);
3853: else
3854: {
3855: do
3856: {
3857: bMore = STROBJ_bEnum(pstro, &cGlyphs, &pgp);
3858:
3859: ConstructUCString(pgp, pmap, cGlyphs, pwstr);
3860:
3861: pwstr += cGlyphs;
3862:
3863: } while (bMore);
3864: }
3865:
3866: return(pwstrSave);
3867: }
3868:
3869:
3870: //--------------------------------------------------------------------------
3871: // VOID ConstructUCString(pgp, pmap, cGlyphs, pwstr)
3872: // GLYPHPOS *pgp;
3873: // PUCMap pmap;
3874: // DWORD cGlyphs;
3875: // PWSTR pwstr;
3876: //
3877: // This routine constructs a UNICODE string from the pstro.
3878: // This routine is ONLY called for device fonts.
3879: //
3880: // History:
3881: // 10-May-1993 -by- Kent Settle (kentse)
3882: // Wrote it.
3883: //--------------------------------------------------------------------------
3884:
3885: VOID ConstructUCString(pgp, pmap, cGlyphs, pwstr)
3886: GLYPHPOS *pgp;
3887: PUCMap pmap;
3888: DWORD cGlyphs;
3889: PWSTR pwstr;
3890: {
3891: BOOL bFound;
3892: DWORD i;
3893: PUCMap pmapReset;
3894: WCHAR *pwc;
3895: CHAR jChar;
3896:
3897: // assume character not found in font.
3898:
3899: bFound = FALSE;
3900:
3901: pwc = pwstr;
3902: pmapReset = pmap;
3903:
3904: for (i = 0; i < cGlyphs; i++)
3905: {
3906: pmap = pmapReset;
3907:
3908: jChar = (CHAR)pgp->hg;
3909:
3910: while (pmap->szChar)
3911: {
3912: // search for the matching code in mapping.h. remember
3913: // that the high bit is used to indicate the font needs
3914: // to be remapped. so ignore the high bit while checking
3915: // for a character match.
3916:
3917: if (jChar == (CHAR)pmap->usPSValue)
3918: {
3919: bFound = TRUE;
3920:
3921: *pwc = (WCHAR)pmap->usUCValue;
3922: break;
3923: }
3924:
3925: // point to the next character in mapping.h.
3926:
3927: pmap++;
3928: } // while.
3929:
3930: // if the character in question was not found, replace it with
3931: // our default character.
3932:
3933: if (!bFound)
3934: {
3935: // get the unicode value for the period character.
3936:
3937: MultiByteToWideChar(CP_ACP, 0, (LPCSTR)".", 1, (LPWSTR)pwc, 1);
3938: }
3939:
3940: // point to the next glyph to fill in.
3941:
3942: pwc++;
3943:
3944: // point to the next GLYPHPOS structure.
3945:
3946: pgp++;
3947: }
3948:
3949: // add the NULL terminator.
3950:
3951: *pwc = (WCHAR)'\0';
3952: }
3953:
3954:
3955: //--------------------------------------------------------------------------
3956: // BOOL GetDeviceWidths(pdev, pfo, pgd, hg)
3957: // PDEVDATA pdev;
3958: // FONTOBJ *pfo;
3959: // GLYPHDATA *pgd;
3960: // HGLYPH hg;
3961: //
3962: // This routine fills in the width parameters of a GLYPHDATA
3963: // structure for the given HGLYPH. This is currently needed since
3964: // the journaling code does not allow us to do engine callbacks
3965: // such as FONTOBJ_cGetGlyphs with a device font.
3966: //
3967: // History:
3968: // 24-May-1993 -by- Kent Settle (kentse)
3969: // Wrote it.
3970: //--------------------------------------------------------------------------
3971:
3972: BOOL GetDeviceWidths(pdev, pfo, pgd, hg)
3973: PDEVDATA pdev;
3974: FONTOBJ *pfo;
3975: GLYPHDATA *pgd;
3976: HGLYPH hg;
3977: {
3978: PNTFM pntfm;
3979: XFORMOBJ *pxo;
3980: PBYTE pCharCode;
3981: PBYTE pCode;
3982: PUSHORT pCharWidth;
3983: int i;
3984: POINTL ptl;
3985: POINTFIX ptfx;
3986: LONG lWidth;
3987:
3988: // make sure we have been given a valid font.
3989:
3990: if ((pfo->iFace == 0) || (pfo->iFace > (pdev->cDeviceFonts + pdev->cSoftFonts)))
3991: {
3992: RIP("PSCRIPT!GetDeviceWidths: invalid iFace.\n");
3993: SetLastError(ERROR_INVALID_PARAMETER);
3994: return(FALSE);
3995: }
3996:
3997: // get the metrics for the given font.
3998:
3999: pntfm = pdev->pfmtable[pfo->iFace - 1].pntfm;
4000:
4001: // get the Notional to Device transform.
4002:
4003: if(!(pxo = FONTOBJ_pxoGetXform(pfo)))
4004: {
4005: RIP("PSCRIPT!DrvQueryFontData: pxo == NULL.\n");
4006: return(-1);
4007: }
4008:
4009: // get the font transform information.
4010:
4011: XFORMOBJ_iGetXform(pxo, &pdev->cgs.FontXform);
4012:
4013: // fill in the glyph widths portions of the GLYPHDATA structure.
4014:
4015: // We don't actually return bitmaps, but we give them
4016: // metrics via this call.
4017:
4018: // get a pointer to the character codes.
4019:
4020: pCharCode = ((PBYTE)pntfm + pntfm->loCharMetrics +
4021: DWORDALIGN(pntfm->cCharacters * sizeof(USHORT)));
4022:
4023: // get a pointer to the character widths.
4024:
4025: pCharWidth = (PUSHORT)((PBYTE)pntfm + pntfm->loCharMetrics);
4026:
4027: // now get the character width for the given GLYPH.
4028: // we set our HGLYPHs to be equal to the PostScript
4029: // character code for that given glyph. this allows
4030: // us to quickly search through our font metrics and
4031: // find the width for the given character.
4032:
4033: // first get a pointer to the character codes. once
4034: // the character has been found, we know how much to
4035: // index into the character widths and find the width
4036: // in question.
4037:
4038: pCode = pCharCode;
4039:
4040: for (i = 0; (USHORT)i < pntfm->cCharacters; i++)
4041: {
4042: if (*pCharCode++ == (BYTE)hg)
4043: break;
4044: }
4045:
4046: // now get the width in question.
4047:
4048: lWidth = (LONG)pCharWidth[i];
4049:
4050: #if 0
4051: // now fill in the GLYPHDATA structure.
4052: // remember under NT 0,0 is top left, while under
4053: // PostScript 0,0 is bottom left. return device coords.
4054:
4055: ptl.x = pntfm->rcBBox.left;
4056: ptl.y = 0;
4057:
4058: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl, &ptfx);
4059:
4060: pgd->rclInk.left = FXTOL(iHipot(ptfx.x, ptfx.y));
4061:
4062: ptl.x = pntfm->rcBBox.bottom;
4063: ptl.y = 0;
4064:
4065: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl, &ptfx);
4066:
4067: pgd->rclInk.top = FXTOL(iHipot(ptfx.x, ptfx.y));
4068:
4069: ptl.x = pntfm->rcBBox.right;
4070: ptl.y = 0;
4071:
4072: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl, &ptfx);
4073:
4074: pgd->rclInk.right = FXTOL(iHipot(ptfx.x, ptfx.y));
4075:
4076: ptl.x = pntfm->rcBBox.top;
4077: ptl.y = 0;
4078:
4079: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl, &ptfx);
4080:
4081: pgd->rclInk.bottom = FXTOL(iHipot(ptfx.x, ptfx.y));
4082: #endif
4083:
4084: ptl.x = lWidth;
4085: ptl.y = 0;
4086:
4087: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl, &ptfx);
4088:
4089: pgd->fxD = iHipot(ptfx.x, ptfx.y);
4090:
4091: pgd->ptqD.x.HighPart = ptfx.x;
4092: pgd->ptqD.x.LowPart = 0;
4093: pgd->ptqD.y.HighPart = ptfx.y;
4094: pgd->ptqD.y.LowPart = 0;
4095:
4096: #if 0
4097: pgd->fxA = 0;
4098: pgd->fxAB = pgd->fxD;
4099:
4100: pgd->fxInkTop = - LTOFX(pgd->rclInk.top);
4101: pgd->fxInkBottom = - LTOFX(pgd->rclInk.bottom);
4102: #endif
4103:
4104: pgd->hg = hg;
4105:
4106: return(TRUE);
4107: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.