// This file is part of Blend2D project // // See blend2d.h or LICENSE.md for license and copyright information // SPDX-License-Identifier: Zlib #ifndef BLEND2D_FORMAT_H_INCLUDED #define BLEND2D_FORMAT_H_INCLUDED #include "api.h" //! \addtogroup blend2d_api_imaging //! \{ //! \name BLFormat - Constants //! \{ //! Pixel format. //! //! Compatibility Table //! ------------------- //! //! ``` //! +---------------------+---------------------+-----------------------------+ //! | Blend2D Format | Cairo Format | QImage::Format | //! +---------------------+---------------------+-----------------------------+ //! | BL_FORMAT_PRGB32 | CAIRO_FORMAT_ARGB32 | Format_ARGB32_Premultiplied | //! | BL_FORMAT_XRGB32 | CAIRO_FORMAT_RGB24 | Format_RGB32 | //! | BL_FORMAT_A8 | CAIRO_FORMAT_A8 | n/a | //! +---------------------+---------------------+-----------------------------+ //! ``` BL_DEFINE_ENUM(BLFormat) { //! None or invalid pixel format. BL_FORMAT_NONE = 0, //! 32-bit premultiplied ARGB pixel format (8-bit components). BL_FORMAT_PRGB32 = 1, //! 32-bit (X)RGB pixel format (8-bit components, alpha ignored). BL_FORMAT_XRGB32 = 2, //! 8-bit alpha-only pixel format. BL_FORMAT_A8 = 3, // Maximum value of `BLFormat`. BL_FORMAT_MAX_VALUE = 3 BL_FORCE_ENUM_UINT32(BL_FORMAT) }; //! Pixel format flags. BL_DEFINE_ENUM(BLFormatFlags) { //! No flags. BL_FORMAT_NO_FLAGS = 0u, //! Pixel format provides RGB components. BL_FORMAT_FLAG_RGB = 0x00000001u, //! Pixel format provides only alpha component. BL_FORMAT_FLAG_ALPHA = 0x00000002u, //! A combination of `BL_FORMAT_FLAG_RGB | BL_FORMAT_FLAG_ALPHA`. BL_FORMAT_FLAG_RGBA = 0x00000003u, //! Pixel format provides LUM component (and not RGB components). BL_FORMAT_FLAG_LUM = 0x00000004u, //! A combination of `BL_FORMAT_FLAG_LUM | BL_FORMAT_FLAG_ALPHA`. BL_FORMAT_FLAG_LUMA = 0x00000006u, //! Indexed pixel format the requires a palette (I/O only). BL_FORMAT_FLAG_INDEXED = 0x00000010u, //! RGB components are premultiplied by alpha component. BL_FORMAT_FLAG_PREMULTIPLIED = 0x00000100u, //! Pixel format doesn't use native byte-order (I/O only). BL_FORMAT_FLAG_BYTE_SWAP = 0x00000200u, // The following flags are only informative. They are part of `blFormatInfo[]`, but don't have to be passed to // `BLPixelConverter` as they will always be calculated automatically. //! Pixel components are byte aligned (all 8bpp). BL_FORMAT_FLAG_BYTE_ALIGNED = 0x00010000u, //! Pixel has some undefined bits that represent no information. //! //! For example a 32-bit XRGB pixel has 8 undefined bits that are usually set to all ones so the format can be //! interpreted as premultiplied RGB as well. There are other formats like 16_0555 where the bit has no information //! and is usually set to zero. Blend2D doesn't rely on the content of such bits. BL_FORMAT_FLAG_UNDEFINED_BITS = 0x00020000u, //! Convenience flag that contains either zero or `BL_FORMAT_FLAG_BYTE_SWAP` depending on host byte order. Little //! endian hosts have this flag set to zero and big endian hosts to `BL_FORMAT_FLAG_BYTE_SWAP`. //! //! \note This is not a real flag that you can test, it's only provided for convenience to define little endian //! pixel formats. BL_FORMAT_FLAG_LE = (BL_BYTE_ORDER == 1234) ? (uint32_t)0 : (uint32_t)BL_FORMAT_FLAG_BYTE_SWAP, //! Convenience flag that contains either zero or `BL_FORMAT_FLAG_BYTE_SWAP` depending on host byte order. Big //! endian hosts have this flag set to zero and little endian hosts to `BL_FORMAT_FLAG_BYTE_SWAP`. //! //! \note This is not a real flag that you can test, it's only provided for convenience to define big endian //! pixel formats. BL_FORMAT_FLAG_BE = (BL_BYTE_ORDER == 4321) ? (uint32_t)0 : (uint32_t)BL_FORMAT_FLAG_BYTE_SWAP BL_FORCE_ENUM_UINT32(BL_FORMAT_FLAG) }; //! \} //! \name BLFormat - C API //! \{ BL_BEGIN_C_DECLS BL_API BLResult BL_CDECL blFormatInfoQuery(BLFormatInfo* self, BLFormat format) BL_NOEXCEPT_C; BL_API BLResult BL_CDECL blFormatInfoSanitize(BLFormatInfo* self) BL_NOEXCEPT_C; BL_END_C_DECLS //! \} //! \name BLFormat - Structs //! \{ //! Provides a detailed information about a pixel format. Use `blFormatInfo` array to get an information of Blend2D //! native pixel formats. struct BLFormatInfo { uint32_t depth; BLFormatFlags flags; union { struct { uint8_t sizes[4]; uint8_t shifts[4]; }; struct { uint8_t rSize; uint8_t gSize; uint8_t bSize; uint8_t aSize; uint8_t rShift; uint8_t gShift; uint8_t bShift; uint8_t aShift; }; BLRgba32* palette; }; #ifdef __cplusplus BL_NODISCARD BL_INLINE_NODEBUG bool operator==(const BLFormatInfo& other) const noexcept { return memcmp(this, &other, sizeof(*this)) == 0; } BL_NODISCARD BL_INLINE_NODEBUG bool operator!=(const BLFormatInfo& other) const noexcept { return memcmp(this, &other, sizeof(*this)) != 0; } BL_INLINE_NODEBUG void reset() noexcept { *this = BLFormatInfo{}; } BL_INLINE void init(uint32_t depth_, BLFormatFlags flags_, const uint8_t sizes_[4], const uint8_t shifts_[4]) noexcept { depth = depth_; flags = flags_; setSizes(sizes_[0], sizes_[1], sizes_[2], sizes_[3]); setShifts(shifts_[0], shifts_[1], shifts_[2], shifts_[3]); } BL_INLINE void setSizes(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 0) noexcept { rSize = r; gSize = g; bSize = b; aSize = a; } BL_INLINE void setShifts(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 0) noexcept { rShift = r; gShift = g; bShift = b; aShift = a; } BL_INLINE_NODEBUG bool hasFlag(BLFormatFlags f) const noexcept { return (flags & f) != 0; } BL_INLINE_NODEBUG void addFlags(BLFormatFlags f) noexcept { flags = BLFormatFlags(flags | f); } BL_INLINE_NODEBUG void clearFlags(BLFormatFlags f) noexcept { flags = BLFormatFlags(flags & ~f); } //! Query Blend2D `format` and copy it to this format info, see `BLFormat`. //! //! Copies data from `blFormatInfo()` to this `BLFormatInfo` struct and returns `BL_SUCCESS` if the `format` was //! valid, otherwise the `BLFormatInfo` is reset and `BL_ERROR_INVALID_VALUE` is returned. //! //! \note The `BL_FORMAT_NONE` is considered invalid format, thus if it's passed to `query()` the return value //! would be `BL_ERROR_INVALID_VALUE`. BL_INLINE_NODEBUG BLResult query(BLFormat format) noexcept { return blFormatInfoQuery(this, format); } //! Sanitize this `BLFormatInfo`. //! //! Sanitizer verifies whether the format is valid and updates the format information about flags to values that //! Blend2D expects. For example format flags are properly examined and simplified if possible, byte-swap is //! implicitly performed for formats where a single component matches one byte, etc... BL_INLINE_NODEBUG BLResult sanitize() noexcept { return blFormatInfoSanitize(this); } #endif }; //! \} //! \name BLFormat - Globals //! \{ BL_BEGIN_C_DECLS //! Pixel format information of Blend2D native pixel formats, see `BLFormat`. extern BL_API const BLFormatInfo blFormatInfo[]; BL_END_C_DECLS //! \} //! \} #endif // BLEND2D_FORMAT_H_INCLUDED