|
|
1.1 ! root 1: /******************************Module*Header*******************************\ ! 2: * Module Name: textout.c ! 3: * ! 4: * VGA DrvTextOut Entry point ! 5: * ! 6: * Copyright (c) 1992 Microsoft Corporation ! 7: \**************************************************************************/ ! 8: #include "driver.h" ! 9: #include "textout.h" ! 10: ! 11: #define SO_MASK \ ! 12: ( \ ! 13: SO_FLAG_DEFAULT_PLACEMENT | \ ! 14: SO_ZERO_BEARINGS | \ ! 15: SO_CHAR_INC_EQUAL_BM_BASE | \ ! 16: SO_MAXEXT_EQUAL_BM_SIDE \ ! 17: ) ! 18: ! 19: // accelerator masks for four canonical directions of ! 20: // writing (multiples of 90 degrees) ! 21: ! 22: #define SO_LTOR (SO_MASK | SO_HORIZONTAL) ! 23: #define SO_RTOL (SO_LTOR | SO_REVERSED) ! 24: #define SO_TTOB (SO_MASK | SO_VERTICAL) ! 25: #define SO_BTOT (SO_TTOB | SO_REVERSED) ! 26: ! 27: /**************************************************************************\ ! 28: * Function Declarations ! 29: \**************************************************************************/ ! 30: ! 31: VOID vGlyphBlt (PDEVSURF,PRECTL,ULONG,PGLYPHPOS,ULONG,ULONG,ULONG,FLONG); ! 32: VOID vStringBlt(PDEVSURF,PRECTL,ULONG,PGLYPHPOS,ULONG,ULONG,ULONG,FLONG); ! 33: ULONG ulSetXParentRegs(ROP4,PULONG,BOOL); ! 34: VOID vResetVGARegs(void); ! 35: BOOL bIdenticalRect(PRECTL,PRECTL); ! 36: FLONG flClipRect(PRECTL,PRECTL,PRECTL); ! 37: VOID lclFillRect(CLIPOBJ *pco, ULONG culRcl, PRECTL prcl, PDEVSURF pdsurf, ! 38: INT iColor); ! 39: BOOL DrvIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2); ! 40: VOID vFastText(GLYPHPOS *, ULONG, PBYTE, ULONG, ULONG, DEVSURF *, RECTL *, ! 41: RECTL *, INT, INT, ULONG, RECTL *); ! 42: ! 43: /**************************************************************************\ ! 44: * Mix mode-Rop4 Mapping Table ! 45: \**************************************************************************/ ! 46: ! 47: static ROP4 arop4[] = { // !!! This table needs serious fixing ! 48: 0x0000, /* 0 */ ! 49: 0x0000, /* DPon */ ! 50: 0x0000, /* DPna */ ! 51: 0x0f0f, /* Pn */ ! 52: 0x0000, /* PDna */ ! 53: 0x5555, /* Dn */ ! 54: 0x0000, /* DPx */ ! 55: 0x0000, /* DPan */ ! 56: 0x0000, /* DPa */ ! 57: 0x0000, /* DPxn */ ! 58: 0x0000, /* D */ ! 59: 0x0000, /* DPno */ ! 60: 0xf0f0, /* P */ ! 61: 0x0000, /* PDno */ ! 62: 0x0000, /* DPo */ ! 63: 0xffff /* 1 */ ! 64: }; ! 65: ! 66: #define B_ORDERED_RECT(prcl) (((prcl) == (PRECTL)NULL) ? 1 : (((prcl)->left <= (prcl)->right) && ((prcl)->top <= (prcl)->bottom))) ! 67: ! 68: ! 69: /******************************Public*Routine******************************\ ! 70: * BOOL DrvTextOut(pso,pstro,pfo,pco,prclExtra,prcOpaque, ! 71: * pvFore,pvBack,pptOrg,r2Fore,r2Back) ! 72: * ! 73: \**************************************************************************/ ! 74: ! 75: BOOL DrvTextOut( ! 76: SURFOBJ *pso, ! 77: STROBJ *pstro, ! 78: FONTOBJ *pfo, ! 79: CLIPOBJ *pco, ! 80: PRECTL prclExtra, ! 81: PRECTL prclOpaque, ! 82: BRUSHOBJ *pboFore, ! 83: BRUSHOBJ *pboOpaque, ! 84: PPOINTL pptlOrg, ! 85: MIX mix) ! 86: { ! 87: PDEVSURF pdsurf; // Pointer to device surface ! 88: ! 89: ULONG iClip; // Clip object's complexity ! 90: ULONG iClipTmp; // Clip object's complexity ! 91: ULONG ircl; // index to current clip rect ! 92: BOOL bMore; // Flag for clip enumeration ! 93: RECT_ENUM txen; // Clip enumeration object ! 94: ! 95: GLYPHPOS *pgp; // pointer to the 1st glyph ! 96: GLYPHBITS *pgb; // pointer to glyph bits. ! 97: ! 98: BOOL bMoreGlyphs; // Glyph enumeration flag ! 99: ULONG cGlyph; // number of glyphs in one batch ! 100: ULONG iGlyph; // index to current glyph ! 101: RECTL rclGlyph; // string/glyph cell ! 102: RECTL rclTmp; // Temporary rectangle ! 103: RECTL rclBankTmp; // Temporary rectangle when bank ! 104: // clipping ! 105: ! 106: ROP4 rop4; // Rop tranlated from mix mode ! 107: ULONG iSolidTextColor; // Solid foreground text color ! 108: ULONG iSolidForeColor; // Solid foreground color ! 109: ULONG iSolidBkColor; // Solid background color ! 110: ! 111: FLONG flStr = 0; // Accelator flag for DrvTextOut() ! 112: ! 113: ULONG ulMixMode; // Glyph mix mode ! 114: PFN pfnBlt; // function to output glyph/string ! 115: FLONG flOption = 0; // Accelator flag for pfnBlt ! 116: FLONG flOptionTemp; // Working version of flOption ! 117: ! 118: RECTL arclTmp[4]; // Temp storage for portions of ! 119: // opaquing rect ! 120: ULONG culRcl; // Temp rectangle count ! 121: ! 122: //--------------------------------------------------------------------- ! 123: // Get the target surface information ! 124: //--------------------------------------------------------------------- ! 125: ! 126: // Now find out if the target is the screen ! 127: pdsurf = (PDEVSURF) pso->dhsurf; ! 128: ! 129: //--------------------------------------------------------------------- ! 130: // Get information about clip object. ! 131: //--------------------------------------------------------------------- ! 132: ! 133: iClip = DC_TRIVIAL; ! 134: ! 135: if (pco != NULL) { ! 136: iClip = pco->iDComplexity; ! 137: } ! 138: ! 139: //--------------------------------------------------------------------- ! 140: // Get text color. ! 141: //--------------------------------------------------------------------- ! 142: ! 143: iSolidForeColor = iSolidTextColor = pboFore->iSolidColor; ! 144: ! 145: //--------------------------------------------------------------------- ! 146: // See if this is text we can handle faster with special-case code. ! 147: //--------------------------------------------------------------------- ! 148: ! 149: if ((((prclOpaque != NULL) && (iClip != DC_COMPLEX)) || ! 150: // handle opaque both non-clipped & ! 151: // rectangle-clipped ! 152: ((prclOpaque == NULL) && (iClip == DC_TRIVIAL))) && ! 153: // handle xpar non-clipped only ! 154: // for now ! 155: (pstro->pgp != NULL) && // no glyph enumeration for now ! 156: (prclExtra == NULL) && // no extra rects for now ! 157: ((pstro->flAccel & (SO_HORIZONTAL | SO_VERTICAL | SO_REVERSED)) == ! 158: SO_HORIZONTAL)) { // only left-to-right text for now ! 159: ! 160: ULONG ulBufferWidthInBytes; ! 161: ULONG ulBufferBytes; ! 162: BOOL bTextPerfectFit; ! 163: ULONG fDrawFlags; ! 164: BYTE *pjTempBuffer; ! 165: BOOL bTempAlloc; ! 166: ! 167: // It's the type of text we can special-case; see if the temp buffer is ! 168: // big enough for the text; if not, try to allocate enough memory. ! 169: // Round up to the nearest dword multiple. ! 170: ! 171: ulBufferWidthInBytes = ((((pstro->rclBkGround.right + 15) & ~0x0F) - ! 172: (pstro->rclBkGround.left & ~0x0F)) >> 3); ! 173: ulBufferBytes = ((ulBufferWidthInBytes * ! 174: (pstro->rclBkGround.bottom - pstro->rclBkGround.top)) + 3) ! 175: & ~0x03; ! 176: ! 177: if (ulBufferBytes <= pdsurf->ulTempBufferSize) { ! 178: // The temp buffer is big enough, so we'll use it ! 179: pjTempBuffer = pdsurf->pvBankBufferPlane0; ! 180: bTempAlloc = FALSE; ! 181: } else { ! 182: // The temp buffer isn't big enough, so we'll try to allocate ! 183: // enough memory ! 184: if ((pjTempBuffer = ! 185: LocalAlloc(LMEM_FIXED, ulBufferBytes)) == NULL) { ! 186: // We couldn't get enough memory, so fall back to the general, ! 187: // slow code ! 188: goto NoFastText; ! 189: } ! 190: ! 191: // Mark that we have to free the buffer when we're done ! 192: bTempAlloc = TRUE; ! 193: } ! 194: ! 195: // One way or another, we've found a buffer that's big enough; set up ! 196: // for accelerated text drawing ! 197: ! 198: // Set fixed pitch, overlap, and top & bottom Y alignment flags ! 199: fDrawFlags = ((pstro->ulCharInc != 0) ? 0x01 : 0) | ! 200: (((pstro->flAccel & (SO_ZERO_BEARINGS | ! 201: SO_FLAG_DEFAULT_PLACEMENT)) != ! 202: (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT)) ! 203: ? 0x02 : 0) | ! 204: (((pstro->flAccel & (SO_ZERO_BEARINGS | ! 205: SO_FLAG_DEFAULT_PLACEMENT | ! 206: SO_MAXEXT_EQUAL_BM_SIDE)) == ! 207: (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT | ! 208: SO_MAXEXT_EQUAL_BM_SIDE)) ? 0x04 : 0); ! 209: ! 210: // If there's an opaque rectangle, we'll do as much opaquing as ! 211: // possible as we do the text. If the opaque rectangle is larger than ! 212: // the text rectangle, then we'll do the fringe areas right now, and ! 213: // the text and associated background areas together later ! 214: if (prclOpaque != (PRECTL) NULL) { ! 215: ! 216: // This driver only handles solid brushes ! 217: iSolidBkColor = pboOpaque->iSolidColor; ! 218: ! 219: // See if we have fringe areas to do. If so, build a list of ! 220: // rectangles to fill, in rightdown order ! 221: ! 222: culRcl = 0; ! 223: ! 224: // Top fragment ! 225: if (pstro->rclBkGround.top > prclOpaque->top) { ! 226: arclTmp[culRcl].top = prclOpaque->top; ! 227: arclTmp[culRcl].left = prclOpaque->left; ! 228: arclTmp[culRcl].right = prclOpaque->right; ! 229: arclTmp[culRcl++].bottom = pstro->rclBkGround.top; ! 230: } ! 231: ! 232: // Left fragment ! 233: if (pstro->rclBkGround.left > prclOpaque->left) { ! 234: arclTmp[culRcl].top = pstro->rclBkGround.top; ! 235: arclTmp[culRcl].left = prclOpaque->left; ! 236: arclTmp[culRcl].right = pstro->rclBkGround.left; ! 237: arclTmp[culRcl++].bottom = pstro->rclBkGround.bottom; ! 238: } ! 239: ! 240: // Right fragment ! 241: if (pstro->rclBkGround.right < prclOpaque->right) { ! 242: arclTmp[culRcl].top = pstro->rclBkGround.top; ! 243: arclTmp[culRcl].right = prclOpaque->right; ! 244: arclTmp[culRcl].left = pstro->rclBkGround.right; ! 245: arclTmp[culRcl++].bottom = pstro->rclBkGround.bottom; ! 246: } ! 247: ! 248: // Bottom fragment ! 249: if (pstro->rclBkGround.bottom < prclOpaque->bottom) { ! 250: arclTmp[culRcl].bottom = prclOpaque->bottom; ! 251: arclTmp[culRcl].left = prclOpaque->left; ! 252: arclTmp[culRcl].right = prclOpaque->right; ! 253: arclTmp[culRcl++].top = pstro->rclBkGround.bottom; ! 254: } ! 255: ! 256: // Fill any fringe rectangles we found ! 257: if (culRcl != 0) { ! 258: if (iClip == DC_TRIVIAL) { ! 259: vTrgBlt(pdsurf, culRcl, arclTmp, R2_COPYPEN, ! 260: iSolidBkColor); ! 261: } else { ! 262: lclFillRect(pco, culRcl, arclTmp, pdsurf, ! 263: iSolidBkColor); ! 264: } ! 265: } ! 266: } ! 267: ! 268: // We're done with separate opaquing; any further opaquing will happen ! 269: // as part of the text drawing ! 270: ! 271: // Clear the buffer if the text isn't going to set every bit ! 272: bTextPerfectFit = (pstro->flAccel & (SO_ZERO_BEARINGS | ! 273: SO_FLAG_DEFAULT_PLACEMENT | SO_MAXEXT_EQUAL_BM_SIDE | ! 274: SO_CHAR_INC_EQUAL_BM_BASE)) == ! 275: (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT | ! 276: SO_MAXEXT_EQUAL_BM_SIDE | SO_CHAR_INC_EQUAL_BM_BASE); ! 277: ! 278: if (!bTextPerfectFit) { ! 279: // Note that we already rounded up to a dword multiple size. ! 280: vClearMemDword((ULONG *)pjTempBuffer, ulBufferBytes >> 2); ! 281: } ! 282: ! 283: // Draw the text into the temp buffer, and thence to the screen ! 284: vFastText(pstro->pgp, ! 285: pstro->cGlyphs, ! 286: ((PBYTE) pjTempBuffer) + ! 287: ((pstro->rclBkGround.left & 0x08) ? 1 : 0), ! 288: ulBufferWidthInBytes, ! 289: pstro->ulCharInc, ! 290: pdsurf, ! 291: &pstro->rclBkGround, ! 292: prclOpaque, ! 293: iSolidForeColor, ! 294: iSolidBkColor, ! 295: fDrawFlags, ! 296: (iClip == DC_TRIVIAL) ? NULL : &pco->rclBounds); ! 297: ! 298: // Free up any memory we allocated for the temp buffer ! 299: if (bTempAlloc) { ! 300: LocalFree(pjTempBuffer); ! 301: } ! 302: ! 303: return(TRUE); ! 304: ! 305: } ! 306: ! 307: NoFastText: ! 308: ! 309: //-------------------------------------------------------------------------- ! 310: // Get the foreground and background colors ! 311: //-------------------------------------------------------------------------- ! 312: ! 313: rop4 = arop4[(mix & 255) - R2_BLACK]; // Get ROP4 from mix mode ! 314: ! 315: // This driver only handles solid brushes ! 316: ! 317: // If no background rectangle, we need to paint only the glyph foreground. ! 318: // Set VGA registers for the current rop and foreground color at once and ! 319: // maintain them while blting the glyphs. ! 320: ! 321: if (prclOpaque == (PRECTL) NULL) ! 322: { ! 323: ulMixMode = ulSetXParentRegs(rop4, &iSolidForeColor, TRUE); ! 324: flStr |= TO_NO_OPAQUE_RECT; ! 325: } else { ! 326: ! 327: // This driver only handles solid brushes ! 328: iSolidBkColor = pboOpaque->iSolidColor; ! 329: // ASSERT ( iSolidBkColor != 0xFFFFFFFFL, "Non solid opaque brush\n" ); ! 330: } ! 331: ! 332: //-------------------------------------------------------------------------- ! 333: // Enumerate glyphs for the string, and output to screen one batch at a time. ! 334: // Here is how we will output background rectangle and glyphs:- ! 335: // ! 336: // if glyphs are non-justified and horizontally aligned ! 337: // if opaque background rectangle doesn't exactly match the string bound ! 338: // Paint portions of background that are outside text cells ! 339: // Output the string one batch at a time, drawing both fg & bg in cells ! 340: // else ! 341: // Paint opaque rectangle only once ! 342: // Output to screen one glyph at a time ! 343: // ! 344: //-------------------------------------------------------------------------- ! 345: ! 346: // Set up the STROBJ for enumerating the glyphs ! 347: ! 348: // STROBJ_vEnumStart(pstro); // This is automatic. ! 349: ! 350: if ((pstro->flAccel == SO_LTOR) && (pstro->ulCharInc != 0)) ! 351: { ! 352: flStr |= TO_FIXED_PITCH; ! 353: if ((pstro->ulCharInc & 7) == 0) ! 354: flStr |= TO_MULTIPLE_BYTE; ! 355: } ! 356: ! 357: do { ! 358: ! 359: // Get the next batch of glyphs ! 360: ! 361: if (pstro->pgp != NULL) { ! 362: // There's only the one batch of glyphs, so save ourselves a call ! 363: pgp = pstro->pgp; ! 364: cGlyph = pstro->cGlyphs; ! 365: bMoreGlyphs = FALSE; ! 366: } else { ! 367: bMoreGlyphs = STROBJ_bEnum(pstro,&cGlyph,&pgp); ! 368: } ! 369: ! 370: //-------------------------------------------------------------------- ! 371: // No glyph, no work! ! 372: //-------------------------------------------------------------------- ! 373: ! 374: if ( cGlyph ) { ! 375: // Collect information about the string. ! 376: ! 377: pgb = pgp->pgdf->pgb; // Locate the bitmap info. ! 378: ! 379: if ((flStr & TO_MULTIPLE_BYTE) && ! 380: ((pgb->ptlOrigin.x + pgp->ptl.x) & 7) == 0) { ! 381: flStr |= TO_BYTE_ALIGNED; ! 382: } ! 383: ! 384: if ((pstro->flAccel == SO_LTOR) && ! 385: (pgb->sizlBitmap.cy <= MAX_GLYPH_HEIGHT)) { ! 386: // We can blt horizontally aligned string with non-justified ! 387: // text at once. ! 388: ! 389: pfnBlt = (PFN)vStringBlt; ! 390: flOption |= VGB_ENTIRE_STRING_BLT; ! 391: ! 392: // we can special-case an aligned byte-size string ! 393: ! 394: flOption |= (flStr & (VGB_BYTE_ALIGNED | VGB_MULTIPLE_BYTE)); ! 395: ! 396: // If there's an opaque rectangle, then if the opaque ! 397: // rectangle exactly matches the text rectangle, we'll do the ! 398: // opaque rectangle as we do the text. If the opaque rectangle ! 399: // is larger than the text rectangle, then we'll do the fringe ! 400: // areas right now, and the text and associated background ! 401: // areas together, later. ! 402: if (!(flStr & TO_NO_OPAQUE_RECT)) { ! 403: ! 404: // See if we have fringe areas to do. If so, build a ! 405: // list of rectangles to fill, in rightdown order ! 406: ! 407: culRcl = 0; ! 408: ! 409: // Top fragment ! 410: if (pstro->rclBkGround.top > prclOpaque->top) { ! 411: arclTmp[culRcl].top = prclOpaque->top; ! 412: arclTmp[culRcl].left = prclOpaque->left; ! 413: arclTmp[culRcl].right = prclOpaque->right; ! 414: arclTmp[culRcl++].bottom = pstro->rclBkGround.top; ! 415: } ! 416: ! 417: // Left fragment ! 418: if (pstro->rclBkGround.left > prclOpaque->left) { ! 419: arclTmp[culRcl].top = pstro->rclBkGround.top; ! 420: arclTmp[culRcl].left = prclOpaque->left; ! 421: arclTmp[culRcl].right = pstro->rclBkGround.left; ! 422: arclTmp[culRcl++].bottom = ! 423: pstro->rclBkGround.bottom; ! 424: } ! 425: ! 426: // Right fragment ! 427: if (pstro->rclBkGround.right < prclOpaque->right) { ! 428: arclTmp[culRcl].top = pstro->rclBkGround.top; ! 429: arclTmp[culRcl].right = prclOpaque->right; ! 430: arclTmp[culRcl].left = pstro->rclBkGround.right; ! 431: arclTmp[culRcl++].bottom = ! 432: pstro->rclBkGround.bottom; ! 433: } ! 434: ! 435: // Bottom fragment ! 436: if (pstro->rclBkGround.bottom < prclOpaque->bottom) { ! 437: arclTmp[culRcl].bottom = prclOpaque->bottom; ! 438: arclTmp[culRcl].left = prclOpaque->left; ! 439: arclTmp[culRcl].right = prclOpaque->right; ! 440: arclTmp[culRcl++].top = pstro->rclBkGround.bottom; ! 441: } ! 442: ! 443: // Fill any fringe rectangles we found ! 444: if (culRcl > 0) { ! 445: if (iClip == DC_TRIVIAL) { ! 446: vTrgBlt(pdsurf, culRcl, arclTmp, R2_COPYPEN, ! 447: iSolidBkColor); ! 448: } else { ! 449: lclFillRect(pco, culRcl, arclTmp, pdsurf, ! 450: iSolidBkColor); ! 451: } ! 452: } ! 453: ! 454: ! 455: // The opaque rectangle exactly matches the text ! 456: // background cells. We can simultaneously paint it ! 457: // with the glyph. Then, pretend no background ! 458: // rectangle. ! 459: ! 460: flStr |= TO_NO_OPAQUE_RECT; ! 461: flOption |= VGB_OPAQUE_BKGRND; ! 462: ! 463: // Although we do not want to set the VGA regs, we ! 464: // need to know their mode when we actually blt. ! 465: ! 466: ulMixMode = ulSetXParentRegs(rop4, &iSolidForeColor, FALSE); ! 467: ! 468: } ! 469: ! 470: // It is foolishly assumed in the clipping vStrBlt that GDI ! 471: // puts all positions in the GLYPHPOS array even when the font ! 472: // is fixed pitch. ! 473: ! 474: if (pstro->ulCharInc != 0) { ! 475: UINT ii; ! 476: LONG x,y; ! 477: ! 478: x = pgp[0].ptl.x; ! 479: y = pgp[0].ptl.y; ! 480: ! 481: for (ii=1; ii<cGlyph; ii++) { ! 482: x += pstro->ulCharInc; ! 483: pgp[ii].ptl.x = x; ! 484: pgp[ii].ptl.y = y; ! 485: } ! 486: } ! 487: } else { ! 488: // We need to output one glyph at a time. ! 489: ! 490: pfnBlt = (PFN) vGlyphBlt; ! 491: ! 492: // It is foolishly assumed in vGlyphBlt that GDI puts all ! 493: // positions in the GLYPHPOS array even when the font is ! 494: // fixed pitch. ! 495: ! 496: if (pstro->ulCharInc != 0) { ! 497: UINT ii; ! 498: LONG x,y; ! 499: ! 500: x = pgp[0].ptl.x; ! 501: y = pgp[0].ptl.y; ! 502: for (ii=1; ii<cGlyph; ii++) { ! 503: x += pstro->ulCharInc; ! 504: pgp[ii].ptl.x = x; ! 505: pgp[ii].ptl.y = y; ! 506: } ! 507: } ! 508: } ! 509: } ! 510: ! 511: //------------------------------------------------------------------ ! 512: // Paint background rectangle if exists. ! 513: //------------------------------------------------------------------ ! 514: ! 515: if (!(flStr & TO_NO_OPAQUE_RECT)) ! 516: { ! 517: switch ( iClip ) ! 518: { ! 519: case DC_RECT: ! 520: ! 521: // Intersect opaque and clip rectangles ! 522: ! 523: flClipRect(&rclTmp, prclOpaque, &pco->rclBounds); ! 524: ! 525: if (BINVALIDRECT(rclTmp)) ! 526: { ! 527: break; ! 528: }; ! 529: prclOpaque = &rclTmp; ! 530: ! 531: case DC_TRIVIAL: ! 532: vTrgBlt(pdsurf, 1, prclOpaque, R2_COPYPEN, iSolidBkColor); ! 533: break; ! 534: ! 535: case DC_COMPLEX: ! 536: ! 537: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, ! 538: ENUM_RECT_LIMIT); ! 539: bMore = TRUE; ! 540: ! 541: do ! 542: { ! 543: if (bMore) { ! 544: bMore = CLIPOBJ_bEnum(pco, (ULONG) ! 545: sizeof(txen), (PVOID) &txen); ! 546: } ! 547: ! 548: for (ircl = 0; ircl < txen.c; ircl++) ! 549: { ! 550: ! 551: // Clip only if we have clipping region ! 552: ! 553: flClipRect ( &rclTmp, prclOpaque, &txen.arcl[ircl] ); ! 554: ! 555: if (!(BINVALIDRECT(rclTmp))) ! 556: { ! 557: // rop4 <--> PATCOPY ! 558: ! 559: vTrgBlt(pdsurf, 1, &rclTmp, ! 560: R2_COPYPEN, iSolidBkColor); ! 561: }; ! 562: } ! 563: ! 564: } while (bMore); ! 565: break; ! 566: } ! 567: ! 568: // We need to paint the background only once. So pretend it ! 569: // does not exist anymore. ! 570: ! 571: flStr |= TO_NO_OPAQUE_RECT; ! 572: ! 573: // Set VGA registers for transparent glyphs. ! 574: ! 575: ulMixMode = ulSetXParentRegs(rop4, &iSolidForeColor, TRUE); ! 576: ! 577: } ! 578: ! 579: //---------------------------------------------------------------------- ! 580: // We are ready to output glyphs to screen. By now either the background ! 581: // rectangle (if any) was painted or we will paint it while outputting ! 582: // each glyph/string. ! 583: //---------------------------------------------------------------------- ! 584: ! 585: for (iGlyph = 0; iGlyph < cGlyph; iGlyph++) ! 586: { ! 587: pgb = pgp[iGlyph].pgdf->pgb; ! 588: iClipTmp = iClip; ! 589: ! 590: if (!(flOption & VGB_ENTIRE_STRING_BLT)) ! 591: { ! 592: pgp[iGlyph].ptl.x += pgb->ptlOrigin.x; ! 593: pgp[iGlyph].ptl.y += pgb->ptlOrigin.y; ! 594: ! 595: rclGlyph.left = pgp[iGlyph].ptl.x; ! 596: rclGlyph.right = rclGlyph.left + pgb->sizlBitmap.cx; ! 597: rclGlyph.top = pgp[iGlyph].ptl.y; ! 598: rclGlyph.bottom = rclGlyph.top + pgb->sizlBitmap.cy; ! 599: ! 600: if ((iClipTmp == DC_TRIVIAL) && ! 601: ((rclGlyph.left < pco->rclBounds.left) || ! 602: (rclGlyph.top < pco->rclBounds.top) || ! 603: (rclGlyph.right > pco->rclBounds.right) || ! 604: (rclGlyph.bottom > pco->rclBounds.bottom))) ! 605: iClipTmp = DC_RECT; ! 606: } else { ! 607: // Build the correct bounding box for the current batch of ! 608: // glyphs (the bounding box in the STROBJ is for the entire ! 609: // string, not on a per-batch basis) ! 610: rclGlyph.left = pgp[iGlyph].ptl.x; ! 611: rclGlyph.right = pgp[iGlyph + cGlyph - 1].ptl.x + ! 612: pgp[iGlyph + cGlyph - 1].pgdf->pgb->sizlBitmap.cx; ! 613: rclGlyph.top = pstro->rclBkGround.top; ! 614: rclGlyph.bottom = pstro->rclBkGround.bottom; ! 615: } ! 616: ! 617: flOption &= ~(VGB_VERT_CLIPPED_GLYPH | VGB_HORIZ_CLIPPED_GLYPH); ! 618: ! 619: switch ( iClipTmp ) ! 620: { ! 621: case DC_RECT: ! 622: ! 623: // Intersect glyph and clip rectangles ! 624: ! 625: flOption |= flClipRect(&rclGlyph, &rclGlyph, &pco->rclBounds); ! 626: if (BINVALIDRECT(rclGlyph)) ! 627: break; ! 628: ! 629: case DC_TRIVIAL: ! 630: // Cycle through all banks that the (possibly clipped) ! 631: // glpyh rect spans ! 632: ! 633: // If the proper bank for the top scan line of ! 634: // the clipped glyph isn't mapped in, map it in ! 635: if ((rclGlyph.top < pdsurf->rcl1WindowClip.top) || ! 636: (rclGlyph.top >= pdsurf->rcl1WindowClip.bottom)) { ! 637: ! 638: // Map in the bank containing the top (possibly ! 639: // clipped) glyph line ! 640: pdsurf->pfnBankControl(pdsurf, ! 641: rclGlyph.top, ! 642: JustifyTop); ! 643: } ! 644: ! 645: // Now draw the part of the rect that's in each ! 646: // bank ! 647: ! 648: for (;;) { ! 649: ! 650: flOptionTemp = flOption | ! 651: flClipRect(&rclBankTmp, &rclGlyph, ! 652: &pdsurf->rcl1WindowClip); ! 653: ! 654: (*pfnBlt)(pdsurf, &rclBankTmp, cGlyph, ! 655: &pgp[iGlyph], iSolidForeColor, iSolidBkColor, ! 656: ulMixMode, flOptionTemp); ! 657: ! 658: // Done if this bank contains the last line ! 659: // of the fill ! 660: if (rclGlyph.bottom <= pdsurf->rcl1WindowClip.bottom) { ! 661: break; ! 662: } ! 663: ! 664: // Map in the next bank ! 665: pdsurf->pfnBankControl(pdsurf, ! 666: pdsurf->rcl1WindowClip.bottom, ! 667: JustifyTop); ! 668: ! 669: } ! 670: ! 671: break; ! 672: ! 673: case DC_COMPLEX: ! 674: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, ! 675: ENUM_RECT_LIMIT); ! 676: bMore = TRUE; ! 677: ! 678: do ! 679: { ! 680: if (bMore) { ! 681: // Enumerate more clip rects ! 682: bMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(txen), ! 683: (PVOID) &txen); ! 684: } ! 685: ! 686: // Draw the portion of the glyph that intersects each ! 687: // clip rect in turn ! 688: for (ircl = 0; ircl < txen.c; ircl++) ! 689: { ! 690: // Clip the glyph to the next clip rect, and set ! 691: // our clipping flags ! 692: flOption |= flClipRect ( &rclTmp, &rclGlyph, ! 693: &txen.arcl[ircl] ); ! 694: ! 695: // If we have a valid rectangle to draw, draw it ! 696: if (!(BINVALIDRECT(rclTmp))) { ! 697: // Cycle through all banks that the clipped ! 698: // glpyh rect spans ! 699: ! 700: // If the proper bank for the top scan line of ! 701: // the clipped glyph isn't mapped in, map it in ! 702: if ((rclTmp.top < ! 703: pdsurf->rcl1WindowClip.top) || ! 704: (rclTmp.top >= ! 705: pdsurf->rcl1WindowClip.bottom)) { ! 706: ! 707: // Map in the bank containing the top ! 708: // clipped glyph line ! 709: pdsurf->pfnBankControl(pdsurf, ! 710: rclTmp.top, ! 711: JustifyTop); ! 712: } ! 713: ! 714: // Now draw the part of the rect that's in each ! 715: // bank ! 716: ! 717: for (;;) { ! 718: ! 719: flOptionTemp = flOption | ! 720: flClipRect(&rclBankTmp, &rclTmp, ! 721: &pdsurf->rcl1WindowClip); ! 722: ! 723: ! 724: (*pfnBlt)(pdsurf, &rclBankTmp, cGlyph, ! 725: &pgp[iGlyph], iSolidForeColor, ! 726: iSolidBkColor, ulMixMode, ! 727: flOptionTemp); ! 728: ! 729: // Done if this bank contains the last line ! 730: // of the fill ! 731: if (rclTmp.bottom <= ! 732: pdsurf->rcl1WindowClip.bottom) { ! 733: break; ! 734: } ! 735: ! 736: // Map in the next bank ! 737: pdsurf->pfnBankControl(pdsurf, ! 738: pdsurf->rcl1WindowClip.bottom, ! 739: JustifyTop); ! 740: ! 741: } ! 742: } ! 743: ! 744: flOption &= ~(VGB_VERT_CLIPPED_GLYPH | ! 745: VGB_HORIZ_CLIPPED_GLYPH); ! 746: } ! 747: } while (bMore); ! 748: break; ! 749: } ! 750: ! 751: // We might have blted the entire string. ! 752: ! 753: if (flOption & VGB_ENTIRE_STRING_BLT) ! 754: break; ! 755: } ! 756: ! 757: } while (bMoreGlyphs); ! 758: ! 759: // Reset VGA registers ! 760: ! 761: vResetVGARegs(); ! 762: ! 763: //-------------------------------------------------------------------------- ! 764: // Now handle the 'extra' rectangles. ! 765: //-------------------------------------------------------------------------- ! 766: ! 767: if (prclExtra != (PRECTL) NULL) ! 768: { ! 769: while (prclExtra->left != prclExtra->right) ! 770: { ! 771: switch ( iClip ) ! 772: { ! 773: case DC_TRIVIAL: ! 774: vTrgBlt(pdsurf, 1, prclExtra, mix, iSolidTextColor); ! 775: break; ! 776: ! 777: case DC_RECT: ! 778: ! 779: // Intersect opaque and clip rectangles ! 780: ! 781: flClipRect ( &rclTmp, prclExtra, &pco->rclBounds ); ! 782: ! 783: if (BINVALIDRECT(rclTmp)) ! 784: break; ! 785: ! 786: vTrgBlt(pdsurf, 1, &rclTmp, mix, iSolidTextColor); ! 787: break; ! 788: ! 789: case DC_COMPLEX: ! 790: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, ! 791: ENUM_RECT_LIMIT); ! 792: bMore = TRUE; ! 793: ! 794: do ! 795: { ! 796: if (bMore) { ! 797: bMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(txen), ! 798: (PVOID) &txen); ! 799: } ! 800: ! 801: for (ircl = 0; ircl < txen.c; ircl++) ! 802: { ! 803: flClipRect ( &rclTmp, prclExtra, &txen.arcl[ircl] ); ! 804: ! 805: if (!(BINVALIDRECT(rclTmp))) ! 806: { ! 807: vTrgBlt(pdsurf, 1, &rclTmp, ! 808: mix, iSolidTextColor); ! 809: }; ! 810: } ! 811: } while (bMore); ! 812: break; ! 813: }; ! 814: ! 815: prclExtra++; // Advance to next extra rectangle ! 816: } ! 817: } ! 818: ! 819: //-------------------------------------------------------------------------- ! 820: // Clean up the surface ! 821: //-------------------------------------------------------------------------- ! 822: ! 823: pptlOrg; ! 824: return(TRUE); ! 825: } ! 826: ! 827: ! 828: //-------------------------------------------------------------------------- ! 829: // Fills the specified rectangles on the specified surface with the ! 830: // specified color, honoring the requested clipping. No more than four ! 831: // rectangles should be passed in. Intended for drawing the areas of the ! 832: // opaquing rectangle that extended beyond the text box. The rectangles must ! 833: // be in left to right, top to bottom order. Assumes there is at least one ! 834: // rectangle in the list. ! 835: //-------------------------------------------------------------------------- ! 836: ! 837: VOID lclFillRect( ! 838: CLIPOBJ *pco, ! 839: ULONG culRcl, ! 840: PRECTL prcl, ! 841: PDEVSURF pdsurf, ! 842: INT iColor) ! 843: { ! 844: BOOL bMore; // Flag for clip enumeration ! 845: RECT_ENUM txen; // Clip enumeration object ! 846: ULONG i, j; ! 847: RECTL arclTmp[4]; ! 848: ULONG culRclTmp; ! 849: RECTL *prclTmp, *prclClipTmp; ! 850: INT iLastBottom; ! 851: RECTL *pClipRcl; ! 852: INT iClip; ! 853: ! 854: // ASSERT(culRcl <= 4, "Too many rects"); ! 855: ! 856: iClip = DC_TRIVIAL; ! 857: ! 858: if (pco != NULL) { ! 859: iClip = pco->iDComplexity; ! 860: } ! 861: ! 862: switch ( iClip ) { ! 863: ! 864: case DC_TRIVIAL: ! 865: ! 866: vTrgBlt(pdsurf, culRcl, prcl, R2_COPYPEN, iColor); ! 867: ! 868: break; ! 869: ! 870: case DC_RECT: ! 871: ! 872: prclTmp = &pco->rclBounds; ! 873: ! 874: // Generate a list of clipped rects ! 875: for (culRclTmp=0, i=0; i<culRcl; i++, prcl++) { ! 876: ! 877: // Intersect fill and clip rectangles ! 878: if (DrvIntersectRect(&arclTmp[culRclTmp], prcl, prclTmp)) { ! 879: ! 880: // Add to list if anything's left to draw ! 881: culRclTmp++; ! 882: } ! 883: } ! 884: ! 885: // Draw the clipped rects ! 886: if (culRclTmp != 0) { ! 887: vTrgBlt(pdsurf, culRclTmp, arclTmp, R2_COPYPEN, iColor); ! 888: } ! 889: ! 890: break; ! 891: ! 892: case DC_COMPLEX: ! 893: ! 894: // Bottom of last rectangle to fill ! 895: iLastBottom = prcl[culRcl-1].bottom; ! 896: ! 897: // Initialize the clip rectangle enumeration to rightdown so we can ! 898: // take advantage of the rectangle list being rightdown ! 899: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, ! 900: ENUM_RECT_LIMIT); ! 901: ! 902: // Scan through all the clip rectangles, looking for intersects ! 903: // of fill areas with region rectangles ! 904: do { ! 905: ! 906: // Get a batch of region rectangles ! 907: bMore = CLIPOBJ_bEnum(pco, (ULONG)sizeof(txen), (PVOID)&txen); ! 908: ! 909: // Clip the rect list to each region rect ! 910: for (j = txen.c, pClipRcl = txen.arcl; j-- > 0; pClipRcl++) { ! 911: ! 912: // Since the rectangles and the region enumeration are both ! 913: // rightdown, we can zip through the region until we reach ! 914: // the first fill rect, and are done when we've passed the ! 915: // last fill rect. ! 916: ! 917: if (pClipRcl->top >= iLastBottom) { ! 918: // Past last fill rectangle; nothing left to do ! 919: return; ! 920: } ! 921: ! 922: // Do intersection tests only if we've reached the top of ! 923: // the first rectangle to fill ! 924: if (pClipRcl->bottom > prcl->top) { ! 925: ! 926: // We've reached the top Y scan of the first rect, so ! 927: // it's worth bothering checking for intersection ! 928: ! 929: // Generate a list of the rects clipped to this region ! 930: // rect ! 931: prclTmp = prcl; ! 932: prclClipTmp = arclTmp; ! 933: for (i = culRcl, culRclTmp=0; i-- > 0; prclTmp++) { ! 934: ! 935: // Intersect fill and clip rectangles ! 936: if (DrvIntersectRect(prclClipTmp, prclTmp, ! 937: pClipRcl)) { ! 938: ! 939: // Add to list if anything's left to draw ! 940: culRclTmp++; ! 941: prclClipTmp++; ! 942: } ! 943: } ! 944: ! 945: // Draw the clipped rects ! 946: if (culRclTmp != 0) { ! 947: vTrgBlt(pdsurf, culRclTmp, arclTmp, R2_COPYPEN, ! 948: iColor); ! 949: } ! 950: } ! 951: } ! 952: } while (bMore); ! 953: ! 954: break; ! 955: } ! 956: ! 957: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.