|
|
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.