⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 font.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
 *	CCcs::Compare (pcf,	lfHeight, fMetafile)
 *
 *	@mfunc
 *		Compares this font cache with the font properties of a 
 *      given CHARFORMAT
 *
 *	@rdesc
 *		FALSE iff did not match exactly.
 */
BOOL CCcs::Compare (
	const CCharFormat * const pcf,	//@parm Description of desired logical font
	LONG	lfHeight)		//@parm	lfHeight as calculated with the given HDC
{
	BOOL result;
	TRACEBEGIN(TRCSUBSYSFONT, TRCSCOPEINTERN, "CCcs::Compare");

	result =
			_yCfHeight      == pcf->yHeight &&	// because different mapping modes
			_lf.lfHeight	== lfHeight &&		//  have diff logical coords
        	_lf.lfWeight	== ((pcf->dwEffects & CFE_BOLD) ? FW_BOLD : FW_NORMAL) &&
	        _lf.lfItalic	== ((pcf->dwEffects & CFE_ITALIC) != 0) &&
	        _fStrikeOut == ((pcf->dwEffects & CFE_STRIKEOUT) != 0) &&
			((((pcf->dwEffects & CFE_UNDERLINE) == 0) 
					&& (_bUnderlineType == CFU_UNDERLINENONE))
				|| (((pcf->dwEffects & CFE_UNDERLINE) != 0) 
					&& (_bUnderlineType == pcf->bUnderlineType))) &&
	        _lf.lfCharSet == pcf->bCharSet &&
        	_lf.lfPitchAndFamily == pcf->bPitchAndFamily &&
			((pcf->bInternalEffects & CFEI_RUNISDBCS)
					? _bConvertMode == CM_LOWBYTE : 1);
	// The following call has been known to cause troubles on Win CE
	result = result && !lstrcmp( _lf.lfFaceName, pcf->szFaceName );
	return result;
}

// =========================  WidthCache by jonmat  =========================
/*
 *	CWidthCache::CheckWidth(ch, rlWidth)
 *	
 *	@mfunc
 *		check to see if we have a width for a TCHAR character.
 *
 *	@comm
 *		Used prior to calling FillWidth(). Since FillWidth
 *		may require selecting the map mode and font in the HDC,
 *		checking here first saves time.
 *
 *	@comm
 *		Statistics are maintained to determine when to
 *		expand the cache. The determination is made after a constant
 *		number of calls in order to make calculations faster.
 *
 *	@rdesc
 *		returns TRUE if we have the width of the given TCHAR.
 */
BOOL CWidthCache::CheckWidth (
	const TCHAR ch,  //@parm char, can be Unicode, to check width for.
	LONG &rlWidth )	//@parm the width of the character
{
	TRACEBEGIN(TRCSUBSYSFONT, TRCSCOPEINTERN, "CWidthCache::CheckWidth");

	BOOL	exist;
	INT		i;

	const	CacheEntry * pWidthData = GetEntry ( ch );

	exist = ( ch == pWidthData->ch		// Have we fetched the width?
				&& pWidthData->width );	//  only because we may have ch == 0.

	if( exist )
	{
		rlWidth = pWidthData->width;
	}
	else
	{
		rlWidth = 0;
	}

	i = CACHE_SWITCH(ch);				// Update statistics
	if ( !_fMaxPerformance[i] )			//  if we have not grown to the max...
	{
		_accesses[i]++;
		if ( !exist )					// Only interesting on collision.
		{
			if ( 0 == pWidthData->width )// Test width not ch, 0 is valid ch.
			{
				_cacheUsed[i]++;		// Used another entry.
				AssertSz( _cacheUsed[i] <= _cacheSize[i]+1, "huh?");
			}
			else
				_collisions[i]++;		// We had a collision.

			if ( _accesses[i] >= PERFCHECKEPOCH )
				CheckPerformance(i);	// After some history, tune cache.
		}
	}
#ifdef DEBUG							// Continue to monitor performance
	else
	{
		_accesses[i]++;
		if ( !exist )					// Only interesting on collision.
		{
			if ( 0 == pWidthData->width )// Test width not ch, 0 is valid ch.
			{
				_cacheUsed[i]++;		// Used another entry.
				AssertSz( _cacheUsed[i] <= _cacheSize[i]+1, "huh?");
			}
			else
				_collisions[i]++;		// We had a collision.
		}

		if ( _accesses[i] > PERFCHECKEPOCH )
		{
			_accesses[i] = 0;
			_collisions[i] = 0;
		}
	}
#endif

	return exist;
}

