Object Model

Object Model & Memory Layout.

Blend2D object model is a foundation of all Blend2D objects. It was designed only for Blend2D and it's not supposed to be used as a foundation of other libraries. The object model provides runtime reflection, small size optimization (SSO), and good performance. In general, it focuses on optimizing memory footprint by taking advantage of SSO storage, however, this makes the implementation more complex compared to a traditional non-SSO model.

Blend2D object model used by BLObjectCore consists of 16 bytes that have the following layout:

BLObjectImpl* impl;
char char_data[16];
uint8_t u8_data[16];
uint16_t u16_data[8];
uint32_t u32_data[4];
uint64_t u64_data[2];
float f32_data[4];
double f64_data[2];
struct {
uint32_t u32_data_overlap[2];
uint32_t impl_payload;
BLObjectInfo info; // 32 bits describing object type and its additional payload.
};
};

Which allows to have either static or dynamic instances:

  • Static instance stores payload in object detail, impl is not a valid pointer and cannot be accessed.
  • Dynamic instance has a valid impl pointer having a content, which type depends on BLObjectType.

The layout was designed to provide the following properties:

  • Reflection - any Blend2D object can be casted to a generic BLObjectCore or BLVarCore and inspected at runtime.
  • Small string, container, and value optimization saves memory allocations (BLString, BLArray, BLBitSet).
  • No atomic reference counting operations for small containers and default constructed objects without data.
  • It's possible to store a floating point RGBA color (BLRgba) as f32_data, which uses all 16 bytes. The last value of the color, which describes alpha channel, cannot have a sign bit set (cannot be negative and cannot be NaN with sign).

32-bit Floating Point is represented the following way (32 bits):

[--------+--------+--------+--------]
[31....24|23....16|15.....8|7......0] (32-bit integer layout)
[--------+--------+--------+--------]
[Seeeeeee|eQ......|........|........] (32-bit floating point)
[--------+--------+--------+--------]

Where:

  • 'S' - Sign bit
  • 'e' - Exponent bits (all bits must be '1' to form NaN).
  • 'Q' - Mantissa bit that can be used to describe quiet and signaling NaNs, the value is not standardized (X86 and ARM use '1' for quiet NaN and '0' for signaling NaN).
  • '.' - Mantissa bits.

Blend2D uses a sign bit to determine whether the data is BLRgba or object compatible. This design has been chosen, because we don't allow alpha values to be negative. When the sign bit is set it means that it's a type inherited from BLObjectCore. When the sign bit is not set the whole payload represents 128-bit BLRgba color, where alpha is not a negative number. It's designed in a way that 31 bits out of 32 can be used as payload that represents object type, object info flags, and additional type-dependent payload.

Object info value looks like this (also compared with floating point):

[--------+--------+--------+--------]
[31....24|23....16|15.....8|7......0] Info Layout:
[--------+--------+--------+--------]
[Seeeeeee|eQ......|........|........] - 32-bit floating-point data view (\ref BLRgba case, 'S' bit (sign bit) set to zero).
[MDRttttt|ttaaaaaa|bbbbcccc|pppppppp] - object info fields view 1 (\ref BLObjectCore case, 'M' bit set to one).
[MDRttttt|ttaaaaaa|qqqqqqqq|pppppppp] - object info fields view 2 (\ref BLObjectCore case, 'M' bit set to one).
[--------+--------+--------+--------]
[--------+--------+--------+--------]
[31....24|23....16|15.....8|7......0] SSO Layout:
[--------+--------+--------+--------]
[1DRttttt|ttaaaaaa|bbbbcccc|pppppppp] - BLArray - 'aaaaaa' is size, 'bbbb' is capacity).
[1DRttttt|00aaaaaa|bbbbcccc|pppppppp] - BLString - 'aaaaaa' is size ^ kSSOCapacity, the rest can be used as characters).
[1DRttttt|ttaaaaaa|bbbbcccc|pppppppp] - BLBitSet - 'R' is used to distinguish between SSO Range and SSO Dense representation.
[1DRttttt|ttaaaaaa|bbbbcccc|pppppppp] - BLFontFeatureSettings - 'aaaaaa' is size, 'bbbbcccc|pppppppp' is used to store feature data.
[1DRttttt|ttaaaaaa|bbbbcccc|pppppppp] - BLFontVariationSettings - 'aaaaaa' is size, 'bbbbcccc|pppppppp' is used to store variation ids.
[--------+--------+--------+--------]

