Browse Source

Fix memory leak in credits.cpp

Thanks to @Lundar
pull/796/head
Anders Jenbo 6 years ago
parent
commit
fa473e9e48
  1. 100
      SourceX/DiabloUI/credits.cpp

100
SourceX/DiabloUI/credits.cpp

@ -26,18 +26,20 @@ const int LINE_H = 22;
// a line is leaving the screen while another one is entering.
#define MAX_VISIBLE_LINES ((VIEWPORT.h - 1) / LINE_H + 2)
struct SurfaceDeleter {
void operator()(SDL_Surface *surface)
struct CachedLine {
CachedLine()
{
SDL_FreeSurface(surface);
m_index = 0;
m_surface = NULL;
palette_version = pal_surface_palette_version;
}
};
struct CachedLine {
CachedLine(std::size_t index, SDL_Surface *surface)
{
m_index = index;
m_surface = surface;
palette_version = pal_surface_palette_version;
}
std::size_t m_index;
@ -94,79 +96,14 @@ CachedLine PrepareLine(std::size_t index)
ScaleSurfaceToOutput(&surface_ptr);
surface = surface_ptr;
}
SDL_FreeSurface(text);
return CachedLine(index, surface);
}
/**
* Similar to std::deque<CachedLine> but simpler and backed by a single vector.
*/
class LinesBuffer {
public:
LinesBuffer(std::size_t capacity)
{
data_.reserve(capacity);
for (std::size_t i = 0; i < capacity; ++i)
data_.push_back(CachedLine(0, NULL));
start_ = 0;
end_ = 0;
empty_ = true;
}
bool empty() const
{
return empty_;
}
CachedLine &front()
{
return data_[start_];
}
CachedLine &back()
{
return data_[end_];
}
CachedLine &operator[](std::size_t i)
{
return data_[(start_ + i) % data_.size()];
}
std::size_t size() const
{
if (empty_)
return 0;
return start_ < end_ ? end_ - start_ : data_.size();
}
void pop_front()
{
start_ = (start_ + 1) % data_.size();
if (start_ == end_)
empty_ = true;
}
void push_back(CachedLine line)
{
end_ = (end_ + 1) % data_.size();
data_[end_] = line;
empty_ = false;
}
private:
std::size_t start_;
std::size_t end_;
bool empty_;
std::vector<CachedLine> data_;
};
class CreditsRenderer {
public:
CreditsRenderer()
: lines_(MAX_VISIBLE_LINES)
{
LoadBackgroundArt("ui_art\\credits.pcx");
LoadTtfFont();
@ -179,6 +116,11 @@ public:
{
ArtBackground.Unload();
UnloadTtfFont();
for (int x = 0; x < lines_.size(); x++) {
if (lines_[x].m_surface)
SDL_FreeSurface(lines_[x].m_surface);
}
}
void Render();
@ -189,7 +131,7 @@ public:
}
private:
LinesBuffer lines_;
std::vector<CachedLine> lines_;
bool finished_;
Uint32 ticks_begin_;
int prev_offset_y_;
@ -216,12 +158,8 @@ void CreditsRenderer::Render()
return;
}
while (!lines_.empty() && lines_.front().m_index != lines_begin)
lines_.pop_front();
if (lines_.empty())
lines_.push_back(PrepareLine(lines_begin));
while (lines_.back().m_index + 1 != lines_end)
lines_.push_back(PrepareLine(lines_.back().m_index + 1));
while (lines_end > lines_.size())
lines_.push_back(PrepareLine(lines_.size()));
SDL_Rect viewport = VIEWPORT;
ScaleOutputRect(&viewport);
@ -229,14 +167,16 @@ void CreditsRenderer::Render()
// We use unscaled coordinates for calculation throughout.
Sint16 dest_y = VIEWPORT.y - (offset_y - lines_begin * LINE_H);
for (std::size_t i = 0; i < lines_.size(); ++i, dest_y += LINE_H) {
for (std::size_t i = lines_begin; i < lines_end; ++i, dest_y += LINE_H) {
CachedLine &line = lines_[i];
if (line.m_surface == NULL)
continue;
// Still fading in: the cached line was drawn with a different fade level.
if (line.palette_version != pal_surface_palette_version)
if (line.palette_version != pal_surface_palette_version) {
SDL_FreeSurface(line.m_surface);
line = PrepareLine(line.m_index);
}
Sint16 dest_x = PANEL_LEFT + VIEWPORT.x + 31;
if (CREDITS_LINES[line.m_index][0] == '\t')

Loading…
Cancel
Save