prime/src/Kyoto/Text/CTextParser.cpp

222 lines
7.4 KiB
C++

#include "Kyoto/Text/CTextParser.hpp"
#include "Kyoto/Math/CVector2f.hpp"
#include "Kyoto/SObjectTag.hpp"
#include "Kyoto/Text/CRasterFont.hpp"
#include "Kyoto/Text/CTextExecuteBuffer.hpp"
#include "Kyoto/Text/TextCommon.hpp"
#include <rstl/StringExtras.hpp>
#include <rstl/algorithm.hpp>
CTextParser::CTextParser(IObjectStore& store) : mObjectStore(store) {}
void CTextParser::ParseText(CTextExecuteBuffer& buffer, const wchar_t* str, int len,
rstl::vector< rstl::pair< CAssetId, CAssetId > >& txtrMap) {
int b = 0, e = 0;
for (b = 0, e = 0; str[e] && (len == -1 || e < len);) {
if (str[e] == L'&') {
if ((len == -1 || e + 1 < len) && str[e + 1] != L'&') {
if (e > b) {
buffer.AddString(str + b, e - b);
}
++e;
b = e;
while ((len == -1 || e < len) && str[e] && str[e] != L';')
++e;
ParseTag(buffer, str + b, e - b, txtrMap);
b = e + 1;
} else {
buffer.AddString(str + b, e + 1 - b);
e += 2;
b = e;
}
} else {
++e;
}
}
if (e > b)
buffer.AddString(str + b, e - b);
}
const CAssetId
CTextParser::GetAssetIdFromString(const rstl::string& inStr,
rstl::vector< rstl::pair< CAssetId, CAssetId > >* txtrMap) {
rstl::wstring str = CStringExtras::ConvertToUNICODE(inStr);
int id = (GetColorValue(str.data()) << 24) | (GetColorValue(str.data() + 2) << 16) |
(GetColorValue(str.data() + 4) << 8) | GetColorValue(str.data() + 6);
if (txtrMap) {
rstl::vector< rstl::pair< CAssetId, CAssetId > >::const_iterator search =
rstl::find_by_key(*txtrMap, id);
if (search != txtrMap->end()) {
return search->second;
}
}
return id;
}
TToken< CRasterFont > CTextParser::GetFont(const wchar_t* str, int len) {
uint id = (GetColorValue(str) << 24) | GetColorValue(str + 2) << 16 |
GetColorValue(str + 4) << 8 | GetColorValue(str + 6);
return mObjectStore.GetObj(SObjectTag('FONT', id));
}
CFontImageDef CTextParser::GetImage(const wchar_t* str, int len,
rstl::vector< rstl::pair< CAssetId, CAssetId > >& vec) {
return CFontImageDef(TToken< CTexture >(), CVector2f(0.f, 0.f));
}
uint CTextParser::HandleUserTag(CTextExecuteBuffer& buffer, const wchar_t* string, int len) {
return 0;
}
void CTextParser::ParseTag(CTextExecuteBuffer& buffer, const wchar_t* string, int len,
rstl::vector< rstl::pair< CAssetId, CAssetId > >& vec) {
if (BeginsWith(string, len, L"font=")) {
TToken< CRasterFont > font = GetFont(string + 5, len - 5);
buffer.AddFont(font);
} else if (BeginsWith(string, len, L"image=")) {
CFontImageDef texture = GetImage(string + 6, len - 6, vec);
buffer.AddImage(texture);
} else if (BeginsWith(string, len, L"fg-color=")) {
buffer.AddColor(kCT_Foreground, ParseColor(string + 9, len - 9));
} else if (BeginsWith(string, len, L"main-color=")) {
buffer.AddColor(kCT_Main, ParseColor(string + 11, len - 11));
} else if (BeginsWith(string, len, L"geometry-color=")) {
buffer.AddColor(kCT_Geometry, ParseColor(string + 11, len - 11));
} else if (BeginsWith(string, len, L"outline-color=")) {
buffer.AddColor(kCT_Outline, ParseColor(string + 14, len - 14));
} else if (BeginsWith(string, len, L"color")) {
int idx = string[6] - L'0';
if (idx < 0 || idx > 9) {
return;
}
const wchar_t* str_remain = string + 7;
len -= 7;
if (*str_remain >= L'0' && *str_remain <= L'9') {
wchar_t tmp = *str_remain;
++str_remain;
len--;
idx = (idx * 10) + (tmp - L'0');
}
if (Equals(str_remain + 10, len - 10, L"no")) {
buffer.AddRemoveColorOverride(idx);
} else {
buffer.AddColorOverride(idx, ParseColor(str_remain + 10, len - 10));
}
} else if (BeginsWith(string, len, L"line-spacing=")) {
const float v = (float)ParseInt(string + 13, len - 13, true);
buffer.AddLineSpacing(v / 100.f);
} else if (BeginsWith(string, len, L"line-extra-space=")) {
buffer.AddLineExtraSpace(ParseInt(string + 17, len - 17, true));
} else if (BeginsWith(string, len, L"just=")) {
if (Equals(string + 5, len - 5, L"left")) {
buffer.AddJustification(kJustification_Left);
} else if (Equals(string + 5, len - 5, L"center")) {
buffer.AddJustification(kJustification_Center);
} else if (Equals(string + 5, len - 5, L"right")) {
buffer.AddJustification(kJustification_Right);
} else if (Equals(string + 5, len - 5, L"full")) {
buffer.AddJustification(kJustification_Full);
} else if (Equals(string + 5, len - 5, L"nleft")) {
buffer.AddJustification(kJustification_NLeft);
} else if (Equals(string + 5, len - 5, L"ncenter")) {
buffer.AddJustification(kJustification_NCenter);
} else if (Equals(string + 5, len - 5, L"nright")) {
buffer.AddJustification(kJustification_NRight);
}
} else if (BeginsWith(string, len, L"vjust=")) {
if (Equals(string + 6, len - 6, L"top")) {
buffer.AddVerticalJustification(kVerticalJustification_Top);
} else if (Equals(string + 6, len - 6, L"center")) {
buffer.AddVerticalJustification(kVerticalJustification_Center);
} else if (Equals(string + 6, len - 6, L"bottom")) {
buffer.AddVerticalJustification(kVerticalJustification_Bottom);
} else if (Equals(string + 6, len - 6, L"full")) {
buffer.AddVerticalJustification(kVerticalJustification_Full);
} else if (Equals(string + 6, len - 6, L"ntop")) {
buffer.AddVerticalJustification(kVerticalJustification_NTop);
} else if (Equals(string + 6, len - 6, L"ncenter")) {
buffer.AddVerticalJustification(kVerticalJustification_NCenter);
} else if (Equals(string + 6, len - 6, L"nbottom")) {
buffer.AddVerticalJustification(kVerticalJustification_NBottom);
}
} else if (Equals(string, len, L"push")) {
buffer.AddPushState();
} else if (Equals(string, len, L"pop")) {
buffer.AddPopState();
} else {
HandleUserTag(buffer, string, len);
}
}
bool CTextParser::BeginsWith(const wchar_t* str1, int len, const wchar_t* str2) {
int i = 0;
for (; str2[i] != L'\x0' && i < len; ++i) {
if (str1[i] != str2[i]) {
return false;
}
}
return str2[i] == L'\x0';
}
bool CTextParser::Equals(const wchar_t* str1, int len, const wchar_t* str2) {
int i = 0;
for (; str2[i] != L'\x0' && i < len; ++i) {
if (str1[i] != str2[i]) {
return false;
}
}
return str2[i] == L'\x0';
}
int CTextParser::ParseInt(const wchar_t* str, int len, bool signVal) {
bool neg = false;
int procCur = 0;
if (signVal && len > 0 && *str == L'-') {
neg = true;
procCur = 1;
}
int val = 0;
while (len > procCur) {
val *= 10;
wchar_t ch = str[procCur];
val += ch - L'0';
++procCur;
}
return neg ? -val : val;
}
int CTextParser::FromHex(wchar_t ch) {
if (ch >= L'0' && ch <= L'9')
return ch - L'0';
if (ch >= L'A' && ch <= L'F')
return ch - L'A' + 10;
if (ch >= L'a' && ch <= L'f')
return ch - L'a' + 10;
return 0;
}
const int CTextParser::GetColorValue(const wchar_t* str) {
return FromHex(str[1]) + (FromHex(str[0]) << 4);
}
CTextColor CTextParser::ParseColor(const wchar_t* str, int len) {
uint r = GetColorValue(str + 1);
uint g = GetColorValue(str + 3);
uint b = GetColorValue(str + 5);
uint a = len == 9 ? GetColorValue(str + 7) : 255;
return CTextColor(r, g, b, a);
}