Initial release
This commit is contained in:
+443
@@ -0,0 +1,443 @@
|
||||
// This file is part of VSTGUI. It is subject to the license terms
|
||||
// in the LICENSE file found in the top-level directory of this
|
||||
// distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "vstguifwd.h"
|
||||
#include "cpoint.h"
|
||||
#include "crect.h"
|
||||
#include "cresourcedescription.h"
|
||||
#include "pixelbuffer.h"
|
||||
#include "platform/iplatformbitmap.h"
|
||||
#include <vector>
|
||||
|
||||
namespace VSTGUI {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CBitmap Declaration
|
||||
//! @brief Encapsulates various platform depended kinds of bitmaps
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBitmap : public AtomicReferenceCounted
|
||||
{
|
||||
public:
|
||||
using BitmapVector = std::vector<PlatformBitmapPtr>;
|
||||
using const_iterator = BitmapVector::const_iterator;
|
||||
|
||||
/** Create an image from a resource identifier */
|
||||
explicit CBitmap (const CResourceDescription& desc);
|
||||
/** Create an image with a given size */
|
||||
CBitmap (CCoord width, CCoord height);
|
||||
/** Create an image with a given size and scale factor */
|
||||
CBitmap (CPoint size, double scaleFactor = 1.);
|
||||
explicit CBitmap (const PlatformBitmapPtr& platformBitmap);
|
||||
~CBitmap () noexcept override = default;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/// @name CBitmap Methods
|
||||
//-----------------------------------------------------------------------------
|
||||
//@{
|
||||
virtual void draw (CDrawContext* context, const CRect& rect, const CPoint& offset = CPoint (0, 0), float alpha = 1.f);
|
||||
|
||||
/** get the width of the image */
|
||||
CCoord getWidth () const;
|
||||
/** get the height of the image */
|
||||
CCoord getHeight () const;
|
||||
/** get size of image */
|
||||
CPoint getSize () const;
|
||||
|
||||
/** check if image is loaded */
|
||||
bool isLoaded () const { return getPlatformBitmap () ? true : false; }
|
||||
|
||||
const CResourceDescription& getResourceDescription () const { return resourceDesc; }
|
||||
|
||||
PlatformBitmapPtr getPlatformBitmap () const;
|
||||
void setPlatformBitmap (const PlatformBitmapPtr& bitmap);
|
||||
|
||||
bool addBitmap (const PlatformBitmapPtr& platformBitmap);
|
||||
PlatformBitmapPtr getBestPlatformBitmapForScaleFactor (double scaleFactor) const;
|
||||
|
||||
const_iterator begin () const { return bitmaps.begin (); }
|
||||
const_iterator end () const { return bitmaps.end (); }
|
||||
//@}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
protected:
|
||||
CBitmap ();
|
||||
|
||||
CResourceDescription resourceDesc;
|
||||
BitmapVector bitmaps;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Description for a multi frame bitmap
|
||||
*
|
||||
* @ingroup new_in_4_12
|
||||
*/
|
||||
struct CMultiFrameBitmapDescription
|
||||
{
|
||||
/** size of one frame */
|
||||
CPoint frameSize {};
|
||||
/** number of total frames */
|
||||
uint16_t numFrames {};
|
||||
/** number of frames per row */
|
||||
uint16_t framesPerRow {1};
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Multi frame bitmap
|
||||
*
|
||||
* A bitmap describing multiple frames ordered in rows and columns
|
||||
*
|
||||
* The index order is columns and then rows:
|
||||
*
|
||||
* 1.Row: 1 -> 2 -> 3
|
||||
* 2.Row: 4 -> 5 -> 6
|
||||
* ...
|
||||
*
|
||||
* @ingroup new_in_4_12
|
||||
*/
|
||||
class CMultiFrameBitmap : public CBitmap
|
||||
{
|
||||
public:
|
||||
using CBitmap::CBitmap;
|
||||
|
||||
CMultiFrameBitmap (const CResourceDescription& desc,
|
||||
CMultiFrameBitmapDescription multiFrameDesc);
|
||||
|
||||
/** set the multi frame description
|
||||
*
|
||||
* @param desc the multi frame description
|
||||
* @return true if bitmap is big enough for the description
|
||||
*/
|
||||
bool setMultiFrameDesc (CMultiFrameBitmapDescription desc);
|
||||
/** get the mult frame description */
|
||||
CMultiFrameBitmapDescription getMultiFrameDesc () const;
|
||||
/** get the frame size */
|
||||
CPoint getFrameSize () const;
|
||||
/** get the number of frames */
|
||||
uint16_t getNumFrames () const;
|
||||
/** get the number of frames per row */
|
||||
uint16_t getNumFramesPerRow () const;
|
||||
/** calculate the rect for one frame */
|
||||
CRect calcFrameRect (uint32_t frameIndex) const;
|
||||
/** draw one frame at the position in the context */
|
||||
void drawFrame (CDrawContext* context, uint16_t frameIndex, CPoint pos);
|
||||
/** return the frame to display for a normalized value
|
||||
*
|
||||
* defaults to:
|
||||
* normalizedToSteps<float, uint16_t> (value, getNumFrames () - 1);
|
||||
*
|
||||
* subclasses can adopt this to other value mappings
|
||||
*
|
||||
* @ingroup new_in_4_12_1
|
||||
*/
|
||||
virtual uint16_t normalizedValueToFrameIndex (float value) const;
|
||||
/** return the normalized value from the frame index
|
||||
*
|
||||
* defaults to:
|
||||
* stepsToNormalized<float, uint16_t> (frameIndex, getNumFrames () - 1);
|
||||
*
|
||||
* subclasses can adopt this to other value mappings
|
||||
*
|
||||
* @ingroup new_in_4_12_1
|
||||
*/
|
||||
virtual float frameIndexToNormalizedValue (uint16_t frameIndex) const;
|
||||
|
||||
private:
|
||||
CMultiFrameBitmapDescription description;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/** an injection class for views that draw frames of a CMultiFrameBitmap
|
||||
*
|
||||
* a view/control can inherit from this class to support drawing only frames in a range of the
|
||||
* multi-frame bitmap.
|
||||
*
|
||||
* @ingroup new_in_4_12_2
|
||||
*/
|
||||
template<typename T>
|
||||
class MultiFrameBitmapView
|
||||
{
|
||||
using This = T;
|
||||
|
||||
public:
|
||||
/** set the range of the CMultiBitmapFrame this view will use for drawing
|
||||
*
|
||||
* @param startIndex the first frame to draw
|
||||
* @param endIndex the last frame to draw
|
||||
*/
|
||||
void setMultiFrameBitmapRange (int32_t startIndex, int32_t endIndex)
|
||||
{
|
||||
if (endIndex >= 0 && startIndex > endIndex)
|
||||
std::swap (startIndex, endIndex);
|
||||
frameStartIndex = startIndex;
|
||||
frameEndIndex = endIndex;
|
||||
static_cast<This*> (this)->invalid ();
|
||||
}
|
||||
|
||||
/** get the range of the CMulitBitmapFrame this view will use for drawing
|
||||
*
|
||||
* @return a std::pair with the start and end index
|
||||
*/
|
||||
std::pair<int32_t, int32_t> getMultiFrameBitmapRange () const
|
||||
{
|
||||
return {frameStartIndex, frameEndIndex};
|
||||
}
|
||||
|
||||
/** get the number of frames this view will use for drawing
|
||||
*
|
||||
* @param mfb the bitmap
|
||||
* @return the number of frames
|
||||
*/
|
||||
uint16_t getMultiFrameBitmapRangeLength (const CMultiFrameBitmap& mfb) const
|
||||
{
|
||||
auto endIndex = frameEndIndex >= 0 ? frameEndIndex : mfb.getNumFrames ();
|
||||
return endIndex - frameStartIndex;
|
||||
}
|
||||
|
||||
/** get the inverse index
|
||||
*
|
||||
* @param mfb the bitmap
|
||||
* @param index the index
|
||||
* @return the inverse index
|
||||
*/
|
||||
uint16_t getInverseIndex (const CMultiFrameBitmap& mfb, uint16_t index) const
|
||||
{
|
||||
auto endIndex = frameEndIndex >= 0 ? frameEndIndex : mfb.getNumFrames () - 1;
|
||||
if (index >= frameStartIndex && index <= endIndex)
|
||||
{
|
||||
return endIndex - (index - frameStartIndex);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/** get the frame index for a normalized value
|
||||
*
|
||||
* @param mfb the bitmap
|
||||
* @param normValue the normalized value
|
||||
* @return the index of the frame for the value
|
||||
*/
|
||||
uint16_t getMultiFrameBitmapIndex (const CMultiFrameBitmap& mfb, float normValue) const
|
||||
{
|
||||
if (frameStartIndex == 0 && frameEndIndex < 0)
|
||||
return mfb.normalizedValueToFrameIndex (normValue);
|
||||
|
||||
auto startNorm = mfb.frameIndexToNormalizedValue (frameStartIndex);
|
||||
auto endNorm = mfb.frameIndexToNormalizedValue (
|
||||
frameEndIndex >= 0 ? frameEndIndex : mfb.getNumFrames () - 1);
|
||||
normValue = normValue * (endNorm - startNorm) + startNorm;
|
||||
return mfb.normalizedValueToFrameIndex (normValue);
|
||||
}
|
||||
|
||||
/** get the normalized value for a frame index
|
||||
*
|
||||
* @param mfb the bitmap
|
||||
* @param index the frame index
|
||||
* @return the normalized value
|
||||
*/
|
||||
float getNormValueFromMultiFrameBitmapIndex (const CMultiFrameBitmap& mfb, uint16_t index) const
|
||||
{
|
||||
auto startNorm = mfb.frameIndexToNormalizedValue (frameStartIndex);
|
||||
auto endNorm = mfb.frameIndexToNormalizedValue (
|
||||
frameEndIndex >= 0 ? frameEndIndex : mfb.getNumFrames () - 1);
|
||||
auto indexNorm = mfb.frameIndexToNormalizedValue (index);
|
||||
return (indexNorm - startNorm) / (endNorm - startNorm);
|
||||
}
|
||||
|
||||
private:
|
||||
int32_t frameStartIndex {0};
|
||||
int32_t frameEndIndex {-1};
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
struct CNinePartTiledDescription
|
||||
{
|
||||
enum
|
||||
{
|
||||
kPartTopLeft,
|
||||
kPartTop,
|
||||
kPartTopRight,
|
||||
kPartLeft,
|
||||
kPartCenter,
|
||||
kPartRight,
|
||||
kPartBottomLeft,
|
||||
kPartBottom,
|
||||
kPartBottomRight,
|
||||
kPartCount
|
||||
};
|
||||
|
||||
CCoord left {0.};
|
||||
CCoord top {0.};
|
||||
CCoord right {0.};
|
||||
CCoord bottom {0.};
|
||||
|
||||
CNinePartTiledDescription () = default;
|
||||
CNinePartTiledDescription (CCoord left, CCoord top, CCoord right, CCoord bottom)
|
||||
: left (left), top (top), right (right), bottom (bottom) {}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void calcRects (const CRect& inBitmapRect, CRect outRect[kPartCount]) const
|
||||
{
|
||||
// Center
|
||||
CRect myCenter = outRect[kPartCenter] (inBitmapRect.left + left,
|
||||
inBitmapRect.top + top,
|
||||
inBitmapRect.right - right,
|
||||
inBitmapRect.bottom - bottom);
|
||||
|
||||
// Edges
|
||||
outRect[kPartTop] (myCenter.left, inBitmapRect.top, myCenter.right, myCenter.top);
|
||||
outRect[kPartLeft] (inBitmapRect.left, myCenter.top, myCenter.left, myCenter.bottom);
|
||||
outRect[kPartRight] (myCenter.right, myCenter.top, inBitmapRect.right, myCenter.bottom);
|
||||
outRect[kPartBottom] (myCenter.left, myCenter.bottom, myCenter.right, inBitmapRect.bottom);
|
||||
|
||||
// Corners
|
||||
outRect[kPartTopLeft] (inBitmapRect.left, inBitmapRect.top, myCenter.left, myCenter.top);
|
||||
outRect[kPartTopRight] (myCenter.right, inBitmapRect.top, inBitmapRect.right, myCenter.top);
|
||||
outRect[kPartBottomLeft] (inBitmapRect.left, myCenter.bottom, myCenter.left, inBitmapRect.bottom);
|
||||
outRect[kPartBottomRight] (myCenter.right, myCenter.bottom, inBitmapRect.right, inBitmapRect.bottom);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CNinePartTiledBitmap Declaration
|
||||
/// @brief a nine-part tiled bitmap
|
||||
/// @ingroup new_in_4_0
|
||||
//-----------------------------------------------------------------------------
|
||||
class CNinePartTiledBitmap : public CBitmap
|
||||
{
|
||||
public:
|
||||
CNinePartTiledBitmap (const CResourceDescription& desc, const CNinePartTiledDescription& offsets);
|
||||
CNinePartTiledBitmap (const PlatformBitmapPtr& platformBitmap, const CNinePartTiledDescription& offsets);
|
||||
~CNinePartTiledBitmap () noexcept override = default;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/// @name Part Offsets
|
||||
//-----------------------------------------------------------------------------
|
||||
//@{
|
||||
void setPartOffsets (const CNinePartTiledDescription& partOffsets) { offsets = partOffsets; }
|
||||
const CNinePartTiledDescription& getPartOffsets () const { return offsets; }
|
||||
//@}
|
||||
|
||||
void draw (CDrawContext* context, const CRect& rect, const CPoint& offset = CPoint (0, 0), float alpha = 1.f) override;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
protected:
|
||||
CNinePartTiledDescription offsets;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/** Convert between Platform Pixel Accessor pixel format and PixelBuffer format */
|
||||
template<typename T1, typename T2,
|
||||
typename std::enable_if<
|
||||
std::is_same<PixelBuffer::Format, T2>::value ||
|
||||
std::is_same<IPlatformBitmapPixelAccess::PixelFormat, T2>::value>::type* = nullptr>
|
||||
inline T1 convert (T2 format)
|
||||
{
|
||||
using PlPixelFormat = IPlatformBitmapPixelAccess::PixelFormat;
|
||||
using Format = PixelBuffer::Format;
|
||||
static_assert (std::is_same<Format, T1>::value || std::is_same<PlPixelFormat, T1>::value,
|
||||
"Unexpected Format");
|
||||
static_assert (!std::is_same<T1, T2>::value, "Unexpected Format");
|
||||
static_assert (static_cast<int32_t> (Format::ARGB) == PlPixelFormat::kARGB, "Format Mismatch");
|
||||
static_assert (static_cast<int32_t> (Format::ABGR) == PlPixelFormat::kABGR, "Format Mismatch");
|
||||
static_assert (static_cast<int32_t> (Format::RGBA) == PlPixelFormat::kRGBA, "Format Mismatch");
|
||||
static_assert (static_cast<int32_t> (Format::BGRA) == PlPixelFormat::kBGRA, "Format Mismatch");
|
||||
return static_cast<T1> (format);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// CBitmapPixelAccess
|
||||
/// @brief direct pixel access to a CBitmap
|
||||
/// @ingroup new_in_4_0
|
||||
//------------------------------------------------------------------------
|
||||
class CBitmapPixelAccess : public AtomicReferenceCounted
|
||||
{
|
||||
public:
|
||||
/** advance position */
|
||||
inline bool operator++ ();
|
||||
/** set current position */
|
||||
inline bool setPosition (uint32_t x, uint32_t y);
|
||||
/** return current x position */
|
||||
inline uint32_t getX () const { return x; }
|
||||
/** return current y position */
|
||||
inline uint32_t getY () const { return y; }
|
||||
/** get color of current pixel */
|
||||
virtual void getColor (CColor& c) const = 0;
|
||||
/** set color of current pixel */
|
||||
virtual void setColor (const CColor& c) = 0;
|
||||
|
||||
/** get native color value */
|
||||
inline void getValue (uint32_t& value);
|
||||
/** set native color value */
|
||||
inline void setValue (uint32_t value);
|
||||
|
||||
inline uint32_t getBitmapWidth () const { return maxX+1; }
|
||||
inline uint32_t getBitmapHeight () const { return maxY+1; }
|
||||
|
||||
inline IPlatformBitmapPixelAccess* getPlatformBitmapPixelAccess () const { return pixelAccess; }
|
||||
/** create an accessor.
|
||||
can return 0 if platform implementation does not support this.
|
||||
result needs to be forgotten before the CBitmap reflects the change to the pixels */
|
||||
static CBitmapPixelAccess* create (CBitmap* bitmap, bool alphaPremultiplied = true);
|
||||
//-----------------------------------------------------------------------------
|
||||
protected:
|
||||
CBitmapPixelAccess ();
|
||||
~CBitmapPixelAccess () noexcept override = default;
|
||||
void init (CBitmap* bitmap, IPlatformBitmapPixelAccess* pixelAccess);
|
||||
|
||||
CBitmap* bitmap;
|
||||
SharedPointer<IPlatformBitmapPixelAccess> pixelAccess;
|
||||
uint8_t* currentPos;
|
||||
uint8_t* address;
|
||||
uint32_t bytesPerRow;
|
||||
uint32_t maxX;
|
||||
uint32_t maxY;
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool CBitmapPixelAccess::operator++ ()
|
||||
{
|
||||
if (x < maxX)
|
||||
{
|
||||
x++;
|
||||
currentPos += 4;
|
||||
return true;
|
||||
}
|
||||
else if (y < maxY)
|
||||
{
|
||||
y++;
|
||||
x = 0;
|
||||
currentPos = address + y * bytesPerRow;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool CBitmapPixelAccess::setPosition (uint32_t _x, uint32_t _y)
|
||||
{
|
||||
if (_x > maxX || _y > maxY)
|
||||
return false;
|
||||
x = _x;
|
||||
y = _y;
|
||||
currentPos = address + y * bytesPerRow + x * 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void CBitmapPixelAccess::getValue (uint32_t& value)
|
||||
{
|
||||
value = *(uint32_t*) (currentPos);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void CBitmapPixelAccess::setValue (uint32_t value)
|
||||
{
|
||||
*(uint32_t*) (currentPos) = value;
|
||||
}
|
||||
|
||||
} // VSTGUI
|
||||
Reference in New Issue
Block a user