diff options
Diffstat (limited to 'src/lib/util/bitmap.cpp')
-rw-r--r-- | src/lib/util/bitmap.cpp | 233 |
1 files changed, 97 insertions, 136 deletions
diff --git a/src/lib/util/bitmap.cpp b/src/lib/util/bitmap.cpp index 87cf8a27b76..8287009311d 100644 --- a/src/lib/util/bitmap.cpp +++ b/src/lib/util/bitmap.cpp @@ -8,14 +8,13 @@ ***************************************************************************/ -#include <assert.h> - #include "bitmap.h" +#include <cassert> +#include <cstring> #include <new> - //************************************************************************** // INLINE HELPERS //************************************************************************** @@ -24,7 +23,7 @@ // compute_rowpixels - compute a rowpixels value //------------------------------------------------- -inline int32_t bitmap_t::compute_rowpixels(int width, int xslop) +inline int32_t bitmap_t::compute_rowpixels(int width, int xslop) noexcept { return width + 2 * xslop; } @@ -35,9 +34,9 @@ inline int32_t bitmap_t::compute_rowpixels(int width, int xslop) // with the given slop values //------------------------------------------------- -inline void bitmap_t::compute_base(int xslop, int yslop) +inline void bitmap_t::compute_base(int xslop, int yslop) noexcept { - m_base = m_alloc.get() + (m_rowpixels * yslop + xslop) * (m_bpp / 8); + m_base = &m_alloc[(m_rowpixels * yslop + xslop) * (m_bpp / 8)]; } @@ -46,7 +45,7 @@ inline void bitmap_t::compute_base(int xslop, int yslop) // is valid and agrees with the BPP //------------------------------------------------- -inline bool bitmap_t::valid_format() const +inline bool bitmap_t::valid_format() const noexcept { switch (m_format) { @@ -82,7 +81,7 @@ inline bool bitmap_t::valid_format() const // BITMAP ALLOCATION/CONFIGURATION //************************************************************************** -bitmap_t::bitmap_t(bitmap_t &&that) +bitmap_t::bitmap_t(bitmap_t &&that) noexcept : m_alloc(std::move(that.m_alloc)) , m_allocbytes(that.m_allocbytes) , m_base(that.m_base) @@ -113,7 +112,7 @@ bitmap_t::bitmap_t(bitmap_t &&that) * @param yslop The yslop. */ -bitmap_t::bitmap_t(bitmap_format format, uint8_t bpp, int width, int height, int xslop, int yslop) +bitmap_t::bitmap_t(bitmap_format format, uint8_t bpp, int width, int height, int xslop, int yslop) noexcept : m_alloc() , m_allocbytes(0) , m_format(format) @@ -139,7 +138,7 @@ bitmap_t::bitmap_t(bitmap_format format, uint8_t bpp, int width, int height, int * @param rowpixels The rowpixels. */ -bitmap_t::bitmap_t(bitmap_format format, uint8_t bpp, void *base, int width, int height, int rowpixels) +bitmap_t::bitmap_t(bitmap_format format, uint8_t bpp, void *base, int width, int height, int rowpixels) noexcept : m_alloc() , m_allocbytes(0) , m_base(base) @@ -165,7 +164,7 @@ bitmap_t::bitmap_t(bitmap_format format, uint8_t bpp, void *base, int width, int * @param subrect The subrect. */ -bitmap_t::bitmap_t(bitmap_format format, uint8_t bpp, bitmap_t &source, const rectangle &subrect) +bitmap_t::bitmap_t(bitmap_format format, uint8_t bpp, bitmap_t &source, const rectangle &subrect) noexcept : m_alloc() , m_allocbytes(0) , m_base(source.raw_pixptr(subrect.top(), subrect.left())) @@ -196,7 +195,7 @@ bitmap_t::~bitmap_t() reset(); } -bitmap_t &bitmap_t::operator=(bitmap_t &&that) +bitmap_t &bitmap_t::operator=(bitmap_t &&that) noexcept { m_alloc = std::move(that.m_alloc); m_allocbytes = that.m_allocbytes; @@ -226,7 +225,7 @@ bitmap_t &bitmap_t::operator=(bitmap_t &&that) * @param yslop The yslop. */ -void bitmap_t::allocate(int width, int height, int xslop, int yslop) +void bitmap_t::allocate(int width, int height, int xslop, int yslop) noexcept { assert(m_format != BITMAP_FORMAT_INVALID); assert(m_bpp == 8 || m_bpp == 16 || m_bpp == 32 || m_bpp == 64); @@ -235,24 +234,28 @@ void bitmap_t::allocate(int width, int height, int xslop, int yslop) reset(); // handle empty requests cleanly - if (width <= 0 || height <= 0) - return; - - // initialize fields - m_rowpixels = compute_rowpixels(width, xslop); - m_width = width; - m_height = height; - m_cliprect.set(0, width - 1, 0, height - 1); - - // allocate memory for the bitmap itself - m_allocbytes = m_rowpixels * (m_height + 2 * yslop) * m_bpp / 8; - m_alloc.reset(new uint8_t[m_allocbytes]); - - // clear to 0 by default - memset(m_alloc.get(), 0, m_allocbytes); - - // compute the base - compute_base(xslop, yslop); + if ((0 < width) && (0 < height)) + { + // allocate memory for the bitmap itself + int32_t const new_rowpixels = compute_rowpixels(width, xslop); + uint32_t const new_allocbytes = new_rowpixels * (height + 2 * yslop) * m_bpp / 8; + m_alloc.reset(new (std::nothrow) uint8_t[new_allocbytes]); + if (m_alloc) + { + // initialize fields + m_allocbytes = new_allocbytes; + m_rowpixels = new_rowpixels; + m_width = width; + m_height = height; + m_cliprect.set(0, width - 1, 0, height - 1); + + // clear to 0 by default + memset(m_alloc.get(), 0, m_allocbytes); + + // compute the base + compute_base(xslop, yslop); + } + } } /** @@ -269,36 +272,41 @@ void bitmap_t::allocate(int width, int height, int xslop, int yslop) * @param yslop The yslop. */ -void bitmap_t::resize(int width, int height, int xslop, int yslop) +void bitmap_t::resize(int width, int height, int xslop, int yslop) noexcept { assert(m_format != BITMAP_FORMAT_INVALID); assert(m_bpp == 8 || m_bpp == 16 || m_bpp == 32 || m_bpp == 64); // handle empty requests cleanly - if (width <= 0 || height <= 0) + if ((width <= 0) || (height <= 0)) width = height = 0; // determine how much memory we need for the new bitmap - int new_rowpixels = compute_rowpixels(width, xslop); - uint32_t new_allocbytes = new_rowpixels * (height + 2 * yslop) * m_bpp / 8; + int32_t const new_rowpixels = compute_rowpixels(width, xslop); + uint32_t const new_allocbytes = new_rowpixels * (height + 2 * yslop) * m_bpp / 8; - // if we need more memory, just realloc if (new_allocbytes > m_allocbytes) { - palette_t *palette = m_palette; + // if we need more memory, just realloc + palette_t *const palette = m_palette; + if (palette) + palette->ref(); allocate(width, height, xslop, yslop); set_palette(palette); - return; + if (palette) + palette->deref(); + } + else + { + // otherwise, reconfigure + m_rowpixels = new_rowpixels; + m_width = width; + m_height = height; + m_cliprect.set(0, width - 1, 0, height - 1); + + // re-compute the base + compute_base(xslop, yslop); } - - // otherwise, reconfigure - m_rowpixels = new_rowpixels; - m_width = width; - m_height = height; - m_cliprect.set(0, width - 1, 0, height - 1); - - // re-compute the base - compute_base(xslop, yslop); } /** @@ -309,7 +317,7 @@ void bitmap_t::resize(int width, int height, int xslop, int yslop) * -------------------------------------------------. */ -void bitmap_t::reset() +void bitmap_t::reset() noexcept { // delete any existing stuff set_palette(nullptr); @@ -317,6 +325,7 @@ void bitmap_t::reset() m_base = nullptr; // reset all fields + m_allocbytes = 0; m_rowpixels = 0; m_width = 0; m_height = 0; @@ -336,8 +345,11 @@ void bitmap_t::reset() * @param rowpixels The rowpixels. */ -void bitmap_t::wrap(void *base, int width, int height, int rowpixels) +void bitmap_t::wrap(void *base, int width, int height, int rowpixels) noexcept { + assert(base || (!width && !height)); + assert(!m_alloc || (&m_alloc[0] > base) || (&m_alloc[m_allocbytes] <= base)); + // delete any existing stuff reset(); @@ -361,8 +373,9 @@ void bitmap_t::wrap(void *base, int width, int height, int rowpixels) * @param subrect The subrect. */ -void bitmap_t::wrap(const bitmap_t &source, const rectangle &subrect) +void bitmap_t::wrap(bitmap_t &source, const rectangle &subrect) noexcept { + assert(&source != this); assert(m_format == source.m_format); assert(m_bpp == source.m_bpp); assert(source.cliprect().contains(subrect)); @@ -389,121 +402,69 @@ void bitmap_t::wrap(const bitmap_t &source, const rectangle &subrect) * @param [in,out] palette If non-null, the palette. */ -void bitmap_t::set_palette(palette_t *palette) +void bitmap_t::set_palette(palette_t *palette) noexcept { - // first dereference any existing palette - if (m_palette != nullptr) - { + // first reference the new palette + if (palette) + palette->ref(); + + // then dereference any existing palette + if (m_palette) m_palette->deref(); - m_palette = nullptr; - } - // then reference any new palette - if (palette != nullptr) - { - palette->ref(); - m_palette = palette; - } + m_palette = palette; } /** - * @fn void bitmap_t::fill(uint32_t color, const rectangle &cliprect) + * @fn void bitmap_t::fill(uint64_t color, const rectangle &bounds) * * @brief ------------------------------------------------- * fill -- fill a bitmap with a solid color * -------------------------------------------------. * * @param color The color. - * @param cliprect The cliprect. + * @param bounds The bounds. */ -void bitmap_t::fill(uint32_t color, const rectangle &cliprect) +void bitmap_t::fill(uint64_t color, const rectangle &bounds) noexcept { // if we have a cliprect, intersect with that - rectangle fill = cliprect; + rectangle fill(bounds); fill &= m_cliprect; - if (fill.empty()) - return; - - // based on the bpp go from there - switch (m_bpp) + if (!fill.empty()) { + // based on the bpp go from there + switch (m_bpp) + { case 8: - // 8bpp always uses memset for (int32_t y = fill.top(); y <= fill.bottom(); y++) - memset(raw_pixptr(y, fill.left()), uint8_t(color), fill.width()); + std::fill_n(&pixt<uint8_t>(y, fill.left()), fill.width(), uint8_t(color)); break; case 16: - // 16bpp can use memset if the bytes are equal - if (uint8_t(color >> 8) == uint8_t(color)) - { - for (int32_t y = fill.top(); y <= fill.bottom(); y++) - memset(raw_pixptr(y, fill.left()), uint8_t(color), fill.width() * 2); - } - else - { - // Fill the first line the hard way - uint16_t *destrow = &pixt<uint16_t>(fill.top()); - for (int32_t x = fill.left(); x <= fill.right(); x++) - destrow[x] = uint16_t(color); - - // For the other lines, just copy the first one - void *destrow0 = &pixt<uint16_t>(fill.top(), fill.left()); - for (int32_t y = fill.top() + 1; y <= fill.bottom(); y++) - { - destrow = &pixt<uint16_t>(y, fill.left()); - memcpy(destrow, destrow0, fill.width() * 2); - } - } + for (int32_t y = fill.top(); y <= fill.bottom(); ++y) + std::fill_n(&pixt<uint16_t>(y, fill.left()), fill.width(), uint16_t(color)); break; case 32: - // 32bpp can use memset if the bytes are equal - if ((uint8_t)(color >> 8) == (uint8_t)color && (uint16_t)(color >> 16) == (uint16_t)color) - { - for (int32_t y = fill.top(); y <= fill.bottom(); y++) - memset(&pixt<uint32_t>(y, fill.left()), uint8_t(color), fill.width() * 4); - } - else - { - // Fill the first line the hard way - uint32_t *destrow = &pixt<uint32_t>(fill.top()); - for (int32_t x = fill.left(); x <= fill.right(); x++) - destrow[x] = uint32_t(color); - - // For the other lines, just copy the first one - uint32_t *destrow0 = &pixt<uint32_t>(fill.top(), fill.left()); - for (int32_t y = fill.top() + 1; y <= fill.bottom(); y++) - { - destrow = &pixt<uint32_t>(y, fill.left()); - memcpy(destrow, destrow0, fill.width() * 4); - } - } + for (int32_t y = fill.top(); y <= fill.bottom(); ++y) + std::fill_n(&pixt<uint32_t>(y, fill.left()), fill.width(), uint32_t(color)); break; case 64: - // 64bpp can use memset if the bytes are equal - if (uint8_t(color >> 8) == uint8_t(color) && uint16_t(color >> 16) == uint16_t(color)) // FIXME: really? wat about the upper bits that would be zeroed when done the "hard way"? - { - for (int32_t y = fill.top(); y <= fill.bottom(); y++) - memset(&pixt<uint64_t>(y, fill.left()), uint8_t(color), fill.width() * 8); - } - else - { - // Fill the first line the hard way - uint64_t *destrow = &pixt<uint64_t>(fill.top()); - for (int32_t x = fill.left(); x <= fill.right(); x++) - destrow[x] = uint64_t(color); - - // For the other lines, just copy the first one - uint64_t *destrow0 = &pixt<uint64_t>(fill.top(), fill.left()); - for (int32_t y = fill.top() + 1; y <= fill.bottom(); y++) - { - destrow = &pixt<uint64_t>(y, fill.left()); - memcpy(destrow, destrow0, fill.width() * 8); - } - } + for (int32_t y = fill.top(); y <= fill.bottom(); ++y) + std::fill_n(&pixt<uint64_t>(y, fill.left()), fill.width(), uint64_t(color)); break; + } } } + + +//************************************************************************** +// EXPLICIT TEMPLATE INSTANTIATIONS +//************************************************************************** + +template class bitmap_specific<uint8_t>; +template class bitmap_specific<uint16_t>; +template class bitmap_specific<uint32_t>; +template class bitmap_specific<uint64_t>; |