summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/bitmap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/bitmap.cpp')
-rw-r--r--src/lib/util/bitmap.cpp233
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>;