Annotation of ntddk/src/video/displays/vga/textout.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.