Where:

  • 'M' - Object marker, forms a valid BLObject signature when set to '1'.
  • 'D' - Dynamic flag - when set the Impl pointer is valid. When 'D' == '0' it means the object is in SSO mode, when 'D' == '1' it means it's in Dynamic mode.
  • 'R' - Ref counted flag - when set together with 'M' and 'D' it makes it guaranteed that teh Impl pointer is ref-counted. Otherwise if 'D' is not set, 'R' flag can be used by the SSO representation to store another bit.
  • 't' - Object type bits - 'ttttttt' forms a 7-bit type having possible values from 0 to 127, see BLObjectType.
  • 'a' - Object 'a' payload (6 bits).
  • 'b' - Object 'b' payload (4 bits).
  • 'c' - Object 'c' payload (4 bits).
  • 'p' - Object 'p' payload (8 bits).
  • 'q' - Object 'q' payload (8 bits aliased with 'bbbbcccc' fields).

Common meaning of payload fields:

  • 'a' - If the object is a container (BLArray, BLString) 'a' field always represents its size in SSO mode. If the object is a BLBitSet, 'a' field is combined with other fields to store a start word index or to mark a BitSet, which contains an SSO range instead of dense words.
  • 'b' - If the object is a container (BLArray) 'b' field always represents its capacity in SSO mode except BLString, which doesn't store capacity in 'b' field and uses it as an additional SSO content byte on little endian targets (SSO capacity is then either 14 on little endian targets or 11 on big endian targets). This is possible as BL_OBJECT_TYPE_STRING must be identifier that has 2 low bits zero, which then makes it possible to use 'ttIRaaaa' as null terminator when the string length is 14 characters.
  • 'c' - Used freely.
  • 'p' - Used freely.
  • 'q' - Used freely.

If the 'D' flag is '1' the following payload fields are used by the allocator (and thus cannot be used by the object):

  • 'a' - Allocation adjustment (4 bits) - At the moment the field describes how many bytes (shifted) to subtract from Impl to get the real pointer returned by Impl allocator. Object deallocation relies on this offset.

Not all object support all defined flags, here is a little overview:

+--------------------------+---+---+---+---+---+---+---+
| Type | M |SSO|Dyn|Ext|Imm|Vrt|Ref|
+--------------------------+---+---+---+---+---+---+---|
| BLVar {Null} | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 'M' - Object marker (always used except wrapping BLRgba).
| BLVar {Bool} | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 'SSO' - Small size optimization support (no Impl).
| BLVar {Int64} | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 'Dyn' - Dynamic Impl support.
| BLVar {UInt64} | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 'Ext' - External data support.
| BLVar {Double} | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 'Imm' - Immutable data support.
| BLVar {BLRgba} | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 'Vrt' - Object provides virtual function table.
| BLVar {BLRgba32} | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 'Ref' - Reference counting support.
| BLVar {BLRgba64} | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
| BLArray<T> | 1 | x | x | x | x | 0 | x | '0' - Never used
| BLBitArray | 1 | x | x | 0 | 0 | 0 | x | '1' - Always used
| BLBitSet | 1 | x | x | 0 | 0 | 0 | x | 'x' - Variable (either used or not)
| BLContext | 1 | 0 | 1 | 0 | 0 | 1 | x |
| BLString | 1 | x | x | 0 | 0 | 0 | x |
| BLPattern | 1 | 0 | 1 | 0 | 0 | 0 | x |
| BLGradient | 1 | 0 | 1 | 0 | 0 | 0 | x |
| BLPath | 1 | 0 | 1 | 0 | x | 0 | x |
| BLImage | 1 | 0 | 1 | x | x | 0 | x |
| BLImageCodec | 1 | 0 | 1 | 0 | x | 1 | x |
| BLImageDecoder | 1 | 0 | 1 | 0 | 0 | 1 | x |
| BLImageEncoder | 1 | 0 | 1 | 0 | 0 | 1 | x |
| BLFont | 1 | 0 | 1 | 0 | 0 | 0 | x |
| BLFontFace | 1 | 0 | 1 | 0 | x | 1 | x |
| BLFontData | 1 | 0 | 1 | x | x | 1 | x |
| BLFontManager | 1 | 0 | 1 | 0 | x | 1 | x |
| BLFontFeatureSettings | 1 | 1 | 1 | 0 | 0 | 0 | x |
| BLFontVariationSettings | 1 | 1 | 1 | 0 | 0 | 0 | x |
+--------------------------+---+---+---+---+---+---+---+

Classes

Macros

BLObject - Constants

BLObject - External Data

BLObject - C API

Macro Definition Documentation

#define BL_DEFINE_OBJECT_DCAST(DERIVED_TYPE)◆ 

Value:
\
template<typename T = DERIVED_TYPE> \
BL_NODISCARD \
BL_INLINE_NODEBUG T& dcast() noexcept { return static_cast<T&>(*this); } \
\
template<typename T = DERIVED_TYPE> \
BL_NODISCARD \
BL_INLINE_NODEBUG const T& dcast() const noexcept { return static_cast<const T&>(*this); } \

