- use a saner data structure to store the BrokenLines.

Calling the old method with a pointer to an array of unspecified length 'dirty' would be an understatement.
Now it uses a TArray to store the single elements
This commit is contained in:
Christoph Oelckers 2018-10-31 19:13:54 +01:00
parent b911bbc424
commit 0d54d335c4
15 changed files with 62 additions and 135 deletions

View file

@ -1194,13 +1194,12 @@ static void PrintSecretString(const char *string, bool thislevel)
else colstr = TEXTCOLOR_GREEN;
}
}
FBrokenLines *brok = V_BreakLines(ConFont, screen->GetWidth()*95/100, string);
auto brok = V_BreakLines(ConFont, screen->GetWidth()*95/100, string);
for (int k = 0; brok[k].Width >= 0; k++)
{
Printf("%s%s\n", colstr, brok[k].Text.GetChars());
}
V_FreeBrokenLines(brok);
}
}

View file

@ -732,8 +732,8 @@ void FNotifyBuffer::Shift(int maxlines)
void FNotifyBuffer::AddString(int printlevel, FString source)
{
FBrokenLines *lines;
int i, width;
TArray<FBrokenLines> lines;
int width;
if ((printlevel != 128 && !show_messages) ||
source.IsEmpty() ||
@ -764,14 +764,14 @@ void FNotifyBuffer::AddString(int printlevel, FString source)
}
}
if (lines == NULL)
if (lines.Size() == 0)
return;
for (i = 0; lines[i].Width >= 0; i++)
for (auto &line : lines)
{
FNotifyText newline;
newline.Text = lines[i].Text;
newline.Text = line.Text;
newline.TimeOut = gametic + int(con_notifytime * TICRATE);
newline.PrintLevel = printlevel;
if (AddType == NEWLINE || Text.Size() == 0)
@ -789,9 +789,6 @@ void FNotifyBuffer::AddString(int printlevel, FString source)
AddType = NEWLINE;
}
V_FreeBrokenLines (lines);
lines = NULL;
switch (source[source.Len()-1])
{
case '\r': AddType = REPLACELINE; break;
@ -1185,22 +1182,22 @@ void C_DrawConsole ()
// No more enqueuing because adding new text to the console won't touch the actual print data.
conbuffer->FormatText(ConFont, ConWidth / textScale);
unsigned int consolelines = conbuffer->GetFormattedLineCount();
FBrokenLines **blines = conbuffer->GetLines();
FBrokenLines **printline = blines + consolelines - 1 - RowAdjust;
FBrokenLines *blines = conbuffer->GetLines();
FBrokenLines *printline = blines + consolelines - 1 - RowAdjust;
int bottomline = ConBottom / textScale - ConFont->GetHeight()*2 - 4;
ConsoleDrawing = true;
for(FBrokenLines **p = printline; p >= blines && lines > 0; p--, lines--)
for(FBrokenLines *p = printline; p >= blines && lines > 0; p--, lines--)
{
if (textScale == 1)
{
screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), (*p)->Text, TAG_DONE);
screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), p->Text, TAG_DONE);
}
else
{
screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), (*p)->Text,
screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), p->Text,
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);

View file

