/******************************Module*Header*******************************\ * Module Name: fdquery.c * * (Brief description) * * Created: 08-Nov-1990 11:57:35 * Author: Bodin Dresevic [BodinD] * * Copyright (c) 1990 Microsoft Corporation \**************************************************************************/ #include "fd.h" ULONG cjBmfdDeviceMetrics ( PFONTCONTEXT pfc, FD_DEVICEMETRICS *pdevm ); VOID vStretchCvtToBitmap ( GLYPHBITS *pgb, PBYTE pjBitmap, // bitmap in *.fnt form ULONG cx, // unscaled width ULONG cy, // unscaled height ULONG yBaseline, PBYTE pjLineBuffer, // preallocated buffer for use by stretch routines ULONG cxScale, // horizontal scaling factor ULONG cyScale, // vertical scaling factor ULONG flSim // simulation flags ); #ifdef FE_SB // Rotation VOID vFill_RotateGLYPHDATA ( GLYPHDATA *pDistinationGlyphData, PVOID SourceGLYPHBITS, PVOID DistinationGLYPHBITS, UINT RotateDegree ); #endif /******************************Public*Routine******************************\ * BmfdQueryFont * * Returns: * Pointer to IFIMETRICS. Returns NULL if an error occurs. * * History: * 30-Aug-1992 -by- Gilman Wong [gilmanw] * IFI/DDI merge. * * 19-Nov-1990 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/ PIFIMETRICS BmfdQueryFont ( DHPDEV dhpdev, HFF hff, ULONG iFace, ULONG_PTR *pid ) { FACEINFO *pfai; DONTUSE(dhpdev); DONTUSE(pid); // // Validate handle. // if (hff == HFF_INVALID) return (PIFIMETRICS) NULL; // // We assume the iFace is within range. // ASSERTGDI( (iFace >= 1L) && (iFace <= PFF(hff)->cFntRes), "gdisrv!BmfdQueryFont: iFace out of range\n" ); // // Get ptr to the appropriate FACEDATA struct, take into account that // iFace values are 1 based. // pfai = &PFF(hff)->afai[iFace - 1]; // // Return the pointer to IFIMETRICS. // return pfai->pifi; } /******************************Public*Routine******************************\ * BmfdQueryFontTree * * This function returns pointers to per-face information. * * Parameters: * * dhpdev Not used. * * hff Handle to a font file. * * iFace Index of a face in the font file. * * iMode This is a 32-bit number that must be one of the following * values: * * Allowed ulMode values: * ---------------------- * * QFT_LIGATURES -- returns a pointer to the ligature map. * * QFT_KERNPAIRS -- return a pointer to the kerning pair table. * * QFT_GLYPHSET -- return a pointer to the WC->HGLYPH mapping table. * * pid Not used. * * Returns: a Returns a pointer to the requested data. This data will not change * until BmfdFree is called on the pointer. Caller must not attempt to * modify the data. NULL is returned if an error occurs. * * History: * 30-Aug-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/ PVOID BmfdQueryFontTree ( DHPDEV dhpdev, HFF hff, ULONG iFace, ULONG iMode, ULONG_PTR *pid ) { FACEINFO *pfai; DONTUSE(dhpdev); DONTUSE(pid); // // Validate parameters. // if (hff == HFF_INVALID) return ((PVOID) NULL); // Note: iFace values are index-1 based. if ((iFace < 1L) || (iFace > PFF(hff)->cFntRes)) { RETURN("gdisrv!BmfdQueryFontTree()\n", (PVOID) NULL); } // // Which mode? // switch (iMode) { case QFT_LIGATURES: case QFT_KERNPAIRS: // // There are no ligatures or kerning pairs for the bitmap fonts, // therefore we return NULL // return ((PVOID) NULL); case QFT_GLYPHSET: // // Find glyphset structure corresponding to this iFace: // pfai = &PFF(hff)->afai[iFace - 1]; return ((PVOID) &pfai->pcp->gset); default: // // Should never get here. // RIP("gdisrv!BmfdQueryFontTree(): unknown iMode\n"); return ((PVOID) NULL); } } /******************************Public*Routine******************************\ * * BOOL bReconnectBmfdFont(FONTFILE *pff) * * * Effects: If the file is marked gone, we try to reconnect and see if we can * use it again. We clear the exception bit so that the system will * be able to use this font again. * * History: * 17-Aug-1994 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/ BOOL bReconnectBmfdFont(FONTFILE *pff) { INT i; PVOID pvView; COUNT cjView; EngAcquireSemaphore(ghsemBMFD); if (pff->fl & FF_EXCEPTION_IN_PAGE_ERROR) { if (!EngMapFontFileFD(pff->iFile, (PULONG*) &pvView, &cjView)) { WARNING("BMFD! can not reconnect this bm font file!!!\n"); EngReleaseSemaphore(ghsemBMFD); return FALSE; } for (i = 0; i < (INT)pff->cFntRes; i++) { pff->afai[i].re.pvResData = (PVOID) ( (BYTE*)pvView + pff->afai[i].re.dpResData ); } // everything is fine again, clear the bit pff->fl &= ~FF_EXCEPTION_IN_PAGE_ERROR; } EngReleaseSemaphore(ghsemBMFD); return TRUE; } /******************************Public*Routine******************************\ * * Routine Name: * * vBmfdScrubGLYPHBITS * * Routine Description: * * This procedure will mask off the last byte of each row so that there * are no pixels set outside the boundary of the glyph. This problem * has been detected in a Bitstream font named ncd0018.fon. * This particular font is in the form of a 32-bit resource. * The problem came to light because the ATI driver relies * on the fact that the glyphs are "scrubbed" and contain no * extraneous bits, even outside the glyph boundary. * * Arguments: * * pGb - a pointer to a GLYPHBITS structure * * Called by: * * BmfdQueryFontData * * Return Value: * * None. * \**************************************************************************/ void vBmfdScrubGLYPHBITS(GLYPHBITS *pGb) { int dp; // number of bytes in each scan int cx; // number of pixels per row BYTE jMask; // mask for last byte of each row; BYTE *pj; // pointer to last byte of row; BYTE *pjLast; // sentinel pointer static BYTE ajMonoMask[8] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; cx = pGb->sizlBitmap.cx; if ( jMask = ajMonoMask[cx & 7] ) { dp = (cx + 7) / 8; pj = pGb->aj + dp - 1; pjLast = pj + dp * pGb->sizlBitmap.cy; for ( ; pj < pjLast; pj += dp ) { *pj &= jMask; } } } /******************************Public*Routine******************************\ * BmfdQueryFontData * * pfo Pointer to a FONTOBJ. * * iMode This is a 32-bit number that must be one of the following * values: * * Allowed ulMode values: * ---------------------- * * QFD_GLYPH -- return glyph metrics only * * QFD_GLYPHANDBITMAP -- return glyph metrics and bitmap * * QFD_GLYPHANDOUTLINE -- return glyph metrics and outline * * QFD_MAXEXTENTS -- return FD_DEVICEMETRICS structure * * QFD_MAXGLYPHBITMAP -- return size of largest glyph AND its metrics * * cData Count of data items in the pvIn buffer. * * pvIn An array of glyph handles. * * pvOut Output buffer. * * Returns: * If mode is QFD_MAXGLYPHBITMAP, then size of glyph metrics plus * largest bitmap is returned. * * Otherwise, if pvOut is NULL, function will return size of the buffer * needed to copy the data requested; else, the function will return the * number of bytes written. * * FD_ERROR is returned if an error occurs. * * History: * 30-Aug-1992 -by- Gilman Wong [gilmanw] * Wrote it. Contructed from pieces of BodinD's original * BmfdQueryGlyphBitmap() and BmfdQueryOutline() functions. \**************************************************************************/ LONG BmfdQueryFontData ( FONTOBJ *pfo, ULONG iMode, HGLYPH hg, GLYPHDATA *pgd, PVOID pv, ULONG cjSize ) { PFONTCONTEXT pfc; LONG cjGlyphData = 0; LONG cjAllData = 0; PCVTFILEHDR pcvtfh; PBYTE pjBitmap; // raw bitmap in the resource file ULONG cxNoSim; // bm width in pels before simulations FWORD sAscent; #ifdef FE_SB // BmfdQueryFontData() PVOID pvDst = NULL; LONG cjGlyphDataNoRotate; #endif // FE_SB // The net connection died on us, but maybe it is alive again: if (!bReconnectBmfdFont(PFF(pfo->iFile))) { WARNING("bmfd!bmfdQueryFontData: this file is gone\n"); return FD_ERROR; } // If pfo->pvProducer is NULL, then we need to open a font context. // if ( pfo->pvProducer == (PVOID) NULL ) pfo->pvProducer = (PVOID) BmfdOpenFontContext(pfo); pfc = PFC(pfo->pvProducer); if ( pfc == (PFONTCONTEXT) NULL ) { WARNING("gdisrv!bmfdQueryFontData(): cannot create font context\n"); return FD_ERROR; } // What mode? switch (iMode) { case QFD_GLYPHANDBITMAP: // // This code is left all inline for better performance. // pcvtfh = &(pfc->pfai->cvtfh); sAscent = pfc->pfai->pifi->fwdWinAscender; pjBitmap = pjRawBitmap(hg, pcvtfh, &pfc->pfai->re, &cxNoSim); #ifdef FE_SB // BmfdQueryFontDate(): Compute size of RASTERGLYPH for ROTATION // // Compute the size of the RASTERGLYPH. ( GLYPHBITS structure size ) // // Compute No Rotated GLYPHBITS size. cjGlyphDataNoRotate = cjGlyphDataSimulated ( pfo, cxNoSim * pfc->ptlScale.x, pcvtfh->cy * pfc->ptlScale.y, (PULONG) NULL, 0L ); // Compute Rotated GLYPHBITS size. switch( pfc->ulRotate ) { case 0L : case 1800L : cjGlyphData = cjGlyphDataNoRotate; break; case 900L : case 2700L : cjGlyphData = cjGlyphDataSimulated ( pfo, cxNoSim * pfc->ptlScale.x, pcvtfh->cy * pfc->ptlScale.y, (PULONG) NULL, pfc->ulRotate ); break; } // // Allocate Buffer for Rotation // if( pfc->ulRotate != 0L && pv != NULL ) { // We have to rotate this bitmap. below here , we keep data in temp Buffer // And will write this data into pv ,when rotate bitmap. // We can't use original pv directly. Because original pv size is computed // for Rotated bitmap. If we use this. it may causes access violation. // hideyukn 08-Feb-1993 // Keep Master pv pvDst = pv; // Allocate New pv pv = (PVOID)EngAllocMem(0, cjGlyphDataNoRotate, 'dfmB'); if( pv == NULL ) { WARNING("BMFD:LocalAlloc for No Rotated bitmap is fail\n"); return( FD_ERROR ); } } else { // This Routine is for at ulRotate != 0 && pv == NULL // // If User want to only GLYPHDATA , We do not do anything for glyphbits // at vFill_RotateGLYPHDATA // // pvDst is only used in case of ulRotate is Non-Zero ; } #else // // Compute the size of the RASTERGLYPH. // cjGlyphData = cjGlyphDataSimulated ( pfo, cxNoSim * pfc->ptlScale.x, pcvtfh->cy * pfc->ptlScale.y, (PULONG) NULL ); #endif #ifdef FE_SB // !!! // !!! Following vComputeSimulatedGLYPHDATA function will set up GLYPHDATA // !!! structure with NO Rotation. If We want to Rotate bitmap , We have to // !!! re-setup this GLYPHDATA structure. Pls look into end of this function. // !!! But No need to ratate bitmap , We don't need to re-set up it. // !!! hideyukn 08-Feb-1993 // !!! #endif // FE_SB // // Fill in the GLYPHDATA portion (metrics) of the RASTERGLYPH. // if ( pgd != (GLYPHDATA *)NULL ) { vComputeSimulatedGLYPHDATA ( pgd, pjBitmap, cxNoSim, pcvtfh->cy, (ULONG)sAscent, pfc->ptlScale.x, pfc->ptlScale.y, pfo ); pgd->hg = hg; } // // Fill in the bitmap portion of the RASTERGLYPH. // if ( pv != NULL ) { if (cxNoSim == 0) { // stolen from ttfd: GLYPHBITS *pgb = (GLYPHBITS *)pv; pgb->ptlOrigin.x = 0; pgb->ptlOrigin.y = -sAscent; pgb->sizlBitmap.cx = 1; // cheating pgb->sizlBitmap.cy = 1; // cheating *((ULONG *)pgb->aj) = 0; // fill in a blank 1x1 dib } else { if (pfc->flStretch & FC_DO_STRETCH) { BYTE ajStretchBuffer[CJ_STRETCH]; if (pfc->flStretch & FC_STRETCH_WIDE) { EngAcquireSemaphore(ghsemBMFD); // need to put try/except here so as to release the semaphore // in case the file disappeares [bodind] #ifndef BMFD_NO_TRY_EXCEPT try { #endif vStretchCvtToBitmap( pv, pjBitmap, cxNoSim , pcvtfh->cy , (ULONG)sAscent , pfc->ajStretchBuffer, pfc->ptlScale.x, pfc->ptlScale.y, pfo->flFontType & (FO_SIM_BOLD | FO_SIM_ITALIC)); #ifndef BMFD_NO_TRY_EXCEPT } except (EXCEPTION_EXECUTE_HANDLER) { WARNING("bmfd! exception while stretching a glyph\n"); vBmfdMarkFontGone( (FONTFILE *)pfc->hff, GetExceptionCode() ); } #endif EngReleaseSemaphore(ghsemBMFD); } else { // we are protected by higher level try/excepts vStretchCvtToBitmap( pv, pjBitmap, cxNoSim , pcvtfh->cy , (ULONG)sAscent , ajStretchBuffer, pfc->ptlScale.x, pfc->ptlScale.y, pfo->flFontType & (FO_SIM_BOLD | FO_SIM_ITALIC)); } } else { switch (pfo->flFontType & (FO_SIM_BOLD | FO_SIM_ITALIC)) { case 0: vCvtToBmp( pv , pgd , pjBitmap , cxNoSim , pcvtfh->cy , (ULONG)sAscent ); break; case FO_SIM_BOLD: vCvtToBoldBmp( pv , pgd , pjBitmap , cxNoSim , pcvtfh->cy , (ULONG)sAscent ); break; case FO_SIM_ITALIC: vCvtToItalicBmp( pv , pgd , pjBitmap , cxNoSim , pcvtfh->cy , (ULONG)sAscent ); break; case (FO_SIM_BOLD | FO_SIM_ITALIC): vCvtToBoldItalicBmp( pv , pgd , pjBitmap , cxNoSim , pcvtfh->cy , (ULONG)sAscent ); break; default: RIP("BMFD!WRONG SIMULATION REQUEST\n"); } } } // Record the pointer to the RASTERGLYPH in the pointer table. if ( pgd != NULL ) { pgd->gdf.pgb = (GLYPHBITS *)pv; } vBmfdScrubGLYPHBITS((GLYPHBITS*)pv); } #ifdef FE_SB // BmfdQueryFontData(): Set up GLYPHDATA and GLYPHBITS for Rotation // Check rotation if( pfc->ulRotate != 0L ) { // Rotate GLYPHDATA and GLYPHBITS // if pv and pvDst is NULL , We only set up GLYPHDATA only // and if pgd is NULL , we only set up pvDst if (pvDst) memset(pvDst, 0, cjSize); vFill_RotateGLYPHDATA( pgd, // GLYPHDATA *pDistinationGlyphData pv, // PVOID SourceGLYPHBITS pvDst, // PVOID DistinationGLYPHBITS pfc->ulRotate // UINT Rotate degree ); // Free GLYPHBITS tenmorary buffer // !!! Now pvDst is Original buffer from GRE. if( pv != NULL ) VFREEMEM( pv ); } #endif // FE_SB return cjGlyphData; case QFD_MAXEXTENTS: // // If buffer NULL, return size. // if ( pv == (PVOID) NULL ) return (sizeof(FD_DEVICEMETRICS)); // // Otherwise, copy the data structure. // else return cjBmfdDeviceMetrics(pfc, (FD_DEVICEMETRICS *) pv); case QFD_GLYPHANDOUTLINE: default: WARNING("gdisrv!BmfdQueryFontData(): unsupported mode\n"); return FD_ERROR; } } /******************************Public*Routine******************************\ * BmfdQueryAdvanceWidths * * * * Queries the advance widths for a range of glyphs. * * * * Sat 16-Jan-1993 22:28:41 -by- Charles Whitmer [chuckwh] * * Wrote it. The code is repeated to avoid multiplies wherever possible. * * The crazy loop unrolling cuts the time of this routine by 25%. * \**************************************************************************/ typedef struct _TYPE2TABLE { USHORT cx; USHORT offData; } TYPE2TABLE; typedef struct _TYPE3TABLE { USHORT cx; USHORT offDataLo; USHORT offDataHi; } TYPE3TABLE; BOOL BmfdQueryAdvanceWidths ( FONTOBJ *pfo, ULONG iMode, HGLYPH *phg, LONG *plWidths, ULONG cGlyphs ) { USHORT *psWidths = (USHORT *) plWidths; // True for the cases we handle. FONTCONTEXT *pfc ; FACEINFO *pfai ; CVTFILEHDR *pcvtfh ; BYTE *pjTable ; USHORT xScale ; USHORT cxExtra ; USHORT cx; if (!bReconnectBmfdFont(PFF(pfo->iFile))) { WARNING("bmfd!bmfdQueryAdvanceWidths: this file is gone\n"); return FD_ERROR; } // If pfo->pvProducer is NULL, then we need to open a font context. // if ( pfo->pvProducer == (PVOID) NULL ) pfo->pvProducer = (PVOID) BmfdOpenFontContext(pfo); pfc = PFC(pfo->pvProducer); if ( pfc == (PFONTCONTEXT) NULL ) { WARNING("bmfd!bmfdQueryAdvanceWidths: cannot create font context\n"); return FD_ERROR; } pfai = pfc->pfai; pcvtfh = &(pfai->cvtfh); pjTable = (BYTE *) pfai->re.pvResData + pcvtfh->dpOffsetTable; xScale = (USHORT) (pfc->ptlScale.x << 4); cxExtra = (pfc->flFontType & FO_SIM_BOLD) ? 16 : 0; if (iMode > QAW_GETEASYWIDTHS) return(GDI_ERROR); // Retrieve widths from type 2 tables. if (pcvtfh->iVersion == 0x00000200) { TYPE2TABLE *p2t = (TYPE2TABLE *) pjTable; if (xScale == 16) { while (cGlyphs > 3) { cx = p2t[phg[0]].cx; psWidths[0] = (cx << 4) + cxExtra; cx = p2t[phg[1]].cx; psWidths[1] = (cx << 4) + cxExtra; cx = p2t[phg[2]].cx; psWidths[2] = (cx << 4) + cxExtra; cx = p2t[phg[3]].cx; psWidths[3] = (cx << 4) + cxExtra; phg += 4; psWidths += 4; cGlyphs -= 4; } while (cGlyphs) { cx = p2t[*phg].cx; *psWidths = (cx << 4) + cxExtra; phg++,psWidths++,cGlyphs--; } } else { while (cGlyphs) { cx = p2t[*phg].cx; *psWidths = (cx * xScale) + cxExtra; phg++,psWidths++,cGlyphs--; } } } // Retrieve widths from type 3 tables. else { TYPE3TABLE *p3t = (TYPE3TABLE *) pjTable; if (xScale == 16) { while (cGlyphs > 3) { cx = p3t[phg[0]].cx; psWidths[0] = (cx << 4) + cxExtra; cx = p3t[phg[1]].cx; psWidths[1] = (cx << 4) + cxExtra; cx = p3t[phg[2]].cx; psWidths[2] = (cx << 4) + cxExtra; cx = p3t[phg[3]].cx; psWidths[3] = (cx << 4) + cxExtra; phg += 4; psWidths += 4; cGlyphs -= 4; } while (cGlyphs) { cx = p3t[*phg].cx; *psWidths = (cx << 4) + cxExtra; phg++,psWidths++,cGlyphs--; } } else { while (cGlyphs) { cx = p3t[*phg].cx; *psWidths = (cx * xScale) + cxExtra; phg++,psWidths++,cGlyphs--; } } } return(TRUE); } /******************************Public*Routine******************************\ * BmfdQueryFontFile * * A function to query per font file information. * * Parameters: * * hff Handle to a font file. * * ulMode This is a 32-bit number that must be one of the following * values: * * Allowed ulMode values: * ---------------------- * * QFF_DESCRIPTION -- copies a UNICODE string in the buffer * that describes the contents of the font file. * * QFF_NUMFACES -- returns number of faces in the font file. * * cjBuf Maximum number of BYTEs to copy into the buffer. The * driver will not copy more than this many BYTEs. * * This should be zero if pulBuf is NULL. * * This parameter is not used in QFF_NUMFACES mode. * * pulBuf Pointer to the buffer to receive the data * If this is NULL, then the required buffer size * is returned as a count of BYTEs. Notice that this * is a PULONG, to enforce 32-bit data alignment. * * This parameter is not used in QFF_NUMFACES mode. * * Returns: * * If mode is QFF_DESCRIPTION, then the number of BYTEs copied into * the buffer is returned by the function. If pulBuf is NULL, * then the required buffer size (as a count of BYTEs) is returned. * * If mode is QFF_NUMFACES, then number of faces in font file is returned. * * FD_ERROR is returned if an error occurs. * * History: * 30-Aug-1992 -by- Gilman Wong [gilmanw] * Added QFF_NUMFACES mode (IFI/DDI merge). * * Fri 20-Mar-1992 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/ LONG BmfdQueryFontFile ( HFF hff, // handle to font file ULONG ulMode, // type of query ULONG cjBuf, // size of buffer (in BYTEs) PULONG pulBuf // return buffer (NULL if requesting size of data) ) { // Verify the HFF. if (hff == HFF_INVALID) { WARNING("bmfd!BmfdQueryFontFile(): invalid HFF\n"); return(FD_ERROR); } // // Which mode?. // switch(ulMode) { case QFF_DESCRIPTION: // // If present, return the description string. // if ( PFF(hff)->cjDescription != 0 ) { // // If there is a buffer, copy the data. // if ( pulBuf != (PULONG) NULL ) { // // Is buffer big enough? // if ( cjBuf < PFF(hff)->cjDescription ) { WARNING("bmfd!BmfdQueryFontFile(): buffer too small for string\n"); return (FD_ERROR); } else { RtlCopyMemory((PVOID) pulBuf, ((PBYTE) PFF(hff)) + PFF(hff)->dpwszDescription, PFF(hff)->cjDescription); } } return (LONG) PFF(hff)->cjDescription; } // // Otherwise, substitute the facename. // else { // // There is no description string associated with the font therefore we // substitue the facename of the first font in the font file. // IFIMETRICS *pifi = PFF(hff)->afai[0].pifi; PWSZ pwszFacename = (PWSZ)((PBYTE) pifi + pifi->dpwszFaceName); ULONG cjFacename = (wcslen(pwszFacename) + 1) * sizeof(WCHAR); // // If there is a buffer, copy to it. // if ( pulBuf != (PULONG) NULL ) { // // Is buffer big enough? // if ( cjBuf < cjFacename ) { WARNING("bmfd!BmfdQueryFontFile(): buffer too small for face\n"); return (FD_ERROR); } else { RtlCopyMemory((PVOID) pulBuf, (PVOID) pwszFacename, cjFacename); } } return ((LONG) cjFacename); } case QFF_NUMFACES: return PFF(hff)->cFntRes; default: WARNING("gdisrv!BmfdQueryFontFile(): unknown mode\n"); return FD_ERROR; } } /******************************Public*Routine******************************\ * cjBmfdDeviceMetrics * * * Effects: * * Warnings: * * History: * 30-Aug-1992 -by- Gilman Wong [gilmanw] * Stole it from BodinD's FdQueryFaceAttr() implementation. \**************************************************************************/ ULONG cjBmfdDeviceMetrics ( PFONTCONTEXT pfc, FD_DEVICEMETRICS *pdevm ) { PIFIMETRICS pifi; UINT xScale = pfc->ptlScale.x; UINT yScale = pfc->ptlScale.y; // compute the accelerator flags for this font // If this is a bitmap font where some of the glyphs have zero widths, // we need to turn off all the accelerator flags if (pfc->pfai->cvtfh.fsFlags & FS_ZERO_WIDTH_GLYPHS) { pdevm->flRealizedType = 0; } else { pdevm->flRealizedType = ( FDM_TYPE_BM_SIDE_CONST | // all char bitmaps have the same cy FDM_TYPE_CONST_BEARINGS | // ac spaces for all chars the same, not 0 necessarilly FDM_TYPE_MAXEXT_EQUAL_BM_SIDE ); // the above flags are set regardless of the possible simulation performed on the face // the remaining two are only set if italicizing has not been done if ( !(pfc->flFontType & FO_SIM_ITALIC) ) { pdevm->flRealizedType |= (FDM_TYPE_ZERO_BEARINGS | FDM_TYPE_CHAR_INC_EQUAL_BM_BASE); } } pifi = pfc->pfai->pifi; #ifdef FE_SB // ROTATION:cjBmfdDeviceMetric(): set direction unit vectors /********************************************************************** Coordinate (0 degree) (90 degree) (180 degree) (270 degree) System |(-) A A | Side | | Base | | | Base Side -----+----->X +------> <------+ <------+ +------> (-) | (+) Base Side | | | Side| | Base |(+) V V Y ***********************************************************************/ switch( pfc->ulRotate ) { case 0L: // the direction unit vectors for all ANSI bitmap fonts are the // same. We do not even have to look to the font context: vLToE(&pdevm->pteBase.x, 1L); vLToE(&pdevm->pteBase.y, 0L); vLToE(&pdevm->pteSide.x, 0L); vLToE(&pdevm->pteSide.y, -1L); // y axis points down pdevm->fxMaxAscender = LTOFX((LONG)pifi->fwdWinAscender * yScale); pdevm->fxMaxDescender = LTOFX((LONG)pifi->fwdWinDescender * yScale ); pdevm->ptlUnderline1.x = 0L; pdevm->ptlUnderline1.y = -(LONG)pifi->fwdUnderscorePosition * yScale; pdevm->ptlStrikeOut.x = (pfc->flFontType & FO_SIM_ITALIC) ? (LONG)pifi->fwdStrikeoutPosition / 2 : 0; pdevm->ptlStrikeOut.y = -(LONG)pifi->fwdStrikeoutPosition * yScale; pdevm->ptlULThickness.x = 0; pdevm->ptlULThickness.y = (LONG)pifi->fwdUnderscoreSize * yScale; pdevm->ptlSOThickness.x = 0; pdevm->ptlSOThickness.y = (LONG)pifi->fwdStrikeoutSize * yScale; break; case 900L: // the direction unit vectors for all ANSI bitmap fonts are the // same. We do not even have to look to the font context: vLToE(&pdevm->pteBase.x, 0L); vLToE(&pdevm->pteBase.y, -1L); vLToE(&pdevm->pteSide.x, -1L); vLToE(&pdevm->pteSide.y, 0L); pdevm->fxMaxAscender = LTOFX((LONG)pifi->fwdWinAscender * yScale); pdevm->fxMaxDescender = LTOFX((LONG)pifi->fwdWinDescender * yScale ); pdevm->ptlUnderline1.x = -(LONG)pifi->fwdUnderscorePosition * yScale; pdevm->ptlUnderline1.y = 0; pdevm->ptlStrikeOut.x = -(LONG)pifi->fwdStrikeoutPosition * yScale; pdevm->ptlStrikeOut.y = (pfc->flFontType & FO_SIM_ITALIC) ? -(LONG)pifi->fwdStrikeoutPosition / 2 : 0; pdevm->ptlULThickness.x = (LONG)pifi->fwdUnderscoreSize * yScale; pdevm->ptlULThickness.y = 0; pdevm->ptlSOThickness.x = (LONG)pifi->fwdStrikeoutSize * yScale; pdevm->ptlSOThickness.y = 0; break; case 1800L: // the direction unit vectors for all ANSI bitmap fonts are the // same. We do not even have to look to the font context: vLToE(&pdevm->pteBase.x, -1L); vLToE(&pdevm->pteBase.y, 0L); vLToE(&pdevm->pteSide.x, 0L); vLToE(&pdevm->pteSide.y, 1L); pdevm->fxMaxAscender = LTOFX((LONG)pifi->fwdWinAscender * yScale); pdevm->fxMaxDescender = LTOFX((LONG)pifi->fwdWinDescender * yScale ); pdevm->ptlUnderline1.x = 0L; pdevm->ptlUnderline1.y = (LONG)pifi->fwdUnderscorePosition * yScale; pdevm->ptlStrikeOut.x = (pfc->flFontType & FO_SIM_ITALIC) ? -(LONG)pifi->fwdStrikeoutPosition / 2 : 0; pdevm->ptlStrikeOut.y = pifi->fwdStrikeoutPosition * yScale; pdevm->ptlULThickness.x = 0; pdevm->ptlULThickness.y = (LONG)pifi->fwdUnderscoreSize * yScale; pdevm->ptlSOThickness.x = 0; pdevm->ptlSOThickness.y = (LONG)pifi->fwdStrikeoutSize * yScale; break; case 2700L: // the direction unit vectors for all ANSI bitmap fonts are the // same. We do not even have to look to the font context: vLToE(&pdevm->pteBase.x, 0L); vLToE(&pdevm->pteBase.y, 1L); vLToE(&pdevm->pteSide.x, 1L); vLToE(&pdevm->pteSide.y, 0L); pdevm->fxMaxAscender = LTOFX((LONG)pifi->fwdWinAscender * yScale); pdevm->fxMaxDescender = LTOFX((LONG)pifi->fwdWinDescender * yScale ); pdevm->ptlUnderline1.x = (LONG)pifi->fwdUnderscorePosition * yScale; pdevm->ptlUnderline1.y = 0L; pdevm->ptlStrikeOut.x = (LONG)pifi->fwdStrikeoutPosition * yScale; pdevm->ptlStrikeOut.y = (pfc->flFontType & FO_SIM_ITALIC) ? (LONG)pifi->fwdStrikeoutPosition / 2 : 0; pdevm->ptlULThickness.x = (LONG)pifi->fwdUnderscoreSize * yScale; pdevm->ptlULThickness.y = 0; pdevm->ptlSOThickness.x = (LONG)pifi->fwdStrikeoutSize * yScale; pdevm->ptlSOThickness.y = 0; break; default: break; } #else // the direction unit vectors for all ANSI bitmap fonts are the // same. We do not even have to look to the font context: vLToE(&pdevm->pteBase.x, 1L); vLToE(&pdevm->pteBase.y, 0L); vLToE(&pdevm->pteSide.x, 0L); vLToE(&pdevm->pteSide.y, -1L); // y axis points down #endif // FE_SB // Set the constant increment for a fixed pitch font. Don't forget to // take into account a bold simulation! pdevm->lD = 0; if ((pifi->flInfo & FM_INFO_CONSTANT_WIDTH) && !(pfc->pfai->cvtfh.fsFlags & FS_ZERO_WIDTH_GLYPHS)) { pdevm->lD = (LONG) pifi->fwdMaxCharInc * xScale; if (pfc->flFontType & FO_SIM_BOLD) pdevm->lD++; } #ifndef FE_SB // cjBmfdDeviceMetric(): // for a bitmap font there is no difference between notional and device // coords, so that the Ascender and Descender can be copied directly // from PIFIMETRICS where these two numbers are in notional coords pdevm->fxMaxAscender = LTOFX((LONG)pifi->fwdWinAscender * yScale); pdevm->fxMaxDescender = LTOFX((LONG)pifi->fwdWinDescender * yScale ); pdevm->ptlUnderline1.x = 0L; pdevm->ptlUnderline1.y = - pifi->fwdUnderscorePosition * yScale; pdevm->ptlStrikeOut.y = - pifi->fwdStrikeoutPosition * yScale; pdevm->ptlStrikeOut.x = (pfc->flFontType & FO_SIM_ITALIC) ? (LONG)pifi->fwdStrikeoutPosition / 2 : 0; pdevm->ptlULThickness.x = 0; pdevm->ptlULThickness.y = (LONG)pifi->fwdUnderscoreSize * yScale; pdevm->ptlSOThickness.x = 0; pdevm->ptlSOThickness.y = (LONG)pifi->fwdStrikeoutSize * yScale; // for a bitmap font there is no difference between notional and device // coords, so that the Ascender and Descender can be copied directly // from PIFIMETRICS where these two numbers are in notional coords pdevm->fxMaxAscender = LTOFX((LONG)pifi->fwdWinAscender * yScale); pdevm->fxMaxDescender = LTOFX((LONG)pifi->fwdWinDescender * yScale ); pdevm->ptlUnderline1.x = 0L; pdevm->ptlUnderline1.y = - pifi->fwdUnderscorePosition * yScale; pdevm->ptlStrikeOut.y = - pifi->fwdStrikeoutPosition * yScale; pdevm->ptlStrikeOut.x = (pfc->flFontType & FO_SIM_ITALIC) ? (LONG)pifi->fwdStrikeoutPosition / 2 : 0; pdevm->ptlULThickness.x = 0; pdevm->ptlULThickness.y = (LONG)pifi->fwdUnderscoreSize * yScale; pdevm->ptlSOThickness.x = 0; pdevm->ptlSOThickness.y = (LONG)pifi->fwdStrikeoutSize * yScale; #endif // FE_SB // max glyph bitmap width in pixels in x direction // does not need to be multiplied by xScale, this has already been taken into // account, see the code in fdfc.c: // cjGlyphMax = // cjGlyphDataSimulated( // pfo, // (ULONG)pcvtfh->usMaxWidth * ptlScale.x, // (ULONG)pcvtfh->cy * ptlScale.y, // &cxMax); // [bodind] pdevm->cxMax = pfc->cxMax; // new fields pdevm->cyMax = pfc->cjGlyphMax / ((pfc->cxMax + 7) / 8); pdevm->cjGlyphMax = pfc->cjGlyphMax; return (sizeof(FD_DEVICEMETRICS)); } #ifdef FE_SB // vFill_RotateGLYPHDATA() #define CJ_DIB8_SCAN(cx) ((((cx) + 7) & ~7) >> 3) /* BIT macro returns non zero ( if bitmap[x,y] is on) or zero (bitmap[x,y] is off). pb : bitmap w : byte count per scan line x : Xth bit in x direction y : scan line x --------------------> y | ******************************* | ******************************* | ******************************* V */ BYTE BitON[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; BYTE BitOFF[8] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe }; #define BIT(pb, w, x, y) (*((PBYTE)(pb) + (w) * (y) + ((x)/8)) & (BitON[(x) & 7])) /******************************************************************************\ * * VOID vFill_RotateGLYPHDATA() * * * History : * * 11-Feb-1992 (Thu) -by- Hideyuki Nagase [hideyukn] * Wrote it. * \******************************************************************************/ VOID vFill_RotateGLYPHDATA ( GLYPHDATA *pDistGlyphData, PVOID SrcGLYPHBITS, PVOID DistGLYPHBITS, UINT RotateDegree ) { GLYPHDATA SrcGlyphData; ULONG ulSrcBitmapSizeX , ulDistBitmapSizeX; ULONG ulSrcBitmapSizeY , ulDistBitmapSizeY; GLYPHBITS *pSrcGlyphBits , *pDistGlyphBits; PBYTE pbSrcBitmap , pbDistBitmap; UINT x , y , k; UINT cjScanSrc , cjScanDist; PBYTE pb; // Now , in this point *pDistGlyphData contain No rotated GLYPHDATA // Copy No rotate GLYPHDATA to Source Area . later we write back changed data to // distination area. // // these field are defined as: // // unit vector along the baseline - fxD, fxA, fxAB // or // unit vector in the ascent direction - fxInkTop, fxInkBottom // // Because baseline direction and ascent direction are rotated // as ulRotate specifies, these fileds should be considered as // rotation independent. // // Init Local value // Set pointer to GLYPHBITS structure pSrcGlyphBits = (GLYPHBITS *)SrcGLYPHBITS; pDistGlyphBits = (GLYPHBITS *)DistGLYPHBITS; if( pDistGlyphData != NULL ) { // Init Source GlyphData SrcGlyphData = *pDistGlyphData; // Record the pointer to GLYPHBITS in GLYPHDATA structure pDistGlyphData->gdf.pgb = pDistGlyphBits; } // Check Rotation switch( RotateDegree ) { case 0L : WARNING("BMFD:vFill_RotateGLYPHDATA():Why come here?\n"); break; case 900L : if( pDistGlyphData != NULL ) { // Setup GLYPHDATA structure // x = y; // y = -x; !!!! HighPart include plus or minus flag pDistGlyphData->ptqD.x = SrcGlyphData.ptqD.y; pDistGlyphData->ptqD.y.HighPart = -(SrcGlyphData.ptqD.x.HighPart); pDistGlyphData->ptqD.y.LowPart = SrcGlyphData.ptqD.x.LowPart; // top = -rihgt ; bottom = -left ; right = bottom ; left = top pDistGlyphData->rclInk.top = -(SrcGlyphData.rclInk.right); pDistGlyphData->rclInk.bottom = -(SrcGlyphData.rclInk.left); pDistGlyphData->rclInk.right = SrcGlyphData.rclInk.bottom; pDistGlyphData->rclInk.left = SrcGlyphData.rclInk.top; } if( pSrcGlyphBits != NULL && pDistGlyphBits != NULL ) { // Get Bitmap size ulSrcBitmapSizeX = pSrcGlyphBits->sizlBitmap.cx; ulSrcBitmapSizeY = pSrcGlyphBits->sizlBitmap.cy; // Get the pointer to Bitmap images pbSrcBitmap = (PBYTE)pSrcGlyphBits->aj; pbDistBitmap = (PBYTE)pDistGlyphBits->aj; // Set Distination Bitmap Size ulDistBitmapSizeX = ulSrcBitmapSizeY; ulDistBitmapSizeY = ulSrcBitmapSizeX; // Setup GLYPHBITS stuff pDistGlyphBits->ptlOrigin.x = pSrcGlyphBits->ptlOrigin.y; pDistGlyphBits->ptlOrigin.y = -(LONG)(ulSrcBitmapSizeX); pDistGlyphBits->sizlBitmap.cx = pSrcGlyphBits->sizlBitmap.cy; pDistGlyphBits->sizlBitmap.cy = pSrcGlyphBits->sizlBitmap.cx; // Rotate bitmap inage cjScanSrc = CJ_DIB8_SCAN( ulSrcBitmapSizeX ); cjScanDist = CJ_DIB8_SCAN( ulDistBitmapSizeX ); // we need to clear the dst buffer because the S3 driver expects // extra stuff on the edges to be zeroed out for ( y = 0; y < ulDistBitmapSizeY ; y++ ) { for ( x= 0 , pb = pbDistBitmap + cjScanDist * y ; x < ulDistBitmapSizeX ; x++ ) { k = x & 7; // k is from 0 to 7; if ( BIT( pbSrcBitmap , cjScanSrc, ulDistBitmapSizeY - y - 1 , x ) ) *pb |= (BitON[ k ] ); else *pb &= (BitOFF[ k ] ); if ( k == 7 ) pb++; } } } break; case 1800L : if( pDistGlyphData != NULL ) { // Setup GLYPHDATA structure // x = -x; !!!! HighPart include plus or minus flag // y = -y; !!!! HighPart include plus or minus flag pDistGlyphData->ptqD.x.HighPart = -(SrcGlyphData.ptqD.x.HighPart); pDistGlyphData->ptqD.x.LowPart = SrcGlyphData.ptqD.x.LowPart; pDistGlyphData->ptqD.y.HighPart = -(SrcGlyphData.ptqD.y.HighPart); pDistGlyphData->ptqD.y.LowPart = SrcGlyphData.ptqD.y.LowPart; // top = -bottom ; bottom = -top ; right = -left ; left = -right pDistGlyphData->rclInk.top = -(SrcGlyphData.rclInk.bottom); pDistGlyphData->rclInk.bottom = -(SrcGlyphData.rclInk.top); pDistGlyphData->rclInk.right = -(SrcGlyphData.rclInk.left); pDistGlyphData->rclInk.left = -(SrcGlyphData.rclInk.right); } if( pSrcGlyphBits != NULL && pDistGlyphBits != NULL ) { // Get Bitmap size ulSrcBitmapSizeX = pSrcGlyphBits->sizlBitmap.cx; ulSrcBitmapSizeY = pSrcGlyphBits->sizlBitmap.cy; // Get the pointer to Bitmap images pbSrcBitmap = (PBYTE)pSrcGlyphBits->aj; pbDistBitmap = (PBYTE)pDistGlyphBits->aj; // Set Distination Bitmap Size ulDistBitmapSizeX = ulSrcBitmapSizeX; ulDistBitmapSizeY = ulSrcBitmapSizeY; // Setup GLYPHBITS stuff pDistGlyphBits->ptlOrigin.x = -(LONG)(ulSrcBitmapSizeX); pDistGlyphBits->ptlOrigin.y = -(LONG)(ulSrcBitmapSizeY + pSrcGlyphBits->ptlOrigin.y); pDistGlyphBits->sizlBitmap.cx = pSrcGlyphBits->sizlBitmap.cx; pDistGlyphBits->sizlBitmap.cy = pSrcGlyphBits->sizlBitmap.cy; // Rotate bitmap inage cjScanSrc = CJ_DIB8_SCAN( ulSrcBitmapSizeX ); cjScanDist = CJ_DIB8_SCAN( ulDistBitmapSizeX ); for ( y = 0; y < ulDistBitmapSizeY ; y++ ) { for ( x = 0 , pb = pbDistBitmap + cjScanDist * y ; x < ulDistBitmapSizeX ; x++ ) { k = x & 7; if ( BIT( pbSrcBitmap, cjScanSrc, ulDistBitmapSizeX - x - 1, ulDistBitmapSizeY - y - 1 ) ) *pb |= (BitON[ k ] ); else *pb &= (BitOFF[ k ] ); if ( k == 7 ) pb++; } } } break; case 2700L : if( pDistGlyphData != NULL ) { // Setup GLYPHDATA structure // x = -y; !!!! HighPart include plus or minus flag // y = x; pDistGlyphData->ptqD.x.HighPart = -(SrcGlyphData.ptqD.y.HighPart); pDistGlyphData->ptqD.x.LowPart = SrcGlyphData.ptqD.y.LowPart; pDistGlyphData->ptqD.y = SrcGlyphData.ptqD.x; // top = left ; bottom = right ; right = -bottom ; left = -top pDistGlyphData->rclInk.top = SrcGlyphData.rclInk.left; pDistGlyphData->rclInk.bottom = SrcGlyphData.rclInk.right; pDistGlyphData->rclInk.right = -(SrcGlyphData.rclInk.bottom); pDistGlyphData->rclInk.left = -(SrcGlyphData.rclInk.top); } if( pSrcGlyphBits != NULL && pDistGlyphBits != NULL ) { // Get Bitmap size ulSrcBitmapSizeX = pSrcGlyphBits->sizlBitmap.cx; ulSrcBitmapSizeY = pSrcGlyphBits->sizlBitmap.cy; // Get the pointer to Bitmap images pbSrcBitmap = (PBYTE)pSrcGlyphBits->aj; pbDistBitmap = (PBYTE)pDistGlyphBits->aj; // Set Distination Bitmap Size ulDistBitmapSizeX = ulSrcBitmapSizeY; ulDistBitmapSizeY = ulSrcBitmapSizeX; // Setup GLYPHBITS stuff pDistGlyphBits->ptlOrigin.x = -(LONG)(ulSrcBitmapSizeY + pSrcGlyphBits->ptlOrigin.y); pDistGlyphBits->ptlOrigin.y = pSrcGlyphBits->ptlOrigin.x; pDistGlyphBits->sizlBitmap.cx = pSrcGlyphBits->sizlBitmap.cy; pDistGlyphBits->sizlBitmap.cy = pSrcGlyphBits->sizlBitmap.cx; // Rotate bitmap inage cjScanSrc = CJ_DIB8_SCAN( ulSrcBitmapSizeX ); cjScanDist = CJ_DIB8_SCAN( ulDistBitmapSizeX ); for ( y = 0; y < ulDistBitmapSizeY ; y++ ) { for ( x = 0 , pb = pbDistBitmap + cjScanDist * y ; x < ulDistBitmapSizeX ; x++ ) { k = x & 7; if ( BIT( pbSrcBitmap, cjScanSrc, y , ulDistBitmapSizeX - x - 1 ) ) *pb |= (BitON[ k ] ); else *pb &= (BitOFF[ k ] ); if ( k == 7 ) pb++; } } } break; default : WARNING("BMFD:vFill_RotateGLYPHDATA():ulRotate is invalid\n"); break; } // end switch } #endif // FE_SB