CTextParser imps

This commit is contained in:
Jack Andersen 2016-03-20 14:25:53 -10:00
parent 6a2d791269
commit 89daac544f
14 changed files with 548 additions and 87 deletions

View File

@ -256,6 +256,7 @@ public:
return ((TToken<T>*)this)->GetObj();
}
T* operator->() {return GetObj();}
const T* operator->() const {return GetObj();}
};
template <class T>

View File

@ -15,12 +15,14 @@ class CDrawStringOptions
friend class CRasterFont;
friend class CTextExecuteBuffer;
friend class CBlockInstruction;
friend class CWordInstruction;
ETextDirection x0_direction = ETextDirection::Horizontal;
std::vector<CTextColor> x4_vec;
std::vector<CTextColor> x4_colors;
public:
CDrawStringOptions()
{
x4_vec.resize(16);
x4_colors.resize(16);
}
};

View File

@ -33,12 +33,12 @@ void CFontRenderState::SetColor(EColorType tp, const CTextColor& col)
{
switch (tp)
{
case EColorType::Zero:
case EColorType::One:
case EColorType::Two:
case EColorType::Main:
case EColorType::Outline:
case EColorType::Geometry:
x20_[int(tp)] = col;
break;
case EColorType::Three:
case EColorType::Foreground:
x20_[0] = col;
break;
case EColorType::Four:
@ -50,7 +50,7 @@ void CFontRenderState::SetColor(EColorType tp, const CTextColor& col)
void CFontRenderState::RefreshPalette()
{
RefreshColor(EColorType::Three);
RefreshColor(EColorType::Foreground);
RefreshColor(EColorType::Four);
}
@ -58,40 +58,40 @@ void CFontRenderState::RefreshColor(EColorType tp)
{
switch (tp)
{
case EColorType::Zero:
case EColorType::Main:
if (!x14_font)
return;
switch (x14_font.GetObj()->GetMode())
{
case EColorType::Zero:
if (!x30_[0])
x0_drawStrOpts.x4_vec[0] = ConvertToTextureSpace(x20_[0]);
case EColorType::Main:
if (!x30_colorOverrides[0])
x0_drawStrOpts.x4_colors[0] = ConvertToTextureSpace(x20_[0]);
break;
case EColorType::One:
if (!x30_[0])
x0_drawStrOpts.x4_vec[0] = ConvertToTextureSpace(x20_[0]);
case EColorType::Outline:
if (!x30_colorOverrides[0])
x0_drawStrOpts.x4_colors[0] = ConvertToTextureSpace(x20_[0]);
break;
default: break;
}
break;
case EColorType::One:
case EColorType::Outline:
if (!x14_font)
return;
if (x30_[1])
if (x30_colorOverrides[1])
return;
if (x14_font.GetObj()->GetMode() == EColorType::One)
x0_drawStrOpts.x4_vec[1] = ConvertToTextureSpace(x20_[1]);
if (x14_font.GetObj()->GetMode() == EColorType::Outline)
x0_drawStrOpts.x4_colors[1] = ConvertToTextureSpace(x20_[1]);
break;
case EColorType::Two:
if (!x30_[2])
x0_drawStrOpts.x4_vec[2] = ConvertToTextureSpace(x20_[2]);
case EColorType::Geometry:
if (!x30_colorOverrides[2])
x0_drawStrOpts.x4_colors[2] = ConvertToTextureSpace(x20_[2]);
break;
case EColorType::Three:
RefreshColor(EColorType::Zero);
RefreshColor(EColorType::Two);
case EColorType::Foreground:
RefreshColor(EColorType::Main);
RefreshColor(EColorType::Geometry);
break;
case EColorType::Four:
RefreshColor(EColorType::One);
RefreshColor(EColorType::Outline);
break;
}
}

View File

@ -15,13 +15,15 @@ class CFontRenderState : public CSaveableState
friend class CLineInstruction;
friend class CBlockInstruction;
friend class CTextInstruction;
friend class CImageInstruction;
friend class CWordInstruction;
CBlockInstruction* x54_curBlock = nullptr;
CDrawStringOptions x58_drawOpts;
s32 x6c_curX = 0;
s32 x70_curY;
const CLineInstruction* x74_currentLineInst = nullptr;
bool xa0_ = true;
bool xa0_lineInitialized = true;
std::vector<CSaveableState> xa4_pushedStates;
public:
CFontRenderState();

View File

@ -13,13 +13,13 @@ class CRasterFont;
enum class EJustification
{
Zero = 0,
One,
Two,
Three,
Four,
Five,
Six,
Left = 0,
Center,
Right,
Full,
NLeft,
NCenter,
NRight,
Seven,
Eight,
Nine
@ -27,13 +27,13 @@ enum class EJustification
enum class EVerticalJustification
{
Zero = 0,
One,
Two,
Three,
Four,
Five,
Six,
Top = 0,
Center,
Bottom,
Full,
NTop,
NCenter,
NBottom,
Seven,
Eight,
Nine
@ -41,10 +41,10 @@ enum class EVerticalJustification
enum class EColorType
{
Zero,
One,
Two,
Three,
Main,
Outline,
Geometry,
Foreground,
Four
};

View File

@ -2,6 +2,7 @@
#include "CFontRenderState.hpp"
#include "CTextRenderBuffer.hpp"
#include "CRasterFont.hpp"
#include "Graphics/CTexture.hpp"
namespace urde
{
@ -22,9 +23,9 @@ void CColorInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf)
void CColorOverrideInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
state.x30_[x4_overrideIdx] = true;
state.x30_colorOverrides[x4_overrideIdx] = true;
zeus::CColor convCol = state.ConvertToTextureSpace(x8_color);
state.x0_drawStrOpts.x4_vec[x4_overrideIdx] = convCol;
state.x0_drawStrOpts.x4_colors[x4_overrideIdx] = convCol;
}
void CFontInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
@ -68,19 +69,19 @@ void CLineInstruction::InvokeLTR(CFontRenderState& state) const
{
switch (x1c_just)
{
case EJustification::Zero:
case EJustification::Three:
case EJustification::Four:
case EJustification::Left:
case EJustification::Full:
case EJustification::NLeft:
case EJustification::Seven:
state.x6c_curX = state.x54_curBlock->x4_offsetX;
break;
case EJustification::One:
case EJustification::Center:
case EJustification::Eight:
state.x6c_curX = state.x54_curBlock->x4_offsetX +
state.x54_curBlock->xc_blockPaddingX / 2 - x8_curX / 2;
break;
case EJustification::Five:
if (x4_ == 1)
case EJustification::NCenter:
if (x4_wordCount == 1)
{
state.x6c_curX = state.x54_curBlock->x4_offsetX +
state.x54_curBlock->xc_blockPaddingX / 2 - x8_curX / 2;
@ -92,12 +93,12 @@ void CLineInstruction::InvokeLTR(CFontRenderState& state) const
state.x54_curBlock->x2c_lineX / 2;
}
break;
case EJustification::Two:
case EJustification::Right:
case EJustification::Nine:
state.x6c_curX = state.x54_curBlock->x4_offsetX +
state.x54_curBlock->xc_blockPaddingX - x8_curX;
break;
case EJustification::Six:
case EJustification::NRight:
state.x6c_curX = state.x54_curBlock->x4_offsetX +
state.x54_curBlock->xc_blockPaddingX -
state.x54_curBlock->x2c_lineX;
@ -111,15 +112,15 @@ void CLineInstruction::InvokeLTR(CFontRenderState& state) const
s32 val = 0;
switch (state.x54_curBlock->x1c_vertJustification)
{
case EVerticalJustification::Zero:
case EVerticalJustification::One:
case EVerticalJustification::Two:
case EVerticalJustification::Four:
case EVerticalJustification::Five:
case EVerticalJustification::Six:
case EVerticalJustification::Top:
case EVerticalJustification::Center:
case EVerticalJustification::Bottom:
case EVerticalJustification::NTop:
case EVerticalJustification::NCenter:
case EVerticalJustification::NBottom:
val = inst.xc_curY;
break;
case EVerticalJustification::Three:
case EVerticalJustification::Full:
val = state.x54_curBlock->x10_blockPaddingY - state.x54_curBlock->x30_lineY;
if (state.x54_curBlock->x34_lineCount > 1)
val /= state.x54_curBlock->x34_lineCount - 1;
@ -139,7 +140,7 @@ void CLineInstruction::InvokeLTR(CFontRenderState& state) const
break;
}
if (state.x54_curBlock->x1c_vertJustification != EVerticalJustification::Three)
if (state.x54_curBlock->x1c_vertJustification != EVerticalJustification::Full)
val = val * state.x40_lineSpacing + state.x44_extraLineSpace;
state.x70_curY += val;
@ -149,10 +150,49 @@ void CLineInstruction::InvokeLTR(CFontRenderState& state) const
void CLineInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
InvokeLTR(state);
state.xa0_ = true;
state.xa0_lineInitialized = true;
state.x74_currentLineInst = this;
}
void CLineSpacingInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
state.x40_lineSpacing = x4_lineSpacing;
}
void CPopStateInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
state.PopState();
}
void CPushStateInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
state.PushState();
}
void CRemoveColorOverrideInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
state.x30_colorOverrides[x4_idx] = false;
}
void CImageInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
if (x4_image.IsLoaded() && x4_image.x4_texs.size())
{
if (state.x54_curBlock->x14_direction == ETextDirection::Horizontal)
{
const CTexture* tex = x4_image.x4_texs[0].GetObj();
if (buf)
{
zeus::CVector2i coords(state.x6c_curX,
state.x70_curY + state.x74_currentLineInst->x18_largestBaseline -
tex->GetHeight() * x4_image.x14_pointsPerTexel.y * 2 / 3);
buf->AddImage(coords, x4_image);
}
state.x6c_curX += tex->GetWidth() * x4_image.x14_pointsPerTexel.x;
}
}
}
void CTextInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
int xOut, yOut;
@ -181,21 +221,21 @@ void CBlockInstruction::SetupPositionLTR(CFontRenderState& state) const
{
switch (x1c_vertJustification)
{
case EVerticalJustification::Zero:
case EVerticalJustification::Three:
case EVerticalJustification::Four:
case EVerticalJustification::Top:
case EVerticalJustification::Full:
case EVerticalJustification::NTop:
case EVerticalJustification::Seven:
state.x70_curY = x8_offsetY;
break;
case EVerticalJustification::One:
case EVerticalJustification::Five:
case EVerticalJustification::Center:
case EVerticalJustification::NCenter:
state.x70_curY = x8_offsetY + (x10_blockPaddingY - x30_lineY) / 2;
break;
case EVerticalJustification::Eight:
state.x70_curY = x8_offsetY + (x10_blockPaddingY - x34_lineCount * x24_largestMonoH) / 2;
break;
case EVerticalJustification::Two:
case EVerticalJustification::Six:
case EVerticalJustification::Bottom:
case EVerticalJustification::NBottom:
state.x70_curY = x8_offsetY + x10_blockPaddingY - x30_lineY;
break;
case EVerticalJustification::Nine:
@ -212,4 +252,43 @@ void CBlockInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf)
SetupPositionLTR(state);
}
void CWordInstruction::InvokeLTR(CFontRenderState& state) const
{
CRasterFont* font = state.x14_font.GetObj();
wchar_t space = L' ';
int w, h;
font->GetSize(state.x0_drawStrOpts, w, h, &space, 1);
const CLineInstruction& inst = *state.x74_currentLineInst;
switch (state.x54_curBlock->x18_justification)
{
case EJustification::Full:
w += (state.x54_curBlock->xc_blockPaddingX - inst.x8_curX) / (inst.x4_wordCount - 1);
break;
case EJustification::NLeft:
case EJustification::NCenter:
case EJustification::NRight:
w += (state.x54_curBlock->x2c_lineX - inst.x8_curX) / (inst.x4_wordCount - 1);
break;
default: break;
}
int wOut = state.x6c_curX;
font->DrawSpace(state.x0_drawStrOpts, wOut,
inst.xc_curY - font->GetMonoHeight() + state.x70_curY, wOut, h, w);
state.x6c_curX = wOut;
}
void CWordInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
if (state.xa0_lineInitialized)
{
state.xa0_lineInitialized = false;
return;
}
if (state.x0_drawStrOpts.x0_direction == ETextDirection::Horizontal)
InvokeLTR(state);
}
}

