|
|
1.1 ! root 1: /******************************Module*Header*******************************\ ! 2: * Module Name: TextOut.c ! 3: * ! 4: * Text ! 5: * ! 6: * Copyright (c) 1992 Microsoft Corporation ! 7: * ! 8: \**************************************************************************/ ! 9: ! 10: #include "driver.h" ! 11: ! 12: BOOL vFastText(PDEV *, GLYPHPOS *, ULONG, PBYTE, ULONG, ULONG, RECTL *, ! 13: RECTL *, INT, INT, ULONG); ! 14: VOID lclFillRect(CLIPOBJ *, ULONG, PRECTL, PPDEV, INT); ! 15: ! 16: /**************************************************************************** ! 17: * DrvTextOut ! 18: ***************************************************************************/ ! 19: ! 20: BOOL DrvTextOut( ! 21: SURFOBJ* pso, ! 22: STROBJ* pstro, ! 23: FONTOBJ* pfo, ! 24: CLIPOBJ* pco, ! 25: RECTL* prclExtra, ! 26: RECTL* prclOpaque, ! 27: BRUSHOBJ* pboFore, ! 28: BRUSHOBJ* pboOpaque, ! 29: POINTL* pptlOrg, ! 30: MIX mix) ! 31: { ! 32: BOOL b; ! 33: PPDEV ppdev; ! 34: INT iClip; // clip object's complexity ! 35: ULONG iSolidForeColor; // Solid foreground color ! 36: ULONG iSolidBkColor; // Solid background color ! 37: RECTL arclTmp[4]; // Temp storage for portions of opaquing rect ! 38: ULONG culRcl; // Temp rectangle count ! 39: ! 40: ppdev = (PPDEV) pso->dhpdev; ! 41: ! 42: ! 43: //--------------------------------------------------------------------- ! 44: // Get information about clip object. ! 45: //--------------------------------------------------------------------- ! 46: ! 47: iClip = DC_TRIVIAL; ! 48: ! 49: if (pco != NULL) { ! 50: iClip = pco->iDComplexity; ! 51: } ! 52: ! 53: //--------------------------------------------------------------------- ! 54: // Get text color. ! 55: //--------------------------------------------------------------------- ! 56: ! 57: iSolidForeColor = pboFore->iSolidColor; ! 58: ! 59: //--------------------------------------------------------------------- ! 60: // See if this is text we can handle faster with special-case code. ! 61: //--------------------------------------------------------------------- ! 62: ! 63: if (((ppdev->fl & DRIVER_PLANAR_CAPABLE) || ! 64: (prclOpaque == (PRECTL) NULL)) && // opaque only if planar for now ! 65: // LATER implement fast non-planar ! 66: // opaque ! 67: (iClip == DC_TRIVIAL) && // no clipping for now ! 68: ((pstro->rclBkGround.right & ~0x03) > ! 69: ((pstro->rclBkGround.left + 3) & ~0x03)) && ! 70: // not if no full nibbles spanned ! 71: // for now @@@ ! 72: (pstro->pgp != NULL) && // no glyph enumeration for now ! 73: (prclExtra == NULL) && // no extra rects for now ! 74: ((pstro->flAccel & (SO_HORIZONTAL | SO_VERTICAL | SO_REVERSED)) == ! 75: SO_HORIZONTAL)) { // only left-to-right text for now ! 76: ! 77: ULONG ulBufferWidthInBytes; ! 78: ULONG ulBufferBytes; ! 79: BOOL bTextPerfectFit; ! 80: ULONG fDrawFlags; ! 81: ! 82: // It's the type of text we can special-case; see if the temp buffer is ! 83: // big enough for the text. ! 84: ! 85: ulBufferWidthInBytes = ((((pstro->rclBkGround.right + 7) & ~0x07) - ! 86: (pstro->rclBkGround.left & ~0x07)) >> 3); ! 87: ulBufferBytes = ulBufferWidthInBytes * ! 88: (pstro->rclBkGround.bottom - pstro->rclBkGround.top); ! 89: ! 90: if (ulBufferBytes <= TMP_BUFFER_SIZE) { ! 91: ! 92: // It's big enough; set up for the accelerator ! 93: ! 94: // Set fixed pitch, overlap, and top & bottom Y alignment flags ! 95: fDrawFlags = ((pstro->ulCharInc != 0) ? 0x01 : 0) | ! 96: (((pstro->flAccel & (SO_ZERO_BEARINGS | ! 97: SO_FLAG_DEFAULT_PLACEMENT)) != ! 98: (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT)) ! 99: ? 0x02 : 0) | ! 100: (((pstro->flAccel & (SO_ZERO_BEARINGS | ! 101: SO_FLAG_DEFAULT_PLACEMENT | ! 102: SO_MAXEXT_EQUAL_BM_SIDE)) == ! 103: (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT | ! 104: SO_MAXEXT_EQUAL_BM_SIDE)) ? 0x04 : 0); ! 105: ! 106: // If there's an opaque rectangle, we'll do as much opaquing as ! 107: // possible as we do the text. If the opaque rectangle is larger ! 108: // than the text rectangle, then we'll do the fringe areas right ! 109: // now, and the text and associated background areas together, ! 110: // later. ! 111: if (prclOpaque != (PRECTL) NULL) { ! 112: ! 113: // This driver only handles solid brushes ! 114: iSolidBkColor = pboOpaque->iSolidColor; ! 115: ! 116: // See if we have fringe areas to do. If so, build a list of ! 117: // rectangles to fill, in rightdown order ! 118: ! 119: culRcl = 0; ! 120: ! 121: // Top fragment ! 122: if (pstro->rclBkGround.top > prclOpaque->top) { ! 123: arclTmp[culRcl].top = prclOpaque->top; ! 124: arclTmp[culRcl].left = prclOpaque->left; ! 125: arclTmp[culRcl].right = prclOpaque->right; ! 126: arclTmp[culRcl++].bottom = pstro->rclBkGround.top; ! 127: } ! 128: ! 129: // Left fragment ! 130: if (pstro->rclBkGround.left > prclOpaque->left) { ! 131: arclTmp[culRcl].top = pstro->rclBkGround.top; ! 132: arclTmp[culRcl].left = prclOpaque->left; ! 133: arclTmp[culRcl].right = pstro->rclBkGround.left; ! 134: arclTmp[culRcl++].bottom = pstro->rclBkGround.bottom; ! 135: } ! 136: ! 137: // Right fragment ! 138: if (pstro->rclBkGround.right < prclOpaque->right) { ! 139: arclTmp[culRcl].top = pstro->rclBkGround.top; ! 140: arclTmp[culRcl].right = prclOpaque->right; ! 141: arclTmp[culRcl].left = pstro->rclBkGround.right; ! 142: arclTmp[culRcl++].bottom = pstro->rclBkGround.bottom; ! 143: } ! 144: ! 145: // Bottom fragment ! 146: if (pstro->rclBkGround.bottom < prclOpaque->bottom) { ! 147: arclTmp[culRcl].bottom = prclOpaque->bottom; ! 148: arclTmp[culRcl].left = prclOpaque->left; ! 149: arclTmp[culRcl].right = prclOpaque->right; ! 150: arclTmp[culRcl++].top = pstro->rclBkGround.bottom; ! 151: } ! 152: ! 153: if (culRcl != 0) { ! 154: if (iClip == DC_TRIVIAL) { ! 155: vTrgBlt(ppdev, culRcl, arclTmp, R2_COPYPEN, ! 156: *((RBRUSH_COLOR*) &iSolidBkColor), NULL); ! 157: } else { ! 158: lclFillRect(pco, culRcl, arclTmp, ppdev, ! 159: iSolidBkColor); ! 160: } ! 161: } ! 162: } ! 163: ! 164: // We're done with separate opaquing; any further opaquing will ! 165: // happen as part of the text drawing ! 166: ! 167: // Clear the buffer if the text isn't going to set every bit ! 168: // BUGBUG do I have to pay attention to ulCharInc? ! 169: bTextPerfectFit = (pstro->flAccel & (SO_ZERO_BEARINGS | ! 170: SO_FLAG_DEFAULT_PLACEMENT | SO_MAXEXT_EQUAL_BM_SIDE | ! 171: SO_CHAR_INC_EQUAL_BM_BASE)) == ! 172: (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT | ! 173: SO_MAXEXT_EQUAL_BM_SIDE | SO_CHAR_INC_EQUAL_BM_BASE); ! 174: ! 175: if (!bTextPerfectFit) { ! 176: vClearMemDword(ppdev->pvTmp, (ulBufferBytes + 3) >> 2); ! 177: } ! 178: ! 179: // Draw the text into the temp buffer, and thence to the screen ! 180: vFastText(ppdev, ! 181: pstro->pgp, ! 182: pstro->cGlyphs, ! 183: ppdev->pvTmp, ! 184: ulBufferWidthInBytes, ! 185: pstro->ulCharInc, ! 186: &pstro->rclBkGround, ! 187: prclOpaque, ! 188: iSolidForeColor, ! 189: iSolidBkColor, ! 190: fDrawFlags); ! 191: ! 192: return(TRUE); ! 193: ! 194: } ! 195: } ! 196: ! 197: // Can't special-case; let the engine draw the text ! 198: ! 199: pso = ppdev->pSurfObj; ! 200: ! 201: // It may be that the opaquing rectangle is larger than the text rectangle, ! 202: // so we'll want to use that to tell the bank manager which banks to ! 203: // enumerate: ! 204: ! 205: pco = pcoBankStart(ppdev, ! 206: (prclOpaque != NULL) ? prclOpaque : &pstro->rclBkGround, ! 207: pso, ! 208: pco); ! 209: ! 210: do { ! 211: b = EngTextOut(pso, ! 212: pstro, ! 213: pfo, ! 214: pco, ! 215: prclExtra, ! 216: prclOpaque, ! 217: pboFore, ! 218: pboOpaque, ! 219: pptlOrg, ! 220: mix); ! 221: ! 222: } while (b && bBankEnum(ppdev, pso, pco)); ! 223: ! 224: return(b); ! 225: } ! 226: ! 227: //-------------------------------------------------------------------------- ! 228: // Fills the specified rectangles on the specified surface with the ! 229: // specified color, honoring the requested clipping. No more than four ! 230: // rectangles should be passed in. Intended for drawing the areas of the ! 231: // opaquing rectangle that extended beyond the text box. The rectangles must ! 232: // be in left to right, top to bottom order. Assumes there is at least one ! 233: // rectangle in the list. ! 234: //-------------------------------------------------------------------------- ! 235: ! 236: VOID lclFillRect( ! 237: CLIPOBJ *pco, ! 238: ULONG culRcl, ! 239: PRECTL prcl, ! 240: PPDEV ppdev, ! 241: INT iColor) ! 242: { ! 243: BOOL bMore; // Flag for clip enumeration ! 244: TEXTENUM txen; // Clip enumeration object ! 245: ULONG i, j; ! 246: RECTL arclTmp[4]; ! 247: ULONG culRclTmp; ! 248: RECTL *prclTmp, *prclClipTmp; ! 249: INT iLastBottom; ! 250: RECTL *pClipRcl; ! 251: INT iClip; ! 252: ! 253: iClip = DC_TRIVIAL; ! 254: ! 255: if (pco != NULL) { ! 256: iClip = pco->iDComplexity; ! 257: } ! 258: ! 259: switch ( iClip ) { ! 260: ! 261: case DC_TRIVIAL: ! 262: ! 263: vTrgBlt(ppdev, culRcl, prcl, R2_COPYPEN, ! 264: *((RBRUSH_COLOR*) &iColor), NULL); ! 265: ! 266: break; ! 267: ! 268: case DC_RECT: ! 269: ! 270: prclTmp = &pco->rclBounds; ! 271: ! 272: // Generate a list of clipped rects ! 273: for (culRclTmp=0, i=0; i<culRcl; i++, prcl++) { ! 274: ! 275: // Intersect fill and clip rectangles ! 276: if (bIntersectRect(&arclTmp[culRclTmp], prcl, prclTmp)) { ! 277: ! 278: // Add to list if anything's left to draw ! 279: culRclTmp++; ! 280: } ! 281: } ! 282: ! 283: // Draw the clipped rects ! 284: if (culRclTmp != 0) { ! 285: vTrgBlt(ppdev, culRclTmp, arclTmp, R2_COPYPEN, ! 286: *((RBRUSH_COLOR*) &iColor), NULL); ! 287: } ! 288: ! 289: break; ! 290: ! 291: case DC_COMPLEX: ! 292: ! 293: // Bottom of last rectangle to fill ! 294: iLastBottom = prcl[culRcl-1].bottom; ! 295: ! 296: // Initialize the clip rectangle enumeration to rightdown so we can ! 297: // take advantage of the rectangle list being rightdown ! 298: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, ! 299: TO_RECT_LIMIT); ! 300: ! 301: // Scan through all the clip rectangles, looking for intersects ! 302: // of fill areas with region rectangles ! 303: do { ! 304: ! 305: // Get a batch of region rectangles ! 306: bMore = CLIPOBJ_bEnum(pco, (ULONG)sizeof(txen), (PVOID)&txen); ! 307: ! 308: // Clip the rect list to each region rect ! 309: for (j = txen.c, pClipRcl = txen.arcl; j-- > 0; pClipRcl++) { ! 310: ! 311: // Since the rectangles and the region enumeration are both ! 312: // rightdown, we can zip through the region until we reach ! 313: // the first fill rect, and are done when we've passed the ! 314: // last fill rect. ! 315: ! 316: if (pClipRcl->top >= iLastBottom) { ! 317: // Past last fill rectangle; nothing left to do ! 318: return; ! 319: } ! 320: ! 321: // Do intersection tests only if we've reached the top of ! 322: // the first rectangle to fill ! 323: if (pClipRcl->bottom > prcl->top) { ! 324: ! 325: // We've reached the top Y scan of the first rect, so ! 326: // it's worth bothering checking for intersection ! 327: ! 328: // Generate a list of the rects clipped to this region ! 329: // rect ! 330: prclTmp = prcl; ! 331: prclClipTmp = arclTmp; ! 332: for (i = culRcl, culRclTmp=0; i-- > 0; prclTmp++) { ! 333: ! 334: // Intersect fill and clip rectangles ! 335: if (bIntersectRect(prclClipTmp, prclTmp, ! 336: pClipRcl)) { ! 337: ! 338: // Add to list if anything's left to draw ! 339: culRclTmp++; ! 340: prclClipTmp++; ! 341: } ! 342: } ! 343: ! 344: // Draw the clipped rects ! 345: if (culRclTmp != 0) { ! 346: vTrgBlt(ppdev, culRclTmp, arclTmp, R2_COPYPEN, ! 347: *((RBRUSH_COLOR*) &iColor), NULL); ! 348: } ! 349: } ! 350: } ! 351: } while (bMore); ! 352: ! 353: break; ! 354: } ! 355: ! 356: } ! 357:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.