@ -74,11 +74,11 @@ FConsoleBuffer::~FConsoleBuffer()
void FConsoleBuffer::FreeBrokenText(unsigned start, unsigned end)
{
if (end > mBrokenConsoleText.Size()) end = mBrokenConsoleText.Size();
if (end > m_BrokenConsoleText.Size()) end = m_BrokenConsoleText.Size();
for (unsigned i = start; i < end; i++)
{
if (mBrokenConsoleText[i] != NULL) V_FreeBrokenLines(mBrokenConsoleText[i]);
mBrokenConsoleText[i] = NULL;
m_BrokenConsoleText[i].Clear();
m_BrokenConsoleText[i].ShrinkToFit();
}
}
@ -260,7 +260,7 @@ void FConsoleBuffer::FormatText(FFont *formatfont, int displaywidth)
if (formatfont != mLastFont || displaywidth != mLastDisplayWidth || mBufferWasCleared)
{
FreeBrokenText();
mBrokenConsoleText.Clear();
m_BrokenConsoleText.Clear();
mBrokenStart.Clear();
mBrokenStart.Push(0);
mBrokenLines.Clear();
@ -268,7 +268,7 @@ void FConsoleBuffer::FormatText(FFont *formatfont, int displaywidth)
mLastDisplayWidth = displaywidth;
mBufferWasCleared = false;
}
unsigned brokensize = mBrokenConsoleText.Size();
unsigned brokensize = m_BrokenConsoleText.Size();
if (brokensize == mConsoleText.Size())
{
// The last line got text appended. We have to wait until here to format it because
@ -276,21 +276,19 @@ void FConsoleBuffer::FormatText(FFont *formatfont, int displaywidth)
if (mLastLineNeedsUpdate)
{
brokensize--;
V_FreeBrokenLines(mBrokenConsoleText[brokensize]);
mBrokenConsoleText.Resize(brokensize);
m_BrokenConsoleText.Resize(brokensize);
}
}
mBrokenLines.Resize(mBrokenStart[brokensize]);
mBrokenStart.Resize(brokensize);
for (unsigned i = brokensize; i < mConsoleText.Size(); i++)
{
FBrokenLines *bl = V_BreakLines(formatfont, displaywidth, mConsoleText[i], true);
mBrokenConsoleText.Push(bl);
auto bl = V_BreakLines(formatfont, displaywidth, mConsoleText[i], true);
m_BrokenConsoleText.Push(bl);
mBrokenStart.Push(mBrokenLines.Size());
while (bl->Width != -1)
for(auto &bline : bl)
{
mBrokenLines.Push(bl);
bl++;
mBrokenLines.Push(bline);
}
}
mTextLines = mBrokenLines.Size();

View file

@ -49,9 +49,9 @@ enum EAddType
class FConsoleBuffer
{
TArray<FString> mConsoleText;
TArray<FBrokenLines *> mBrokenConsoleText; // This holds the structures returned by V_BreakLines and is used for memory management.
TArray<TArray<FBrokenLines>> m_BrokenConsoleText; // This holds the structures returned by V_BreakLines and is used for memory management.
TArray<unsigned int> mBrokenStart;
TArray<FBrokenLines *> mBrokenLines; // This holds the single lines, indexed by mBrokenStart and is used for printing.
TArray<FBrokenLines> mBrokenLines; // This holds the single lines, indexed by mBrokenStart and is used for printing.
FILE * mLogFile;
EAddType mAddType;
int mTextLines;
@ -80,6 +80,6 @@ public:
mConsoleText.Clear();
}
int GetFormattedLineCount() { return mTextLines; }
FBrokenLines **GetLines() { return &mBrokenLines[0]; }
FBrokenLines *GetLines() { return &mBrokenLines[0]; }
};

View file

@ -194,7 +194,6 @@ DHUDMessage::DHUDMessage (FFont *font, const char *text, float x, float y, int h
WrapWidth = 0;
HandleAspect = true;
Top = y;
Lines = NULL;
HoldTics = (int)(holdTime * TICRATE);
Tics = 0;
TextColor = textColor;
@ -215,11 +214,6 @@ DHUDMessage::DHUDMessage (FFont *font, const char *text, float x, float y, int h
void DHUDMessage::OnDestroy()
{
if (Lines)
{
V_FreeBrokenLines (Lines);
Lines = NULL;
}
if (SourceText != NULL)
{
delete[] SourceText;
@ -260,7 +254,6 @@ void DHUDMessage::Serialize(FSerializer &arc)
if (arc.isReading())
{
Lines = NULL;
ResetText(SourceText);
}
}
@ -329,24 +322,16 @@ void DHUDMessage::ResetText (const char *text)
width = SCREENWIDTH / active_con_scaletext();
}
if (Lines != NULL)
{
V_FreeBrokenLines (Lines);
}
Lines = V_BreakLines (Font, NoWrap ? INT_MAX : width, (uint8_t *)text);
NumLines = 0;
NumLines = Lines.Size();
Width = 0;
Height = 0;
if (Lines)
for (auto &line : Lines)
{
for (; Lines[NumLines].Width >= 0; NumLines++)
{
Height += Font->GetHeight ();
Width = MAX<int> (Width, Lines[NumLines].Width);
}
Height += Font->GetHeight ();
Width = MAX<int> (Width, line.Width);
}
}

View file

@ -133,7 +133,7 @@ public:
}
protected:
FBrokenLines *Lines;
TArray<FBrokenLines> Lines;
int Width, Height, NumLines;
float Left, Top;
bool CenterX, NoWrap;

