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