// This file is part of Blend2D project // // See blend2d.h or LICENSE.md for license and copyright information // SPDX-License-Identifier: Zlib #ifndef BLEND2D_API_H_INCLUDED #define BLEND2D_API_H_INCLUDED // This header can only be included by either or by internal Blend2D headers. Prevent users including // headers by accident and prevent not including "blend2d/api-build_p.h" during the Blend2D compilation. #if !defined(BLEND2D_H_INCLUDED) && !defined(BLEND2D_API_BUILD_P_H_INCLUDED) && !defined(__INTELLISENSE__) #pragma message("Include either or to use Blend2D library") #endif #include #include #include #include #ifdef __cplusplus #include #else #include #endif //! \mainpage API Reference //! //! Blend2D C/C++ API reference documentation generated by Doxygen. //! //! \section main_introduction Introduction //! //! Blend2D API consists of enumerations, functions, structs, and C++ classes. Common concepts like enumerations and //! POD structs are shared between C and C++. Some structs contain extra functionality like `BLSomething::reset()` //! that is only available to C++ users, however, such functionality is only provided for convenience and doesn't //! affect how Blend2D can be used from C. //! //! Blend2D C++ API is in fact build on top of the C API and all C++ functions are inlines that call C API without any //! overhead. It would require double effort to document both C and C++ APIs separately so we have decided to only //! document C++ API and to only list \ref blend2d_api_c_functions "C API" for users that need it. The C API should be //! straightforward and matches very well the C++ part. //! //! \section main_important Important //! //! Doxygen sorts struct members in anonymous structs and unions and we haven't figured out how to turn this off. This //! means that the order of members in "Public Attributes" doesn't have to reflect the original struct packing. Always //! double-check struct members in case you plan to use a brace initialization of simple structs. //! //! \section main_groups Groups //! //! The documentation is split into the following groups: //! //! $$DOCS_GROUP_OVERVIEW$$ //! \defgroup blend2d_api_globals Global API //! \brief Global functions, constants, and classes used universally across //! the library. //! \defgroup blend2d_api_geometry Geometry API //! \brief Geometries, paths, and transformations. //! //! Blend2D offers various geometry structures and objects that can be used with //! either `BLPath` for path building or `BLContext` for rendering. //! \defgroup blend2d_api_imaging Imaging API //! \brief Images and image codecs. //! \defgroup blend2d_api_styling Styling API //! \brief Colors, gradients, and patterns. //! \defgroup blend2d_api_text Text API //! \brief Fonts & Text support. //! \defgroup blend2d_api_rendering Rendering Context //! \brief 2D rendering context API, structures, and constants. //! \defgroup blend2d_api_runtime Runtime API //! \brief Interaction with Blend2D runtime. //! \defgroup blend2d_api_filesystem Filesystem API //! \brief Filesystem utilities. //! \defgroup blend2d_api_impl Impl API //! \brief API required for extending Blend2D functionality. //! //! Everything that is part of this group requires `` to be //! included before the use as this API is only for users that extend Blend2D. //! \defgroup blend2d_api_macros Macros //! \brief Preprocessor macros and compile-time constants. //! \defgroup blend2d_api_c_functions C API //! \brief Global C API functions exported as `extern "C"` (C API). //! //! We do not document these functions as they are called from C++ wrappers, which are documented and should be used //! as a reference. The most important thing in using C API is to understand how lifetime of objects is managed. //! //! Each type that requires initialization provides `Init`, 'Destroy', and `Reset` functions. Init/Destroy are called //! by C++ constructors and destructors on C++ side and must be used the same way by C users. Although these functions //! return `BLResult` it's guaranteed the result is always `BL_SUCCESS` - the return value is only provided for //! consistency and possible tail calling. //! //! The following example should illustrate how `Init` and `Destroy` works: //! //! ``` //! BLImageCore img; //! //! // Initializes the BLImage object, always succeeds. //! blImageInit(&img); //! //! // Creates image data, note how it's called on an already initialized object. //! blImageCreate(&img, 128, 128, BL_FORMAT_PRGB32); //! //! // Destroys the BLImage object, always succeeds. //! blImageDestroy(&img); //! ``` //! //! Some init functions may provide shortcuts for the most used scenarios that //! merge initialization and resource allocation into a single function: //! //! ``` //! BLImageCore img; //! //! // Combines blImageInit() with blImageCreate(). //! blImageInitAs(&img, 128, 128, BL_FORMAT_PRGB32); //! //! // Destroys the data, doesn't have to be called if blImageInitAs() failed. //! blImageDestroy(&img); //! ``` //! //! It's worth knowing that default initialization in Blend2D costs nothing and no resources are allocated, thus //! initialization never fails and in theory default initialized objects don't have to be destroyed as they don't //! hold any data that would have to be deallocated (however never do that in practice). //! //! There is a distinction between 'destroy()' and 'reset()' functionality. Destroy would destroy the object and //! put it into a non-reusable state. Thus if the object is used by accident it should crash on null-pointer access. //! On the contrary, resetting the object with 'reset()' explicitly states that the instance will be reused so //! 'reset()' basically destroys the object and puts it into its default constructed state for further use. This //! means that it's not needed to explicitly call 'destroy()' on instance that was reset, and it also is not needed //! for a default constructed instance. However, we recommend to not count on this behavior and to always properly //! initialize and destroy Blend2D objects. //! //! The following example should explain how init/reset can avoid destroy: //! //! ``` //! BLImageCore img; //! //! // Now image is default constructed/initialized. if you did just this and abandon it then no resources will //! // be leaked as default construction is not allocating any resources nor increasing any reference counters. //! blImageInit(&img); //! //! // Now image will have to dynamically allocate some memory to store pixel data. If this succeeds the image //! // will have to be explicitly destroyed when it's no longer needed to release the associated data it holds. //! BLResult result = blImageCreate(&img, 128, 128, BL_FORMAT_PRGB32); //! //! // If `blImageCreate()` failed it leaves the object in the state it was prior to the call. Most of API calls //! // in Blend2D behave like this (it's transactional). This means that if the call failed the `img` would still //! // be default constructed and the function can simply return without leaking any resources. In C++ API the //! // compiler would emit a call to `blImageDestroy()` implicitly, but that's just how RAII works. //! if (result != BL_SUCCESS) //! return result; //! //! // Resetting image would destroy its data and make it default constructed. //! blImageReset(&img); //! //! // The instance is valid after `reset()` - it's now a default constructed instance as created by `blImageInit()`. //! printf("%p", img.impl); //! //! // Calling `blImageDestroy()` would make the instance invalid. //! blImageDestroy(&img); //! //! // Calling any method except initialization such as `blImageInit()` on invalid instance is UNDEFINED BEHAVIOR! //! blImageCreate(&img, 128, 128, BL_FORMAT_PRGB32); // Can crash, can corrupt memory, can succeed, never do that! //! ``` //! \cond INTERNAL //! \defgroup blend2d_internal Internal //! //! \brief Internal API. //! \defgroup blend2d_codec_impl Codecs //! //! \brief Codecs implementation. //! \defgroup blend2d_raster_engine_impl Raster //! //! \brief Raster rendering context. //! \defgroup blend2d_pipeline_jit JIT pipeline compiler //! //! \brief JIT pipeline compiler. //! \defgroup blend2d_pipeline_reference Reference pipeline implementation //! //! \brief Reference pipeline implementation. //! \defgroup blend2d_opentype_impl OpenType //! //! \brief OpenType implementation. //! \endcond // Blend2D Version // =============== //! \addtogroup blend2d_api_macros //! \{ //! \name Version Information //! \{ //! Makes a version number representing a `MAJOR.MINOR.PATCH` combination. #define BL_MAKE_VERSION(MAJOR, MINOR, PATCH) (((MAJOR) << 16) | ((MINOR) << 8) | (PATCH)) //! Blend2D library version. #define BL_VERSION BL_MAKE_VERSION(0, 11, 4) //! \} //! \} // Build Type // ========== //! \cond INTERNAL // These definitions can be used to enable static library build. Embed is used when Blend2D's source code is embedded // directly in another project, implies static build as well. // // #define BL_STATIC // Blend2D is a statically linked library. // These definitions control the build mode and tracing support. The build mode should be auto-detected at compile // time, but it's possible to override it in case that the auto-detection fails. // // Tracing is a feature that is never compiled by default and it's only used to debug Blend2D itself. // // #define BL_BUILD_DEBUG // Define to enable debug-mode. // #define BL_BUILD_RELEASE // Define to enable release-mode. // Detect BL_BUILD_DEBUG and BL_BUILD_RELEASE if not defined. #if !defined(BL_BUILD_DEBUG) && !defined(BL_BUILD_RELEASE) #ifndef NDEBUG #define BL_BUILD_DEBUG #else #define BL_BUILD_RELEASE #endif #endif //! \endcond // Public Macros // ============= //! \addtogroup blend2d_api_macros //! \{ //! \name Target Information //! \{ //! \def BL_BYTE_ORDER //! //! A compile-time constant (macro) that defines byte-order of the target. It can be either `1234` for little-endian //! targets or `4321` for big-endian targets. Blend2D uses this macro internally, but it's also available to end //! users as sometimes it could be important for deciding between pixel formats or other important details. #if (defined(__ARMEB__)) || (defined(__MIPSEB__)) || \ (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) #define BL_BYTE_ORDER 4321 #else #define BL_BYTE_ORDER 1234 #endif //! \} //! \name Decorators //! \{ //! \def BL_API //! //! A base API decorator that marks functions and variables exported by Blend2D. #if !defined(BL_STATIC) #if defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__)) #if defined(BL_BUILD_EXPORT) #define BL_API __declspec(dllexport) #else #define BL_API __declspec(dllimport) #endif #elif defined(_WIN32) && defined(__GNUC__) #if defined(BL_BUILD_EXPORT) #define BL_API __attribute__((dllexport)) #else #define BL_API __attribute__((dllimport)) #endif #elif defined(__GNUC__) #define BL_API __attribute__((__visibility__("default"))) #endif #endif #ifndef BL_API #define BL_API #endif //! \def BL_CDECL //! //! Calling convention used by all exported functions and function callbacks. If you pass callbacks to Blend2D it's //! strongly advised to decorate the callback explicitly as some compilers provide a way of overriding a global //! calling convention (like __vectorcall on Windows platform), which would break the use of such callbacks. #if defined(__GNUC__) && defined(__i386__) && !defined(__x86_64__) #define BL_CDECL __attribute__((__cdecl__)) #elif defined(_MSC_VER) #define BL_CDECL __cdecl #else #define BL_CDECL #endif //! \def BL_INLINE //! //! Marks functions that should always be inlined. #if defined(__GNUC__) #define BL_INLINE inline __attribute__((__always_inline__)) #elif defined(_MSC_VER) #define BL_INLINE __forceinline #else #define BL_INLINE inline #endif //! \def BL_INLINE_NODEBUG //! //! The same as `BL_INLINE` possibly combined with `__attribute__((artificial))` or `__attribute__((nodebug))` if //! the compiler supports any of them. //! //! The purpose of this macro is to tell the compiler that the function should not need debugging, thus the debug //! information can be omitted completely. Blend2D uses tris decorator to decorate C++ inline functions that either //! call C API or that are trivial to improve debugging experience of some tiny abstractions. #if defined(__clang__) #define BL_INLINE_NODEBUG inline __attribute__((__always_inline__, __nodebug__)) #elif defined(__GNUC__) #define BL_INLINE_NODEBUG inline __attribute__((__always_inline__, __artificial__)) #else #define BL_INLINE_NODEBUG BL_INLINE #endif //! \def BL_NORETURN //! //! Function attribute used by functions that never return (that terminate the process). This attribute is used only //! once by `blRuntimeAssertionFailure()` function, which is only used when assertions are enabled. This macro should //! be considered internal and it's not designed for Blend2D users. #if defined(__GNUC__) #define BL_NORETURN __attribute__((__noreturn__)) #elif defined(_MSC_VER) #define BL_NORETURN __declspec(noreturn) #else #define BL_NORETURN #endif //! \def BL_NODISCARD //! //! Tells the compiler to issue a warning in case that the return value of a function was not used. #if defined(__cplusplus) && __cplusplus >= 201703L #define BL_NODISCARD [[nodiscard]] #elif defined(__clang__) // GCC's behavior doesn't respect casting to void so we only support clang. #define BL_NODISCARD __attribute__((__warn_unused_result__)) #else #define BL_NODISCARD #endif //! \def BL_NOEXCEPT //! //! Defined to `noexcept` in C++17 mode an nothing in C mode. The reason this macro is provided is because Blend2D //! C API doesn't use exceptions and is marked as such. #if defined(__cplusplus) && __cplusplus >= 201703L // Function typedefs are `noexcept`, however, it's not available until C++17. #define BL_NOEXCEPT noexcept #else #define BL_NOEXCEPT #endif //! \def BL_CONSTEXPR //! //! Evaluates to constexpr in C++17 mode. #if __cplusplus >= 201703L #define BL_CONSTEXPR constexpr #else #define BL_CONSTEXPR #endif //! \def BL_NOEXCEPT_C //! //! Defined to `noexcept` in C++11 mode an nothing in C mode. This is used to mark Blend2D C API, which is `noexcept` //! by design. #if defined(__cplusplus) #define BL_NOEXCEPT_C noexcept #else #define BL_NOEXCEPT_C #endif //! \def BL_PURE //! //! Function attribute that describes functions that have no side effects. The macro expands to //! `__attribute__((__pure__))` when compiling with GCC or Clang if the attribute is supported, otherwise it expands //! to nothing. #if defined(__clang_major__) && __clang_major__ >= 6 #define BL_PURE __attribute__((__pure__)) #elif defined(__GNUC__) && __GNUC__ >= 6 #define BL_PURE __attribute__((__pure__)) #else #define BL_PURE #endif //! \def BL_ALIGN_TYPE(TYPE, ALIGNMENT) //! //! Defines a type with a particular alignment, avoiding the use of alignas() as some compilers //! have a buggy implementation and restrict alignas() more than a compiler specific attribute. #if defined(__GNUC__) #define BL_ALIGN_TYPE(TYPE, ALIGNMENT) __attribute__((__aligned__(ALIGNMENT))) TYPE #elif defined(_MSC_VER) #define BL_ALIGN_TYPE(TYPE, ALIGNMENT) __declspec(align(ALIGNMENT)) TYPE #else #define BL_ALIGN_TYPE(TYPE, ALIGNMENT) TYPE #endif //! \} //! \name Assumptions //! \{ //! \def BL_ASSUME(...) //! //! Macro that tells the C/C++ compiler that the expression `...` evaluates to true. This macro is only used by few //! places and should be considered internal as you shouldn't need it when using Blend2D library. #if defined(__clang__) #define BL_ASSUME(...) __builtin_assume(__VA_ARGS__) #elif defined(__GNUC__) && __GNUC__ >= 13 #define BL_ASSUME(...) __attribute__((__assume__(__VA_ARGS__))) #elif defined(__GNUC__) #define BL_ASSUME(...) do { if (!(__VA_ARGS__)) __builtin_unreachable(); } while (0) #elif defined(_MSC_VER) #define BL_ASSUME(...) __assume(__VA_ARGS__) #else #define BL_ASSUME(...) (void)0 #endif //! \def BL_LIKELY(...) //! //! A condition is likely. //! \def BL_UNLIKELY(...) //! //! A condition is unlikely. #if defined(__GNUC__) #define BL_LIKELY(...) __builtin_expect(!!(__VA_ARGS__), 1) #define BL_UNLIKELY(...) __builtin_expect(!!(__VA_ARGS__), 0) #else #define BL_LIKELY(...) (__VA_ARGS__) #define BL_UNLIKELY(...) (__VA_ARGS__) #endif //! \} //! \name Debugging and Error Handling //! \{ //! \def BL_ASSERT(EXP) //! //! Run-time assertion executed in debug builds. #ifdef BL_BUILD_DEBUG #define BL_ASSERT(EXP) \ do { \ if (BL_UNLIKELY(!(EXP))) \ blRuntimeAssertionFailure(__FILE__, __LINE__, #EXP); \ } while (0) #else #define BL_ASSERT(EXP) ((void)0) #endif //! Executes the code within the macro and returns if it returned any value other than `BL_SUCCESS`. This macro is //! heavily used across the library for error handling. #define BL_PROPAGATE(...) \ do { \ BLResult resultToPropagate = (__VA_ARGS__); \ if (BL_UNLIKELY(resultToPropagate)) \ return resultToPropagate; \ } while (0) //! \} //! \name Utilities //! \{ //! Creates a 32-bit tag (uint32_t) from the given `A`, `B`, `C`, and `D` values. #define BL_MAKE_TAG(A, B, C, D) ((BLTag)(((BLTag)(A) << 24) | ((BLTag)(B) << 16) | ((BLTag)(C) << 8) | ((BLTag)(D)))) //! \} //! \cond INTERNAL //! \name Internals //! \{ //! \def BL_DEFINE_ENUM(NAME) //! //! Defines an enumeration used by Blend2D that is `uint32_t`. //! \def BL_FORCE_ENUM_UINT32(ENUM_VALUE_PREFIX) //! //! Forces an enumeration to be represented as 32-bit unsigned integer. //! //! This must be used in public C API, because when compiled by a C compiler (not C++ compiler) the enums won't //! have type information (it's a C++ feature). So this macro adds an additional enum value that would force the //! C compiler to make the type unsigned and at 32-bit. //! \} //! \endcond #ifdef __cplusplus #define BL_DEFINE_CONST static constexpr #define BL_DEFINE_ENUM(NAME) enum NAME : uint32_t #define BL_FORCE_ENUM_UINT32(ENUM_VALUE_PREFIX) #else #define BL_DEFINE_CONST static const #define BL_DEFINE_ENUM(NAME) typedef enum NAME NAME; enum NAME #define BL_FORCE_ENUM_UINT32(ENUM_VALUE_PREFIX) ,ENUM_VALUE_PREFIX##_FORCE_UINT = 0xFFFFFFFFu #endif //! \cond INTERNAL //! \name Internals //! \{ //! \def BL_BEGIN_C_DECLS //! Begins C declarations scope when compiling with a C++ compiler. //! \def BL_END_C_DECLS //! Ends C declarations scope when compiling with a C++ compiler. //! \} //! \endcond #ifdef __cplusplus #define BL_BEGIN_C_DECLS extern "C" { #define BL_END_C_DECLS } /* {ExternC} */ #else #define BL_BEGIN_C_DECLS #define BL_END_C_DECLS #endif //! \cond INTERNAL //! \name Compiler Diagnostics //! \{ // Diagnostic warnings can be turned on/off by using pragmas, however, this is a compiler specific stuff we have to // maintain for each compiler. Ideally we should have a clean code that would compiler without any warnings with all // of them enabled by default, but since there is a lot of nitpicks we just disable some locally when needed (like // unused parameter in null-impl functions, etc). #if defined(__clang__) #define BL_DIAGNOSTIC_PUSH(...) _Pragma("clang diagnostic push") __VA_ARGS__ #define BL_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") #define BL_DIAGNOSTIC_NO_UNUSED_FUNCTIONS _Pragma("clang diagnostic ignored \"-Wunused-function\"") #define BL_DIAGNOSTIC_NO_UNUSED_PARAMETERS _Pragma("clang diagnostic ignored \"-Wunused-parameter\"") #define BL_DIAGNOSTIC_NO_EXTRA_WARNINGS _Pragma("clang diagnostic ignored \"-Wextra\"") #elif defined(__GNUC__) #define BL_DIAGNOSTIC_PUSH(...) _Pragma("GCC diagnostic push") __VA_ARGS__ #define BL_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") #define BL_DIAGNOSTIC_NO_UNUSED_FUNCTIONS _Pragma("GCC diagnostic ignored \"-Wunused-function\"") #define BL_DIAGNOSTIC_NO_UNUSED_PARAMETERS _Pragma("GCC diagnostic ignored \"-Wunused-parameter\"") #define BL_DIAGNOSTIC_NO_EXTRA_WARNINGS _Pragma("GCC diagnostic ignored \"-Wextra\"") #elif defined(_MSC_VER) #define BL_DIAGNOSTIC_PUSH(...) __pragma(warning(push)) __VA_ARGS__ #define BL_DIAGNOSTIC_POP __pragma(warning(pop)) #define BL_DIAGNOSTIC_NO_UNUSED_FUNCTIONS __pragma(warning(disable: 4505)) #define BL_DIAGNOSTIC_NO_UNUSED_PARAMETERS __pragma(warning(disable: 4100)) #define BL_DIAGNOSTIC_NO_EXTRA_WARNINGS #endif #if !defined(BL_DIAGNOSTIC_PUSH) #define BL_DIAGNOSTIC_PUSH(...) #define BL_DIAGNOSTIC_POP #define BL_DIAGNOSTIC_NO_UNUSED_FUNCTIONS #define BL_DIAGNOSTIC_NO_UNUSED_PARAMETERS #define BL_DIAGNOSTIC_NO_EXTRA_WARNINGS #endif //! \} //! \endcond //! \} // Forward Declarations // ==================== #ifdef __cplusplus #define BL_FORWARD_DECLARE_STRUCT(NAME) struct NAME #else #define BL_FORWARD_DECLARE_STRUCT(NAME) typedef struct NAME NAME #endif #ifdef __cplusplus #define BL_FORWARD_DECLARE_UNION(NAME) union NAME #else #define BL_FORWARD_DECLARE_UNION(NAME) typedef union NAME NAME #endif #ifdef __cplusplus #define BL_FORWARD_DECLARE_ENUM(NAME) enum NAME : uint32_t #else #define BL_FORWARD_DECLARE_ENUM(NAME) typedef enum NAME NAME #endif BL_FORWARD_DECLARE_STRUCT(BLRange); BL_FORWARD_DECLARE_STRUCT(BLRandom); BL_FORWARD_DECLARE_STRUCT(BLFileCore); BL_FORWARD_DECLARE_STRUCT(BLFileInfo); BL_FORWARD_DECLARE_STRUCT(BLRuntimeScopeCore); BL_FORWARD_DECLARE_STRUCT(BLRuntimeBuildInfo); BL_FORWARD_DECLARE_STRUCT(BLRuntimeSystemInfo); BL_FORWARD_DECLARE_STRUCT(BLRuntimeResourceInfo); BL_FORWARD_DECLARE_STRUCT(BLRgba); BL_FORWARD_DECLARE_STRUCT(BLRgba32); BL_FORWARD_DECLARE_STRUCT(BLRgba64); BL_FORWARD_DECLARE_STRUCT(BLPoint); BL_FORWARD_DECLARE_STRUCT(BLPointI); BL_FORWARD_DECLARE_STRUCT(BLSize); BL_FORWARD_DECLARE_STRUCT(BLSizeI); BL_FORWARD_DECLARE_STRUCT(BLBox); BL_FORWARD_DECLARE_STRUCT(BLBoxI); BL_FORWARD_DECLARE_STRUCT(BLRect); BL_FORWARD_DECLARE_STRUCT(BLRectI); BL_FORWARD_DECLARE_STRUCT(BLLine); BL_FORWARD_DECLARE_STRUCT(BLTriangle); BL_FORWARD_DECLARE_STRUCT(BLRoundRect); BL_FORWARD_DECLARE_STRUCT(BLCircle); BL_FORWARD_DECLARE_STRUCT(BLEllipse); BL_FORWARD_DECLARE_STRUCT(BLArc); BL_FORWARD_DECLARE_STRUCT(BLMatrix2D); BL_FORWARD_DECLARE_STRUCT(BLApproximationOptions); BL_FORWARD_DECLARE_STRUCT(BLStrokeOptionsCore); BL_FORWARD_DECLARE_STRUCT(BLFormatInfo); BL_FORWARD_DECLARE_STRUCT(BLObjectCore); BL_FORWARD_DECLARE_STRUCT(BLObjectImpl); BL_FORWARD_DECLARE_STRUCT(BLObjectVirt); BL_FORWARD_DECLARE_STRUCT(BLObjectVirtBase); BL_FORWARD_DECLARE_STRUCT(BLObjectInfo); BL_FORWARD_DECLARE_UNION(BLObjectDetail); BL_FORWARD_DECLARE_STRUCT(BLArrayCore); BL_FORWARD_DECLARE_STRUCT(BLArrayImpl); BL_FORWARD_DECLARE_STRUCT(BLBitArrayCore); BL_FORWARD_DECLARE_STRUCT(BLBitArrayImpl); BL_FORWARD_DECLARE_STRUCT(BLBitSetCore); BL_FORWARD_DECLARE_STRUCT(BLBitSetData); BL_FORWARD_DECLARE_STRUCT(BLBitSetImpl); BL_FORWARD_DECLARE_STRUCT(BLBitSetSegment); BL_FORWARD_DECLARE_STRUCT(BLBitSetBuilderCore); BL_FORWARD_DECLARE_STRUCT(BLStringCore); BL_FORWARD_DECLARE_STRUCT(BLStringImpl); BL_FORWARD_DECLARE_STRUCT(BLPathCore); BL_FORWARD_DECLARE_STRUCT(BLPathImpl); BL_FORWARD_DECLARE_STRUCT(BLPathView); BL_FORWARD_DECLARE_STRUCT(BLImageData); BL_FORWARD_DECLARE_STRUCT(BLImageInfo); BL_FORWARD_DECLARE_STRUCT(BLImageCore); BL_FORWARD_DECLARE_STRUCT(BLImageImpl); BL_FORWARD_DECLARE_STRUCT(BLImageCodecCore); BL_FORWARD_DECLARE_STRUCT(BLImageCodecImpl); BL_FORWARD_DECLARE_STRUCT(BLImageCodecVirt); BL_FORWARD_DECLARE_STRUCT(BLImageDecoderCore); BL_FORWARD_DECLARE_STRUCT(BLImageDecoderImpl); BL_FORWARD_DECLARE_STRUCT(BLImageDecoderVirt); BL_FORWARD_DECLARE_STRUCT(BLImageEncoderCore); BL_FORWARD_DECLARE_STRUCT(BLImageEncoderImpl); BL_FORWARD_DECLARE_STRUCT(BLImageEncoderVirt); BL_FORWARD_DECLARE_STRUCT(BLPixelConverterCore); BL_FORWARD_DECLARE_STRUCT(BLPixelConverterOptions); BL_FORWARD_DECLARE_STRUCT(BLGradientCore); BL_FORWARD_DECLARE_STRUCT(BLGradientImpl); BL_FORWARD_DECLARE_STRUCT(BLGradientStop); BL_FORWARD_DECLARE_STRUCT(BLLinearGradientValues); BL_FORWARD_DECLARE_STRUCT(BLRadialGradientValues); BL_FORWARD_DECLARE_STRUCT(BLConicGradientValues); BL_FORWARD_DECLARE_STRUCT(BLPatternCore); BL_FORWARD_DECLARE_STRUCT(BLPatternImpl); BL_FORWARD_DECLARE_STRUCT(BLContextCookie); BL_FORWARD_DECLARE_STRUCT(BLContextCreateInfo); BL_FORWARD_DECLARE_STRUCT(BLContextHints); BL_FORWARD_DECLARE_STRUCT(BLContextState); BL_FORWARD_DECLARE_STRUCT(BLContextCore); BL_FORWARD_DECLARE_STRUCT(BLContextImpl); BL_FORWARD_DECLARE_STRUCT(BLContextVirt); BL_FORWARD_DECLARE_STRUCT(BLGlyphBufferCore); BL_FORWARD_DECLARE_STRUCT(BLGlyphBufferImpl); BL_FORWARD_DECLARE_STRUCT(BLGlyphInfo); BL_FORWARD_DECLARE_STRUCT(BLGlyphMappingState); BL_FORWARD_DECLARE_STRUCT(BLGlyphOutlineSinkInfo); BL_FORWARD_DECLARE_STRUCT(BLGlyphPlacement); BL_FORWARD_DECLARE_STRUCT(BLGlyphRun); BL_FORWARD_DECLARE_STRUCT(BLFontUnicodeCoverage); BL_FORWARD_DECLARE_STRUCT(BLFontFaceInfo); BL_FORWARD_DECLARE_STRUCT(BLFontQueryProperties); BL_FORWARD_DECLARE_STRUCT(BLFontFeatureItem); BL_FORWARD_DECLARE_STRUCT(BLFontFeatureSettingsCore); BL_FORWARD_DECLARE_STRUCT(BLFontFeatureSettingsImpl); BL_FORWARD_DECLARE_STRUCT(BLFontFeatureSettingsView); BL_FORWARD_DECLARE_STRUCT(BLFontDesignMetrics); BL_FORWARD_DECLARE_STRUCT(BLFontMatrix); BL_FORWARD_DECLARE_STRUCT(BLFontMetrics); BL_FORWARD_DECLARE_STRUCT(BLFontPanose); BL_FORWARD_DECLARE_STRUCT(BLFontTable); BL_FORWARD_DECLARE_STRUCT(BLFontVariationItem); BL_FORWARD_DECLARE_STRUCT(BLFontVariationSettingsCore); BL_FORWARD_DECLARE_STRUCT(BLFontVariationSettingsImpl); BL_FORWARD_DECLARE_STRUCT(BLFontVariationSettingsView); BL_FORWARD_DECLARE_STRUCT(BLTextMetrics); BL_FORWARD_DECLARE_STRUCT(BLFontCore); BL_FORWARD_DECLARE_STRUCT(BLFontImpl); BL_FORWARD_DECLARE_STRUCT(BLFontDataCore); BL_FORWARD_DECLARE_STRUCT(BLFontDataImpl); BL_FORWARD_DECLARE_STRUCT(BLFontDataVirt); BL_FORWARD_DECLARE_STRUCT(BLFontFaceCore); BL_FORWARD_DECLARE_STRUCT(BLFontFaceImpl); BL_FORWARD_DECLARE_STRUCT(BLFontFaceVirt); BL_FORWARD_DECLARE_STRUCT(BLFontManagerCore); BL_FORWARD_DECLARE_STRUCT(BLFontManagerImpl); BL_FORWARD_DECLARE_STRUCT(BLFontManagerVirt); BL_FORWARD_DECLARE_STRUCT(BLVarCore); #undef BL_FORWARD_DECLARE_ENUM #undef BL_FORWARD_DECLARE_UNION #undef BL_FORWARD_DECLARE_STRUCT // C++ API. #ifdef __cplusplus class BLFile; class BLRuntimeScope; template class BLArray; class BLBitArray; class BLBitSet; template class BLBitSetBuilderT; class BLString; class BLPath; class BLStrokeOptions; class BLImage; class BLImageCodec; class BLImageDecoder; class BLImageEncoder; class BLPattern; class BLGradient; class BLContext; class BLPixelConverter; class BLGlyphBuffer; class BLGlyphRunIterator; class BLFont; class BLFontData; class BLFontFace; class BLFontFeatureSettings; class BLFontManager; class BLFontVariationSettings; class BLVar; #endif // Public Types // ============ //! \ingroup blend2d_api_globals //! //! Result code used by most Blend2D functions (32-bit unsigned integer). //! //! The `BLResultCode` enumeration contains Blend2D result codes that contain Blend2D specific set of errors and //! an extended set of errors that can come from WIN32 or POSIX APIs. Since the success result code is zero it's //! recommended to use the following check to determine whether a call failed or not: //! //! ``` //! BLResult result = doSomething(); //! if (result != BL_SUCCESS) { //! // `doSomething()` failed... //! } //! ``` typedef uint32_t BLResult; //! \ingroup blend2d_api_globals //! //! Tag is a 32-bit integer consisting of 4 characters in the following format: //! //! ``` //! tag = ((a << 24) | (b << 16) | (c << 8) | d) //! ``` //! //! Tags are used extensively by OpenType fonts and other binary formats like PNG. In most cases TAGs should only //! contain ASCII letters, digits, and spaces. //! //! Blend2D uses `BLTag` in public and internal APIs to distinguish between a regular `uint32_t` and tag. typedef uint32_t BLTag; //! \ingroup blend2d_api_globals //! //! Unique identifier that can be used for caching purposes. //! //! Some objects such as \ref BLImage and \ref BLFontFace have assigned an unique identifier that can be used to //! identify such objects for caching purposes. This identifier is never zero, so zero can be safely used as //! "uncached". //! //! \note Unique identifier is per-process. It's implemented as an increasing global or thread-local counter in //! a way that identifiers would not collide. typedef uint64_t BLUniqueId; //! \ingroup blend2d_api_globals //! //! BLUnknown is `void` - it's used in places that accept pointer to `BLVarCore` or any `BLObjectCore` compatible //! object. typedef void BLUnknown; //! \ingroup blend2d_api_globals //! //! A sink that can be used to debug various parts of Blend2D. typedef void (BL_CDECL* BLDebugMessageSinkFunc)(const char* message, size_t size, void* userData) BL_NOEXCEPT; // Public Constants // ================ //! \ingroup blend2d_api_globals //! //! Blend2D result code. BL_DEFINE_ENUM(BLResultCode) { //! Successful result code. BL_SUCCESS = 0, BL_ERROR_START_INDEX = 0x00010000u, BL_ERROR_OUT_OF_MEMORY = 0x00010000u, //!< Out of memory [ENOMEM]. BL_ERROR_INVALID_VALUE, //!< Invalid value/argument [EINVAL]. BL_ERROR_INVALID_STATE, //!< Invalid state [EFAULT]. BL_ERROR_INVALID_HANDLE, //!< Invalid handle or file. [EBADF]. BL_ERROR_INVALID_CONVERSION, //!< Invalid conversion. BL_ERROR_OVERFLOW, //!< Overflow or value too large [EOVERFLOW]. BL_ERROR_NOT_INITIALIZED, //!< Object not initialized. BL_ERROR_NOT_IMPLEMENTED, //!< Not implemented [ENOSYS]. BL_ERROR_NOT_PERMITTED, //!< Operation not permitted [EPERM]. BL_ERROR_IO, //!< IO error [EIO]. BL_ERROR_BUSY, //!< Device or resource busy [EBUSY]. BL_ERROR_INTERRUPTED, //!< Operation interrupted [EINTR]. BL_ERROR_TRY_AGAIN, //!< Try again [EAGAIN]. BL_ERROR_TIMED_OUT, //!< Timed out [ETIMEDOUT]. BL_ERROR_BROKEN_PIPE, //!< Broken pipe [EPIPE]. BL_ERROR_INVALID_SEEK, //!< File is not seekable [ESPIPE]. BL_ERROR_SYMLINK_LOOP, //!< Too many levels of symlinks [ELOOP]. BL_ERROR_FILE_TOO_LARGE, //!< File is too large [EFBIG]. BL_ERROR_ALREADY_EXISTS, //!< File/directory already exists [EEXIST]. BL_ERROR_ACCESS_DENIED, //!< Access denied [EACCES]. BL_ERROR_MEDIA_CHANGED, //!< Media changed [Windows::ERROR_MEDIA_CHANGED]. BL_ERROR_READ_ONLY_FS, //!< The file/FS is read-only [EROFS]. BL_ERROR_NO_DEVICE, //!< Device doesn't exist [ENXIO]. BL_ERROR_NO_ENTRY, //!< Not found, no entry (fs) [ENOENT]. BL_ERROR_NO_MEDIA, //!< No media in drive/device [ENOMEDIUM]. BL_ERROR_NO_MORE_DATA, //!< No more data / end of file [ENODATA]. BL_ERROR_NO_MORE_FILES, //!< No more files [ENMFILE]. BL_ERROR_NO_SPACE_LEFT, //!< No space left on device [ENOSPC]. BL_ERROR_NOT_EMPTY, //!< Directory is not empty [ENOTEMPTY]. BL_ERROR_NOT_FILE, //!< Not a file [EISDIR]. BL_ERROR_NOT_DIRECTORY, //!< Not a directory [ENOTDIR]. BL_ERROR_NOT_SAME_DEVICE, //!< Not same device [EXDEV]. BL_ERROR_NOT_BLOCK_DEVICE, //!< Not a block device [ENOTBLK]. BL_ERROR_INVALID_FILE_NAME, //!< File/path name is invalid [n/a]. BL_ERROR_FILE_NAME_TOO_LONG, //!< File/path name is too long [ENAMETOOLONG]. BL_ERROR_TOO_MANY_OPEN_FILES, //!< Too many open files [EMFILE]. BL_ERROR_TOO_MANY_OPEN_FILES_BY_OS, //!< Too many open files by OS [ENFILE]. BL_ERROR_TOO_MANY_LINKS, //!< Too many symbolic links on FS [EMLINK]. BL_ERROR_TOO_MANY_THREADS, //!< Too many threads [EAGAIN]. BL_ERROR_THREAD_POOL_EXHAUSTED, //!< Thread pool is exhausted and couldn't acquire the requested thread count. BL_ERROR_FILE_EMPTY, //!< File is empty (not specific to any OS error). BL_ERROR_OPEN_FAILED, //!< File open failed [Windows::ERROR_OPEN_FAILED]. BL_ERROR_NOT_ROOT_DEVICE, //!< Not a root device/directory [Windows::ERROR_DIR_NOT_ROOT]. BL_ERROR_UNKNOWN_SYSTEM_ERROR, //!< Unknown system error that failed to translate to Blend2D result code. BL_ERROR_INVALID_ALIGNMENT, //!< Invalid data alignment. BL_ERROR_INVALID_SIGNATURE, //!< Invalid data signature or header. BL_ERROR_INVALID_DATA, //!< Invalid or corrupted data. BL_ERROR_INVALID_STRING, //!< Invalid string (invalid data of either UTF8, UTF16, or UTF32). BL_ERROR_INVALID_KEY, //!< Invalid key or property. BL_ERROR_DATA_TRUNCATED, //!< Truncated data (more data required than memory/stream provides). BL_ERROR_DATA_TOO_LARGE, //!< Input data too large to be processed. BL_ERROR_DECOMPRESSION_FAILED, //!< Decompression failed due to invalid data (RLE, Huffman, etc). BL_ERROR_INVALID_GEOMETRY, //!< Invalid geometry (invalid path data or shape). BL_ERROR_NO_MATCHING_VERTEX, //!< Returned when there is no matching vertex in path data. BL_ERROR_INVALID_CREATE_FLAGS, //!< Invalid create flags (BLContext). BL_ERROR_NO_MATCHING_COOKIE, //!< No matching cookie (BLContext). BL_ERROR_NO_STATES_TO_RESTORE, //!< No states to restore (BLContext). BL_ERROR_TOO_MANY_SAVED_STATES, //!< Cannot save state as the number of saved states reached the limit (BLContext). BL_ERROR_IMAGE_TOO_LARGE, //!< The size of the image is too large. BL_ERROR_IMAGE_NO_MATCHING_CODEC, //!< Image codec for a required format doesn't exist. BL_ERROR_IMAGE_UNKNOWN_FILE_FORMAT, //!< Unknown or invalid file format that cannot be read. BL_ERROR_IMAGE_DECODER_NOT_PROVIDED, //!< Image codec doesn't support reading the file format. BL_ERROR_IMAGE_ENCODER_NOT_PROVIDED, //!< Image codec doesn't support writing the file format. BL_ERROR_PNG_MULTIPLE_IHDR, //!< Multiple IHDR chunks are not allowed (PNG). BL_ERROR_PNG_INVALID_IDAT, //!< Invalid IDAT chunk (PNG). BL_ERROR_PNG_INVALID_IEND, //!< Invalid IEND chunk (PNG). BL_ERROR_PNG_INVALID_PLTE, //!< Invalid PLTE chunk (PNG). BL_ERROR_PNG_INVALID_TRNS, //!< Invalid tRNS chunk (PNG). BL_ERROR_PNG_INVALID_FILTER, //!< Invalid filter type (PNG). BL_ERROR_JPEG_UNSUPPORTED_FEATURE, //!< Unsupported feature (JPEG). BL_ERROR_JPEG_INVALID_SOS, //!< Invalid SOS marker or header (JPEG). BL_ERROR_JPEG_INVALID_SOF, //!< Invalid SOF marker (JPEG). BL_ERROR_JPEG_MULTIPLE_SOF, //!< Multiple SOF markers (JPEG). BL_ERROR_JPEG_UNSUPPORTED_SOF, //!< Unsupported SOF marker (JPEG). BL_ERROR_FONT_NOT_INITIALIZED, //!< Font doesn't have any data as it's not initialized. BL_ERROR_FONT_NO_MATCH, //!< Font or font face was not matched (BLFontManager). BL_ERROR_FONT_NO_CHARACTER_MAPPING, //!< Font has no character to glyph mapping data. BL_ERROR_FONT_MISSING_IMPORTANT_TABLE, //!< Font has missing an important table. BL_ERROR_FONT_FEATURE_NOT_AVAILABLE, //!< Font feature is not available. BL_ERROR_FONT_CFF_INVALID_DATA, //!< Font has an invalid CFF data. BL_ERROR_FONT_PROGRAM_TERMINATED, //!< Font program terminated because the execution reached the limit. BL_ERROR_GLYPH_SUBSTITUTION_TOO_LARGE, //!< Glyph substitution requires too much space and was terminated. BL_ERROR_INVALID_GLYPH //!< Invalid glyph identifier. BL_FORCE_ENUM_UINT32(BL_ERROR) }; //! \ingroup blend2d_api_globals //! //! Byte order. BL_DEFINE_ENUM(BLByteOrder) { //! Little endian byte-order. BL_BYTE_ORDER_LE = 0, //! Big endian byte-order. BL_BYTE_ORDER_BE = 1, //! Native (host) byte-order. BL_BYTE_ORDER_NATIVE = BL_BYTE_ORDER == 1234 ? BL_BYTE_ORDER_LE : BL_BYTE_ORDER_BE, //! Swapped byte-order (BE if host is LE and vice versa). BL_BYTE_ORDER_SWAPPED = BL_BYTE_ORDER == 1234 ? BL_BYTE_ORDER_BE : BL_BYTE_ORDER_LE BL_FORCE_ENUM_UINT32(BL_BYTE_ORDER) }; //! \ingroup blend2d_api_globals //! //! Data access flags. BL_DEFINE_ENUM(BLDataAccessFlags) { //! No data access flags. BL_DATA_ACCESS_NO_FLAGS = 0x00u, //! Read access. BL_DATA_ACCESS_READ = 0x01u, //! Write access. BL_DATA_ACCESS_WRITE = 0x02u, //! Read and write access. BL_DATA_ACCESS_RW = 0x03u BL_FORCE_ENUM_UINT32(BL_DATA_ACCESS) }; //! \ingroup blend2d_api_globals //! //! Data source type. BL_DEFINE_ENUM(BLDataSourceType) { //! No data source. BL_DATA_SOURCE_TYPE_NONE = 0, //! Memory data source. BL_DATA_SOURCE_TYPE_MEMORY = 1, //! File data source. BL_DATA_SOURCE_TYPE_FILE = 2, //! Custom data source. BL_DATA_SOURCE_TYPE_CUSTOM = 3, //! Maximum value `BLDataSourceType`. BL_DATA_SOURCE_TYPE_MAX_VALUE = 3 BL_FORCE_ENUM_UINT32(BL_DATA_SOURCE_TYPE) }; //! \ingroup blend2d_api_globals //! //! Modification operation applied to Blend2D containers. BL_DEFINE_ENUM(BLModifyOp) { //! Assign operation, which reserves space only to fit the requested input. BL_MODIFY_OP_ASSIGN_FIT = 0, //! Assign operation, which takes into consideration successive appends. BL_MODIFY_OP_ASSIGN_GROW = 1, //! Append operation, which reserves space only to fit the current and appended content. BL_MODIFY_OP_APPEND_FIT = 2, //! Append operation, which takes into consideration successive appends. BL_MODIFY_OP_APPEND_GROW = 3, //! Maximum value of `BLModifyOp`. BL_MODIFY_OP_MAX_VALUE = 3 BL_FORCE_ENUM_UINT32(BL_MODIFY_OP) }; //! \ingroup blend2d_api_globals //! //! Boolean operator. BL_DEFINE_ENUM(BLBooleanOp) { //! Result = B. BL_BOOLEAN_OP_COPY = 0, //! Result = A & B. BL_BOOLEAN_OP_AND = 1, //! Result = A | B. BL_BOOLEAN_OP_OR = 2, //! Result = A ^ B. BL_BOOLEAN_OP_XOR = 3, //! Result = A & ~B. BL_BOOLEAN_OP_AND_NOT = 4, //! Result = ~A & B. BL_BOOLEAN_OP_NOT_AND = 5, //! Maximum value of `BLBooleanOp`. BL_BOOLEAN_OP_MAX_VALUE = 5 BL_FORCE_ENUM_UINT32(BL_BOOLEAN_OP) }; //! \ingroup blend2d_api_styling //! //! Extend mode. BL_DEFINE_ENUM(BLExtendMode) { //! Pad extend [default]. BL_EXTEND_MODE_PAD = 0, //! Repeat extend. BL_EXTEND_MODE_REPEAT = 1, //! Reflect extend. BL_EXTEND_MODE_REFLECT = 2, //! Alias to `BL_EXTEND_MODE_PAD`. BL_EXTEND_MODE_PAD_X_PAD_Y = 0, //! Pad X and repeat Y. BL_EXTEND_MODE_PAD_X_REPEAT_Y = 3, //! Pad X and reflect Y. BL_EXTEND_MODE_PAD_X_REFLECT_Y = 4, //! Alias to `BL_EXTEND_MODE_REPEAT`. BL_EXTEND_MODE_REPEAT_X_REPEAT_Y = 1, //! Repeat X and pad Y. BL_EXTEND_MODE_REPEAT_X_PAD_Y = 5, //! Repeat X and reflect Y. BL_EXTEND_MODE_REPEAT_X_REFLECT_Y = 6, //! Alias to `BL_EXTEND_MODE_REFLECT`. BL_EXTEND_MODE_REFLECT_X_REFLECT_Y = 2, //! Reflect X and pad Y. BL_EXTEND_MODE_REFLECT_X_PAD_Y = 7, //! Reflect X and repeat Y. BL_EXTEND_MODE_REFLECT_X_REPEAT_Y = 8, //! Count of simple extend modes (that use the same value for X and Y). BL_EXTEND_MODE_SIMPLE_MAX_VALUE = 2, //! Count of complex extend modes (that can use independent values for X and Y). BL_EXTEND_MODE_COMPLEX_MAX_VALUE = 8, //! Maximum value of `BLExtendMode`. BL_EXTEND_MODE_MAX_VALUE = 8 BL_FORCE_ENUM_UINT32(BL_EXTEND_MODE) }; //! \ingroup blend2d_api_text //! //! Text encoding. BL_DEFINE_ENUM(BLTextEncoding) { //! UTF-8 encoding. BL_TEXT_ENCODING_UTF8 = 0, //! UTF-16 encoding (native endian). BL_TEXT_ENCODING_UTF16 = 1, //! UTF-32 encoding (native endian). BL_TEXT_ENCODING_UTF32 = 2, //! LATIN1 encoding (one byte per character). BL_TEXT_ENCODING_LATIN1 = 3, //! Platform native `wchar_t` (or Windows `WCHAR`) encoding, alias to //! either UTF-32, UTF-16, or UTF-8 depending on `sizeof(wchar_t)`. BL_TEXT_ENCODING_WCHAR = sizeof(wchar_t) == 4 ? BL_TEXT_ENCODING_UTF32 : sizeof(wchar_t) == 2 ? BL_TEXT_ENCODING_UTF16 : BL_TEXT_ENCODING_UTF8, //! Maximum value of `BLTextEncoding`. BL_TEXT_ENCODING_MAX_VALUE = 3 BL_FORCE_ENUM_UINT32(BL_TEXT_ENCODING) }; // Internal API // ============ #ifdef __cplusplus //! \cond INTERNAL //! \ingroup blend2d_internal //! //! Internal namespace that should never be used by Blend2D users. //! //! This namespace provides functionality that is internally used by the public C++ API in public headers. //! There should never be functionality that is not used by public headers, that should always be hidden. namespace BLInternal { template BL_INLINE_NODEBUG typename std::remove_reference::type&& move(T&& v) noexcept { return static_cast::type&&>(v); } template BL_INLINE_NODEBUG T&& forward(typename std::remove_reference::type& v) noexcept { return static_cast(v); } template BL_INLINE_NODEBUG T&& forward(typename std::remove_reference::type&& v) noexcept { return static_cast(v); } template BL_INLINE void swap(T& t1, T& t2) noexcept { T temp(move(t1)); t1 = move(t2); t2 = move(temp); } //! StdIntT provides a signed integer type as defined by by size. template struct StdIntT; template<> struct StdIntT<1, false> { typedef int8_t Type; }; template<> struct StdIntT<2, false> { typedef int16_t Type; }; template<> struct StdIntT<4, false> { typedef int32_t Type; }; template<> struct StdIntT<8, false> { typedef int64_t Type; }; template<> struct StdIntT<1, true> { typedef uint8_t Type; }; template<> struct StdIntT<2, true> { typedef uint16_t Type; }; template<> struct StdIntT<4, true> { typedef uint32_t Type; }; template<> struct StdIntT<8, true> { typedef uint64_t Type; }; template using IntBySize = typename StdIntT::Type; template using UIntBySize = typename StdIntT::Type; template using IntByType = typename StdIntT::Type; template using UIntByType = typename StdIntT::Type; template struct ConstCTZ { enum : uint32_t { kValue = (kInput & (uint64_t(1) << 0)) ? 0 : (kInput & (uint64_t(1) << 1)) ? 1 : (kInput & (uint64_t(1) << 2)) ? 2 : (kInput & (uint64_t(1) << 3)) ? 3 : (kInput & (uint64_t(1) << 4)) ? 4 : (kInput & (uint64_t(1) << 5)) ? 5 : (kInput & (uint64_t(1) << 6)) ? 6 : (kInput & (uint64_t(1) << 7)) ? 7 : (kInput & (uint64_t(1) << 8)) ? 8 : (kInput & (uint64_t(1) << 9)) ? 9 : (kInput & (uint64_t(1) << 10)) ? 10 : (kInput & (uint64_t(1) << 11)) ? 11 : (kInput & (uint64_t(1) << 12)) ? 12 : (kInput & (uint64_t(1) << 13)) ? 13 : (kInput & (uint64_t(1) << 14)) ? 14 : (kInput & (uint64_t(1) << 15)) ? 15 : (kInput & (uint64_t(1) << 16)) ? 16 : (kInput & (uint64_t(1) << 17)) ? 17 : (kInput & (uint64_t(1) << 18)) ? 18 : (kInput & (uint64_t(1) << 19)) ? 19 : (kInput & (uint64_t(1) << 20)) ? 20 : (kInput & (uint64_t(1) << 21)) ? 21 : (kInput & (uint64_t(1) << 22)) ? 22 : (kInput & (uint64_t(1) << 23)) ? 23 : (kInput & (uint64_t(1) << 24)) ? 24 : (kInput & (uint64_t(1) << 25)) ? 25 : (kInput & (uint64_t(1) << 26)) ? 26 : (kInput & (uint64_t(1) << 27)) ? 27 : (kInput & (uint64_t(1) << 28)) ? 28 : (kInput & (uint64_t(1) << 29)) ? 29 : (kInput & (uint64_t(1) << 30)) ? 30 : (kInput & (uint64_t(1) << 31)) ? 31 : (kInput & (uint64_t(1) << 32)) ? 32 : (kInput & (uint64_t(1) << 33)) ? 33 : (kInput & (uint64_t(1) << 34)) ? 34 : (kInput & (uint64_t(1) << 35)) ? 35 : (kInput & (uint64_t(1) << 36)) ? 36 : (kInput & (uint64_t(1) << 37)) ? 37 : (kInput & (uint64_t(1) << 38)) ? 38 : (kInput & (uint64_t(1) << 39)) ? 39 : (kInput & (uint64_t(1) << 40)) ? 40 : (kInput & (uint64_t(1) << 41)) ? 41 : (kInput & (uint64_t(1) << 42)) ? 42 : (kInput & (uint64_t(1) << 43)) ? 43 : (kInput & (uint64_t(1) << 44)) ? 44 : (kInput & (uint64_t(1) << 45)) ? 45 : (kInput & (uint64_t(1) << 46)) ? 46 : (kInput & (uint64_t(1) << 47)) ? 47 : (kInput & (uint64_t(1) << 48)) ? 48 : (kInput & (uint64_t(1) << 49)) ? 49 : (kInput & (uint64_t(1) << 50)) ? 50 : (kInput & (uint64_t(1) << 51)) ? 51 : (kInput & (uint64_t(1) << 52)) ? 52 : (kInput & (uint64_t(1) << 53)) ? 53 : (kInput & (uint64_t(1) << 54)) ? 54 : (kInput & (uint64_t(1) << 55)) ? 55 : (kInput & (uint64_t(1) << 56)) ? 56 : (kInput & (uint64_t(1) << 57)) ? 57 : (kInput & (uint64_t(1) << 58)) ? 58 : (kInput & (uint64_t(1) << 59)) ? 59 : (kInput & (uint64_t(1) << 60)) ? 60 : (kInput & (uint64_t(1) << 61)) ? 61 : (kInput & (uint64_t(1) << 62)) ? 62 : (kInput & (uint64_t(1) << 63)) ? 63 : 64 }; }; //! Type category. //! //! Provides type categorization for compile-time type reflection that can be used by templates. enum TypeCategory : uint32_t { //! Type is unknown. kTypeCategoryUnknown = 0, //! Type is a boolean (`bool`). kTypeCategoryBool = 1, //! Type is integral. kTypeCategoryInt = 2, //! Type is a floating point. kTypeCategoryFloat = 3, //! Type is a pointer. kTypeCategoryPtr = 4, //! Type is a structure. kTypeCategoryStruct = 5, //! Type is BLObject compatible. kTypeCategoryObject = 6 }; //! Type flags. //! //! Provides details about a categorized type. enum TypeFlags : uint32_t { //! Type has no flags. kTypeNoFlags = 0x0000u, //! Type is primitive (either bool, integer, or floating point). kTypeFlagPrimitive = 0x0001u, //! Type is `BLArrayCore` or `BLArray`. kTypeFlagArray = 0x0002u, //! Type is `BLVarCore` or `BLVar` kTypeFlagVar = 0x0004u, //! Type is `BLxxxCore` - C API type. kTypeFlagCore = 0x0008u, //! Type is `BLRgba`. kTypeFlagRgba = 0x0010u, //! Type is `BLRgba32`. kTypeFlagRgba32 = 0x0020u, //! Type is `BLRgba64`. kTypeFlagRgba64 = 0x0040u, //! Type is `BLGradient[Core]` or `BLPattern[Core]`. kTypeFlagStyle = 0x0080u }; template struct TypeTraits { enum : uint32_t { kCategory = std::is_pointer::value ? kTypeCategoryPtr : std::is_integral::value ? kTypeCategoryInt : std::is_floating_point::value ? kTypeCategoryFloat : kTypeCategoryStruct, kFlags = std::is_pointer::value ? kTypeFlagPrimitive : std::is_integral::value ? kTypeFlagPrimitive : std::is_floating_point::value ? kTypeFlagPrimitive : kTypeNoFlags }; }; template<> struct TypeTraits { enum : uint32_t { kCategory = kTypeCategoryBool, kFlags = kTypeFlagPrimitive }; }; // BLArrayCore and BLArray specialization. template<> struct TypeTraits { enum : uint32_t { kCategory = kTypeCategoryObject, kFlags = kTypeFlagArray | kTypeFlagCore }; }; template struct TypeTraits> { enum : uint32_t { kCategory = kTypeCategoryObject, kFlags = kTypeFlagArray }; }; // Other types compatible with BLObjectCore. #define BL_DEFINE_OBJECT_TRAITS(T, Flags) \ template<> \ struct TypeTraits { \ enum : uint32_t { \ kCategory = kTypeCategoryObject, \ kFlags = Flags | kTypeFlagCore \ }; \ }; \ \ template<> \ struct TypeTraits { \ enum : uint32_t { \ kCategory = kTypeCategoryObject, \ kFlags = Flags \ }; \ }; BL_DEFINE_OBJECT_TRAITS(BLBitArray , kTypeNoFlags) BL_DEFINE_OBJECT_TRAITS(BLBitSet , kTypeNoFlags) BL_DEFINE_OBJECT_TRAITS(BLContext , kTypeNoFlags) BL_DEFINE_OBJECT_TRAITS(BLFont , kTypeNoFlags) BL_DEFINE_OBJECT_TRAITS(BLFontData , kTypeNoFlags) BL_DEFINE_OBJECT_TRAITS(BLFontFace , kTypeNoFlags) BL_DEFINE_OBJECT_TRAITS(BLFontFeatureSettings , kTypeNoFlags) BL_DEFINE_OBJECT_TRAITS(BLFontManager , kTypeNoFlags) BL_DEFINE_OBJECT_TRAITS(BLFontVariationSettings, kTypeNoFlags) BL_DEFINE_OBJECT_TRAITS(BLGradient , kTypeFlagStyle) BL_DEFINE_OBJECT_TRAITS(BLImage , kTypeNoFlags) BL_DEFINE_OBJECT_TRAITS(BLImageCodec , kTypeNoFlags) BL_DEFINE_OBJECT_TRAITS(BLImageDecoder , kTypeNoFlags) BL_DEFINE_OBJECT_TRAITS(BLImageEncoder , kTypeNoFlags) BL_DEFINE_OBJECT_TRAITS(BLPath , kTypeNoFlags) BL_DEFINE_OBJECT_TRAITS(BLPattern , kTypeFlagStyle) BL_DEFINE_OBJECT_TRAITS(BLString , kTypeNoFlags) BL_DEFINE_OBJECT_TRAITS(BLVar , kTypeFlagVar) #undef BL_DEFINE_OBJECT_TRAITS //! Helper to implement placement new/delete without relying on `` header. struct PlacementNew { void* ptr; }; } // {BLInternal} //! Implementation of a placement new so we don't have to depend on ``. BL_INLINE_NODEBUG void* operator new(size_t, const BLInternal::PlacementNew& p) { #if defined(_MSC_VER) && !defined(__clang__) BL_ASSUME(p.ptr != nullptr); // Otherwise MSVC would emit a nullptr check. #endif return p.ptr; } BL_INLINE_NODEBUG void operator delete(void*, const BLInternal::PlacementNew&) noexcept {} //! \endcond #endif // Public API - TraceError // ======================= //! \addtogroup blend2d_api_globals //! \{ //! \name Debugging Functionality //! \{ //! Returns the `result` passed. //! //! Provided for debugging purposes. Putting a breakpoint inside `blTraceError()` can help with tracing an origin //! of errors reported / returned by Blend2D as each error goes through this function. //! //! It's a zero-cost solution that doesn't affect release builds in any way. BL_NODISCARD static inline BLResult blTraceError(BLResult result) BL_NOEXCEPT_C { return result; } BL_BEGIN_C_DECLS BL_API BL_NORETURN void BL_CDECL blRuntimeAssertionFailure(const char* file, int line, const char* msg) BL_NOEXCEPT_C; BL_END_C_DECLS //! \} //! \} // Public API - Templates // ====================== #ifdef __cplusplus // These are the only global functions provided in C++ mode. They are needed by C++ API wrappers and can be used // freely by Blend2D users as these templates have specializations for some geometry types. For example `blMin(a, b)` // works with numbers as well as with `BLPoint`. //! \addtogroup blend2d_api_globals //! \{ //! \name Explicit Construction & Destruction. //! //! These should be only necessary when extending Blend2D. //! //! \{ //! Constructs an instance in place (calls its constructor) with optional `args`. template static BL_INLINE void blCallCtor(T& instance, Args&&... args) noexcept { // Only needed by MSVC as otherwise it could generate null-pointer check before calling the constructor. If the // assumption is used with GCC or Clang it would emit a "-Wtautological-undefined-compare" warning so we really // have to only enable this for compilers that don't have the necessary diagnostics to remove the nullptr check. #if defined(_MSC_VER) && !defined(__clang__) BL_ASSUME(&instance != nullptr); #endif new(BLInternal::PlacementNew{&instance}) T(BLInternal::forward(args)...); } //! Destroys an instance in place (calls its destructor). template static BL_INLINE void blCallDtor(T& instance) noexcept { // Only needed by MSVC as otherwise it could generate null-pointer check before calling the destructor. If the // assumption is used with GCC or Clang it would emit a "-Wtautological-undefined-compare" warning so we really // have to only enable this for compilers that don't have the necessary diagnostics to remove the nullptr check. #if defined(_MSC_VER) && !defined(__clang__) BL_ASSUME(&instance != nullptr); #endif instance.~T(); } //! \} //! \name Global C++ Functions //! \{ //! Bit-cast `x` of `In` type to the given `Out` type. //! //! Useful to bit-cast between integers and floating points. The size of `Out` and `In` must be the same otherwise the //! compilation would fail. Bit casting is used by `blEquals` to implement bit equality for floating point types. template BL_NODISCARD static BL_INLINE_NODEBUG Out blBitCast(const In& x) noexcept { static_assert(sizeof(Out) == sizeof(In), "The size of 'In' and 'Out' types must match"); union { In in; Out out; } u = { x }; return u.out; } //! Returns an absolute value of `a`. template BL_NODISCARD BL_INLINE_NODEBUG constexpr T blAbs(const T& a) noexcept { return T(a < T(0) ? -a : a); } //! Returns a minimum value of `a` and `b`. template BL_NODISCARD BL_INLINE_NODEBUG constexpr T blMin(const T& a, const T& b) noexcept { return T(b < a ? b : a); } //! Returns a maximum value of `a` and `b`. template BL_NODISCARD BL_INLINE_NODEBUG constexpr T blMax(const T& a, const T& b) noexcept { return T(a < b ? b : a); } //! Clamps `a` to a range defined as `[b, c]`. template BL_NODISCARD BL_INLINE_NODEBUG constexpr T blClamp(const T& a, const T& b, const T& c) noexcept { return blMin(c, blMax(b, a)); } //! Returns a minimum value of all arguments passed. template BL_NODISCARD BL_INLINE_NODEBUG constexpr T blMin(const T& a, const T& b, Args&&... args) noexcept { return blMin(blMin(a, b), BLInternal::forward(args)...); } //! Returns a maximum value of all arguments passed. template BL_NODISCARD BL_INLINE_NODEBUG constexpr T blMax(const T& a, const T& b, Args&&... args) noexcept { return blMax(blMax(a, b), BLInternal::forward(args)...); } //! Returns `true` if `a` and `b` equals at binary level. //! //! For example `blEquals(NaN, NaN) == true`. template BL_NODISCARD BL_INLINE_NODEBUG bool blEquals(const T& a, const T& b) noexcept { return a == b; } //! \cond NEVER template<> BL_NODISCARD BL_INLINE_NODEBUG bool blEquals(const float& a, const float& b) noexcept { return blBitCast(a) == blBitCast(b); } template<> BL_NODISCARD BL_INLINE_NODEBUG bool blEquals(const double& a, const double& b) noexcept { return blBitCast(a) == blBitCast(b); } //! \endcond //! \} //! \} #endif //! \addtogroup blend2d_api_globals //! \{ //! Provides start and end indexes. It has the same semantics as Slices in other programming languages - range is //! always within [star, end) internal (start is inclusive, end is exclusive). It's used to specify a range of an //! operation of indexed containers like `BLString`, `BLArray`, `BLGradient`, `BLPath`, etc... struct BLRange { size_t start; size_t end; #ifdef __cplusplus //! \name Construction & Destruction //! \{ BL_NODISCARD static BL_INLINE_NODEBUG constexpr BLRange everything() noexcept { return BLRange{0, SIZE_MAX}; } //! \} //! \name Overloaded Operators //! \{ BL_NODISCARD BL_INLINE_NODEBUG bool operator==(const BLRange& other) const noexcept { return equals(other); } BL_NODISCARD BL_INLINE_NODEBUG bool operator!=(const BLRange& other) const noexcept { return !equals(other); } //! \} //! \name Common Functionality //! \{ //! Reset the range to [0, 0). BL_INLINE_NODEBUG void reset() noexcept { *this = BLRange{}; } //! Reset the range to [start, end). BL_INLINE_NODEBUG void reset(size_t rStart, size_t rEnd) noexcept { *this = BLRange{rStart, rEnd}; } //! \} //! \name Equality & Comparison //! \{ BL_NODISCARD BL_INLINE_NODEBUG bool equals(const BLRange& other) const noexcept { return bool(unsigned(blEquals(start, other.start)) & unsigned(blEquals(end, other.end))); } //! \} #endif }; #ifdef __cplusplus //! Array view of `T`. //! //! \note In C mode the type of data used by `BLArrayView` is `const void*`, thus it has to be retyped to a real //! type this view points to. There are only few specializations like `BLStringView` that point to a real type. template struct BLArrayView { const T* data; size_t size; BL_INLINE_NODEBUG void reset() noexcept { *this = BLArrayView{}; } BL_INLINE_NODEBUG void reset(const T* dataIn, size_t sizeIn) noexcept { data = dataIn; size = sizeIn; } BL_INLINE const T& operator[](size_t index) noexcept { BL_ASSERT(index < size); return data[index]; } BL_INLINE_NODEBUG const T* begin() const noexcept { return data; } BL_INLINE_NODEBUG const T* end() const noexcept { return data + size; } BL_INLINE_NODEBUG const T* cbegin() const noexcept { return data; } BL_INLINE_NODEBUG const T* cend() const noexcept { return data + size; } }; // In C++ mode these are just typedefs of `BLArrayView`. //! View of char[] data used by String. typedef BLArrayView BLStringView; //! View of untyped data. typedef BLArrayView BLDataView; #else #define BL_DEFINE_ARRAY_VIEW(NAME, TYPE) \ typedef struct { \ const TYPE* data; \ size_t size; \ } NAME BL_DEFINE_ARRAY_VIEW(BLArrayView, void); BL_DEFINE_ARRAY_VIEW(BLStringView, char); typedef BLArrayView BLDataView; #undef BL_DEFINE_ARRAY_VIEW #endif //! \} #endif // BLEND2D_API_H_INCLUDED