|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1991-1992 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: Text.c ! 8: ! 9: Abstract: ! 10: ! 11: This module attempts to cache fonts on the VXL video board and draw glyphs ! 12: using hardware acceleration, ! 13: If the font cannot be cached the Engine is called to draw the glyphs. ! 14: ! 15: Environment: ! 16: ! 17: ! 18: Revision History: ! 19: ! 20: --*/ ! 21: ! 22: #include "driver.h" ! 23: #include "jzvxl484.h" ! 24: ! 25: // ! 26: // The following macro is the hash function for computing the cache ! 27: // index from a Glyph Handle and FontId. ! 28: // ! 29: ! 30: #define HASH_FUNCTION(GlyphHandle,FontId) \ ! 31: ((GlyphHandle & 0x7FF) << 1) + \ ! 32: FontId + \ ! 33: (FontId << 7) ! 34: ! 35: ! 36: ! 37: //#define CACHE_STATS ! 38: ! 39: // ! 40: // Define string object accelerator masks. ! 41: // ! 42: ! 43: #define SO_MASK \ ! 44: (SO_FLAG_DEFAULT_PLACEMENT | SO_ZERO_BEARINGS | \ ! 45: SO_CHAR_INC_EQUAL_BM_BASE | SO_MAXEXT_EQUAL_BM_SIDE) ! 46: ! 47: #define SO_LTOR (SO_MASK | SO_HORIZONTAL) ! 48: #define SO_RTOL (SO_LTOR | SO_REVERSED) ! 49: #define SO_TTOB (SO_MASK | SO_VERTICAL) ! 50: #define SO_BTOT (SO_TTOB | SO_REVERSED) ! 51: ! 52: static ULONG TextForegroundColor = 0xFFFFFFFF; ! 53: static ULONG TextBackgroundColor = 0xFFFFFFFF; ! 54: ! 55: #ifdef CACHE_STATS ! 56: static ULONG CacheUnused = Vxl.CacheSize; ! 57: static ULONG CharCount = 0; ! 58: static ULONG CacheMisses = 0; ! 59: static ULONG CacheReplacement = 0; ! 60: static ULONG ReplacementTotal = 0; ! 61: static ULONG CharTotal = 0; ! 62: static ULONG MissTotal = 0; ! 63: static ULONG HigherFontId = 0; ! 64: static ULONG HigherGlyphHandle = 0; ! 65: #endif ! 66: ! 67: static UCHAR ToBigEndian[256] = { ! 68: 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, ! 69: 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, ! 70: 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, ! 71: 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, ! 72: 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, ! 73: 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, ! 74: 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, ! 75: 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, ! 76: 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, ! 77: 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, ! 78: 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, ! 79: 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, ! 80: 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, ! 81: 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, ! 82: 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, ! 83: 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff ! 84: }; ! 85: ! 86: ! 87: ! 88: BOOL ! 89: DrvTextOut ! 90: ( ! 91: IN SURFOBJ *pso, ! 92: IN STROBJ *pstro, ! 93: IN FONTOBJ *pfo, ! 94: IN CLIPOBJ *pco, ! 95: IN RECTL *prclExtra, ! 96: IN RECTL *prclOpaque, ! 97: IN BRUSHOBJ *pboFore, ! 98: IN BRUSHOBJ *pboOpaque, ! 99: IN POINTL *pptlOrg, ! 100: IN MIX mix ! 101: ) ! 102: /*++ ! 103: ! 104: Routine Description: ! 105: ! 106: This function will cache fonts on the VXL video board and use accelerator ! 107: hardware to draw each glyph. An attemp is made to use opaque mode ! 108: text output to draw text and background color at the same time. If this ! 109: cannot be done then glyph forground and backgrounds are drawn spearately. ! 110: ! 111: Arguments: ! 112: ! 113: MIX is not checked. Since the GCAPS_ARBMIXTEXT capability bit is not ! 114: set, mix mode is always R2_COPYPEN. ! 115: ! 116: Return Value: ! 117: ! 118: ! 119: --*/ ! 120: ! 121: { ! 122: BOOL bMoreGlyphs; ! 123: LONG LineIndex; ! 124: ULONG ByteIndex; ! 125: PGLYPHPOS GlyphPosList; ! 126: ULONG GlyphCount; ! 127: ULONG GlyphHandle; ! 128: ULONG CacheIndex; ! 129: ULONG FontId; ! 130: GLYPHBITS *FontBitMap; ! 131: PBYTE BitMapPtr; ! 132: ULONG X,Y; ! 133: BOOL Allocate; ! 134: PULONG CacheData; ! 135: ULONG BitMapData; ! 136: ULONG SrcAdr,DstAdr,XYCmd,Cmd; ! 137: PGLYPHPOS GlyphEnd; ! 138: PGLYPHPOS GlyphStart; ! 139: LONG GlyphStride; ! 140: RECTL OpaqueRectl; ! 141: ULONG GlyphBytesPerScan,ShiftAmount; ! 142: ! 143: // ! 144: // Make sure the surface is the screen. ! 145: // ! 146: ! 147: if (pso->pvBits != (PVOID)Vxl.ScreenBase) { ! 148: goto DevFailTextOut; ! 149: } ! 150: ! 151: // ! 152: // If the width of the glyph is bigger than what the accelerator supports ! 153: // The font is non cacheable ! 154: // Clipping is not trivial OR ! 155: // SolidColor is a brush. ! 156: // call GDI to draw the text. ! 157: // ! 158: ! 159: ! 160: if ((pfo->cxMax > 32) || ! 161: (pfo->flFontType & DEVICE_FONTTYPE) || ! 162: (pco->iDComplexity != DC_TRIVIAL) || ! 163: (pboFore->iSolidColor == 0xFFFFFFFFL)) { ! 164: ! 165: goto DevFailTextOut; ! 166: } ! 167: ! 168: // ! 169: // Set Jaguar foreground color only if it changed since the ! 170: // previous call. Changing Foreground/Background color requires ! 171: // synchronization. ! 172: // ! 173: ! 174: if (TextForegroundColor != pboFore->iSolidColor) { ! 175: TextForegroundColor = pboFore->iSolidColor; ! 176: DevSetFgColor(TextForegroundColor); ! 177: } ! 178: ! 179: // ! 180: // Check that the Background color is solid. ! 181: // Set Jaguar Background color if it changed. ! 182: // ! 183: ! 184: if (prclOpaque != (PRECTL) NULL) { ! 185: if (pboOpaque->iSolidColor == 0xFFFFFFFFL) { ! 186: goto DevFailTextOut; ! 187: } ! 188: if (TextBackgroundColor != pboOpaque->iSolidColor) { ! 189: TextBackgroundColor = pboOpaque->iSolidColor; ! 190: DevSetBgColor(TextBackgroundColor); ! 191: } ! 192: } ! 193: ! 194: // ! 195: // enumerate the string psto into glyphs (GLYPHPOS), then send a draw ! 196: // command for each. Deal with clipping later. ! 197: // ! 198: ! 199: FontId = pfo->iUniq; ! 200: #ifdef CACHE_STATS ! 201: if (FontId > HigherFontId) { ! 202: HigherFontId = FontId; ! 203: } ! 204: #endif ! 205: if (((pstro->flAccel == SO_LTOR) || (pstro->flAccel == SO_RTOL) || ! 206: (pstro->flAccel == SO_TTOB) || (pstro->flAccel == SO_BTOT)) && ! 207: (prclOpaque != NULL)) { ! 208: ! 209: // ! 210: // If the top of the opaque rectangle is less than the top of the ! 211: // background rectangle, then fill the region between the top of ! 212: // opaque rectangle and the top of the background rectangle and ! 213: // reduce the size of the opaque rectangle. ! 214: // ! 215: ! 216: OpaqueRectl = *prclOpaque; ! 217: if (OpaqueRectl.top < pstro->rclBkGround.top) { ! 218: OpaqueRectl.bottom = pstro->rclBkGround.top; ! 219: DrvpFillRectangle(&OpaqueRectl, pboOpaque->iSolidColor); ! 220: OpaqueRectl.top = pstro->rclBkGround.top; ! 221: OpaqueRectl.bottom = prclOpaque->bottom; ! 222: } ! 223: ! 224: // ! 225: // If the bottom of the opaque rectangle is greater than the bottom ! 226: // of the background rectangle, then fill the region between the ! 227: // bottom of the background rectangle and the bottom of the opaque ! 228: // rectangle and reduce the size of the opaque rectangle. ! 229: // ! 230: ! 231: if (OpaqueRectl.bottom > pstro->rclBkGround.bottom) { ! 232: OpaqueRectl.top = pstro->rclBkGround.bottom; ! 233: DrvpFillRectangle(&OpaqueRectl, pboOpaque->iSolidColor); ! 234: OpaqueRectl.top = pstro->rclBkGround.top; ! 235: OpaqueRectl.bottom = pstro->rclBkGround.bottom; ! 236: } ! 237: ! 238: // ! 239: // If the left of the opaque rectangle is less than the left of ! 240: // the background rectangle, then fill the region between the ! 241: // left of the opaque rectangle and the left of the background ! 242: // rectangle. ! 243: // ! 244: ! 245: if (OpaqueRectl.left < pstro->rclBkGround.left) { ! 246: OpaqueRectl.right = pstro->rclBkGround.left; ! 247: DrvpFillRectangle(&OpaqueRectl, pboOpaque->iSolidColor); ! 248: OpaqueRectl.right = prclOpaque->right; ! 249: } ! 250: ! 251: // ! 252: // If the right of the opaque rectangle is greater than the right ! 253: // of the background rectangle, then fill the region between the ! 254: // right of the opaque rectangle and the right of the background ! 255: // rectangle. ! 256: // ! 257: ! 258: if (OpaqueRectl.right > pstro->rclBkGround.right) { ! 259: OpaqueRectl.left = pstro->rclBkGround.right; ! 260: DrvpFillRectangle(&OpaqueRectl, pboOpaque->iSolidColor); ! 261: } ! 262: ! 263: Cmd = JAGUAR_TEXT_OPAQUE << XYCMD_CMD_SHIFT; ! 264: ! 265: } else { ! 266: ! 267: // ! 268: // We now have a cacheable font and drawable rectangles, first clip and draw ! 269: // all opaque rectangles. ! 270: // ! 271: ! 272: if (prclOpaque != (PRECTL)NULL) { ! 273: ! 274: DrvpFillRectangle(prclOpaque,pboOpaque->iSolidColor); ! 275: ! 276: } ! 277: Cmd = JAGUAR_TEXT_TRANSPARENT << XYCMD_CMD_SHIFT; ! 278: } ! 279: ! 280: // ! 281: // If the font is fixed pitch, then optimize the computation of ! 282: // x and y coordinate values. Otherwise, compute the x and y values ! 283: // for each glyph. ! 284: // ! 285: ! 286: if (pstro->ulCharInc != 0) { ! 287: ! 288: // ! 289: // The font is fixed pitch. Capture the glyph dimensions and ! 290: // compute the starting display address. ! 291: // ! 292: ! 293: if (pstro->pgp == NULL) { ! 294: bMoreGlyphs = STROBJ_bEnum(pstro, &GlyphCount, &GlyphPosList); ! 295: ! 296: } else { ! 297: GlyphCount = pstro->cGlyphs; ! 298: GlyphPosList = pstro->pgp; ! 299: bMoreGlyphs = FALSE; ! 300: } ! 301: ! 302: #ifdef CACHE_STATS ! 303: CharCount += GlyphCount; ! 304: #endif ! 305: ! 306: FontBitMap = GlyphPosList->pgdf->pgb; ! 307: X = FontBitMap->sizlBitmap.cx; ! 308: Y = FontBitMap->sizlBitmap.cy; ! 309: ! 310: DstAdr = ((GlyphPosList->ptl.y + FontBitMap->ptlOrigin.y) * Vxl.JaguarScreenX) + ! 311: ((GlyphPosList->ptl.x + FontBitMap->ptlOrigin.x) << Vxl.ColorModeShift) ; ! 312: ! 313: // ! 314: // Compute the glyph stride. ! 315: // ! 316: ! 317: GlyphStride = ((pstro->ulCharInc) << Vxl.ColorModeShift); ! 318: if ((pstro->flAccel & SO_VERTICAL) != 0) { ! 319: GlyphStride *= Vxl.JaguarScreenX; ! 320: } ! 321: ! 322: // ! 323: // If the direction of drawing is reversed, then the stride is ! 324: // negative. ! 325: // ! 326: ! 327: if ((pstro->flAccel & SO_REVERSED) != 0) { ! 328: GlyphStride = -GlyphStride; ! 329: } ! 330: ! 331: // ! 332: // Output the set of glyphs. ! 333: // ! 334: ! 335: do { ! 336: GlyphEnd = &GlyphPosList[GlyphCount]; ! 337: GlyphStart = GlyphPosList; ! 338: do { ! 339: ! 340: GlyphHandle = (ULONG) (GlyphStart->hg); ! 341: ! 342: CacheIndex = HASH_FUNCTION(GlyphHandle,FontId); ! 343: ! 344: CacheIndex &= Vxl.CacheIndexMask; ! 345: ! 346: // ! 347: // Get glyph info ! 348: // ! 349: ! 350: FontBitMap = GlyphStart->pgdf->pgb; ! 351: ! 352: // ! 353: // If FontId or GlyphHandle don't match, cache this glyph. ! 354: // ! 355: ! 356: if (Vxl.CacheTag[CacheIndex].FontId != FontId) { ! 357: Allocate = TRUE; ! 358: } else { ! 359: if (Vxl.CacheTag[CacheIndex].GlyphHandle != GlyphHandle) { ! 360: Allocate = TRUE; ! 361: } else { ! 362: Allocate = FALSE; ! 363: } ! 364: } ! 365: if (Allocate) { ! 366: ! 367: // ! 368: // Wait for the accelerator to be idle to ensure ! 369: // that the glyph being replaced is not in use. ! 370: // ! 371: ! 372: WaitForJaguarIdle(); ! 373: ! 374: #ifdef CACHE_STATS ! 375: CacheMisses++; ! 376: ! 377: if (Vxl.CacheTag[CacheIndex].FontId == FreeTag) { ! 378: CacheUnused--; ! 379: } else { ! 380: CacheReplacement++; ! 381: } ! 382: ! 383: if (Vxl.CacheTag[CacheIndex].FontId == FontId) { ! 384: DISPDBG((3, "Replacing same font Glyph %x with glyph %x\n", ! 385: Vxl.CacheTag[CacheIndex].FontId, ! 386: FontId)); ! 387: } ! 388: ! 389: if (Vxl.CacheTag[CacheIndex].GlyphHandle == GlyphHandle) { ! 390: DISPDBG((3, "Replacing same Glyph %x font %x with font %x\n", ! 391: GlyphHandle, ! 392: Vxl.CacheTag[CacheIndex].FontId, ! 393: FontId)); ! 394: } ! 395: ! 396: if (GlyphHandle > HigherGlyphHandle) { ! 397: HigherGlyphHandle = GlyphHandle; ! 398: } ! 399: #endif ! 400: // ! 401: // if the entry that needs to be replaced ! 402: // is used as extension for a glyph > 32 lines ! 403: // go backwards and clear the Id so that if the ! 404: // glyph > 32 is used again it'll miss in the cache ! 405: // ! 406: // ! 407: ! 408: LineIndex = CacheIndex; ! 409: while (Vxl.CacheTag[LineIndex].FontId == GlyphExtended) { ! 410: LineIndex--; ! 411: Vxl.CacheTag[LineIndex].FontId = FreeTag; ! 412: } ! 413: ! 414: // ! 415: // Clear the entries used by the big glyph that follows the one ! 416: // that needs to be replaced ! 417: // ! 418: ! 419: LineIndex = CacheIndex+1; ! 420: while (Vxl.CacheTag[LineIndex].FontId == GlyphExtended) { ! 421: Vxl.CacheTag[LineIndex].FontId = FreeTag; ! 422: LineIndex++; ! 423: } ! 424: ! 425: // ! 426: // Store the tag for the current glyph. ! 427: // ! 428: ! 429: Vxl.CacheTag[CacheIndex].FontId = FontId; ! 430: Vxl.CacheTag[CacheIndex].GlyphHandle = GlyphHandle; ! 431: ! 432: CacheData = Vxl.FontCacheBase + (CacheIndex << 5); ! 433: ! 434: // ! 435: // Fix the bit ordering and store the bitmap ! 436: // in off screen video memory. ! 437: // ! 438: ! 439: BitMapPtr = FontBitMap->aj; ! 440: GlyphBytesPerScan = (X+7) >> 3; ! 441: ShiftAmount = (GlyphBytesPerScan-1) << 3; ! 442: ! 443: ! 444: for (LineIndex=0;LineIndex < Y; LineIndex ++) { ! 445: BitMapData = 0; ! 446: ! 447: ! 448: for (ByteIndex = 0; ByteIndex < GlyphBytesPerScan; ByteIndex++) { ! 449: BitMapData >>= 8; ! 450: BitMapData |= ToBigEndian[*BitMapPtr++] << ShiftAmount; ! 451: } ! 452: *CacheData++ = BitMapData; ! 453: } ! 454: ! 455: // ! 456: // If Y is bigger than 32 lines, the glyph that was just cached ! 457: // took more than one entry. Fix the CacheTags. ! 458: // ! 459: ! 460: for (ByteIndex = 1; LineIndex > 32 ;ByteIndex++) { ! 461: Vxl.CacheTag[CacheIndex+ByteIndex].FontId = GlyphExtended; ! 462: LineIndex -=32; ! 463: } ! 464: } ! 465: ! 466: // ! 467: // Find out where to draw the glyph and the glyph's starting address ! 468: // ! 469: ! 470: SrcAdr = Vxl.FontCacheOffset + (CacheIndex << 7); ! 471: ! 472: XYCmd = Cmd | (Y << XYCMD_Y_SHIFT) | X; ! 473: ! 474: FifoWrite(DstAdr,SrcAdr,XYCmd); ! 475: ! 476: DstAdr += GlyphStride; ! 477: GlyphStart += 1; ! 478: } while (GlyphStart != GlyphEnd); ! 479: ! 480: if (bMoreGlyphs) { ! 481: bMoreGlyphs = STROBJ_bEnum(pstro, &GlyphCount, &GlyphPosList); ! 482: #ifdef CACHE_STATS ! 483: CharCount += GlyphCount; ! 484: #endif ! 485: ! 486: } else { ! 487: break; ! 488: } ! 489: } while (TRUE); ! 490: ! 491: } else { ! 492: ! 493: // ! 494: // The font is not fixed pitch. Compute the x and y values for ! 495: // each glyph individually. ! 496: // ! 497: ! 498: do { ! 499: ! 500: // ! 501: // Get each glyph handle, find the physical address and send the ! 502: // draw command to the accelerator. Don't worry about clipping yet. ! 503: // ! 504: ! 505: bMoreGlyphs = STROBJ_bEnum(pstro, &GlyphCount,&GlyphPosList); ! 506: ! 507: #ifdef CACHE_STATS ! 508: CharCount += GlyphCount; ! 509: #endif ! 510: ! 511: GlyphEnd = &GlyphPosList[GlyphCount]; ! 512: GlyphStart = GlyphPosList; ! 513: do { ! 514: ! 515: GlyphHandle = (ULONG) (GlyphStart->hg); ! 516: ! 517: CacheIndex = HASH_FUNCTION(GlyphHandle,FontId); ! 518: ! 519: CacheIndex &= Vxl.CacheIndexMask; ! 520: ! 521: // ! 522: // Get glyph info ! 523: // ! 524: ! 525: FontBitMap = GlyphStart->pgdf->pgb; ! 526: X = FontBitMap->sizlBitmap.cx; ! 527: Y = FontBitMap->sizlBitmap.cy; ! 528: ! 529: // ! 530: // If FontId or GlyphHandle don't match, cache this glyph. ! 531: // ! 532: ! 533: ! 534: if (Vxl.CacheTag[CacheIndex].FontId != FontId) { ! 535: Allocate = TRUE; ! 536: } else { ! 537: if (Vxl.CacheTag[CacheIndex].GlyphHandle != GlyphHandle) { ! 538: Allocate = TRUE; ! 539: } else { ! 540: Allocate = FALSE; ! 541: } ! 542: } ! 543: ! 544: if (Allocate) { ! 545: ! 546: // ! 547: // Wait for the accelerator to be idle to ensure ! 548: // that the glyph being replaced is not in use. ! 549: // ! 550: WaitForJaguarIdle(); ! 551: ! 552: #ifdef CACHE_STATS ! 553: CacheMisses++; ! 554: #endif ! 555: ! 556: // ! 557: // The Glyph that has to be replaced is from the same font, ! 558: // wait for the accelerator to be idle before caching the ! 559: // glyph. ! 560: // ! 561: ! 562: #ifdef CACHE_STATS ! 563: if (Vxl.CacheTag[CacheIndex].FontId == FreeTag) { ! 564: CacheUnused--; ! 565: } else { ! 566: CacheReplacement++; ! 567: } ! 568: ! 569: if (Vxl.CacheTag[CacheIndex].FontId == FontId) { ! 570: DISPDBG((3, "Replacing same font Glyph %x with glyph %x\n", ! 571: Vxl.CacheTag[CacheIndex].FontId, ! 572: FontId)); ! 573: } ! 574: ! 575: if (Vxl.CacheTag[CacheIndex].GlyphHandle == GlyphHandle) { ! 576: DISPDBG((3, "Replacing same Glyph %x font %x with font %x\n", ! 577: GlyphHandle, ! 578: Vxl.CacheTag[CacheIndex].FontId, ! 579: FontId)); ! 580: } ! 581: ! 582: if (GlyphHandle > HigherGlyphHandle) { ! 583: HigherGlyphHandle = GlyphHandle; ! 584: } ! 585: #endif ! 586: ! 587: // ! 588: // if the entry that needs to be replaced ! 589: // is used as extension for a glyph > 32 lines ! 590: // go backwards and clear the Id so that if the ! 591: // glyph > 32 is used again it'll miss in the cache ! 592: // ! 593: ! 594: LineIndex = CacheIndex; ! 595: while (Vxl.CacheTag[LineIndex].FontId == GlyphExtended) { ! 596: LineIndex--; ! 597: Vxl.CacheTag[LineIndex].FontId = FreeTag; ! 598: } ! 599: ! 600: // ! 601: // Clear the entries used by the big glyph that follows the one ! 602: // that needs to be replaced ! 603: // ! 604: ! 605: LineIndex = CacheIndex+1; ! 606: while (Vxl.CacheTag[LineIndex].FontId == GlyphExtended) { ! 607: Vxl.CacheTag[LineIndex].FontId = FreeTag; ! 608: LineIndex++; ! 609: } ! 610: ! 611: // ! 612: // Store the tag for the current glyph. ! 613: // ! 614: ! 615: Vxl.CacheTag[CacheIndex].FontId = FontId; ! 616: Vxl.CacheTag[CacheIndex].GlyphHandle = GlyphHandle; ! 617: ! 618: CacheData = Vxl.FontCacheBase + (CacheIndex << 5); ! 619: ! 620: BitMapPtr = FontBitMap->aj; ! 621: GlyphBytesPerScan = (X+7) >> 3; ! 622: ShiftAmount = (GlyphBytesPerScan-1) << 3; ! 623: ! 624: for (LineIndex=0;LineIndex < Y; LineIndex ++) { ! 625: BitMapData = 0; ! 626: for (ByteIndex = 0; ByteIndex < GlyphBytesPerScan; ByteIndex++) { ! 627: ! 628: BitMapData >>= 8; ! 629: BitMapData |= ToBigEndian[*BitMapPtr++] << ShiftAmount; ! 630: } ! 631: *CacheData++ = BitMapData; ! 632: } ! 633: ! 634: // ! 635: // If Y is bigger than 32 lines, the glyph we just cached ! 636: // took more than one entry. Fix the CacheTags. ! 637: // ! 638: ! 639: for (ByteIndex = 1; LineIndex > 32 ;ByteIndex++) { ! 640: Vxl.CacheTag[CacheIndex+ByteIndex].FontId = GlyphExtended; ! 641: LineIndex -=32; ! 642: } ! 643: ! 644: } ! 645: ! 646: SrcAdr = Vxl.FontCacheOffset + (CacheIndex << 7); ! 647: ! 648: DstAdr = Vxl.JaguarScreenX * (GlyphStart->ptl.y + FontBitMap->ptlOrigin.y) + ! 649: ((GlyphStart->ptl.x + FontBitMap->ptlOrigin.x) << Vxl.ColorModeShift); ! 650: ! 651: XYCmd = Cmd | (Y << XYCMD_Y_SHIFT) | X; ! 652: ! 653: FifoWrite(DstAdr,SrcAdr,XYCmd); ! 654: GlyphStart += 1; ! 655: } while (GlyphStart != GlyphEnd); ! 656: } while (bMoreGlyphs); ! 657: } ! 658: ! 659: // ! 660: // Draw extra rectangles using foreground brush ! 661: // ! 662: ! 663: if (prclExtra != (PRECTL)NULL) { ! 664: DrvpFillRectangle(prclExtra,pboFore->iSolidColor); ! 665: } ! 666: ! 667: #ifdef CACHE_STATS ! 668: if (CharCount >= 10000) { ! 669: ReplacementTotal += CacheReplacement; ! 670: CharTotal += CharCount; ! 671: MissTotal += CacheMisses; ! 672: DISPDBG((3, "Cache Statistics for last %ld chars\n",CharCount)); ! 673: DISPDBG((3, "Misses = %ld Rate = %ld Replacements %ld\n", ! 674: CacheMisses, ! 675: (CacheMisses*100)/CharCount, ! 676: CacheReplacement)); ! 677: ! 678: DISPDBG((3, "Cache Statistics since begining. Total of %ld chars\n",CharTotal)); ! 679: DISPDBG((3, "Misses = %ld Rate = %ld Replacements %ld Unused entries = %ld\n", ! 680: MissTotal, ! 681: (MissTotal*100)/CharTotal, ! 682: ReplacementTotal, ! 683: CacheUnused)); ! 684: DISPDBG((3, "HigherFontId = %x HigherGlyphHandle = %x\n",HigherFontId,HigherGlyphHandle)); ! 685: CharCount = 0; ! 686: CacheMisses = 0; ! 687: CacheReplacement = 0; ! 688: } ! 689: ! 690: #endif ! 691: ! 692: // ! 693: // Done with call, return ! 694: // ! 695: ! 696: return(TRUE); ! 697: ! 698: // ! 699: // Could not execute this TextOut call, pass to engine. ! 700: // No need to synchronize here since Eng routine will call DrvSynchronize. ! 701: // ! 702: ! 703: ! 704: DevFailTextOut: ! 705: ! 706: return(EngTextOut(pso, ! 707: pstro, ! 708: pfo, ! 709: pco, ! 710: prclExtra, ! 711: prclOpaque, ! 712: pboFore, ! 713: pboOpaque, ! 714: pptlOrg, ! 715: mix)); ! 716: ! 717: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.