/*++ Copyright (c) 1996 - 1999 Microsoft Corporation Module Name: bmpdload.c Abstract: Implementation of True Type Download as Bitmap routines. Environment: Windows NT Unidrv driver Revision History: 06/06/97 -ganeshp- Created --*/ // //This line should be before the line including font.h. //Comment out this line to disable FTRC and FTST macroes. // //#define FILETRACE #include "font.h" BOOL BFreeTrueTypeBMPPFM( PFONTMAP pfm ) /*++ Routine Description: Frees a downloded font's PFM. Arguments: pfm Pointer to Fontmap Return Value: TRUE for success and FALSE for failure Note: 6/6/1997 -ganeshp- Created it. --*/ { if (pfm) { MemFree(pfm); return TRUE; } else { return FALSE; } } DWORD DwTrueTypeBMPGlyphOut( TO_DATA *pTod ) /*++ Routine Description: This functions outputs the downloaded glyphs. All the information is stored in TOD Arguments: pTod TextOut Data. Return Value: Number of Glyph outputed. O for ERROR. Note: 6/9/1997 -ganeshp- Created it. --*/ { DWORD dwNumGlyphsPrinted; // Glyphs Printed DWORD dwCurrGlyphIndex; // Current Glyph to print. DWORD dwGlyphsToPrint; // Number of Glyphs to print. DWORD dwCopyOfGlyphsToPrint; // Copy of dwGlyphsToPrint GLYPHPOS *pgp; // Glyph position array. PDEV *pPDev; // Our PDEV. PDLGLYPH pdlGlyph; // Download Glyph information INT iX, iY; // X and Y position of Glyphs. POINTL ptlRem; // Remainder of XoveTo and YMoveTo. BOOL bSetCursorForEachGlyph; // X and Y position should be set if TRUE // // Local Initialization. // dwCurrGlyphIndex = pTod->dwCurrGlyph; dwCopyOfGlyphsToPrint = dwGlyphsToPrint = pTod->cGlyphsToPrint; dwNumGlyphsPrinted = 0; pgp = pTod->pgp; pPDev = pTod->pPDev; iX = pTod->pgp->ptl.x; iY = pTod->pgp->ptl.y; FTRC(\n********TRACING DwTrueTypeBMPGlyphOut ***********\n); FTST(dwCurrGlyphIndex,%d); FTST(dwGlyphsToPrint,%d); // // Set the cursor to first glyph if not already set. // if ( !(pTod->flFlags & TODFL_FIRST_GLYPH_POS_SET) ) { VSetCursor( pPDev, iX, iY, MOVE_ABSOLUTE, &ptlRem); // // We need to handle the return value. Devices with resoloutions finer // than their movement capability (like LBP-8 IV) get into a knot here, // attempting to y-move on each glyph. We pretend we got where we // wanted to be. // pPDev->ctl.ptCursor.x += ptlRem.x; pPDev->ctl.ptCursor.y += ptlRem.y ; // // Now set the flag. // pTod->flFlags |= TODFL_FIRST_GLYPH_POS_SET; } // // Now start printing. The printing should be optimised for default // placement. In this case we assume that GDI has placed the glyphs // based upon their width and we don't need to update our cursor pos // after every glyph. we print all the glyphs and then move the cursor // to the last glyph position. If we know the width of the downloaded // glyph then we will update position the cursor at the end of the // glyphs box else we will just move to the last glyph cursor position. // // If the default placement is not set then we print a glyph and move. If // we know the width we do some optimization. we find out the new cursor // position, by adding the glyph width. If the new position matches that of // the next glyph we just update our cursor position else we move to the // the next glyph position. // bSetCursorForEachGlyph = SET_CURSOR_FOR_EACH_GLYPH(pTod->flAccel); while (dwGlyphsToPrint) { pdlGlyph = pTod->apdlGlyph[dwCurrGlyphIndex]; if (bSetCursorForEachGlyph) { // // If we are printing top to down or right to left we need to // set the position. // if( pTod->flAccel & SO_VERTICAL ) { // // When we are printing veritcal, only Y changes.X position is // same for all glyphs. // iX = pTod->ptlFirstGlyph.x; iY = pgp[dwNumGlyphsPrinted].ptl.y; } else if ( (pTod->flAccel & SO_HORIZONTAL) && (pTod->flAccel & SO_REVERSED) ) { // // This is the Horizental reversed case(Right to Left). In this // case only x position changes.Y is set to first glyph's Y. // iX = pgp[dwNumGlyphsPrinted].ptl.x; iY = pTod->ptlFirstGlyph.y; } else { // // The Glyphs are not placed at default positions.Each glyph has // explicit X and Y.So we need to move. // iX = pgp[dwNumGlyphsPrinted].ptl.x; iY = pgp[dwNumGlyphsPrinted].ptl.y; } VSetCursor( pPDev, iX, iY, MOVE_ABSOLUTE, &ptlRem); } // // Default placement or we have moved to the correct position. Now Just // print the Glyph. // if ( !BPrintADLGlyph(pPDev, pTod, pdlGlyph) ) { ERR(("UniFont:DwTrueTypeBMPGlyphOut:BPrintADLGlyph Failed\n")); goto ErrorExit; } // // If for each glyph, cursor has to be set, then update cursor position. // This may result in fewer Movement command, because if the next // glyph's position is at the updated cursor, we will not send any // Movement command. // if( pTod->flAccel & SO_VERTICAL ) iY += pdlGlyph->wWidth; else iX += pdlGlyph->wWidth; if (bSetCursorForEachGlyph) { // // If for each glyph, the cursor position has to be set, then iX // and iY are already updated. So just use them. // VSetCursor( pPDev, iX, iY, MOVE_ABSOLUTE | MOVE_UPDATE, &ptlRem); } else if (dwGlyphsToPrint == 1) //Last Glyph { // // Set the cursor to the end of the last glyph. Only the X position // has to be updated. This has to be done only for default // placement, as for non default placement case, we update cursor // position after printing the glyph.For default placement use the // cursor position of the last glyph.In TextOut Call, for default // placement, we have already computed the position for each glyph. // VSetCursor( pPDev, iX, iY, MOVE_ABSOLUTE | MOVE_UPDATE, &ptlRem); } // // Update the counters. // dwGlyphsToPrint--; dwNumGlyphsPrinted++; dwCurrGlyphIndex++; } // // If no failure then we would have printed all the glyphs. // ASSERTMSG( (dwNumGlyphsPrinted == dwCopyOfGlyphsToPrint), ("UniFont:DwTrueTypeBMPGlyphOut: All glyphs are not printed")); FTRC(After Printing The values are:\n); FTST(dwGlyphsToPrint,%d); FTST(dwNumGlyphsPrinted,%d); FTST(dwCopyOfGlyphsToPrint,%d); FTST(dwCurrGlyphIndex,%d); ErrorExit: FTRC(********END TRACING DwTrueTypeBMPGlyphOut ***********\n); return dwNumGlyphsPrinted; } BOOL BSelectTrueTypeBMP( PDEV *pPDev, PFONTMAP pFM, POINTL* pptl ) /*++ Routine Description: To Select a TrueType Downloaded as Bitmap Font. Arguments: pPDev Pointer to PDEV pDM fontmap pointer. pptl Point Size of the font, Not used. Return Value: TRUE for success and FALSE for failure Note: 6/9/1997 -ganeshp- Created it. --*/ { BOOL bRet; // // Local Initialization. // bRet = FALSE; if( pFM->flFlags & FM_SOFTFONT ) { /* * Call BSendFont to download the installed softfont. */ if( !BSendDLFont( pPDev, pFM ) ) return FALSE; /* * Can now select the font: this is done using a specific * ID. The ID is stored in the FONTMAP structure. The calling * function has updated the standard variable so just send * CMD_SELECTFONTID command. */ BUpdateStandardVar(pPDev, pFM, 0, 0, STD_CFID ); WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo, CMD_SELECTFONTID)); bRet = TRUE; } return bRet; } BOOL BDeselectTrueTypeBMP( PDEV *pPDev, PFONTMAP pFM ) /*++ Routine Description: Arguments: pPDev Pointer to PDEV Return Value: TRUE for success and FALSE for failure Note: 6/9/1997 -ganeshp- Created it. --*/ { BOOL bRet; COMMAND *pCmd; // // Local Initialization. // bRet = FALSE; if( pFM->flFlags & FM_SOFTFONT ) { /* * Can now select the font: this is done using a specific * ID. The ID is stored in the FONTMAP structure. The calling * function has updated the standard variable so just send * CMD_SELECTFONTID command. */ pCmd = COMMANDPTR(pPDev->pDriverInfo, CMD_DESELECTFONTID); if (pCmd) { BUpdateStandardVar(pPDev, pFM, 0, 0, STD_CFID); WriteChannel(pPDev,pCmd ); } bRet = TRUE; } return bRet; } DWORD DwDLTrueTypeBMPHeader( PDEV *pPDev, PFONTMAP pFM ) /*++ Routine Description: Arguments: pPDev Pointer to PDEV pFM FontMap for All Font information Return Value: This function returns the memory used to download this font. If this function fails, this function has to return 0, Note: 6/9/1997 -ganeshp- Created it. --*/ { DWORD dwMem; // // Local Initialization. // dwMem = DwDLPCLHeader(pPDev, pFM->pIFIMet, pFM->ulDLIndex ); return dwMem; } DWORD DwDLTrueTypeBMPGlyph( PDEV *pPDev, PFONTMAP pFM, HGLYPH hGlyph, WORD wDLGlyphId, WORD *pwWidth ) /*++ Routine Description: Arguments: pPDev Pointer to PDEV pFM FontMap data hGlyph Handle to the Glyph. wDLGlyphId Downloaded Glyph Id. pwWidth Width of the Glyph. Update this parameter. Return Value: The memory used to download thsi glyph. Note: 6/9/1997 -ganeshp- Created it. --*/ { DWORD dwMem; TO_DATA *pTod; GLYPHDATA *pgd; PFONTMAP_TTB pFMTB; DL_MAP *pdm; // // Initialize Local Variables // dwMem = 0; pTod = PFDV->ptod; pgd = NULL; pFMTB = pFM->pSubFM; pdm = pFMTB->u.pvDLData;; // // Check the Set FontID flag. If this flag is set that means the // CMD_SETFONTID command is send and we don't need to set it again. // Else we should send this command as PCL glyph downloding needs this // command to be sent, before we download any glyph. // if (!(PFDV->flFlags & FDV_SET_FONTID)) { pFM->ulDLIndex = pdm->wCurrFontId; BUpdateStandardVar(pPDev, pFM, 0, 0, STD_STD | STD_NFID); WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo, CMD_SETFONTID)); PFDV->flFlags |= FDV_SET_FONTID; } BUpdateStandardVar(pPDev, pFM, wDLGlyphId, 0, STD_GL); if( !FONTOBJ_cGetGlyphs( pTod->pfo, FO_GLYPHBITS, (ULONG)1, &hGlyph, &pgd ) || !(*pwWidth = (WORD)IDLGlyph( pPDev, wDLGlyphId, pgd, &dwMem )) ) { ERR(("Unifont!DwDLTrueTypeBMPGlyph: Downloading Glyph Failed\n")); return 0; } // // Update memory consumption usage // ((PFONTMAP_TTB)pFM->pSubFM)->dwDLSize += dwMem; return dwMem; } BOOL BCheckCondTrueTypeBMP( PDEV *pPDev, FONTOBJ *pfo, STROBJ *pso, IFIMETRICS *pifi ) /*++ Routine Description: Arguments: pPDev Pointer to PDEV pfo FONTOBJ to download pso StringObj pifi IFI mertics. Return Value: TRUE for success and FALSE for failure Note: 6/9/1997 -ganeshp- Created it. --*/ { INT iFontIndex; DL_MAP *pdm; PFONTPDEV pFontPDev; INT iGlyphsDL; DWORD cjMemUsed; BOOL bRet; // // Local variables initialization. // iFontIndex = PtrToLong(pfo->pvConsumer) - 1; pFontPDev = PFDV; bRet = FALSE; if (pdm = PGetDLMapFromIdx (pFontPDev, iFontIndex)) { // // Trunction may have happened.We won't download if the number glyphs // or Glyph max size are == MAXWORD. // if ( (pdm->cTotalGlyphs != MAXWORD) && (pdm->wMaxGlyphSize != MAXWORD) && (pdm->wFirstDLGId != MAXWORD) && (pdm->wLastDLGId != MAXWORD) ) { /* * Must now decide whether to download this font or not. This is * a guess work. We should try to findout the memory consumption. * Check on memory usage. Assume all glyphs are the largest size: * this is pessimistic for a proportional font, but safe, given * the vaguaries of tracking memory usage. */ ASSERTMSG((pdm->cTotalGlyphs && pdm->wMaxGlyphSize),\ ("pdm->cTotalGlyphs = %d, pdm->wGlyphMaxSize = %d\n",\ pdm->cTotalGlyphs,pdm->wMaxGlyphSize)); iGlyphsDL = min( (pdm->wLastDLGId - pdm->wFirstDLGId), pdm->cTotalGlyphs ); cjMemUsed = iGlyphsDL * pdm->wMaxGlyphSize; if( !(pifi->flInfo & FM_INFO_CONSTANT_WIDTH) ) { /* * If this is a proportionally spaced font, we should reduce * the estimate of memory size for this font. The reason is * that the above estimate is the size of the biggest glyph * in the font. There will (for Latin fonts, anyway) be many * smaller glyphs, some much smaller. */ cjMemUsed /= PCL_PITCH_ADJ; } /* * We only download if the memory used for this font is less than * available memory. */ if( (pFontPDev->dwFontMemUsed + cjMemUsed) > pFontPDev->dwFontMem ) { WARNING(("UniFont!BCheckCondTrueTypeBMP:Not Downloading the font:TOO BIG for download\n")); } else bRet = TRUE; } } return bRet; } FONTMAP * InitPFMTTBitmap( PDEV *pPDev, FONTOBJ *pFontObj ) /*++ Routine Description: This routine initializes the True Type downloaded(as bitmap) font's PFM. Arguments: pPDev Pointer to PDEV pFontObj FontObj pointer. Return Value: Pointer to FONTMAP for success and NULL for failure. Note: 6/6/1997 -ganeshp- Created it. --*/ { PFONTMAP pfm; DWORD dwSize; dwSize = sizeof(FONTMAP) + sizeof(FONTMAP_TTB); if ( pfm = MemAlloc( dwSize ) ) { ZeroMemory(pfm, dwSize); pfm->dwSignature = FONTMAP_ID; pfm->dwSize = sizeof(FONTMAP); pfm->dwFontType = FMTYPE_TTBITMAP; pfm->pSubFM = (PVOID)(pfm+1); pfm->ulDLIndex = (ULONG)-1; // // These two entries are meaningless. // pfm->wFirstChar = 0; pfm->wLastChar = 0xffff; pfm->pfnGlyphOut = DwTrueTypeBMPGlyphOut; pfm->pfnSelectFont = BSelectTrueTypeBMP; pfm->pfnDeSelectFont = BDeselectTrueTypeBMP; pfm->pfnDownloadFontHeader = DwDLTrueTypeBMPHeader; pfm->pfnDownloadGlyph = DwDLTrueTypeBMPGlyph; pfm->pfnCheckCondition = BCheckCondTrueTypeBMP; pfm->pfnFreePFM = BFreeTrueTypeBMPPFM; } return pfm; } #undef FILETRACE