Annotation of ntddk/src/video/displays/vga256/textout.c, revision 1.1

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

unix.superglobalmegacorp.com

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