Annotation of ntddk/src/perf/vgacode/textout.c, revision 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.