/*
 *	CWidthCache::CheckPerformance(i)
 *	
 *	@mfunc
 *		check performance and increase cache size if deemed necessary.
 *
 *	@devnote
 *		To calculate 25% collision rate, we make use of the fact that
 *		we are only called once every 64 accesses. The inequality is 
 *		100 * collisions / accesses >= 25. By converting from 100ths to
 *		8ths, the ineqaulity becomes (collisions << 3) / accesses >= 2.
 *		Substituting 64 for accesses, this becomes (collisions >> 3) >= 2.
 */
void CWidthCache::CheckPerformance(
	INT i ) //@parm which cache to check.
{
	TRACEBEGIN(TRCSUBSYSFONT, TRCSCOPEINTERN, "CWidthCache::CheckPerformance");

	if ( _fMaxPerformance[i] )			// Exit if already grown to our max.
		return;

	if (								// Grow the cache when
										//  cacheSize > 0 && 75% utilized,
			(  _cacheSize[i] > DEFAULTCACHESIZE &&
			( (_cacheSize[i] >> 1) + (_cacheSize[i] >> 2)) < _cacheUsed[i])
										//  or approx 25% collision rate.
		||  ( _collisions[i] >> COLLISION_SHIFT ) >= 2 )
	{
		GrowCache( &_pWidthCache[i], &_cacheSize[i], &_cacheUsed[i] );
	}
	_collisions[i]	= 0;				// This prevents wraps but makes
	_accesses[i]	= 0;				//  calc a local rate, not global.
										
										// Note if we've max'ed out.
	if ( _cacheSize[i] >= maxCacheSize[i] )
		_fMaxPerformance[i] = TRUE;

	AssertSz( _cacheSize[i] <= maxCacheSize[i], "max must be 2^n-1");
	AssertSz( _cacheUsed[i] <= _cacheSize[i]+1, "huh?");
}

/*
 *	CWidthCache::GrowCache(ppWidthCache, pCacheSize, pCacheUsed)
 *	
 *	@mfunc
 *		Exponentially expand the size of the cache.
 *
 *	@comm
 *		The cache size must be of the form 2^n as we use a
 *		logical & to get the hash MOD by storing 2^n-1 as
 *		the size and using this as the modulo.
 *
 *	@rdesc
 *		Returns TRUE if we were able to allocate the new cache.
 *		All in params are also out params.
 *		
 */
BOOL CWidthCache::GrowCache(
	CacheEntry **ppWidthCache,	//@parm cache
	INT *		pCacheSize,		//@parm cache's respective size.
	INT *		pCacheUsed)		//@parm cache's respective utilization.
{
	TRACEBEGIN(TRCSUBSYSFONT, TRCSCOPEINTERN, "CWidthCache::GrowCache");

	CacheEntry		*pNewWidthCache, *pOldWidthCache, *pWidthData;
	INT 			j, newCacheSize, newCacheUsed;
	TCHAR			ch;
	UINT uT;
	
	j = *pCacheSize;						// Allocate cache of 2^n.
	newCacheSize = max ( INITIALCACHESIZE, (j << 1) + 1);
	if (newCacheSize + 1 < newCacheSize || FAILED(UIntMult(sizeof(CacheEntry), newCacheSize + 1, &uT)))
		return FALSE;
	pNewWidthCache = (CacheEntry *)
			PvAlloc( uT, GMEM_ZEROINIT);

	if ( pNewWidthCache )
	{
		newCacheUsed = 0;
		*pCacheSize = newCacheSize;			// Update out params.
		pOldWidthCache = *ppWidthCache;
		*ppWidthCache = pNewWidthCache;
		for (; j >= 0; j--)					// Move old cache info to new.
		{
			ch = pOldWidthCache[j].ch;
			if ( ch )
			{
				pWidthData			= &pNewWidthCache [ch & newCacheSize];
				if ( 0 == pWidthData->ch )
					newCacheUsed++;			// Used another entry.
				pWidthData->ch		= ch;
				pWidthData->width	= pOldWidthCache[j].width;
			}
		}
		*pCacheUsed = newCacheUsed;			// Update out param.

											// Free old cache.
              											
		if (   pOldWidthCache <  &_defaultWidthCache[0][0]
			|| pOldWidthCache > &_defaultWidthCache[TOTALCACHES-1][(DEFAULTCACHESIZE+1)-1])
			//-1 on _defaultWidthCache indexes because of 0 based array.
		{
			FreePv(pOldWidthCache);
		}
	}

	return NULL != pNewWidthCache;
}

