Added centered text in textboxes in FT mode.

This commit is contained in:
Muzychenko Andrey 2021-11-20 19:03:22 +03:00
parent 2229f9b70e
commit 3b7dc0dae2
2 changed files with 78 additions and 49 deletions

View File

@ -4,6 +4,7 @@
#include "control.h" #include "control.h"
#include "fullscrn.h" #include "fullscrn.h"
#include "loader.h" #include "loader.h"
#include "pb.h"
#include "render.h" #include "render.h"
#include "score.h" #include "score.h"
#include "timer.h" #include "timer.h"
@ -84,7 +85,7 @@ void TTextBox::Clear()
OffsetX, OffsetX,
OffsetY); OffsetY);
else else
gdrv::fill_bitmap(render::vscreen, Width, Height, OffsetX, OffsetY, 0); gdrv::fill_bitmap(render::vscreen, Width, Height, OffsetX, OffsetY, 0);
if (Timer) if (Timer)
{ {
if (Timer != -1) if (Timer != -1)
@ -186,8 +187,7 @@ void TTextBox::Draw()
if (display) if (display)
{ {
auto font = Font; if (!Font)
if (!font)
{ {
gdrv::grtext_draw_ttext_in_box( gdrv::grtext_draw_ttext_in_box(
Message1->Text, Message1->Text,
@ -199,64 +199,84 @@ void TTextBox::Draw()
return; return;
} }
auto text = Message1->Text; std::vector<LayoutResult> lines{};
for (auto y = OffsetY; ; y += font->Height) auto textHeight = 0;
for (auto text = Message1->Text; ; textHeight += Font->Height)
{ {
auto curChar = *text; if (!text[0] || textHeight + Font->Height > Height)
if (!curChar || y + font->Height > OffsetY + Height)
break; break;
auto totalWidth = 0; auto line = LayoutTextLine(text);
char* textEndSpace = nullptr; if (line.Start == line.End)
auto textEnd = text; break;
while (true) lines.push_back(line);
{ text = line.End;
auto maskedChar = curChar & 0x7F; }
if (!maskedChar || maskedChar == '\n')
break;
auto charBmp = font->Chars[maskedChar];
if (charBmp)
{
auto width = charBmp->Width + font->GapWidth + totalWidth;
if (width > Width)
{
if (textEndSpace)
textEnd = textEndSpace;
break;
}
if (*textEnd == ' ')
textEndSpace = textEnd;
curChar = *(textEnd + 1);
totalWidth = width;
++textEnd;
}
else
{
curChar = *textEnd;
}
}
// Textboxes in FT display texts centered
auto offY = OffsetY;
if (pb::FullTiltMode)
offY += (Height - textHeight) / 2;
for (auto line : lines)
{
auto offX = OffsetX; auto offX = OffsetX;
while (text < textEnd) if (pb::FullTiltMode)
offX += (Width - line.Width) / 2;
for (auto text = line.Start; text < line.End; text++)
{ {
auto charBmp = font->Chars[*text++ & 0x7F]; auto charBmp = Font->Chars[*text & 0x7F];
if (charBmp) if (charBmp)
{ {
auto height = charBmp->Height; auto height = charBmp->Height;
auto width = charBmp->Width; auto width = charBmp->Width;
if (render::background_bitmap) if (render::background_bitmap)
gdrv::copy_bitmap_w_transparency(render::vscreen, width, height, offX, y, charBmp, 0, gdrv::copy_bitmap_w_transparency(render::vscreen, width, height, offX, offY, charBmp, 0,
0); 0);
else else
gdrv::copy_bitmap(render::vscreen, width, height, offX, y, charBmp, 0, 0); gdrv::copy_bitmap(render::vscreen, width, height, offX, offY, charBmp, 0, 0);
font = Font; offX += charBmp->Width + Font->GapWidth;
offX += charBmp->Width + font->GapWidth;
} }
} }
while ((*text & 0x7F) == ' ') offY += Font->Height;
++text;
if ((*text & 0x7F) == '\n')
++text;
} }
} }
}
TTextBox::LayoutResult TTextBox::LayoutTextLine(char* textStart) const
{
auto lineWidth = 0, wordWidth = 0;
char *wordBoundary = nullptr, *textEnd;
for (textEnd = textStart; ; ++textEnd)
{
auto maskedChar = textEnd[0] & 0x7F;
if (!maskedChar || maskedChar == '\n')
break;
auto charBmp = Font->Chars[maskedChar];
if (!charBmp)
continue;
auto width = lineWidth + charBmp->Width + Font->GapWidth;
if (width > Width)
{
if (wordBoundary)
{
textEnd = wordBoundary;
lineWidth = wordWidth;
}
break;
}
if (maskedChar == ' ')
{
wordBoundary = textEnd;
wordWidth = width;
}
lineWidth = width;
}
while ((*textEnd & 0x7F) == ' ')
++textEnd;
if ((*textEnd & 0x7F) == '\n')
++textEnd;
return LayoutResult{textStart, textEnd, lineWidth};
} }

View File

@ -22,7 +22,16 @@ public:
int Message(int code, float value) override; int Message(int code, float value) override;
void Clear(); void Clear();
void Display(const char* text, float time); void Display(const char* text, float time);
void Draw();
static void TimerExpired(int timerId, void* tb); private:
struct LayoutResult
{
char *Start, *End;
int Width;
};
static void TimerExpired(int timerId, void* caller);
void Draw();
LayoutResult LayoutTextLine(char* textStart) const;
}; };