Fix crash from new brush code when TPTMP is enabled

Okay yeah this is actually a well-camouflaged refactor.
This commit is contained in:
Tamás Bálint Misius 2023-02-28 14:55:57 +01:00
parent 114017d550
commit 369dadf81e
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
9 changed files with 80 additions and 172 deletions

View File

@ -3,10 +3,7 @@
#include "Misc.h"
#include <cmath>
BitmapBrush::BitmapBrush(ui::Point inputSize, unsigned char const *inputBitmap):
Brush(),
radius(inputSize / 2),
origSize(0, 0)
BitmapBrush::BitmapBrush(ui::Point inputSize, unsigned char const *inputBitmap)
{
ui::Point newSize = inputSize;
@ -24,7 +21,11 @@ BitmapBrush::BitmapBrush(ui::Point inputSize, unsigned char const *inputBitmap):
origBitmap[x + y * newSize.X] = inputBitmap[x + y * inputSize.X];
}
std::pair<ui::Point, std::unique_ptr<unsigned char []>> BitmapBrush::GenerateBitmap() const
BitmapBrush::BitmapBrush(const BitmapBrush &other) : BitmapBrush(other.origSize, &other.origBitmap[0])
{
}
std::unique_ptr<unsigned char []> BitmapBrush::GenerateBitmap() const
{
ui::Point size = radius * 2 + 1;
auto bitmap = std::make_unique<unsigned char []>(size.X * size.Y);
@ -58,13 +59,10 @@ std::pair<ui::Point, std::unique_ptr<unsigned char []>> BitmapBrush::GenerateBit
}
}
}
return std::make_pair(radius, std::move(bitmap));
return bitmap;
}
std::unique_ptr<Brush> BitmapBrush::Clone() const
{
auto into = std::make_unique<BitmapBrush>(origSize, &origBitmap[0]);
into->radius = radius;
copyBitmaps(*into);
return into;
return std::make_unique<BitmapBrush>(*this);
}

View File

@ -1,36 +1,18 @@
/*
* BitmapBrush.h
*
* Created on: Nov 18, 2012
* Author: Simon Robertshaw
*/
#pragma once
#include <vector>
#include "Brush.h"
class BitmapBrush: public Brush
{
ui::Point radius;
ui::Point origSize;
ui::Point origSize{ 0, 0 };
// 2D array with coords [0, origSize.X) by [0, origSize.Y)
std::unique_ptr<unsigned char []> origBitmap;
public:
BitmapBrush(ui::Point size, unsigned char const *bitmap);
BitmapBrush(const BitmapBrush &other);
virtual ~BitmapBrush() override = default;
std::pair<ui::Point, std::unique_ptr<unsigned char []>> GenerateBitmap() const override;
ui::Point GetRadius() const override
{
return radius;
}
void SetRadius(ui::Point radius) override
{
this->radius = radius;
InvalidateCache();
}
std::unique_ptr<unsigned char []> GenerateBitmap() const override;
std::unique_ptr<Brush> Clone() const override;
};

View File

