mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1027 lines
30 KiB
1027 lines
30 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: TextOut.c
|
|
*
|
|
* XGA Text accelerations
|
|
*
|
|
* Copyright (c) 1992 Microsoft Corporation
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "driver.h"
|
|
|
|
// Part of the fix to limit the amount of resources allocated for fonts
|
|
|
|
#define MAX_GLYPHS_TO_ALLOC 256
|
|
|
|
#define CJ_SCAN(cx) (((cx) + 7) >> 3)
|
|
|
|
BOOL bSetXgaTextColorAndMix(PPDEV ppdev, MIX mix, BRUSHOBJ *pboFore, BRUSHOBJ *pboOpaque);
|
|
BOOL bOpaqueRect(PPDEV pdev, CLIPOBJ *pco, RECTL *prclOpaque, BRUSHOBJ *pboOpaque);
|
|
|
|
PCACHEDGLYPH pCacheFont(PPDEV ppdev, STROBJ *pstro, FONTOBJ *pfo);
|
|
BOOL bBlowCache(SURFOBJ *pso);
|
|
|
|
BOOL bHandleCachedFonts(
|
|
SURFOBJ *pso,
|
|
STROBJ *pstro,
|
|
FONTOBJ *pfo,
|
|
CLIPOBJ *pco,
|
|
RECTL *prclExtra,
|
|
RECTL *prclOpaque,
|
|
BRUSHOBJ *pboFore,
|
|
BRUSHOBJ *pboOpaque,
|
|
POINTL *pptlOrg,
|
|
MIX mix
|
|
);
|
|
|
|
|
|
BOOL bHandleNonCachedFonts(
|
|
SURFOBJ *pso,
|
|
STROBJ *pstro,
|
|
FONTOBJ *pfo,
|
|
CLIPOBJ *pco,
|
|
RECTL *prclExtra,
|
|
RECTL *prclOpaque,
|
|
BRUSHOBJ *pboFore,
|
|
BRUSHOBJ *pboOpaque,
|
|
POINTL *pptlOrg,
|
|
MIX mix
|
|
);
|
|
|
|
BYTE Rop2ToXgaRop[] = {
|
|
XGA_0, /* 0 */
|
|
XGA_S_OR_NOT_D, /* DPon */
|
|
XGA_NOT_S_AND_D, /* DPna */
|
|
XGA_NOT_S, /* Pn */
|
|
XGA_NOT_S_AND_NOT_D,/* PDna */
|
|
XGA_NOT_D, /* Dn */
|
|
XGA_S_XOR_D, /* DPx */
|
|
XGA_S_AND_NOT_D, /* DPan */
|
|
XGA_S_AND_D, /* DPa */
|
|
XGA_S_XOR_NOT_D, /* DPxn */
|
|
XGA_D, /* D */
|
|
XGA_NOT_S_OR_D, /* DPno */
|
|
XGA_S, /* P */
|
|
XGA_NOT_S_OR_NOT_D, /* PDno */
|
|
XGA_S_OR_D, /* DPo */
|
|
XGA_1 /* 1 */
|
|
};
|
|
|
|
BYTE jNibbleBitSwap[] = {
|
|
0x00, // 0 - 0000
|
|
0x08, // 1 - 0001
|
|
0x04, // 2 - 0010
|
|
0x0C, // 3 - 0011
|
|
0x02, // 4 - 0100
|
|
0x0A, // 5 - 0101
|
|
0x06, // 6 - 0110
|
|
0x0E, // 7 - 0111
|
|
0x01, // 8 - 1000
|
|
0x09, // 9 - 1001
|
|
0x05, // A - 1010
|
|
0x0D, // B - 1011
|
|
0x03, // C - 1100
|
|
0x0B, // D - 1101
|
|
0x07, // E - 1110
|
|
0x0F // F - 1111
|
|
};
|
|
|
|
#define BITSWAP(b) ((jNibbleBitSwap[b & 0xF] << 4) | (jNibbleBitSwap[(b >> 4) & 0xF]))
|
|
|
|
|
|
/****************************************************************************
|
|
* DrvTextOut
|
|
***************************************************************************/
|
|
BOOL DrvTextOut(
|
|
SURFOBJ *pso,
|
|
STROBJ *pstro,
|
|
FONTOBJ *pfo,
|
|
CLIPOBJ *pco,
|
|
RECTL *prclExtra,
|
|
RECTL *prclOpaque,
|
|
BRUSHOBJ *pboFore,
|
|
BRUSHOBJ *pboOpaque,
|
|
POINTL *pptlOrg,
|
|
MIX mix)
|
|
{
|
|
BOOL b;
|
|
|
|
DISPDBG((2, "XGA.DLL!DrvTextOut - Entry\n"));
|
|
|
|
vWaitForCoProcessor((PPDEV)pso->dhpdev, 100);
|
|
|
|
b = FALSE;
|
|
|
|
// For now only handle fonts with the A & B spaceing components
|
|
// of 0. This limitation will be removed when I get some more time
|
|
// to work on this driver. !!!
|
|
|
|
if (!(pstro->flAccel & SO_ZERO_BEARINGS))
|
|
{
|
|
if ((pso) && (pso->iType == STYPE_DEVICE))
|
|
pso = ((PPDEV)(pso->dhpdev))->pSurfObj;
|
|
|
|
b = EngTextOut(pso, pstro, pfo, pco,
|
|
prclExtra, prclOpaque, pboFore,
|
|
pboOpaque, pptlOrg, mix);
|
|
return(b);
|
|
}
|
|
|
|
if (((PPDEV)pso->dhpdev)->ulfAccelerations_debug & CACHED_FONTS)
|
|
{
|
|
b = bHandleCachedFonts(pso, pstro, pfo, pco,
|
|
prclExtra, prclOpaque, pboFore,
|
|
pboOpaque, pptlOrg, mix);
|
|
|
|
if (b == FALSE)
|
|
{
|
|
b = bHandleNonCachedFonts(pso, pstro, pfo, pco,
|
|
prclExtra, prclOpaque, pboFore,
|
|
pboOpaque, pptlOrg, mix);
|
|
}
|
|
}
|
|
|
|
if (b == FALSE)
|
|
{
|
|
if ((pso) && (pso->iType == STYPE_DEVICE))
|
|
pso = ((PPDEV)(pso->dhpdev))->pSurfObj;
|
|
|
|
b = EngTextOut(pso, pstro, pfo, pco,
|
|
prclExtra, prclOpaque, pboFore,
|
|
pboOpaque, pptlOrg, mix);
|
|
}
|
|
|
|
return (b);
|
|
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
* bHandleCachedFonts
|
|
***************************************************************************/
|
|
BOOL bHandleCachedFonts(
|
|
SURFOBJ *pso,
|
|
STROBJ *pstro,
|
|
FONTOBJ *pfo,
|
|
CLIPOBJ *pco,
|
|
RECTL *prclExtra,
|
|
RECTL *prclOpaque,
|
|
BRUSHOBJ *pboFore,
|
|
BRUSHOBJ *pboOpaque,
|
|
POINTL *pptlOrg,
|
|
MIX mix)
|
|
{
|
|
BOOL b,
|
|
bMoreGlyphs,
|
|
bFound;
|
|
|
|
ULONG iGlyph,
|
|
cGlyphs;
|
|
|
|
POINTL ptl;
|
|
|
|
GLYPHPOS *pgp;
|
|
|
|
ULONG ulPhyXgaGlyphBuff;
|
|
|
|
UINT ihGlyph,
|
|
cxGlyph,
|
|
cyGlyph,
|
|
GlyphBmPitchInBytes,
|
|
GlyphBmPitchInPels;
|
|
|
|
ULONG XGAPixelOp,
|
|
ulXgaMask;
|
|
|
|
INT yGlyphBias;
|
|
|
|
PCACHEDGLYPH pCachedGlyphs,
|
|
pcg;
|
|
|
|
FONTINFO fi;
|
|
|
|
ULONG cFntGlyphs;
|
|
|
|
PXGACPREGS pXgaCpRegs = ((PPDEV)pso->dhpdev)->pXgaCpRegs;
|
|
|
|
|
|
DISPDBG((3, "XGA.DLL!bHandleCachedFonts\n"));
|
|
|
|
// Take care of any opaque rectangles.
|
|
|
|
if (prclOpaque != NULL)
|
|
{
|
|
b = bOpaqueRect((PPDEV)pso->dhpdev, pco, prclOpaque, pboOpaque);
|
|
if (b == FALSE)
|
|
{
|
|
return (b);
|
|
}
|
|
}
|
|
|
|
// Take care of the glyph attributes, color and mix.
|
|
|
|
b = bSetXgaTextColorAndMix((PPDEV)pso->dhpdev, mix, pboFore, pboOpaque);
|
|
if (b == FALSE)
|
|
return (b);
|
|
|
|
// Take care of setting the clip rectangle for the string.
|
|
|
|
b = bSetXgaClipping((PPDEV)pso->dhpdev, pco, &ulXgaMask);
|
|
if (b == FALSE)
|
|
return (b);
|
|
|
|
// Setup the Control Word for the XGA.
|
|
|
|
XGAPixelOp = BS_BACK_COLOR | FS_FORE_COLOR |
|
|
STEP_PX_BLT |
|
|
SRC_PEL_MAP_A | DST_PEL_MAP_A |
|
|
PATT_PEL_MAP_B | MSK_DISABLE |
|
|
DM_ALL_PELS | OCT_DY ;
|
|
|
|
XGAPixelOp |= ulXgaMask;
|
|
|
|
//
|
|
// Get the glyphs into the cache. If the cache is full, then blow
|
|
// away the cache and start caching over. If there is a problem
|
|
// with blowing away the cache go back and try the A/B buffer
|
|
// approach. If the cache was blown away with no error start caching
|
|
// all over again. If there is another problem with caching then go
|
|
// back and try the A/B buffer approach, and finally, if the A/B
|
|
// buffer scheme fails go back to the engine.
|
|
//
|
|
|
|
pCachedGlyphs = pCacheFont((PPDEV)pso->dhpdev, pstro, pfo);
|
|
if (pCachedGlyphs == NULL)
|
|
{
|
|
DISPDBG((1, "XGA.DLL!bHandleCachedFonts - pCacheFont failed once\n"));
|
|
b = bBlowCache(pso);
|
|
if (b == FALSE)
|
|
{
|
|
DISPDBG((1, "XGA.DLL!bHandleCachedFonts - bBlowCache failed\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
pCachedGlyphs = pCacheFont((PPDEV)pso->dhpdev, pstro, pfo);
|
|
if (pCachedGlyphs == NULL)
|
|
{
|
|
DISPDBG((1, "XGA.DLL!bHandleCachedFonts - pCacheFont failed twice\n"));
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
// Need to get the number of glyphs in the font.
|
|
// Get the font info.
|
|
|
|
FONTOBJ_vGetInfo(pfo, sizeof(FONTINFO), &fi);
|
|
cFntGlyphs = fi.cGlyphsSupported;
|
|
|
|
// This is where we clamp the size of the Font structures we are allocating.
|
|
|
|
if (cFntGlyphs > MAX_GLYPHS_TO_ALLOC)
|
|
cFntGlyphs = MAX_GLYPHS_TO_ALLOC;
|
|
|
|
|
|
// Get the Glyph Handles.
|
|
|
|
STROBJ_vEnumStart(pstro);
|
|
|
|
do
|
|
{
|
|
bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphs, &pgp);
|
|
|
|
// If this is a mono-spaced font we need to set the X
|
|
// for each glyph.
|
|
|
|
if (pstro->ulCharInc != 0)
|
|
{
|
|
UINT ii;
|
|
LONG x,y;
|
|
|
|
x = pgp[0].ptl.x;
|
|
y = pgp[0].ptl.y;
|
|
for (ii=1; ii < cGlyphs; ii++)
|
|
{
|
|
x += pstro->ulCharInc;
|
|
pgp[ii].ptl.x = x;
|
|
pgp[ii].ptl.y = y;
|
|
}
|
|
}
|
|
|
|
for (iGlyph = 0; iGlyph < cGlyphs; iGlyph++)
|
|
{
|
|
|
|
|
|
// Get the Glyph Handle.
|
|
// If there was a hash table hit for the glygph
|
|
// then were "golden", if not then we have to search
|
|
// the collision list.
|
|
|
|
ihGlyph = pgp[iGlyph].hg % cFntGlyphs;
|
|
|
|
pcg = &(pCachedGlyphs[ihGlyph]);
|
|
if (!(pcg->fl & VALID_GLYPH) || (pcg->hg != pgp[iGlyph].hg))
|
|
{
|
|
DISPDBG((2, "XGA.DLL!bHandleCachedFonts - searching collision list\n"));
|
|
|
|
bFound = FALSE;
|
|
pcg = &(pCachedGlyphs[ihGlyph]);
|
|
while (pcg->pcgCollisionLink != END_COLLISIONS)
|
|
{
|
|
pcg = pcg->pcgCollisionLink;
|
|
if (pcg->hg == pgp[iGlyph].hg)
|
|
{
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If we do not find the glyph in the cache, then something
|
|
// went wrong. We emit an error message, then fail, so the
|
|
// non-cached font code can render the glyph.
|
|
|
|
if (bFound == FALSE)
|
|
{
|
|
DISPDBG((1, "XGA.DLL!bHandleCachedFonts - Cached Font not found\n"));
|
|
return (FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ulPhyXgaGlyphBuff = pcg->ulCpPhysicalMemory;
|
|
cxGlyph = pcg->sizlBitmap.cx;
|
|
cyGlyph = pcg->sizlBitmap.cy;
|
|
GlyphBmPitchInPels = pcg->BmPitchInPels;
|
|
GlyphBmPitchInBytes = pcg->BmPitchInBytes;
|
|
|
|
// Adjust the placement of the glyph.
|
|
|
|
yGlyphBias = (cyGlyph + pcg->ptlOrigin.y) - 1;
|
|
|
|
ptl.x = pgp[iGlyph].ptl.x + pcg->ptlOrigin.x;
|
|
ptl.y = pgp[iGlyph].ptl.y + yGlyphBias;
|
|
|
|
// Note: We wait here so every thing that can be done
|
|
// to get ready for the next character is done
|
|
// before we have to wait for the CoProcessor.
|
|
|
|
vWaitForCoProcessor((PPDEV)pso->dhpdev, 10);
|
|
|
|
// Setup the pattern bitmap Pel interface registers.
|
|
|
|
pXgaCpRegs->XGAPixelMapIndex = PEL_MAP_B;
|
|
pXgaCpRegs->XGAPixMapBasePtr = ulPhyXgaGlyphBuff;
|
|
pXgaCpRegs->XGAPixMapWidth = GlyphBmPitchInPels - 1;
|
|
pXgaCpRegs->XGAPixMapHeight = cyGlyph - 1;
|
|
pXgaCpRegs->XGAPixMapFormat = PATT_MAP_FORMAT;
|
|
|
|
// Setup the Blit pattern and dest.
|
|
// Note: There is no source bitmap, Until we get the pattern
|
|
// brush.
|
|
|
|
pXgaCpRegs->XGAOpDim1 = cxGlyph - 1;
|
|
pXgaCpRegs->XGAOpDim2 = cyGlyph - 1;
|
|
|
|
pXgaCpRegs->XGAPatternMapX = 0;
|
|
pXgaCpRegs->XGAPatternMapY = cyGlyph - 1;
|
|
|
|
pXgaCpRegs->XGADestMapX = LOWORD(ptl.x);
|
|
pXgaCpRegs->XGADestMapY = LOWORD(ptl.y);
|
|
|
|
// Do the blit operation.
|
|
|
|
pXgaCpRegs->XGAPixelOp = XGAPixelOp;
|
|
|
|
|
|
}
|
|
|
|
} while(bMoreGlyphs);
|
|
|
|
return (TRUE);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
* bHandleNonCachedFonts
|
|
***************************************************************************/
|
|
BOOL bHandleNonCachedFonts(
|
|
SURFOBJ *pso,
|
|
STROBJ *pstro,
|
|
FONTOBJ *pfo,
|
|
CLIPOBJ *pco,
|
|
RECTL *prclExtra,
|
|
RECTL *prclOpaque,
|
|
BRUSHOBJ *pboFore,
|
|
BRUSHOBJ *pboOpaque,
|
|
POINTL *pptlOrg,
|
|
MIX mix)
|
|
{
|
|
BOOL b,
|
|
bMoreGlyphs;
|
|
ULONG iGlyph,
|
|
cGlyphs;
|
|
GLYPHBITS *pgb;
|
|
POINTL ptl;
|
|
GLYPHPOS *pgp;
|
|
PBYTE pLinXgaGlyphBuff,
|
|
pXgaLinGlyphBuffA,
|
|
pXgaLinGlyphBuffB;
|
|
ULONG ulPhyXgaGlyphBuff,
|
|
ulXgaPhyGlyphBuffA,
|
|
ulXgaPhyGlyphBuffB,
|
|
cjGlyphBuff;
|
|
UINT i,
|
|
cxGlyph,
|
|
cyGlyph,
|
|
nGlyph,
|
|
GlyphBmPitchInBytes,
|
|
GlyphBmPitchInPels;
|
|
ULONG XGAPixelOp,
|
|
ulXgaMask;
|
|
FONTINFO FontInfo;
|
|
PCPALLOCNODE pcpanA,
|
|
pcpanB;
|
|
INT yGlyphBias;
|
|
|
|
PXGACPREGS pXgaCpRegs = ((PPDEV)pso->dhpdev)->pXgaCpRegs;
|
|
|
|
DISPDBG((3, "XGA.DLL!bHandleNonCachedFonts\n"));
|
|
|
|
// Take care of any opaque rectangles.
|
|
|
|
if (prclOpaque != NULL)
|
|
{
|
|
b = bOpaqueRect((PPDEV)pso->dhpdev, pco, prclOpaque, pboOpaque);
|
|
if (b == FALSE)
|
|
{
|
|
return (b);
|
|
}
|
|
}
|
|
|
|
// Take care of the glyph attributes, color and mix.
|
|
|
|
b = bSetXgaTextColorAndMix((PPDEV)pso->dhpdev, mix, pboFore, pboOpaque);
|
|
if (b == FALSE)
|
|
return (b);
|
|
|
|
// Take care of the clipping.
|
|
|
|
b = bSetXgaClipping((PPDEV)pso->dhpdev, pco, &ulXgaMask);
|
|
if (b == FALSE)
|
|
return (b);
|
|
|
|
// Setup the Control Word for the XGA.
|
|
|
|
XGAPixelOp = BS_BACK_COLOR | FS_FORE_COLOR |
|
|
STEP_PX_BLT |
|
|
SRC_PEL_MAP_A | DST_PEL_MAP_A |
|
|
PATT_PEL_MAP_B | MSK_DISABLE |
|
|
DM_ALL_PELS | OCT_DY ;
|
|
|
|
XGAPixelOp |= ulXgaMask;
|
|
|
|
// Get the size of the largest glyph in the font.
|
|
|
|
FONTOBJ_vGetInfo(pfo, sizeof(FONTINFO), &FontInfo);
|
|
|
|
cjGlyphBuff = FontInfo.cjMaxGlyph1;
|
|
|
|
// Get the Glyph Data.
|
|
|
|
STROBJ_vEnumStart(pstro);
|
|
|
|
// Get two buffers in XGA off screen memory.
|
|
|
|
pcpanA = (PCPALLOCNODE) hCpAlloc((PPDEV)pso->dhpdev, cjGlyphBuff, XGA_LOCK_MEM);
|
|
pXgaLinGlyphBuffA = (PBYTE) pcpanA->pCpLinearMemory;
|
|
ulXgaPhyGlyphBuffA = pcpanA->ulCpPhysicalMemory;
|
|
|
|
pcpanB = (PCPALLOCNODE) hCpAlloc((PPDEV)pso->dhpdev, cjGlyphBuff, XGA_LOCK_MEM);
|
|
pXgaLinGlyphBuffB = (PBYTE) pcpanB->pCpLinearMemory;
|
|
ulXgaPhyGlyphBuffB = pcpanB->ulCpPhysicalMemory;
|
|
|
|
do
|
|
{
|
|
bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphs, &pgp);
|
|
|
|
// If this is a mono-spaced font we need to set the X
|
|
// for each glyph.
|
|
|
|
if (pstro->ulCharInc != 0)
|
|
{
|
|
UINT ii;
|
|
LONG x,y;
|
|
|
|
x = pgp[0].ptl.x;
|
|
y = pgp[0].ptl.y;
|
|
for (ii=1; ii < cGlyphs; ii++)
|
|
{
|
|
x += pstro->ulCharInc;
|
|
pgp[ii].ptl.x = x;
|
|
pgp[ii].ptl.y = y;
|
|
}
|
|
}
|
|
|
|
for (iGlyph = 0; iGlyph < cGlyphs; iGlyph++)
|
|
{
|
|
|
|
// Get a pointer to the GlyphBits.
|
|
|
|
pgb = pgp[iGlyph].pgdf->pgb;
|
|
|
|
// Get the linear address for the XGA Glyph Buffer.
|
|
|
|
if (iGlyph & 0x1)
|
|
{
|
|
pLinXgaGlyphBuff = pXgaLinGlyphBuffA;
|
|
ulPhyXgaGlyphBuff = ulXgaPhyGlyphBuffA;
|
|
}
|
|
else
|
|
{
|
|
pLinXgaGlyphBuff = pXgaLinGlyphBuffB;
|
|
ulPhyXgaGlyphBuff = ulXgaPhyGlyphBuffB;
|
|
}
|
|
|
|
// Copy over the bits.
|
|
|
|
cxGlyph = pgb->sizlBitmap.cx;
|
|
cyGlyph = pgb->sizlBitmap.cy;
|
|
|
|
GlyphBmPitchInBytes = CJ_SCAN(cxGlyph);
|
|
GlyphBmPitchInPels = GlyphBmPitchInBytes * 8;
|
|
|
|
nGlyph = GlyphBmPitchInBytes * cyGlyph;
|
|
|
|
// Need to swap the bits with in the byte.
|
|
// I think there is an easier way.
|
|
|
|
for (i = 0; i < nGlyph; i++)
|
|
{
|
|
pLinXgaGlyphBuff[i] = BITSWAP(pgb->aj[i]);
|
|
}
|
|
|
|
// Adjust the placement of the glyph.
|
|
|
|
yGlyphBias = (cyGlyph + pgb->ptlOrigin.y) - 1;
|
|
|
|
ptl.x = pgp[iGlyph].ptl.x;
|
|
ptl.y = pgp[iGlyph].ptl.y + yGlyphBias;
|
|
|
|
// Note: We wait here so every thing that can be done
|
|
// to get ready for the next character is done
|
|
// before we have to wait for the CoProcessor.
|
|
|
|
vWaitForCoProcessor((PPDEV)pso->dhpdev, 10);
|
|
|
|
// Setup the pattern bitmap Pel interface registers.
|
|
|
|
pXgaCpRegs->XGAPixelMapIndex = PEL_MAP_B;
|
|
pXgaCpRegs->XGAPixMapBasePtr = ulPhyXgaGlyphBuff;
|
|
pXgaCpRegs->XGAPixMapWidth = GlyphBmPitchInPels - 1;
|
|
pXgaCpRegs->XGAPixMapHeight = cyGlyph - 1;
|
|
pXgaCpRegs->XGAPixMapFormat = PATT_MAP_FORMAT;
|
|
|
|
// Setup the Blit pattern and dest.
|
|
// Note: There is no source bitmap, Until we get the pattern
|
|
// brush.
|
|
|
|
pXgaCpRegs->XGAOpDim1 = cxGlyph - 1;
|
|
pXgaCpRegs->XGAOpDim2 = cyGlyph - 1;
|
|
|
|
pXgaCpRegs->XGAPatternMapX = 0;
|
|
pXgaCpRegs->XGAPatternMapY = cyGlyph - 1;
|
|
|
|
pXgaCpRegs->XGADestMapX = LOWORD(ptl.x);
|
|
pXgaCpRegs->XGADestMapY = LOWORD(ptl.y);
|
|
|
|
// Do the blit operation.
|
|
|
|
pXgaCpRegs->XGAPixelOp = XGAPixelOp;
|
|
|
|
|
|
}
|
|
|
|
|
|
} while(bMoreGlyphs);
|
|
|
|
hCpFree((PPDEV)(pso->dhpdev), (HANDLE) pcpanA);
|
|
hCpFree((PPDEV)(pso->dhpdev), (HANDLE) pcpanB);
|
|
|
|
return (TRUE);
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* XGA Solid Opaque Rect.
|
|
*
|
|
* Returns TRUE if the Opaque Rect was handled.
|
|
****************************************************************************/
|
|
BOOL bOpaqueRect(PPDEV ppdev, CLIPOBJ *pco, RECTL *prclOpaque, BRUSHOBJ *pboOpaque)
|
|
|
|
{
|
|
BOOL b;
|
|
INT width,
|
|
height;
|
|
|
|
ULONG XGAPixelOp,
|
|
ulXgaMask,
|
|
iSolidColor;
|
|
|
|
PXGACPREGS pXgaCpRegs = ppdev->pXgaCpRegs;
|
|
|
|
|
|
DISPDBG((3, "XGA.DLL!bOpaqueRect - Entry\n"));
|
|
|
|
b = bSetXgaClipping(ppdev, pco, &ulXgaMask);
|
|
if (b == FALSE)
|
|
return (b);
|
|
|
|
|
|
iSolidColor = pboOpaque->iSolidColor;
|
|
if (iSolidColor == -1)
|
|
return(FALSE);
|
|
|
|
// Setup the BitBlt parameters.
|
|
|
|
width = (prclOpaque->right - prclOpaque->left) - 1;
|
|
height = (prclOpaque->bottom - prclOpaque->top) - 1;
|
|
|
|
pXgaCpRegs->XGAOpDim1 = width;
|
|
pXgaCpRegs->XGAOpDim2 = height;
|
|
|
|
pXgaCpRegs->XGADestMapX = (USHORT) prclOpaque->left;
|
|
pXgaCpRegs->XGADestMapY = (USHORT) prclOpaque->top;
|
|
|
|
pXgaCpRegs->XGAForeGrMix = XGA_S;
|
|
pXgaCpRegs->XGABackGrMix = XGA_S;
|
|
|
|
pXgaCpRegs->XGAForeGrColorReg = iSolidColor;
|
|
pXgaCpRegs->XGABackGrColorReg = iSolidColor;
|
|
|
|
// Now build the Pel Operation Register Op Code;
|
|
|
|
XGAPixelOp = BS_BACK_COLOR | FS_FORE_COLOR |
|
|
STEP_PX_BLT |
|
|
SRC_PEL_MAP_A | DST_PEL_MAP_A |
|
|
PATT_FOREGROUND;
|
|
|
|
XGAPixelOp |= ulXgaMask;
|
|
|
|
pXgaCpRegs->XGAPixelOp = XGAPixelOp;
|
|
|
|
vWaitForCoProcessor(ppdev, 10);
|
|
|
|
return (TRUE);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
* bSetXgaTextColorAndMix - Setup the XGA's Text Colors and mix modes
|
|
*****************************************************************************/
|
|
BOOL bSetXgaTextColorAndMix(PPDEV ppdev, MIX mix, BRUSHOBJ *pboFore, BRUSHOBJ *pboOpaque)
|
|
{
|
|
ULONG ulForeSolidColor;
|
|
BYTE jXgaForeMix;
|
|
|
|
PXGACPREGS pXgaCpRegs = ppdev->pXgaCpRegs;
|
|
|
|
// Pickup all the glyph attributes.
|
|
|
|
jXgaForeMix = Rop2ToXgaRop[(mix & 0xF) - R2_BLACK];
|
|
|
|
ulForeSolidColor = pboFore->iSolidColor;
|
|
|
|
// Let the engine handle the non-solid brush cases.
|
|
|
|
if (ulForeSolidColor == -1)
|
|
return(FALSE);
|
|
|
|
// Set the XGA Attributes.
|
|
|
|
pXgaCpRegs->XGAForeGrMix = jXgaForeMix;
|
|
pXgaCpRegs->XGABackGrMix = XGA_D;
|
|
|
|
pXgaCpRegs->XGAForeGrColorReg = ulForeSolidColor;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* pCacheFont - Make sure the glyphs we need in this font are cached.
|
|
* Return a pointer to the array of glyph caches.
|
|
*
|
|
* if there is an error, return NULL.
|
|
****************************************************************************/
|
|
PCACHEDGLYPH pCacheFont(PPDEV ppdev, STROBJ *pstro, FONTOBJ *pfo)
|
|
{
|
|
ULONG iUniq;
|
|
|
|
FONTINFO fi;
|
|
|
|
PCACHEDFONT pcf,
|
|
pCachedFont;
|
|
|
|
ULONG i,
|
|
iGlyph,
|
|
cFntGlyphs,
|
|
cStrGlyphs,
|
|
nGlyph,
|
|
iGlyphCache;
|
|
|
|
UINT nSize;
|
|
|
|
GLYPHPOS *pgp;
|
|
|
|
GLYPHBITS *pgb;
|
|
|
|
PCACHEDGLYPH pCachedGlyphs,
|
|
pcgNew,
|
|
pcg;
|
|
|
|
ULONG cxGlyph,
|
|
cyGlyph,
|
|
GlyphBmPitchInPels,
|
|
GlyphBmPitchInBytes;
|
|
|
|
PBYTE pLinXgaGlyphBuff;
|
|
|
|
PCPALLOCNODE pcpan;
|
|
|
|
HGLYPH hg;
|
|
|
|
BOOL bFound;
|
|
|
|
// Are we already doing any caching for this font?
|
|
|
|
iUniq = pfo->iUniq;
|
|
|
|
if (ppdev->pCachedFontsRoot == NULL)
|
|
{
|
|
// This is the first font.
|
|
// Allocate a node for it.
|
|
|
|
ppdev->pCachedFontsRoot = (PCACHEDFONT) EngAllocMem(FL_ZERO_MEMORY, sizeof(CACHEDFONT), ALLOC_TAG);
|
|
if (ppdev->pCachedFontsRoot == NULL)
|
|
{
|
|
DISPDBG((1, "XGA.DLL!pCacheFont - EngAllocMem of pCachedFontsRoot failed\n"));
|
|
return(NULL);
|
|
}
|
|
|
|
pCachedFont = ppdev->pCachedFontsRoot;
|
|
pCachedFont->iUniq = iUniq;
|
|
|
|
}
|
|
else
|
|
{
|
|
// Search for the font in the font list
|
|
|
|
for (pcf = ppdev->pCachedFontsRoot; pcf != NULL; pcf = pcf->pcfNext)
|
|
{
|
|
if (pcf->iUniq == iUniq)
|
|
break;
|
|
}
|
|
|
|
if (pcf != NULL)
|
|
{
|
|
pCachedFont = pcf;
|
|
}
|
|
else
|
|
{
|
|
// Allocate a Font Cache node.
|
|
|
|
pCachedFont = (PCACHEDFONT) EngAllocMem(FL_ZERO_MEMORY, sizeof(CACHEDFONT), ALLOC_TAG);
|
|
if (pCachedFont == NULL)
|
|
{
|
|
DISPDBG((1, "XGA.DLL!pCacheFont - EngAllocMem of pCachedFont failed\n"));
|
|
return(NULL);
|
|
}
|
|
|
|
// Add this font to the beginning of the font list.
|
|
|
|
pCachedFont->pcfNext = ppdev->pCachedFontsRoot;
|
|
ppdev->pCachedFontsRoot = pCachedFont;
|
|
|
|
// Set the font ID for the font.
|
|
|
|
pCachedFont->iUniq = iUniq;
|
|
}
|
|
}
|
|
|
|
// If this font is new to the font cache, allocate the glyph cache.
|
|
|
|
FONTOBJ_vGetInfo(pfo, sizeof(FONTINFO), &fi);
|
|
cFntGlyphs = fi.cGlyphsSupported;
|
|
|
|
// This is where we clamp the size of the Font structures we are allocating.
|
|
|
|
if (cFntGlyphs > MAX_GLYPHS_TO_ALLOC)
|
|
cFntGlyphs = MAX_GLYPHS_TO_ALLOC;
|
|
|
|
if (pCachedFont->pCachedGlyphs == NULL)
|
|
{
|
|
// Get the font info.
|
|
|
|
pCachedFont->cGlyphs = cFntGlyphs;
|
|
|
|
// Allocate memory for the CachedGlyphs of this font.
|
|
|
|
nSize = cFntGlyphs * sizeof(CACHEDGLYPH);
|
|
|
|
pCachedFont->pCachedGlyphs = (PCACHEDGLYPH) EngAllocMem(FL_ZERO_MEMORY, nSize, ALLOC_TAG);
|
|
if (pCachedFont->pCachedGlyphs == NULL)
|
|
{
|
|
DISPDBG((1, "XGA.DLL!pCacheFont - EngAllocMem of pCachedGlyphs failed\n"));
|
|
pCachedFont->cGlyphs = 0;
|
|
return(NULL);
|
|
}
|
|
|
|
}
|
|
|
|
// Add the glyphs we're concerned about to the Glyph Cache.
|
|
|
|
STROBJ_bEnum(pstro, &cStrGlyphs, &pgp);
|
|
|
|
pCachedGlyphs = pCachedFont->pCachedGlyphs;
|
|
for (iGlyph = 0; iGlyph < cStrGlyphs; iGlyph++)
|
|
{
|
|
// Get the glyph handle, this will be used as the index
|
|
// into the glyph cache for this font.
|
|
|
|
iGlyphCache = (UINT) pgp[iGlyph].hg % cFntGlyphs;
|
|
|
|
// Check if the glyph is already in the cache.
|
|
|
|
hg = pgp[iGlyph].hg;
|
|
pcg = &(pCachedGlyphs[iGlyphCache]);
|
|
if (!(pcg->fl & VALID_GLYPH) || (pcg->hg != hg))
|
|
{
|
|
// The glyph element in the main hash table for this font
|
|
// is not for this glyph.
|
|
// Search the collision list to see if we have allocated
|
|
// a glyph node yet.
|
|
|
|
bFound = FALSE;
|
|
for (pcg = &(pCachedGlyphs[iGlyphCache]);
|
|
pcg->pcgCollisionLink != END_COLLISIONS;
|
|
pcg = pcg->pcgCollisionLink)
|
|
{
|
|
if (pcg->hg == hg)
|
|
{
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If we found an allocated glyph node for this font,
|
|
// then continue the testing for glyphs.
|
|
|
|
if (bFound == TRUE)
|
|
continue;
|
|
|
|
// A glyph node has not been allocated for this glyph yet
|
|
// in the collision list, so search to the end of the collision
|
|
// and allocate the node.
|
|
|
|
if (!(pCachedGlyphs[iGlyphCache].fl & VALID_GLYPH))
|
|
{
|
|
// The glyph element has not been allocated yet, so
|
|
// we will allocate it now.
|
|
|
|
pcg = &(pCachedGlyphs[iGlyphCache]);
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((2, "XGA.DLL!pCacheFont - Collision in the glyph hash table\n"));
|
|
|
|
// Search for the end of the collision list.
|
|
|
|
pcg = &(pCachedGlyphs[iGlyphCache]);
|
|
|
|
while (pcg->pcgCollisionLink != END_COLLISIONS)
|
|
{
|
|
pcg = pcg->pcgCollisionLink;
|
|
}
|
|
|
|
// Allocate a new font glyph node.
|
|
|
|
pcgNew = (PCACHEDGLYPH) EngAllocMem(FL_ZERO_MEMORY, sizeof(CACHEDGLYPH), ALLOC_TAG);
|
|
if (pcgNew == NULL)
|
|
{
|
|
DISPDBG((1, "XGA.DLL!pCacheFont - Local Alloc (pcgNew) failed\n"));
|
|
return (NULL);
|
|
}
|
|
|
|
// Connect the end of the collision list to the new
|
|
// glyph node.
|
|
|
|
pcg->pcgCollisionLink = pcgNew;
|
|
|
|
// Set up the pointer to the node where going to init.
|
|
|
|
pcg = pcgNew;
|
|
|
|
}
|
|
|
|
// Pickup the pointer to the glyph bits.
|
|
|
|
pgb = pgp[iGlyph].pgdf->pgb;
|
|
|
|
cxGlyph = pgb->sizlBitmap.cx;
|
|
cyGlyph = pgb->sizlBitmap.cy;
|
|
|
|
GlyphBmPitchInBytes = CJ_SCAN(cxGlyph);
|
|
GlyphBmPitchInPels = GlyphBmPitchInBytes * 8;
|
|
|
|
nGlyph = GlyphBmPitchInBytes * cyGlyph;
|
|
|
|
// Allocate memory for the glyph data on the XGA.
|
|
|
|
pcpan = (PCPALLOCNODE) hCpAlloc(ppdev ,nGlyph, XGA_LOCK_MEM);
|
|
if (pcpan == NULL)
|
|
{
|
|
DISPDBG((1, "XGA.DLL!pCacheFont - hCpAlloc failed\n"));
|
|
return(NULL);
|
|
}
|
|
|
|
// Initialize the Glyph Cache node.
|
|
|
|
pcg->fl |= VALID_GLYPH;
|
|
pcg->hg = pgp[iGlyph].hg;
|
|
pcg->pcgCollisionLink = END_COLLISIONS;
|
|
pcg->ptlOrigin = pgb->ptlOrigin;
|
|
pcg->sizlBitmap = pgb->sizlBitmap;
|
|
|
|
pcg->BmPitchInPels = GlyphBmPitchInPels;
|
|
pcg->BmPitchInBytes = GlyphBmPitchInBytes;
|
|
|
|
pcg->pcpan = pcpan;
|
|
pcg->pCpLinearMemory = pcpan->pCpLinearMemory;
|
|
pcg->ulCpPhysicalMemory = pcpan->ulCpPhysicalMemory;
|
|
|
|
// Initialize the Glyph Cache data in XGA memory.
|
|
|
|
pLinXgaGlyphBuff = pcpan->pCpLinearMemory;
|
|
|
|
// Need to swap the bits with in the byte.
|
|
// I think there is an easier way.
|
|
|
|
for (i = 0; i < nGlyph; i++)
|
|
{
|
|
pLinXgaGlyphBuff[i] = BITSWAP(pgb->aj[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(pCachedGlyphs);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
* bBlowCache - Blow Away the Cache
|
|
***************************************************************************/
|
|
BOOL bBlowCache(SURFOBJ *pso)
|
|
{
|
|
BOOL b;
|
|
PCACHEDFONT pcf,
|
|
pcfLast;
|
|
|
|
// Traverse the CachedFonts list.
|
|
// Free all the system memory used for each font.
|
|
|
|
for (pcf = ((PPDEV)pso->dhpdev)->pCachedFontsRoot; pcf != NULL; pcf = pcf->pcfNext)
|
|
{
|
|
EngFreeMem(pcf->pCachedGlyphs);
|
|
}
|
|
|
|
// Now free all the memory for the font nodes.
|
|
|
|
for (pcf = ((PPDEV)pso->dhpdev)->pCachedFontsRoot; pcf != NULL; )
|
|
{
|
|
pcfLast = pcf;
|
|
pcf = pcf->pcfNext;
|
|
EngFreeMem(pcfLast);
|
|
}
|
|
|
|
((PPDEV)pso->dhpdev)->pCachedFontsRoot = NULL;
|
|
|
|
// Now Free all the memory used to maintain the XGA heap.
|
|
|
|
vCpMmDestroyHeap((PPDEV)pso->dhpdev);
|
|
|
|
// Now ReInitialize the XGA Heap.
|
|
|
|
b = bCpMmInitHeap( (PPDEV)pso->dhpdev );
|
|
if (b == FALSE)
|
|
{
|
|
DISPDBG((1, "XGA.DLL!bBlowCache - bCpMmInitHeap failed\n"));
|
|
}
|
|
|
|
return (b);
|
|
|
|
}
|