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

unix.superglobalmegacorp.com

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