/******************************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); }