canvas.h
#ifndef CANVAS_H #define CANVAS_H #include "aligned_vector.h" #include <stdexcept> #include <type_traits> template<typename T, size_t Alignment = DEFAULT_MEMORY_ALIGNMENT> class Canvas { static_assert(std::is_trivially_copyable_v<T>); public: Canvas(size_t a_width, size_t a_height, const T & a_fillValue = T()) : m_width(a_width) , m_height(a_height) { if((a_width == 0) || (a_height == 0)) throw std::bad_array_new_length(); m_rowSize = a_width * sizeof(T); m_stride = ((m_rowSize + Alignment - 1) / Alignment) * Alignment; m_data = std::move(aligned_vector<T, Alignment>(m_height * m_stride, a_fillValue)); } Canvas(const Canvas & a_other) = default; Canvas(Canvas && a_other) = default; Canvas & operator=(const Canvas & a_other) = default; Canvas & operator=(Canvas && a_other) = default; virtual ~Canvas() = default; size_t width() const { return m_width; } size_t height() const { return m_height; } size_t stride() const { return m_stride; } size_t rowSize() const { return m_rowSize; } std::byte * bytes() { return (std::byte *)m_data.data(); } const std::byte * bytes() const { return (const std::byte *)m_data.data(); } const T * operator[](size_t a_row) const { return (const T *)(bytes() + a_row * m_stride); } T * operator[](size_t a_row) { return (T *)(bytes() + a_row * m_stride); } [[nodiscard]] Canvas resized(size_t a_width, size_t a_height, const T & a_fillValue = T()) const { Canvas newCanvas(a_width, a_height, a_fillValue); for(size_t i = 0; i < std::min(m_height, a_height); ++i) memcpy(newCanvas[i], operator[](i), std::min(m_rowSize, newCanvas.rowSize())); return newCanvas; } protected: size_t m_width{0}; size_t m_height{0}; size_t m_stride{0}; size_t m_rowSize{0}; aligned_vector<T, Alignment> m_data; }; #endif
Leave a Comment