#define BL_DEFINE_OBJECT_PROPERTY_API◆ 

Value:
\
BL_INLINE_NODEBUG BLResult getProperty(const char* name, BLVarCore& valueOut) const noexcept { \
return blObjectGetProperty(this, name, SIZE_MAX, &valueOut); \
} \
\ \
BL_INLINE_NODEBUG BLResult getProperty(BLStringView name, BLVarCore& valueOut) const noexcept {\
return blObjectGetProperty(this, name.data, name.size, &valueOut); \
} \
\ \
BL_INLINE_NODEBUG BLResult setProperty(const char* name, const BLObjectCore& value) noexcept { \
return blObjectSetProperty(this, name, SIZE_MAX, &value); \
} \
\ \
BL_INLINE_NODEBUG BLResult setProperty(BLStringView name, const BLObjectCore& value) noexcept {\
return blObjectSetProperty(this, name.data, name.size, &value); \
}

Typedef Documentation

typedef void(* BLDestroyExternalDataFunc)(void* impl, void* externalData, void* userData)◆ 

A function callback that is called when an Impl that holds external data is going to be destroyed. It's often used as a notification that a data passed to a certain Impl is no longer in use by Blend2D.

Enumeration Type Documentation

BLObjectInfoBits : uint32_tenum◆ 

Defines a mask of each field of the object info.

Note
This is part of the official documentation, however, users should not use these enumerations in any context.
ConstantDescription
BL_OBJECT_INFO_P_MASK 

Mask describing 'P' payload (8 bits).

BL_OBJECT_INFO_Q_MASK 

Mask describing 'Q' payload (8 bits aliased with 'bbbbcccc' bits).

BL_OBJECT_INFO_C_MASK 

Mask describing 'C' payload (4 bits).

BL_OBJECT_INFO_B_MASK 

Mask describing 'B' payload (4 bits).

BL_OBJECT_INFO_A_MASK 

Mask describing 'A' payload (6 bits).

BL_OBJECT_INFO_FIELDS_MASK 

Mask of all payload fields combined, except 'M', 'T', type identification, and 'R' (RefCounted marker).

BL_OBJECT_INFO_TYPE_MASK 

Mask describing object type (8 bits), see BLObjectType.

BL_OBJECT_INFO_R_FLAG 

Flag describing a ref-counted object (if set together with 'D' flag)

Note
This flag is free for use by SSO, it has no meaning when 'D' flag is not set).
BL_OBJECT_INFO_D_FLAG 

Flag describing a dynamic object - if this flag is not set, it means the object is in SSO mode.

BL_OBJECT_INFO_M_FLAG 

