Initial release

This commit is contained in:
civ
2026-08-16 18:24:52 +07:00
commit 876886a39a
13244 changed files with 2353959 additions and 0 deletions
+443
View File
@@ -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