mirror of https://github.com/AxioDL/metaforce.git
CTextParser imps
This commit is contained in:
parent
6a2d791269
commit
89daac544f
|
@ -256,6 +256,7 @@ public:
|
|||
return ((TToken<T>*)this)->GetObj();
|
||||
}
|
||||
T* operator->() {return GetObj();}
|
||||
const T* operator->() const {return GetObj();}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue