File:  [WindowsNT SDKs] / ntddk / src / video / displays / framebuf / mips / text.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:31:12 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntddk-nov-1993, HEAD
Microsoft Windows NT Build 511 (DDK SDK) 11-01-1993

/******************************Module*Header*******************************\
* Module Name: text.c
*
* Optimized TextOut for the MIPS.  Reduces the total number of memory writes
* required to output a glyph which significantly improves performance when
* using slower video memory.
*
* Copyright (c) 1992 Microsoft Corporation
\**************************************************************************/

#include "driver.h"

//
// Define string object accelerator masks.
//

#define SO_MASK \
    (SO_FLAG_DEFAULT_PLACEMENT | SO_ZERO_BEARINGS | \
     SO_CHAR_INC_EQUAL_BM_BASE | SO_MAXEXT_EQUAL_BM_SIDE)

#define SO_LTOR (SO_MASK | SO_HORIZONTAL)
#define SO_RTOL (SO_LTOR | SO_REVERSED)
#define SO_TTOB (SO_MASK | SO_VERTICAL)
#define SO_BTOT (SO_TTOB | SO_REVERSED)

//
// Define enumeration structure.
//

#define BB_RECT_LIMIT 20

typedef struct _ENUMRECTLIST {
    ULONG c;
    RECTL arcl[BB_RECT_LIMIT];
} ENUMRECTLIST;

//
// Define function prototype for glyph output routines.
//

typedef
VOID
(*PDRVP_GLYPHOUT_ROUTINE) (
    IN PBYTE DrawPoint,
    IN PULONG GlyphBits,
    IN ULONG GlyphWidth,
    IN ULONG GlyphHeight
    );

VOID
DrvpOutputGlyphTransparent (
    IN PBYTE DrawPoint,
    IN PBYTE GlyphBitmap,
    IN ULONG GlyphWidth,
    IN ULONG GlyphHeight
    );

//
// Define big endian color mask table conversion table.
//

const ULONG DrvpColorMask[16] = {
    0x00000000,                         // 0000 -> 0000
    0xff000000,                         // 0001 -> 1000
    0x00ff0000,                         // 0010 -> 0100
    0xffff0000,                         // 0011 -> 1100
    0x0000ff00,                         // 0100 -> 0010
    0xff00ff00,                         // 0101 -> 1010
    0x00ffff00,                         // 0110 -> 0110
    0xffffff00,                         // 0111 -> 1110
    0x000000ff,                         // 1000 -> 0001
    0xff0000ff,                         // 1001 -> 1001
    0x00ff00ff,                         // 1010 -> 0101
    0xffff00ff,                         // 1011 -> 1101
    0x0000ffff,                         // 1100 -> 0011
    0xff00ffff,                         // 1101 -> 1011
    0x00ffffff,                         // 1110 -> 0111
    0xffffffff};                        // 1111 -> 1111

//
// Define draw color table that is generated for text output.
//

ULONG DrvpDrawColorTable[16];

//
// Define foreground color for transparent output.
//

ULONG DrvpForeGroundColor;

//
// Define scanline width value.
//

ULONG DrvpScanLineWidth;

//
// Define global opaque glyph output routine address table.
//

extern PDRVP_GLYPHOUT_ROUTINE DrvpOpaqueTable[8];

/******************************Public*Routine******************************\
* DrvpIntersectRect
*
* This routine checks to see if the two specified retangles intersect.
*
* A value of TRUE is returned if the rectangles intersect. Otherwise,
* a value of FALSE is returned.
*
\**************************************************************************/

BOOL DrvpIntersectRect (
    IN PRECTL Rectl1,
    IN PRECTL Rectl2,
    OUT PRECTL DestRectl)

{

    //
    // Compute the maximum left edge and the minimum right edge.
    //

    DestRectl->left  = max(Rectl1->left, Rectl2->left);
    DestRectl->right = min(Rectl1->right, Rectl2->right);

    //
    // If the minimum right edge is greater than the maximum left edge,
    // then the rectanges may intersect. Otherwise, they do not intersect.
    //

    if (DestRectl->left < DestRectl->right) {

        //
        // Compute the maximum top edge and the minimum bottom edge.
        //

        DestRectl->top = max(Rectl1->top, Rectl2->top);
        DestRectl->bottom = min(Rectl1->bottom, Rectl2->bottom);

        //
        // If the minimum bottom edge is greater than the maximum top
        // edge, then the rectanges intersect. Otherwise, they do not
        // intersect.
        //

        if (DestRectl->top < DestRectl->bottom) {
            return TRUE;
        }
    }

    return FALSE;
}

