Annotation of ntddk/src/perf/vgacode/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: #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: }

unix.superglobalmegacorp.com

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