diff --git a/config/GM8E01_00/splits.txt b/config/GM8E01_00/splits.txt index 6ddd26b2..00de826a 100644 --- a/config/GM8E01_00/splits.txt +++ b/config/GM8E01_00/splits.txt @@ -2914,7 +2914,6 @@ Kyoto/Text/CFontInstruction.cpp: Kyoto/Text/CFontRenderState.cpp: .text start:0x802FECC4 end:0x802FF80C .rodata start:0x803D6E60 end:0x803D6E68 - .sdata2 start:0x805AE458 end:0x805AE460 Kyoto/Text/CLineExtraSpaceInstruction.cpp: .text start:0x802FF80C end:0x802FF8A0 @@ -2923,6 +2922,7 @@ Kyoto/Text/CLineExtraSpaceInstruction.cpp: Kyoto/Text/CLineInstruction.cpp: .text start:0x802FF8A0 end:0x802FFCAC .data start:0x803ED630 end:0x803ED678 + .sdata2 start:0x805AE458 end:0x805AE460 Kyoto/Text/CLineSpacingInstruction.cpp: .text start:0x802FFCAC end:0x802FFD40 diff --git a/config/GM8E01_00/symbols.txt b/config/GM8E01_00/symbols.txt index 3c7bd733..8a50a5d7 100644 --- a/config/GM8E01_00/symbols.txt +++ b/config/GM8E01_00/symbols.txt @@ -13231,10 +13231,10 @@ PageInvoke__26CLineExtraSpaceInstructionCFR16CFontRenderStateP17CTextRenderBuffe Invoke__26CLineExtraSpaceInstructionCFR16CFontRenderStateP17CTextRenderBuffer = .text:0x802FF894; // type:function size:0xC scope:global __dt__16CLineInstructionFv = .text:0x802FF8A0; // type:function size:0x5C scope:global GetBaseline__16CLineInstructionCFv = .text:0x802FF8FC; // type:function size:0x38 scope:global -GetHeight__16CLineInstructionFv = .text:0x802FF934; // type:function size:0x38 scope:global +GetHeight__16CLineInstructionCFv = .text:0x802FF934; // type:function size:0x38 scope:global TestLargestImage__16CLineInstructionFiii = .text:0x802FF96C; // type:function size:0x38 scope:global TestLargestFont__16CLineInstructionFiii = .text:0x802FF9A4; // type:function size:0x38 scope:global -SetLineSpacing__16CFontRenderStateFf = .text:0x802FF9DC; // type:function size:0x244 scope:global +InvokeTTB__16CLineInstructionCFR16CFontRenderState = .text:0x802FF9DC; // type:function size:0x244 scope:global PageInvoke__16CLineInstructionCFR16CFontRenderStateP17CTextRenderBuffer = .text:0x802FFC20; // type:function size:0x38 scope:global Invoke__16CLineInstructionCFR16CFontRenderStateP17CTextRenderBuffer = .text:0x802FFC58; // type:function size:0x54 scope:global __dt__23CLineSpacingInstructionFv = .text:0x802FFCAC; // type:function size:0x5C scope:weak @@ -18839,7 +18839,7 @@ __vt__17CColorInstruction = .data:0x803ED5B0; // type:object size:0x1C scope:glo __vt__25CColorOverrideInstruction = .data:0x803ED5D0; // type:object size:0x1C scope:global __vt__16CFontInstruction = .data:0x803ED5F0; // type:object size:0x1C __vt__26CLineExtraSpaceInstruction = .data:0x803ED610; // type:object size:0x1C scope:global -lbl_803ED630 = .data:0x803ED630; // type:object size:0x1C +__vt__16CLineInstruction = .data:0x803ED630; // type:object size:0x1C jumptable_803ED64C = .data:0x803ED64C; // type:object size:0x28 scope:local __vt__23CLineSpacingInstruction = .data:0x803ED678; // type:object size:0x1C scope:global __vt__20CPopStateInstruction = .data:0x803ED698; // type:object size:0x1C scope:global @@ -26565,7 +26565,7 @@ lbl_805AE43C = .sdata2:0x805AE43C; // type:object size:0x4 align:4 data:float lbl_805AE440 = .sdata2:0x805AE440; // type:object size:0x8 align:8 data:double lbl_805AE448 = .sdata2:0x805AE448; // type:object size:0x8 align:4 data:float lbl_805AE450 = .sdata2:0x805AE450; // type:object size:0x4 align:4 data:float -lbl_805AE458 = .sdata2:0x805AE458; // type:object size:0x8 align:8 data:double +@480 = .sdata2:0x805AE458; // type:object size:0x8 scope:local align:8 data:double lbl_805AE460 = .sdata2:0x805AE460; // type:object size:0x8 align:4 data:float @388 = .sdata2:0x805AE468; // type:object size:0x4 scope:local align:4 data:float lbl_805AE470 = .sdata2:0x805AE470; // type:object size:0x8 align:8 data:double diff --git a/config/GM8E01_01/splits.txt b/config/GM8E01_01/splits.txt index 62263229..7e85fe00 100644 --- a/config/GM8E01_01/splits.txt +++ b/config/GM8E01_01/splits.txt @@ -2914,7 +2914,6 @@ Kyoto/Text/CFontInstruction.cpp: Kyoto/Text/CFontRenderState.cpp: .text start:0x802FEDA4 end:0x802FF8EC .rodata start:0x803D7040 end:0x803D7048 - .sdata2 start:0x805AE638 end:0x805AE640 Kyoto/Text/CLineExtraSpaceInstruction.cpp: .text start:0x802FF8EC end:0x802FF980 @@ -2923,6 +2922,7 @@ Kyoto/Text/CLineExtraSpaceInstruction.cpp: Kyoto/Text/CLineInstruction.cpp: .text start:0x802FF980 end:0x802FFD8C .data start:0x803ED810 end:0x803ED858 + .sdata2 start:0x805AE638 end:0x805AE640 Kyoto/Text/CLineSpacingInstruction.cpp: .text start:0x802FFD8C end:0x802FFE20 diff --git a/config/GM8E01_01/symbols.txt b/config/GM8E01_01/symbols.txt index 8db66eb7..7c2b1cdc 100644 --- a/config/GM8E01_01/symbols.txt +++ b/config/GM8E01_01/symbols.txt @@ -13231,10 +13231,10 @@ PageInvoke__26CLineExtraSpaceInstructionCFR16CFontRenderStateP17CTextRenderBuffe Invoke__26CLineExtraSpaceInstructionCFR16CFontRenderStateP17CTextRenderBuffer = .text:0x802FF974; // type:function size:0xC scope:global __dt__16CLineInstructionFv = .text:0x802FF980; // type:function size:0x5C scope:global GetBaseline__16CLineInstructionCFv = .text:0x802FF9DC; // type:function size:0x38 scope:global -GetHeight__16CLineInstructionFv = .text:0x802FFA14; // type:function size:0x38 scope:global +GetHeight__16CLineInstructionCFv = .text:0x802FFA14; // type:function size:0x38 scope:global TestLargestImage__16CLineInstructionFiii = .text:0x802FFA4C; // type:function size:0x38 scope:global TestLargestFont__16CLineInstructionFiii = .text:0x802FFA84; // type:function size:0x38 scope:global -SetLineSpacing__16CFontRenderStateFf = .text:0x802FFABC; // type:function size:0x244 scope:global +InvokeTTB__16CLineInstructionCFR16CFontRenderState = .text:0x802FFABC; // type:function size:0x244 scope:global PageInvoke__16CLineInstructionCFR16CFontRenderStateP17CTextRenderBuffer = .text:0x802FFD00; // type:function size:0x38 scope:global Invoke__16CLineInstructionCFR16CFontRenderStateP17CTextRenderBuffer = .text:0x802FFD38; // type:function size:0x54 scope:global __dt__23CLineSpacingInstructionFv = .text:0x802FFD8C; // type:function size:0x5C scope:weak @@ -18746,7 +18746,7 @@ __vt__17CColorInstruction = .data:0x803ED790; // type:object size:0x1C __vt__25CColorOverrideInstruction = .data:0x803ED7B0; // type:object size:0x1C __vt__16CFontInstruction = .data:0x803ED7D0; // type:object size:0x1C __vt__26CLineExtraSpaceInstruction = .data:0x803ED7F0; // type:object size:0x1C -lbl_803ED810 = .data:0x803ED810; // type:object size:0x1C +__vt__16CLineInstruction = .data:0x803ED810; // type:object size:0x1C jumptable_803ED82C = .data:0x803ED82C; // type:object size:0x28 scope:local __vt__23CLineSpacingInstruction = .data:0x803ED858; // type:object size:0x1C __vt__20CPopStateInstruction = .data:0x803ED878; // type:object size:0x1C diff --git a/config/GM8E01_48/symbols.txt b/config/GM8E01_48/symbols.txt index 33bbc7d0..7b2359be 100644 --- a/config/GM8E01_48/symbols.txt +++ b/config/GM8E01_48/symbols.txt @@ -13231,10 +13231,10 @@ PageInvoke__26CLineExtraSpaceInstructionCFR16CFontRenderStateP17CTextRenderBuffe Invoke__26CLineExtraSpaceInstructionCFR16CFontRenderStateP17CTextRenderBuffer = .text:0x802FFA04; // type:function size:0xC __dt__16CLineInstructionFv = .text:0x802FFA10; // type:function size:0x5C GetBaseline__16CLineInstructionCFv = .text:0x802FFA6C; // type:function size:0x38 -GetHeight__16CLineInstructionFv = .text:0x802FFAA4; // type:function size:0x38 +GetHeight__16CLineInstructionCFv = .text:0x802FFAA4; // type:function size:0x38 TestLargestImage__16CLineInstructionFiii = .text:0x802FFADC; // type:function size:0x38 TestLargestFont__16CLineInstructionFiii = .text:0x802FFB14; // type:function size:0x38 -SetLineSpacing__16CFontRenderStateFf = .text:0x802FFB4C; // type:function size:0x244 +InvokeTTB__16CLineInstructionCFR16CFontRenderState = .text:0x802FFB4C; // type:function size:0x244 PageInvoke__16CLineInstructionCFR16CFontRenderStateP17CTextRenderBuffer = .text:0x802FFD90; // type:function size:0x38 Invoke__16CLineInstructionCFR16CFontRenderStateP17CTextRenderBuffer = .text:0x802FFDC8; // type:function size:0x54 __dt__23CLineSpacingInstructionFv = .text:0x802FFE1C; // type:function size:0x5C diff --git a/configure.py b/configure.py index c2c41208..26b2b767 100755 --- a/configure.py +++ b/configure.py @@ -1432,7 +1432,7 @@ def MatchingFor(*versions): MatchingFor("GM8E01_00", "GM8E01_01"), "Kyoto/Text/CLineExtraSpaceInstruction.cpp", ), - Object(NonMatching, "Kyoto/Text/CLineInstruction.cpp"), + Object(MatchingFor("GM8E01_00", "GM8E01_01"), "Kyoto/Text/CLineInstruction.cpp"), Object( MatchingFor("GM8E01_00", "GM8E01_01"), "Kyoto/Text/CLineSpacingInstruction.cpp", diff --git a/include/Kyoto/Text/CFontRenderState.hpp b/include/Kyoto/Text/CFontRenderState.hpp index aed22f3d..93451a0f 100644 --- a/include/Kyoto/Text/CFontRenderState.hpp +++ b/include/Kyoto/Text/CFontRenderState.hpp @@ -1,6 +1,7 @@ #ifndef _CFONTRENDERSTATE #define _CFONTRENDERSTATE +#include "Kyoto/Text/CBlockInstruction.hpp" #include "Kyoto/Text/CDrawStringOptions.hpp" #include "Kyoto/Text/CRasterFont.hpp" #include "Kyoto/Text/CSaveableState.hpp" @@ -9,21 +10,6 @@ class CBlockInstruction; class CLineInstruction; -namespace rstl { -template < typename T, typename Container = vector< T > > -class stack { -public: - stack(const typename Container::allocator_type& allocator = typename Container::allocator_type()) - : container(allocator) {} - - void push(const T& v) { container.push_back(v); } - T& top() { return container.front(); } - void pop() { container.pop_back(); } - -private: - Container container; -}; -} // namespace rstl class CFontRenderState { public: CFontRenderState(); @@ -38,7 +24,9 @@ class CFontRenderState { void SetFont(const TToken< CRasterFont >& font) { x0_state.SetFont(font); } rstl::vector< CTextColor >& GetColors() { return x0_state.GetColors(); } rstl::vector< bool >& GetOverride() { return x0_state.GetOverride(); } + float GetLineSpacing() const { return x0_state.GetLineSpacing(); } void SetLineSpacing(float spacing) { x0_state.SetLineSpacing(spacing); } + int GetLineExtraSpacing() const { return x0_state.GetLineExtraSpacing(); } void SetExtraLineSpace(int spacing) { x0_state.SetLineExtraSpace(spacing); } const CBlockInstruction* GetBlock() const { return x88_curBlock; } void SetBlock(const CBlockInstruction* block) { @@ -52,6 +40,23 @@ class CFontRenderState { bool IsFirstWordOnLine() const { return x108_lineInitialized; } void SetFirstWordOnLine(bool v) { x108_lineInitialized = v; } + void SetLine(const CLineInstruction* line) { xdc_currentLineInst = line; } + + void SubX(const int x) { xd4_curX -= x; } + + void AddX(const int x) { xd4_curX += x; } + + void SubY(const int y) { xd8_curY -= y; } + void AddY(const int y) { xd8_curY += y; } + + int GetSpacing(const int v) const { + if (GetBlock()->GetVerticalJustification() == kVerticalJustification_Full) { + return v; + } + + return (static_cast< int >(static_cast< float >(v) * GetLineSpacing()) + GetLineExtraSpacing()); + } + private: CSaveableState x0_state; CBlockInstruction* x88_curBlock; diff --git a/include/Kyoto/Text/CLineInstruction.hpp b/include/Kyoto/Text/CLineInstruction.hpp index 3e915a7d..20ccede6 100644 --- a/include/Kyoto/Text/CLineInstruction.hpp +++ b/include/Kyoto/Text/CLineInstruction.hpp @@ -2,17 +2,39 @@ #define _CLINEINSTRUCTION #include "Kyoto/Text/CInstruction.hpp" +#include "Kyoto/Text/TextCommon.hpp" + class CLineInstruction : public CInstruction { public: + CLineInstruction(int width, int height, int baseline, EJustification justification, + EVerticalJustification verticalJustification); + + int GetHeight() const; int GetBaseline() const; - int GetX() const { return x8_x; } - int GetY() const { return xc_y; } + void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const override; + void InvokeTTB(CFontRenderState& state) const; + void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const override; + + void TestLargestFont(const int width, const int height, const int baseLine); + void TestLargestImage(const int width, const int height, const int baseline); + + int GetX() const { return mCurX; } + int GetY() const { return mCurY; } private: - int x4_unk; - int x8_x; - int xc_y; + int mWordCount; + int mCurX; + int mCurY; + int mLargestFontHeight; + int mLargestFontWidth; + int mLargestFontBaseline; + int mLargestImageHeight; + int mLargestImageWidth; + int mLargestImageBaseline; + EJustification mJustification; + EVerticalJustification mVerticalJustification; + bool mImageBaseline; }; #endif // _CLINEINSTRUCTION diff --git a/include/Kyoto/Text/CSaveableState.hpp b/include/Kyoto/Text/CSaveableState.hpp index 19eb140d..41aabf9f 100644 --- a/include/Kyoto/Text/CSaveableState.hpp +++ b/include/Kyoto/Text/CSaveableState.hpp @@ -15,18 +15,19 @@ class CSaveableState { CDrawStringOptions& GetOptions() { return x0_drawStringOptions; } rstl::optional_object< TToken< CRasterFont > >& GetFont() { return x48_font; } - void SetFont(const TToken& font) { x48_font = font; } - rstl::vector& GetColors() { return x54_colors; } - rstl::vector& GetOverride() { return x64_colorOverrides; } + void SetFont(const TToken< CRasterFont >& font) { x48_font = font; } + rstl::vector< CTextColor >& GetColors() { return x54_colors; } + rstl::vector< bool >& GetOverride() { return x64_colorOverrides; } + float GetLineSpacing() const { return x74_lineSpacing; } void SetLineSpacing(float spacing) { x74_lineSpacing = spacing; } + int GetLineExtraSpacing() const { return x78_extraLineSpacing; } void SetLineExtraSpace(int spacing) { x78_extraLineSpacing = spacing; } - -//private: + // private: CDrawStringOptions x0_drawStringOptions; rstl::optional_object< TToken< CRasterFont > > x48_font; rstl::vector< CTextColor > x54_colors; - rstl::vector x64_colorOverrides; + rstl::vector< bool > x64_colorOverrides; float x74_lineSpacing; int x78_extraLineSpacing; bool x7c_enableWordWrap; diff --git a/src/Kyoto/Text/CLineInstruction.cpp b/src/Kyoto/Text/CLineInstruction.cpp new file mode 100644 index 00000000..5d0e5b70 --- /dev/null +++ b/src/Kyoto/Text/CLineInstruction.cpp @@ -0,0 +1,126 @@ +#include "Kyoto/Text/CLineInstruction.hpp" + +#include "Kyoto/Text/CBlockInstruction.hpp" +#include "Kyoto/Text/CFontRenderState.hpp" + +void CLineInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + if (state.GetBlock()->GetTextDirection() == kTD_Horizontal) { + InvokeTTB(state); + } + + state.SetFirstWordOnLine(true); + state.SetLine(this); +} + +void CLineInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + if (state.GetLine() != nullptr) { + return; + } + Invoke(state, buf); +} + +void CLineInstruction::InvokeTTB(CFontRenderState& state) const { + switch (mJustification) { + case kJustification_Left: + case kJustification_Full: + case kJustification_NLeft: + case kJustification_LeftMono: + state.SetX(state.GetBlock()->GetOutputX()); + break; + case kJustification_Center: + case kJustification_CenterMono: + state.SetX(state.GetBlock()->GetOutputX() + state.GetBlock()->GetOutputWidth() / 2 - mCurX / 2); + break; + case kJustification_NCenter: + if (mWordCount == 1) { + state.SetX(state.GetBlock()->GetOutputX() + state.GetBlock()->GetOutputWidth() / 2 - + mCurX / 2); + } else { + state.SetX(state.GetBlock()->GetOutputX() + state.GetBlock()->GetOutputWidth() / 2 - + state.GetBlock()->GetLineX() / 2); + } + break; + case kJustification_Right: + case kJustification_RightMono: + state.SetX(state.GetBlock()->GetOutputX() + state.GetBlock()->GetOutputWidth() - mCurX); + break; + case kJustification_NRight: + state.SetX(state.GetBlock()->GetOutputX() + state.GetBlock()->GetOutputWidth() - + state.GetBlock()->GetLineX()); + break; + default: + break; + } + + if (state.GetLine() == nullptr) { + return; + } + const CLineInstruction& inst = *state.GetLine(); + int val = 0; + + switch (state.GetBlock()->GetVerticalJustification()) { + case kVerticalJustification_Top: + case kVerticalJustification_Center: + case kVerticalJustification_Bottom: + case kVerticalJustification_NTop: + case kVerticalJustification_NCenter: + case kVerticalJustification_NBottom: + val = inst.GetY(); + break; + case kVerticalJustification_Full: { + const int tmp = state.GetBlock()->GetOutputHeight() - state.GetBlock()->GetLineY(); + val = (state.GetBlock()->GetLines() > 1 ? tmp / (state.GetBlock()->GetLines() - 1) : 0) + + inst.GetY(); + break; + } + case kVerticalJustification_TopMono: { + val = state.GetBlock()->GetLargestFontHeight(); + } break; + case kVerticalJustification_CenterMono: { + val = ((inst.GetY() - state.GetBlock()->GetLargestFontHeight()) / 2) + + state.GetBlock()->GetLargestFontHeight(); + } break; + case kVerticalJustification_RightMono: { + int tmp = state.GetBlock()->GetLargestFontHeight() * 2; + val = tmp - inst.GetY(); + } break; + default: + break; + } + state.AddY(state.GetSpacing(val)); +} + +void CLineInstruction::TestLargestFont(const int width, const int height, const int baseLine) { + if (mLargestFontBaseline == 0) { + mLargestFontBaseline = baseLine; + } + if (mLargestFontWidth < width) { + mLargestFontWidth = width; + } + if (mLargestFontHeight < height) { + mLargestFontHeight = height; + mLargestFontBaseline = baseLine; + } +} + +void CLineInstruction::TestLargestImage(const int width, const int height, const int baseline) { + if (mLargestImageBaseline == 0) { + mLargestImageBaseline = baseline; + } + if (mLargestImageWidth < width) { + mLargestImageWidth = width; + } + if (mLargestImageHeight < height) { + mLargestImageHeight = height; + mLargestImageBaseline = baseline; + } +} + +int CLineInstruction::GetHeight() const { + return (mLargestFontHeight != 0 && !mImageBaseline) ? mLargestFontHeight : mLargestImageHeight; +} + +int CLineInstruction::GetBaseline() const { + return (mLargestFontHeight != 0 && !mImageBaseline) ? mLargestFontBaseline + : mLargestImageBaseline; +} \ No newline at end of file