Merge from master: centered textboxes in FT mode.

This commit is contained in:
Muzychenko Andrey 2021-11-23 15:49:56 +03:00
parent 818a90b7aa
commit 53b2399687
4 changed files with 83 additions and 50 deletions

View File

@ -155,6 +155,8 @@ void TTextBox::Display(const wchar_t* text, float time)
void TTextBox::Draw(bool redraw) void TTextBox::Draw(bool redraw)
{ {
LayoutResult lines[5];
auto bmp = BgBmp; auto bmp = BgBmp;
if (bmp) if (bmp)
gdrv::copy_bitmap( gdrv::copy_bitmap(
@ -203,8 +205,7 @@ void TTextBox::Draw(bool redraw)
if (display) if (display)
{ {
auto font = Font; if (!Font)
if (!font)
{ {
gdrv::blit( gdrv::blit(
&render::vscreen, &render::vscreen,
@ -219,68 +220,50 @@ void TTextBox::Draw(bool redraw)
render::vscreen.XPosition + OffsetX, render::vscreen.XPosition + OffsetX,
render::vscreen.YPosition + OffsetY, render::vscreen.YPosition + OffsetY,
Width, Width,
Height); Height,
pb::FullTiltMode);
return; return;
} }
auto text = Message1->Text; auto textHeight = 0, lineCount = 0;
for (auto y = OffsetY; ; y += font->Height) for (auto text = Message1->Text; lineCount < 10; textHeight += Font->Height, lineCount++)
{ {
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);
wchar_t* textEndSpace = nullptr; if (line.Start == line.End)
auto textEnd = text;
while (true)
{
auto maskedChar = curChar & 0x7F;
if (!maskedChar || maskedChar == '\n')
break; break;
auto charBmp = font->Chars[maskedChar]; lines[lineCount] = line;
if (charBmp) text = line.End;
{
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 i = 0; i < lineCount; i++)
{
auto line = lines[i];
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;
} }
} }
@ -293,3 +276,42 @@ void TTextBox::Draw(bool redraw)
Width, Width,
Height); Height);
} }
TTextBox::LayoutResult TTextBox::LayoutTextLine(wchar_t* textStart) const
{
auto lineWidth = 0, wordWidth = 0;
wchar_t *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

@ -24,5 +24,15 @@ public:
void Display(const wchar_t* text, float time); void Display(const wchar_t* text, float time);
void Draw(bool redraw = false); void Draw(bool redraw = false);
static void TimerExpired(int timerId, void* tb); private:
struct LayoutResult
{
wchar_t *Start, *End;
int Width;
};
static void TimerExpired(int timerId, void* caller);
LayoutResult LayoutTextLine(wchar_t* textStart) const;
}; };

View File

@ -427,7 +427,7 @@ void gdrv::ScrollBitmapHorizontal(gdrv_bitmap8* bmp, int xStart)
} }
void gdrv::grtext_draw_ttext_in_box(LPCWSTR text, int xOff, int yOff, int width, int height) void gdrv::grtext_draw_ttext_in_box(LPCWSTR text, int xOff, int yOff, int width, int height, bool centered)
{ {
// Original font was 16 points, used with lowest table resolution // Original font was 16 points, used with lowest table resolution
static const int fontSizes[3] = static const int fontSizes[3] =
@ -495,7 +495,8 @@ void gdrv::grtext_draw_ttext_in_box(LPCWSTR text, int xOff, int yOff, int width,
int prevMode = SetBkMode(dc, TRANSPARENT); int prevMode = SetBkMode(dc, TRANSPARENT);
COLORREF color = SetTextColor(dc, grtext_red | grtext_green << 8 | grtext_blue << 16); COLORREF color = SetTextColor(dc, grtext_red | grtext_green << 8 | grtext_blue << 16);
DrawTextW(dc, text, lstrlenW(text), &rc, DT_NOPREFIX | DT_WORDBREAK); auto textFormat = DT_NOPREFIX | DT_WORDBREAK | (centered ? DT_CENTER : 0);
DrawTextW(dc, text, lstrlenW(text), &rc, textFormat);
SelectObject(dc, hOldFont); SelectObject(dc, hOldFont);
DeleteObject(hNewFont); DeleteObject(hNewFont);

View File

@ -65,7 +65,7 @@ public:
static void copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, static void copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff,
gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff); gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff);
static void ScrollBitmapHorizontal(gdrv_bitmap8* bmp, int xStart); static void ScrollBitmapHorizontal(gdrv_bitmap8* bmp, int xStart);
static void grtext_draw_ttext_in_box(LPCWSTR text, int xOff, int yOff, int width, int height); static void grtext_draw_ttext_in_box(LPCWSTR text, int xOff, int yOff, int width, int height, bool centered);
private: private:
/*COLORONCOLOR or HALFTONE*/ /*COLORONCOLOR or HALFTONE*/
static const int stretchMode = COLORONCOLOR; static const int stretchMode = COLORONCOLOR;