Flag describing a valid object compatible with BLObjectCore interface (otherwise it's most likely BLRgba).

BL_OBJECT_INFO_MD_FLAGS 

A combination of BL_OBJECT_INFO_M_FLAG and BL_OBJECT_INFO_D_FLAG flags.

BL_OBJECT_INFO_MDR_FLAGS 

A combination of BL_OBJECT_INFO_M_FLAG, BL_OBJECT_INFO_D_FLAG, BL_OBJECT_INFO_R_FLAG flags.

BLObjectType : uint32_tenum◆ 

Object type identifier.

ConstantDescription
BL_OBJECT_TYPE_RGBA 

Object represents a RGBA value stored as four 32-bit floating point components (can be used as Style).

BL_OBJECT_TYPE_RGBA32 

Object represents a RGBA32 value stored as 32-bit integer in 0xAARRGGBB form.

BL_OBJECT_TYPE_RGBA64 

Object represents a RGBA64 value stored as 64-bit integer in 0xAAAARRRRGGGGBBBB form.

BL_OBJECT_TYPE_NULL 

Object is Null (can be used as style).

BL_OBJECT_TYPE_PATTERN 

Object is BLPattern (can be used as style).

BL_OBJECT_TYPE_GRADIENT 

Object is BLGradient (can be used as style).

BL_OBJECT_TYPE_IMAGE 

Object is BLImage.

BL_OBJECT_TYPE_PATH 

Object is BLPath.

BL_OBJECT_TYPE_FONT 

Object is BLFont.

BL_OBJECT_TYPE_FONT_FEATURE_SETTINGS 

Object is BLFontFeatureSettings.

BL_OBJECT_TYPE_FONT_VARIATION_SETTINGS 

Object is BLFontVariationSettings.

BL_OBJECT_TYPE_BIT_ARRAY 

Object is BLBitArray.

BL_OBJECT_TYPE_BIT_SET 

Object is BLBitSet.

BL_OBJECT_TYPE_BOOL 

Object represents a boolean value.

BL_OBJECT_TYPE_INT64 

Object represents a 64-bit signed integer value.

BL_OBJECT_TYPE_UINT64 

Object represents a 64-bit unsigned integer value.

BL_OBJECT_TYPE_DOUBLE 

Object represents a 64-bit floating point value.

BL_OBJECT_TYPE_STRING 

Object is BLString.

BL_OBJECT_TYPE_ARRAY_OBJECT 

Object is BLArray<T> where T is a BLObject compatible type.

BL_OBJECT_TYPE_ARRAY_INT8 

Object is BLArray<T> where T matches 8-bit signed integral type.

BL_OBJECT_TYPE_ARRAY_UINT8 

Object is BLArray<T> where T matches 8-bit unsigned integral type.

BL_OBJECT_TYPE_ARRAY_INT16 

Object is BLArray<T> where T matches 16-bit signed integral type.

BL_OBJECT_TYPE_ARRAY_UINT16 

Object is BLArray<T> where T matches 16-bit unsigned integral type.

BL_OBJECT_TYPE_ARRAY_INT32 

Object is BLArray<T> where T matches 32-bit signed integral type.

BL_OBJECT_TYPE_ARRAY_UINT32 

Object is BLArray<T> where T matches 32-bit unsigned integral type.

BL_OBJECT_TYPE_ARRAY_INT64 

Object is BLArray<T> where T matches 64-bit signed integral type.

BL_OBJECT_TYPE_ARRAY_UINT64 

Object is BLArray<T> where T matches 64-bit unsigned integral type.

BL_OBJECT_TYPE_ARRAY_FLOAT32 

Object is BLArray<T> where T matches 32-bit floating point type.

BL_OBJECT_TYPE_ARRAY_FLOAT64 

Object is BLArray<T> where T matches 64-bit floating point type.

BL_OBJECT_TYPE_ARRAY_STRUCT_1 

Object is BLArray<T> where T is a struct of size 1.

BL_OBJECT_TYPE_ARRAY_STRUCT_2 

Object is BLArray<T> where T is a struct of size 2.

BL_OBJECT_TYPE_ARRAY_STRUCT_3 

Object is BLArray<T> where T is a struct of size 3.

BL_OBJECT_TYPE_ARRAY_STRUCT_4 

Object is BLArray<T> where T is a struct of size 4.

BL_OBJECT_TYPE_ARRAY_STRUCT_6 

Object is BLArray<T> where T is a struct of size 6.

BL_OBJECT_TYPE_ARRAY_STRUCT_8 

Object is BLArray<T> where T is a struct of size 8.

BL_OBJECT_TYPE_ARRAY_STRUCT_10 

Object is BLArray<T> where T is a struct of size 10.

BL_OBJECT_TYPE_ARRAY_STRUCT_12 

Object is BLArray<T> where T is a struct of size 12.

BL_OBJECT_TYPE_ARRAY_STRUCT_16 

Object is BLArray<T> where T is a struct of size 16.

BL_OBJECT_TYPE_ARRAY_STRUCT_20 

Object is BLArray<T> where T is a struct of size 20.

BL_OBJECT_TYPE_ARRAY_STRUCT_24 

Object is BLArray<T> where T is a struct of size 24.

BL_OBJECT_TYPE_ARRAY_STRUCT_32 

Object is BLArray<T> where T is a struct of size 32.

BL_OBJECT_TYPE_CONTEXT 

Object is BLContext.

BL_OBJECT_TYPE_IMAGE_CODEC 

Object is BLImageCodec.

BL_OBJECT_TYPE_IMAGE_DECODER 

Object is BLImageDecoder.

BL_OBJECT_TYPE_IMAGE_ENCODER 

Object is BLImageEncoder.

BL_OBJECT_TYPE_FONT_FACE 

Object is BLFontFace.

BL_OBJECT_TYPE_FONT_DATA 

Object is BLFontData.

BL_OBJECT_TYPE_FONT_MANAGER 

Object is BLFontManager.

BL_OBJECT_TYPE_MIN_ARRAY 

Minimum object type of an array object.

BL_OBJECT_TYPE_MAX_ARRAY 

Maximum object type of an array object.

BL_OBJECT_TYPE_MIN_STYLE 

Minimum object type identifier that can be used as a style.

BL_OBJECT_TYPE_MAX_STYLE 

Maximum object type identifier that can be used as a style.

BL_OBJECT_TYPE_MIN_VIRTUAL 

Minimum object type of an object with virtual function table.

BL_OBJECT_TYPE_MAX_VIRTUAL 

Maximum object type of an object with virtual function table.

BL_OBJECT_TYPE_MAX_VALUE 

Maximum possible value of an object type, including identifiers reserved for the future.