/******************************Public*Routine******************************\
* DrvpSolidColorFill
*
* Routine Description:
*
*     This routine fills a rectangle with a solid color.
*
* Arguments:
*
*     Rectangle - Supplies a pointer to a rectangle.
*
*     FillColor - Supplies the fill color.
*
*
* Return Value:
*
*     None.
*
\**************************************************************************/

VOID DrvpSolidColorFill (
    IN SURFOBJ *pso,
    IN PRECTL Rectangle,
    IN ULONG FillColor)

{

    PUCHAR Destination;
    ULONG Index;
    ULONG Length;
    LONG  lDelta = pso->lDelta;

    //
    // Compute rectangle fill parameters and fill rectangle with solid color.
    //

    Destination = ((PBYTE) pso->pvScan0) + (Rectangle->top * lDelta) + Rectangle->left;
    Length = Rectangle->right - Rectangle->left;
    for (Index = 0; Index < (Rectangle->bottom - Rectangle->top); Index += 1) {
        RtlFillMemory((PVOID)Destination, Length, FillColor);
        Destination += lDelta;
    }

    return;
}

/******************************Public*Routine******************************\
* DrvpEqualRectangle
*
* This routine compares two rectangles for equality.
*
\**************************************************************************/

BOOL DrvpEqualRectangle (
    IN RECTL *prcl1,
    IN RECTL *prcl2)

{

    if ((prcl1->left == prcl2->left) && (prcl1->right == prcl2->right) &&
        (prcl1->bottom == prcl2->bottom) && (prcl1->top == prcl2->top)) {
        return TRUE;

    } else {
        return FALSE;
    }
}

/******************************Public*Routine******************************\
* DrvpFillRectangle
*
* This routine fills a rectangle with clipping.
*
\**************************************************************************/

VOID DrvpFillRectangle (
    IN SURFOBJ *pso,
    IN CLIPOBJ *pco,
    IN RECTL *prcl,
    IN BRUSHOBJ *pbo)

{

    ENUMRECTLIST ClipEnum;
    RECTL Region;
    ULONG Index;
    BOOL More;
    ULONG iDComplexity;

    if (pco) {
        iDComplexity = pco->iDComplexity;

    } else {
        iDComplexity = DC_TRIVIAL;
    }


    //
    // Clip and fill the rectangle with the specified color.
    //

    switch(iDComplexity) {
    case DC_TRIVIAL:
        DrvpSolidColorFill(pso, prcl, pbo->iSolidColor);
        return;

    case DC_RECT:
        More = FALSE;
        ClipEnum.c = 1;
        ClipEnum.arcl[0] = pco->rclBounds;
        break;

    case DC_COMPLEX:
        More = TRUE;
        CLIPOBJ_cEnumStart(pco,
                           FALSE,
                           CT_RECTANGLES,
                           CD_LEFTWARDS,
                           BB_RECT_LIMIT);

        break;
    }

    //
    // Do a solid color fill for each nonclipped region.
    //

    do {

        //
        // If more clip regions is TRUE, then get the next batch of
        // clipping regions.
        //

        if (More != FALSE) {
            More = CLIPOBJ_bEnum(pco, sizeof(ClipEnum), (PVOID)&ClipEnum);
        }

        //
        // If the clipping is not trival, then do the clipping for the
        // next region and do the solid fill. Otherwise, do the solid
        // fill with no clipping.
        //

        for (Index = 0; Index < ClipEnum.c; Index += 1) {
            if (DrvpIntersectRect(&ClipEnum.arcl[Index],
                                  prcl,
                                  &Region)) {
            DrvpSolidColorFill(pso, &Region, pbo->iSolidColor);
            }
        }

    } while (More);
    return;
}

/******************************Public*Routine******************************\
* DrvTextOut
*
* This routine outputs text to the screen.
*
* History:
*  07-Jul-1992 -by- David N. Cutler [davec]
* Wrote it.
\**************************************************************************/

BOOL DrvTextOut (
    IN SURFOBJ *pso,
    IN STROBJ *pstro,
    IN FONTOBJ *pfo,
    IN CLIPOBJ *pco,
    IN RECTL *prclExtra,
    IN RECTL *prclOpaque,
    IN BRUSHOBJ *pboFore,
    IN BRUSHOBJ *pboOpaque,
    IN POINTL *pptlOrg,
    IN MIX mix)