View File

@ -63,7 +63,10 @@ class CLineInstruction : public CInstruction
{
friend class CTextExecuteBuffer;
friend class CTextInstruction;
s32 x4_ = 0;
friend class CImageInstruction;
friend class CWordInstruction;
s32 x4_wordCount = 0;
s32 x8_curX = 0;
s32 xc_curY = 0;
s32 x10_largestMonoHeight = 0;
@ -109,9 +112,9 @@ public:
class CImageInstruction : public CInstruction
{
CFontImageDef x0_image;
CFontImageDef x4_image;
public:
CImageInstruction(const CFontImageDef& image) : x0_image(image) {}
CImageInstruction(const CFontImageDef& image) : x4_image(image) {}
void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const;
};
@ -127,6 +130,9 @@ class CBlockInstruction : public CInstruction
{
friend class CTextExecuteBuffer;
friend class CLineInstruction;
friend class CImageInstruction;
friend class CWordInstruction;
s32 x4_offsetX;
s32 x8_offsetY;
s32 xc_blockPaddingX;
@ -154,6 +160,7 @@ public:
class CWordInstruction : public CInstruction
{
public:
void InvokeLTR(CFontRenderState& state) const;
void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const;
};

View File

@ -34,10 +34,10 @@ CRasterFont::CRasterFont(urde::CInputStream& in, urde::IObjectStore& store)
x80_texture = store.GetObj({'TXTR', txtrId});
EColorType mode = EColorType(in.readUint32Big());
/* TODO: Make an enum */
if (mode == EColorType::One)
x2c_mode = EColorType::One;
else if (mode == EColorType::Zero)
x2c_mode = EColorType::Zero;
if (mode == EColorType::Outline)
x2c_mode = EColorType::Outline;
else if (mode == EColorType::Main)
x2c_mode = EColorType::Main;
u32 glyphCount = in.readUint32Big();
xc_glyphs.reserve(glyphCount);
@ -103,7 +103,7 @@ void CRasterFont::SinglePassDrawString(const CDrawStringOptions& opts, int x, in
{
left += x;
top += glyph->GetBaseline() - y;
renderBuf->AddCharacter(zeus::CVector2i(left, top), *chr, opts.x4_vec[0]);
renderBuf->AddCharacter(zeus::CVector2i(left, top), *chr, opts.x4_colors[0]);
}
x += glyph->GetC() + glyph->GetB();
}

View File

@ -95,7 +95,7 @@ class CRasterFont
std::vector<std::pair<wchar_t, CGlyph>> xc_glyphs;
std::vector<CKernPair> x1c_kerning;
s32 x28_lineMargin = 0;
EColorType x2c_mode = EColorType::Zero;
EColorType x2c_mode = EColorType::Main;
CFontInfo x30_fontInfo;
TLockedToken<CTexture> x80_texture;
bool x88_ = false;

View File

@ -17,22 +17,25 @@ class CSaveableState
friend class CFontInstruction;
friend class CLineExtraSpaceInstruction;
friend class CTextInstruction;
friend class CLineSpacingInstruction;
friend class CRemoveColorOverrideInstruction;
friend class CWordInstruction;
protected:
CDrawStringOptions x0_drawStrOpts;
TToken<CRasterFont> x14_font;
std::vector<CTextColor> x20_;
std::vector<bool> x30_;
std::vector<bool> x30_colorOverrides;
float x40_lineSpacing = 1.f;
s32 x44_extraLineSpace = 0;
bool x48_ = false;
EJustification x4c_just = EJustification::Zero;
EVerticalJustification x50_vjust = EVerticalJustification::Zero;
EJustification x4c_just = EJustification::Left;
EVerticalJustification x50_vjust = EVerticalJustification::Top;
public:
CSaveableState()
{
x20_.resize(3, zeus::CColor::skBlack);
x30_.resize(16);
x30_colorOverrides.resize(16);
}
};

View File

@ -111,7 +111,7 @@ int CTextExecuteBuffer::WrapOneLTR(const wchar_t* str, int len)
if (x18_textState.x48_)
{
if (w + x70_curLine->x8_curX > x6c_curBlock->xc_blockPaddingX &&
x70_curLine->x4_ > 1 &&
x70_curLine->x4_wordCount > 1 &&
x7c_curX + w < x6c_curBlock->xc_blockPaddingX)
{
MoveWordLTR();
@ -167,7 +167,7 @@ void CTextExecuteBuffer::MoveWordLTR()
{
x70_curLine->xc_curY = std::min(x70_curLine->xc_curY, x84_);
x88_spaceDistance = 0;
--x70_curLine->x4_;
--x70_curLine->x4_wordCount;
TerminateLineLTR();
x70_curLine = static_cast<CLineInstruction*>(x0_instList.emplace(x74_curWordIt,
@ -198,7 +198,7 @@ void CTextExecuteBuffer::StartNewWord()
x78_curY = 0;
x80_ = x70_curLine->x8_curX;
x84_ = x70_curLine->xc_curY;
++x70_curLine->x4_;
++x70_curLine->x4_wordCount;
}
void CTextExecuteBuffer::TerminateLine()
@ -214,7 +214,7 @@ void CTextExecuteBuffer::TerminateLineLTR()
x70_curLine->xc_curY = x70_curLine->x10_largestMonoHeight;
}
if (x6c_curBlock->x1c_vertJustification == EVerticalJustification::Three)
if (x6c_curBlock->x1c_vertJustification == EVerticalJustification::Full)
{
x6c_curBlock->x30_lineY += x70_curLine->xc_curY;
}
@ -312,6 +312,22 @@ void CTextExecuteBuffer::AddImage(const CFontImageDef& image)
x0_instList.emplace(x0_instList.cend(), new CImageInstruction(image));
}
void CTextExecuteBuffer::AddFont(const TToken<CRasterFont>& font)
{
x0_instList.emplace(x0_instList.cend(), new CFontInstruction(font));
x18_textState.x14_font = font;
if (x6c_curBlock)
x6c_curBlock->TestLargestFont(font->GetMonoWidth(),
font->GetMonoHeight(),
font->GetBaseline());
if (x70_curLine)
x70_curLine->TestLargestFont(font->GetMonoWidth(),
font->GetMonoHeight(),
font->GetBaseline());
}
void CTextExecuteBuffer::EndBlock()
{
if (x70_curLine)

View File

@ -54,6 +54,7 @@ public:
void AddColorOverride(int idx, const CTextColor& color);
void AddColor(EColorType, const CTextColor& color);
void AddImage(const CFontImageDef& image);
void AddFont(const TToken<CRasterFont>& font);
void EndBlock();
void BeginBlock(s32 offX, s32 offY, s32 padX, s32 padY,
ETextDirection dir, EJustification just,

View File

@ -0,0 +1,330 @@
#include "CTextParser.hpp"
#include "CFontImageDef.hpp"
#include "CTextExecuteBuffer.hpp"
namespace urde
{
CTextColor CTextParser::ParseColor(const wchar_t* str, int len)
{
u8 r = GetColorValue(str + 1);
u8 g = GetColorValue(str + 3);
u8 b = GetColorValue(str + 5);
u8 a = 0xff;
if (len == 9)
a = GetColorValue(str + 7);
return CTextColor(r, g, b, a);
}
u8 CTextParser::GetColorValue(const wchar_t* str)
{
return (FromHex(str[0]) << 4) + FromHex(str[1]);
}
u32 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;
}
s32 CTextParser::ParseInt(const wchar_t* str, int len, bool signVal)
{
bool neg = false;
int procCur = 0;
if (signVal && len && *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;
}
bool CTextParser::Equals(const wchar_t* str, int len, const wchar_t* other)
{
int i=0;
for (; *other && i<len ; ++i, ++str, ++other)
{
if (*str != *other)
return false;
}
return other[i] == L'\0';
}
bool CTextParser::BeginsWith(const wchar_t* str, int len, const wchar_t* other)
{
int i=0;
for (; *other && i<len ; ++i, ++str, ++other)
{
if (*str != *other)
return false;
}
return true;
}
void CTextParser::ParseTag(CTextExecuteBuffer& out, const wchar_t* str, int len)
{
if (BeginsWith(str, len, L"font="))
{
TToken<CRasterFont> font = GetFont(str + 5, len - 5);
out.AddFont(font);
}
else if (BeginsWith(str, len, L"image="))
{
CFontImageDef image = GetImage(str + 6, len - 6);
out.AddImage(image);
}
else if (BeginsWith(str, len, L"fg-color="))
{
CTextColor color = ParseColor(str + 9, len - 9);
out.AddColor(EColorType::Foreground, color);
}
else if (BeginsWith(str, len, L"main-color="))
{
CTextColor color = ParseColor(str + 11, len - 11);
out.AddColor(EColorType::Main, color);
}
else if (BeginsWith(str, len, L"geometry-color="))
{
CTextColor color = ParseColor(str + 15, len - 15);
out.AddColor(EColorType::Geometry, color);
}
else if (BeginsWith(str, len, L"outline-color="))
{
CTextColor color = ParseColor(str + 14, len - 14);
out.AddColor(EColorType::Outline, color);
}
else if (BeginsWith(str, len, L"color"))
{
const wchar_t* valCur = str + 7;
len -= 7;
int val = str[6] - L'0';
if (str[7] >= L'0' && str[7] <= L'9')
{
++valCur;
--len;
val *= 10;
val += str[7] - L'0';
}
if (Equals(valCur + 10, len - 10, L"no"))
out.AddRemoveColorOverride(val);
else
{
CTextColor color = ParseColor(str + 10, len - 10);
out.AddColorOverride(val, color);
}
}
else if (BeginsWith(str, len, L"line-spacing="))
{
out.AddLineSpacing(ParseInt(str + 13, len - 13, true) / 100.0);
}
else if (BeginsWith(str, len, L"line-extra-space="))
{
out.AddLineSpacing(ParseInt(str + 17, len - 17, true));
}
else if (BeginsWith(str, len, L"just="))
{
if (Equals(str + 5, len - 5, L"left"))
out.AddJustification(EJustification::Left);
else if (Equals(str + 5, len - 5, L"center"))
out.AddJustification(EJustification::Center);
else if (Equals(str + 5, len - 5, L"right"))
out.AddJustification(EJustification::Right);
else if (Equals(str + 5, len - 5, L"full"))
out.AddJustification(EJustification::Full);
else if (Equals(str + 5, len - 5, L"nleft"))
out.AddJustification(EJustification::NLeft);
else if (Equals(str + 5, len - 5, L"ncenter"))
out.AddJustification(EJustification::NCenter);
else if (Equals(str + 5, len - 5, L"nright"))
out.AddJustification(EJustification::NRight);
}
else if (BeginsWith(str, len, L"vjust="))
{
if (Equals(str + 6, len - 6, L"top"))
out.AddVerticalJustification(EVerticalJustification::Top);
else if (Equals(str + 6, len - 6, L"center"))
out.AddVerticalJustification(EVerticalJustification::Center);
else if (Equals(str + 6, len - 6, L"bottom"))
out.AddVerticalJustification(EVerticalJustification::Bottom);
else if (Equals(str + 6, len - 6, L"full"))
out.AddVerticalJustification(EVerticalJustification::Full);
else if (Equals(str + 6, len - 6, L"ntop"))
out.AddVerticalJustification(EVerticalJustification::NTop);
else if (Equals(str + 6, len - 6, L"ncenter"))
out.AddVerticalJustification(EVerticalJustification::NCenter);
else if (Equals(str + 6, len - 6, L"nbottom"))
out.AddVerticalJustification(EVerticalJustification::NBottom);
}
else if (Equals(str, len, L"push"))
{
out.AddPushState();
}
else if (Equals(str, len, L"pop"))
{
out.AddPopState();
}
}
CFontImageDef CTextParser::GetImage(const wchar_t* str, int len)
{
int commaCount = 0;
for (int i=0 ; i<len ; ++i)
if (str[i] == L',')
++commaCount;
if (commaCount)
{
std::wstring iterable(str, len);
size_t tokenPos;
size_t commaPos;
commaPos = iterable.find(L',');
iterable[commaPos] = L'\0';
tokenPos = commaPos + 1;
auto AdvanceCommaPos = [&]()
{
commaPos = iterable.find(L',', tokenPos);
if (commaPos == std::wstring::npos)
commaPos = iterable.size();
iterable[commaPos] = L'\0';
};
auto AdvanceTokenPos = [&]()
{
tokenPos = commaPos + 1;
};
if (BeginsWith(str, len, L"A"))
{
/* Animated texture array */
AdvanceCommaPos();
float interval = std::wcstof(&iterable[tokenPos], nullptr);
AdvanceTokenPos();
std::vector<TToken<CTexture>> texs;
texs.reserve(commaCount - 1);
do
{
AdvanceCommaPos();
texs.push_back(x0_store.GetObj({SBIG('TXTR'),
GetAssetIdFromString(&iterable[tokenPos])}));
AdvanceTokenPos();
} while (commaPos != iterable.size());
return CFontImageDef(std::move(texs), interval, zeus::CVector2f(1.f, 1.f));
}
else if (BeginsWith(str, len, L"SA"))
{
/* Scaled and animated texture array */
AdvanceCommaPos();
float interval = std::wcstof(&iterable[tokenPos], nullptr);
AdvanceTokenPos();
AdvanceCommaPos();
float scaleX = std::wcstof(&iterable[tokenPos], nullptr);
AdvanceTokenPos();
AdvanceCommaPos();
float scaleY = std::wcstof(&iterable[tokenPos], nullptr);
AdvanceTokenPos();
std::vector<TToken<CTexture>> texs;
texs.reserve(commaCount - 3);
do
{
AdvanceCommaPos();
texs.push_back(x0_store.GetObj({SBIG('TXTR'),
GetAssetIdFromString(&iterable[tokenPos])}));
AdvanceTokenPos();
} while (commaPos != iterable.size());
return CFontImageDef(std::move(texs), interval, zeus::CVector2f(scaleX, scaleY));
}
else if (BeginsWith(str, len, L"SI"))
{
/* Scaled single texture */
AdvanceCommaPos();
float scaleX = std::wcstof(&iterable[tokenPos], nullptr);
AdvanceTokenPos();
AdvanceCommaPos();
float scaleY = std::wcstof(&iterable[tokenPos], nullptr);
AdvanceTokenPos();
AdvanceCommaPos();
TToken<CTexture> tex = x0_store.GetObj({SBIG('TXTR'),
GetAssetIdFromString(&iterable[tokenPos])});
AdvanceTokenPos();
return CFontImageDef(std::move(tex), zeus::CVector2f(scaleX, scaleY));
}
}
TToken<CTexture> tex = x0_store.GetObj({SBIG('TXTR'), GetAssetIdFromString(str)});
return CFontImageDef(std::move(tex), zeus::CVector2f(1.f, 1.f));
}
TResId CTextParser::GetAssetIdFromString(const wchar_t* str)
{
u8 r = GetColorValue(str);
u8 g = GetColorValue(str + 2);
u8 b = GetColorValue(str + 4);
u8 a = GetColorValue(str + 6);
return (r << 24) | (g << 16) | (b << 8) | a;
}
TToken<CRasterFont> CTextParser::GetFont(const wchar_t* str, int len)
{
return x0_store.GetObj({SBIG('FONT'), GetAssetIdFromString(str)});
}
void CTextParser::ParseText(CTextExecuteBuffer& out, const wchar_t* str, int len)
{
for (int b=0, e=0 ; str[e] && (len == -1 || e < len) ;)
{
if (str[e] != L'&')
{
++e;
continue;
}
if ((len == -1 || e+1 < len) && str[e+1] != L'&')
{
out.AddString(str + b, e - b);
++e;
b = e;
while (str[e] && (len == -1 || e < len) && str[e] != L';')
++e;
ParseTag(out, str + e, e - b);
b = e + 1;
}
else
{
out.AddString(str + b, e + 1 - b);
e += 2;
b = e;
}
}
}
}

View File

@ -1,11 +1,31 @@
#ifndef __URDE_CTEXTPARSER_HPP__
#define __URDE_CTEXTPARSER_HPP__
#include "CGuiTextSupport.hpp"
namespace urde
{
class CTextExecuteBuffer;
class CFontImageDef;
class CTextParser
{
IObjectStore& x0_store;
static CTextColor ParseColor(const wchar_t* str, int len);
static u8 GetColorValue(const wchar_t* str);
static u32 FromHex(wchar_t ch);
static s32 ParseInt(const wchar_t* str, int len, bool signVal);
static TResId GetAssetIdFromString(const wchar_t* str);
static bool Equals(const wchar_t* str, int len, const wchar_t* other);
static bool BeginsWith(const wchar_t* str, int len, const wchar_t* other);
void ParseTag(CTextExecuteBuffer& out, const wchar_t* str, int len);
CFontImageDef GetImage(const wchar_t* str, int len);
TToken<CRasterFont> GetFont(const wchar_t* str, int len);
public:
CTextParser(IObjectStore& store) : x0_store(store) {}
void ParseText(CTextExecuteBuffer& out, const wchar_t* str, int len);
};
}