|
|
1.1 ! root 1: /******************************Module*Header*******************************\ ! 2: * Module Name: TextOut.c ! 3: * ! 4: * S3 Text accelerations ! 5: * ! 6: * Copyright (c) 1992 Microsoft Corporation ! 7: * ! 8: \**************************************************************************/ ! 9: ! 10: #include "driver.h" ! 11: #include "memory.h" ! 12: ! 13: // Part of the fix to limit the amount of resources allocated for fonts ! 14: ! 15: #define MAX_GLYPHS_TO_ALLOC 256 ! 16: ! 17: // number of bytes in the glyph bitmap scanline ! 18: ! 19: #define CJ_SCAN(cx) (((cx) + 7) >> 3) ! 20: ! 21: #define TRIVIAL_ACCEPT 0x00000001 ! 22: #define MONO_SPACED_FONT 0x00000002 ! 23: #define MONO_SIZE_VALID 0x00000004 ! 24: #define MONO_FIRST_TIME 0x00000008 ! 25: ! 26: PCACHEDFONT pCachedFontsRoot; // Cached Fonts list root. ! 27: ! 28: WORD iPlaneBits[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; ! 29: ! 30: BOOL bOpaqueRect( ! 31: PPDEV ppdev, ! 32: RECTL *prclOpaque, ! 33: RECTL *prclBounds, ! 34: BRUSHOBJ *pboOpaque); ! 35: ! 36: BOOL bSetS3TextColorAndMix( ! 37: PPDEV ppdev, ! 38: MIX mix, ! 39: BRUSHOBJ *pboFore, ! 40: BRUSHOBJ *pboOpaque); ! 41: ! 42: VOID vBlowCache(PPDEV ppdev); ! 43: ! 44: VOID vInitGlyphAlloc(PPDEV ppdev); ! 45: ! 46: BOOL bAllocGlyphMemory(PPDEV ppdev, ! 47: PSIZEL psizlGlyph, ! 48: PXYZPOINTL pxyzGlyph); ! 49: ! 50: PCACHEDGLYPH pCacheFont(PPDEV ppdev, ! 51: STROBJ *pstro, ! 52: FONTOBJ *pfo, ! 53: PCACHEDFONT *ppCachedFont); ! 54: ! 55: BOOL bAllocateGlyph(PPDEV ppdev, ! 56: HGLYPH hg, ! 57: GLYPHBITS *pgb, ! 58: PCACHEDGLYPH pcg); ! 59: ! 60: BOOL bHandleNonCachedFonts(SURFOBJ *pso, ! 61: STROBJ *pstro, ! 62: FONTOBJ *pfo, ! 63: RECTL *prclClip, ! 64: RECTL *prclExtra, ! 65: RECTL *prclOpaque, ! 66: BRUSHOBJ *pboFore, ! 67: BRUSHOBJ *pboOpaque, ! 68: POINTL *pptlOrg, ! 69: MIX mix); ! 70: ! 71: BOOL bHandleCachedFonts(SURFOBJ *pso, ! 72: STROBJ *pstro, ! 73: RECTL *prclClip, ! 74: FONTOBJ *pfo, ! 75: RECTL *prclOpaque, ! 76: BRUSHOBJ *pboFore, ! 77: BRUSHOBJ *pboOpaque, ! 78: POINTL *pptlOrg, ! 79: MIX mix); ! 80: ! 81: #if DBG ! 82: ! 83: ULONG nGlyphs, nOverlaps; ! 84: ! 85: #define TFIFOWAIT(level) nGlyphs++; \ ! 86: if (INPW(GP_STAT) & level) { \ ! 87: nOverlaps++; \ ! 88: while (INPW(GP_STAT) & level); \ ! 89: } ! 90: #else ! 91: ! 92: #define TFIFOWAIT(level) FIFOWAIT(level) ! 93: ! 94: #endif ! 95: ! 96: ! 97: /**************************************************************************** ! 98: * DrvDestroyFont ! 99: ***************************************************************************/ ! 100: VOID DrvDestroyFont(FONTOBJ *pfo) ! 101: { ! 102: PCACHEDFONT pCachedFont, pcfLast; ! 103: PCACHEDGLYPH pcg, pcgNext; ! 104: INT nGlyphs, i; ! 105: ! 106: DISPDBG((1, "S3.DLL!DrvDestroyFont - Entry\n")); ! 107: ! 108: if (((pCachedFont = ((PCACHEDFONT) pfo->pvConsumer)) != NULL)) ! 109: { ! 110: if (pfo->iUniq == pCachedFont->iUniq) ! 111: { ! 112: // We have found our font. ! 113: ! 114: DISPDBG((1, "S3.DLL: Destroying font: pfo->iUniq: %x\n", ! 115: pfo->iUniq)); ! 116: ! 117: // First free any nodes in the collision list. ! 118: ! 119: nGlyphs = pCachedFont->cGlyphs+1; ! 120: for (i = 0; i < nGlyphs; i++) ! 121: { ! 122: // get a pointer to this glyph node. ! 123: ! 124: pcg = &(pCachedFont->pCachedGlyphs[i]); ! 125: ! 126: // get a pointer to this glyphs collision list ! 127: ! 128: pcg = pcg->pcgCollisionLink; ! 129: for (; pcg != NULL; pcg = pcgNext) ! 130: { ! 131: pcgNext = pcg->pcgCollisionLink; ! 132: LocalFree(pcg); ! 133: } ! 134: } ! 135: ! 136: // Now free the cached glyph array ! 137: ! 138: LocalFree(pCachedFont->pCachedGlyphs); ! 139: ! 140: // Now remove the font node from the list of fonts ! 141: // and free it. ! 142: ! 143: pcfLast = (PCACHEDFONT) &pCachedFontsRoot; ! 144: for (pCachedFont = pCachedFontsRoot; ! 145: pCachedFont != NULL; ! 146: pCachedFont = pCachedFont->pcfNext) ! 147: { ! 148: if (pCachedFont->iUniq == pfo->iUniq) ! 149: { ! 150: pcfLast->pcfNext = pCachedFont->pcfNext; ! 151: LocalFree(pCachedFont); ! 152: break; ! 153: } ! 154: pcfLast = pCachedFont; ! 155: } ! 156: ! 157: if (pCachedFont == NULL) ! 158: { ! 159: RIP("S3.DLL!DrvDestroyFont - pCachedFont not found\n"); ! 160: } ! 161: } ! 162: else ! 163: { ! 164: RIP("S3.DLL!DrvDestroyFont - pfo->pvConsumer error\n"); ! 165: } ! 166: } ! 167: ! 168: // In all cases we want to zero out the pvConsumer field. ! 169: ! 170: pfo->pvConsumer = NULL; ! 171: ! 172: } ! 173: ! 174: ! 175: /**************************************************************************** ! 176: * DrvTextOut ! 177: ***************************************************************************/ ! 178: BOOL DrvTextOut( ! 179: SURFOBJ *pso, ! 180: STROBJ *pstro, ! 181: FONTOBJ *pfo, ! 182: CLIPOBJ *pco, ! 183: RECTL *prclExtra, ! 184: RECTL *prclOpaque, ! 185: BRUSHOBJ *pboFore, ! 186: BRUSHOBJ *pboOpaque, ! 187: POINTL *pptlOrg, ! 188: MIX mix) ! 189: { ! 190: BOOL b, bMore; ! 191: UINT i; ! 192: ENUMRECTS8 EnumRects8; ! 193: PPDEV ppdev; ! 194: ! 195: DISPDBG((3, "S3.DLL: DrvTextOut - Entry\n")); ! 196: ! 197: // Pickup the ppdev. ! 198: ! 199: ppdev = (PPDEV) pso->dhpdev; ! 200: ! 201: // Protect the code path from a potentially NULL clip object ! 202: // This also gives a maximum rclBounds which we use later: ! 203: ! 204: if (pco == NULL || pco->iDComplexity == DC_TRIVIAL) ! 205: { ! 206: pco = ppdev->pcoDefault; ! 207: } ! 208: ! 209: // Determine if we can cache this string. ! 210: // This is done by checking the size of glyph. ! 211: ! 212: b = TRUE; ! 213: ! 214: if ((pfo->cxMax > GLYPH_CACHE_CX) || ! 215: ((pstro->rclBkGround.bottom - pstro->rclBkGround.top) > GLYPH_CACHE_CY)) ! 216: { ! 217: b = FALSE; ! 218: } ! 219: ! 220: // If the glyphs in this string will fit in the font cache ! 221: // then try to render it as a cached font. ! 222: ! 223: if (b == TRUE) ! 224: { ! 225: // Take care of the clipping. ! 226: ! 227: if (pco->iDComplexity != DC_COMPLEX) ! 228: { ! 229: b = bHandleCachedFonts(pso, pstro, &(pco->rclBounds), pfo, ! 230: prclOpaque, pboFore, ! 231: pboOpaque, pptlOrg, mix); ! 232: ! 233: } ! 234: else ! 235: { ! 236: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0); ! 237: ! 238: do ! 239: { ! 240: bMore = CLIPOBJ_bEnum(pco, sizeof (ENUMRECTS8), ! 241: (PULONG)&EnumRects8); ! 242: ! 243: for (i = 0; i < EnumRects8.c; i++) ! 244: { ! 245: b = bHandleCachedFonts(pso, pstro, &(EnumRects8.arcl[i]), ! 246: pfo, prclOpaque, pboFore, pboOpaque, pptlOrg, mix); ! 247: if (!b) ! 248: { ! 249: // If we failed, stop immediately, so we can fall back ! 250: // to bHandleNonCachedFonts. Otherwise, if we just blew ! 251: // the cache, the next call in this loop will succeed, ! 252: // and we'll never redo this rectangle properly. Note ! 253: // that this is very inefficient, forcing the whole ! 254: // rest of the call to go through ! 255: // bHandleNonCachedFonts ! 256: break; ! 257: } ! 258: } ! 259: ! 260: } while (bMore & b); ! 261: } ! 262: } ! 263: ! 264: // If something went wrong with rendering the string as a cached ! 265: // font then render it as a large font. ! 266: ! 267: if (b == FALSE) ! 268: { ! 269: if (pco->iDComplexity != DC_COMPLEX) ! 270: { ! 271: b = bHandleNonCachedFonts(pso, pstro, pfo, &(pco->rclBounds), ! 272: prclExtra, prclOpaque, pboFore, pboOpaque, pptlOrg, mix); ! 273: ! 274: } ! 275: else ! 276: { ! 277: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0); ! 278: ! 279: do ! 280: { ! 281: bMore = CLIPOBJ_bEnum(pco, sizeof (ENUMRECTS8), ! 282: (PULONG)&EnumRects8); ! 283: ! 284: for (i = 0; i < EnumRects8.c; i++) ! 285: { ! 286: b = bHandleNonCachedFonts(pso, pstro, pfo, ! 287: &(EnumRects8.arcl[i]), prclExtra, prclOpaque, ! 288: pboFore, pboOpaque, pptlOrg, mix); ! 289: } ! 290: ! 291: } while (bMore); ! 292: } ! 293: ! 294: vResetS3Clipping(ppdev); ! 295: } ! 296: ! 297: return (b); ! 298: } ! 299: ! 300: ! 301: /**************************************************************************** ! 302: * bHandleCachedFonts ! 303: ***************************************************************************/ ! 304: BOOL bHandleCachedFonts( ! 305: SURFOBJ *pso, ! 306: STROBJ *pstro, ! 307: RECTL *prclClip, ! 308: FONTOBJ *pfo, ! 309: RECTL *prclOpaque, ! 310: BRUSHOBJ *pboFore, ! 311: BRUSHOBJ *pboOpaque, ! 312: POINTL *pptlOrg, ! 313: MIX mix) ! 314: { ! 315: BOOL b, bMoreGlyphs, bFound; ! 316: ULONG iGlyph, cGlyphs; ! 317: POINTL ptl; ! 318: GLYPHPOS *pgp; ! 319: INT ihGlyph, cxGlyph, cyGlyph; ! 320: PCACHEDGLYPH pCachedGlyphs, pcg, pcgNew; ! 321: WORD Cmd; ! 322: XYZPOINTL xyzGlyph; ! 323: PCACHEDFONT pCachedFont; ! 324: PPDEV ppdev; ! 325: INT i, culRcl; ! 326: ULONG flAccel; ! 327: RECTL arclTmp[4]; ! 328: ULONG ulCharInc; ! 329: ULONG yMonoStart, xMonoPosition; ! 330: POINTL ptlSrc; ! 331: RECTL rclGlyph; ! 332: HGLYPH hg; ! 333: GLYPHBITS *pgb; ! 334: ULONG fl = 0; ! 335: BYTE jBackgroundRop; ! 336: ! 337: DISPDBG((4, "S3.DLL:bHandleCachedFonts - Entry\n")); ! 338: ! 339: ppdev = (PPDEV) pso->dhpdev; ! 340: ! 341: // ! 342: // If we have seen this font before then pvConsumer will be non-NULL. ! 343: // ! 344: ! 345: if (((pCachedFont = ((PCACHEDFONT) pfo->pvConsumer)) != NULL)) ! 346: { ! 347: pCachedGlyphs = pCachedFont->pCachedGlyphs; ! 348: ! 349: if (pfo->iUniq != pCachedFont->iUniq) ! 350: { ! 351: DISPDBG((1, "S3.DLL: pfo->iUniq: %x, pCachedFont->iUniq: %x\n", ! 352: pfo->iUniq, pCachedFont->iUniq)); ! 353: return (FALSE); ! 354: } ! 355: } ! 356: ! 357: else ! 358: { ! 359: DISPDBG((2, "S3.DLL!bHandleCachedFonts - Caching Font: %d\n", pfo->iUniq)); ! 360: ! 361: pCachedGlyphs = pCacheFont(ppdev, pstro, pfo, &pCachedFont); ! 362: ! 363: if (pCachedGlyphs == NULL) ! 364: { ! 365: DISPDBG((1, "S3.DLL!bHandleCachedFonts - pCacheFont failed once\n")); ! 366: ! 367: vBlowCache(ppdev); ! 368: ! 369: pCachedGlyphs = pCacheFont(ppdev, pstro, pfo, &pCachedFont); ! 370: if (pCachedGlyphs == NULL) ! 371: { ! 372: DISPDBG((1, "S3.DLL!bHandleCachedFonts - pCacheFont failed twice\n")); ! 373: return(FALSE); ! 374: } ! 375: } ! 376: ! 377: (PCACHEDFONT)(pfo->pvConsumer) = pCachedFont; ! 378: } ! 379: ! 380: // If this string has a Zero Bearing and the string object's ! 381: // opaque rectangle is the same size as the opaque rectangle then ! 382: // and opaque mode is requested, then lay down the glyphs in ! 383: // opaque mode. ! 384: ! 385: if (((flAccel = pstro->flAccel) & SO_ZERO_BEARINGS) && ! 386: ((flAccel & (SO_HORIZONTAL | SO_VERTICAL | SO_REVERSED)) == SO_HORIZONTAL) && ! 387: (flAccel & SO_CHAR_INC_EQUAL_BM_BASE) && ! 388: (prclOpaque != NULL)) ! 389: { ! 390: // If the Opaque rect and the string rect match then ! 391: // were done. If not then we have to fill in the strips ! 392: // (top, bottom, left, and right) around the text. ! 393: ! 394: culRcl = 0; ! 395: ! 396: // Top fragment ! 397: ! 398: if (pstro->rclBkGround.top > prclOpaque->top) ! 399: { ! 400: arclTmp[culRcl].top = prclOpaque->top; ! 401: arclTmp[culRcl].left = prclOpaque->left; ! 402: arclTmp[culRcl].right = prclOpaque->right; ! 403: arclTmp[culRcl++].bottom = pstro->rclBkGround.top; ! 404: } ! 405: ! 406: // Left fragment ! 407: ! 408: if (pstro->rclBkGround.left > prclOpaque->left) ! 409: { ! 410: arclTmp[culRcl].top = pstro->rclBkGround.top; ! 411: arclTmp[culRcl].left = prclOpaque->left; ! 412: arclTmp[culRcl].right = pstro->rclBkGround.left; ! 413: arclTmp[culRcl++].bottom = pstro->rclBkGround.bottom; ! 414: } ! 415: ! 416: // Right fragment ! 417: ! 418: if (pstro->rclBkGround.right < prclOpaque->right) ! 419: { ! 420: arclTmp[culRcl].top = pstro->rclBkGround.top; ! 421: arclTmp[culRcl].right = prclOpaque->right; ! 422: arclTmp[culRcl].left = pstro->rclBkGround.right; ! 423: arclTmp[culRcl++].bottom = pstro->rclBkGround.bottom; ! 424: } ! 425: ! 426: // Bottom fragment ! 427: ! 428: if (pstro->rclBkGround.bottom < prclOpaque->bottom) ! 429: { ! 430: arclTmp[culRcl].bottom = prclOpaque->bottom; ! 431: arclTmp[culRcl].left = prclOpaque->left; ! 432: arclTmp[culRcl].right = prclOpaque->right; ! 433: arclTmp[culRcl++].top = pstro->rclBkGround.bottom; ! 434: } ! 435: ! 436: // Fill any fringe rectangles we found ! 437: ! 438: for (i = 0; i < culRcl; i++) ! 439: { ! 440: bOpaqueRect(ppdev, &(arclTmp[i]), prclClip, pboOpaque); ! 441: } ! 442: ! 443: // Set the mix mode for opaque text. ! 444: ! 445: mix = (mix & 0x0F) | (R2_COPYPEN << 8); ! 446: b = bSetS3TextColorAndMix(ppdev, mix, pboFore, pboOpaque); ! 447: if (b == FALSE) ! 448: return (b); ! 449: ! 450: } ! 451: else ! 452: { ! 453: // Take care of any opaque rectangles. ! 454: ! 455: if (prclOpaque != NULL) ! 456: { ! 457: bOpaqueRect(ppdev, prclOpaque, prclClip, pboOpaque); ! 458: } ! 459: ! 460: jBackgroundRop = R2_NOP; ! 461: ! 462: // Take care of the glyph attributes, color and mix. ! 463: ! 464: mix = (mix & 0x0F) | (jBackgroundRop << 8); ! 465: b = bSetS3TextColorAndMix(ppdev, mix, pboFore, pboOpaque); ! 466: if (b == FALSE) ! 467: return (b); ! 468: } ! 469: ! 470: // Test for a trivial accept of the string rect. ! 471: ! 472: if (bTrivialAcceptTest(&(pstro->rclBkGround), prclClip)) ! 473: fl |= TRIVIAL_ACCEPT; ! 474: ! 475: // Test and setup for a mono-spaced font. ! 476: ! 477: if ((ulCharInc = pstro->ulCharInc) != 0) ! 478: fl |= MONO_SPACED_FONT; ! 479: ! 480: // Set the S3 command. ! 481: ! 482: Cmd = BITBLT | DRAW | DIR_TYPE_XY | WRITE | ! 483: MULTIPLE_PIXELS| DRAWING_DIR_TBLRXM; ! 484: ! 485: // This does not change in the inner loop so it is now out of it. ! 486: ! 487: FIFOWAIT(FIFO_1_EMPTY); ! 488: OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | DISPLAY_MEMORY)); ! 489: ! 490: // Get the Glyph Handles. ! 491: ! 492: if ((pstro->pgp) == NULL) ! 493: STROBJ_vEnumStart(pstro); ! 494: ! 495: do ! 496: { ! 497: if (pstro->pgp == NULL) ! 498: { ! 499: bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphs, &pgp); ! 500: ! 501: } ! 502: else ! 503: { ! 504: pgp = pstro->pgp; ! 505: cGlyphs = pstro->cGlyphs; ! 506: bMoreGlyphs = FALSE; ! 507: } ! 508: ! 509: // For mono space fonts this is non-zero. ! 510: ! 511: if (fl & MONO_SPACED_FONT) ! 512: { ! 513: xMonoPosition = pgp[0].ptl.x; ! 514: yMonoStart = pgp[0].ptl.y; ! 515: } ! 516: ! 517: for (iGlyph = 0; iGlyph < cGlyphs; iGlyph++) ! 518: { ! 519: // Get the Glyph Handle. ! 520: // If there was a hash table hit for the glygph ! 521: // then were "golden", if not then we have to search ! 522: // the collision list. ! 523: ! 524: ihGlyph = pgp[iGlyph].hg & pCachedFont->cGlyphs; ! 525: ! 526: pcg = &(pCachedGlyphs[ihGlyph]); ! 527: ! 528: if ((hg = pgp[iGlyph].hg) != pcg->hg) ! 529: { ! 530: if (!(pcg->fl & VALID_GLYPH)) ! 531: { ! 532: // Allocate a place in the cache. ! 533: ! 534: pgb = pgp[iGlyph].pgdf->pgb; ! 535: b = bAllocateGlyph(ppdev, hg, pgb, pcg); ! 536: if (b == FALSE) ! 537: { ! 538: vBlowCache(ppdev); ! 539: return (FALSE); ! 540: } ! 541: ! 542: b = bSetS3TextColorAndMix(ppdev, mix, pboFore, pboOpaque); ! 543: if (b == FALSE) ! 544: return (FALSE); ! 545: ! 546: FIFOWAIT(FIFO_1_EMPTY); ! 547: OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | DISPLAY_MEMORY)); ! 548: ! 549: } ! 550: else ! 551: { ! 552: // Search the collision list. ! 553: ! 554: DISPDBG((1, "S3.DLL!bHandleCachedFonts - searching collision list\n")); ! 555: ! 556: bFound = FALSE; ! 557: while (pcg->pcgCollisionLink != END_COLLISIONS) ! 558: { ! 559: pcg = pcg->pcgCollisionLink; ! 560: ! 561: if (pcg->hg == pgp[iGlyph].hg) ! 562: { ! 563: bFound = TRUE; ! 564: break; ! 565: } ! 566: } ! 567: ! 568: if (!bFound) ! 569: { ! 570: // Allocate a new font glyph node. ! 571: ! 572: pcgNew = (PCACHEDGLYPH) LocalAlloc(LPTR, sizeof(CACHEDGLYPH)); ! 573: if (pcgNew == NULL) ! 574: { ! 575: DISPDBG((1, "S3.DLL!bHandleCachedFont - Local Alloc (pcgNew) failed\n")); ! 576: return (FALSE); ! 577: } ! 578: ! 579: // Connect the end of the collision list to the new ! 580: // glyph node. ! 581: ! 582: pcg->pcgCollisionLink = pcgNew; ! 583: ! 584: // Set up the pointer to the node where going to init. ! 585: ! 586: pcg = pcgNew; ! 587: ! 588: pgb = pgp[iGlyph].pgdf->pgb; ! 589: b = bAllocateGlyph(ppdev, hg, pgb, pcg); ! 590: if (b == FALSE) ! 591: { ! 592: vBlowCache(ppdev); ! 593: return (FALSE); ! 594: } ! 595: ! 596: b = bSetS3TextColorAndMix(ppdev, mix, pboFore, pboOpaque); ! 597: if (b == FALSE) ! 598: return (FALSE); ! 599: ! 600: FIFOWAIT(FIFO_1_EMPTY); ! 601: OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | DISPLAY_MEMORY)); ! 602: ! 603: } ! 604: } ! 605: } ! 606: ! 607: // Adjust the placement of the glyph. ! 608: // And if this is a mono-spaced font set the blt height & width. ! 609: ! 610: if (fl & MONO_SPACED_FONT) ! 611: { ! 612: ptl.x = xMonoPosition + pcg->ptlOrigin.x; ! 613: ptl.y = yMonoStart + pcg->ptlOrigin.y; ! 614: xMonoPosition += ulCharInc; ! 615: ! 616: if ((!(fl & MONO_SIZE_VALID) && (fl & TRIVIAL_ACCEPT)) || ! 617: (!(fl & MONO_FIRST_TIME))) ! 618: { ! 619: fl |= MONO_SIZE_VALID; ! 620: ! 621: TFIFOWAIT(FIFO_2_EMPTY); ! 622: OUTPW(RECT_WIDTH, pcg->sizlBitmap.cx - 1); ! 623: OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | (pcg->sizlBitmap.cy - 1))); ! 624: } ! 625: ! 626: } ! 627: else ! 628: { ! 629: ptl.x = pgp[iGlyph].ptl.x + pcg->ptlOrigin.x; ! 630: ptl.y = pgp[iGlyph].ptl.y + pcg->ptlOrigin.y; ! 631: } ! 632: ! 633: if (fl & TRIVIAL_ACCEPT) ! 634: { ! 635: // Blit the glyph ! 636: ! 637: if (!(fl & MONO_SPACED_FONT)) ! 638: { ! 639: TFIFOWAIT(FIFO_2_EMPTY); ! 640: OUTPW(RECT_WIDTH, pcg->sizlBitmap.cx - 1); ! 641: OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | (pcg->sizlBitmap.cy - 1))); ! 642: } ! 643: ! 644: TFIFOWAIT(FIFO_6_EMPTY); ! 645: TEST_AND_SET_RD_MASK(LOWORD(pcg->xyzGlyph.z)); ! 646: ! 647: OUTPW(CUR_X, pcg->xyzGlyph.x); ! 648: OUTPW(CUR_Y, pcg->xyzGlyph.y); ! 649: OUTPW(DEST_X, ptl.x); ! 650: OUTPW(DEST_Y, ptl.y); ! 651: OUTPW(CMD, Cmd); ! 652: ! 653: } ! 654: else ! 655: { ! 656: xyzGlyph = pcg->xyzGlyph; ! 657: ! 658: // Clip each character, ! 659: ! 660: rclGlyph.left = ptl.x; ! 661: rclGlyph.top = ptl.y; ! 662: rclGlyph.right = ptl.x + pcg->sizlBitmap.cx; ! 663: rclGlyph.bottom = ptl.y + pcg->sizlBitmap.cy; ! 664: ! 665: if (bIntersectTest(&rclGlyph, prclClip)) ! 666: { ! 667: rclGlyph.left = max (rclGlyph.left, prclClip->left); ! 668: rclGlyph.top = max (rclGlyph.top, prclClip->top); ! 669: rclGlyph.right = min (rclGlyph.right, prclClip->right); ! 670: rclGlyph.bottom = min (rclGlyph.bottom, prclClip->bottom); ! 671: ! 672: cxGlyph = (rclGlyph.right - rclGlyph.left) - 1; ! 673: cyGlyph = (rclGlyph.bottom - rclGlyph.top) - 1; ! 674: ! 675: if (cxGlyph < 0 || cyGlyph < 0) ! 676: continue; ! 677: ! 678: ptlSrc.x = xyzGlyph.x + (rclGlyph.left - ptl.x); ! 679: ptlSrc.y = xyzGlyph.y + (rclGlyph.top - ptl.y); ! 680: ! 681: // Blit the glyph ! 682: ! 683: TFIFOWAIT(FIFO_8_EMPTY); ! 684: TEST_AND_SET_RD_MASK(LOWORD(pcg->xyzGlyph.z)); ! 685: ! 686: OUTPW(RECT_WIDTH, cxGlyph); ! 687: OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | cyGlyph)); ! 688: OUTPW(CUR_X, ptlSrc.x); ! 689: OUTPW(CUR_Y, ptlSrc.y); ! 690: OUTPW(DEST_X, rclGlyph.left); ! 691: OUTPW(DEST_Y, rclGlyph.top); ! 692: OUTPW(CMD, Cmd); ! 693: ! 694: } ! 695: else ! 696: { ! 697: continue; ! 698: } ! 699: } ! 700: } ! 701: ! 702: } while(bMoreGlyphs); ! 703: ! 704: return (TRUE); ! 705: ! 706: } ! 707: ! 708: ! 709: /**************************************************************************** ! 710: * bHandleNonCachedFonts ! 711: ***************************************************************************/ ! 712: BOOL bHandleNonCachedFonts( ! 713: SURFOBJ *pso, ! 714: STROBJ *pstro, ! 715: FONTOBJ *pfo, ! 716: RECTL *prclClip, ! 717: RECTL *prclExtra, ! 718: RECTL *prclOpaque, ! 719: BRUSHOBJ *pboFore, ! 720: BRUSHOBJ *pboOpaque, ! 721: POINTL *pptlOrg, ! 722: MIX mix) ! 723: { ! 724: BOOL b, ! 725: bMoreGlyphs; ! 726: ULONG iGlyph, ! 727: cGlyphs; ! 728: GLYPHBITS *pgb; ! 729: POINTL ptl; ! 730: GLYPHPOS *pgp; ! 731: LONG cyGlyph, ! 732: cjGlyph, ! 733: GlyphBmPitchInBytes; ! 734: WORD S3Cmd; ! 735: INT i, culRcl; ! 736: ULONG flAccel; ! 737: RECTL arclTmp[4]; ! 738: ! 739: ULONG ulCharInc; ! 740: ULONG yMonoStart, xMonoPosition; ! 741: PPDEV ppdev; ! 742: BYTE jBackgroundRop; ! 743: RECTL rclClip; ! 744: ! 745: ULONG fl = 0; ! 746: ! 747: DISPDBG((4, "S3.DLL!bHandleNonCachedFonts\n")); ! 748: ! 749: ppdev = (PPDEV) pso->dhpdev; ! 750: ! 751: // We need to reset the clipping so any opaque rectangles are ! 752: // rendered correctly. ! 753: ! 754: vResetS3Clipping(ppdev); ! 755: ! 756: // If this string has a Zero Bearing and the string object's ! 757: // opaque rectangle is the same size as the opaque rectangle then ! 758: // and opaque mode is requested, then lay down the glyphs in ! 759: // opaque mode. ! 760: ! 761: if (((flAccel = pstro->flAccel) & SO_ZERO_BEARINGS) && ! 762: ((flAccel & (SO_HORIZONTAL | SO_VERTICAL | SO_REVERSED)) == SO_HORIZONTAL) && ! 763: (flAccel & SO_CHAR_INC_EQUAL_BM_BASE) && ! 764: (prclOpaque != NULL)) ! 765: { ! 766: // If the Opaque rect and the string rect match then ! 767: // were done. If not then we have to fill in the strips ! 768: // (top, bottom, left, and right) around the text. ! 769: ! 770: culRcl = 0; ! 771: ! 772: // Top fragment ! 773: ! 774: if (pstro->rclBkGround.top > prclOpaque->top) ! 775: { ! 776: arclTmp[culRcl].top = prclOpaque->top; ! 777: arclTmp[culRcl].left = prclOpaque->left; ! 778: arclTmp[culRcl].right = prclOpaque->right; ! 779: arclTmp[culRcl++].bottom = pstro->rclBkGround.top; ! 780: } ! 781: ! 782: // Left fragment ! 783: ! 784: if (pstro->rclBkGround.left > prclOpaque->left) ! 785: { ! 786: arclTmp[culRcl].top = pstro->rclBkGround.top; ! 787: arclTmp[culRcl].left = prclOpaque->left; ! 788: arclTmp[culRcl].right = pstro->rclBkGround.left; ! 789: arclTmp[culRcl++].bottom = pstro->rclBkGround.bottom; ! 790: } ! 791: ! 792: // Right fragment ! 793: ! 794: if (pstro->rclBkGround.right < prclOpaque->right) ! 795: { ! 796: arclTmp[culRcl].top = pstro->rclBkGround.top; ! 797: arclTmp[culRcl].right = prclOpaque->right; ! 798: arclTmp[culRcl].left = pstro->rclBkGround.right; ! 799: arclTmp[culRcl++].bottom = pstro->rclBkGround.bottom; ! 800: } ! 801: ! 802: // Bottom fragment ! 803: ! 804: if (pstro->rclBkGround.bottom < prclOpaque->bottom) ! 805: { ! 806: arclTmp[culRcl].bottom = prclOpaque->bottom; ! 807: arclTmp[culRcl].left = prclOpaque->left; ! 808: arclTmp[culRcl].right = prclOpaque->right; ! 809: arclTmp[culRcl++].top = pstro->rclBkGround.bottom; ! 810: } ! 811: ! 812: // Fill any fringe rectangles we found ! 813: ! 814: for (i = 0; i < culRcl; i++) ! 815: { ! 816: bOpaqueRect(ppdev, &(arclTmp[i]), prclClip, pboOpaque); ! 817: } ! 818: ! 819: // Set the mix mode for opaque text. ! 820: ! 821: mix = (mix & 0x0F) | (R2_COPYPEN << 8); ! 822: b = bSetS3TextColorAndMix(ppdev, mix, pboFore, pboOpaque); ! 823: if (b == FALSE) ! 824: return (b); ! 825: } ! 826: else ! 827: { ! 828: // Take care of any opaque rectangles. ! 829: ! 830: if (prclOpaque != NULL) ! 831: { ! 832: bOpaqueRect(ppdev, prclOpaque, prclClip, pboOpaque); ! 833: } ! 834: ! 835: jBackgroundRop = R2_NOP; ! 836: ! 837: // Take care of the glyph attributes, color and mix. ! 838: ! 839: mix = (mix & 0x0F) | (jBackgroundRop << 8); ! 840: b = bSetS3TextColorAndMix(ppdev, mix, pboFore, pboOpaque); ! 841: if (b == FALSE) ! 842: return (b); ! 843: } ! 844: ! 845: rclClip = *prclClip; ! 846: rclClip.bottom; ! 847: rclClip.right; ! 848: vSetS3ClipRect(ppdev, &rclClip); ! 849: ! 850: // Test and setup for a mono-spaced font. ! 851: ! 852: if ((ulCharInc = pstro->ulCharInc) != 0) ! 853: fl |= MONO_SPACED_FONT; ! 854: ! 855: // Setup the Command Word for the S3. ! 856: ! 857: S3Cmd = RECTANGLE_FILL | BUS_SIZE_8 | ! 858: WAIT | DRAWING_DIR_TBLRXM | DRAW | ! 859: LAST_PIXEL_ON | MULTIPLE_PIXELS | WRITE; ! 860: ! 861: FIFOWAIT(FIFO_2_EMPTY) ! 862: ! 863: // Enable the write mask for all planes. ! 864: // and set the S3 for CPU Data. ! 865: ! 866: TEST_AND_SET_WRT_MASK(0xFF); ! 867: OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | CPU_DATA)); ! 868: ! 869: // Get the Glyph Handles. ! 870: ! 871: if ((pstro->pgp) == NULL) ! 872: STROBJ_vEnumStart(pstro); ! 873: ! 874: do ! 875: { ! 876: if (pstro->pgp == NULL) ! 877: { ! 878: bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphs, &pgp); ! 879: } ! 880: else ! 881: { ! 882: pgp = pstro->pgp; ! 883: cGlyphs = pstro->cGlyphs; ! 884: bMoreGlyphs = FALSE; ! 885: } ! 886: ! 887: // For mono space fonts this is non-zero. ! 888: ! 889: if (fl & MONO_SPACED_FONT) ! 890: { ! 891: xMonoPosition = pgp[0].ptl.x; ! 892: yMonoStart = pgp[0].ptl.y; ! 893: } ! 894: ! 895: for (iGlyph = 0; iGlyph < cGlyphs; iGlyph++) ! 896: { ! 897: // Get a pointer to the GlyphBits. ! 898: ! 899: pgb = pgp[iGlyph].pgdf->pgb; ! 900: ! 901: // Adjust the placement of the glyph. ! 902: // If this is a mono-spaced font set the blt height & width only ! 903: // once for the string. ! 904: ! 905: if (fl & MONO_SPACED_FONT) ! 906: { ! 907: ptl.x = xMonoPosition + pgb->ptlOrigin.x; ! 908: ptl.y = yMonoStart + pgb->ptlOrigin.y; ! 909: xMonoPosition += ulCharInc; ! 910: ! 911: if (!(fl & MONO_SIZE_VALID)) ! 912: { ! 913: fl |= MONO_SIZE_VALID; ! 914: ! 915: // Calculate the number of bytes in this glyph. ! 916: ! 917: cyGlyph = pgb->sizlBitmap.cy; ! 918: ! 919: GlyphBmPitchInBytes = CJ_SCAN(pgb->sizlBitmap.cx); ! 920: cjGlyph = GlyphBmPitchInBytes * cyGlyph; ! 921: ! 922: TFIFOWAIT(FIFO_2_EMPTY); ! 923: OUTPW(RECT_WIDTH, pgb->sizlBitmap.cx - 1); ! 924: OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | cyGlyph - 1)); ! 925: } ! 926: ! 927: FIFOWAIT(FIFO_3_EMPTY) ! 928: } ! 929: else ! 930: { ! 931: ptl.x = pgp[iGlyph].ptl.x + pgb->ptlOrigin.x; ! 932: ptl.y = pgp[iGlyph].ptl.y + pgb->ptlOrigin.y; ! 933: ! 934: // Calculate the number of bytes in this glyph. ! 935: ! 936: cyGlyph = pgb->sizlBitmap.cy; ! 937: ! 938: GlyphBmPitchInBytes = CJ_SCAN(pgb->sizlBitmap.cx); ! 939: cjGlyph = GlyphBmPitchInBytes * cyGlyph; ! 940: ! 941: FIFOWAIT(FIFO_5_EMPTY) ! 942: ! 943: // Set up for the image transfer. ! 944: ! 945: OUTPW(RECT_WIDTH, pgb->sizlBitmap.cx - 1); ! 946: OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | cyGlyph - 1)); ! 947: } ! 948: ! 949: // If a character is way off to the left then continue ! 950: ! 951: if ((ptl.x < 0) && ((ptl.x + pgb->sizlBitmap.cx) < 0)) ! 952: continue; ! 953: ! 954: // Yes, believe it or not we have to check for chipping on the right also. ! 955: ! 956: if ((ptl.x > (LONG) ppdev->cxScreen) && ((ptl.x + pgb->sizlBitmap.cx) > (LONG) ppdev->cxScreen)) ! 957: continue; ! 958: ! 959: // Set up for the image transfer. ! 960: ! 961: OUTPW(CUR_X, LOWORD(ptl.x)); ! 962: OUTPW(CUR_Y, LOWORD(ptl.y)); ! 963: ! 964: GPWAIT(); ! 965: ! 966: OUTPW(CMD, S3Cmd); ! 967: ! 968: CHECK_DATA_READY; ! 969: ! 970: vDataPortOutB(ppdev, pgb->aj, cjGlyph); ! 971: ! 972: CHECK_DATA_COMPLETE; ! 973: ! 974: } ! 975: ! 976: } while(bMoreGlyphs); ! 977: ! 978: return (TRUE); ! 979: ! 980: } ! 981: ! 982: ! 983: /***************************************************************************** ! 984: * S3 Solid Opaque Rect. ! 985: * ! 986: * Returns TRUE if the Opaque Rect was handled. ! 987: ****************************************************************************/ ! 988: BOOL bOpaqueRect( ! 989: PPDEV ppdev, ! 990: RECTL *prclOpaque, ! 991: RECTL *prclBounds, ! 992: BRUSHOBJ *pboOpaque) ! 993: { ! 994: INT width, height; ! 995: WORD S3Cmd; ! 996: ULONG iSolidColor; ! 997: RECTL rclClipped; ! 998: BOOL bClipRequired; ! 999: ! 1000: DISPDBG((4, "S3.DLL!bOpaqueRect - Entry\n")); ! 1001: ! 1002: rclClipped = *prclOpaque; ! 1003: ! 1004: // First handle the trivial rejection. ! 1005: ! 1006: bClipRequired = bIntersectTest(&rclClipped, prclBounds); ! 1007: ! 1008: // define the clipped target rectangle. ! 1009: ! 1010: if (bClipRequired) ! 1011: { ! 1012: rclClipped.left = max (rclClipped.left, prclBounds->left); ! 1013: rclClipped.top = max (rclClipped.top, prclBounds->top); ! 1014: rclClipped.right = min (rclClipped.right, prclBounds->right); ! 1015: rclClipped.bottom = min (rclClipped.bottom, prclBounds->bottom); ! 1016: } ! 1017: else ! 1018: return (TRUE); ! 1019: ! 1020: // Set the color ! 1021: ! 1022: iSolidColor = pboOpaque->iSolidColor; ! 1023: if (iSolidColor == -1) ! 1024: return(FALSE); ! 1025: ! 1026: width = (rclClipped.right - rclClipped.left) - 1; ! 1027: height = (rclClipped.bottom - rclClipped.top) - 1; ! 1028: ! 1029: if (width >= 0 && height >= 0) ! 1030: { ! 1031: ! 1032: FIFOWAIT(FIFO_8_EMPTY) ! 1033: ! 1034: TEST_AND_SET_FRGD_MIX(FOREGROUND_COLOR | OVERPAINT); ! 1035: TEST_AND_SET_FRGD_COLOR(LOWORD(iSolidColor)); ! 1036: OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES)); ! 1037: OUTPW(CUR_X, LOWORD(rclClipped.left)); ! 1038: OUTPW(CUR_Y, LOWORD(rclClipped.top)); ! 1039: OUTPW(RECT_WIDTH, width); ! 1040: OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | height)); ! 1041: ! 1042: S3Cmd = RECTANGLE_FILL | DRAWING_DIR_TBLRXM | DRAW | ! 1043: DIR_TYPE_XY | LAST_PIXEL_ON | ! 1044: MULTIPLE_PIXELS | WRITE; ! 1045: ! 1046: OUTPW(CMD, S3Cmd); ! 1047: } ! 1048: ! 1049: return (TRUE); ! 1050: } ! 1051: ! 1052: ! 1053: ! 1054: /****************************************************************************** ! 1055: * bSetS3TextColorAndMix - Setup the S3's Text Colors and mix modes ! 1056: * ! 1057: * Note: We will always set the mode to transparent. We will assume the ! 1058: * opaque rectangle will take care of any opaqueing we may need. ! 1059: *****************************************************************************/ ! 1060: BOOL bSetS3TextColorAndMix( ! 1061: PPDEV ppdev, ! 1062: MIX mix, ! 1063: BRUSHOBJ *pboFore, ! 1064: BRUSHOBJ *pboOpaque) ! 1065: { ! 1066: ULONG ulForeSolidColor, ulBackSolidColor; ! 1067: BYTE jS3ForeMix, jS3BackMix; ! 1068: ! 1069: // Pickup all the glyph attributes. ! 1070: ! 1071: jS3ForeMix = Rop2ToS3Rop[(mix & 0xF) - R2_BLACK]; ! 1072: ulForeSolidColor = pboFore->iSolidColor; ! 1073: ! 1074: jS3BackMix = Rop2ToS3Rop[((mix >> 8) & 0xF) - R2_BLACK]; ! 1075: ulBackSolidColor = pboOpaque->iSolidColor; ! 1076: ! 1077: // For now let the engine handle the non-solid brush cases. !!! ! 1078: // We should use S3 when we get some more time !!! ! 1079: ! 1080: if (ulForeSolidColor == -1 || ulBackSolidColor == -1) ! 1081: return(FALSE); ! 1082: ! 1083: FIFOWAIT(FIFO_4_EMPTY) ! 1084: ! 1085: // Set the S3 Attributes. ! 1086: ! 1087: TEST_AND_SET_FRGD_MIX(FOREGROUND_COLOR | jS3ForeMix); ! 1088: TEST_AND_SET_FRGD_COLOR(LOWORD(ulForeSolidColor)); ! 1089: ! 1090: TEST_AND_SET_BKGD_MIX(BACKGROUND_COLOR | jS3BackMix); ! 1091: TEST_AND_SET_BKGD_COLOR(LOWORD(ulBackSolidColor)); ! 1092: ! 1093: return (TRUE); ! 1094: ! 1095: } ! 1096: ! 1097: /***************************************************************************** ! 1098: * pCacheFont - Make sure the glyphs we need in this font are cached. ! 1099: * Return a pointer to the array of glyph caches. ! 1100: * ! 1101: * if there is an error, return NULL. ! 1102: ****************************************************************************/ ! 1103: PCACHEDGLYPH pCacheFont( ! 1104: PPDEV ppdev, ! 1105: STROBJ *pstro, ! 1106: FONTOBJ *pfo, ! 1107: PCACHEDFONT *ppCachedFont) ! 1108: { ! 1109: FONTINFO fi; ! 1110: PCACHEDFONT pCachedFont; ! 1111: ULONG cFntGlyphs; ! 1112: UINT nSize; ! 1113: ! 1114: BOOL bFoundBit, bEven; ! 1115: ULONG mask, mask1; ! 1116: INT i, j; ! 1117: ! 1118: DISPDBG((3, "S3.DLL!pCacheFont - Entry\n")); ! 1119: ! 1120: // Allocate a Font Cache node. ! 1121: ! 1122: pCachedFont = (PCACHEDFONT) LocalAlloc(LPTR, sizeof(CACHEDFONT)); ! 1123: if (pCachedFont == NULL) ! 1124: { ! 1125: DISPDBG((1, "S3.DLL!pCacheFont - LocalAlloc of pCachedFont failed\n")); ! 1126: return(NULL); ! 1127: } ! 1128: ! 1129: // Add this font to the beginning of the font list. ! 1130: ! 1131: pCachedFont->pcfNext = pCachedFontsRoot; ! 1132: pCachedFontsRoot = pCachedFont; ! 1133: ! 1134: // Set the font ID for the font. ! 1135: ! 1136: pCachedFont->iUniq = pfo->iUniq; ! 1137: ! 1138: // Allocate the glyph cache. ! 1139: ! 1140: FONTOBJ_vGetInfo(pfo, sizeof(FONTINFO), &fi); ! 1141: cFntGlyphs = fi.cGlyphsSupported; ! 1142: ! 1143: // This is where we clamp the size of the Font structures we are allocating. ! 1144: ! 1145: if (cFntGlyphs > MAX_GLYPHS_TO_ALLOC) ! 1146: cFntGlyphs = MAX_GLYPHS_TO_ALLOC; ! 1147: ! 1148: // Round up to the next power of 2. ! 1149: ! 1150: bFoundBit = FALSE; ! 1151: mask = 0x80000000; ! 1152: for (i = 32; i != 0 && !bFoundBit; i--) ! 1153: { ! 1154: if (cFntGlyphs & mask) ! 1155: { ! 1156: bFoundBit = TRUE; ! 1157: mask1 = mask >> 1; ! 1158: bEven = TRUE; ! 1159: for (j = i - 1; j != 0; j--) ! 1160: { ! 1161: if (cFntGlyphs & mask1 ) ! 1162: { ! 1163: bEven = FALSE; ! 1164: break; ! 1165: } ! 1166: mask1 >>= 1; ! 1167: } ! 1168: } ! 1169: else ! 1170: mask >>= 1; ! 1171: } ! 1172: ! 1173: if (bEven) ! 1174: cFntGlyphs = mask; ! 1175: else ! 1176: cFntGlyphs = mask << 1; ! 1177: ! 1178: // Get the font info. ! 1179: ! 1180: pCachedFont->cGlyphs = cFntGlyphs - 1; ! 1181: ! 1182: // Allocate memory for the CachedGlyphs of this font. ! 1183: ! 1184: nSize = cFntGlyphs * sizeof(CACHEDGLYPH); ! 1185: ! 1186: pCachedFont->pCachedGlyphs = (PCACHEDGLYPH) LocalAlloc(LPTR, nSize); ! 1187: if (pCachedFont->pCachedGlyphs == NULL) ! 1188: { ! 1189: DISPDBG((1, "S3.DLL!pCacheFont - LocalAlloc of pCachedGlyphs failed\n")); ! 1190: pCachedFont->cGlyphs = 0; ! 1191: return(NULL); ! 1192: } ! 1193: ! 1194: pCachedFont->pCachedGlyphs[0].hg = (HGLYPH)-1; ! 1195: ! 1196: // Return the pointer to the cached font. This is required ! 1197: // by the collision handling code. ! 1198: ! 1199: *ppCachedFont = pCachedFont; ! 1200: ! 1201: return(pCachedFont->pCachedGlyphs); ! 1202: ! 1203: } ! 1204: ! 1205: ! 1206: /***************************************************************************** ! 1207: * bAllocateGlyph - Allocate and initialize the cached glyph ! 1208: ****************************************************************************/ ! 1209: BOOL bAllocateGlyph( ! 1210: PPDEV ppdev, ! 1211: HGLYPH hg, ! 1212: GLYPHBITS *pgb, ! 1213: PCACHEDGLYPH pcg) ! 1214: { ! 1215: BOOL b; ! 1216: ULONG cyGlyph, GlyphBmPitchInPels, GlyphBmPitchInBytes; ! 1217: XYZPOINTL xyzGlyph; ! 1218: WORD Cmd; ! 1219: ! 1220: DISPDBG((3, "S3.DLL!bAllocateGlyph - Entry\n")); ! 1221: ! 1222: cyGlyph = pgb->sizlBitmap.cy; ! 1223: ! 1224: GlyphBmPitchInBytes = CJ_SCAN(pgb->sizlBitmap.cx); ! 1225: GlyphBmPitchInPels = GlyphBmPitchInBytes * 8; ! 1226: ! 1227: // Allocate memory for the glyph data on the S3. ! 1228: ! 1229: b = bAllocGlyphMemory(ppdev, &(pgb->sizlBitmap), &xyzGlyph); ! 1230: if (b == FALSE) ! 1231: { ! 1232: DISPDBG((1, "S3.DLL!bAllocateGlyph - hCpAlloc failed\n")); ! 1233: return(FALSE); ! 1234: } ! 1235: ! 1236: // Initialize the Glyph Cache node. ! 1237: ! 1238: pcg->fl |= VALID_GLYPH; ! 1239: pcg->hg = hg; ! 1240: pcg->pcgCollisionLink = END_COLLISIONS; ! 1241: pcg->ptlOrigin = pgb->ptlOrigin; ! 1242: pcg->sizlBitmap = pgb->sizlBitmap; ! 1243: pcg->BmPitchInPels = GlyphBmPitchInPels; ! 1244: pcg->BmPitchInBytes = GlyphBmPitchInBytes; ! 1245: pcg->xyzGlyph = xyzGlyph; ! 1246: ! 1247: // Initialize the Glyph Cache data in S3 memory. ! 1248: ! 1249: Cmd = RECTANGLE_FILL | BUS_SIZE_8 | WAIT | ! 1250: DRAW | DRAWING_DIR_TBLRXM | DIR_TYPE_XY | ! 1251: LAST_PIXEL_ON | MULTIPLE_PIXELS | WRITE; ! 1252: ! 1253: // Setup the S3 chip. ! 1254: ! 1255: FIFOWAIT(FIFO_5_EMPTY); ! 1256: ! 1257: TEST_AND_SET_FRGD_MIX(LOGICAL_1); ! 1258: TEST_AND_SET_BKGD_MIX(LOGICAL_0); ! 1259: TEST_AND_SET_WRT_MASK(LOWORD(xyzGlyph.z)); ! 1260: OUTPW(CUR_X, xyzGlyph.x); ! 1261: OUTPW(CUR_Y, xyzGlyph.y); ! 1262: ! 1263: FIFOWAIT(FIFO_4_EMPTY); ! 1264: ! 1265: OUTPW(MULTIFUNC_CNTL, (DATA_EXTENSION | CPU_DATA)); ! 1266: OUTPW(RECT_WIDTH, GlyphBmPitchInPels - 1); ! 1267: OUTPW(MULTIFUNC_CNTL, (RECT_HEIGHT | cyGlyph - 1)); ! 1268: GPWAIT(); ! 1269: OUTPW(CMD, Cmd); ! 1270: ! 1271: CHECK_DATA_READY; ! 1272: ! 1273: // Now transfer the data. ! 1274: ! 1275: vDataPortOutB(ppdev, pgb->aj, GlyphBmPitchInBytes * cyGlyph); ! 1276: ! 1277: CHECK_DATA_COMPLETE; ! 1278: ! 1279: // Need to reset the write mask. ! 1280: ! 1281: FIFOWAIT(FIFO_1_EMPTY); ! 1282: ! 1283: TEST_AND_SET_WRT_MASK(0xFF); ! 1284: ! 1285: return (TRUE); ! 1286: } ! 1287: ! 1288: ! 1289: /**************************************************************************** ! 1290: * vBlowCache - Blow Away the Cache ! 1291: ***************************************************************************/ ! 1292: VOID vBlowCache(PPDEV ppdev) ! 1293: { ! 1294: PCACHEDFONT pcf; ! 1295: PCACHEDGLYPH pcg, pcgNext; ! 1296: INT nGlyphs, i; ! 1297: ! 1298: DISPDBG((2, "S3.DLL!vBlowCache - Entry\n")); ! 1299: ! 1300: // Traverse the CachedFonts list. ! 1301: // Free the collision nodes, and invalidate the cached glyphs ! 1302: ! 1303: for (pcf = pCachedFontsRoot; pcf != NULL; pcf = pcf->pcfNext) ! 1304: { ! 1305: // If there are any collision nodes for this glyph ! 1306: // free them. ! 1307: ! 1308: nGlyphs = pcf->cGlyphs+1; ! 1309: ! 1310: for (i = 0; i < nGlyphs; i++) ! 1311: { ! 1312: pcg = &(pcf->pCachedGlyphs[i]); ! 1313: pcg = pcg->pcgCollisionLink; ! 1314: for (; pcg != NULL; pcg = pcgNext) ! 1315: { ! 1316: pcgNext = pcg->pcgCollisionLink; ! 1317: LocalFree(pcg); ! 1318: } ! 1319: pcf->pCachedGlyphs[i].pcgCollisionLink = NULL; ! 1320: ! 1321: } ! 1322: ! 1323: // Invalidate all the glyphs in the glyph array. ! 1324: ! 1325: pcg = pcf->pCachedGlyphs; ! 1326: for (i = 0; i < nGlyphs; i++) ! 1327: { ! 1328: pcg[i].hg = (HGLYPH) -1; ! 1329: pcg[i].fl &= ~VALID_GLYPH; ! 1330: } ! 1331: } ! 1332: ! 1333: // Now ReInitialize the S3 Heap. ! 1334: ! 1335: memset((PVOID)ppdev->ajGlyphAllocBitVector, ! 1336: 0, CACHED_GLYPHS_ROWS * GLYPHS_PER_ROW); ! 1337: ! 1338: return; ! 1339: } ! 1340: ! 1341: /****************************************************************************** ! 1342: * bAllocGlyphMemory - ! 1343: * ! 1344: * Allocate the some memory for the glyph. ! 1345: * ! 1346: * ! 1347: * return: TRUE - if memory was allocated. ! 1348: * FALSE - if there was no more memory. ! 1349: * ! 1350: *****************************************************************************/ ! 1351: BOOL bAllocGlyphMemory( ! 1352: PPDEV ppdev, ! 1353: PSIZEL psizlGlyph, ! 1354: PXYZPOINTL pxyzGlyph) ! 1355: { ! 1356: BOOL bFound; ! 1357: INT iPlane, iRow, iGlyph; ! 1358: BYTE jPlaneBitVector; ! 1359: ! 1360: ! 1361: // Search the bit vector ! 1362: ! 1363: bFound = FALSE; ! 1364: for (iPlane = 0; iPlane < 8; iPlane++) ! 1365: { ! 1366: jPlaneBitVector = (BYTE) iPlaneBits[iPlane]; ! 1367: ! 1368: for (iRow = 0; iRow < CACHED_GLYPHS_ROWS; iRow++) ! 1369: { ! 1370: for (iGlyph = 0; iGlyph < GLYPHS_PER_ROW; iGlyph++) ! 1371: { ! 1372: if (!(ppdev->ajGlyphAllocBitVector[iRow][iGlyph] & jPlaneBitVector)) ! 1373: { ! 1374: bFound = TRUE; ! 1375: ppdev->ajGlyphAllocBitVector[iRow][iGlyph] |= ! 1376: jPlaneBitVector; ! 1377: ! 1378: pxyzGlyph->z = jPlaneBitVector; ! 1379: pxyzGlyph->x = iGlyph * GLYPH_CACHE_CX; ! 1380: pxyzGlyph->y = (iRow * GLYPH_CACHE_CY) + GLYPH_CACHE_Y; ! 1381: ! 1382: DISPDBG((5, "S3.DLL!bAllocGlyphMemory\n")); ! 1383: DISPDBG((5, "\t pxyzGlyph->z: %0x\n", pxyzGlyph->z)); ! 1384: DISPDBG((5, "\t pxyzGlyph->x: %d\n", pxyzGlyph->x)); ! 1385: DISPDBG((5, "\t pxyzGlyph->y: %d\n", pxyzGlyph->y)); ! 1386: ! 1387: return (bFound); ! 1388: } ! 1389: } ! 1390: } ! 1391: } ! 1392: ! 1393: return (bFound); ! 1394: } ! 1395:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.