thunderbrew/src/ui/CSimpleFont.cpp

237 lines
7.3 KiB
C++
Raw Normal View History

2023-01-02 13:17:18 -06:00
#include "ui/CSimpleFont.hpp"
#include "gx/Coordinate.hpp"
#include "gx/Font.hpp"
#include "ui/CSimpleFontScript.hpp"
#include "ui/FrameXML.hpp"
#include "ui/LoadXML.hpp"
#include "ui/Types.hpp"
#include "util/CStatus.hpp"
#include "util/StringTo.hpp"
#include <common/XML.hpp>
#include <storm/String.hpp>
TSHashTable<SIMPLEFONT, HASHKEY_STRI> CSimpleFont::s_fontList;
int32_t CSimpleFont::s_metatable;
int32_t CSimpleFont::s_objectType;
SIMPLEFONT::SIMPLEFONT() : TSHashObject<SIMPLEFONT, HASHKEY_STRI>() {
auto m = SMemAlloc(sizeof(CSimpleFont), __FILE__, __LINE__, 0x0);
this->font = new (m) CSimpleFont();
2023-01-02 13:17:18 -06:00
}
void CSimpleFont::CreateScriptMetaTable() {
lua_State* L = FrameScript_GetContext();
int32_t ref = FrameScript_Object::CreateScriptMetaTable(L, &CSimpleFont::RegisterScriptMethods);
CSimpleFont::s_metatable = ref;
}
CSimpleFont* CSimpleFont::GetFont(const char* name, int32_t a2) {
SIMPLEFONT* hashed = CSimpleFont::s_fontList.Ptr(name);
if (hashed) {
return hashed->font;
}
if (!a2) {
return nullptr;
}
hashed = CSimpleFont::s_fontList.New(name, 0, 0);
CSimpleFont* font = hashed->font;
if (font->m_name) {
font->UnregisterScriptObject(font->m_name);
}
font->m_name = hashed->m_key.m_str;
if (font->m_name) {
font->RegisterScriptObject(font->m_name);
}
return hashed->font;
}
int32_t CSimpleFont::GetObjectType() {
if (!CSimpleFont::s_objectType) {
CSimpleFont::s_objectType = ++FrameScript_Object::s_objectTypes;
}
return CSimpleFont::s_objectType;
}
void CSimpleFont::RegisterScriptMethods(lua_State* L) {
FrameScript_Object::FillScriptMethodTable(L, SimpleFontMethods, NUM_SIMPLE_FONT_SCRIPT_METHODS);
}
CSimpleFont::CSimpleFont() : FrameScript_Object() {
// TODO
}
void CSimpleFont::FontObjectUpdated(CSimpleFontStringAttributes& attributes) {
attributes.Update(this->m_attributes, this->m_fontableFlags);
this->UpdateObjects();
}
char* CSimpleFont::GetName() {
return const_cast<char*>(this->m_name);
}
int32_t CSimpleFont::GetScriptMetaTable() {
return CSimpleFont::s_metatable;
}
bool CSimpleFont::IsA(int32_t type) {
return type == CSimpleFont::s_objectType;
}
void CSimpleFont::LoadXML(XMLNode* node, CStatus* status) {
const char* inheritsAttr = node->GetAttributeByName("inherits");
if (inheritsAttr && *inheritsAttr) {
auto font = CSimpleFont::GetFont(inheritsAttr, 0);
if (font) {
this->SetFontObject(font);
} else {
status->Add(
STATUS_WARNING,
"Couldn't find inherited font: %s",
inheritsAttr
);
}
}
const char* fontAttr = node->GetAttributeByName("font");
if (fontAttr && *fontAttr) {
auto font = CSimpleFont::GetFont(fontAttr, 0);
if (font) {
this->SetFontObject(font);
} else {
float fontHeight = 0.0f;
XMLNode* fontHeightNode = node->GetChildByName("FontHeight");
if (fontHeightNode) {
LoadXML_Value(fontHeightNode, fontHeight, status);
}
if (fontHeight == 0.0f) {
status->Add(
STATUS_WARNING,
"Font %s: Missing font height in %s element",
this->GetDisplayName(),
node->GetName()
);
return;
}
uint32_t fontFlags = 0;
const char* outlineAttr = node->GetAttributeByName("outline");
if (outlineAttr && *outlineAttr) {
if (!SStrCmpI(outlineAttr, "NORMAL", STORM_MAX_STR)) {
fontFlags |= FONT_OUTLINE;
} else if (!SStrCmpI(outlineAttr, "THICK", STORM_MAX_STR)) {
fontFlags |= (FONT_OUTLINE | FONT_THICKOUTLINE);
}
}
const char* monochromeAttr = node->GetAttributeByName("monochrome");
if (monochromeAttr && *monochromeAttr && StringToBOOL(monochromeAttr)) {
fontFlags |= FONT_MONOCHROME;
}
if (this->m_attributes.SetFont(fontAttr, fontHeight, fontFlags)) {
this->m_fontableFlags &= ~FLAG_FONT_UPDATE;
} else {
status->Add(
STATUS_WARNING,
"Font %s: Unable to load font file %s",
this->GetDisplayName(),
fontAttr
);
}
}
}
const char* spacingAttr = node->GetAttributeByName("spacing");
if (spacingAttr && *spacingAttr) {
float spacing = SStrToFloat(spacingAttr);
float ndcSpacing = spacing / (CoordinateGetAspectCompensation() * 1024.0);
float ddcSpacing = NDCToDDCWidth(ndcSpacing);
this->m_attributes.SetSpacing(ddcSpacing);
this->m_fontableFlags &= ~FLAG_SPACING_UPDATE;
}
const char* justifyVAttr = node->GetAttributeByName("justifyV");
if (justifyVAttr && *justifyVAttr) {
uint32_t justify;
if (StringToJustify(justifyVAttr, justify)) {
this->m_attributes.SetJustifyV(justify);
this->m_fontableFlags &= ~FLAG_STYLE_UPDATE;
}
}
const char* justifyHAttr = node->GetAttributeByName("justifyH");
if (justifyHAttr && *justifyHAttr) {
uint32_t justify;
if (StringToJustify(justifyHAttr, justify)) {
this->m_attributes.SetJustifyH(justify);
this->m_fontableFlags &= ~FLAG_STYLE_UPDATE;
}
}
const char* nonspacewrapAttr = node->GetAttributeByName("nonspacewrap");
if (nonspacewrapAttr && *nonspacewrapAttr) {
bool nonspacewrap = StringToBOOL(nonspacewrapAttr);
this->m_attributes.SetNonSpaceWrap(nonspacewrap);
}
const char* indentedAttr = node->GetAttributeByName("indented");
if (indentedAttr && *indentedAttr) {
bool indented = StringToBOOL(indentedAttr);
this->m_attributes.SetIndented(indented);
}
for (XMLNode* child = node->m_child; child; child = child->m_next) {
if (!SStrCmpI(child->GetName(), "Color", STORM_MAX_STR)) {
CImVector color;
LoadXML_Color(child, color);
this->m_attributes.SetColor(color);
this->m_fontableFlags &= ~FLAG_COLOR_UPDATE;
} else if(!SStrCmpI(child->GetName(), "Shadow", STORM_MAX_STR)) {
C2Vector shadowOffset = { 0.001f, -0.001f };
CImVector shadowColor = { 0x00, 0x00, 0x00, 0xFF };
auto colorChild = child->GetChildByName("Color");
if (colorChild) {
LoadXML_Color(colorChild, shadowColor);
}
auto offsetChild = child->GetChildByName("Offset");
if (offsetChild) {
LoadXML_Dimensions(offsetChild, shadowOffset.x, shadowOffset.y, status);
}
this->m_attributes.SetShadow(shadowColor, shadowOffset);
this->m_fontableFlags &= ~FLAG_SHADOW_UPDATE;
}
}
}
void CSimpleFont::UpdateObjects() {
if (this->m_attributes.m_flags) {
for (auto node = this->m_fontableList.Head(); node; node = this->m_fontableList.Link(node)->Next()) {
node->FontObjectUpdated(this->m_attributes);
}
this->m_attributes.m_flags &= ~FLAG_COMPLETE_UPDATE;
}
}