Files
FC1/CryFont/FFontXML.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

367 lines
7.6 KiB
C++

///////////////////////////////////////////////////////////////////////
//
// CryFont Source Code
//
// File: FFontXML.cpp
// Description: XML parsing to load a font.
//
// History:
// - August 21, 2001: Created by Alberto Demichelis
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "FFont.h"
#include <XmlStream.h>
#include <Cry_Math.h>
#include <string>
//////////////////////////////////////////////////////////////////////////////////////////////
// Xml parser class.
// Not very nice implementation but... cool enought ;)
#define ELEMENT_UNKNOWN 0
#define ELEMENT_FONT 1
#define ELEMENT_EFFECT 2
#define ELEMENT_PASS 4
#define ELEMENT_PASS_COLOR 5
#define ELEMENT_PASS_SIZESCALE 11
#define ELEMENT_PASS_POSOFFSET 12
#define ELEMENT_PASS_BLEND 14
///////////////////////////////////////////////
// utility function to get the blending type from a string
static inline CFFont::eBlendMode GetBlendModeFromString(const string& str)
{
CFFont::eBlendMode blend = CFFont::BLEND_SRCCOLOR;
if(str == "zero")
{
blend = CFFont::BLEND_ZERO;
}
else if(str == "one")
{
blend = CFFont::BLEND_ONE;
}
else if(str == "srccolor" ||
str == "src_color")
{
blend = CFFont::BLEND_SRCCOLOR;
}
else if(str == "invsrccolor" ||
str == "inv_src_color")
{
blend = CFFont::BLEND_INVSRCCOLOR;
}
else if(str == "srcalpha" ||
str == "src_alpha")
{
blend = CFFont::BLEND_SRCALPHA;
}
else if(str == "invsrcalpha" ||
str == "inv_src_alpha")
{
blend = CFFont::BLEND_INVSRCALPHA;
}
else if(str == "dstalpha" ||
str == "dst_alpha")
{
blend = CFFont::BLEND_DSTALPHA;
}
else if(str == "invdstalpha" ||
str == "inv_dst_alpha")
{
blend = CFFont::BLEND_INVDSTALPHA;
}
else if(str == "dstcolor" ||
str == "dst_color")
{
blend = CFFont::BLEND_DSTCOLOR;
}
else if(str == "invdstcolor" ||
str == "inv_dst_color")
{
blend = CFFont::BLEND_INVDSTCOLOR;
}
return blend;
}
//////////////////////////////////////////////////////////////////////////////////////////////
// Xml parser implementation
class CXmlFontShader : public IXmlNotify
{
public:
CXmlFontShader(CFFont *pFont)
{
m_pFont = pFont;
m_nElement = ELEMENT_UNKNOWN;
m_pEffect = NULL;
m_pPass = NULL;
m_FontTexSize.set(0,0);
m_bNoRescale = 0,
m_FontSmoothAmount = 0;
m_FontSmoothMethod = FONT_SMOOTH_NONE;
}
~CXmlFontShader()
{
}
// notify methods
void FoundElement(const string& name,const string& value)
{
//MessageBox(NULL, string("[" + name + "]").c_str(), "FoundElement", MB_OK);
// process the previous element
switch(m_nElement)
{
case ELEMENT_FONT:
{
int iWidth = GetISystem()->GetIRenderer()->GetWidth();
if(!m_FontTexSize.x || !m_FontTexSize.y)
{
m_FontTexSize.set(512, 512);
}
m_pFont->Load(m_strFontPath.c_str(), m_FontTexSize.x,m_FontTexSize.y, TTFFLAG_CREATE(m_FontSmoothMethod, m_FontSmoothAmount));
}
break;
default:
break;
}
// Translate the m_nElement name to a define
if(name == "font")
{
m_nElement = ELEMENT_FONT;
}
else if(name == "effect")
{
m_nElement = ELEMENT_EFFECT;
}
else if(name == "pass")
{
m_pPass = NULL;
m_nElement = ELEMENT_PASS;
if(m_pEffect)
m_pPass = m_pEffect->NewPass();
}
else if(name == "color")
{
m_nElement = ELEMENT_PASS_COLOR;
}
else if(name == "size")
{
m_nElement = ELEMENT_PASS_SIZESCALE;
}
else if(name == "pos" ||
name == "offset")
{
m_nElement = ELEMENT_PASS_POSOFFSET;
}
else if(name == "blend" ||
name == "blending")
{
m_nElement = ELEMENT_PASS_BLEND;
}
else
{
m_nElement = ELEMENT_UNKNOWN;
}
}
void FoundAttribute (const string & name,const string &value )
{
//MessageBox(NULL, string(name + "\n" + value).c_str(), "FoundAttribute", MB_OK);
switch(m_nElement)
{
case ELEMENT_FONT:
if(name == "path")
{
m_strFontPath = value;
}
else if(name == "w")
{
m_FontTexSize.x = (long)atof(value.c_str());
}
else if(name == "h")
{
m_FontTexSize.y = (long)atof(value.c_str());
}
else if(name == "norescale")
{
if (value.empty() || (atoi(value.c_str()) != 0))
{
m_bNoRescale = 1;
}
}
else if (name == "smooth")
{
if (value == "blur")
{
m_FontSmoothMethod = FONT_SMOOTH_BLUR;
}
else if (value == "supersample")
{
m_FontSmoothMethod = FONT_SMOOTH_SUPERSAMPLE;
}
else if (value == "none")
{
m_FontSmoothMethod = FONT_SMOOTH_NONE;
}
}
else if (name == "smooth_amount")
{
m_FontSmoothAmount = (long)atof(value.c_str());
}
break;
case ELEMENT_EFFECT:
if(name == "name")
{
if(value == "default")
{
m_pFont->SetEffect(NULL);
m_pEffect = m_pFont->GetCurrentEffect();
m_pEffect->strName = "default";
m_pEffect->Clear();
}
else
{
m_pEffect = m_pFont->NewEffect();
m_pEffect->strName = value;
}
}
break;
case ELEMENT_PASS_COLOR:
if(!m_pPass) break;
if(name == "r") { m_pPass->cColor.r = (float)atof(value.c_str()); }
else if(name == "g") { m_pPass->cColor.g = (float)atof(value.c_str()); }
else if(name == "b") { m_pPass->cColor.b = (float)atof(value.c_str()); }
else if(name == "a") { m_pPass->cColor.a = (float)atof(value.c_str()); }
break;
case ELEMENT_PASS_SIZESCALE:
if(!m_pPass) break;
if(name == "x")
{
m_pPass->vSizeScale.x = (float)atof(value.c_str());
}
else if(name == "y")
{
m_pPass->vSizeScale.y = (float)atof(value.c_str());
}
else if(name == "scale")
{
m_pPass->vSizeScale.x =
m_pPass->vSizeScale.y = (float)atof(value.c_str());
}
break;
case ELEMENT_PASS_POSOFFSET:
if(!m_pPass) break;
if(name == "x")
{
m_pPass->vPosOffset.x = (float)atoi(value.c_str());
}
else if(name == "y")
{
m_pPass->vPosOffset.y = (float)atoi(value.c_str());
}
break;
case ELEMENT_PASS_BLEND:
if(!m_pPass) break;
if(name == "src")
{
m_pPass->blendSrc = GetBlendModeFromString(value);
}
else if(name == "dst")
{
m_pPass->blendDest = GetBlendModeFromString(value);
}
else if(name == "type")
{
if(value == "modulate")
{
m_pPass->blendSrc = CFFont::BLEND_SRCALPHA;
m_pPass->blendDest = CFFont::BLEND_INVSRCALPHA;
}
else if(value == "additive")
{
m_pPass->blendSrc = CFFont::BLEND_ZERO;
m_pPass->blendDest = CFFont::BLEND_INVSRCALPHA;
}
}
break;
default:
case ELEMENT_UNKNOWN:
break;
}
}
public:
CFFont *m_pFont;
unsigned long m_nElement;
CFFont::SEffect* m_pEffect;
CFFont::SRenderingPass* m_pPass;
string m_strFontPath;
vector2l m_FontTexSize;
bool m_bNoRescale;
int m_FontSmoothMethod;
int m_FontSmoothAmount;
};
//////////////////////////////////////////////////////////////////////////////////////////////
// Main loading function
///////////////////////////////////////////////
bool CFFont::Load(const char *szFile)
{
ICryPak *pPak = GetISystem()->GetIPak();
if (!pPak)
{
return false;
}
FILE *fp = pPak->FOpen(szFile, "rb");
if(!fp)
return false;
pPak->FSeek(fp,0,SEEK_END);
int size = pPak->FTell(fp);
char *buffer = new char[size+1];
if(!buffer)
{
pPak->FClose(fp);
return false;
}
buffer[size] = 0;
pPak->FSeek(fp,0,SEEK_SET);
pPak->FRead(buffer,size,1,fp);
pPak->FClose(fp);
CXmlFontShader xmlfs(this);
XmlStream xml(&xmlfs);
xml.parse(buffer,size);
SetEffect("default");
delete [] buffer;
return m_bOK;
}