Exemple #1
0
bool C4FontLoader::InitFont(CStdFont &rFont, const char *szFontName, FontType eType, int32_t iSize, C4GroupSet *pGfxGroups, bool fDoShadow)
	{
	// safety
	if (!szFontName || !*szFontName)
		{
		LogFatal(LoadResStr("IDS_ERR_INITFONTS"));
		return false;
		}
	// get font to load
	// pFontDefs may be NULL if no fonts are loaded; but then iFontDefCount is zero as well
	// the function must not be aborted, because a standard windows font may be loaded
	std::vector<C4FontDef>::iterator pFontDefC = FontDefs.begin(), pFontDef = FontDefs.end();
	while (pFontDefC != FontDefs.end())
		{
		// check font
		if (pFontDefC->Name == szFontName)
			{
			int32_t iSizeDiff = Abs(pFontDefC->iSize - iSize);
			// better match than last font?
			if (pFontDef == FontDefs.end() || Abs(pFontDef->iSize - iSize) >= iSizeDiff)
				pFontDef = pFontDefC;
			}
		// check next one
		++pFontDefC;
		}
	// if def has not been found, use the def as font name
	// determine font def string
	const char *szFontString = szFontName;
	// special: Fonts without shadow are always newly rendered
	if (!fDoShadow) { pFontDef=FontDefs.end(); }
	if (pFontDef!=FontDefs.end()) switch (eType)
		{
		case C4FT_Log:      szFontString = pFontDef->LogFont.getData(); break;
		case C4FT_MainSmall:szFontString = pFontDef->SmallFont.getData(); break;
		case C4FT_Main:     szFontString = pFontDef->Font.getData(); break;
		case C4FT_Caption:  szFontString = pFontDef->CaptionFont.getData(); break;
		case C4FT_Title:    szFontString = pFontDef->TitleFont.getData(); break;
		default: LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; // invalid call
		}
	// font not assigned?
	if (!*szFontString)
		{
		// invalid call or spec
		LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false;
		}
	// get font name
	char FontFaceName[C4MaxName+1], FontParam[C4MaxName+1];
	SCopyUntil(szFontString, FontFaceName, ',', C4MaxName);
	// is it an image file?
	const char *szExt = GetExtension(FontFaceName);
	if (SEqualNoCase(szExt, "png") || SEqualNoCase(szExt, "bmp"))
		{
		// image file name: load bitmap font from image file
		// if no graphics group is given, do not load yet
		if (!pGfxGroups)
			{
			LogFatal(LoadResStr("IDS_ERR_INITFONTS"));
			return false;
			}
		// indent given?	
		int32_t iIndent = 0;
		if (SCopySegment(szFontString, 1, FontParam, ',', C4MaxName))
			sscanf(FontParam, "%i", &iIndent);
		// load font face from gfx group
		int32_t iGrpId;
		C4Group *pGrp = pGfxGroups->FindEntry(FontFaceName, NULL, &iGrpId);
		if (!pGrp)
			{
			LogFatal(LoadResStr("IDS_ERR_INITFONTS"));
			return false;
			}
		// check if it's already loaded from that group with that parameters
		if (!rFont.IsSameAsID(FontFaceName, iGrpId, iIndent))
			{
			// it's not; so (re-)load it now!
			if (rFont.IsInitialized())
				{
				// reloading
				rFont.Clear();
				LogF(LoadResStr("IDS_PRC_UPDATEFONT"), FontFaceName, iIndent, 0);
				}
			C4Surface sfc;
			if (!sfc.Load(*pGrp, FontFaceName))
				{
				LogFatal(LoadResStr("IDS_ERR_INITFONTS"));
				return false;
				}
			// init font from face
			try 
				{
				rFont.Init(GetFilenameOnly(FontFaceName), &sfc, iIndent);
				}
			catch (std::runtime_error & e)
				{
				LogFatal(e.what());
				LogFatal(LoadResStr("IDS_ERR_INITFONTS"));
				return false;
				}
			rFont.id = iGrpId;
			}
		}
	else
		{
		int32_t iDefFontSize; DWORD dwDefWeight=FW_NORMAL;
#if defined(_WIN32) && !defined(HAVE_FREETYPE)
		switch (eType)
			{
			case C4FT_Log:     iDefFontSize = 8; break;
			case C4FT_MainSmall:iDefFontSize = iSize+1; break;
			case C4FT_Main:    iDefFontSize = iSize+4; break;
			case C4FT_Caption: iDefFontSize = iSize+6; dwDefWeight = FW_BOLD; break;
			case C4FT_Title:   iDefFontSize = iSize*3; break;
			default: LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; // invalid call
			}
#else
		switch (eType)
			{
			case C4FT_Log:     iDefFontSize = iSize*12/14; break;
			case C4FT_MainSmall:iDefFontSize = iSize*13/14; break;
			case C4FT_Main:    iDefFontSize = iSize; break;
			case C4FT_Caption: iDefFontSize = iSize*16/14; /*dwDefWeight = FW_MEDIUM;*/ break;
			case C4FT_Title:   iDefFontSize = iSize*22/14; /*dwDefWeight = FW_MEDIUM;*/ break;
			default: LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; // invalid call
			}
#endif
		// regular font name: let WinGDI or Freetype draw a font with the given parameters
		// font size given?	
		if (SCopySegment(szFontString, 1, FontParam, ',', C4MaxName))
			sscanf(FontParam, "%i", &iDefFontSize);
		// font weight given?
		if (SCopySegment(szFontString, 2, FontParam, ',', C4MaxName))
			sscanf(FontParam, "%i", &dwDefWeight);
		// check if it's already loaded from that group with that parameters
		if (!rFont.IsSameAs(FontFaceName, iDefFontSize, dwDefWeight))
			{
			// it's not; so (re-)load it now!
			if (rFont.IsInitialized())
				{
				// reloading
				rFont.Clear();
				LogF(LoadResStr("IDS_PRC_UPDATEFONT"), FontFaceName, iDefFontSize, dwDefWeight);
				}
			// init with given font name
			try 
				{
				// check if one of the internally listed fonts should be used
				C4VectorFont * pFont = pVectorFonts;
				while (pFont)
					{
					if (SEqual(pFont->Name.getData(), FontFaceName))
						{
						if (InitFont(rFont, pFont, iDefFontSize, dwDefWeight, fDoShadow)) break;
						}
					pFont = pFont->pNext;
					}
				// no internal font matching? Then create one using the given face/filename (using a system font)
				if (!pFont)
					{
					pFont = new C4VectorFont();
					if (pFont->Init(FontFaceName, iDefFontSize, dwDefWeight, Config.General.LanguageCharset))
						{
						AddVectorFont(pFont);
						if (!InitFont(rFont, pFont, iDefFontSize, dwDefWeight, fDoShadow))
						  throw std::runtime_error(FormatString("Error initializing font %s", FontFaceName).getData());
						}
					else
						{
						delete pFont;
						// no match for font face found
						throw std::runtime_error(FormatString("Font face %s undefined", FontFaceName).getData());
						}
					}
				}
			catch (std::runtime_error & e)
				{
				LogFatal(e.what());
				LogFatal(LoadResStr("IDS_ERR_INITFONTS"));
				return false;
				}
			rFont.id = 0;
			}
		}
	// done, success
	return true;
	}