2019-12-22 20:04:07 +00:00
|
|
|
#include "Runtime/GuiSys/CTextExecuteBuffer.hpp"
|
|
|
|
|
|
|
|
#include "Runtime/Graphics/CGraphicsPalette.hpp"
|
|
|
|
#include "Runtime/Graphics/CTexture.hpp"
|
|
|
|
#include "Runtime/GuiSys/CFontImageDef.hpp"
|
|
|
|
#include "Runtime/GuiSys/CFontRenderState.hpp"
|
|
|
|
#include "Runtime/GuiSys/CInstruction.hpp"
|
|
|
|
#include "Runtime/GuiSys/CRasterFont.hpp"
|
|
|
|
#include "Runtime/GuiSys/CTextRenderBuffer.hpp"
|
|
|
|
#include "Runtime/GuiSys/CWordBreakTables.hpp"
|
2016-03-19 03:58:01 +00:00
|
|
|
|
2021-04-10 08:42:06 +00:00
|
|
|
namespace metaforce {
|
2016-03-19 03:58:01 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
CTextRenderBuffer CTextExecuteBuffer::BuildRenderBuffer(CGuiWidget::EGuiModelDrawFlags df) const {
|
|
|
|
CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally, df);
|
2016-03-19 03:58:01 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
{
|
|
|
|
CFontRenderState rendState;
|
|
|
|
for (const std::shared_ptr<CInstruction>& inst : x0_instList)
|
|
|
|
inst->Invoke(rendState, &ret);
|
|
|
|
}
|
2016-03-19 03:58:01 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
ret.SetMode(CTextRenderBuffer::EMode::BufferFill);
|
2016-03-19 03:58:01 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
{
|
|
|
|
CFontRenderState rendState;
|
|
|
|
for (const std::shared_ptr<CInstruction>& inst : x0_instList)
|
|
|
|
inst->Invoke(rendState, &ret);
|
|
|
|
}
|
2016-03-19 03:58:01 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
return ret;
|
2016-03-19 03:58:01 +00:00
|
|
|
}
|
|
|
|
|
2016-12-31 00:51:51 +00:00
|
|
|
CTextRenderBuffer CTextExecuteBuffer::BuildRenderBufferPage(InstList::const_iterator start,
|
|
|
|
InstList::const_iterator pgStart,
|
2017-01-29 03:58:16 +00:00
|
|
|
InstList::const_iterator pgEnd,
|
2018-12-08 05:30:43 +00:00
|
|
|
CGuiWidget::EGuiModelDrawFlags df) const {
|
|
|
|
CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally, df);
|
|
|
|
|
|
|
|
{
|
|
|
|
CFontRenderState rendState;
|
|
|
|
for (auto it = start; it != pgStart; ++it) {
|
|
|
|
const std::shared_ptr<CInstruction>& inst = *it;
|
|
|
|
inst->PageInvoke(rendState, &ret);
|
2016-12-31 00:51:51 +00:00
|
|
|
}
|
2018-12-08 05:30:43 +00:00
|
|
|
for (auto it = pgStart; it != pgEnd; ++it) {
|
|
|
|
const std::shared_ptr<CInstruction>& inst = *it;
|
|
|
|
inst->Invoke(rendState, &ret);
|
|
|
|
}
|
|
|
|
}
|
2016-12-31 00:51:51 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
ret.SetMode(CTextRenderBuffer::EMode::BufferFill);
|
2016-12-31 00:51:51 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
{
|
|
|
|
CFontRenderState rendState;
|
|
|
|
for (auto it = start; it != pgStart; ++it) {
|
|
|
|
const std::shared_ptr<CInstruction>& inst = *it;
|
|
|
|
inst->PageInvoke(rendState, &ret);
|
|
|
|
}
|
|
|
|
for (auto it = pgStart; it != pgEnd; ++it) {
|
|
|
|
const std::shared_ptr<CInstruction>& inst = *it;
|
|
|
|
inst->Invoke(rendState, &ret);
|
2016-12-31 00:51:51 +00:00
|
|
|
}
|
2018-12-08 05:30:43 +00:00
|
|
|
}
|
2016-12-31 00:51:51 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
return ret;
|
2016-12-31 00:51:51 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 03:58:16 +00:00
|
|
|
std::list<CTextRenderBuffer> CTextExecuteBuffer::BuildRenderBufferPages(const zeus::CVector2i& extent,
|
2018-12-08 05:30:43 +00:00
|
|
|
CGuiWidget::EGuiModelDrawFlags df) const {
|
|
|
|
std::list<CTextRenderBuffer> ret;
|
|
|
|
|
|
|
|
for (auto it = x0_instList.begin(); it != x0_instList.end();) {
|
|
|
|
CTextRenderBuffer rbuf(CTextRenderBuffer::EMode::AllocTally, df);
|
2016-12-31 00:51:51 +00:00
|
|
|
|
|
|
|
{
|
2018-12-08 05:30:43 +00:00
|
|
|
CFontRenderState rstate;
|
|
|
|
for (auto it2 = x0_instList.begin(); it2 != x0_instList.end(); ++it2) {
|
|
|
|
const std::shared_ptr<CInstruction>& inst2 = *it2;
|
|
|
|
inst2->Invoke(rstate, &rbuf);
|
|
|
|
}
|
|
|
|
}
|
2016-12-31 00:51:51 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
rbuf.SetMode(CTextRenderBuffer::EMode::BufferFill);
|
2016-12-31 00:51:51 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
InstList::const_iterator pageEnd = it;
|
|
|
|
{
|
|
|
|
CFontRenderState rstate;
|
|
|
|
bool seekingToPage = true;
|
|
|
|
for (auto it2 = x0_instList.begin(); it2 != x0_instList.end(); ++it2) {
|
|
|
|
const std::shared_ptr<CInstruction>& inst2 = *it2;
|
|
|
|
if (it2 == it)
|
|
|
|
seekingToPage = false;
|
|
|
|
if (seekingToPage) {
|
|
|
|
inst2->PageInvoke(rstate, &rbuf);
|
|
|
|
} else {
|
|
|
|
inst2->Invoke(rstate, &rbuf);
|
|
|
|
if (!rbuf.HasSpaceAvailable(zeus::CVector2i{}, extent))
|
|
|
|
break;
|
|
|
|
++pageEnd;
|
|
|
|
}
|
|
|
|
}
|
2016-12-31 00:51:51 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
ret.push_back(BuildRenderBufferPage(x0_instList.cbegin(), it, pageEnd, df));
|
|
|
|
it = pageEnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2016-12-31 00:51:51 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
std::vector<CToken> CTextExecuteBuffer::GetAssets() const {
|
|
|
|
size_t totalAssets = 0;
|
|
|
|
for (const std::shared_ptr<CInstruction>& inst : x0_instList)
|
|
|
|
totalAssets += inst->GetAssetCount();
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
std::vector<CToken> ret;
|
|
|
|
ret.reserve(totalAssets);
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
for (const std::shared_ptr<CInstruction>& inst : x0_instList)
|
|
|
|
inst->GetAssets(ret);
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
return ret;
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::AddString(const char16_t* str, int count) {
|
|
|
|
if (!xa4_curLine)
|
|
|
|
StartNewLine();
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
const char16_t* charCur = str;
|
|
|
|
const char16_t* wordCur = str;
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
for (int ac = 0; *charCur && (ac < count || count == -1); ++charCur, ++ac) {
|
|
|
|
if (*charCur == u'\n' || *charCur == u' ') {
|
|
|
|
AddStringFragment(wordCur, charCur - wordCur);
|
|
|
|
wordCur = charCur + 1;
|
|
|
|
if (*charCur == u'\n') {
|
|
|
|
StartNewLine();
|
|
|
|
} else {
|
|
|
|
StartNewWord();
|
|
|
|
int w, h;
|
|
|
|
char16_t space = u' ';
|
|
|
|
x18_textState.x48_font->GetSize(x18_textState.x0_drawStrOpts, w, h, &space, 1);
|
|
|
|
if (xa0_curBlock->x14_dir == ETextDirection::Horizontal) {
|
|
|
|
xa4_curLine->x8_curX += w;
|
|
|
|
xbc_spaceDistance = w;
|
|
|
|
} else {
|
|
|
|
xa4_curLine->xc_curY += h;
|
|
|
|
xbc_spaceDistance = h;
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
2018-12-08 05:30:43 +00:00
|
|
|
}
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
2018-12-08 05:30:43 +00:00
|
|
|
}
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
if (charCur > wordCur)
|
|
|
|
AddStringFragment(wordCur, charCur - wordCur);
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::AddStringFragment(const char16_t* str, int len) {
|
|
|
|
if (xa0_curBlock->x14_dir == ETextDirection::Horizontal)
|
|
|
|
for (int i = 0; i < len;)
|
|
|
|
i += WrapOneLTR(str + i, len - i);
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
int CTextExecuteBuffer::WrapOneLTR(const char16_t* str, int len) {
|
|
|
|
if (!x18_textState.x48_font)
|
|
|
|
return len;
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
CRasterFont* font = x18_textState.x48_font.GetObj();
|
|
|
|
int rem = len;
|
|
|
|
int w, h;
|
|
|
|
x18_textState.x48_font->GetSize(x18_textState.x0_drawStrOpts, w, h, str, len);
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
if (x18_textState.x7c_enableWordWrap) {
|
|
|
|
if (w + xa4_curLine->x8_curX > xa0_curBlock->xc_blockExtentX && xa4_curLine->x4_wordCount >= 1 &&
|
|
|
|
xb0_curX + w < xa0_curBlock->xc_blockExtentX) {
|
|
|
|
MoveWordLTR();
|
|
|
|
}
|
|
|
|
if (w + xa4_curLine->x8_curX > xa0_curBlock->xc_blockExtentX && len > 1) {
|
|
|
|
const char16_t* strEnd = str + len;
|
|
|
|
int aRank = 5;
|
|
|
|
|
|
|
|
do {
|
|
|
|
--rem;
|
|
|
|
--strEnd;
|
|
|
|
int endRank = 4;
|
|
|
|
if (len > 2)
|
|
|
|
endRank = CWordBreakTables::GetEndRank(*(strEnd - 1));
|
|
|
|
|
|
|
|
int beginRank = CWordBreakTables::GetBeginRank(*strEnd);
|
|
|
|
|
|
|
|
if (endRank < aRank && endRank <= beginRank) {
|
|
|
|
aRank = endRank;
|
|
|
|
} else {
|
|
|
|
x18_textState.x48_font->GetSize(x18_textState.x0_drawStrOpts, w, h, str, rem);
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
2018-12-08 05:30:43 +00:00
|
|
|
|
|
|
|
} while (w + xa4_curLine->x8_curX > xa0_curBlock->xc_blockExtentX && rem > 1);
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
2018-12-08 05:30:43 +00:00
|
|
|
}
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
xac_curY = std::max(xac_curY, font->GetMonoHeight());
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
xa4_curLine->TestLargestFont(font->GetMonoWidth(), font->GetMonoHeight(), font->GetBaseline());
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
xa4_curLine->x8_curX += w;
|
|
|
|
xa0_curBlock->x2c_lineX = std::max(xa0_curBlock->x2c_lineX, xa4_curLine->x8_curX);
|
|
|
|
xb0_curX += w;
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
x0_instList.emplace(x0_instList.cend(), std::make_shared<CTextInstruction>(str, rem));
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
if (rem != len)
|
|
|
|
StartNewLine();
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
return rem;
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::MoveWordLTR() {
|
|
|
|
xa4_curLine->x8_curX -= (xb0_curX + xbc_spaceDistance);
|
|
|
|
xa4_curLine->xc_curY = std::min(xa4_curLine->xc_curY, xb8_curWordY);
|
|
|
|
xbc_spaceDistance = 0;
|
|
|
|
--xa4_curLine->x4_wordCount;
|
|
|
|
TerminateLineLTR();
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
xa4_curLine = static_cast<CLineInstruction*>(
|
|
|
|
x0_instList
|
|
|
|
.emplace(xa8_curWordIt, std::make_shared<CLineInstruction>(x18_textState.x80_just, x18_textState.x84_vjust,
|
|
|
|
xc0_imageBaseline))
|
|
|
|
->get());
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
// Dunno what's up with this in the original; seems fine without
|
2020-05-04 02:27:48 +00:00
|
|
|
x0_instList.emplace(xa8_curWordIt, std::make_shared<CWordInstruction>());
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
++xa0_curBlock->x34_lineCount;
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::StartNewLine() {
|
|
|
|
if (xa4_curLine)
|
|
|
|
TerminateLine();
|
2016-03-19 03:58:01 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
xa8_curWordIt = x0_instList.emplace(
|
|
|
|
x0_instList.cend(),
|
|
|
|
std::make_shared<CLineInstruction>(x18_textState.x80_just, x18_textState.x84_vjust, xc0_imageBaseline));
|
|
|
|
xa4_curLine = static_cast<CLineInstruction*>(xa8_curWordIt->get());
|
|
|
|
xbc_spaceDistance = 0;
|
2016-03-19 03:58:01 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
StartNewWord();
|
|
|
|
++xa0_curBlock->x34_lineCount;
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::StartNewWord() {
|
|
|
|
xa8_curWordIt = x0_instList.emplace(x0_instList.cend(), std::make_shared<CWordInstruction>());
|
|
|
|
xb0_curX = 0;
|
|
|
|
xac_curY = 0;
|
|
|
|
xb4_curWordX = xa4_curLine->x8_curX;
|
|
|
|
xb8_curWordY = xa4_curLine->xc_curY;
|
|
|
|
++xa4_curLine->x4_wordCount;
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::TerminateLine() {
|
|
|
|
if (xa0_curBlock->x14_dir == ETextDirection::Horizontal)
|
|
|
|
TerminateLineLTR();
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::TerminateLineLTR() {
|
2021-06-04 06:21:36 +00:00
|
|
|
if (!xa4_curLine->xc_curY /*&& x18_textState.IsFinishedLoading()*/) {
|
2018-12-08 05:30:43 +00:00
|
|
|
xa4_curLine->xc_curY = std::max(xa4_curLine->GetHeight(), x18_textState.x48_font->GetCarriageAdvance());
|
|
|
|
}
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
if (xa0_curBlock->x1c_vertJustification == EVerticalJustification::Full) {
|
|
|
|
xa0_curBlock->x30_lineY += xa4_curLine->xc_curY;
|
|
|
|
} else {
|
|
|
|
xa0_curBlock->x30_lineY += x18_textState.x78_extraLineSpace + xa4_curLine->xc_curY * x18_textState.x74_lineSpacing;
|
|
|
|
}
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::AddPopState() {
|
|
|
|
x0_instList.emplace(x0_instList.cend(), std::make_shared<CPopStateInstruction>());
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
x18_textState = xc4_stateStack.back();
|
|
|
|
xc4_stateStack.pop_back();
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2020-05-04 02:27:48 +00:00
|
|
|
if (xa4_curLine->x8_curX == 0) {
|
2018-12-08 05:30:43 +00:00
|
|
|
xa4_curLine->x28_just = x18_textState.x80_just;
|
|
|
|
xa4_curLine->x2c_vjust = x18_textState.x84_vjust;
|
|
|
|
}
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::AddPushState() {
|
|
|
|
x0_instList.emplace(x0_instList.cend(), std::make_shared<CPushStateInstruction>());
|
|
|
|
xc4_stateStack.push_back(x18_textState);
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::AddVerticalJustification(EVerticalJustification vjust) {
|
|
|
|
x18_textState.x84_vjust = vjust;
|
|
|
|
if (!xa4_curLine)
|
|
|
|
return;
|
|
|
|
if (xa4_curLine->x8_curX)
|
|
|
|
return;
|
|
|
|
xa4_curLine->x2c_vjust = vjust;
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::AddJustification(EJustification just) {
|
|
|
|
x18_textState.x80_just = just;
|
|
|
|
if (!xa4_curLine)
|
|
|
|
return;
|
|
|
|
if (xa4_curLine->x8_curX)
|
|
|
|
return;
|
|
|
|
xa4_curLine->x28_just = just;
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::AddLineExtraSpace(s32 space) {
|
|
|
|
x0_instList.emplace(x0_instList.cend(), std::make_shared<CLineExtraSpaceInstruction>(space));
|
|
|
|
x18_textState.x78_extraLineSpace = space;
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::AddLineSpacing(float spacing) {
|
|
|
|
x0_instList.emplace(x0_instList.cend(), std::make_shared<CLineSpacingInstruction>(spacing));
|
|
|
|
x18_textState.x74_lineSpacing = spacing;
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::AddRemoveColorOverride(int idx) {
|
|
|
|
x0_instList.emplace(x0_instList.cend(), std::make_shared<CRemoveColorOverrideInstruction>(idx));
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::AddColorOverride(int idx, const CTextColor& color) {
|
|
|
|
x0_instList.emplace(x0_instList.cend(), std::make_shared<CColorOverrideInstruction>(idx, color));
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::AddColor(EColorType tp, const CTextColor& color) {
|
|
|
|
x0_instList.emplace(x0_instList.cend(), std::make_shared<CColorInstruction>(tp, color));
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::AddImage(const CFontImageDef& image) {
|
|
|
|
if (!xa4_curLine)
|
|
|
|
StartNewLine();
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
if (xa0_curBlock) {
|
|
|
|
const CTexture* tex = image.x4_texs[0].GetObj();
|
|
|
|
int width = tex->GetWidth() * image.x14_cropFactor.x();
|
|
|
|
int height = tex->GetHeight() * image.x14_cropFactor.y();
|
2016-03-20 06:37:08 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
if (x18_textState.x7c_enableWordWrap && xa4_curLine->x8_curX + width > xa0_curBlock->xc_blockExtentX &&
|
|
|
|
xa4_curLine->x4_wordCount > 1)
|
|
|
|
StartNewLine();
|
2017-01-30 04:16:20 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
xa4_curLine->TestLargestImage(width, height, image.CalculateBaseline());
|
2017-01-30 04:16:20 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
xa4_curLine->x8_curX += width;
|
|
|
|
if (xa4_curLine->x8_curX > width)
|
|
|
|
xa0_curBlock->x2c_lineX = xa4_curLine->x8_curX;
|
|
|
|
}
|
2016-03-20 06:37:08 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
x0_instList.emplace(x0_instList.cend(), std::make_shared<CImageInstruction>(image));
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::AddFont(const TToken<CRasterFont>& font) {
|
|
|
|
x0_instList.emplace(x0_instList.cend(), std::make_shared<CFontInstruction>(font));
|
|
|
|
x18_textState.x48_font = font;
|
2016-03-21 00:25:53 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
if (xa0_curBlock)
|
|
|
|
xa0_curBlock->TestLargestFont(font->GetMonoWidth(), font->GetMonoHeight(), font->GetBaseline());
|
2016-03-21 00:25:53 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
if (xa4_curLine)
|
|
|
|
xa4_curLine->TestLargestFont(font->GetMonoWidth(), font->GetMonoHeight(), font->GetBaseline());
|
2016-03-21 00:25:53 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::EndBlock() {
|
|
|
|
if (xa4_curLine)
|
|
|
|
TerminateLine();
|
|
|
|
xa4_curLine = nullptr;
|
|
|
|
xa0_curBlock = nullptr;
|
2016-03-20 00:32:30 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::BeginBlock(s32 offX, s32 offY, s32 extX, s32 extY, bool imageBaseline, ETextDirection dir,
|
|
|
|
EJustification just, EVerticalJustification vjust) {
|
|
|
|
xc0_imageBaseline = imageBaseline;
|
|
|
|
xa0_curBlock = static_cast<CBlockInstruction*>(
|
|
|
|
x0_instList
|
|
|
|
.emplace(x0_instList.cend(), std::make_shared<CBlockInstruction>(offX, offY, extX, extY, dir, just, vjust))
|
|
|
|
->get());
|
2016-03-20 06:37:08 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
if (x18_textState.x48_font) {
|
|
|
|
CRasterFont* font = x18_textState.x48_font.GetObj();
|
|
|
|
s32 baseline = font->GetBaseline();
|
|
|
|
s32 monoH = font->GetMonoHeight();
|
|
|
|
s32 monoW = font->GetMonoWidth();
|
|
|
|
xa0_curBlock->TestLargestFont(monoW, monoH, baseline);
|
|
|
|
}
|
|
|
|
|
|
|
|
x18_textState.x0_drawStrOpts.x0_direction = dir;
|
|
|
|
x18_textState.x80_just = just;
|
|
|
|
x18_textState.x84_vjust = vjust;
|
2016-03-19 03:58:01 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CTextExecuteBuffer::Clear() {
|
|
|
|
x0_instList.clear();
|
|
|
|
x18_textState = CSaveableState();
|
|
|
|
xa0_curBlock = nullptr;
|
|
|
|
xa4_curLine = nullptr;
|
|
|
|
xa8_curWordIt = x0_instList.begin();
|
|
|
|
xb4_curWordX = 0;
|
|
|
|
xb8_curWordY = 0;
|
|
|
|
xbc_spaceDistance = 0;
|
2016-03-19 03:58:01 +00:00
|
|
|
}
|
|
|
|
|
2021-04-10 08:42:06 +00:00
|
|
|
} // namespace metaforce
|