#pragma once #include #include #include // common types using u8 = std::uint8_t; using i8 = std::int8_t; using u16 = std::uint16_t; using i16 = std::int16_t; using u32 = std::uint32_t; using i32 = std::int32_t; using u64 = std::uint64_t; using i64 = std::int64_t; using usize = std::size_t; using f32 = float; using f64 = double; struct tSize { u32 width; u32 height; }; struct tRect { u32 x; u32 y; u32 width; u32 height; }; struct cSurface { private: u32* pBuffer; tSize size; u32 stride; bool owned { false }; struct OwnedTag {}; public: cSurface(u32* pBuffer, const tSize& size, u32 stride = -1) { if(stride == -1) { this->stride = size.width; } else { this->stride = stride; } this->size = size; this->pBuffer = pBuffer; this->owned = false; } cSurface(u32* pBuffer, const tSize& size, OwnedTag) { this->pBuffer = pBuffer; this->size = size; owned = true; } ~cSurface() { if(owned) { delete[] pBuffer; this->pBuffer = nullptr; } } cSurface(const cSurface&) = delete; cSurface(cSurface&& move) { this->pBuffer = move.pBuffer; move.pBuffer = nullptr; this->size = {}; this->stride = -1; this->owned = move.owned; move.owned = false; } u32 Stride() const { return stride; } u32 StrideBytes() const { return stride * sizeof(u32); } const tSize& Size() const { return size; } u32* Memory() { return &this->pBuffer[0]; } // creates a new owned cSurface which owns this memory std::unique_ptr ClonePiece(const tRect& rect) { auto* pSurfaceMemory = new u32[rect.width * rect.height * sizeof(u32)]; for(u32 y = 0; y < rect.height; ++y) { auto* pTileLineStart = &pBuffer[(rect.y + y) * this->stride + rect.x]; memcpy(&pSurfaceMemory[y * rect.width], pTileLineStart, rect.width * sizeof(u32)); } return std::unique_ptr(new cSurface(pSurfaceMemory, { rect.width, rect.height }, OwnedTag {})); } }; /// like vector but doesn't grow on its own template struct unique_buffer { T* m_buffer; size_t size; public: unique_buffer() { m_buffer = nullptr; size = 0; } // forbid copying or movement for now unique_buffer(const unique_buffer&) = delete; unique_buffer(unique_buffer&&) = delete; ~unique_buffer() { resize(0); } size_t get_size() const { return this->size; } void resize(size_t new_size) { if(m_buffer) { delete[] m_buffer; m_buffer = nullptr; size = 0; } if(new_size) { m_buffer = new T[new_size]; size = new_size; } } T* data() { return &m_buffer[0]; } const T* data() const { return &m_buffer[0]; } };