|
|
1.1 root 1: //--------------------------------------------------------------------------
2: //
3: // Module Name: FONTDATA.C
4: //
5: // Brief Description: Device font data querying routines
6: //
7: // Author: Kent Settle (kentse)
8: // Created: 25-Apr-1991
9: //
10: // Copyright (C) 1991 - 1992 Microsoft Corporation.
11: //
12: // This module contains DrvQueryFontData and related routines.
13: //
14: // History:
15: // 25-Apr-1991 -by- Kent Settle (kentse)
16: // Created.
17: //--------------------------------------------------------------------------
18:
19: #include "pscript.h"
20: #include "enable.h"
21: #include "resource.h"
22: #include <memory.h>
23: #include "winbase.h"
24:
25: #define WIN31_INTEGER_METRICS
26:
27: extern HMODULE ghmodDrv; // GLOBAL MODULE HANDLE.
28: extern LONG iHipot(LONG, LONG);
29:
30: //--------------------------------------------------------------------------
31: // LONG DrvQueryFontData (dhpdev,pfo,iMode,cData,pvIn,pvOut)
32: // DHPDEV dhpdev;
33: // PFONTOBJ pfo;
34: // ULONG iMode;
35: // ULONG cData;
36: // PVOID pvIn;
37: // PVOID pvOut;
38: //
39: // This function is used to return information about a realized font.
40: // GDI provides a pointer to an array of glyph or kerning handles and
41: // the driver returns information about the glyphs or kerning pairs.
42: // The driver may assume that all handles in the array are valid.
43: //
44: // Parameters:
45: // dhpdev
46: // This is a PDEV handle returned from a call to DrvEnablePDEV.
47: //
48: // pfo
49: // This is a pointer to a FONTOBJ. Details of the font realization
50: // can be queried from this object.
51: //
52: // iMode
53: // This defines the information requested. This may take one of the
54: // following values.
55: //
56: // QFD_GLYPH GDI has placed an array of cData HGLYPHs at pvIn.
57: // If pvOut is not NULL the driver must return an array
58: // of corresponding GLYPHDATA structures to the buffer
59: // at pvOut. If pvOut is NULL then the driver should return
60: // only the size of the buffer needed for output.
61: //
62: // QFD_KERNPAIR GDI has placed an array of cData HKERNs at pvIn.
63: // If pvOut is not NULL the driver must return an array of
64: // corresponding POINTLs to the buffer at pvOUt, each of
65: // which describes a kerning adjustment. If pvOut if NULL
66: // the driver should return only the size of the buffer
67: // needed for output.
68: //
69: //
70: // cData
71: // A count of input items at pvIn. The interpretation of this count
72: // depends on iMode.
73: //
74: // pvIn
75: // This is a pointer to an array of cData handles.If iMode is equal to
76: // DRV_FONTDATA_GLYPH then these are glyph handles (HGLYPHs). If iMode
77: // is DRV_FONTDATA_KERNPAIR then the handles identify kerning pairs
78: // (HKERNS). The driver may assume that all handles are valid.
79: //
80: // Returns:
81: // The return value is either the number of BYTEs needed or the number of
82: // BYTEs written, depending on iMode. In all cases a return value of
83: // -1 indicates an error, and an error code is logged.
84: //
85: //
86: // History:
87: // 25-Apr-1991 -by- Kent Settle (kentse)
88: // Wrote it.
89: //--------------------------------------------------------------------------
90:
91: LONG DrvQueryFontData (dhpdev,pfo,iMode,hg,pgd,pv,cjSize)
92: DHPDEV dhpdev;
93: FONTOBJ *pfo;
94: ULONG iMode;
95: HGLYPH hg;
96: GLYPHDATA *pgd;
97: PVOID pv;
98: ULONG cjSize;
99: {
100: PNTFM pntfm = NULL;
101: LONG lWidth;
102: PBYTE pCharCode;
103: PBYTE pCode;
104: PUSHORT pCharWidth;
105: int i;
106: PDEVDATA pdev;
107: XFORMOBJ *pxo;
108: ULONG ulComplex;
109: PIFIMETRICS pifi;
110: POINTL ptl1, ptl2;
111: POINTFIX ptfx1;
112: FD_DEVICEMETRICS *pdm = (FD_DEVICEMETRICS *)pv;
113: FIX fxLength, fxExtLeading;
114: LONG lfHeight, InternalLeading;
115: FD_REALIZEEXTRA *pre = NULL;
116: DWORD dwPointSize, dwLeadSuggest;
117:
118: #ifdef TESTING
119: DbgPrint("Entering DrvQueryFontData.\n");
120: #endif
121:
122: pdev = (PDEVDATA)dhpdev;
123:
124: if (bValidatePDEV(pdev) == FALSE)
125: return(-1);
126:
127: // make sure we have been given a valid font.
128:
129: if ((pfo->iFace == 0) || (pfo->iFace > (pdev->cDeviceFonts + pdev->cSoftFonts)))
130: {
131: RIP("PSCRIPT!DrvQueryFontData: invalid iFace.\n");
132: SetLastError(ERROR_INVALID_PARAMETER);
133: return(-1);
134: }
135:
136: // get the metrics for the given font.
137:
138: pntfm = pdev->pfmtable[pfo->iFace - 1].pntfm;
139:
140: // get the Notional to Device transform.
141:
142: if(!(pxo = FONTOBJ_pxoGetXform(pfo)))
143: {
144: RIP("PSCRIPT!DrvQueryFontData: pxo == NULL.\n");
145: return(-1);
146: }
147:
148: // get the font transform information.
149:
150: ulComplex = XFORMOBJ_iGetXform(pxo, &pdev->cgs.FontXform);
151:
152: // get local pointer to IFIMETRICS.
153:
154: pifi = (PIFIMETRICS)((CHAR *)pntfm + pntfm->loIFIMETRICS);
155:
156: // fill in the appropriate data, depending on iMode.
157:
158: switch(iMode)
159: {
160: case QFD_GLYPHANDBITMAP:
161: // We don't actually return bitmaps, but we give them
162: // metrics via this call.
163:
164: if (pgd)
165: {
166: // get a pointer to the character codes.
167:
168: pCharCode = ((PBYTE)pntfm + pntfm->loCharMetrics +
169: DWORDALIGN(pntfm->cCharacters * sizeof(USHORT)));
170:
171: // get a pointer to the character widths.
172:
173: pCharWidth = (PUSHORT)((PBYTE)pntfm + pntfm->loCharMetrics);
174:
175: // now get the character width for the given GLYPH.
176: // we set our HGLYPHs to be equal to the PostScript
177: // character code for that given glyph. this allows
178: // us to quickly search through our font metrics and
179: // find the width for the given character.
180:
181: // first get a pointer to the character codes. once
182: // the character has been found, we know how much to
183: // index into the character widths and find the width
184: // in question.
185:
186: pCode = pCharCode;
187:
188: for (i = 0; (USHORT)i < pntfm->cCharacters; i++)
189: {
190: if (*pCharCode++ == (BYTE)hg)
191: break;
192: }
193:
194: // now get the width in question.
195:
196: lWidth = (LONG)pCharWidth[i];
197:
198: //!!! currently, I am just putting the BBox for the font here, not
199: //!!! for the character. Does anyone care? - kentse.
200:
201: // now fill in the GLYPHDATA structure.
202: // remember under NT 0,0 is top left, while under
203: // PostScript 0,0 is bottom left. return device coords.
204:
205: #ifdef THIS_IS_WRONG
206: //!!! but fortunatelly it is also useless except for tt fonts [bodind]
207: //!!! rclInk is measured along x,y, not along base,side unit vectors
208:
209: ptl1.x = pntfm->rcBBox.left;
210: ptl1.y = 0;
211: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx1);
212: pgd->rclInk.left = FXTOL(iHipot(ptfx1.x, ptfx1.y));
213:
214: ptl1.x = pntfm->rcBBox.right;
215: ptl1.y = 0;
216: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx1);
217: pgd->rclInk.right = FXTOL(iHipot(ptfx1.x, ptfx1.y));
218:
219: ptl1.x = 0;
220: ptl1.y = -pntfm->rcBBox.bottom;
221: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx1);
222: pgd->rclInk.bottom = FXTOL(iHipot(ptfx1.x, ptfx1.y));
223:
224:
225: ptl1.x = 0;
226: ptl1.y = -pntfm->rcBBox.top;
227: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx1);
228: pgd->rclInk.top = FXTOL(iHipot(ptfx1.x, ptfx1.y));
229:
230: #endif // THIS_IS_WRONG
231:
232: // fxInkBottom,Top are measured along pteSide vector:
233:
234: ptl1.x = 0;
235: ptl1.y = pntfm->rcBBox.bottom;
236: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx1);
237: pgd->fxInkBottom = iHipot(ptfx1.x, ptfx1.y);
238: if (pntfm->rcBBox.bottom < 0)
239: pgd->fxInkBottom = -pgd->fxInkBottom;
240:
241: ptl1.x = 0;
242: ptl1.y = pntfm->rcBBox.top;
243: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx1);
244: pgd->fxInkTop = iHipot(ptfx1.x, ptfx1.y);
245: if (pntfm->rcBBox.top < 0)
246: pgd->fxInkTop = -pgd->fxInkTop;
247:
248: #ifdef WIN31_INTEGER_METRICS
249: pgd->fxInkBottom = ROUNDFIX(pgd->fxInkBottom);
250: pgd->fxInkTop = ROUNDFIX(pgd->fxInkTop);
251: #endif
252:
253: // aw info, ideally we would like more precission than 28.4
254: // in case of text at an angle. [bodind]
255:
256: ptl1.x = lWidth;
257: ptl1.y = 0;
258:
259: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx1);
260:
261: pgd->fxD = iHipot(ptfx1.x, ptfx1.y);
262:
263: pgd->ptqD.x.HighPart = ptfx1.x;
264: pgd->ptqD.x.LowPart = 0;
265: pgd->ptqD.y.HighPart = ptfx1.y;
266: pgd->ptqD.y.LowPart = 0;
267:
268: #ifdef WIN31_INTEGER_METRICS
269: pgd->fxD = ROUNDFIX(pgd->fxD);
270: pgd->ptqD.x.HighPart = ROUNDFIX(pgd->ptqD.x.HighPart);
271: pgd->ptqD.y.HighPart = ROUNDFIX(pgd->ptqD.y.HighPart);
272: #endif
273:
274: //!!! often wrong but it seems win31 is doing the same thing
275: //!!! this may cause char to stick outside the computed
276: //!!! background box. try ZapfChancery on NT and Win31
277:
278: pgd->fxA = 0;
279: pgd->fxAB = pgd->fxD;
280:
281: pgd->hg = hg;
282: }
283:
284: // size is now just the size of the (in this case non-existant)
285: // bitmap
286: return 0;
287:
288:
289: case QFD_MAXEXTENTS:
290: // if there is no output buffer, just return the size needed.
291:
292: if (pv == NULL)
293: return((LONG)sizeof(FD_DEVICEMETRICS));
294:
295: ASSERTPS(
296: cjSize >= sizeof(FD_DEVICEMETRICS),
297: "pscript! cjSize < sizeof(FD_DEVICEMETRICS)\n"
298: );
299:
300: // we have a large enough buffer, so fill it in.
301:
302: pdm->flRealizedType = 0;
303:
304: // base and side, as used below, basically are vectors
305: // describing the orientation of the font. for example,
306: // for a left to right font, the base vector would be
307: // (1,0). the side vector should be in the direction of
308: // the ascender, so in the standard case the side vector
309: // would be (0,-1), since 0 is up in Windows.
310:
311: ptl1.x = 1000;
312: ptl1.y = 0;
313:
314: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx1);
315:
316: fxLength = iHipot(ptfx1.x, ptfx1.y);
317:
318: pdm->pteBase.x = (FLOAT)ptfx1.x / fxLength;
319: pdm->pteBase.y = (FLOAT)ptfx1.y / fxLength;
320:
321: ptl1.x = 0;
322: ptl1.y = -1000;
323:
324: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx1);
325:
326: fxLength = iHipot(ptfx1.x, ptfx1.y);
327:
328: pdm->pteSide.x = (FLOAT)ptfx1.x / fxLength;
329: pdm->pteSide.y = (FLOAT)ptfx1.y / fxLength;
330:
331: // munge with the FD_REALIZEEXTRA external leading field for
332: // win31 compatability.
333:
334: if (pgd)
335: {
336: // -fxLength is the FIX 28.4 lfHeight in pels.
337:
338: lfHeight = abs(FXTOL(fxLength));
339:
340: // get point size as win31 does.
341:
342: dwPointSize = (DWORD)MulDiv(lfHeight, PS_RESOLUTION,
343: pdev->psdm.dm.dmPrintQuality);
344:
345: if (pifi->jWinPitchAndFamily & FF_ROMAN)
346: {
347: dwLeadSuggest = 2;
348: }
349: else if (pifi->jWinPitchAndFamily & FF_SWISS)
350: {
351: if (dwPointSize <= 12)
352: dwLeadSuggest = 2;
353: else if (dwPointSize < 14)
354: dwLeadSuggest = 3;
355: else
356: dwLeadSuggest = 4;
357: }
358: else
359: {
360: // default to 19.6%.
361:
362: dwLeadSuggest = (DWORD)MulDiv(dwPointSize, 196,
363: ADOBE_FONT_UNITS);
364: }
365:
366: // get notional internal leading.
367:
368: InternalLeading = (pntfm->rcBBox.top - pntfm->rcBBox.bottom) -
369: ADOBE_FONT_UNITS;
370:
371: // make it device coordinates.
372:
373: InternalLeading = MulDiv(InternalLeading, lfHeight,
374: ADOBE_FONT_UNITS);
375:
376: if (InternalLeading < 0)
377: InternalLeading = 0;
378:
379: fxExtLeading = LTOFX(MulDiv(dwLeadSuggest,
380: pdev->psdm.dm.dmPrintQuality,
381: PS_RESOLUTION) - InternalLeading);
382:
383: // if the external leading was calculated to be negative, or
384: // if this is a fixed pitch font, set external leading to
385: // zero.
386:
387: if ((fxExtLeading < 0) ||
388: (pifi->jWinPitchAndFamily & FIXED_PITCH))
389: fxExtLeading = 0;
390:
391: // fill in the leading field of the FD_REALIZEEXTRA struct.
392:
393: ((FD_REALIZEEXTRA *)pgd)->lExtLeading = (LONG)fxExtLeading;
394:
395: if (pifi->jWinPitchAndFamily & FIXED_PITCH)
396: ((FD_REALIZEEXTRA *)pgd)->alReserved[0] = 0;
397: }
398:
399: // cxMax the same as max char width for a and c's are zero:
400:
401: ptl1.x = pifi->fwdMaxCharInc;
402: ptl1.y = 0;
403:
404: XFORMOBJ_bApplyXform(pxo, XF_LTOL, 1, &ptl1, &ptl2);
405:
406: // now get the length of the vector.
407:
408: pdm->cxMax = iHipot(ptl2.x, ptl2.y);
409:
410: // lD is the advance width if the font is fixed pitch,
411: // otherwise, set to zero.
412:
413: if(pifi->fwdMaxCharInc != pifi->fwdAveCharWidth)
414: pdm->lD = 0;
415: else
416: {
417: pdm->lD = (LONG)pdm->cxMax;
418: }
419:
420: // calculate the max ascender.
421:
422: ptl1.x = 0;
423: ptl1.y = pntfm->rcBBox.top;
424:
425: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx1);
426:
427: pdm->fxMaxAscender = iHipot(ptfx1.x, ptfx1.y);
428:
429: // calculate the max descender.
430:
431: ptl1.x = 0;
432: ptl1.y = pntfm->rcBBox.bottom;
433:
434: if (ptl1.y < 0)
435: ptl1.y = -ptl1.y;
436:
437: // do the ugly fixed pitch means zero internal leading hack.
438:
439: if (pifi->jWinPitchAndFamily & FIXED_PITCH)
440: {
441: // get notional internal leading.
442:
443: InternalLeading = (pntfm->rcBBox.top - pntfm->rcBBox.bottom) -
444: ADOBE_FONT_UNITS;
445:
446: // WFW seems to make all the adjustment here in the
447: // MaxDescender, so we will too.
448:
449: ptl1.y -= InternalLeading;
450:
451: if (ptl1.y < 0)
452: ptl1.y = 0;
453: }
454:
455: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx1);
456:
457: pdm->fxMaxDescender = iHipot(ptfx1.x, ptfx1.y);
458:
459: #ifdef WIN31_INTEGER_METRICS
460: pdm->fxMaxAscender = ROUNDFIX(pdm->fxMaxAscender);
461: pdm->fxMaxDescender = ROUNDFIX(pdm->fxMaxDescender);
462: #endif
463:
464: // calculate the underline position for this font instance.
465:
466: ptl1.x = 0;
467: ptl1.y = - pifi->fwdUnderscorePosition;
468:
469: XFORMOBJ_bApplyXform(pxo, XF_LTOL, 1, &ptl1, &pdm->ptlUnderline1);
470:
471: // calculate the strikeout position for this font instance.
472:
473: ptl1.x = 0;
474: ptl1.y = - (pntfm->fwdLowerCaseAscent / 2);
475:
476: XFORMOBJ_bApplyXform(pxo, XF_LTOL, 1, &ptl1, &pdm->ptlStrikeOut);
477:
478: // calculate the line thickness.
479:
480: ptl1.x = 0;
481: ptl1.y = pifi->fwdUnderscoreSize;
482:
483: XFORMOBJ_bApplyXform(pxo, XF_LTOL, 1, &ptl1, &pdm->ptlULThickness);
484:
485: pdm->ptlSOThickness = pdm->ptlULThickness;
486:
487: return(sizeof(FD_DEVICEMETRICS));
488:
489:
490: default:
491: RIP("PSCRIPT!DrvQueryFontData: invalid iMode.\n");
492: return(-1);
493: }
494: }
495:
496:
497: //--------------------------------------------------------------------------
498: // BOOL DrvQueryAdvanceWidths(
499: // DHPDEV dhpdev,
500: // FONTOBJ *pfo,
501: // ULONG iMode,
502: // HGLYPH *phg,
503: // PVOID plWidths,
504: // ULONG cGlyphs);
505: //
506: // This routine returns an array of FIX (28.4) widths in pels of the
507: // indicated glyphs.
508: //
509: // History:
510: // 23-Jan-1993 -by- Kent Settle (kentse)
511: // Wrote it.
512: //--------------------------------------------------------------------------
513:
514: BOOL DrvQueryAdvanceWidths(
515: DHPDEV dhpdev,
516: FONTOBJ *pfo,
517: ULONG iMode,
518: HGLYPH *phg,
519: PVOID plWidths,
520: ULONG cGlyphs)
521: {
522: PDEVDATA pdev;
523: ULONG i, j;
524: PNTFM pntfm;
525: HGLYPH *phglyph;
526: USHORT *pwidth;
527: USHORT *pCharWidth;
528: PBYTE pCharCode;
529: PBYTE pCode;
530: XFORMOBJ *pxo;
531: POINTL ptl;
532: POINTFIX ptfx;
533: #ifdef WIN31_INTEGER_METRICS
534: POINTL ptl2;
535: FIX fxLength;
536: LONG lfHeight;
537: #endif
538:
539: pdev = (PDEVDATA)dhpdev;
540:
541: if (bValidatePDEV(pdev) == FALSE)
542: return(FALSE);
543:
544: // for now we will treat GETWIDTHS and GETEASYWIDTHS the same.
545:
546: if ((iMode != QAW_GETWIDTHS) && (iMode != QAW_GETEASYWIDTHS))
547: {
548: SetLastError(ERROR_INVALID_PARAMETER);
549: #if DBG
550: DbgPrint("PSCRIPT!DrvQueryAdvanceWidths: invalid iMode.\n");
551: #endif
552: return(FALSE);
553: }
554:
555: // see if there is anything to do.
556:
557: if (!cGlyphs)
558: return(TRUE);
559:
560: // make sure we have been given a valid font.
561:
562: if ((pfo->iFace == 0) ||
563: (pfo->iFace > (pdev->cDeviceFonts + pdev->cSoftFonts)))
564: {
565: RIP("PSCRIPT!DrvQueryAdvanceWidths: invalid iFace.\n");
566: SetLastError(ERROR_INVALID_PARAMETER);
567: return(FALSE);
568: }
569:
570: // get the metrics for the given font.
571:
572: pntfm = pdev->pfmtable[pfo->iFace - 1].pntfm;
573:
574: // get a pointer to the character widths.
575:
576: pCharWidth = (PUSHORT)((PBYTE)pntfm + pntfm->loCharMetrics);
577:
578: // get a pointer to the character codes.
579:
580: pCharCode = ((PBYTE)pntfm + pntfm->loCharMetrics +
581: DWORDALIGN(pntfm->cCharacters * sizeof(USHORT)));
582:
583: // get the Notional to Device transform.
584:
585: if(!(pxo = FONTOBJ_pxoGetXform(pfo)))
586: {
587: RIP("PSCRIPT!DrvQueryAdvancedWidths: pxo == NULL.\n");
588: return(FALSE);
589: }
590:
591: // get some local pointers to munge with.
592:
593: phglyph = phg;
594: pwidth = (USHORT *) plWidths;
595:
596: for (i = 0; i < cGlyphs; i++)
597: {
598: pCode = pCharCode;
599:
600: for (j = 0; (USHORT)j < pntfm->cCharacters; j++)
601: {
602: if (*pCode++ == (BYTE)*phglyph)
603: break;
604: }
605:
606: // now get the width in question.
607:
608: #ifdef WIN31_INTEGER_METRICS
609: ptl.x = 0;
610: ptl.y = 1000;
611:
612: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl, &ptfx);
613:
614: fxLength = iHipot(ptfx.x, ptfx.y);
615:
616: lfHeight = abs(FXTOL(fxLength));
617:
618: *pwidth = LTOFX(MulDiv(pCharWidth[j], lfHeight, ADOBE_FONT_UNITS));
619: #else
620: ptl.x = (LONG)pCharWidth[j];
621: ptl.y = 0;
622:
623: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl, &ptfx);
624:
625: *pwidth = (USHORT)iHipot(ptfx.x, ptfx.y);
626: #endif
627:
628: // get the next glyph.
629:
630: phglyph++;
631: pwidth++;
632: }
633:
634: return(TRUE);
635: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.