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(); return ((TToken<T>*)this)->GetObj();
} }
T* operator->() {return GetObj();} T* operator->() {return GetObj();}
const T* operator->() const {return GetObj();}
}; };
template <class T> template <class T>

View File

@ -15,12 +15,14 @@ class CDrawStringOptions
friend class CRasterFont; friend class CRasterFont;
friend class CTextExecuteBuffer; friend class CTextExecuteBuffer;
friend class CBlockInstruction; friend class CBlockInstruction;
friend class CWordInstruction;
ETextDirection x0_direction = ETextDirection::Horizontal; ETextDirection x0_direction = ETextDirection::Horizontal;
std::vector<CTextColor> x4_vec; std::vector<CTextColor> x4_colors;
public: public:
CDrawStringOptions() 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) switch (tp)
{ {
case EColorType::Zero: case EColorType::Main:
case EColorType::One: case EColorType::Outline:
case EColorType::Two: case EColorType::Geometry:
x20_[int(tp)] = col; x20_[int(tp)] = col;
break; break;
case EColorType::Three: case EColorType::Foreground:
x20_[0] = col; x20_[0] = col;
break; break;
case EColorType::Four: case EColorType::Four:
@ -50,7 +50,7 @@ void CFontRenderState::SetColor(EColorType tp, const CTextColor& col)
void CFontRenderState::RefreshPalette() void CFontRenderState::RefreshPalette()
{ {
RefreshColor(EColorType::Three); RefreshColor(EColorType::Foreground);
RefreshColor(EColorType::Four); RefreshColor(EColorType::Four);
} }
@ -58,40 +58,40 @@ void CFontRenderState::RefreshColor(EColorType tp)
{ {
switch (tp) switch (tp)
{ {
case EColorType::Zero: case EColorType::Main:
if (!x14_font) if (!x14_font)
return; return;
switch (x14_font.GetObj()->GetMode()) switch (x14_font.GetObj()->GetMode())
{ {
case EColorType::Zero: case EColorType::Main:
if (!x30_[0]) if (!x30_colorOverrides[0])
x0_drawStrOpts.x4_vec[0] = ConvertToTextureSpace(x20_[0]); x0_drawStrOpts.x4_colors[0] = ConvertToTextureSpace(x20_[0]);
break; break;
case EColorType::One: case EColorType::Outline:
if (!x30_[0]) if (!x30_colorOverrides[0])
x0_drawStrOpts.x4_vec[0] = ConvertToTextureSpace(x20_[0]); x0_drawStrOpts.x4_colors[0] = ConvertToTextureSpace(x20_[0]);
break; break;
default: break; default: break;
} }
break; break;
case EColorType::One: case EColorType::Outline:
if (!x14_font) if (!x14_font)
return; return;
if (x30_[1]) if (x30_colorOverrides[1])
return; return;
if (x14_font.GetObj()->GetMode() == EColorType::One) if (x14_font.GetObj()->GetMode() == EColorType::Outline)
x0_drawStrOpts.x4_vec[1] = ConvertToTextureSpace(x20_[1]); x0_drawStrOpts.x4_colors[1] = ConvertToTextureSpace(x20_[1]);
break; break;
case EColorType::Two: case EColorType::Geometry:
if (!x30_[2]) if (!x30_colorOverrides[2])
x0_drawStrOpts.x4_vec[2] = ConvertToTextureSpace(x20_[2]); x0_drawStrOpts.x4_colors[2] = ConvertToTextureSpace(x20_[2]);
break; break;
case EColorType::Three: case EColorType::Foreground:
RefreshColor(EColorType::Zero); RefreshColor(EColorType::Main);
RefreshColor(EColorType::Two); RefreshColor(EColorType::Geometry);
break; break;
case EColorType::Four: case EColorType::Four:
RefreshColor(EColorType::One); RefreshColor(EColorType::Outline);
break; break;
} }
} }

View File

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

View File

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

View File

@ -2,6 +2,7 @@
#include "CFontRenderState.hpp" #include "CFontRenderState.hpp"
#include "CTextRenderBuffer.hpp" #include "CTextRenderBuffer.hpp"
#include "CRasterFont.hpp" #include "CRasterFont.hpp"
#include "Graphics/CTexture.hpp"
namespace urde namespace urde
{ {
@ -22,9 +23,9 @@ void CColorInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf)
void CColorOverrideInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const 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); 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 void CFontInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
@ -68,19 +69,19 @@ void CLineInstruction::InvokeLTR(CFontRenderState& state) const
{ {
switch (x1c_just) switch (x1c_just)
{ {
case EJustification::Zero: case EJustification::Left:
case EJustification::Three: case EJustification::Full:
case EJustification::Four: case EJustification::NLeft:
case EJustification::Seven: case EJustification::Seven:
state.x6c_curX = state.x54_curBlock->x4_offsetX; state.x6c_curX = state.x54_curBlock->x4_offsetX;
break; break;
case EJustification::One: case EJustification::Center:
case EJustification::Eight: case EJustification::Eight:
state.x6c_curX = state.x54_curBlock->x4_offsetX + state.x6c_curX = state.x54_curBlock->x4_offsetX +
state.x54_curBlock->xc_blockPaddingX / 2 - x8_curX / 2; state.x54_curBlock->xc_blockPaddingX / 2 - x8_curX / 2;
break; break;
case EJustification::Five: case EJustification::NCenter:
if (x4_ == 1) if (x4_wordCount == 1)
{ {
state.x6c_curX = state.x54_curBlock->x4_offsetX + state.x6c_curX = state.x54_curBlock->x4_offsetX +
state.x54_curBlock->xc_blockPaddingX / 2 - x8_curX / 2; 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; state.x54_curBlock->x2c_lineX / 2;
} }
break; break;
case EJustification::Two: case EJustification::Right:
case EJustification::Nine: case EJustification::Nine:
state.x6c_curX = state.x54_curBlock->x4_offsetX + state.x6c_curX = state.x54_curBlock->x4_offsetX +
state.x54_curBlock->xc_blockPaddingX - x8_curX; state.x54_curBlock->xc_blockPaddingX - x8_curX;
break; break;
case EJustification::Six: case EJustification::NRight:
state.x6c_curX = state.x54_curBlock->x4_offsetX + state.x6c_curX = state.x54_curBlock->x4_offsetX +
state.x54_curBlock->xc_blockPaddingX - state.x54_curBlock->xc_blockPaddingX -
state.x54_curBlock->x2c_lineX; state.x54_curBlock->x2c_lineX;
@ -111,15 +112,15 @@ void CLineInstruction::InvokeLTR(CFontRenderState& state) const
s32 val = 0; s32 val = 0;
switch (state.x54_curBlock->x1c_vertJustification) switch (state.x54_curBlock->x1c_vertJustification)
{ {
case EVerticalJustification::Zero: case EVerticalJustification::Top:
case EVerticalJustification::One: case EVerticalJustification::Center:
case EVerticalJustification::Two: case EVerticalJustification::Bottom:
case EVerticalJustification::Four: case EVerticalJustification::NTop:
case EVerticalJustification::Five: case EVerticalJustification::NCenter:
case EVerticalJustification::Six: case EVerticalJustification::NBottom:
val = inst.xc_curY; val = inst.xc_curY;
break; break;
case EVerticalJustification::Three: case EVerticalJustification::Full:
val = state.x54_curBlock->x10_blockPaddingY - state.x54_curBlock->x30_lineY; val = state.x54_curBlock->x10_blockPaddingY - state.x54_curBlock->x30_lineY;
if (state.x54_curBlock->x34_lineCount > 1) if (state.x54_curBlock->x34_lineCount > 1)
val /= state.x54_curBlock->x34_lineCount - 1; val /= state.x54_curBlock->x34_lineCount - 1;
@ -139,7 +140,7 @@ void CLineInstruction::InvokeLTR(CFontRenderState& state) const
break; 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; val = val * state.x40_lineSpacing + state.x44_extraLineSpace;
state.x70_curY += val; state.x70_curY += val;
@ -149,10 +150,49 @@ void CLineInstruction::InvokeLTR(CFontRenderState& state) const
void CLineInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const void CLineInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{ {
InvokeLTR(state); InvokeLTR(state);
state.xa0_ = true; state.xa0_lineInitialized = true;
state.x74_currentLineInst = this; 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 void CTextInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{ {
int xOut, yOut; int xOut, yOut;
@ -181,21 +221,21 @@ void CBlockInstruction::SetupPositionLTR(CFontRenderState& state) const
{ {
switch (x1c_vertJustification) switch (x1c_vertJustification)
{ {
case EVerticalJustification::Zero: case EVerticalJustification::Top:
case EVerticalJustification::Three: case EVerticalJustification::Full:
case EVerticalJustification::Four: case EVerticalJustification::NTop:
case EVerticalJustification::Seven: case EVerticalJustification::Seven:
state.x70_curY = x8_offsetY; state.x70_curY = x8_offsetY;
break; break;
case EVerticalJustification::One: case EVerticalJustification::Center:
case EVerticalJustification::Five: case EVerticalJustification::NCenter:
state.x70_curY = x8_offsetY + (x10_blockPaddingY - x30_lineY) / 2; state.x70_curY = x8_offsetY + (x10_blockPaddingY - x30_lineY) / 2;
break; break;
case EVerticalJustification::Eight: case EVerticalJustification::Eight:
state.x70_curY = x8_offsetY + (x10_blockPaddingY - x34_lineCount * x24_largestMonoH) / 2; state.x70_curY = x8_offsetY + (x10_blockPaddingY - x34_lineCount * x24_largestMonoH) / 2;
break; break;
case EVerticalJustification::Two: case EVerticalJustification::Bottom:
case EVerticalJustification::Six: case EVerticalJustification::NBottom:
state.x70_curY = x8_offsetY + x10_blockPaddingY - x30_lineY; state.x70_curY = x8_offsetY + x10_blockPaddingY - x30_lineY;
break; break;
case EVerticalJustification::Nine: case EVerticalJustification::Nine:
@ -212,4 +252,43 @@ void CBlockInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf)
SetupPositionLTR(state); 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 CTextExecuteBuffer;
friend class CTextInstruction; friend class CTextInstruction;
s32 x4_ = 0; friend class CImageInstruction;
friend class CWordInstruction;
s32 x4_wordCount = 0;
s32 x8_curX = 0; s32 x8_curX = 0;
s32 xc_curY = 0; s32 xc_curY = 0;
s32 x10_largestMonoHeight = 0; s32 x10_largestMonoHeight = 0;
@ -109,9 +112,9 @@ public:
class CImageInstruction : public CInstruction class CImageInstruction : public CInstruction
{ {
CFontImageDef x0_image; CFontImageDef x4_image;
public: public:
CImageInstruction(const CFontImageDef& image) : x0_image(image) {} CImageInstruction(const CFontImageDef& image) : x4_image(image) {}
void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const;
}; };
@ -127,6 +130,9 @@ class CBlockInstruction : public CInstruction
{ {
friend class CTextExecuteBuffer; friend class CTextExecuteBuffer;
friend class CLineInstruction; friend class CLineInstruction;
friend class CImageInstruction;
friend class CWordInstruction;
s32 x4_offsetX; s32 x4_offsetX;
s32 x8_offsetY; s32 x8_offsetY;
s32 xc_blockPaddingX; s32 xc_blockPaddingX;
@ -154,6 +160,7 @@ public:
class CWordInstruction : public CInstruction class CWordInstruction : public CInstruction
{ {
public: public:
void InvokeLTR(CFontRenderState& state) const;
void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) 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}); x80_texture = store.GetObj({'TXTR', txtrId});
EColorType mode = EColorType(in.readUint32Big()); EColorType mode = EColorType(in.readUint32Big());
/* TODO: Make an enum */ /* TODO: Make an enum */
if (mode == EColorType::One) if (mode == EColorType::Outline)
x2c_mode = EColorType::One; x2c_mode = EColorType::Outline;
else if (mode == EColorType::Zero) else if (mode == EColorType::Main)
x2c_mode = EColorType::Zero; x2c_mode = EColorType::Main;
u32 glyphCount = in.readUint32Big(); u32 glyphCount = in.readUint32Big();
xc_glyphs.reserve(glyphCount); xc_glyphs.reserve(glyphCount);
@ -103,7 +103,7 @@ void CRasterFont::SinglePassDrawString(const CDrawStringOptions& opts, int x, in
{ {
left += x; left += x;
top += glyph->GetBaseline() - y; 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(); x += glyph->GetC() + glyph->GetB();
} }

View File

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

View File

@ -17,22 +17,25 @@ class CSaveableState
friend class CFontInstruction; friend class CFontInstruction;
friend class CLineExtraSpaceInstruction; friend class CLineExtraSpaceInstruction;
friend class CTextInstruction; friend class CTextInstruction;
friend class CLineSpacingInstruction;
friend class CRemoveColorOverrideInstruction;
friend class CWordInstruction;
protected: protected:
CDrawStringOptions x0_drawStrOpts; CDrawStringOptions x0_drawStrOpts;
TToken<CRasterFont> x14_font; TToken<CRasterFont> x14_font;
std::vector<CTextColor> x20_; std::vector<CTextColor> x20_;
std::vector<bool> x30_; std::vector<bool> x30_colorOverrides;
float x40_lineSpacing = 1.f; float x40_lineSpacing = 1.f;
s32 x44_extraLineSpace = 0; s32 x44_extraLineSpace = 0;
bool x48_ = false; bool x48_ = false;
EJustification x4c_just = EJustification::Zero; EJustification x4c_just = EJustification::Left;
EVerticalJustification x50_vjust = EVerticalJustification::Zero; EVerticalJustification x50_vjust = EVerticalJustification::Top;
public: public:
CSaveableState() CSaveableState()
{ {
x20_.resize(3, zeus::CColor::skBlack); 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 (x18_textState.x48_)
{ {
if (w + x70_curLine->x8_curX > x6c_curBlock->xc_blockPaddingX && 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) x7c_curX + w < x6c_curBlock->xc_blockPaddingX)
{ {
MoveWordLTR(); MoveWordLTR();
@ -167,7 +167,7 @@ void CTextExecuteBuffer::MoveWordLTR()
{ {
x70_curLine->xc_curY = std::min(x70_curLine->xc_curY, x84_); x70_curLine->xc_curY = std::min(x70_curLine->xc_curY, x84_);
x88_spaceDistance = 0; x88_spaceDistance = 0;
--x70_curLine->x4_; --x70_curLine->x4_wordCount;
TerminateLineLTR(); TerminateLineLTR();
x70_curLine = static_cast<CLineInstruction*>(x0_instList.emplace(x74_curWordIt, x70_curLine = static_cast<CLineInstruction*>(x0_instList.emplace(x74_curWordIt,
@ -198,7 +198,7 @@ void CTextExecuteBuffer::StartNewWord()
x78_curY = 0; x78_curY = 0;
x80_ = x70_curLine->x8_curX; x80_ = x70_curLine->x8_curX;
x84_ = x70_curLine->xc_curY; x84_ = x70_curLine->xc_curY;
++x70_curLine->x4_; ++x70_curLine->x4_wordCount;
} }
void CTextExecuteBuffer::TerminateLine() void CTextExecuteBuffer::TerminateLine()
@ -214,7 +214,7 @@ void CTextExecuteBuffer::TerminateLineLTR()
x70_curLine->xc_curY = x70_curLine->x10_largestMonoHeight; 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; 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)); 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() void CTextExecuteBuffer::EndBlock()
{ {
if (x70_curLine) if (x70_curLine)

View File

@ -54,6 +54,7 @@ public:
void AddColorOverride(int idx, const CTextColor& color); void AddColorOverride(int idx, const CTextColor& color);
void AddColor(EColorType, const CTextColor& color); void AddColor(EColorType, const CTextColor& color);
void AddImage(const CFontImageDef& image); void AddImage(const CFontImageDef& image);
void AddFont(const TToken<CRasterFont>& font);
void EndBlock(); void EndBlock();
void BeginBlock(s32 offX, s32 offY, s32 padX, s32 padY, void BeginBlock(s32 offX, s32 offY, s32 padX, s32 padY,
ETextDirection dir, EJustification just, 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__ #ifndef __URDE_CTEXTPARSER_HPP__
#define __URDE_CTEXTPARSER_HPP__ #define __URDE_CTEXTPARSER_HPP__
#include "CGuiTextSupport.hpp"
namespace urde namespace urde
{ {
class CTextExecuteBuffer;
class CFontImageDef;
class CTextParser 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);
}; };
} }