View file

@ -686,12 +686,11 @@ class CommandDrawString : public SBarInfoCommand
{
if(lineBreaks)
{
FBrokenLines *lines = V_BreakLines(font, breakWidth, str.GetChars());
for(int i = 0;lines[i].Width >= 0;i++)
auto lines = V_BreakLines(font, breakWidth, str.GetChars());
for(unsigned i = 0; i < lines.Size();i++)
{
statusBar->DrawString(font, lines[i].Text, x, y+i*(font->GetHeight()+4), block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), translation, spacing, shadow, shadowX, shadowY);
}
V_FreeBrokenLines(lines);
}
else
statusBar->DrawString(font, str.GetChars(), x, y, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), translation, spacing, shadow, shadowX, shadowY);

View file

@ -1106,10 +1106,10 @@ void DBaseStatusBar::DrawLog ()
hudheight = SCREENHEIGHT / scale;
int linelen = hudwidth<640? Scale(hudwidth,9,10)-40 : 560;
FBrokenLines *lines = V_BreakLines (SmallFont, linelen, CPlayer->LogText);
auto lines = V_BreakLines (SmallFont, linelen, CPlayer->LogText);
int height = 20;
for (int i = 0; lines[i].Width != -1; i++) height += SmallFont->GetHeight () + 1;
for (unsigned i = 0; i < lines.Size(); i++) height += SmallFont->GetHeight () + 1;
int x,y,w;
@ -1138,8 +1138,6 @@ void DBaseStatusBar::DrawLog ()
DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, TAG_DONE);
y += SmallFont->GetHeight ()+1;
}
V_FreeBrokenLines (lines);
}
}
@ -1882,13 +1880,12 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawString)
if (wrapwidth > 0)
{
FBrokenLines *brk = V_BreakLines(font->mFont, wrapwidth, string, true);
for (int i = 0; brk[i].Width >= 0; i++)
auto brk = V_BreakLines(font->mFont, wrapwidth, string, true);
for (auto &line : brk)
{
self->DrawString(font->mFont, brk[i].Text, x, y, flags, alpha, trans, font->mSpacing, font->mMonospaced, font->mShadowX, font->mShadowY);
self->DrawString(font->mFont, line.Text, x, y, flags, alpha, trans, font->mSpacing, font->mMonospaced, font->mShadowX, font->mShadowY);
y += font->mFont->GetHeight() + linespacing;
}
V_FreeBrokenLines(brk);
}
else
{

View file

@ -535,13 +535,10 @@ void FSavegameManager::UnloadSaveData()
{
delete SavePic;
}
if (SaveComment != nullptr)
{
V_FreeBrokenLines(SaveComment);
}
SaveComment.Clear();
SaveComment.ShrinkToFit();
SavePic = nullptr;
SaveComment = nullptr;
SavePicData.Clear();
}
@ -615,7 +612,7 @@ void FSavegameManager::DrawSaveComment(FFont *font, int cr, int x, int y, int sc
// I'm not sure why SaveComment would go nullptr in this loop, but I got
// a crash report where it was nullptr when i reached 1, so now I check
// for that.
for (int i = 0; SaveComment != nullptr && SaveComment[i].Width >= 0 && i < maxlines; ++i)
for (int i = 0; i < maxlines && (unsigned)i < SaveComment.Size(); ++i)
{
screen->DrawText(font, cr, x, y + font->GetHeight() * i * scalefactor, SaveComment[i].Text, DTA_CleanNoMove, true, TAG_DONE);
}
@ -647,14 +644,9 @@ void FSavegameManager::SetFileInfo(int Selected)
{
if (!SaveGames[Selected]->Filename.IsEmpty())
{
char workbuf[512];
mysnprintf(workbuf, countof(workbuf), "File on disk:\n%s", SaveGames[Selected]->Filename.GetChars());
if (SaveComment != nullptr)
{
V_FreeBrokenLines(SaveComment);
}
SaveComment = V_BreakLines(SmallFont, WindowSize, workbuf);
FString work;
work.Format("File on disk:\n%s", SaveGames[Selected]->Filename.GetChars());
SaveComment = V_BreakLines(SmallFont, WindowSize, work);
}
}

View file

@ -73,7 +73,7 @@ private:
int LastAccessed = -1;
TArray<char> SavePicData;
FTexture *SavePic = nullptr;
FBrokenLines *SaveComment = nullptr;
TArray<FBrokenLines> SaveComment;
public:
int WindowSize = 0;

View file

@ -715,27 +715,6 @@ DEFINE_ACTION_FUNCTION(DConversationMenu, SendConversationReply)
}
// Needed for the conversion process.
class DBrokenLines : public DObject
{
DECLARE_ABSTRACT_CLASS(DBrokenLines, DObject)
public:
FBrokenLines *mBroken;
unsigned int mCount;
DBrokenLines(FBrokenLines *broken, unsigned int count)
{
mBroken = broken;
mCount = count;
}
void OnDestroy() override
{
V_FreeBrokenLines(mBroken);
}
};
//============================================================================
//
// P_FreeStrifeConversations