/*
 *	CWidthCache::FillWidth(hdc, ch, xOverhang, rlWidth)
 *	
 *	@mfunc
 *		Call GetCharWidth() to obtain the width of the given char.
 *
 *	@comm
 *		The HDC must be setup with the mapping mode and proper font
 *		selected *before* calling this routine.
 *
 *	@rdesc
 *		Returns TRUE if we were able to obtain the widths.
 *		
 */
BOOL CWidthCache::FillWidth (
	HDC			hdc,		//@parm Current HDC we want font info for.
	const TCHAR	ch,			//@parm Char to obtain width for.
	const SHORT xOverhang,	//@parm Equivalent to GetTextMetrics() tmOverhang.
	LONG &		rlWidth,	//@parm Width of character
	UINT		uiCodePage,	//@parm code page for text	
	BOOL		fANSI,		//@parm indicates font needs to use ANSI call.
	INT			iDefWidth,	//@parm Default width to use if font calc's zero
							//width. (Handles Win95 problem).
	INT			iDBCDefWidth,	//@parm Default width for DBC to use 
								// Handles Win95 Trad Chinese problem.
	BOOL		fFixPitch)		//@parm fix pitch font for DBC to use 
								// Handles Win95 Trad Chinese problem.
{
	TRACEBEGIN(TRCSUBSYSFONT, TRCSCOPEINTERN, "CWidthCache::FillWidth");

	char	ansiChar[2] = {0};
	INT		numOfDBCS = 0;
	CacheEntry * pWidthData = GetEntry ( ch );

	(void) W32->REGetCharWidth( hdc, ch, &pWidthData->width, uiCodePage );

#if 0
	// REVIEW  May not need codepage.
	// TODO

	if (!fANSI && uiCodePage != SYMBOL_CODEPAGE)
		(void) W32->REGetCharWidth( hdc, ch, &pWidthData->width, uiCodePage );
	else
	{
		WORD wDBCS = ch;
		(void) GetCharWidthA( hdc, wDBCS, wDBCS, &pWidthData->width );				
	}

	// Is this needed ????
	// fAnsi case, SYMBOL_CHARSET, or GetCharWidthW failed: try GetCharWidthA 
	if (!fRes || 0 == pWidthData->width)
	{
		if(uiCodePage != SYMBOL_CODEPAGE)
		{
			// Try to convert string
			numOfDBCS = WideCharToMultiByte( uiCodePage, 0, &ch, 1, 
				ansiChar, 2, NULL, NULL);

			if (2 == numOfDBCS)
				wDBCS = (BYTE)ansiChar[0] << 8 | (BYTE)ansiChar[1];

			else if (numOfDBCS)
				wDBCS = (BYTE)ansiChar[0];
		}
		fRes = GetCharWidthA( hdc, wDBCS, wDBCS, &pWidthData->width );				
	}
#endif

	pWidthData->ch = ch;
//	pWidthData->width	-= xOverhang;		// Don't need since we use
											//  GetTextExtentPoint32()
	if (0 >= pWidthData->width)
	{
		// Sometimes GetCharWidth will return a zero length for small
		// characters. When this happens we will use the default width
		// for the font if that is non-zero otherwise we just us 1 because
		// this is the smallest valid value.

		// This code can also be triggered if the overhang is bugger than the
		// width returned by the OS call to get the character width.
		
		// under Win95 Trad. Chinese, there is a bug in the font.
		// It is returning a width of 0 for a few characters (Eg 0x09F8D, 0x81E8)
		// In such case, we need to use 2 * iDefWidth since these are DBCS
		if (0 == iDefWidth)
			pWidthData->width = 1;
		else
			pWidthData->width = (numOfDBCS == 2) ? 
				(iDBCDefWidth ? iDBCDefWidth : 2 * iDefWidth) : iDefWidth;
	}

	rlWidth = pWidthData->width;
	return TRUE;
}

