V_BEGIN_NAMESPACE
-struct VBitmapData {
- ~VBitmapData();
- VBitmapData();
- static VBitmapData *create(int width, int height, VBitmap::Format format);
- RefCount ref;
- int width;
- int height;
- int depth;
- int stride;
- int nBytes;
- VBitmap::Format format;
- uchar * data;
- VBitmapCleanupFunction cleanupFunction;
- void * cleanupInfo;
- uint ownData : 1;
- uint roData : 1;
-};
-
-VBitmapData::~VBitmapData()
-{
- if (cleanupFunction) cleanupFunction(cleanupInfo);
- if (data && ownData) free(data);
- data = 0;
-}
-
-VBitmapData::VBitmapData()
- : ref(0),
- width(0),
- height(0),
- depth(0),
- stride(0),
- nBytes(0),
- format(VBitmap::Format::ARGB32),
- data(nullptr),
- cleanupFunction(0),
- cleanupInfo(0),
- ownData(true),
- roData(false)
-{
-}
-
-VBitmapData *VBitmapData::create(int width, int height, VBitmap::Format format)
-{
- if ((width <= 0) || (height <= 0) || format == VBitmap::Format::Invalid)
- return nullptr;
-
- int depth = 1;
- switch (format) {
- case VBitmap::Format::Alpha8:
- depth = 8;
- VECTOR_FALLTHROUGH
- case VBitmap::Format::ARGB32:
- case VBitmap::Format::ARGB32_Premultiplied:
- depth = 32;
- break;
- default:
- break;
+struct VBitmap::Impl {
+ uchar * mData{nullptr};
+ uint mWidth{0};
+ uint mHeight{0};
+ uint mStride{0};
+ uint mBytes{0};
+ VBitmap::Format mFormat{VBitmap::Format::Invalid};
+ bool mOwnData;
+ bool mRoData;
+
+ Impl() = delete ;
+
+ Impl(uint width, uint height, VBitmap::Format format):
+ mOwnData(true),
+ mRoData(false)
+ {
+ uint depth = Impl::depth(format);
+ uint stride = ((width * depth + 31) >> 5) << 2; // bytes per scanline (must be multiple of 4)
+
+ mWidth = width;
+ mHeight = height;
+ mFormat = format;
+ mStride = stride;
+ mBytes = mStride * mHeight;
+ mData = reinterpret_cast<uchar *>(::operator new(mBytes));
+
+ if (!mData) {
+ // handle malloc failure
+ ;
+ }
}
- const int stride = ((width * depth + 31) >> 5)
- << 2; // bytes per scanline (must be multiple of 4)
-
- VBitmapData *d = new VBitmapData;
-
- d->width = width;
- d->height = height;
- d->depth = depth;
- d->format = format;
- d->stride = stride;
- d->nBytes = d->stride * height;
- d->data = (uchar *)malloc(d->nBytes);
-
- if (!d->data) {
- delete d;
- return 0;
+ Impl(uchar *data, uint w, uint h, uint bytesPerLine, VBitmap::Format format):
+ mOwnData(false),
+ mRoData(false)
+ {
+ mWidth = w;
+ mHeight = h;
+ mFormat = format;
+ mStride = bytesPerLine;
+ mBytes = mStride * mHeight;
+ mData = data;
}
- return d;
-}
-
-inline void VBitmap::cleanUp(VBitmapData *d)
-{
- delete d;
-}
-
-void VBitmap::detach()
-{
- if (d) {
- if (d->ref.isShared() || d->roData) *this = copy();
+ ~Impl()
+ {
+ if (mOwnData && mData) ::operator delete(mData);
}
-}
-
-VBitmap::~VBitmap()
-{
- if (!d) return;
-
- if (!d->ref.deref()) cleanUp(d);
-}
-
-VBitmap::VBitmap() : d(nullptr) {}
-
-VBitmap::VBitmap(const VBitmap &other)
-{
- d = other.d;
- if (d) d->ref.ref();
-}
-VBitmap::VBitmap(VBitmap &&other) : d(other.d)
-{
- other.d = nullptr;
-}
-
-VBitmap &VBitmap::operator=(const VBitmap &other)
-{
- if (!d) {
- d = other.d;
- if (d) d->ref.ref();
- } else {
- if (!d->ref.deref()) cleanUp(d);
- other.d->ref.ref();
- d = other.d;
+ uint stride() const {return mStride;}
+ uint width() const {return mWidth;}
+ uint height() const {return mHeight;}
+ VBitmap::Format format() const {return mFormat;}
+ uchar* data() { return mData;}
+
+ static uint depth(VBitmap::Format format)
+ {
+ uint depth = 1;
+ switch (format) {
+ case VBitmap::Format::Alpha8:
+ depth = 8;
+ break;
+ case VBitmap::Format::ARGB32:
+ case VBitmap::Format::ARGB32_Premultiplied:
+ depth = 32;
+ break;
+ default:
+ break;
+ }
+ return depth;
}
+ void fill(uint /*pixel*/)
+ {
+ //@TODO
+ }
+};
- return *this;
-}
-
-inline VBitmap &VBitmap::operator=(VBitmap &&other)
+VBitmap::VBitmap(uint width, uint height, VBitmap::Format format)
{
- if (d && !d->ref.deref()) cleanUp(d);
- d = other.d;
- return *this;
-}
+ if (width <=0 || height <=0 || format == Format::Invalid) return;
-VBitmap::VBitmap(int w, int h, VBitmap::Format format) {}
-VBitmap::VBitmap(uchar *data, int w, int h, int bytesPerLine,
- VBitmap::Format format, VBitmapCleanupFunction f,
- void *cleanupInfo)
-{
- d = new VBitmapData;
- d->data = data;
- d->format = format;
- d->width = w;
- d->height = h;
- d->stride = bytesPerLine;
- d->cleanupFunction = nullptr;
- d->cleanupInfo = nullptr;
- d->ownData = false;
- d->roData = false;
- d->ref.setOwned();
-}
+ mImpl = std::make_shared<Impl>(width, height, format);
-VBitmap VBitmap::copy(const VRect &r) const
-{
- // TODO implement properly.
- return *this;
-}
-
-int VBitmap::stride() const
-{
- return d ? d->stride : 0;
}
-int VBitmap::width() const
+VBitmap::VBitmap(uchar *data, uint width, uint height, uint bytesPerLine,
+ VBitmap::Format format)
{
- return d ? d->width : 0;
-}
+ if (!data ||
+ width <=0 || height <=0 ||
+ bytesPerLine <=0 ||
+ format == Format::Invalid) return;
-int VBitmap::height() const
-{
- return d ? d->height : 0;
+ mImpl = std::make_shared<Impl>(data, width, height, bytesPerLine, format);
}
-uchar *VBitmap::bits()
+uint VBitmap::stride() const
{
- if (!d) return 0;
- detach();
-
- // In case detach ran out of memory...
- if (!d) return 0;
-
- return d->data;
+ return mImpl ? mImpl->stride() : 0;
}
-const uchar *VBitmap::bits() const
+uint VBitmap::width() const
{
- return d ? d->data : 0;
+ return mImpl ? mImpl->width() : 0;
}
-bool VBitmap::isNull() const
+uint VBitmap::height() const
{
- return !d;
+ return mImpl ? mImpl->height() : 0;
}
-uchar *VBitmap::scanLine(int i)
+uchar *VBitmap::data()
{
- if (!d) return 0;
-
- detach();
-
- // In case detach() ran out of memory
- if (!d) return 0;
-
- return d->data + i * d->stride;
+ return mImpl ? mImpl->data() : nullptr;
}
-const uchar *VBitmap::scanLine(int i) const
+bool VBitmap::valid() const
{
- if (!d) return 0;
-
- // assert(i >= 0 && i < height());
- return d->data + i * d->stride;
+ return mImpl ? true : false;
}
VBitmap::Format VBitmap::format() const
{
- if (!d) return VBitmap::Format::Invalid;
- return d->format;
+ return mImpl ? mImpl->format() : VBitmap::Format::Invalid;
}
void VBitmap::fill(uint pixel)
{
- if (!d) return;
+ if (mImpl) mImpl->fill(pixel);
}
V_END_NAMESPACE
V_BEGIN_NAMESPACE
-struct VBitmapData;
-typedef void (*VBitmapCleanupFunction)(void *);
class VBitmap {
public:
- enum class Format { Invalid, Alpha8, ARGB32, ARGB32_Premultiplied, Last };
- ~VBitmap();
- VBitmap();
- VBitmap(const VBitmap &other);
- VBitmap(VBitmap &&other);
- VBitmap &operator=(const VBitmap &);
- VBitmap &operator=(VBitmap &&other);
-
- VBitmap(int w, int h, VBitmap::Format format);
- VBitmap(uchar *data, int w, int h, int bytesPerLine, VBitmap::Format format,
- VBitmapCleanupFunction f = nullptr, void *cleanupInfo = nullptr);
-
- VBitmap copy(const VRect &rect = VRect()) const;
- void fill(uint pixel);
-
- int width() const;
- int height() const;
- uchar * bits();
- const uchar * bits() const;
- uchar * scanLine(int);
- const uchar * scanLine(int) const;
- int stride() const;
- bool isNull() const;
+ enum class Format: uchar {
+ Invalid,
+ Alpha8,
+ ARGB32,
+ ARGB32_Premultiplied
+ };
+
+ VBitmap() = default;
+ VBitmap(uint w, uint h, VBitmap::Format format);
+ VBitmap(uchar *data, uint w, uint h, uint bytesPerLine, VBitmap::Format format);
+
+ uint stride() const;
+ uint width() const;
+ uint height() const;
VBitmap::Format format() const;
+ bool valid() const;
+ uchar * data();
+ void fill(uint pixel);
private:
- void detach();
- void cleanUp(VBitmapData *x);
- VBitmapData *d{nullptr};
+ struct Impl;
+ std::shared_ptr<Impl> mImpl;
};
V_END_NAMESPACE