View file

@ -358,7 +358,7 @@ void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage
TArray<line_t*> lines;
while ((ln = it.Next())) // iterator and Trace both use validcount and interfere with each other
lines.Push(ln);
for (int i = 0; i < lines.Size(); i++)
for (unsigned i = 0; i < lines.Size(); i++)
{
ln = lines[i];
DVector2 pos2d = bombspot->Pos().XY();

View file

@ -87,6 +87,7 @@ The FON2 header is followed by variable length data:
#include "cmdlib.h"
#include "sc_man.h"
#include "hu_stuff.h"
#include "gstrings.h"
#include "v_text.h"
#include "vm.h"
@ -919,7 +920,9 @@ DEFINE_ACTION_FUNCTION(FFont, StringWidth)
{
PARAM_SELF_STRUCT_PROLOGUE(FFont);
PARAM_STRING(str);
ACTION_RETURN_INT(self->StringWidth(str));
const char *txt = str[0] == '$' ? GStrings(&str[1]) : str.GetChars();
ACTION_RETURN_INT(self->StringWidth(txt));
}
//==========================================================================

View file

@ -345,7 +345,7 @@ static void breakit (FBrokenLines *line, FFont *font, const uint8_t *start, cons
line->Width = font->StringWidth (line->Text);
}
FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const uint8_t *string, bool preservecolor, unsigned int *count)
TArray<FBrokenLines> V_BreakLines (FFont *font, int maxwidth, const uint8_t *string, bool preservecolor, unsigned int *count)
{
TArray<FBrokenLines> Lines(128);
@ -448,21 +448,7 @@ FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const uint8_t *string, bo
}
}
}
// Make a copy of the broken lines and return them
FBrokenLines *broken = new FBrokenLines[Lines.Size() + 1];
for (unsigned ii = 0; ii < Lines.Size(); ++ii)
{
broken[ii] = Lines[ii];
}
broken[Lines.Size()].Width = -1;
if (count != nullptr)
{
*count = Lines.Size();
}
return broken;
return Lines;
}
void V_FreeBrokenLines (FBrokenLines *lines)
@ -478,18 +464,11 @@ class DBrokenLines : public DObject
DECLARE_ABSTRACT_CLASS(DBrokenLines, DObject)
public:
FBrokenLines *mBroken;
unsigned int mCount;
TArray<FBrokenLines> mBroken;
DBrokenLines(FBrokenLines *broken, unsigned int count)
DBrokenLines(TArray<FBrokenLines> &broken)
{
mBroken = broken;
mCount = count;
}
void OnDestroy() override
{
V_FreeBrokenLines(mBroken);
mBroken = std::move(broken);
}
};
@ -498,21 +477,21 @@ IMPLEMENT_CLASS(DBrokenLines, true, false);
DEFINE_ACTION_FUNCTION(DBrokenLines, Count)
{
PARAM_SELF_PROLOGUE(DBrokenLines);
ACTION_RETURN_INT(self->mCount);
ACTION_RETURN_INT(self->mBroken.Size());
}
DEFINE_ACTION_FUNCTION(DBrokenLines, StringWidth)
{
PARAM_SELF_PROLOGUE(DBrokenLines);
PARAM_INT(index);
ACTION_RETURN_INT((unsigned)index >= self->mCount? -1 : self->mBroken[index].Width);
ACTION_RETURN_INT((unsigned)index >= self->mBroken.Size()? -1 : self->mBroken[index].Width);
}
DEFINE_ACTION_FUNCTION(DBrokenLines, StringAt)
{
PARAM_SELF_PROLOGUE(DBrokenLines);
PARAM_INT(index);
ACTION_RETURN_STRING((unsigned)index >= self->mCount? -1 : self->mBroken[index].Text);
ACTION_RETURN_STRING((unsigned)index >= self->mBroken.Size() ? -1 : self->mBroken[index].Text);
}
DEFINE_ACTION_FUNCTION(FFont, BreakLines)
@ -522,6 +501,6 @@ DEFINE_ACTION_FUNCTION(FFont, BreakLines)
PARAM_INT(maxwidth);
unsigned int count;
FBrokenLines *broken = V_BreakLines(self, maxwidth, text, true, &count);
ACTION_RETURN_OBJECT(Create<DBrokenLines>(broken, count));
TArray<FBrokenLines> broken = V_BreakLines(self, maxwidth, text, true, &count);
ACTION_RETURN_OBJECT(Create<DBrokenLines>(broken));
}