/*
 *	CWidthCache::GetWidth(ch)
 *	
 *	@mfunc
 *		get the width (A+B+C) for the given character.
 *	@comm
 *		we've already called GetCharWidth() at this point.
 *	@rdesc
 *		the width.
 */
INT CWidthCache::GetWidth (
	const TCHAR ch )//@parm char, can be Unicode, to check width for.
{
	TRACEBEGIN(TRCSUBSYSFONT, TRCSCOPEINTERN, "CWidthCache::GetWidth");

	const CacheEntry * pWidthData = GetEntry ( ch );

	AssertSz( pWidthData->ch == ch, "Table not filled in?" );

	return pWidthData->width;
}

/*
 *	CWidthCache::Free()
 *	
 *	@mfunc
 *		Free any dynamic memory allocated by the width cache and prepare
 *		it to be recycled.
 *		
 */
VOID CWidthCache::Free()
{
	TRACEBEGIN(TRCSUBSYSFONT, TRCSCOPEINTERN, "CWidthCache::Free");

	INT i;

	for (i = 0; i < TOTALCACHES; i++ )
	{
		_fMaxPerformance[i] = FALSE;
		_cacheSize[i]		= DEFAULTCACHESIZE;
		_cacheUsed[i]		= 0;
		_collisions[i]		= 0;
		_accesses[i]		= 0;
		if ( _pWidthCache[i] != &_defaultWidthCache[i][0] )
		{
			FreePv(_pWidthCache[i]);
			_pWidthCache[i] = &_defaultWidthCache[i][0];
		}	
		ZeroMemory(_pWidthCache[i], sizeof(CacheEntry)*(DEFAULTCACHESIZE + 1));
	}
}

/*
 *	CWidthCache::CWidthCache()
 *	
 *	@mfunc
 *		Point the caches to the defaults.
 *		
 */
CWidthCache::CWidthCache()
{
	TRACEBEGIN(TRCSUBSYSFONT, TRCSCOPEINTERN, "CWidthCache::CWidthCache");

	INT i;

	for (i = 0; i < TOTALCACHES; i++ )
	{
		_pWidthCache[i] = &_defaultWidthCache[i][0];
	}
}

/*
 *	CWidthCache::~CWidthCache()
 *	
 *	@mfunc
 *		Free any allocated caches.
 *		
 */
CWidthCache::~CWidthCache()
{
	TRACEBEGIN(TRCSUBSYSFONT, TRCSCOPEINTERN, "CWidthCache::~CWidthCache");


	INT i;

	for (i = 0; i < TOTALCACHES; i++ )
	{
		if (_pWidthCache[i] != &_defaultWidthCache[i][0])
			FreePv(_pWidthCache[i]);
	}
}

#if 0 // unused
/*
 *	INT CheckDBChar ( UINT uiCodePage, WCHAR wChar, char *pAnsiChar)
 *	
 *	@func
 *		Determine if the input wChar is converted to a DBC or SBC
 *
 *	@comm
 *		Called when we need to determine the char width and when we render 
 *		the char.  This is mainly used for determining if the Bullet char (0xb7)
 *		has a DBC equivalent.
 *
 *	@rdesc
 *		return 2 if DBCS, otherwise return 0. Also, pAnsiChar contains the DBCS.
 *		
 */
INT	CheckDBChar ( UINT uiCodePage, WCHAR wChar, char *pAnsiChar)
{
	WORD wDBCS=0;
	
	// Convert string	
	if ( uiCodePage )	
		// check if we have a DBC bullet for this codepage		
		wDBCS = WideCharToMultiByte( uiCodePage, 0, &wChar, 1, 		
			pAnsiChar, 2, NULL, NULL);

	if ( 2 != wDBCS )
		*pAnsiChar = (CHAR)wChar;

	return wDBCS;
}
#endif



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -