From 223544fa016625de6b47ade6be022fa9826f5fc3 Mon Sep 17 00:00:00 2001 From: scawful Date: Tue, 23 Sep 2025 22:01:06 -0400 Subject: [PATCH] Add copy and move constructors to Bitmap class for better resource management - Implemented a copy constructor and copy assignment operator to enable deep copying of Bitmap objects. - Added move constructor and move assignment operator to optimize resource handling and prevent unnecessary data duplication. - Introduced SetPixel method for modifying individual pixels in the bitmap. - Added Resize method to adjust bitmap dimensions while preserving existing pixel data, enhancing flexibility in bitmap manipulation. --- src/app/gfx/bitmap.cc | 154 ++++++++++++++++++++++++++++++++++++++++++ src/app/gfx/bitmap.h | 35 ++++++++++ 2 files changed, 189 insertions(+) diff --git a/src/app/gfx/bitmap.cc b/src/app/gfx/bitmap.cc index f7ea5c0b..63c9a258 100644 --- a/src/app/gfx/bitmap.cc +++ b/src/app/gfx/bitmap.cc @@ -215,6 +215,100 @@ Bitmap::Bitmap(int width, int height, int depth, SetPalette(palette); } +Bitmap::Bitmap(const Bitmap& other) + : width_(other.width_), + height_(other.height_), + depth_(other.depth_), + active_(other.active_), + modified_(other.modified_), + palette_(other.palette_), + data_(other.data_) { + // Copy the data and recreate surface/texture + pixel_data_ = data_.data(); + if (active_ && !data_.empty()) { + surface_ = Arena::Get().AllocateSurface(width_, height_, depth_, + GetSnesPixelFormat(BitmapFormat::kIndexed)); + if (surface_) { + surface_->pixels = pixel_data_; + } + } +} + +Bitmap& Bitmap::operator=(const Bitmap& other) { + if (this != &other) { + width_ = other.width_; + height_ = other.height_; + depth_ = other.depth_; + active_ = other.active_; + modified_ = other.modified_; + palette_ = other.palette_; + data_ = other.data_; + + // Copy the data and recreate surface/texture + pixel_data_ = data_.data(); + if (active_ && !data_.empty()) { + surface_ = Arena::Get().AllocateSurface(width_, height_, depth_, + GetSnesPixelFormat(BitmapFormat::kIndexed)); + if (surface_) { + surface_->pixels = pixel_data_; + } + } + } + return *this; +} + +Bitmap::Bitmap(Bitmap&& other) noexcept + : width_(other.width_), + height_(other.height_), + depth_(other.depth_), + active_(other.active_), + modified_(other.modified_), + texture_pixels(other.texture_pixels), + pixel_data_(other.pixel_data_), + palette_(std::move(other.palette_)), + data_(std::move(other.data_)), + surface_(other.surface_), + texture_(other.texture_) { + // Reset the moved-from object + other.width_ = 0; + other.height_ = 0; + other.depth_ = 0; + other.active_ = false; + other.modified_ = false; + other.texture_pixels = nullptr; + other.pixel_data_ = nullptr; + other.surface_ = nullptr; + other.texture_ = nullptr; +} + +Bitmap& Bitmap::operator=(Bitmap&& other) noexcept { + if (this != &other) { + width_ = other.width_; + height_ = other.height_; + depth_ = other.depth_; + active_ = other.active_; + modified_ = other.modified_; + texture_pixels = other.texture_pixels; + pixel_data_ = other.pixel_data_; + palette_ = std::move(other.palette_); + data_ = std::move(other.data_); + surface_ = other.surface_; + texture_ = other.texture_; + + // Reset the moved-from object + other.width_ = 0; + other.height_ = 0; + other.depth_ = 0; + other.active_ = false; + other.modified_ = false; + other.texture_pixels = nullptr; + other.pixel_data_ = nullptr; + other.surface_ = nullptr; + other.texture_ = nullptr; + } + return *this; +} + void Bitmap::Create(int width, int height, int depth, std::span data) { data_ = std::vector(data.begin(), data.end()); Create(width, height, depth, data_); @@ -450,5 +544,65 @@ std::vector Bitmap::GetPngData() { } #endif +void Bitmap::SetPixel(int x, int y, const SnesColor& color) { + if (x < 0 || x >= width_ || y < 0 || y >= height_) { + return; // Bounds check + } + + int position = y * width_ + x; + if (position >= 0 && position < (int)data_.size()) { + // Convert SnesColor to palette index + uint8_t color_index = 0; + for (size_t i = 0; i < palette_.size(); i++) { + if (palette_[i].rgb().x == color.rgb().x && + palette_[i].rgb().y == color.rgb().y && + palette_[i].rgb().z == color.rgb().z) { + color_index = static_cast(i); + break; + } + } + data_[position] = color_index; + modified_ = true; + } +} + +void Bitmap::Resize(int new_width, int new_height) { + if (new_width <= 0 || new_height <= 0) { + return; // Invalid dimensions + } + + std::vector new_data(new_width * new_height, 0); + + // Copy existing data, handling size changes + if (!data_.empty()) { + for (int y = 0; y < std::min(height_, new_height); y++) { + for (int x = 0; x < std::min(width_, new_width); x++) { + int old_pos = y * width_ + x; + int new_pos = y * new_width + x; + if (old_pos < (int)data_.size() && new_pos < (int)new_data.size()) { + new_data[new_pos] = data_[old_pos]; + } + } + } + } + + width_ = new_width; + height_ = new_height; + data_ = std::move(new_data); + pixel_data_ = data_.data(); + + // Recreate surface with new dimensions + surface_ = Arena::Get().AllocateSurface(width_, height_, depth_, + GetSnesPixelFormat(BitmapFormat::kIndexed)); + if (surface_) { + surface_->pixels = pixel_data_; + active_ = true; + } else { + active_ = false; + } + + modified_ = true; +} + } // namespace gfx } // namespace yaze diff --git a/src/app/gfx/bitmap.h b/src/app/gfx/bitmap.h index 051c7547..5ce55f37 100644 --- a/src/app/gfx/bitmap.h +++ b/src/app/gfx/bitmap.h @@ -71,6 +71,31 @@ class Bitmap { Bitmap(int width, int height, int depth, const std::vector &data, const SnesPalette &palette); + /** + * @brief Copy constructor - creates a deep copy + */ + Bitmap(const Bitmap& other); + + /** + * @brief Copy assignment operator + */ + Bitmap& operator=(const Bitmap& other); + + /** + * @brief Move constructor + */ + Bitmap(Bitmap&& other) noexcept; + + /** + * @brief Move assignment operator + */ + Bitmap& operator=(Bitmap&& other) noexcept; + + /** + * @brief Destructor + */ + ~Bitmap() = default; + /** * @brief Create a bitmap with the given dimensions and data */ @@ -134,6 +159,16 @@ class Bitmap { */ void WriteColor(int position, const ImVec4 &color); + /** + * @brief Set a pixel at the given x,y coordinates + */ + void SetPixel(int x, int y, const SnesColor& color); + + /** + * @brief Resize the bitmap to new dimensions + */ + void Resize(int new_width, int new_height); + /** * @brief Extract an 8x8 tile from the bitmap */