|
|
1.1 ! root 1: //-------------------------------------------------------------------------- ! 2: // ! 3: // Module Name: ESCAPE.C ! 4: // ! 5: // Brief Description: This module contains the PSCRIPT driver's Escape ! 6: // functions and related routines. ! 7: // ! 8: // Author: Kent Settle (kentse) ! 9: // Created: 08-Feb-1991 ! 10: // ! 11: // Copyright (c) 1991 - 1992 Microsoft Corporation ! 12: // ! 13: // This routine contains routines to handle the various Escape functions. ! 14: //-------------------------------------------------------------------------- ! 15: ! 16: #include "pscript.h" ! 17: #include "enable.h" ! 18: ! 19: // DrawEscape to output encapsulated PostScript data. ! 20: ! 21: typedef struct tagEPSDATA ! 22: { ! 23: DWORD cbData; // Size of the structure and EPS data in bytes. ! 24: DWORD nVersion; // Language level, e.g. 1 for level 1 PostScript. ! 25: POINTL aptl[3]; // Output parallelogram in 28.4 FIX device coords. ! 26: // This is followed by the EPS data. ! 27: } EPSDATA, *PEPSDATA; ! 28: ! 29: FLOAT FixToFloat(FIX); ! 30: BOOL bDoEpsXform(PDEVDATA, PEPSDATA); ! 31: extern BOOL bDoClipObj(PDEVDATA, CLIPOBJ *, RECTL *, RECTL *, BOOL *, BOOL *, DWORD); ! 32: ! 33: #define ESC_NOT_SUPPORTED 0xFFFFFFFF ! 34: #define ESC_IS_SUPPORTED 0x00000001 ! 35: ! 36: //-------------------------------------------------------------------------- ! 37: // ULONG DrvEscape (pso, iEsc, cjIn, pvIn, cjOut, pvOut) ! 38: // SURFOBJ *pso; ! 39: // ULONG iEsc; ! 40: // ULONG cjIn; ! 41: // PVOID pvIn; ! 42: // ULONG cjOut; ! 43: // PVOID pvOut; ! 44: // ! 45: // This entry point serves more than one function call. The particular ! 46: // function depends on the value of the iEsc parameter. ! 47: // ! 48: // In general, the DrvEscape functions will be device specific functions ! 49: // that don't belong in a device independent DDI. This entry point is ! 50: // optional for all devices. ! 51: // ! 52: // Parameters: ! 53: // pso ! 54: // Identifies the surface that the call is directed to. ! 55: // ! 56: // iEsc ! 57: // Specifies the particular function to be performed. The meaning of ! 58: // the remaining arguments depends on this parameter. Allowed values ! 59: // are as follows. ! 60: // ! 61: // ESC_QUERYESCSUPPORT ! 62: // Asks if the driver supports a particular escape function. The ! 63: // escape function number is a ULONG pointed to by pvIn. A non-zero ! 64: // value should be returned if the function is supported. cjIn has a ! 65: // value of 4. The arguments cjOut and pvOut are ignored. ! 66: // ! 67: // ESC_PASSTHROUGH ! 68: // Passes raw device data to the device driver. The number of BYTEs of ! 69: // raw data is indicated by cjIn. The data is pointed to by pvIn. The ! 70: // arguments cjOut and pvOut are ignored. Returns the number of BYTEs ! 71: // written if the function is successful. Otherwise, it returns zero ! 72: // and logs an error code. ! 73: // cjIn ! 74: // The size, in BYTEs, of the data buffer pointed to by pvIn. ! 75: // ! 76: // pvIn ! 77: // The input data for the call. The format of the input data depends ! 78: // on the function specified by iEsc. ! 79: // ! 80: // cjOut ! 81: // The size, in BYTEs, of the output data buffer pointed to by pvOut. ! 82: // The driver must never write more than this many BYTEs to the output ! 83: // buffer. ! 84: // ! 85: // pvOut ! 86: // The output buffer for the call. The format of the output data depends ! 87: // on the function specified by iEsc. ! 88: // ! 89: // Returns: ! 90: // Depends on the function specified by iEsc. In general, the driver should ! 91: // return 0xFFFFFFFF if an unsupported function is called. ! 92: // ! 93: // History: ! 94: // 02-Feb-1991 -by- Kent Settle (kentse) ! 95: // Wrote it. ! 96: //-------------------------------------------------------------------------- ! 97: ! 98: ULONG DrvEscape (pso, iEsc, cjIn, pvIn, cjOut, pvOut) ! 99: SURFOBJ *pso; ! 100: ULONG iEsc; ! 101: ULONG cjIn; ! 102: PVOID pvIn; ! 103: ULONG cjOut; ! 104: PVOID pvOut; ! 105: { ! 106: PDEVDATA pdev; ! 107: DWORD cWritten; ! 108: FLOAT *pfloat; ! 109: LONG ytmp; ! 110: ULONG ulRet = ESC_NOT_SUPPORTED; ! 111: ! 112: // handle each case depending on which escape function is being asked for. ! 113: ! 114: switch (iEsc) ! 115: { ! 116: case QUERYESCSUPPORT: ! 117: // when querying escape support, the function in question is ! 118: // passed in the ULONG passed in pvIn. ! 119: ! 120: switch (*(PULONG)pvIn) ! 121: { ! 122: case QUERYESCSUPPORT: ! 123: case PASSTHROUGH: ! 124: case POSTSCRIPT_PASSTHROUGH: ! 125: case GETDEVICEUNITS: ! 126: return(ESC_IS_SUPPORTED); ! 127: ! 128: case SETCOPYCOUNT: ! 129: return(MAX_COPIES); ! 130: ! 131: default: ! 132: // return 0 if the escape in question is not supported. ! 133: ! 134: return(0); ! 135: } ! 136: ! 137: case POSTSCRIPT_PASSTHROUGH: ! 138: case PASSTHROUGH: ! 139: // get the pointer to our DEVDATA structure and make sure it is ours. ! 140: ! 141: pdev = (PDEVDATA) pso->dhpdev; ! 142: ! 143: if (bValidatePDEV(pdev) == FALSE) ! 144: { ! 145: RIP("PSCRIPT!DrvEscape: invalid pdev.\n"); ! 146: SetLastError(ERROR_INVALID_PARAMETER); ! 147: ulRet = 0; ! 148: break; ! 149: } ! 150: ! 151: // do nothing if the document has been cancelled. ! 152: ! 153: if (pdev->dwFlags & PDEV_CANCELDOC) ! 154: return(*(LPWORD)pvIn); ! 155: ! 156: if (iEsc == POSTSCRIPT_PASSTHROUGH) ! 157: { ! 158: // initialize the current graphics state. ! 159: ! 160: init_cgs(pdev); ! 161: ! 162: if (pdev->dwFlags & PDEV_WITHINPAGE) ! 163: { ! 164: ps_restore(pdev, FALSE); ! 165: pdev->dwFlags &= ~PDEV_WITHINPAGE; ! 166: } ! 167: ! 168: if (pdev->dwFlags & PDEV_PROCSET) ! 169: { ! 170: PrintString(pdev, "end\n"); ! 171: pdev->dwFlags &= ~PDEV_PROCSET; ! 172: } ! 173: } ! 174: ! 175: pdev->dwFlags |= PDEV_RAWDATASENT; ! 176: ! 177: // just write out what is in the buffer. do NOT add a ! 178: // header to the output. that would be wrong. ! 179: ! 180: bPSFlush(pdev); ! 181: ! 182: cjIn = (*(LPWORD)pvIn); ! 183: pvIn = (LPVOID)(((LPWORD)pvIn) + 1); ! 184: ! 185: if (!WritePrinter(pdev->hPrinter, pvIn, cjIn, &cWritten)) ! 186: { ! 187: DbgPrint("PSCRIPT!DrvEscape PASSTHROUGH: WritePrinter failed.\n"); ! 188: ulRet = 0; ! 189: break; ! 190: } ! 191: else ! 192: ulRet = cWritten; ! 193: ! 194: break; ! 195: ! 196: case GETDEVICEUNITS: ! 197: // get the pointer to our DEVDATA structure and make sure it is ours. ! 198: ! 199: pdev = (PDEVDATA) pso->dhpdev; ! 200: ! 201: if ((bValidatePDEV(pdev) == FALSE) || (cjOut < (sizeof(LONG) * 4))) ! 202: { ! 203: RIP("PSCRIPT!DrvEscape GETDEVICEUNITS: invalid pdev or cjOut.\n"); ! 204: SetLastError(ERROR_INVALID_PARAMETER); ! 205: ulRet = 0; ! 206: break; ! 207: } ! 208: ! 209: pfloat = (FLOAT *)pvOut; ! 210: ! 211: // fill in the first two bytes with the resolution we actually ! 212: // send to the printer. ! 213: ! 214: *pfloat++ =(FLOAT)(pdev->CurForm.imagearea.right - ! 215: pdev->CurForm.imagearea.left); ! 216: ! 217: // handle landscape vs portrait. ! 218: ! 219: ytmp = pdev->CurForm.imagearea.bottom - ! 220: pdev->CurForm.imagearea.top; ! 221: ! 222: #ifndef LANDSCAPE_270_ROTATE // 90 degree case. ! 223: if ((pdev->psdm.dm.dmFields & DM_ORIENTATION) && ! 224: (pdev->psdm.dm.dmOrientation == DMORIENT_LANDSCAPE)) ! 225: ytmp = -ytmp; ! 226: #endif ! 227: ! 228: *pfloat++ = (FLOAT)ytmp; ! 229: ! 230: // now fill in the offset of our origin from the upper left ! 231: // corner of the piece of paper. ! 232: ! 233: *pfloat++ = (FLOAT)pdev->CurForm.imagearea.left; ! 234: ! 235: ytmp = pdev->CurForm.imagearea.top; ! 236: ! 237: *pfloat = (FLOAT)ytmp; ! 238: ! 239: ulRet = TRUE; ! 240: break; ! 241: ! 242: case SETCOPYCOUNT: ! 243: // the copy count is a DWORD count sitting at pvIn. ! 244: ! 245: if (!pvIn) ! 246: { ! 247: ulRet = 0; ! 248: break; ! 249: } ! 250: ! 251: // get the pointer to our DEVDATA structure and make sure it is ours. ! 252: ! 253: pdev = (PDEVDATA) pso->dhpdev; ! 254: ! 255: if (bValidatePDEV(pdev) == FALSE) ! 256: { ! 257: RIP("PSCRIPT!DrvEscape: invalid pdev.\n"); ! 258: SetLastError(ERROR_INVALID_PARAMETER); ! 259: ulRet = 0; ! 260: break; ! 261: } ! 262: ! 263: // if user specified zero or one copy, do nothing. one ! 264: // copy will be printed by default. ! 265: ! 266: if (*(DWORD *)pvIn <= MIN_COPIES) ! 267: { ! 268: // let the caller know how many copies we will do. ! 269: ! 270: pdev->cCopies = 1; ! 271: ! 272: if (pvOut) ! 273: *(DWORD *)pvOut = pdev->cCopies; ! 274: ! 275: ulRet = TRUE; ! 276: break; ! 277: } ! 278: ! 279: // we have a positive number of copies. let's set a limit. ! 280: ! 281: pdev->cCopies = min(*(DWORD *)pvIn, MAX_COPIES); ! 282: ! 283: // let the caller know how many copies we will do. ! 284: ! 285: if (pvOut) ! 286: *(DWORD *)pvOut = pdev->cCopies; ! 287: ! 288: ulRet = TRUE; ! 289: break; ! 290: ! 291: default: ! 292: // if we get to the default case, we have been passed an ! 293: // unsupported escape function number. ! 294: ! 295: DbgPrint("PSCRIPT!DrvEscape %x ESC_NOT_SUPPORTED.\n", iEsc); ! 296: ulRet = ESC_NOT_SUPPORTED; ! 297: break; ! 298: ! 299: } ! 300: ! 301: return(ulRet); ! 302: } ! 303: ! 304: //-------------------------------------------------------------------------- ! 305: // ULONG DrvDrawEscape( ! 306: // SURFOBJ *pso, ! 307: // ULONG iEsc, ! 308: // CLIPOBJ *pco, ! 309: // RECTL *prcl, ! 310: // ULONG cjIn, ! 311: // PVOID pvIn); ! 312: // ! 313: // Supports the ESCAPSULATED_POSTSCRIPT escape. ! 314: // ! 315: // History: ! 316: // Sat May 08 13:27:52 1993 -by- Hock San Lee [hockl] ! 317: // Wrote it. ! 318: //-------------------------------------------------------------------------- ! 319: ! 320: ULONG DrvDrawEscape( ! 321: SURFOBJ *pso, ! 322: ULONG iEsc, ! 323: CLIPOBJ *pco, ! 324: RECTL *prcl, ! 325: ULONG cjIn, ! 326: PVOID pvIn) ! 327: { ! 328: PDEVDATA pdev; ! 329: DWORD cWritten; ! 330: PEPSDATA pEpsData; ! 331: BOOL bRet; ! 332: BOOL bFirstClipPass; // TRUE 1st call to bDoClipObj. ! 333: BOOL bMoreClipping; // TRUE if more clipping to enumerate. ! 334: BOOL bClipping; // TRUE if clipping being done. ! 335: ! 336: // handle each case depending on which escape function is being asked for. ! 337: ! 338: switch (iEsc) ! 339: { ! 340: case QUERYESCSUPPORT: ! 341: // when querying escape support, the function in question is ! 342: // passed in the ULONG passed in pvIn. ! 343: ! 344: switch (*(PULONG)pvIn) ! 345: { ! 346: case QUERYESCSUPPORT: ! 347: case ENCAPSULATED_POSTSCRIPT: ! 348: return(ESC_IS_SUPPORTED); ! 349: ! 350: default: ! 351: // return 0 if the escape in question is not supported. ! 352: return(0); ! 353: } ! 354: ! 355: case ENCAPSULATED_POSTSCRIPT: ! 356: ! 357: // get the pointer to our DEVDATA structure and make sure it is ours. ! 358: ! 359: pdev = (PDEVDATA) pso->dhpdev; ! 360: ! 361: if (bValidatePDEV(pdev) == FALSE) ! 362: { ! 363: RIP("PSCRIPT!DrvDrawEscape: invalid pdev.\n"); ! 364: SetLastError(ERROR_INVALID_PARAMETER); ! 365: return(0); ! 366: } ! 367: ! 368: // get the encapsulated PostScript data. ! 369: ! 370: pEpsData = (PEPSDATA) pvIn; ! 371: ! 372: // make sure that the driver can handle the eps language level. ! 373: ! 374: if ((pdev->pntpd->LangLevel < pEpsData->nVersion) ! 375: && !(pdev->pntpd->LangLevel == 0 && pEpsData->nVersion <= 1)) ! 376: { ! 377: SetLastError(ERROR_NOT_SUPPORTED); ! 378: return(0); ! 379: } ! 380: ! 381: // set up the clip path. ! 382: ! 383: bFirstClipPass = TRUE; ! 384: bMoreClipping = TRUE; ! 385: ! 386: while (bMoreClipping) ! 387: { ! 388: if (bClipping = bDoClipObj(pdev, pco, NULL, NULL, ! 389: &bMoreClipping, &bFirstClipPass, ! 390: 25)) ! 391: ps_clip(pdev, TRUE); ! 392: ! 393: // prepare for the included EPS data. ! 394: ! 395: ps_begin_eps(pdev); ! 396: ! 397: // set up the transform needed to map the EPS to the device ! 398: // parallelogram. ! 399: // We ignore prcl here and assume that it is at (0,0). ! 400: ! 401: if (!bDoEpsXform(pdev, pEpsData)) ! 402: { ! 403: RIP("PSCRIPT!DrvDrawEscape: invalid xform.\n"); ! 404: SetLastError(ERROR_INVALID_PARAMETER); ! 405: ps_end_eps(pdev); ! 406: return(0); ! 407: } ! 408: ! 409: // write out the EPS data. The EPS data is assumed to begin ! 410: // with %%BeginDocument as recommanded in the DSC version 3.0 ! 411: // by Adobe. ! 412: ! 413: bPSFlush(pdev); ! 414: bRet = WritePrinter(pdev->hPrinter, ! 415: (PBYTE) pEpsData + sizeof(EPSDATA), ! 416: pEpsData->cbData - sizeof(EPSDATA), ! 417: &cWritten); ! 418: if (!bRet) ! 419: DbgPrint("PSCRIPT!DrvDrawEscape ENCAPSULATED_POSTSCRIPT: WritePrinter failed.\n"); ! 420: ! 421: // restore state and cleanup stacks. ! 422: ! 423: ps_end_eps(pdev); ! 424: ! 425: if (bClipping) ! 426: ps_restore(pdev, TRUE); ! 427: ! 428: } ! 429: ! 430: return(bRet ? 1 : 0); ! 431: ! 432: default: ! 433: // if we get to the default case, we have been passed an ! 434: // unsupported escape function number. ! 435: ! 436: DbgPrint("PSCRIPT!DrvDrawEscape %x ESC_NOT_SUPPORTED.\n", iEsc); ! 437: ! 438: return(ESC_NOT_SUPPORTED); ! 439: } ! 440: } ! 441: ! 442: BOOL bDoEpsXform(pdev, pEpsData) ! 443: PDEVDATA pdev; ! 444: PEPSDATA pEpsData; ! 445: { ! 446: PBYTE pbEps, pbEpsEnd, pbBoundingBox; ! 447: FLOAT aeBoundingBox[4]; // bl.x, bl.y, tr.x, tr.y ! 448: XFORM xform; ! 449: PS_FIX psfxM11, psfxM12, psfxM21, psfxM22, psfxdx, psfxdy; ! 450: int i; ! 451: BOOL bIsNegative; ! 452: POINTE apteDst[3], apteSrc[3]; ! 453: ! 454: // look for the string %%BoundingBox: ! 455: ! 456: pbEps = (PBYTE) pEpsData + sizeof(EPSDATA); ! 457: pbEpsEnd = (PBYTE) pEpsData + pEpsData->cbData - 1; ! 458: ! 459: pbBoundingBox = pbEps; ! 460: while (pbBoundingBox <= pbEpsEnd) ! 461: { ! 462: if (!memcmp(pbBoundingBox, "%%BoundingBox:", 14)) ! 463: { ! 464: pbBoundingBox += 14; ! 465: ! 466: // store the bounding box coordinates in aeBoundingBox[]. ! 467: ! 468: for (i = 0; i < 4; i++) ! 469: { ! 470: // initialize bounding box. ! 471: ! 472: aeBoundingBox[i] = 0.0f; ! 473: ! 474: // skip white space. ! 475: ! 476: while (*pbBoundingBox == ' ' || *pbBoundingBox == '\t') ! 477: pbBoundingBox++; ! 478: ! 479: // get sign. ! 480: ! 481: if (*pbBoundingBox == '-') ! 482: { ! 483: pbBoundingBox++; ! 484: bIsNegative = TRUE; ! 485: } ! 486: else ! 487: bIsNegative = FALSE; ! 488: ! 489: // if this is not an integer, it may be an (atend) and ! 490: // the bounding box is at the end of the EPS data. ! 491: ! 492: if (!(*pbBoundingBox >= '0' && *pbBoundingBox <= '9' || *pbBoundingBox == '.')) ! 493: goto find_bounding_box; ! 494: ! 495: // get integer. ! 496: ! 497: while (*pbBoundingBox >= '0' && *pbBoundingBox <= '9') ! 498: { ! 499: aeBoundingBox[i] = aeBoundingBox[i] * 10.0f ! 500: + (FLOAT) (int) (*pbBoundingBox - '0'); ! 501: pbBoundingBox++; ! 502: } ! 503: ! 504: // get fraction if any. ! 505: ! 506: if (*pbBoundingBox == '.') ! 507: { ! 508: FLOAT eDiv; ! 509: ! 510: pbBoundingBox++; // skip '.' ! 511: ! 512: eDiv = 10.0f; ! 513: while (*pbBoundingBox >= '0' && *pbBoundingBox <= '9') ! 514: { ! 515: aeBoundingBox[i] += (FLOAT) (int) (*pbBoundingBox - '0') ! 516: / eDiv; ! 517: eDiv *= 10.0f; ! 518: pbBoundingBox++; ! 519: } ! 520: } ! 521: ! 522: if (bIsNegative) ! 523: aeBoundingBox[i] = aeBoundingBox[i] * -1.0f; ! 524: } ! 525: break; // got it! ! 526: } ! 527: else ! 528: pbBoundingBox++; ! 529: ! 530: // look for the '%' character. ! 531: ! 532: find_bounding_box: ! 533: ! 534: while (*pbBoundingBox != '%' && pbBoundingBox <= pbEpsEnd) ! 535: pbBoundingBox++; ! 536: } ! 537: ! 538: if (pbBoundingBox > pbEpsEnd) ! 539: { ! 540: RIP("PSCRIPT!bDoEpsXform: invalid EPS bounding box.\n"); ! 541: SetLastError(ERROR_INVALID_PARAMETER); ! 542: return(FALSE); ! 543: } ! 544: ! 545: // convert the parallelogram to PostScript coordinates (FLOAT, 72dpi). ! 546: ! 547: apteDst[0].x = XE72DPI(FixToFloat(pEpsData->aptl[0].x)); // left u0 ! 548: apteDst[0].y = YE72DPI(FixToFloat(pEpsData->aptl[0].y)); // top v0 ! 549: apteDst[1].x = XE72DPI(FixToFloat(pEpsData->aptl[1].x)); // right u1 ! 550: apteDst[1].y = YE72DPI(FixToFloat(pEpsData->aptl[1].y)); // top v1 ! 551: apteDst[2].x = XE72DPI(FixToFloat(pEpsData->aptl[2].x)); // left u2 ! 552: apteDst[2].y = YE72DPI(FixToFloat(pEpsData->aptl[2].y)); // bottom v2 ! 553: ! 554: apteSrc[0].x = aeBoundingBox[0]; // left x0 ! 555: apteSrc[0].y = aeBoundingBox[3]; // top y0 ! 556: apteSrc[1].x = aeBoundingBox[2]; // right x1 ! 557: apteSrc[1].y = aeBoundingBox[3]; // top y1 ! 558: apteSrc[2].x = aeBoundingBox[0]; // left x2 ! 559: apteSrc[2].y = aeBoundingBox[1]; // bottom y2 ! 560: ! 561: // Here is the transform equation from source EPS parallelogram ! 562: // [(x0,y0) (x1,y1) (x2,y2)] to the device parallelogram ! 563: // [(u0,v0) (u1,v1) (u2,v2)]: ! 564: // ! 565: // (u) (u0) [(x) (x0)] ! 566: // ( ) = ( ) + M * [( ) - ( )] ! 567: // (v) (v0) [(y) (y0)] ! 568: // ! 569: // where ! 570: // ! 571: // [(u1-u0)/(x1-x0) (u2-u0)/(y2-y0)] ! 572: // M = [ ] ! 573: // [(v1-v0)/(x1-x0) (v2-v0)/(y2-y0)] ! 574: ! 575: xform.eM11 = (apteDst[1].x - apteDst[0].x) / (apteSrc[1].x - apteSrc[0].x); ! 576: xform.eM12 = (apteDst[1].y - apteDst[0].y) / (apteSrc[1].x - apteSrc[0].x); ! 577: xform.eM21 = (apteDst[2].x - apteDst[0].x) / (apteSrc[2].y - apteSrc[0].y); ! 578: xform.eM22 = (apteDst[2].y - apteDst[0].y) / (apteSrc[2].y - apteSrc[0].y); ! 579: xform.eDx = apteDst[0].x - xform.eM11 * apteSrc[0].x - xform.eM21 * apteSrc[0].y; ! 580: xform.eDy = apteDst[0].y - xform.eM12 * apteSrc[0].x - xform.eM22 * apteSrc[0].y; ! 581: ! 582: // output the transform. ! 583: ! 584: psfxM11 = ETOPSFX(xform.eM11); ! 585: psfxM12 = ETOPSFX(xform.eM12); ! 586: psfxM21 = ETOPSFX(xform.eM21); ! 587: psfxM22 = ETOPSFX(xform.eM22); ! 588: psfxdx = ETOPSFX(xform.eDx); ! 589: psfxdy = ETOPSFX(xform.eDy); ! 590: ! 591: PrintString(pdev, "["); ! 592: PrintPSFIX(pdev, 6, psfxM11, psfxM12, psfxM21, psfxM22, ! 593: psfxdx, psfxdy); ! 594: PrintString(pdev, "] concat\n"); ! 595: ! 596: return(TRUE); ! 597: } ! 598: ! 599: FLOAT ae16[16] = { 0.0f / 16.0f, 1.0f / 16.0f, 2.0f / 16.0f, 3.0f / 16.0f, ! 600: 4.0f / 16.0f, 5.0f / 16.0f, 6.0f / 16.0f, 7.0f / 16.0f, ! 601: 8.0f / 16.0f, 9.0f / 16.0f, 10.0f / 16.0f, 11.0f / 16.0f, ! 602: 12.0f / 16.0f, 13.0f / 16.0f, 14.0f / 16.0f, 15.0f / 16.0f}; ! 603: ! 604: // Convert 28.4 FIX to FLOAT. ! 605: ! 606: FLOAT FixToFloat(FIX fx) ! 607: { ! 608: FLOAT e; ! 609: ! 610: e = (FLOAT) ((LONG) fx >> 4); ! 611: e += ae16[fx & 0xF]; ! 612: ! 613: return(e); ! 614: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.