@ -1,30 +1,34 @@
#include "Brush.h"
#include "graphics/Renderer.h"
void Brush::InvalidateCache()
Brush::Brush(const Brush &other)
{
size = ui::Point(0, 0);
bitmap.reset();
outline.reset();
radius = other.radius;
auto size = GetSize();
if (other.bitmap)
{
bitmap = std::make_unique<unsigned char []>(size.X * size.Y);
std::copy(&other.bitmap[0], &other.bitmap[0] + size.X * size.Y, &bitmap[0]);
}
if (other.outline)
{
outline = std::make_unique<unsigned char []>(size.X * size.Y);
std::copy(&other.outline[0], &other.outline[0] + size.X * size.Y, &outline[0]);
}
}
void Brush::ensureBitmap() const
void Brush::InitBitmap()
{
if (bitmap)
return;
auto pair = GenerateBitmap();
size = pair.first;
bitmap = std::move(pair.second);
bitmap = GenerateBitmap();
}
void Brush::ensureOutline() const
void Brush::InitOutline()
{
if (outline)
return;
ensureBitmap();
ui::Point bounds = size * 2 + 1;
InitBitmap();
ui::Point bounds = GetSize();
outline = std::make_unique<unsigned char []>(bounds.X * bounds.Y);
for (int j = 0; j < bounds.Y; j++)
{
for (int i = 0; i < bounds.X; i++)
{
bool value = false;
@ -43,6 +47,13 @@ void Brush::ensureOutline() const
}
outline[i + j * bounds.X] = value ? 0xFF : 0;
}
}
}
void Brush::SetRadius(ui::Point newRadius)
{
radius = newRadius;
InitOutline();
}
void Brush::AdjustSize(int delta, bool logarithmic, bool keepX, bool keepY)
@ -73,22 +84,6 @@ void Brush::AdjustSize(int delta, bool logarithmic, bool keepX, bool keepY)
SetRadius(newSize);
}
void Brush::copyBitmaps(Brush &into) const
{
into.size = size;
size_t bounds = (2 * size.X + 1) * (2 * size.Y + 1);
if (bitmap)
{
into.bitmap = std::make_unique<unsigned char []>(bounds);
std::copy(&bitmap[0], &bitmap[bounds], &into.bitmap[0]);
}
if (outline)
{
into.outline = std::make_unique<unsigned char []>(bounds);
std::copy(&outline[0], &outline[bounds], &into.outline[0]);
}
}
void Brush::RenderRect(Renderer * ren, ui::Point position1, ui::Point position2) const
{
int width, height;
@ -123,8 +118,7 @@ void Brush::RenderLine(Renderer * ren, ui::Point position1, ui::Point position2)
void Brush::RenderPoint(Renderer * ren, ui::Point position) const
{
ensureOutline();
ren->xor_bitmap(&outline[0], position.X - size.X, position.Y - size.Y, 2 * size.X + 1, 2 * size.Y + 1);
ren->xor_bitmap(&outline[0], position.X - radius.X, position.Y - radius.Y, 2 * radius.X + 1, 2 * radius.Y + 1);
}
void Brush::RenderFill(Renderer * ren, ui::Point position) const

View File

@ -6,13 +6,12 @@ class Renderer;
class Brush
{
private:
ui::Point mutable size;
// 2D arrays indexed by coordinates from [-size.X, size.X] by [-size.Y, size.Y]
std::unique_ptr<unsigned char []> mutable bitmap;
std::unique_ptr<unsigned char []> mutable outline;
// 2D arrays indexed by coordinates from [-radius.X, radius.X] by [-radius.Y, radius.Y]
std::unique_ptr<unsigned char []> bitmap;
std::unique_ptr<unsigned char []> outline;
void ensureBitmap() const;
void ensureOutline() const;
void InitBitmap();
void InitOutline();
struct iterator
{
@ -21,14 +20,15 @@ private:
iterator &operator++()
{
auto radius = parent.GetRadius();
do
{
if (++x > parent.size.X)
if (++x > radius.X)
{
--y;
x = -parent.size.X;
x = -radius.X;
}
} while (y >= -parent.size.Y && !parent.bitmap[x + parent.size.X + (y + parent.size.Y) * (2 * parent.size.X + 1)]);
} while (y >= -radius.Y && !parent.bitmap[x + radius.X + (y + radius.Y) * (2 * radius.X + 1)]);
return *this;
}
@ -50,42 +50,42 @@ private:
};
protected:
Brush():
size(0, 0),
bitmap(),
outline()
{
}
ui::Point radius{ 0, 0 };
void InvalidateCache();
virtual std::pair<ui::Point, std::unique_ptr<unsigned char []>> GenerateBitmap() const = 0;
void copyBitmaps(Brush &into) const;
virtual std::unique_ptr<unsigned char []> GenerateBitmap() const = 0;
public:
Brush() = default;
Brush(const Brush &other);
virtual ~Brush() = default;
virtual ui::Point GetRadius() const = 0;
virtual void SetRadius(ui::Point radius) = 0;
virtual void AdjustSize(int delta, bool logarithmic, bool keepX, bool keepY);
virtual std::unique_ptr<Brush> Clone() const = 0;
ui::Point GetSize() const
{
return size;
return radius * 2 + 1;
}
ui::Point GetRadius() const
{
return radius;
}
iterator begin() const
{
// bottom to top is the preferred order for Simulation::CreateParts
return ++iterator{*this, size.X, size.Y + 1};
return ++iterator{*this, radius.X, radius.Y + 1};
}
iterator end() const
{
return iterator{*this, -size.X, -size.Y - 1};
return iterator{*this, -radius.X, -radius.Y - 1};
}
void RenderRect(Renderer * ren, ui::Point position1, ui::Point position2) const;
void RenderLine(Renderer * ren, ui::Point position1, ui::Point position2) const;
void RenderPoint(Renderer * ren, ui::Point position) const;
void RenderFill(Renderer * ren, ui::Point position) const;
void SetRadius(ui::Point newRadius);
};

View File

@ -4,19 +4,16 @@
class EllipseBrush: public Brush
{
ui::Point radius;
bool perfectCircle;
public:
EllipseBrush(ui::Point radius, bool perfectCircle = true):
Brush(),
radius(radius),
perfectCircle(perfectCircle)
EllipseBrush(bool newPerfectCircle) :
perfectCircle(newPerfectCircle)
{
}
virtual ~EllipseBrush() override = default;
std::pair<ui::Point, std::unique_ptr<unsigned char []>> GenerateBitmap() const override
std::unique_ptr<unsigned char []> GenerateBitmap() const override
{
ui::Point size = radius * 2 + 1;
auto bitmap = std::make_unique<unsigned char []>(size.X * size.Y);
@ -64,24 +61,11 @@ public:
bitmap[size.X/2] = 255;
bitmap[size.X*size.Y-size.X/2-1] = 255;
}
return std::make_pair(radius, std::move(bitmap));
}
ui::Point GetRadius() const override
{
return radius;
}
void SetRadius(ui::Point radius) override
{
this->radius = radius;
InvalidateCache();
return bitmap;
}
std::unique_ptr<Brush> Clone() const override
{
auto into = std::make_unique<EllipseBrush>(radius, perfectCircle);
copyBitmaps(*into);
return into;
return std::make_unique<EllipseBrush>(*this);
}
};