View file

@ -39,7 +39,7 @@
struct FBrokenLines
{
int Width;
unsigned Width;
FString Text;
};
@ -79,11 +79,10 @@ struct FBrokenLines
#define TEXTCOLOR_CHAT "\034*"
#define TEXTCOLOR_TEAMCHAT "\034!"
FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const uint8_t *str, bool preservecolor = false, unsigned int *count = nullptr);
void V_FreeBrokenLines (FBrokenLines *lines);
inline FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const char *str, bool preservecolor = false, unsigned int *count = nullptr)
TArray<FBrokenLines> V_BreakLines (FFont *font, int maxwidth, const uint8_t *str, bool preservecolor = false, unsigned int *count = nullptr);
inline TArray<FBrokenLines> V_BreakLines (FFont *font, int maxwidth, const char *str, bool preservecolor = false, unsigned int *count = nullptr)
{ return V_BreakLines (font, maxwidth, (const uint8_t *)str, preservecolor, count); }
inline FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const FString &str, bool preservecolor = false, unsigned int *count = nullptr)
inline TArray<FBrokenLines> V_BreakLines (FFont *font, int maxwidth, const FString &str, bool preservecolor = false, unsigned int *count = nullptr)
{ return V_BreakLines (font, maxwidth, (const uint8_t *)str.GetChars(), preservecolor, count); }
int GetCharFromString(const uint8_t *&string);