/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #ifndef OD_SR_DATA_BUFFER_H #define OD_SR_DATA_BUFFER_H /** * DataBuffer Class with optimized texture operations * Encapsulates buffer data and provides high-performance pixel access */ // Forward declarations of function pointers typedef void (*PixelGetter)(const OdUInt8* pData, OdUInt32 scanLineLength, const ODCOLORREF* pTexPalette, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a); typedef void (*PixelSetter)(OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8 r, OdUInt8 g, OdUInt8 b, OdUInt8 a); /** * Texture format enumeration values */ namespace TextureFormat { enum ColorOrder { RGB, BGR }; enum BitsPerPixel { BPP1 = 1, BPP4 = 4, BPP8 = 8, BPP24 = 24, BPP32 = 32 }; enum TransparencyMode { None, Default, OneBit, EightBit }; /** * Named parameters for texture format configuration * Provides a cleaner way to specify texture properties */ struct TextureFormatParams { // Texture format components BitsPerPixel bpp; ColorOrder colorOrder; bool usePalette; TransparencyMode transparency; // Constructor with default values TextureFormatParams( BitsPerPixel _bpp = BPP32, ColorOrder _colorOrder = BGR, bool _usePalette = false, TransparencyMode _transparency = None) : bpp(_bpp), colorOrder(_colorOrder), usePalette(_usePalette), transparency(_transparency) { } // Chainable setters for fluent API TextureFormatParams& setBpp(BitsPerPixel _bpp) { bpp = _bpp; return *this; } TextureFormatParams& setColorOrder(ColorOrder _colorOrder) { colorOrder = _colorOrder; return *this; } TextureFormatParams& setUsePalette(bool _usePalette) { usePalette = _usePalette; return *this; } TextureFormatParams& setTransparency(TransparencyMode _transparency) { transparency = _transparency; return *this; } }; } /** * All getter implementations as non-member functions * These are internal implementation details, not exposed directly */ namespace TextureGetters { // === 1BPP PALETTE GETTERS === inline void Get1bppPalette(const OdUInt8* pData, OdUInt32 scanLineLength, const ODCOLORREF* pTexPalette, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a) { OdUInt8 nColorIndex = ((pData + scanLineLength * y)[x / 8] >> (0x07 - (x % 8))) & 0x01; r = ODGETRED(pTexPalette[nColorIndex]); g = ODGETGREEN(pTexPalette[nColorIndex]); b = ODGETBLUE(pTexPalette[nColorIndex]); a = 255; // No alpha } inline void Get1bppPaletteTransparent(const OdUInt8* pData, OdUInt32 scanLineLength, const ODCOLORREF* pTexPalette, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a) { OdUInt8 nColorIndex = ((pData + scanLineLength * y)[x / 8] >> (0x07 - (x % 8))) & 0x01; r = ODGETRED(pTexPalette[nColorIndex]); g = ODGETGREEN(pTexPalette[nColorIndex]); b = ODGETBLUE(pTexPalette[nColorIndex]); a = ODGETALPHA(pTexPalette[nColorIndex]); } // === 4BPP PALETTE GETTERS === inline void Get4bppPalette(const OdUInt8* pData, OdUInt32 scanLineLength, const ODCOLORREF* pTexPalette, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a) { OdUInt8 nColorIndex = ((x % 2) & 0x01) ? ((pData + scanLineLength * y)[x / 2] & 0x0F) : (((pData + scanLineLength * y)[x / 2] & 0xF0) >> 4); r = ODGETRED(pTexPalette[nColorIndex]); g = ODGETGREEN(pTexPalette[nColorIndex]); b = ODGETBLUE(pTexPalette[nColorIndex]); a = 255; // No alpha } inline void Get4bppPaletteTransparent(const OdUInt8* pData, OdUInt32 scanLineLength, const ODCOLORREF* pTexPalette, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a) { OdUInt8 nColorIndex = ((x % 2) & 0x01) ? ((pData + scanLineLength * y)[x / 2] & 0x0F) : (((pData + scanLineLength * y)[x / 2] & 0xF0) >> 4); r = ODGETRED(pTexPalette[nColorIndex]); g = ODGETGREEN(pTexPalette[nColorIndex]); b = ODGETBLUE(pTexPalette[nColorIndex]); a = ODGETALPHA(pTexPalette[nColorIndex]); } // === 8BPP PALETTE GETTERS === inline void Get8bppPalette(const OdUInt8* pData, OdUInt32 scanLineLength, const ODCOLORREF* pTexPalette, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a) { OdUInt8 nColorIndex = (pData + scanLineLength * y)[x]; r = ODGETRED(pTexPalette[nColorIndex]); g = ODGETGREEN(pTexPalette[nColorIndex]); b = ODGETBLUE(pTexPalette[nColorIndex]); a = 255; // No alpha } inline void Get8bppPaletteTransparent(const OdUInt8* pData, OdUInt32 scanLineLength, const ODCOLORREF* pTexPalette, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a) { OdUInt8 nColorIndex = (pData + scanLineLength * y)[x]; r = ODGETRED(pTexPalette[nColorIndex]); g = ODGETGREEN(pTexPalette[nColorIndex]); b = ODGETBLUE(pTexPalette[nColorIndex]); a = ODGETALPHA(pTexPalette[nColorIndex]); } // === 24BPP DIRECT COLOR GETTERS === inline void Get24bppBGR(const OdUInt8* pData, OdUInt32 scanLineLength, const ODCOLORREF* /*pTexPalette*/, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a) { const OdUInt8* texBGR = pData + scanLineLength * y + x * 3; b = texBGR[0]; g = texBGR[1]; r = texBGR[2]; a = 255; // No alpha } inline void Get24bppRGB(const OdUInt8* pData, OdUInt32 scanLineLength, const ODCOLORREF* /*pTexPalette*/, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a) { const OdUInt8* texRGB = pData + scanLineLength * y + x * 3; r = texRGB[0]; g = texRGB[1]; b = texRGB[2]; a = 255; // No alpha } // === 32BPP DIRECT COLOR GETTERS === inline void Get32bppBGR(const OdUInt8* pData, OdUInt32 scanLineLength, const ODCOLORREF* /*pTexPalette*/, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a) { const OdUInt8* texBGRA = pData + scanLineLength * y + x * 4; b = texBGRA[0]; g = texBGRA[1]; r = texBGRA[2]; a = 255; // ignore alpha, i.e. set it visible } inline void Get32bppBGR_Transparent1Bit(const OdUInt8* pData, OdUInt32 scanLineLength, const ODCOLORREF* /*pTexPalette*/, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a) { const OdUInt8* texBGRA = pData + scanLineLength * y + x * 4; b = texBGRA[0]; g = texBGRA[1]; r = texBGRA[2]; a = texBGRA[3] == 255 ? 255 : 0; // 1-bit alpha, so it's just visible or not } inline void Get32bppBGR_Transparent8Bit(const OdUInt8* pData, OdUInt32 scanLineLength, const ODCOLORREF* /*pTexPalette*/, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a) { const OdUInt8* texBGRA = pData + scanLineLength * y + x * 4; b = texBGRA[0]; g = texBGRA[1]; r = texBGRA[2]; a = texBGRA[3]; } inline void Get32bppRGB(const OdUInt8* pData, OdUInt32 scanLineLength, const ODCOLORREF* /*pTexPalette*/, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a) { const OdUInt8* texRGBA = pData + scanLineLength * y + x * 4; r = texRGBA[0]; g = texRGBA[1]; b = texRGBA[2]; a = 255; // ignore alpha, i.e. set it visible } inline void Get32bppRGB_Transparent1Bit(const OdUInt8* pData, OdUInt32 scanLineLength, const ODCOLORREF* /*pTexPalette*/, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a) { const OdUInt8* texBGRA = pData + scanLineLength * y + x * 4; r = texBGRA[0]; g = texBGRA[1]; b = texBGRA[2]; a = texBGRA[3] == 255 ? 255 : 0; // 1-bit alpha, so it's just visible or not } inline void Get32bppRGB_Transparent8Bit(const OdUInt8* pData, OdUInt32 scanLineLength, const ODCOLORREF* /*pTexPalette*/, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a) { const OdUInt8* texRGBA = pData + scanLineLength * y + x * 4; r = texRGBA[0]; g = texRGBA[1]; b = texRGBA[2]; a = texRGBA[3]; // 8-bit alpha } } /** * All setter implementations as non-member functions */ namespace TextureSetters { // === 24BPP DIRECT COLOR SETTERS === inline void Set24bppBGR(OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8 r, OdUInt8 g, OdUInt8 b, OdUInt8 /*a*/) { OdUInt8* texBGR = pData + scanLineLength * y + x * 3; texBGR[0] = b; texBGR[1] = g; texBGR[2] = r; } inline void Set24bppRGB(OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8 r, OdUInt8 g, OdUInt8 b, OdUInt8 /*a*/) { OdUInt8* texRGB = pData + scanLineLength * y + x * 3; texRGB[0] = r; texRGB[1] = g; texRGB[2] = b; } // === 32BPP DIRECT COLOR SETTERS === inline void Set32bppBGR(OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8 r, OdUInt8 g, OdUInt8 b, OdUInt8 /*a*/) { ODCOLORREF* texBGRA = reinterpret_cast(pData + scanLineLength * y + x * 4); *texBGRA = ODRGB(r, g, b); } inline void Set32bppBGR_Transparent1Bit(OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8 r, OdUInt8 g, OdUInt8 b, OdUInt8 a) { ODCOLORREF* texBGRA = reinterpret_cast(pData + scanLineLength * y + x * 4); *texBGRA = ODRGBA(r, g, b, a > 0 ? 255 : 0); } inline void Set32bppBGR_Transparent8Bit(OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8 r, OdUInt8 g, OdUInt8 b, OdUInt8 a) { ODCOLORREF* texBGRA = reinterpret_cast(pData + scanLineLength * y + x * 4); *texBGRA = ODRGBA(r, g, b, a); } inline void Set32bppRGB(OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8 r, OdUInt8 g, OdUInt8 b, OdUInt8 /*a*/) { ODCOLORREF* texRGBA = reinterpret_cast(pData + scanLineLength * y + x * 4); *texRGBA = ODRGB(b, g, r); } inline void Set32bppRGB_Transparent1Bit(OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8 r, OdUInt8 g, OdUInt8 b, OdUInt8 a) { ODCOLORREF* texRGBA = reinterpret_cast(pData + scanLineLength * y + x * 4); *texRGBA = ODRGBA(b, g, r, a > 0 ? 255 : 0); } inline void Set32bppRGB_Transparent8Bit(OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8 r, OdUInt8 g, OdUInt8 b, OdUInt8 a) { ODCOLORREF* texRGBA = reinterpret_cast(pData + scanLineLength * y + x * 4); *texRGBA = ODRGBA(b, g, r, a); } } /** * OdSrDataBuffer class encapsulating texture data with pixel access methods */ class OdSrDataBuffer { public: // Constructor OdSrDataBuffer(); inline bool initialized() const { return m_pData && m_scanLineLength > 0; } inline OdInt32 invertY(OdInt32 y) const { return m_height - 1 - y; } // Initialize with data void setData(OdUInt8* pData, OdUInt32 scanLineLength, int width, int height) { m_pData = pData; m_scanLineLength = scanLineLength; m_width = width; m_height = height; } void reset() { m_pData = nullptr; m_scanLineLength = 0; m_width = 0; m_height = 0; m_pTexPalette = nullptr; // Note: we don't reset format parameters (m_bpp, m_colorOrder, etc.) or function pointers // as they might be reused for the next texture setup } // Format setters void setBitsPerPixel(TextureFormat::BitsPerPixel bpp) { if (m_bpp != bpp) { m_bpp = bpp; updateAccessFunctions(); } } void setColorOrder(TextureFormat::ColorOrder order) { if (m_colorOrder != order) { m_colorOrder = order; updateAccessFunctions(); } } void setUsePalette(bool usePalette) { if (m_usePalette != usePalette) { m_usePalette = usePalette; updateAccessFunctions(); } } void setTransparencyMode(TextureFormat::TransparencyMode transparency) { if (m_transparency != transparency) { m_transparency = transparency; updateAccessFunctions(); } } void setPalette(ODCOLORREF* pPalette) { m_pTexPalette = pPalette; } // Set all format parameters at once (more efficient) void setFormat(TextureFormat::BitsPerPixel bpp, TextureFormat::ColorOrder order, ODCOLORREF* pColorPalette, TextureFormat::TransparencyMode transparency) { bool usePalette = pColorPalette != nullptr; bool needUpdate = (m_bpp != bpp) || (m_colorOrder != order) || (m_usePalette != usePalette) || (m_transparency != transparency); m_bpp = bpp; m_colorOrder = order; m_usePalette = usePalette; m_transparency = transparency; m_pTexPalette = pColorPalette; if (needUpdate) { updateAccessFunctions(); } } // High-performance pixel access methods inline void getPixel(int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a) const { if (m_pixelGetter && x >= 0 && x < m_width && y >= 0 && y < m_height) { m_pixelGetter(m_pData, m_scanLineLength, m_pTexPalette, x, y, r, g, b, a); } } inline void setPixel(int x, int y, OdUInt8 r, OdUInt8 g, OdUInt8 b, OdUInt8 a = 255) { if (m_pixelSetter && x >= 0 && x < m_width && y >= 0 && y < m_height) { m_pixelSetter(m_pData, m_scanLineLength, x, y, r, g, b, a); } } // Getters for properties TextureFormat::BitsPerPixel getBitsPerPixel() const { return m_bpp; } TextureFormat::ColorOrder getColorOrder() const { return m_colorOrder; } bool usePalette() const { return m_usePalette; } TextureFormat::TransparencyMode getTransparencyMode() const { return m_transparency; } int getWidth() const { return m_width; } int getHeight() const { return m_height; } //inline void Get1bppPalette(const OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, // OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a); /*inline void Get1bppPaletteTransparent(const OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a); inline void Get4bppPalette(const OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a); inline void Get4bppPaletteTransparent(const OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a); inline void Get8bppPalette(const OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a); inline void Get8bppPaletteTransparent(const OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a); inline void Get24bppBGR(const OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a); inline void Get24bppRGB(const OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a); inline void Get32bppBGR(const OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a); inline void Get32bppBGR_Transparent1Bit(const OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a); inline void Get32bppBGR_Transparent8Bit(const OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a); inline void Get32bppRGB(const OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a); inline void Get32bppRGB_Transparent1Bit(const OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a); inline void Get32bppRGB_Transparent8Bit(const OdUInt8* pData, OdUInt32 scanLineLength, int x, int y, OdUInt8& r, OdUInt8& g, OdUInt8& b, OdUInt8& a);*/ private: // Update pixel access function pointers based on current format void updateAccessFunctions(); public: // Buffer data OdUInt8* m_pData; OdUInt32 m_scanLineLength; int m_width; int m_height; private: // Format parameters TextureFormat::BitsPerPixel m_bpp; TextureFormat::ColorOrder m_colorOrder; bool m_usePalette; TextureFormat::TransparencyMode m_transparency; ODCOLORREF* m_pTexPalette; // Function pointers for pixel access // These are updated only when format parameters change PixelGetter m_pixelGetter; PixelSetter m_pixelSetter; }; #endif // OD_SR_DATA_BUFFER_H