View File

@ -462,14 +462,14 @@ void GameModel::BuildFavoritesMenu()
void GameModel::BuildBrushList()
{
std::optional<ui::Point> radius;
ui::Point radius{ 4, 4 };
if (brushList.size())
radius = brushList[currentBrush]->GetRadius();
brushList.clear();
brushList.push_back(std::make_unique<EllipseBrush>(ui::Point(4, 4), perfectCircle));
brushList.push_back(std::make_unique<RectangleBrush>(ui::Point(4, 4)));
brushList.push_back(std::make_unique<TriangleBrush>(ui::Point(4, 4)));
brushList.push_back(std::make_unique<EllipseBrush>(perfectCircle));
brushList.push_back(std::make_unique<RectangleBrush>());
brushList.push_back(std::make_unique<TriangleBrush>());
//Load more from brushes folder
for (ByteString brushFile : Platform::DirectorySearch(BRUSH_DIR, "", { ".ptb" }))
@ -489,8 +489,7 @@ void GameModel::BuildBrushList()
brushList.push_back(std::make_unique<BitmapBrush>(ui::Point(dimension, dimension), reinterpret_cast<unsigned char const *>(brushData.data())));
}
if (radius && (size_t)currentBrush < brushList.size())
brushList[currentBrush]->SetRadius(*radius);
brushList[currentBrush]->SetRadius(radius);
notifyBrushChanged();
}

View File

@ -3,40 +3,19 @@
class RectangleBrush: public Brush
{
ui::Point radius;
public:
RectangleBrush(ui::Point radius):
Brush(),
radius(radius)
{
}
virtual ~RectangleBrush() override = default;
std::pair<ui::Point, std::unique_ptr<unsigned char []>> GenerateBitmap() const override
std::unique_ptr<unsigned char []> GenerateBitmap() const override
{
ui::Point size = radius * 2 + 1;
auto size = GetSize();
auto bitmap = std::make_unique<unsigned char []>(size.X * size.Y);
std::fill(&bitmap[0], &bitmap[size.X * size.Y], 0xFF);
return std::make_pair(radius, std::move(bitmap));
}
ui::Point GetRadius() const override
{
return radius;
}
void SetRadius(ui::Point radius) override
{
this->radius = radius;
InvalidateCache();
std::fill(&bitmap[0], &bitmap[0] + size.X * size.Y, 0xFF);
return bitmap;
}
std::unique_ptr<Brush> Clone() const override
{
auto into = std::make_unique<RectangleBrush>(radius);
copyBitmaps(*into);
return into;
return std::make_unique<RectangleBrush>(*this);
}
};

View File

@ -1,28 +1,13 @@
/*
* TriangleBrush.h
*
* Created on: Jan 26, 2012
* Author: Savely Skresanov
*/
#pragma once
#include "Brush.h"
#include <cmath>
class TriangleBrush: public Brush
{
ui::Point radius;
public:
TriangleBrush(ui::Point radius):
Brush(),
radius(radius)
{
}
virtual ~TriangleBrush() override = default;
std::pair<ui::Point, std::unique_ptr<unsigned char []>> GenerateBitmap() const override
std::unique_ptr<unsigned char []> GenerateBitmap() const override
{
ui::Point size = radius * 2 + 1;
auto bitmap = std::make_unique<unsigned char []>(size.X * size.Y);
@ -43,24 +28,11 @@ public:
}
}
}
return std::make_pair(radius, std::move(bitmap));
}
ui::Point GetRadius() const override
{
return radius;
}
void SetRadius(ui::Point radius) override
{
this->radius = radius;
InvalidateCache();
return bitmap;
}
std::unique_ptr<Brush> Clone() const override
{
auto into = std::make_unique<RectangleBrush>(radius);
copyBitmaps(*into);
return into;
return std::make_unique<TriangleBrush>(*this);
}
};

View File

@ -2202,7 +2202,7 @@ int LuaScriptInterface::simulation_brush(lua_State * l)
lua_pushnumber(l, positionX);
lua_pushnumber(l, positionY);
std::vector<ui::Point> points;
std::copy(brush->begin(), brush->end(), std::back_inserter(points));
std::copy(newBrush->begin(), newBrush->end(), std::back_inserter(points));
lua_pushnumber(l, 0); // index
lua_pushnumber(l, points.size());
auto points_ud = reinterpret_cast<ui::Point *>(lua_newuserdata(l, points.size() * sizeof(ui::Point)));