{

    ULONG BackGroundColor;
    PBYTE DrawPoint;
    FONTINFO FontInformation;
    ULONG ForeGroundColor;
    ULONG GlyphCount;
    PGLYPHPOS GlyphEnd;
    ULONG GlyphHeight;
    PGLYPHPOS GlyphList;
    PDRVP_GLYPHOUT_ROUTINE GlyphOutputRoutine;
    PGLYPHPOS GlyphStart;
    ULONG GlyphWidth;
    LONG GlyphStride;
    ULONG Index;
    BOOL More;
    RECTL OpaqueRectl;
    LONG OriginX;
    LONG OriginY;
    PBYTE pjScreenBase;
    GLYPHBITS *pgb;

    //
    // DrvTextOut will only get called with solid color brushes and
    // the mix mode being the simplest R2_COPYPEN. The driver must
    // set a capabilities bit to get called with more complicated
    // mix brushes.
    //

//    ASSERT(pboFore->iSolidColor != 0xffffffff);
//    ASSERT(pboOpaque->iSolidColor != 0xffffffff);
//    ASSERT(mix == ((R2_COPYPEN << 8) | R2_COPYPEN));

    //
    // If the complexity of the clipping is not trival, then let GDI
    // process the request.
    //

    if (pco->iDComplexity != DC_TRIVIAL) {
        return(EngTextOut(pso,
                          pstro,
                          pfo,
                          pco,
                          prclExtra,
                          prclOpaque,
                          pboFore,
                          pboOpaque,
                          pptlOrg,
                          mix));
    }

    //
    // The foreground color is used for the text and extra rectangle
    // if it specified. The background color is used for the opaque
    // rectangle. If the foreground color is not a solid color brush
    // or the opaque rectangle is specified and is not a solid color
    // brush, then let GDI process the request.
    //

    DrvpScanLineWidth = pso->lDelta;
    pjScreenBase = pso->pvScan0;

    //
    // Check if the background and foreground can be draw at the same time.
    //

    ForeGroundColor = pboFore->iSolidColor;
    ForeGroundColor |= (ForeGroundColor << 8);
    ForeGroundColor |= (ForeGroundColor << 16);
    if (((pstro->flAccel == SO_LTOR) || (pstro->flAccel == SO_RTOL) ||
        (pstro->flAccel == SO_TTOB) || (pstro->flAccel == SO_BTOT)) &&
        (prclOpaque != NULL) && (pfo->cxMax <= 32)) {

        //
        // The background and the foreground can be draw at the same
        // time. Generate the drawing color table and draw the text
        // opaquely.
        //

        BackGroundColor = pboOpaque->iSolidColor;
        BackGroundColor |= (BackGroundColor << 8);
        BackGroundColor |= (BackGroundColor << 16);
        for (Index = 0; Index < 16; Index += 1) {
            DrvpDrawColorTable[Index] =
                (ForeGroundColor & DrvpColorMask[Index]) |
                    (BackGroundColor & (~DrvpColorMask[Index]));
        }

        //
        // If the top of the opaque rectangle is less than the top of the
        // background rectangle, then fill the region between the top of
        // opaque rectangle and the top of the background rectangle and
        // reduce the size of the opaque rectangle.
        //

        OpaqueRectl = *prclOpaque;
        if (OpaqueRectl.top < pstro->rclBkGround.top) {
            OpaqueRectl.bottom = pstro->rclBkGround.top;
            DrvpFillRectangle(pso,pco, &OpaqueRectl, pboOpaque);
            OpaqueRectl.top = pstro->rclBkGround.top;
            OpaqueRectl.bottom = prclOpaque->bottom;
        }

        //
        // If the bottom of the opaque rectangle is greater than the bottom
        // of the background rectangle, then fill the region between the
        // bottom of the background rectangle and the bottom of the opaque
        // rectangle and reduce the size of the opaque rectangle.
        //

        if (OpaqueRectl.bottom > pstro->rclBkGround.bottom) {
            OpaqueRectl.top = pstro->rclBkGround.bottom;
            DrvpFillRectangle(pso, pco, &OpaqueRectl, pboOpaque);
            OpaqueRectl.top = pstro->rclBkGround.top;
            OpaqueRectl.bottom = pstro->rclBkGround.bottom;
        }

        //
        // If the left of the opaque rectangle is less than the left of
        // the background rectangle, then fill the region between the
        // left of the opaque rectangle and the left of the background
        // rectangle.
        //

        if (OpaqueRectl.left < pstro->rclBkGround.left) {
            OpaqueRectl.right = pstro->rclBkGround.left;
            DrvpFillRectangle(pso, pco, &OpaqueRectl, pboOpaque);
            OpaqueRectl.right = prclOpaque->right;
        }

        //
        // If the right of the opaque rectangle is greater than the right
        // of the background rectangle, then fill the region between the
        // right of the opaque rectangle and the right of the background
        // rectangle.
        //

        if (OpaqueRectl.right > pstro->rclBkGround.right) {
            OpaqueRectl.left = pstro->rclBkGround.right;
            DrvpFillRectangle(pso, pco, &OpaqueRectl, pboOpaque);
        }

        //
        // If the font is fixed pitch, then optimize the computation of
        // x and y coordinate values. Otherwise, compute the x and y values
        // for each glyph.
        //

        if (pstro->ulCharInc != 0) {

            //
            // The font is fixed pitch. Capture the glyph dimensions and
            // compute the starting display address.
            //

            if (pstro->pgp == NULL) {
                More = STROBJ_bEnum(pstro, &GlyphCount, &GlyphList);

            } else {
                GlyphCount = pstro->cGlyphs;
                GlyphList = pstro->pgp;
                More = FALSE;
            }

            pgb = GlyphList->pgdf->pgb;
            GlyphWidth = pgb->sizlBitmap.cx;
            GlyphHeight = pgb->sizlBitmap.cy;
            OriginX = GlyphList->ptl.x + pgb->ptlOrigin.x;
            OriginY = GlyphList->ptl.y + pgb->ptlOrigin.y;
            DrawPoint = pjScreenBase + ((OriginY * DrvpScanLineWidth) + OriginX);

            //
            // Compute the glyph stride.
            //

            GlyphStride = pstro->ulCharInc;
            if ((pstro->flAccel & SO_VERTICAL) != 0) {
                GlyphStride *= DrvpScanLineWidth;
            }

            //
            // If the direction of drawing is reversed, then the stride is
            // negative.
            //

            if ((pstro->flAccel & SO_REVERSED) != 0) {
                GlyphStride = - GlyphStride;
            }

            //
            // Output the initial set of glyphs.
            //

            GlyphOutputRoutine = DrvpOpaqueTable[(GlyphWidth - 1) >> 2];
            GlyphEnd = &GlyphList[GlyphCount];
            GlyphStart = GlyphList;
            do {
                pgb = GlyphStart->pgdf->pgb;
                (GlyphOutputRoutine)(DrawPoint,
                                     (PULONG)&pgb->aj[0],
                                     GlyphWidth,
                                     GlyphHeight);

                DrawPoint += GlyphStride;
                GlyphStart += 1;
            } while (GlyphStart != GlyphEnd);

            //
            // Output the subsequent set of glyphs.
            //

            while (More) {
                More = STROBJ_bEnum(pstro, &GlyphCount, &GlyphList);
                GlyphEnd = &GlyphList[GlyphCount];
                GlyphStart = GlyphList;
                do {
                    pgb = GlyphStart->pgdf->pgb;
                    (GlyphOutputRoutine)(DrawPoint,
                                         (PULONG)&pgb->aj[0],
                                         GlyphWidth,
                                         GlyphHeight);

                    DrawPoint += GlyphStride;
                    GlyphStart += 1;
                } while (GlyphStart != GlyphEnd);
            }

        } else {

            //
            // The font is not fixed pitch. Compute the x and y values for
            // each glyph individually.
            //

            do {
                More = STROBJ_bEnum(pstro, &GlyphCount, &GlyphList);
                GlyphEnd = &GlyphList[GlyphCount];
                GlyphStart = GlyphList;
                do {
                    pgb = GlyphStart->pgdf->pgb;
                    OriginX = GlyphStart->ptl.x + pgb->ptlOrigin.x;
                    OriginY = GlyphStart->ptl.y + pgb->ptlOrigin.y;
                    DrawPoint = pjScreenBase +
                                    ((OriginY * DrvpScanLineWidth) + OriginX);

                    GlyphWidth = pgb->sizlBitmap.cx;
                    GlyphOutputRoutine = DrvpOpaqueTable[(GlyphWidth - 1) >> 2];
                    (GlyphOutputRoutine)(DrawPoint,
                                         (PULONG)&pgb->aj[0],
                                         GlyphWidth,
                                         pgb->sizlBitmap.cy);

                    GlyphStart += 1;
                } while(GlyphStart != GlyphEnd);
            } while(More);
        }

    } else {

        //
        // The background and the foreground cannot be draw at the same
        // time. Set the foreground color and fill the background rectangle,
        // if specified, and then draw the text transparently.
        //

        DrvpForeGroundColor = ForeGroundColor;
        if (prclOpaque != NULL) {
            DrvpFillRectangle(pso, pco, prclOpaque, pboOpaque);
        }

        //
        // If the font is fixed pitch, then optimize the computation of
        // x and y coordinate values. Otherwise, compute the x and y values
        // for each glyph.
        //

        if (pstro->ulCharInc != 0) {

            //
            // The font is fixed pitch. Capture the glyph dimensions and
            // compute the starting display address.
            //

            if (pstro->pgp == NULL) {
                More = STROBJ_bEnum(pstro, &GlyphCount, &GlyphList);

            } else {
                GlyphCount = pstro->cGlyphs;
                GlyphList = pstro->pgp;
                More = FALSE;
            }

            pgb = GlyphList->pgdf->pgb;
            GlyphWidth = pgb->sizlBitmap.cx;
            GlyphHeight = pgb->sizlBitmap.cy;
            OriginX = GlyphList->ptl.x + pgb->ptlOrigin.x;
            OriginY = GlyphList->ptl.y + pgb->ptlOrigin.y;
            DrawPoint = pjScreenBase + ((OriginY * DrvpScanLineWidth) + OriginX);

            //
            // Compute the glyph stride.
            //

            GlyphStride = pstro->ulCharInc;
            if ((pstro->flAccel & SO_VERTICAL) != 0) {
                GlyphStride *= DrvpScanLineWidth;
            }

            //
            // If the direction of drawing is reversed, then the stride is
            // negative.
            //

            if ((pstro->flAccel & SO_REVERSED) != 0) {
                GlyphStride = -GlyphStride;
            }

            //
            // Output the initial set of glyphs.
            //

            GlyphEnd = &GlyphList[GlyphCount];
            GlyphStart = GlyphList;
            do {
                pgb = GlyphStart->pgdf->pgb;
                DrvpOutputGlyphTransparent(DrawPoint,
                                           &pgb->aj[0],
                                           GlyphWidth,
                                           GlyphHeight);

                DrawPoint += GlyphStride;
                GlyphStart += 1;
            } while (GlyphStart != GlyphEnd);

            //
            // Output the subsequent set of glyphs.
            //

            while (More) {
                More = STROBJ_bEnum(pstro, &GlyphCount, &GlyphList);
                GlyphEnd = &GlyphList[GlyphCount];
                GlyphStart = GlyphList;
                do {
                    pgb = GlyphStart->pgdf->pgb;
                    DrvpOutputGlyphTransparent(DrawPoint,
                                               &pgb->aj[0],
                                               GlyphWidth,
                                               GlyphHeight);

                    DrawPoint += GlyphStride;
                    GlyphStart += 1;
                } while (GlyphStart != GlyphEnd);
            }

        } else {

            //
            // The font is not fixed pitch. Compute the x and y values for
            // each glyph individually.
            //

            do {
                More = STROBJ_bEnum(pstro, &GlyphCount, &GlyphList);
                GlyphEnd = &GlyphList[GlyphCount];
                GlyphStart = GlyphList;
                do {
                    pgb = GlyphStart->pgdf->pgb;
                    OriginX = GlyphStart->ptl.x + pgb->ptlOrigin.x;
                    OriginY = GlyphStart->ptl.y + pgb->ptlOrigin.y;
                    DrawPoint = pjScreenBase +
                                    ((OriginY * DrvpScanLineWidth) + OriginX);

                    DrvpOutputGlyphTransparent(DrawPoint,
                                               &pgb->aj[0],
                                               pgb->sizlBitmap.cx,
                                               pgb->sizlBitmap.cy);

                    GlyphStart += 1;
                } while(GlyphStart != GlyphEnd);
            } while(More);
        }
    }

    //
    // Fill the extra rectangles if specified.
    //

    if (prclExtra != (PRECTL)NULL) {
        while (prclExtra->left != prclExtra->right) {
            DrvpFillRectangle(pso, pco, prclExtra, pboFore);
            prclExtra += 1;
        }
    }

    return(TRUE);
}

unix.superglobalmegacorp.com

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