win32font.cpp

来自「这是VCF框架的代码」· C++ 代码 · 共 1,154 行 · 第 1/2 页

CPP
1,154
字号
//Win32Font.cpp/*Copyright 2000-2004 The VCF Project.Please see License.txt in the top level directorywhere you installed the VCF.*/#include "vcf/GraphicsKit/GraphicsKit.h"#include "vcf/GraphicsKit/GraphicsKitPrivate.h"using namespace VCF;Win32Font::Win32Font( const String& fontName ):	font_(NULL),	pointSize_(-1.0),	fontName_(fontName),	logFont_(NULL),	tm_(NULL),	oldDPI_(0){	HDC dc = GetDC( ::GetDesktopWindow() ); // gets screen DC	oldDPI_ = GetDeviceCaps( dc, LOGPIXELSY);	ReleaseDC( ::GetDesktopWindow(), dc );	init();}Win32Font::Win32Font( const String& fontName, const double& pointSize ):	font_(NULL),	pointSize_(pointSize),	fontName_(fontName),	logFont_(NULL),	tm_(NULL),	oldDPI_(0){	HDC dc = GetDC( ::GetDesktopWindow() ); // gets screen DC	oldDPI_ = GetDeviceCaps( dc, LOGPIXELSY);	ReleaseDC( ::GetDesktopWindow(), dc );	init();}Win32Font::~Win32Font(){	Win32FontManager::removeFont( this );	//fontName_ = "";	if ( System::isUnicodeEnabled() ) {		delete (LOGFONTW*)logFont_;		delete (TEXTMETRICW*)tm_;	}	else {		delete (LOGFONTA*)logFont_;		delete (TEXTMETRICA*)tm_;	}}void Win32Font::init(){	if ( System::isUnicodeEnabled() ) {		logFont_ = new LOGFONTW;		memset( logFont_, 0, sizeof(LOGFONTW) );		tm_ = new TEXTMETRICW;		memset( tm_, 0, sizeof(TEXTMETRICW) );	}	else {		logFont_ = new LOGFONTA;		memset( logFont_, 0, sizeof(LOGFONTA) );		tm_ = new TEXTMETRICA;		memset( tm_, 0, sizeof(TEXTMETRICA) );	}	int fontHeight = 0;	//ANSI_VAR_FONT produces bold text on WinME. Changed to DEFAULT_GUI_FONT, which	//gives same appearrance on WinXP as ANSI_VAR_FONT. dougtinkham	//Unfortunately DEFAULT_GUI_FONT looks like shit on Win2k :( 	//we'll check here to see the OS version and then base the decision on that	//WinMe = DEFAULT_GUI_FONT. But Win98, Win2K, WinXP = ANSI_VAR_FONT. JC (aka ddiego)	HFONT defFont = NULL;		static OSVERSIONINFO osVersion = {0};	if ( 0 == osVersion.dwOSVersionInfoSize ) {		osVersion.dwOSVersionInfoSize = sizeof(osVersion);		::GetVersionEx( &osVersion );	}			if ( VER_PLATFORM_WIN32_NT == osVersion.dwPlatformId ) {		if ( (osVersion.dwMinorVersion >= 1) && (osVersion.dwMinorVersion != 51) ) { //Windows XP or better			/*****************************************************			*			*			*NOTE THIS WELL!!!!			*If we do not use DEFAULT_GUI_FONT, we get a rather ugly			*aliased font that looks like crap. This is on:			*OS Name	Microsoft Windows XP Professional			*Version	5.1.2600 Service Pack 2 Build 2600			*Hardware Abstraction Layer	Version = "5.1.2600.2180 (xpsp_sp2_rtm.040803-2158)"			*			*So to sum up - if we change this ANSI_VAR_FONT then it looks ugly,			*if we use DEFAULT_GUI_FONT it looks much nicer.			*			*JC			******************************************************/			defFont = (HFONT)GetStockObject( DEFAULT_GUI_FONT );		}		else { //Windows 2k or worse			defFont = (HFONT)GetStockObject( ANSI_VAR_FONT );		}	}	else { //Windows 9x		if ( 90 == osVersion.dwMinorVersion ) { //Windows ME			defFont = (HFONT)GetStockObject( DEFAULT_GUI_FONT );		}		else { //Windows 98			defFont = (HFONT)GetStockObject( ANSI_VAR_FONT );		}	}		//defFont = NULL;	if ( NULL != defFont ){		if ( System::isUnicodeEnabled() ) {			LOGFONTW tmpLogFont = {0};			GetObjectW( defFont, sizeof(LOGFONTW), &tmpLogFont );			memcpy( logFont_, &tmpLogFont, sizeof(LOGFONTW));		}		else {			LOGFONTA tmpLogFont = {0};			GetObjectA( defFont, sizeof(LOGFONTA), &tmpLogFont );			memcpy( logFont_, &tmpLogFont, sizeof(LOGFONTA));		}	}	else {		if ( System::isUnicodeEnabled() ) {			LOGFONTW& tmpLF = *((LOGFONTW*)logFont_);			tmpLF.lfCharSet = ANSI_CHARSET;//DEFAULT_CHARSET might be better ?			tmpLF.lfClipPrecision = CLIP_DEFAULT_PRECIS;			tmpLF.lfEscapement = 0;			tmpLF.lfItalic = FALSE;			tmpLF.lfOrientation = 0;			tmpLF.lfOutPrecision = OUT_DEFAULT_PRECIS;			tmpLF.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;			tmpLF.lfQuality = DEFAULT_QUALITY;			tmpLF.lfStrikeOut = FALSE;			tmpLF.lfUnderline = FALSE;			tmpLF.lfWeight = FW_NORMAL;			tmpLF.lfWidth = 0;//let font mapper choose closest match			fontHeight = tmpLF.lfHeight;		}		else{			LOGFONTA& tmpLF = *((LOGFONTA*)logFont_);			tmpLF.lfCharSet = ANSI_CHARSET;//DEFAULT_CHARSET might be better ?			tmpLF.lfClipPrecision = CLIP_DEFAULT_PRECIS;			tmpLF.lfEscapement = 0;			tmpLF.lfItalic = FALSE;			tmpLF.lfOrientation = 0;			tmpLF.lfOutPrecision = OUT_DEFAULT_PRECIS;			tmpLF.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;			tmpLF.lfQuality = DEFAULT_QUALITY;			tmpLF.lfStrikeOut = FALSE;			tmpLF.lfUnderline = FALSE;			tmpLF.lfWeight = FW_NORMAL;			tmpLF.lfWidth = 0;//let font mapper choose closest match			fontHeight = tmpLF.lfHeight;		}	}	if ( System::isUnicodeEnabled() ) {		fontHeight = ((LOGFONTW*)logFont_)->lfHeight;	}	else{		fontHeight = ((LOGFONTA*)logFont_)->lfHeight;	}	bool releaseDC = true;	HDC dc = NULL;	if ( NULL != font_ ) {		if ( NULL != font_->getGraphicsContext() ) {			dc = (HDC) font_->getGraphicsContext()->getPeer()->getContextID();			if ( NULL != dc ) {				releaseDC = false;			}		}	}	if ( NULL == dc ) {		dc = GetDC( ::GetDesktopWindow() ); // gets screen DC	}		if ( pointSize_ > 0.0 ) {		fontHeight = -MulDiv( pointSize_, GetDeviceCaps( dc, LOGPIXELSY), 72 );	}	if ( releaseDC ) {		ReleaseDC( ::GetDesktopWindow(), dc );	}	if ( System::isUnicodeEnabled() ) {		LOGFONTW& tmpLF = *((LOGFONTW*)logFont_);		tmpLF.lfHeight = fontHeight;		if ( fontName_.empty() ) {			fontName_.append( tmpLF.lfFaceName, LF_FACESIZE );		}		else {			memset( ((LOGFONTW*)logFont_)->lfFaceName, 0, LF_FACESIZE*sizeof(VCFChar) );			fontName_.copy( tmpLF.lfFaceName, minVal<int>( fontName_.size(), LF_FACESIZE) );		}	}	else {		LOGFONTA& tmpLF = *((LOGFONTA*)logFont_);		tmpLF.lfHeight = fontHeight;		if ( fontName_.empty() ) {			fontName_.append( tmpLF.lfFaceName, LF_FACESIZE );		}		else {			AnsiString tmpFntName = fontName_;			memset( ((LOGFONTA*)logFont_)->lfFaceName, 0, LF_FACESIZE*sizeof(char) );			tmpFntName.copy( tmpLF.lfFaceName, minVal<int>( tmpFntName.size(), LF_FACESIZE) );		}	}	updateTextMetrics();	Win32FontManager::initializeFont( this );}OSHandleID Win32Font::getFontHandleID(){	return (OSHandleID)logFont_;}void Win32Font::updateTextMetrics(){	bool releaseDC = true;	HDC dc = NULL;	if ( NULL != font_ ) {		if ( NULL != font_->getGraphicsContext() ) {			dc = (HDC) font_->getGraphicsContext()->getPeer()->getContextID();			if ( NULL != dc ) {				releaseDC = false;			}		}	}	if ( NULL == dc ) {		dc = GetDC( ::GetDesktopWindow() ); // gets screen DC	}	int dcs = ::SaveDC( dc );	HFONT tmpFont = NULL;	HFONT oldFont = NULL;	if ( System::isUnicodeEnabled() ) {		tmpFont = CreateFontIndirectW( (LOGFONTW*)logFont_ );		oldFont = (HFONT)SelectObject( dc, tmpFont );		memset( tm_, 0, sizeof(TEXTMETRICW) );		GetTextMetricsW( dc, (TEXTMETRICW*)tm_ );	}	else {		tmpFont = CreateFontIndirectA( (LOGFONTA*)logFont_ );		oldFont = (HFONT)SelectObject( dc, tmpFont );		memset( tm_, 0, sizeof(TEXTMETRICA) );		GetTextMetricsA( dc, (TEXTMETRICA*)tm_ );	}	::RestoreDC( dc, dcs );	SelectObject( dc, oldFont );	DeleteObject( tmpFont );	if ( releaseDC ) {		ReleaseDC( ::GetDesktopWindow(), dc );	}}bool Win32Font::isTrueType(){	bool result = false;	if ( System::isUnicodeEnabled() ) {		if ( (((TEXTMETRICW*)tm_)->tmPitchAndFamily & TMPF_TRUETYPE) != 0 ){			result = true;		}	}	else {		if ( (((TEXTMETRICA*)tm_)->tmPitchAndFamily & TMPF_TRUETYPE) != 0 ){			result = true;		}	}	return result;}double Win32Font::getPointSize(){	bool releaseDC = true;	HDC dc = NULL;	//this gets a HDC either from the GraphicsContext that is associated 	// to this font ( i.e. 'owning' this font as it would always be the 	// case for printing ), or from the desktop window.	if ( NULL != font_ ) {		if ( NULL != font_->getGraphicsContext() ) {			//look at win32Ctx if we are having problems in the assertions below			//Win32Context* win32Ctx = (Win32Context*)font_->getGraphicsContext()->getPeer();			dc = (HDC) font_->getGraphicsContext()->getPeer()->getContextID();			if ( NULL != dc ) {				releaseDC = false;			}		}	}	if ( NULL == dc ) {	  dc = GetDC( ::GetDesktopWindow() ); // gets screen DC	}		if ( NULL == dc ) {		//damn! We are well and truly screwed at this point!		DWORD err = ::GetLastError();		String msg = "\nNULL dc in Win32Font::getPointSize() - need to fix this!!!!\n\t";		msg +=  VCFWin32::Win32Utils::getErrorString(err) + "\n";				StringUtils::trace( MAKE_ERROR_MSG_2(msg) );				//this assert stays in  - we should NEVER, EVER, EVER have a NULL HDC at this point.		//this would indicate the presence of unspeakable evil, and we should all run for		//cover if this is the case		VCF_ASSERT( dc != NULL );  	}	double ppi = (double)GetDeviceCaps( dc, LOGPIXELSY);	if ( ((int)ppi) <= 0 ) {		DWORD err = ::GetLastError();		String msg = "\nppi <= 0 in Win32Font::getPointSize() - need to fix this!!!!\n\t";		msg +=  VCFWin32::Win32Utils::getErrorString(err) + "\n";				StringUtils::trace( MAKE_ERROR_MSG_2(msg) );			/**		The asserts will stay in here for the time being because we should NEVER 		EVER be getting them, and if we are it's a sympomatic problem of something else		*/		VCF_ASSERT( ((int)ppi) > 0 ); 	}	int lfHeight = 0;	if ( System::isUnicodeEnabled() ) {		lfHeight = ((LOGFONTW*)logFont_)->lfHeight;	}	else {		lfHeight = ((LOGFONTA*)logFont_)->lfHeight;	}	if ( lfHeight == 0 ) {		DWORD err = ::GetLastError();		String msg = "\nlfHeight == 0 in Win32Font::getPointSize() - need to fix this!!!!\n\t";		msg +=  VCFWin32::Win32Utils::getErrorString(err) + "\n";				StringUtils::trace( MAKE_ERROR_MSG_2(msg) );		VCF_ASSERT( lfHeight != 0 ); 	}	/*	JC I took these out - while I understand the need for a workaround here	we don't want to be doing this - ppi of 0 or a lfHeight of 0 is BAD BAD BAD	and we need to fix the problem(s) that may be causing them.	if (ppi == 0.0){		ppi = 96.0;	}	if (lfHeight == 0) {		lfHeight=1;	}	*/	double result = fabs( ((double)lfHeight / ppi) * 72.0 );	if ( GetDeviceCaps( dc, LOGPIXELSY) != this->oldDPI_ ) {		result = result * ( ppi / oldDPI_ );		oldDPI_ = GetDeviceCaps( dc, LOGPIXELSY);	}	// releases the device context if it is not the one associated to the font.	if ( releaseDC ) {		ReleaseDC( ::GetDesktopWindow(), dc );	}	return result;}void Win32Font::setPointSize( const double pointSize ){	bool releaseDC = true;	HDC dc = NULL;	if ( NULL != font_ ) {		if ( NULL != font_->getGraphicsContext() ) {			dc = (HDC) font_->getGraphicsContext()->getPeer()->getContextID();			if ( NULL != dc ) {				releaseDC = false;			}		}	}	if ( NULL == dc ) {		dc = GetDC( ::GetDesktopWindow() ); // gets screen DC	}	double ppi = (double)GetDeviceCaps( dc, LOGPIXELSY);	long lfHeight = (pointSize / 72) * ppi;	if ( releaseDC ) {		ReleaseDC( ::GetDesktopWindow(), dc );	}		bool needsUpdate = false;	if ( System::isUnicodeEnabled() ) {		needsUpdate = (lfHeight != ((LOGFONTW*)logFont_)->lfHeight);	}	else {		needsUpdate = (lfHeight != ((LOGFONTA*)logFont_)->lfHeight);	}	if ( true == needsUpdate ) {		Win32FontManager::removeFont( this );	}	if ( isTrueType() ) {		lfHeight = -lfHeight;	}	if ( System::isUnicodeEnabled() ) {		((LOGFONTW*)logFont_)->lfHeight = lfHeight;		((LOGFONTW*)logFont_)->lfWidth = 0; //let font mapper choose closest match	}	else {		((LOGFONTA*)logFont_)->lfHeight = lfHeight;		((LOGFONTA*)logFont_)->lfWidth = 0; //let font mapper choose closest match	}	if ( true == needsUpdate ) {		updateTextMetrics();		Win32FontManager::initializeFont( this );	}}double Win32Font::getPixelSize(){	double result = 0.0;	if ( System::isUnicodeEnabled() ) {		result = abs( ((LOGFONTW*)logFont_)->lfHeight );	}	else {		result = abs( ((LOGFONTA*)logFont_)->lfHeight );	}	return result;}void Win32Font::setPixelSize( const double pixelSize ){	bool needsUpdate = false;	double pixSize = pixelSize;	if ( System::isUnicodeEnabled() ) {		needsUpdate = (pixelSize != ((LOGFONTW*)logFont_)->lfHeight);	}	else {		needsUpdate = (pixelSize != ((LOGFONTA*)logFont_)->lfHeight);	}	if ( true == needsUpdate ) {		Win32FontManager::removeFont( this );	}	int lfHeight = pixSize;	if ( isTrueType() ) {		if ( !(lfHeight < 0) ) { //if it's NOT negative, then flip it o negative!			lfHeight = -lfHeight;		}	}	if ( System::isUnicodeEnabled() ) {		((LOGFONTW*)logFont_)->lfHeight = lfHeight;		((LOGFONTW*)logFont_)->lfWidth = 0; //let font mapper choose closest match	}	else {		((LOGFONTA*)logFont_)->lfHeight = lfHeight;		((LOGFONTA*)logFont_)->lfWidth = 0; //let font mapper choose closest match	}	if ( true == needsUpdate ) {		updateTextMetrics();		Win32FontManager::initializeFont( this );	}}void Win32Font::setBold( const bool& bold ){	DWORD style = bold ? FW_BOLD : FW_NORMAL;	bool needsUpdate = false;	if ( System::isUnicodeEnabled() ) {		needsUpdate = (style != ((LOGFONTW*)logFont_)->lfWeight);	}	else {		needsUpdate = (style != ((LOGFONTA*)logFont_)->lfWeight);	}	if ( true == needsUpdate ) {		Win32FontManager::removeFont( this );	}	if ( System::isUnicodeEnabled() ) {		((LOGFONTW*)logFont_)->lfWeight = style;	}	else {		((LOGFONTA*)logFont_)->lfWeight = style;	}	if ( true == needsUpdate ) {		updateTextMetrics();		Win32FontManager::initializeFont( this );	}}bool Win32Font::getBold(){	bool result = false;	if ( System::isUnicodeEnabled() ) {		result = (((LOGFONTW*)logFont_)->lfWeight == FW_NORMAL) ? false : true;	}	else {		result = (((LOGFONTA*)logFont_)->lfWeight == FW_NORMAL) ? false : true;	}

⌨️ 快捷键说明

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