odin-blend2d

Odin bindings to Blend2D
Log | Files | Refs | README | LICENSE

commit f0393aad5b2cd3b872d09793efcf74bdc446fd2b
parent 3ced436227108c9e41564dded5f9ef509c87331c
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date:   Sat, 25 Oct 2025 23:19:33 -0300

binding: add initial set of bindings

Diffstat:
Abinding/api-impl.odin | 15+++++++++++++++
Abinding/api.odin | 376+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/array.odin | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/bitarray.odin | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/bitset.odin | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/context.odin | 759+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/filesystem.odin | 266+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/font.odin | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/fontdata.odin | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/fontdefs.odin | 730+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/fontface.odin | 234+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/fontfeaturesettings.odin | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/fontmanager.odin | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/fontvariationsettings.odin | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/format.odin | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/geometry.odin | 244+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/glyphbuffer.odin | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/glyphrun.odin | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/gradient.odin | 188+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/image.odin | 157+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/imagecodec.odin | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/imagedecoder.odin | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/imageencoder.odin | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/matrix.odin | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/object.odin | 336+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/path.odin | 369+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/pattern.odin | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/pixelconverter.odin | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/random.odin | 35+++++++++++++++++++++++++++++++++++
Abinding/rgba.odin | 42++++++++++++++++++++++++++++++++++++++++++
Abinding/runtime.odin | 230+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/runtimescope.odin | 27+++++++++++++++++++++++++++
Abinding/string.odin | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abinding/var.odin | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
34 files changed, 5730 insertions(+), 0 deletions(-)

diff --git a/binding/api-impl.odin b/binding/api-impl.odin @@ -0,0 +1,15 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + diff --git a/binding/api.odin b/binding/api.odin @@ -0,0 +1,376 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +BYTE_ORDER :: 1234 + +//! \ingroup bl_globals +//! +//! Result code used by most Blend2D functions (32-bit unsigned integer). +//! +//! The \ref 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 = do_something(); +//! if (result != BL_SUCCESS) { +//! // `do_something()` failed... +//! } +//! ``` +Result :: u32 + +//! \ingroup bl_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 \ref BLTag in public and internal APIs to distinguish between a regular `uint32_t` and tag. +Tag :: u32 + +//! \ingroup bl_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. +UniqueId :: u64 + +//! \ingroup bl_globals +//! +//! BLUnknown is `void` - it's used in places that accept pointer to \ref BLVarCore or any \ref BLObjectCore +//! compatible object. +Unknown :: struct {} + +//! \ingroup bl_globals +//! +//! A sink that can be used to debug various parts of Blend2D. +DebugMessageSinkFunc :: proc "c" (message: cstring, size: c.size_t, user_data: rawptr) + +//! \ingroup bl_globals +//! +//! Blend2D result code. +ResultCode :: enum u32 { + //! Successful result code. + SUCCESS = 0, + ERROR_START_INDEX = 65536, + ERROR_OUT_OF_MEMORY = 65536, //!< Out of memory [ENOMEM]. + ERROR_INVALID_VALUE = 65537, //!< Invalid value/argument [EINVAL]. + ERROR_INVALID_STATE = 65538, //!< Invalid state [EFAULT]. + ERROR_INVALID_HANDLE = 65539, //!< Invalid handle or file. [EBADF]. + ERROR_INVALID_CONVERSION = 65540, //!< Invalid conversion. + ERROR_OVERFLOW = 65541, //!< Overflow or value too large [EOVERFLOW]. + ERROR_NOT_INITIALIZED = 65542, //!< Object not initialized. + ERROR_NOT_IMPLEMENTED = 65543, //!< Not implemented [ENOSYS]. + ERROR_NOT_PERMITTED = 65544, //!< Operation not permitted [EPERM]. + ERROR_IO = 65545, //!< IO error [EIO]. + ERROR_BUSY = 65546, //!< Device or resource busy [EBUSY]. + ERROR_INTERRUPTED = 65547, //!< Operation interrupted [EINTR]. + ERROR_TRY_AGAIN = 65548, //!< Try again [EAGAIN]. + ERROR_TIMED_OUT = 65549, //!< Timed out [ETIMEDOUT]. + ERROR_BROKEN_PIPE = 65550, //!< Broken pipe [EPIPE]. + ERROR_INVALID_SEEK = 65551, //!< File is not seekable [ESPIPE]. + ERROR_SYMLINK_LOOP = 65552, //!< Too many levels of symlinks [ELOOP]. + ERROR_FILE_TOO_LARGE = 65553, //!< File is too large [EFBIG]. + ERROR_ALREADY_EXISTS = 65554, //!< File/directory already exists [EEXIST]. + ERROR_ACCESS_DENIED = 65555, //!< Access denied [EACCES]. + ERROR_MEDIA_CHANGED = 65556, //!< Media changed [Windows::ERROR_MEDIA_CHANGED]. + ERROR_READ_ONLY_FS = 65557, //!< The file/FS is read-only [EROFS]. + ERROR_NO_DEVICE = 65558, //!< Device doesn't exist [ENXIO]. + ERROR_NO_ENTRY = 65559, //!< Not found, no entry (fs) [ENOENT]. + ERROR_NO_MEDIA = 65560, //!< No media in drive/device [ENOMEDIUM]. + ERROR_NO_MORE_DATA = 65561, //!< No more data / end of file [ENODATA]. + ERROR_NO_MORE_FILES = 65562, //!< No more files [ENMFILE]. + ERROR_NO_SPACE_LEFT = 65563, //!< No space left on device [ENOSPC]. + ERROR_NOT_EMPTY = 65564, //!< Directory is not empty [ENOTEMPTY]. + ERROR_NOT_FILE = 65565, //!< Not a file [EISDIR]. + ERROR_NOT_DIRECTORY = 65566, //!< Not a directory [ENOTDIR]. + ERROR_NOT_SAME_DEVICE = 65567, //!< Not same device [EXDEV]. + ERROR_NOT_BLOCK_DEVICE = 65568, //!< Not a block device [ENOTBLK]. + ERROR_INVALID_FILE_NAME = 65569, //!< File/path name is invalid [n/a]. + ERROR_FILE_NAME_TOO_LONG = 65570, //!< File/path name is too long [ENAMETOOLONG]. + ERROR_TOO_MANY_OPEN_FILES = 65571, //!< Too many open files [EMFILE]. + ERROR_TOO_MANY_OPEN_FILES_BY_OS = 65572, //!< Too many open files by OS [ENFILE]. + ERROR_TOO_MANY_LINKS = 65573, //!< Too many symbolic links on FS [EMLINK]. + ERROR_TOO_MANY_THREADS = 65574, //!< Too many threads [EAGAIN]. + ERROR_THREAD_POOL_EXHAUSTED = 65575, //!< Thread pool is exhausted and couldn't acquire the requested thread count. + ERROR_FILE_EMPTY = 65576, //!< File is empty (not specific to any OS error). + ERROR_OPEN_FAILED = 65577, //!< File open failed [Windows::ERROR_OPEN_FAILED]. + ERROR_NOT_ROOT_DEVICE = 65578, //!< Not a root device/directory [Windows::ERROR_DIR_NOT_ROOT]. + ERROR_UNKNOWN_SYSTEM_ERROR = 65579, //!< Unknown system error that failed to translate to Blend2D result code. + ERROR_INVALID_ALIGNMENT = 65580, //!< Invalid data alignment. + ERROR_INVALID_SIGNATURE = 65581, //!< Invalid data signature or header. + ERROR_INVALID_DATA = 65582, //!< Invalid or corrupted data. + ERROR_INVALID_STRING = 65583, //!< Invalid string (invalid data of either UTF8, UTF16, or UTF32). + ERROR_INVALID_KEY = 65584, //!< Invalid key or property. + ERROR_DATA_TRUNCATED = 65585, //!< Truncated data (more data required than memory/stream provides). + ERROR_DATA_TOO_LARGE = 65586, //!< Input data too large to be processed. + ERROR_DECOMPRESSION_FAILED = 65587, //!< Decompression failed due to invalid data (RLE, Huffman, etc). + ERROR_INVALID_GEOMETRY = 65588, //!< Invalid geometry (invalid path data or shape). + ERROR_NO_MATCHING_VERTEX = 65589, //!< Returned when there is no matching vertex in path data. + ERROR_INVALID_CREATE_FLAGS = 65590, //!< Invalid create flags (BLContext). + ERROR_NO_MATCHING_COOKIE = 65591, //!< No matching cookie (BLContext). + ERROR_NO_STATES_TO_RESTORE = 65592, //!< No states to restore (BLContext). + ERROR_TOO_MANY_SAVED_STATES = 65593, //!< Cannot save state as the number of saved states reached the limit (BLContext). + ERROR_IMAGE_TOO_LARGE = 65594, //!< The size of the image is too large. + ERROR_IMAGE_NO_MATCHING_CODEC = 65595, //!< Image codec for a required format doesn't exist. + ERROR_IMAGE_UNKNOWN_FILE_FORMAT = 65596, //!< Unknown or invalid file format that cannot be read. + ERROR_IMAGE_DECODER_NOT_PROVIDED = 65597, //!< Image codec doesn't support reading the file format. + ERROR_IMAGE_ENCODER_NOT_PROVIDED = 65598, //!< Image codec doesn't support writing the file format. + ERROR_PNG_MULTIPLE_IHDR = 65599, //!< Multiple IHDR chunks are not allowed (PNG). + ERROR_PNG_INVALID_IDAT = 65600, //!< Invalid IDAT chunk (PNG). + ERROR_PNG_INVALID_IEND = 65601, //!< Invalid IEND chunk (PNG). + ERROR_PNG_INVALID_PLTE = 65602, //!< Invalid PLTE chunk (PNG). + ERROR_PNG_INVALID_TRNS = 65603, //!< Invalid tRNS chunk (PNG). + ERROR_PNG_INVALID_FILTER = 65604, //!< Invalid filter type (PNG). + ERROR_JPEG_UNSUPPORTED_FEATURE = 65605, //!< Unsupported feature (JPEG). + ERROR_JPEG_INVALID_SOS = 65606, //!< Invalid SOS marker or header (JPEG). + ERROR_JPEG_INVALID_SOF = 65607, //!< Invalid SOF marker (JPEG). + ERROR_JPEG_MULTIPLE_SOF = 65608, //!< Multiple SOF markers (JPEG). + ERROR_JPEG_UNSUPPORTED_SOF = 65609, //!< Unsupported SOF marker (JPEG). + ERROR_FONT_NOT_INITIALIZED = 65610, //!< Font doesn't have any data as it's not initialized. + ERROR_FONT_NO_MATCH = 65611, //!< Font or font face was not matched (BLFontManager). + ERROR_FONT_NO_CHARACTER_MAPPING = 65612, //!< Font has no character to glyph mapping data. + ERROR_FONT_MISSING_IMPORTANT_TABLE = 65613, //!< Font has missing an important table. + ERROR_FONT_FEATURE_NOT_AVAILABLE = 65614, //!< Font feature is not available. + ERROR_FONT_CFF_INVALID_DATA = 65615, //!< Font has an invalid CFF data. + ERROR_FONT_PROGRAM_TERMINATED = 65616, //!< Font program terminated because the execution reached the limit. + ERROR_GLYPH_SUBSTITUTION_TOO_LARGE = 65617, //!< Glyph substitution requires too much space and was terminated. + ERROR_INVALID_GLYPH = 65618, //!< Invalid glyph identifier. + ERROR_FORCE_UINT = 4294967295, +} + +//! \ingroup bl_globals +//! +//! Byte order. +ByteOrder :: enum u32 { + //! Little endian byte-order. + LE = 0, + + //! Big endian byte-order. + BE = 1, + + //! Native (host) byte-order. + NATIVE = 0, + + //! Swapped byte-order (BE if host is LE and vice versa). + SWAPPED = 1, + FORCE_UINT = 4294967295, +} + +//! \ingroup bl_globals +//! +//! Data access flags. +DataAccessFlags :: enum u32 { + //! No data access flags. + NO_FLAGS = 0, + + //! Read access. + READ = 1, + + //! Write access. + WRITE = 2, + + //! Read and write access. + RW = 3, + FORCE_UINT = 4294967295, +} + +//! \ingroup bl_globals +//! +//! Data source type. +DataSourceType :: enum u32 { + //! No data source. + NONE = 0, + + //! Memory data source. + MEMORY = 1, + + //! File data source. + FILE = 2, + + //! Custom data source. + CUSTOM = 3, + + //! Maximum value `BLDataSourceType`. + MAX_VALUE = 3, + FORCE_UINT = 4294967295, +} + +//! \ingroup bl_globals +//! +//! Modification operation applied to Blend2D containers. +ModifyOp :: enum u32 { + //! Assign operation, which reserves space only to fit the requested input. + ASSIGN_FIT = 0, + + //! Assign operation, which takes into consideration successive appends. + ASSIGN_GROW = 1, + + //! Append operation, which reserves space only to fit the current and appended content. + APPEND_FIT = 2, + + //! Append operation, which takes into consideration successive appends. + APPEND_GROW = 3, + + //! Maximum value of `BLModifyOp`. + MAX_VALUE = 3, + FORCE_UINT = 4294967295, +} + +//! \ingroup bl_globals +//! +//! Boolean operator. +BooleanOp :: enum u32 { + //! Result = B. + COPY = 0, + + //! Result = A & B. + AND = 1, + + //! Result = A | B. + OR = 2, + + //! Result = A ^ B. + XOR = 3, + + //! Result = A & ~B. + AND_NOT = 4, + + //! Result = ~A & B. + NOT_AND = 5, + + //! Maximum value of `BLBooleanOp`. + MAX_VALUE = 5, + FORCE_UINT = 4294967295, +} + +//! \ingroup bl_styling +//! +//! Extend mode. +ExtendMode :: enum u32 { + //! Pad extend [default]. + PAD = 0, + + //! Repeat extend. + REPEAT = 1, + + //! Reflect extend. + REFLECT = 2, + + //! Alias of `BL_EXTEND_MODE_PAD`. + PAD_X_PAD_Y = 0, + + //! Pad X and repeat Y. + PAD_X_REPEAT_Y = 3, + + //! Pad X and reflect Y. + PAD_X_REFLECT_Y = 4, + + //! Alias of `BL_EXTEND_MODE_REPEAT`. + REPEAT_X_REPEAT_Y = 1, + + //! Repeat X and pad Y. + REPEAT_X_PAD_Y = 5, + + //! Repeat X and reflect Y. + REPEAT_X_REFLECT_Y = 6, + + //! Alias of `BL_EXTEND_MODE_REFLECT`. + REFLECT_X_REFLECT_Y = 2, + + //! Reflect X and pad Y. + REFLECT_X_PAD_Y = 7, + + //! Reflect X and repeat Y. + REFLECT_X_REPEAT_Y = 8, + + //! Count of simple extend modes (that use the same value for X and Y). + SIMPLE_MAX_VALUE = 2, + + //! Count of complex extend modes (that can use independent values for X and Y). + COMPLEX_MAX_VALUE = 8, + + //! Maximum value of `BLExtendMode`. + MAX_VALUE = 8, + FORCE_UINT = 4294967295, +} + +//! \ingroup bl_text +//! +//! Text encoding. +TextEncoding :: enum u32 { + //! UTF-8 encoding. + UTF8 = 0, + + //! UTF-16 encoding (native endian). + UTF16 = 1, + + //! UTF-32 encoding (native endian). + UTF32 = 2, + + //! LATIN1 encoding (one byte per character). + 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)`. + WCHAR = 2, + + //! Maximum value of `BLTextEncoding`. + MAX_VALUE = 3, + FORCE_UINT = 4294967295, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! This function is called by Blend2D when an internal assertion failure happens. + //! + //! Failing an assertion means that there is either a bug in Blend2D or in user code that uses Blend2D and that the + //! state of the application is already corrupted and thus irrecoverable. Note that this would be a fatal error if + //! this function gets called in production. + runtime_assertion_failure :: proc(file: cstring, line: i32, msg: cstring) --- +} + +//! 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 \ref BLString, \ref BLArray, \ref BLGradient, \ref BLPath, etc... +Range :: struct { + start: c.size_t, + end: c.size_t, +} + +ArrayView :: struct { + data: rawptr, + size: c.size_t, +} + +StringView :: struct { + data: cstring, + size: c.size_t, +} + +DataView :: ArrayView + diff --git a/binding/array.odin b/binding/array.odin @@ -0,0 +1,88 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Array container [C API]. +ArrayCore :: struct { + _d: ObjectDetail, +} + +//! \cond INTERNAL +//! Array container [C API Impl]. +ArrayImpl :: struct { + //! Pointer to array data. + data: rawptr, + + //! Array size [in items]. + size: c.size_t, + + //! Array capacity [in items]. + capacity: c.size_t, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \endcond + array_init :: proc(self: ^ArrayCore, array_type: ObjectType) -> Result --- + array_init_move :: proc(self: ^ArrayCore, other: ^ArrayCore) -> Result --- + array_init_weak :: proc(self: ^ArrayCore, other: ^ArrayCore) -> Result --- + array_destroy :: proc(self: ^ArrayCore) -> Result --- + array_reset :: proc(self: ^ArrayCore) -> Result --- + array_get_size :: proc(self: ^ArrayCore) -> c.size_t --- + array_get_capacity :: proc(self: ^ArrayCore) -> c.size_t --- + array_get_item_size :: proc(self: ^ArrayCore) -> c.size_t --- + array_get_data :: proc(self: ^ArrayCore) -> rawptr --- + array_clear :: proc(self: ^ArrayCore) -> Result --- + array_shrink :: proc(self: ^ArrayCore) -> Result --- + array_reserve :: proc(self: ^ArrayCore, n: c.size_t) -> Result --- + array_resize :: proc(self: ^ArrayCore, n: c.size_t, fill: rawptr) -> Result --- + array_make_mutable :: proc(self: ^ArrayCore, data_out: ^rawptr) -> Result --- + array_modify_op :: proc(self: ^ArrayCore, op: ModifyOp, n: c.size_t, data_out: ^rawptr) -> Result --- + array_insert_op :: proc(self: ^ArrayCore, index: c.size_t, n: c.size_t, data_out: ^rawptr) -> Result --- + array_assign_move :: proc(self: ^ArrayCore, other: ^ArrayCore) -> Result --- + array_assign_weak :: proc(self: ^ArrayCore, other: ^ArrayCore) -> Result --- + array_assign_deep :: proc(self: ^ArrayCore, other: ^ArrayCore) -> Result --- + array_assign_data :: proc(self: ^ArrayCore, data: rawptr, n: c.size_t) -> Result --- + array_assign_external_data :: proc(self: ^ArrayCore, data: rawptr, size: c.size_t, capacity: c.size_t, data_access_flags: DataAccessFlags, destroy_func: DestroyExternalDataFunc, user_data: rawptr) -> Result --- + array_append_u8 :: proc(self: ^ArrayCore, value: u8) -> Result --- + array_append_u16 :: proc(self: ^ArrayCore, value: u16) -> Result --- + array_append_u32 :: proc(self: ^ArrayCore, value: u32) -> Result --- + array_append_u64 :: proc(self: ^ArrayCore, value: u64) -> Result --- + array_append_f32 :: proc(self: ^ArrayCore, value: f32) -> Result --- + array_append_f64 :: proc(self: ^ArrayCore, value: f64) -> Result --- + array_append_item :: proc(self: ^ArrayCore, item: rawptr) -> Result --- + array_append_data :: proc(self: ^ArrayCore, data: rawptr, n: c.size_t) -> Result --- + array_insert_u8 :: proc(self: ^ArrayCore, index: c.size_t, value: u8) -> Result --- + array_insert_u16 :: proc(self: ^ArrayCore, index: c.size_t, value: u16) -> Result --- + array_insert_u32 :: proc(self: ^ArrayCore, index: c.size_t, value: u32) -> Result --- + array_insert_u64 :: proc(self: ^ArrayCore, index: c.size_t, value: u64) -> Result --- + array_insert_f32 :: proc(self: ^ArrayCore, index: c.size_t, value: f32) -> Result --- + array_insert_f64 :: proc(self: ^ArrayCore, index: c.size_t, value: f64) -> Result --- + array_insert_item :: proc(self: ^ArrayCore, index: c.size_t, item: rawptr) -> Result --- + array_insert_data :: proc(self: ^ArrayCore, index: c.size_t, data: rawptr, n: c.size_t) -> Result --- + array_replace_u8 :: proc(self: ^ArrayCore, index: c.size_t, value: u8) -> Result --- + array_replace_u16 :: proc(self: ^ArrayCore, index: c.size_t, value: u16) -> Result --- + array_replace_u32 :: proc(self: ^ArrayCore, index: c.size_t, value: u32) -> Result --- + array_replace_u64 :: proc(self: ^ArrayCore, index: c.size_t, value: u64) -> Result --- + array_replace_f32 :: proc(self: ^ArrayCore, index: c.size_t, value: f32) -> Result --- + array_replace_f64 :: proc(self: ^ArrayCore, index: c.size_t, value: f64) -> Result --- + array_replace_item :: proc(self: ^ArrayCore, index: c.size_t, item: rawptr) -> Result --- + array_replace_data :: proc(self: ^ArrayCore, r_start: c.size_t, r_end: c.size_t, data: rawptr, n: c.size_t) -> Result --- + array_remove_index :: proc(self: ^ArrayCore, index: c.size_t) -> Result --- + array_remove_range :: proc(self: ^ArrayCore, r_start: c.size_t, r_end: c.size_t) -> Result --- + array_equals :: proc(a: ^ArrayCore, b: ^ArrayCore) -> i32 --- +} + diff --git a/binding/bitarray.odin b/binding/bitarray.odin @@ -0,0 +1,75 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! BitArray container [C API]. +BitArrayCore :: struct { + _d: ObjectDetail, +} + +//! \cond INTERNAL +//! BitArray container [C API Impl]. +BitArrayImpl :: struct { + //! Size in bit units. + size: u32, + + //! Capacity in bit-word units. + capacity: u32, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \endcond + bit_array_init :: proc(self: ^BitArrayCore) -> Result --- + bit_array_init_move :: proc(self: ^BitArrayCore, other: ^BitArrayCore) -> Result --- + bit_array_init_weak :: proc(self: ^BitArrayCore, other: ^BitArrayCore) -> Result --- + bit_array_destroy :: proc(self: ^BitArrayCore) -> Result --- + bit_array_reset :: proc(self: ^BitArrayCore) -> Result --- + bit_array_assign_move :: proc(self: ^BitArrayCore, other: ^BitArrayCore) -> Result --- + bit_array_assign_weak :: proc(self: ^BitArrayCore, other: ^BitArrayCore) -> Result --- + bit_array_assign_words :: proc(self: ^BitArrayCore, word_data: ^u32, word_count: u32) -> Result --- + bit_array_is_empty :: proc(self: ^BitArrayCore) -> i32 --- + bit_array_get_size :: proc(self: ^BitArrayCore) -> u32 --- + bit_array_get_word_count :: proc(self: ^BitArrayCore) -> u32 --- + bit_array_get_capacity :: proc(self: ^BitArrayCore) -> u32 --- + bit_array_get_data :: proc(self: ^BitArrayCore) -> ^u32 --- + bit_array_get_cardinality :: proc(self: ^BitArrayCore) -> u32 --- + bit_array_get_cardinality_in_range :: proc(self: ^BitArrayCore, start_bit: u32, end_bit: u32) -> u32 --- + bit_array_has_bit :: proc(self: ^BitArrayCore, bit_index: u32) -> i32 --- + bit_array_has_bits_in_range :: proc(self: ^BitArrayCore, start_bit: u32, end_bit: u32) -> i32 --- + bit_array_subsumes :: proc(a: ^BitArrayCore, b: ^BitArrayCore) -> i32 --- + bit_array_intersects :: proc(a: ^BitArrayCore, b: ^BitArrayCore) -> i32 --- + bit_array_get_range :: proc(self: ^BitArrayCore, start_out: ^u32, end_out: ^u32) -> i32 --- + bit_array_equals :: proc(a: ^BitArrayCore, b: ^BitArrayCore) -> i32 --- + bit_array_compare :: proc(a: ^BitArrayCore, b: ^BitArrayCore) -> i32 --- + bit_array_clear :: proc(self: ^BitArrayCore) -> Result --- + bit_array_resize :: proc(self: ^BitArrayCore, n_bits: u32) -> Result --- + bit_array_reserve :: proc(self: ^BitArrayCore, n_bits: u32) -> Result --- + bit_array_shrink :: proc(self: ^BitArrayCore) -> Result --- + bit_array_set_bit :: proc(self: ^BitArrayCore, bit_index: u32) -> Result --- + bit_array_fill_range :: proc(self: ^BitArrayCore, start_bit: u32, end_bit: u32) -> Result --- + bit_array_fill_words :: proc(self: ^BitArrayCore, bit_index: u32, word_data: ^u32, word_count: u32) -> Result --- + bit_array_clear_bit :: proc(self: ^BitArrayCore, bit_index: u32) -> Result --- + bit_array_clear_range :: proc(self: ^BitArrayCore, start_bit: u32, end_bit: u32) -> Result --- + bit_array_clear_word :: proc(self: ^BitArrayCore, bit_index: u32, word_value: u32) -> Result --- + bit_array_clear_words :: proc(self: ^BitArrayCore, bit_index: u32, word_data: ^u32, word_count: u32) -> Result --- + bit_array_replace_op :: proc(self: ^BitArrayCore, n_bits: u32, data_out: ^^u32) -> Result --- + bit_array_replace_bit :: proc(self: ^BitArrayCore, bit_index: u32, bit_value: i32) -> Result --- + bit_array_replace_word :: proc(self: ^BitArrayCore, bit_index: u32, word_value: u32) -> Result --- + bit_array_replace_words :: proc(self: ^BitArrayCore, bit_index: u32, word_data: ^u32, word_count: u32) -> Result --- + bit_array_append_bit :: proc(self: ^BitArrayCore, bit_value: i32) -> Result --- + bit_array_append_word :: proc(self: ^BitArrayCore, word_value: u32) -> Result --- + bit_array_append_words :: proc(self: ^BitArrayCore, word_data: ^u32, word_count: u32) -> Result --- +} + diff --git a/binding/bitset.odin b/binding/bitset.odin @@ -0,0 +1,121 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! \name BLBitSet - Constants +//! \{ +BitSetConstants :: enum u32 { + //! Invalid bit-index. + //! + //! This is the only index that cannot be stored in `BLBitSet`. + INVALID_INDEX = 4294967295, + + //! Range mask used by `BLBitsetSegment::start` value - if set the segment is a range of all ones. + RANGE_MASK = 2147483648, + + //! Number of words in a BLBitSetSegment. + SEGMENT_WORD_COUNT = 4, +} + +//! BitSet segment. +//! +//! Segment provides either a dense set of bits starting at `start` or a range of bits all set to one. The start of +//! the segment is always aligned to segment size, which can be calculated as `32 * BL_BIT_SET_SEGMENT_WORD_COUNT`. +//! Even ranges are aligned to this value, thus up to 3 segments are used to describe a range that doesn't start/end +//! at the segment boundary. +//! +//! When the segment describes dense bits its size is always fixed and represents `32 * BL_BIT_SET_SEGMENT_WORD_COUNT` +//! bits, which is currently 128 bits. However, when the segment describes all ones, the first value in data `data[0]` +//! describes the last bit of the range, which means that an arbitrary range can be encoded within a single segment. +BitSetSegment :: struct { + _start_word: u32, + _data: [4]u32, +} + +//! BitSet data view. +BitSetData :: struct { + segment_data: ^BitSetSegment, + segment_count: u32, + sso_segments: [3]BitSetSegment, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \name BLBitSet - C API + //! \{ + bit_set_init :: proc(self: ^BitSetCore) -> Result --- + bit_set_init_move :: proc(self: ^BitSetCore, other: ^BitSetCore) -> Result --- + bit_set_init_weak :: proc(self: ^BitSetCore, other: ^BitSetCore) -> Result --- + bit_set_init_range :: proc(self: ^BitSetCore, start_bit: u32, end_bit: u32) -> Result --- + bit_set_destroy :: proc(self: ^BitSetCore) -> Result --- + bit_set_reset :: proc(self: ^BitSetCore) -> Result --- + bit_set_assign_move :: proc(self: ^BitSetCore, other: ^BitSetCore) -> Result --- + bit_set_assign_weak :: proc(self: ^BitSetCore, other: ^BitSetCore) -> Result --- + bit_set_assign_deep :: proc(self: ^BitSetCore, other: ^BitSetCore) -> Result --- + bit_set_assign_range :: proc(self: ^BitSetCore, start_bit: u32, end_bit: u32) -> Result --- + bit_set_assign_words :: proc(self: ^BitSetCore, start_word: u32, word_data: ^u32, word_count: u32) -> Result --- + bit_set_is_empty :: proc(self: ^BitSetCore) -> i32 --- + bit_set_get_data :: proc(self: ^BitSetCore, out: ^BitSetData) -> Result --- + bit_set_get_segment_count :: proc(self: ^BitSetCore) -> u32 --- + bit_set_get_segment_capacity :: proc(self: ^BitSetCore) -> u32 --- + bit_set_get_cardinality :: proc(self: ^BitSetCore) -> u32 --- + bit_set_get_cardinality_in_range :: proc(self: ^BitSetCore, start_bit: u32, end_bit: u32) -> u32 --- + bit_set_has_bit :: proc(self: ^BitSetCore, bit_index: u32) -> i32 --- + bit_set_has_bits_in_range :: proc(self: ^BitSetCore, start_bit: u32, end_bit: u32) -> i32 --- + bit_set_subsumes :: proc(a: ^BitSetCore, b: ^BitSetCore) -> i32 --- + bit_set_intersects :: proc(a: ^BitSetCore, b: ^BitSetCore) -> i32 --- + bit_set_get_range :: proc(self: ^BitSetCore, start_out: ^u32, end_out: ^u32) -> i32 --- + bit_set_equals :: proc(a: ^BitSetCore, b: ^BitSetCore) -> i32 --- + bit_set_compare :: proc(a: ^BitSetCore, b: ^BitSetCore) -> i32 --- + bit_set_clear :: proc(self: ^BitSetCore) -> Result --- + bit_set_shrink :: proc(self: ^BitSetCore) -> Result --- + bit_set_optimize :: proc(self: ^BitSetCore) -> Result --- + bit_set_chop :: proc(self: ^BitSetCore, start_bit: u32, end_bit: u32) -> Result --- + bit_set_add_bit :: proc(self: ^BitSetCore, bit_index: u32) -> Result --- + bit_set_add_range :: proc(self: ^BitSetCore, range_start_bit: u32, range_end_bit: u32) -> Result --- + bit_set_add_words :: proc(self: ^BitSetCore, start_word: u32, word_data: ^u32, word_count: u32) -> Result --- + bit_set_clear_bit :: proc(self: ^BitSetCore, bit_index: u32) -> Result --- + bit_set_clear_range :: proc(self: ^BitSetCore, range_start_bit: u32, range_end_bit: u32) -> Result --- + + // TODO: Future API (BitSet). + /* + BL_API BLResult BL_CDECL bl_bit_set_combine(BLBitSetCore* dst, const BLBitSetCore* a, const BLBitSetCore* b, BLBooleanOp boolean_op) BL_NOEXCEPT_C; + */ + bit_set_builder_commit :: proc(self: ^BitSetCore, builder: ^BitSetBuilderCore, new_area_index: u32) -> Result --- + bit_set_builder_add_range :: proc(self: ^BitSetCore, builder: ^BitSetBuilderCore, start_bit: u32, end_bit: u32) -> Result --- +} + +//! BitSet container [C API]. +BitSetCore :: struct { + _d: ObjectDetail, +} + +//! BitSet builder [C API]. +BitSetBuilderCore :: struct { + //! Shift to get `_area_index` from bit index, equals to `log2(kBitCount)`. + _area_shift: u32, + + //! Area index - index from 0...N where each index represents `kBitCount` bits. + _area_index: u32, +} + +//! BitSet container [Impl]. +BitSetImpl :: struct { + //! Count of used segments in `segment_data`. + segment_count: u32, + + //! Count of allocated segments in `segment_data`. + segment_capacity: u32, +} + diff --git a/binding/context.odin b/binding/context.odin @@ -0,0 +1,759 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Rendering context type. +ContextType :: enum u32 { + //! No rendering context. + NONE = 0, + + //! Dummy rendering context. + DUMMY = 1, + + /* + //! Proxy rendering context. + BL_CONTEXT_TYPE_PROXY = 2, + */ + + //! Software-accelerated rendering context. + RASTER = 3, + + //! Maximum value of `BLContextType`. + MAX_VALUE = 3, + FORCE_UINT = 4294967295, +} + +//! Rendering context hint. +ContextHint :: enum u32 { + //! Rendering quality. + RENDERING_QUALITY = 0, + + //! Gradient quality. + GRADIENT_QUALITY = 1, + + //! Pattern quality. + PATTERN_QUALITY = 2, + + //! Maximum value of `BLContextHint`. + MAX_VALUE = 7, + FORCE_UINT = 4294967295, +} + +//! Describes a rendering context style slot - fill or stroke. +ContextStyleSlot :: enum u32 { + //! Fill operation style slot. + FILL = 0, + + //! Stroke operation style slot. + STROKE = 1, + + //! Maximum value of `BLContextStyleSlot` + MAX_VALUE = 1, + FORCE_UINT = 4294967295, +} + +//! The type of a text rendering operation. +//! +//! This value specifies the type of the parameter passed to the text rendering API. +//! +//! \note In most cases this should not be required to use by Blend2D users. The C API provides functions that +//! wrap all of the text operations and C++ API provides functions that use `BLContextRenderTextOp` internally. +ContextRenderTextOp :: enum u32 { + //! UTF-8 text rendering operation - UTF-8 string passed as \ref BLStringView or \ref BLArrayView<uint8_t>. + UTF8 = 0, + + //! UTF-16 text rendering operation - UTF-16 string passed as \ref BLArrayView<uint16_t>. + UTF16 = 1, + + //! UTF-32 text rendering operation - UTF-32 string passed as \ref BLArrayView<uint32_t>. + UTF32 = 2, + + //! LATIN1 text rendering operation - LATIN1 string is passed as \ref BLStringView or \ref BLArrayView<uint8_t>. + LATIN1 = 3, + + //! `wchar_t` text rendering operation - wchar_t string is passed as \ref BLArrayView<wchar_t>. + WCHAR = 2, + + //! Glyph run text rendering operation - the \ref BLGlyphRun parameter is passed. + GLYPH_RUN = 4, + + //! Maximum value of `BLContextRenderTextInputType` + MAX_VALUE = 4, + TYPE_FORCE_UINT = 4294967295, +} + +//! Rendering context flush flags, used by \ref BLContext::flush(). +ContextFlushFlags :: enum u32 { + NO_FLAGS = 0, + + //! Flushes the command queue and waits for its completion (will block until done). + SYNC = 2147483648, + FORCE_UINT = 4294967295, +} + +//! Rendering context creation flags. +ContextCreateFlags :: enum u32 { + //! No flags. + NO_FLAGS = 0, + + //! Disables JIT pipeline generator. + FLAG_DISABLE_JIT = 1, + + //! Fallbacks to a synchronous rendering in case that the rendering engine wasn't able to acquire threads. This + //! flag only makes sense when the asynchronous mode was specified by having `thread_count` greater than 0. If the + //! rendering context fails to acquire at least one thread it would fallback to synchronous mode with no worker + //! threads. + //! + //! \note If this flag is specified with `thread_count == 1` it means to immediately fallback to synchronous + //! rendering. It's only practical to use this flag with 2 or more requested threads. + FLAG_FALLBACK_TO_SYNC = 1048576, + + //! If this flag is specified and asynchronous rendering is enabled then the context would create its own isolated + //! thread-pool, which is useful for debugging purposes. + //! + //! Do not use this flag in production as rendering contexts with isolated thread-pool have to create and destroy all + //! threads they use. This flag is only useful for testing, debugging, and isolated benchmarking. + FLAG_ISOLATED_THREAD_POOL = 16777216, + + //! If this flag is specified and JIT pipeline generation enabled then the rendering context would create its own + //! isolated JIT runtime. which is useful for debugging purposes. This flag will be ignored if JIT pipeline + //! compilation is either not supported or was disabled by other flags. + //! + //! Do not use this flag in production as rendering contexts with isolated JIT runtime do not use global pipeline + //! cache, that's it, after the rendering context is destroyed the JIT runtime is destroyed with it with all + //! compiled pipelines. This flag is only useful for testing, debugging, and isolated benchmarking. + FLAG_ISOLATED_JIT_RUNTIME = 33554432, + + //! Enables logging to stderr of isolated runtime. + //! + //! \note Must be used with \ref BL_CONTEXT_CREATE_FLAG_ISOLATED_JIT_RUNTIME otherwise it would have no effect. + FLAG_ISOLATED_JIT_LOGGING = 67108864, + + //! Override CPU features when creating isolated context. + FLAG_OVERRIDE_CPU_FEATURES = 134217728, + FLAG_FORCE_UINT = 4294967295, +} + +//! Error flags that are accumulated during the rendering context lifetime and that can be queried through +//! \ref BLContext::accumulated_error_flags(). The reason why these flags exist is that errors can happen during +//! asynchronous rendering, and there is no way the user can catch these errors. +ContextErrorFlags :: enum u32 { + //! No flags. + NO_FLAGS = 0, + + //! The rendering context returned or encountered \ref BL_ERROR_INVALID_VALUE, which is mostly related to + //! the function argument handling. It's very likely some argument was wrong when calling \ref BLContext API. + FLAG_INVALID_VALUE = 1, + + //! Invalid state describes something wrong, for example a pipeline compilation error. + FLAG_INVALID_STATE = 2, + + //! The rendering context has encountered invalid geometry. + FLAG_INVALID_GEOMETRY = 4, + + //! The rendering context has encountered invalid glyph. + FLAG_INVALID_GLYPH = 8, + + //! The rendering context has encountered invalid or uninitialized font. + FLAG_INVALID_FONT = 16, + + //! Thread pool was exhausted and couldn't acquire the requested number of threads. + FLAG_THREAD_POOL_EXHAUSTED = 536870912, + + //! Out of memory condition. + FLAG_OUT_OF_MEMORY = 1073741824, + + //! Unknown error, which we don't have flag for. + FLAG_UNKNOWN_ERROR = 2147483648, + FLAG_FORCE_UINT = 4294967295, +} + +//! Specifies the behavior of \ref BLContext::swap_styles() operation. +ContextStyleSwapMode :: enum u32 { + //! Swap only fill and stroke styles without affecting fill and stroke alpha. + STYLES = 0, + + //! Swap both fill and stroke styles and their alpha values. + STYLES_WITH_ALPHA = 1, + + //! Maximum value of `BLContextStyleSwapMode`. + MAX_VALUE = 1, + FORCE_UINT = 4294967295, +} + +//! Specifies how style transformation matrix is combined with the rendering context transformation matrix, used by +//! \ref BLContext::set_style() function. +ContextStyleTransformMode :: enum u32 { + //! Style transformation matrix should be transformed with the rendering context user and meta matrix (default). + //! + //! \note This transformation mode is identical to how user geometry is transformed and it's the default + //! transformation and most likely the behavior expected in most cases. + USER = 0, + + //! Style transformation matrix should be transformed with the rendering context meta matrix. + META = 1, + + //! Style transformation matrix is considered absolute, and is not combined with a rendering context transform. + NONE = 2, + + //! Maximum value of `BLContextStyleTransformMode`. + MAX_VALUE = 2, + FORCE_UINT = 4294967295, +} + +//! Clip mode. +ClipMode :: enum u32 { + //! Clipping to a rectangle that is aligned to the pixel grid. + ALIGNED_RECT = 0, + + //! Clipping to a rectangle that is not aligned to pixel grid. + UNALIGNED_RECT = 1, + + //! Clipping to a non-rectangular area that is defined by using mask. + MASK = 2, + + //! Count of clip modes. + COUNT = 3, + FORCE_UINT = 4294967295, +} + +//! Composition & blending operator. +CompOp :: enum u32 { + //! Source-over [default]. + SRC_OVER = 0, + + //! Source-copy. + SRC_COPY = 1, + + //! Source-in. + SRC_IN = 2, + + //! Source-out. + SRC_OUT = 3, + + //! Source-atop. + SRC_ATOP = 4, + + //! Destination-over. + DST_OVER = 5, + + //! Destination-copy [nop]. + DST_COPY = 6, + + //! Destination-in. + DST_IN = 7, + + //! Destination-out. + DST_OUT = 8, + + //! Destination-atop. + DST_ATOP = 9, + + //! Xor. + XOR = 10, + + //! Clear. + CLEAR = 11, + + //! Plus. + PLUS = 12, + + //! Minus. + MINUS = 13, + + //! Modulate. + MODULATE = 14, + + //! Multiply. + MULTIPLY = 15, + + //! Screen. + SCREEN = 16, + + //! Overlay. + OVERLAY = 17, + + //! Darken. + DARKEN = 18, + + //! Lighten. + LIGHTEN = 19, + + //! Color dodge. + COLOR_DODGE = 20, + + //! Color burn. + COLOR_BURN = 21, + + //! Linear burn. + LINEAR_BURN = 22, + + //! Linear light. + LINEAR_LIGHT = 23, + + //! Pin light. + PIN_LIGHT = 24, + + //! Hard-light. + HARD_LIGHT = 25, + + //! Soft-light. + SOFT_LIGHT = 26, + + //! Difference. + DIFFERENCE = 27, + + //! Exclusion. + EXCLUSION = 28, + + //! Count of composition & blending operators. + MAX_VALUE = 28, + FORCE_UINT = 4294967295, +} + +//! Rendering quality. +RenderingQuality :: enum u32 { + //! Render using anti-aliasing. + ANTIALIAS = 0, + + //! Maximum value of `BLRenderingQuality`. + MAX_VALUE = 0, + FORCE_UINT = 4294967295, +} + +//! Information that can be used to customize the rendering context. +ContextCreateInfo :: struct { + //! Create flags, see \ref BLContextCreateFlags. + flags: u32, + + //! Number of worker threads to use for asynchronous rendering, if non-zero. + //! + //! If `thread_count` is zero it means to initialize the context for synchronous rendering. This means that every + //! operation will take effect immediately. If `thread_count` is `1` it means that the rendering will be asynchronous, + //! but no thread would be acquired from a thread-pool, because the user thread will be used as a worker. And + //! finally, if `thread_count` is greater than `1` then total of `thread_count - 1` threads will be acquired from + //! thread-pool and used as additional workers. + thread_count: u32, + + //! CPU features to use in isolated JIT runtime (if supported), only used when `flags` contains + //! \ref BL_CONTEXT_CREATE_FLAG_OVERRIDE_CPU_FEATURES. + cpu_features: u32, + + //! Maximum number of commands to be queued. + //! + //! If this parameter is zero the queue size will be determined automatically. + //! + //! TODO: To be documented, has no effect at the moment. + command_queue_limit: u32, + + //! Maximum number of saved states. + //! + //! \note Zero value tells the rendering engine to use the default saved state limit, which currently defaults + //! to 4096 states. This option allows to even increase or decrease the limit, depending on the use case. + saved_state_limit: u32, + + //! Pixel origin. + //! + //! Pixel origin is an offset in pixel units that can be used as an origin for fetchers and effects that use a pixel + //! X/Y coordinate in the calculation. One example of using pixel origin is dithering, where it's used to shift the + //! dithering matrix. + pixel_origin: PointI, + + //! Reserved for future use, must be zero. + reserved: [1]u32, +} + +//! Holds an arbitrary 128-bit value (cookie) that can be used to match other cookies. Blend2D uses cookies in places +//! where it allows to "lock" some state that can only be unlocked by a matching cookie. Please don't confuse cookies +//! with a security of any kind, it's just an arbitrary data that must match to proceed with a certain operation. +//! +//! Cookies can be used with \ref BLContext::save() and \ref BLContext::restore() operations. +ContextCookie :: struct { + data: [2]u64, +} + +//! Rendering context hints. +ContextHints :: struct { + using _: struct #raw_union { + using _: struct { + rendering_quality: u8, + gradient_quality: u8, + pattern_quality: u8, + }, + + hints: [8]u8, + }, +} + +//! Rendering context [C API]. +ContextCore :: struct { + _d: ObjectDetail, +} + +//! \cond INTERNAL +//! Rendering context [Virtual Function Table]. +ContextVirt :: struct { + base: ObjectVirtBase, + + // Interface - Most Used Functions + // ------------------------------- + + // NOTE 1: These functions are called directly by the BLContext C++ API (the dispatch is inlined). So in general + // on x86 targets the compiler will generate something like `call [base + offset]` instruction to perform the call. + // We want to have the most used functions first as these would use 8-bit offset instead of 32-bit offset. We have + // space for 12 functions as 8-bit offset is signed (from -128 to 127) and the BLObjectVirt already uses 3 functions. + // + // NOTE 2: On non-X86 platforms such as AArch64 we don't have to worry about offsets as the instruction would be + // encoded in 32-bits regardless of the offset. + apply_transform_op: proc "c" (impl: ^ContextImpl, op_type: TransformOp, op_data: rawptr) -> Result, + fill_rect_i: proc "c" (impl: ^ContextImpl, rect: ^RectI) -> Result, + fill_rect_i_rgba32: proc "c" (impl: ^ContextImpl, rect: ^RectI, rgba32: u32) -> Result, + fill_rect_i_ext: proc "c" (impl: ^ContextImpl, rect: ^RectI, style: ^ObjectCore) -> Result, + fill_rect_d: proc "c" (impl: ^ContextImpl, rect: ^Rect) -> Result, + fill_rect_d_rgba32: proc "c" (impl: ^ContextImpl, rect: ^Rect, rgba32: u32) -> Result, + fill_rect_d_ext: proc "c" (impl: ^ContextImpl, rect: ^Rect, style: ^ObjectCore) -> Result, + fill_path_d: proc "c" (impl: ^ContextImpl, origin: ^Point, path: ^PathCore) -> Result, + fill_path_d_rgba32: proc "c" (impl: ^ContextImpl, origin: ^Point, path: ^PathCore, rgba32: u32) -> Result, + fill_path_d_ext: proc "c" (impl: ^ContextImpl, origin: ^Point, path: ^PathCore, style: ^ObjectCore) -> Result, + blit_image_i: proc "c" (impl: ^ContextImpl, origin: ^PointI, img: ^ImageCore, img_area: ^RectI) -> Result, + blit_scaled_image_i: proc "c" (impl: ^ContextImpl, rect: ^RectI, img: ^ImageCore, img_area: ^RectI) -> Result, + + // Interface + // --------- + flush: proc "c" (impl: ^ContextImpl, flags: ContextFlushFlags) -> Result, + save: proc "c" (impl: ^ContextImpl, cookie: ^ContextCookie) -> Result, + restore: proc "c" (impl: ^ContextImpl, cookie: ^ContextCookie) -> Result, + user_to_meta: proc "c" (impl: ^ContextImpl) -> Result, + set_hint: proc "c" (impl: ^ContextImpl, hint_type: ContextHint, value: u32) -> Result, + set_hints: proc "c" (impl: ^ContextImpl, hints: ^ContextHints) -> Result, + set_flatten_mode: proc "c" (impl: ^ContextImpl, mode: FlattenMode) -> Result, + set_flatten_tolerance: proc "c" (impl: ^ContextImpl, tolerance: f64) -> Result, + set_approximation_options: proc "c" (impl: ^ContextImpl, options: ^ApproximationOptions) -> Result, + get_style: proc "c" (impl: ^ContextImpl, slot: ContextStyleSlot, transformed: i32, style_out: ^VarCore) -> Result, + set_style: proc "c" (impl: ^ContextImpl, slot: ContextStyleSlot, style: ^ObjectCore, transform_mode: ContextStyleTransformMode) -> Result, + set_style_rgba: proc "c" (impl: ^ContextImpl, slot: ContextStyleSlot, rgba: ^Rgba) -> Result, + set_style_rgba32: proc "c" (impl: ^ContextImpl, slot: ContextStyleSlot, rgba32: u32) -> Result, + set_style_rgba64: proc "c" (impl: ^ContextImpl, slot: ContextStyleSlot, rgba64: u64) -> Result, + disable_style: proc "c" (impl: ^ContextImpl, slot: ContextStyleSlot) -> Result, + set_style_alpha: proc "c" (impl: ^ContextImpl, slot: ContextStyleSlot, alpha: f64) -> Result, + swap_styles: proc "c" (impl: ^ContextImpl, mode: ContextStyleSwapMode) -> Result, + set_global_alpha: proc "c" (impl: ^ContextImpl, alpha: f64) -> Result, + set_comp_op: proc "c" (impl: ^ContextImpl, comp_op: CompOp) -> Result, + set_fill_rule: proc "c" (impl: ^ContextImpl, fill_rule: FillRule) -> Result, + set_stroke_width: proc "c" (impl: ^ContextImpl, width: f64) -> Result, + set_stroke_miter_limit: proc "c" (impl: ^ContextImpl, miter_limit: f64) -> Result, + set_stroke_cap: proc "c" (impl: ^ContextImpl, position: StrokeCapPosition, stroke_cap: StrokeCap) -> Result, + set_stroke_caps: proc "c" (impl: ^ContextImpl, stroke_cap: StrokeCap) -> Result, + set_stroke_join: proc "c" (impl: ^ContextImpl, stroke_join: StrokeJoin) -> Result, + set_stroke_dash_offset: proc "c" (impl: ^ContextImpl, dash_offset: f64) -> Result, + set_stroke_dash_array: proc "c" (impl: ^ContextImpl, dash_array: ^ArrayCore) -> Result, + set_stroke_transform_order: proc "c" (impl: ^ContextImpl, transform_order: StrokeTransformOrder) -> Result, + set_stroke_options: proc "c" (impl: ^ContextImpl, options: ^StrokeOptionsCore) -> Result, + clip_to_rect_i: proc "c" (impl: ^ContextImpl, rect: ^RectI) -> Result, + clip_to_rect_d: proc "c" (impl: ^ContextImpl, rect: ^Rect) -> Result, + restore_clipping: proc "c" (impl: ^ContextImpl) -> Result, + clear_all: proc "c" (impl: ^ContextImpl) -> Result, + clear_recti: proc "c" (impl: ^ContextImpl, rect: ^RectI) -> Result, + clear_rectd: proc "c" (impl: ^ContextImpl, rect: ^Rect) -> Result, + fill_all: proc "c" (impl: ^ContextImpl) -> Result, + fill_all_rgba32: proc "c" (impl: ^ContextImpl, rgba32: u32) -> Result, + fill_all_ext: proc "c" (impl: ^ContextImpl, style: ^ObjectCore) -> Result, + fill_geometry: proc "c" (impl: ^ContextImpl, type: GeometryType, data: rawptr) -> Result, + fill_geometry_rgba32: proc "c" (impl: ^ContextImpl, type: GeometryType, data: rawptr, rgba32: u32) -> Result, + fill_geometry_ext: proc "c" (impl: ^ContextImpl, type: GeometryType, data: rawptr, style: ^ObjectCore) -> Result, + fill_text_op_i: proc "c" (self: ^ContextImpl, origin: ^PointI, font: ^FontCore, op: ContextRenderTextOp, data: rawptr) -> Result, + fill_text_op_i_rgba32: proc "c" (self: ^ContextImpl, origin: ^PointI, font: ^FontCore, op: ContextRenderTextOp, data: rawptr, rgba32: u32) -> Result, + fill_text_op_i_ext: proc "c" (self: ^ContextImpl, origin: ^PointI, font: ^FontCore, op: ContextRenderTextOp, data: rawptr, style: ^ObjectCore) -> Result, + fill_text_op_d: proc "c" (self: ^ContextImpl, origin: ^Point, font: ^FontCore, op: ContextRenderTextOp, data: rawptr) -> Result, + fill_text_op_d_rgba32: proc "c" (self: ^ContextImpl, origin: ^Point, font: ^FontCore, op: ContextRenderTextOp, data: rawptr, rgba32: u32) -> Result, + fill_text_op_d_ext: proc "c" (self: ^ContextImpl, origin: ^Point, font: ^FontCore, op: ContextRenderTextOp, data: rawptr, style: ^ObjectCore) -> Result, + fill_mask_i: proc "c" (impl: ^ContextImpl, origin: ^PointI, mask: ^ImageCore, mask_area: ^RectI) -> Result, + fill_mask_i_rgba32: proc "c" (impl: ^ContextImpl, origin: ^PointI, mask: ^ImageCore, mask_area: ^RectI, rgba32: u32) -> Result, + fill_mask_i_ext: proc "c" (impl: ^ContextImpl, origin: ^PointI, mask: ^ImageCore, mask_area: ^RectI, style: ^ObjectCore) -> Result, + fill_mask_d: proc "c" (impl: ^ContextImpl, origin: ^Point, mask: ^ImageCore, mask_area: ^RectI) -> Result, + fill_mask_d_Rgba32: proc "c" (impl: ^ContextImpl, origin: ^Point, mask: ^ImageCore, mask_area: ^RectI, rgba32: u32) -> Result, + fill_mask_d_ext: proc "c" (impl: ^ContextImpl, origin: ^Point, mask: ^ImageCore, mask_area: ^RectI, style: ^ObjectCore) -> Result, + stroke_path_d: proc "c" (impl: ^ContextImpl, origin: ^Point, path: ^PathCore) -> Result, + stroke_path_d_rgba32: proc "c" (impl: ^ContextImpl, origin: ^Point, path: ^PathCore, rgba32: u32) -> Result, + stroke_path_d_ext: proc "c" (impl: ^ContextImpl, origin: ^Point, path: ^PathCore, style: ^ObjectCore) -> Result, + stroke_geometry: proc "c" (impl: ^ContextImpl, type: GeometryType, data: rawptr) -> Result, + stroke_geometry_rgba32: proc "c" (impl: ^ContextImpl, type: GeometryType, data: rawptr, rgba32: u32) -> Result, + stroke_geometry_ext: proc "c" (impl: ^ContextImpl, type: GeometryType, data: rawptr, style: ^ObjectCore) -> Result, + stroke_text_op_i: proc "c" (self: ^ContextImpl, origin: ^PointI, font: ^FontCore, op: ContextRenderTextOp, data: rawptr) -> Result, + stroke_text_op_i_rgba32: proc "c" (self: ^ContextImpl, origin: ^PointI, font: ^FontCore, op: ContextRenderTextOp, data: rawptr, rgba32: u32) -> Result, + stroke_text_op_i_ext: proc "c" (self: ^ContextImpl, origin: ^PointI, font: ^FontCore, op: ContextRenderTextOp, data: rawptr, style: ^ObjectCore) -> Result, + stroke_text_op_d: proc "c" (self: ^ContextImpl, origin: ^Point, font: ^FontCore, op: ContextRenderTextOp, data: rawptr) -> Result, + stroke_text_op_d_rgba32: proc "c" (self: ^ContextImpl, origin: ^Point, font: ^FontCore, op: ContextRenderTextOp, data: rawptr, rgba32: u32) -> Result, + stroke_text_op_d_ext: proc "c" (self: ^ContextImpl, origin: ^Point, font: ^FontCore, op: ContextRenderTextOp, data: rawptr, style: ^ObjectCore) -> Result, + blit_image_d: proc "c" (impl: ^ContextImpl, origin: ^Point, img: ^ImageCore, img_area: ^RectI) -> Result, + blit_scaled_image_d: proc "c" (impl: ^ContextImpl, rect: ^Rect, img: ^ImageCore, img_area: ^RectI) -> Result, +} + +//! Rendering context state. +//! +//! This state is not meant to be created by users, it's only provided for users that want to introspect +//! the rendering context state and for C++ API that accesses it directly for performance reasons. +ContextState :: struct { + //! Target image or image object with nullptr impl in case that the rendering context doesn't render to an image. + target_image: ^ImageCore, + + //! Current size of the target in abstract units, pixels if rendering to \ref BLImage. + target_size: Size, + + //! Current rendering context hints. + hints: ContextHints, + + //! Current composition operator. + comp_op: u8, + + //! Current fill rule. + fill_rule: u8, + + //! Current type of a style object of fill and stroke operations indexed by \ref BLContextStyleSlot. + style_type: [2]u8, + + //! Count of saved states in the context. + saved_state_count: u32, + + //! Current global alpha value [0, 1]. + global_alpha: f64, + + //! Current fill or stroke alpha indexed by style slot, see \ref BLContextStyleSlot. + style_alpha: [2]f64, + + //! Current stroke options. + stroke_options: StrokeOptionsCore, + + //! Current approximation options. + approximation_options: ApproximationOptions, + + //! Current meta transformation matrix. + meta_transform: Matrix2D, + + //! Current user transformation matrix. + user_transform: Matrix2D, + + //! Current final transformation matrix, which combines all transformation matrices. + final_transform: Matrix2D, +} + +//! Rendering context [C API Impl]. +ContextImpl :: struct { + //! Virtual function table. + virt: ^ContextVirt, + + //! Current state of the context. + state: ^ContextState, + + //! Type of the rendering context, see \ref BLContextType. + context_type: u32, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \endcond + context_init :: proc(self: ^ContextCore) -> Result --- + context_init_move :: proc(self: ^ContextCore, other: ^ContextCore) -> Result --- + context_init_weak :: proc(self: ^ContextCore, other: ^ContextCore) -> Result --- + context_init_as :: proc(self: ^ContextCore, image: ^ImageCore, cci: ^ContextCreateInfo) -> Result --- + context_destroy :: proc(self: ^ContextCore) -> Result --- + context_reset :: proc(self: ^ContextCore) -> Result --- + context_assign_move :: proc(self: ^ContextCore, other: ^ContextCore) -> Result --- + context_assign_weak :: proc(self: ^ContextCore, other: ^ContextCore) -> Result --- + context_get_type :: proc(self: ^ContextCore) -> ContextType --- + context_get_target_size :: proc(self: ^ContextCore, target_size_out: ^Size) -> Result --- + context_get_target_image :: proc(self: ^ContextCore) -> ^ImageCore --- + context_begin :: proc(self: ^ContextCore, image: ^ImageCore, cci: ^ContextCreateInfo) -> Result --- + context_end :: proc(self: ^ContextCore) -> Result --- + context_flush :: proc(self: ^ContextCore, flags: ContextFlushFlags) -> Result --- + context_save :: proc(self: ^ContextCore, cookie: ^ContextCookie) -> Result --- + context_restore :: proc(self: ^ContextCore, cookie: ^ContextCookie) -> Result --- + context_get_meta_transform :: proc(self: ^ContextCore, transform_out: ^Matrix2D) -> Result --- + context_get_user_transform :: proc(self: ^ContextCore, transform_out: ^Matrix2D) -> Result --- + context_get_final_transform :: proc(self: ^ContextCore, transform_out: ^Matrix2D) -> Result --- + context_user_to_meta :: proc(self: ^ContextCore) -> Result --- + context_apply_transform_op :: proc(self: ^ContextCore, op_type: TransformOp, op_data: rawptr) -> Result --- + context_get_hint :: proc(self: ^ContextCore, hint_type: ContextHint) -> u32 --- + context_set_hint :: proc(self: ^ContextCore, hint_type: ContextHint, value: u32) -> Result --- + context_get_hints :: proc(self: ^ContextCore, hints_out: ^ContextHints) -> Result --- + context_set_hints :: proc(self: ^ContextCore, hints: ^ContextHints) -> Result --- + context_set_flatten_mode :: proc(self: ^ContextCore, mode: FlattenMode) -> Result --- + context_set_flatten_tolerance :: proc(self: ^ContextCore, tolerance: f64) -> Result --- + context_set_approximation_options :: proc(self: ^ContextCore, options: ^ApproximationOptions) -> Result --- + context_get_fill_style :: proc(self: ^ContextCore, style_out: ^VarCore) -> Result --- + context_get_transformed_fill_style :: proc(self: ^ContextCore, style_out: ^VarCore) -> Result --- + context_set_fill_style :: proc(self: ^ContextCore, style: ^Unknown) -> Result --- + context_set_fill_style_with_mode :: proc(self: ^ContextCore, style: ^Unknown, transform_mode: ContextStyleTransformMode) -> Result --- + context_set_fill_style_rgba :: proc(self: ^ContextCore, rgba: ^Rgba) -> Result --- + context_set_fill_style_rgba32 :: proc(self: ^ContextCore, rgba32: u32) -> Result --- + context_set_fill_style_rgba64 :: proc(self: ^ContextCore, rgba64: u64) -> Result --- + context_disable_fill_style :: proc(self: ^ContextCore) -> Result --- + context_get_fill_alpha :: proc(self: ^ContextCore) -> f64 --- + context_set_fill_alpha :: proc(self: ^ContextCore, alpha: f64) -> Result --- + context_get_stroke_style :: proc(self: ^ContextCore, style_out: ^VarCore) -> Result --- + context_get_transformed_stroke_style :: proc(self: ^ContextCore, style_out: ^VarCore) -> Result --- + context_set_stroke_style :: proc(self: ^ContextCore, style: ^Unknown) -> Result --- + context_set_stroke_style_with_mode :: proc(self: ^ContextCore, style: ^Unknown, transform_mode: ContextStyleTransformMode) -> Result --- + context_set_stroke_style_rgba :: proc(self: ^ContextCore, rgba: ^Rgba) -> Result --- + context_set_stroke_style_rgba32 :: proc(self: ^ContextCore, rgba32: u32) -> Result --- + context_set_stroke_style_rgba64 :: proc(self: ^ContextCore, rgba64: u64) -> Result --- + context_disable_stroke_style :: proc(self: ^ContextCore) -> Result --- + context_get_stroke_alpha :: proc(self: ^ContextCore) -> f64 --- + context_set_stroke_alpha :: proc(self: ^ContextCore, alpha: f64) -> Result --- + context_swap_styles :: proc(self: ^ContextCore, mode: ContextStyleSwapMode) -> Result --- + context_get_global_alpha :: proc(self: ^ContextCore) -> f64 --- + context_set_global_alpha :: proc(self: ^ContextCore, alpha: f64) -> Result --- + context_get_comp_op :: proc(self: ^ContextCore) -> CompOp --- + context_set_comp_op :: proc(self: ^ContextCore, comp_op: CompOp) -> Result --- + context_get_fill_rule :: proc(self: ^ContextCore) -> FillRule --- + context_set_fill_rule :: proc(self: ^ContextCore, fill_rule: FillRule) -> Result --- + context_get_stroke_width :: proc(self: ^ContextCore) -> f64 --- + context_set_stroke_width :: proc(self: ^ContextCore, width: f64) -> Result --- + context_get_stroke_miter_limit :: proc(self: ^ContextCore) -> f64 --- + context_set_stroke_miter_limit :: proc(self: ^ContextCore, miter_limit: f64) -> Result --- + context_get_stroke_cap :: proc(self: ^ContextCore, position: StrokeCapPosition) -> StrokeCap --- + context_set_stroke_cap :: proc(self: ^ContextCore, position: StrokeCapPosition, stroke_cap: StrokeCap) -> Result --- + context_set_stroke_caps :: proc(self: ^ContextCore, stroke_cap: StrokeCap) -> Result --- + context_get_stroke_join :: proc(self: ^ContextCore) -> StrokeJoin --- + context_set_stroke_join :: proc(self: ^ContextCore, stroke_join: StrokeJoin) -> Result --- + context_get_stroke_transform_order :: proc(self: ^ContextCore) -> StrokeTransformOrder --- + context_set_stroke_transform_order :: proc(self: ^ContextCore, transform_order: StrokeTransformOrder) -> Result --- + context_get_stroke_dash_offset :: proc(self: ^ContextCore) -> f64 --- + context_set_stroke_dash_offset :: proc(self: ^ContextCore, dash_offset: f64) -> Result --- + context_get_stroke_dash_array :: proc(self: ^ContextCore, dash_array_out: ^ArrayCore) -> Result --- + context_set_stroke_dash_array :: proc(self: ^ContextCore, dash_array: ^ArrayCore) -> Result --- + context_get_stroke_options :: proc(self: ^ContextCore, options: ^StrokeOptionsCore) -> Result --- + context_set_stroke_options :: proc(self: ^ContextCore, options: ^StrokeOptionsCore) -> Result --- + context_clip_to_rect_i :: proc(self: ^ContextCore, rect: ^RectI) -> Result --- + context_clip_to_rect_d :: proc(self: ^ContextCore, rect: ^Rect) -> Result --- + context_restore_clipping :: proc(self: ^ContextCore) -> Result --- + context_clear_all :: proc(self: ^ContextCore) -> Result --- + context_clear_rect_i :: proc(self: ^ContextCore, rect: ^RectI) -> Result --- + context_clear_rect_d :: proc(self: ^ContextCore, rect: ^Rect) -> Result --- + context_fill_all :: proc(self: ^ContextCore) -> Result --- + context_fill_all_rgba32 :: proc(self: ^ContextCore, rgba32: u32) -> Result --- + context_fill_all_rgba64 :: proc(self: ^ContextCore, rgba64: u64) -> Result --- + context_fill_all_ext :: proc(self: ^ContextCore, style: ^Unknown) -> Result --- + context_fill_rect_i :: proc(self: ^ContextCore, rect: ^RectI) -> Result --- + context_fill_rect_i_rgba32 :: proc(self: ^ContextCore, rect: ^RectI, rgba32: u32) -> Result --- + context_fill_rect_i_rgba64 :: proc(self: ^ContextCore, rect: ^RectI, rgba64: u64) -> Result --- + context_fill_rect_i_ext :: proc(self: ^ContextCore, rect: ^RectI, style: ^Unknown) -> Result --- + context_fill_rect_d :: proc(self: ^ContextCore, rect: ^Rect) -> Result --- + context_fill_rect_d_rgba32 :: proc(self: ^ContextCore, rect: ^Rect, rgba32: u32) -> Result --- + context_fill_rect_d_rgba64 :: proc(self: ^ContextCore, rect: ^Rect, rgba64: u64) -> Result --- + context_fill_rect_d_ext :: proc(self: ^ContextCore, rect: ^Rect, style: ^Unknown) -> Result --- + context_fill_path_d :: proc(self: ^ContextCore, origin: ^Point, path: ^PathCore) -> Result --- + context_fill_path_d_rgba32 :: proc(self: ^ContextCore, origin: ^Point, path: ^PathCore, rgba32: u32) -> Result --- + context_fill_path_d_rgba64 :: proc(self: ^ContextCore, origin: ^Point, path: ^PathCore, rgba64: u64) -> Result --- + context_fill_path_d_ext :: proc(self: ^ContextCore, origin: ^Point, path: ^PathCore, style: ^Unknown) -> Result --- + context_fill_geometry :: proc(self: ^ContextCore, type: GeometryType, data: rawptr) -> Result --- + context_fill_geometry_rgba32 :: proc(self: ^ContextCore, type: GeometryType, data: rawptr, rgba32: u32) -> Result --- + context_fill_geometry_rgba64 :: proc(self: ^ContextCore, type: GeometryType, data: rawptr, rgba64: u64) -> Result --- + context_fill_geometry_ext :: proc(self: ^ContextCore, type: GeometryType, data: rawptr, style: ^Unknown) -> Result --- + context_fill_utf8_text_i :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: cstring, size: c.size_t) -> Result --- + context_fill_utf8_text_i_rgba32 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: cstring, size: c.size_t, rgba32: u32) -> Result --- + context_fill_utf8_text_i_rgba64 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: cstring, size: c.size_t, rgba64: u64) -> Result --- + context_fill_utf8_text_i_ext :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: cstring, size: c.size_t, style: ^Unknown) -> Result --- + context_fill_utf8_text_d :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: cstring, size: c.size_t) -> Result --- + context_fill_utf8_text_d_rgba32 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: cstring, size: c.size_t, rgba32: u32) -> Result --- + context_fill_utf8_text_d_rgba64 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: cstring, size: c.size_t, rgba64: u64) -> Result --- + context_fill_utf8_text_d_ext :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: cstring, size: c.size_t, style: ^Unknown) -> Result --- + context_fill_utf16_text_i :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u16, size: c.size_t) -> Result --- + context_fill_utf16_text_i_rgba32 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u16, size: c.size_t, rgba32: u32) -> Result --- + context_fill_utf16_text_i_rgba64 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u16, size: c.size_t, rgba64: u64) -> Result --- + context_fill_utf16_text_i_ext :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u16, size: c.size_t, style: ^Unknown) -> Result --- + context_fill_utf16_text_d :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u16, size: c.size_t) -> Result --- + context_fill_utf16_text_d_rgba32 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u16, size: c.size_t, rgba32: u32) -> Result --- + context_fill_utf16_text_d_rgba64 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u16, size: c.size_t, rgba64: u64) -> Result --- + context_fill_utf16_text_d_ext :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u16, size: c.size_t, style: ^Unknown) -> Result --- + context_fill_utf32_text_i :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u32, size: c.size_t) -> Result --- + context_fill_utf32_text_i_rgba32 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u32, size: c.size_t, rgba32: u32) -> Result --- + context_fill_utf32_text_i_rgba64 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u32, size: c.size_t, rgba64: u64) -> Result --- + context_fill_utf32_text_i_ext :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u32, size: c.size_t, style: ^Unknown) -> Result --- + context_fill_utf32_text_d :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u32, size: c.size_t) -> Result --- + context_fill_utf32_text_d_rgba32 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u32, size: c.size_t, rgba32: u32) -> Result --- + context_fill_utf32_text_d_rgba64 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u32, size: c.size_t, rgba64: u64) -> Result --- + context_fill_utf32_text_d_ext :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u32, size: c.size_t, style: ^Unknown) -> Result --- + context_fill_glyph_run_i :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, glyph_run: ^GlyphRun) -> Result --- + context_fill_glyph_run_i_rgba32 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, glyph_run: ^GlyphRun, rgba32: u32) -> Result --- + context_fill_glyph_run_i_rgba64 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, glyph_run: ^GlyphRun, rgba64: u64) -> Result --- + context_fill_glyph_run_i_ext :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, glyph_run: ^GlyphRun, style: ^Unknown) -> Result --- + context_fill_glyph_run_d :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, glyph_run: ^GlyphRun) -> Result --- + context_fill_glyph_run_d_rgba32 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, glyph_run: ^GlyphRun, rgba32: u32) -> Result --- + context_fill_glyph_run_d_rgba64 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, glyph_run: ^GlyphRun, rgba64: u64) -> Result --- + context_fill_glyph_run_d_ext :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, glyph_run: ^GlyphRun, style: ^Unknown) -> Result --- + context_fill_mask_i :: proc(self: ^ContextCore, origin: ^PointI, mask: ^ImageCore, mask_area: ^RectI) -> Result --- + context_fill_mask_i_rgba32 :: proc(self: ^ContextCore, origin: ^PointI, mask: ^ImageCore, mask_area: ^RectI, rgba32: u32) -> Result --- + context_fill_mask_i_rgba64 :: proc(self: ^ContextCore, origin: ^PointI, mask: ^ImageCore, mask_area: ^RectI, rgba64: u64) -> Result --- + context_fill_mask_i_ext :: proc(self: ^ContextCore, origin: ^PointI, mask: ^ImageCore, mask_area: ^RectI, style: ^Unknown) -> Result --- + context_fill_mask_d :: proc(self: ^ContextCore, origin: ^Point, mask: ^ImageCore, mask_area: ^RectI) -> Result --- + context_fill_mask_d_rgba32 :: proc(self: ^ContextCore, origin: ^Point, mask: ^ImageCore, mask_area: ^RectI, rgba32: u32) -> Result --- + context_fill_mask_d_rgba64 :: proc(self: ^ContextCore, origin: ^Point, mask: ^ImageCore, mask_area: ^RectI, rgba64: u64) -> Result --- + context_fill_mask_d_ext :: proc(self: ^ContextCore, origin: ^Point, mask: ^ImageCore, mask_area: ^RectI, style: ^Unknown) -> Result --- + context_stroke_rect_i :: proc(self: ^ContextCore, rect: ^RectI) -> Result --- + context_stroke_rect_i_rgba32 :: proc(self: ^ContextCore, rect: ^RectI, rgba32: u32) -> Result --- + context_stroke_rect_i_rgba64 :: proc(self: ^ContextCore, rect: ^RectI, rgba64: u64) -> Result --- + context_stroke_rect_i_ext :: proc(self: ^ContextCore, rect: ^RectI, style: ^Unknown) -> Result --- + context_stroke_rect_d :: proc(self: ^ContextCore, rect: ^Rect) -> Result --- + context_stroke_rect_d_rgba32 :: proc(self: ^ContextCore, rect: ^Rect, rgba32: u32) -> Result --- + context_stroke_rect_d_rgba64 :: proc(self: ^ContextCore, rect: ^Rect, rgba64: u64) -> Result --- + context_stroke_rect_d_ext :: proc(self: ^ContextCore, rect: ^Rect, style: ^Unknown) -> Result --- + context_stroke_path_d :: proc(self: ^ContextCore, origin: ^Point, path: ^PathCore) -> Result --- + context_stroke_path_d_rgba32 :: proc(self: ^ContextCore, origin: ^Point, path: ^PathCore, rgba32: u32) -> Result --- + context_stroke_path_d_rgba64 :: proc(self: ^ContextCore, origin: ^Point, path: ^PathCore, rgba64: u64) -> Result --- + context_stroke_path_d_ext :: proc(self: ^ContextCore, origin: ^Point, path: ^PathCore, style: ^Unknown) -> Result --- + context_stroke_geometry :: proc(self: ^ContextCore, type: GeometryType, data: rawptr) -> Result --- + context_stroke_geometry_rgba32 :: proc(self: ^ContextCore, type: GeometryType, data: rawptr, rgba32: u32) -> Result --- + context_stroke_geometry_rgba64 :: proc(self: ^ContextCore, type: GeometryType, data: rawptr, rgba64: u64) -> Result --- + context_stroke_geometry_ext :: proc(self: ^ContextCore, type: GeometryType, data: rawptr, style: ^Unknown) -> Result --- + context_stroke_utf8_text_i :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: cstring, size: c.size_t) -> Result --- + context_stroke_utf8_text_i_rgba32 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: cstring, size: c.size_t, rgba32: u32) -> Result --- + context_stroke_utf8_text_i_rgba64 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: cstring, size: c.size_t, rgba64: u64) -> Result --- + context_stroke_utf8_text_i_ext :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: cstring, size: c.size_t, style: ^Unknown) -> Result --- + context_stroke_utf8_text_d :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: cstring, size: c.size_t) -> Result --- + context_stroke_utf8_text_d_rgba32 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: cstring, size: c.size_t, rgba32: u32) -> Result --- + context_stroke_utf8_text_d_rgba64 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: cstring, size: c.size_t, rgba64: u64) -> Result --- + context_stroke_utf8_text_d_ext :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: cstring, size: c.size_t, style: ^Unknown) -> Result --- + context_stroke_utf16_text_i :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u16, size: c.size_t) -> Result --- + context_stroke_utf16_text_i_rgba32 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u16, size: c.size_t, rgba32: u32) -> Result --- + context_stroke_utf16_text_i_rgba64 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u16, size: c.size_t, rgba64: u64) -> Result --- + context_stroke_utf16_text_i_ext :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u16, size: c.size_t, style: ^Unknown) -> Result --- + context_stroke_utf16_text_d :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u16, size: c.size_t) -> Result --- + context_stroke_utf16_text_d_rgba32 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u16, size: c.size_t, rgba32: u32) -> Result --- + context_stroke_utf16_text_d_rgba64 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u16, size: c.size_t, rgba64: u64) -> Result --- + context_stroke_utf16_text_d_ext :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u16, size: c.size_t, style: ^Unknown) -> Result --- + context_stroke_utf32_text_i :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u32, size: c.size_t) -> Result --- + context_stroke_utf32_text_i_rgba32 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u32, size: c.size_t, rgba32: u32) -> Result --- + context_stroke_utf32_text_i_rgba64 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u32, size: c.size_t, rgba64: u64) -> Result --- + context_stroke_utf32_text_i_ext :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, text: ^u32, size: c.size_t, style: ^Unknown) -> Result --- + context_stroke_utf32_text_d :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u32, size: c.size_t) -> Result --- + context_stroke_utf32_text_d_rgba32 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u32, size: c.size_t, rgba32: u32) -> Result --- + context_stroke_utf32_text_d_rgba64 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u32, size: c.size_t, rgba64: u64) -> Result --- + context_stroke_utf32_text_d_ext :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, text: ^u32, size: c.size_t, style: ^Unknown) -> Result --- + context_stroke_glyph_run_i :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, glyph_run: ^GlyphRun) -> Result --- + context_stroke_glyph_run_i_rgba32 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, glyph_run: ^GlyphRun, rgba32: u32) -> Result --- + context_stroke_glyph_run_i_rgba64 :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, glyph_run: ^GlyphRun, rgba64: u64) -> Result --- + context_stroke_glyph_run_i_ext :: proc(self: ^ContextCore, origin: ^PointI, font: ^FontCore, glyph_run: ^GlyphRun, style: ^Unknown) -> Result --- + context_stroke_glyph_run_d :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, glyph_run: ^GlyphRun) -> Result --- + context_stroke_glyph_run_d_rgba32 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, glyph_run: ^GlyphRun, rgba32: u32) -> Result --- + context_stroke_glyph_run_d_rgba64 :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, glyph_run: ^GlyphRun, rgba64: u64) -> Result --- + context_stroke_glyph_run_d_ext :: proc(self: ^ContextCore, origin: ^Point, font: ^FontCore, glyph_run: ^GlyphRun, style: ^Unknown) -> Result --- + context_blit_image_i :: proc(self: ^ContextCore, origin: ^PointI, img: ^ImageCore, img_area: ^RectI) -> Result --- + context_blit_image_d :: proc(self: ^ContextCore, origin: ^Point, img: ^ImageCore, img_area: ^RectI) -> Result --- + context_blit_scaled_image_i :: proc(self: ^ContextCore, rect: ^RectI, img: ^ImageCore, img_area: ^RectI) -> Result --- + context_blit_scaled_image_d :: proc(self: ^ContextCore, rect: ^Rect, img: ^ImageCore, img_area: ^RectI) -> Result --- +} + diff --git a/binding/filesystem.odin b/binding/filesystem.odin @@ -0,0 +1,266 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! File information flags, used by \ref BLFileInfo. +FileInfoFlags :: enum u32 { + //! File owner has read permission (compatible with 0400 octal notation). + OWNER_R = 256, + + //! File owner has write permission (compatible with 0200 octal notation). + OWNER_W = 128, + + //! File owner has execute permission (compatible with 0100 octal notation). + OWNER_X = 64, + + //! A combination of \ref BL_FILE_INFO_OWNER_R, \ref BL_FILE_INFO_OWNER_W, and \ref BL_FILE_INFO_OWNER_X. + OWNER_MASK = 448, + + //! File group owner has read permission (compatible with 040 octal notation). + GROUP_R = 32, + + //! File group owner has write permission (compatible with 020 octal notation). + GROUP_W = 16, + + //! File group owner has execute permission (compatible with 010 octal notation). + GROUP_X = 8, + + //! A combination of \ref BL_FILE_INFO_GROUP_R, \ref BL_FILE_INFO_GROUP_W, and \ref BL_FILE_INFO_GROUP_X. + GROUP_MASK = 56, + + //! Other users have read permission (compatible with 04 octal notation). + OTHER_R = 4, + + //! Other users have write permission (compatible with 02 octal notation). + OTHER_W = 2, + + //! Other users have execute permission (compatible with 01 octal notation). + OTHER_X = 1, + + //! A combination of \ref BL_FILE_INFO_OTHER_R, \ref BL_FILE_INFO_OTHER_W, and \ref BL_FILE_INFO_OTHER_X. + OTHER_MASK = 7, + + //! Set user ID to file owner user ID on execution (compatible with 04000 octal notation). + SUID = 2048, + + //! Set group ID to file's user group ID on execution (compatible with 02000 octal notation). + SGID = 1024, + + //! A combination of all file permission bits. + PERMISSIONS_MASK = 4095, + + //! A flag specifying that this is a regular file. + REGULAR = 65536, + + //! A flag specifying that this is a directory. + DIRECTORY = 131072, + + //! A flag specifying that this is a symbolic link. + SYMLINK = 262144, + + //! A flag describing a character device. + CHAR_DEVICE = 1048576, + + //! A flag describing a block device. + BLOCK_DEVICE = 2097152, + + //! A flag describing a FIFO (named pipe). + FIFO = 4194304, + + //! A flag describing a socket. + SOCKET = 8388608, + + //! A flag describing a hidden file (Windows only). + HIDDEN = 16777216, + + //! A flag describing a hidden file (Windows only). + EXECUTABLE = 33554432, + + //! A flag describing an archive (Windows only). + ARCHIVE = 67108864, + + //! A flag describing a system file (Windows only). + SYSTEM = 134217728, + + //! File information is valid (the request succeeded). + VALID = 2147483648, + FORCE_UINT = 4294967295, +} + +//! File open flags, see \ref BLFile::open(). +FileOpenFlags :: enum u32 { + //! No flags. + NO_FLAGS = 0, + + //! Opens the file for reading. + //! + //! The following system flags are used when opening the file: + //! - `O_RDONLY` (Posix) + //! - `GENERIC_READ` (Windows) + READ = 1, + + //! Opens the file for writing: + //! + //! The following system flags are used when opening the file: + //! - `O_WRONLY` (Posix) + //! - `GENERIC_WRITE` (Windows) + WRITE = 2, + + //! Opens the file for reading & writing. + //! + //! The following system flags are used when opening the file: + //! - `O_RDWR` (Posix) + //! - `GENERIC_READ | GENERIC_WRITE` (Windows) + RW = 3, + + //! Creates the file if it doesn't exist or opens it if it does. + //! + //! The following system flags are used when opening the file: + //! - `O_CREAT` (Posix) + //! - `CREATE_ALWAYS` or `OPEN_ALWAYS` depending on other flags (Windows) + CREATE = 4, + + //! Opens the file for deleting or renaming (Windows). + //! + //! Adds `DELETE` flag when opening the file to `ACCESS_MASK`. + DELETE = 8, + + //! Truncates the file. + //! + //! The following system flags are used when opening the file: + //! - `O_TRUNC` (Posix) + //! - `TRUNCATE_EXISTING` (Windows) + TRUNCATE = 16, + + //! Opens the file for reading in exclusive mode (Windows). + //! + //! Exclusive mode means to not specify the `FILE_SHARE_READ` option. + READ_EXCLUSIVE = 268435456, + + //! Opens the file for writing in exclusive mode (Windows). + //! + //! Exclusive mode means to not specify the `FILE_SHARE_WRITE` option. + WRITE_EXCLUSIVE = 536870912, + + //! Opens the file for both reading and writing (Windows). + //! + //! This is a combination of both `BL_FILE_OPEN_READ_EXCLUSIVE` and `BL_FILE_OPEN_WRITE_EXCLUSIVE`. + RW_EXCLUSIVE = 805306368, + + //! Creates the file in exclusive mode - fails if the file already exists. + //! + //! The following system flags are used when opening the file: + //! - `O_EXCL` (Posix) + //! - `CREATE_NEW` (Windows) + CREATE_EXCLUSIVE = 1073741824, + + //! Opens the file for deleting or renaming in exclusive mode (Windows). + //! + //! Exclusive mode means to not specify the `FILE_SHARE_DELETE` option. + DELETE_EXCLUSIVE = 2147483648, + FORCE_UINT = 4294967295, +} + +//! File seek mode, see \ref BLFile::seek(). +//! +//! \note Seek constants should be compatible with constants used by both POSIX +//! and Windows API. +FileSeekType :: enum u32 { + //! Seek from the beginning of the file (SEEK_SET). + SET = 0, + + //! Seek from the current position (SEEK_CUR). + CUR = 1, + + //! Seek from the end of the file (SEEK_END). + END = 2, + + //! Maximum value of `BLFileSeekType`. + MAX_VALUE = 3, + FORCE_UINT = 4294967295, +} + +//! File read flags used by \ref BLFileSystem::read_file(). +FileReadFlags :: enum u32 { + //! No flags. + NO_FLAGS = 0, + + //! Use memory mapping to read the content of the file. + //! + //! The destination buffer `BLArray<>` would be configured to use the memory mapped buffer instead of allocating its + //! own. + MMAP_ENABLED = 1, + + //! Avoid memory mapping of small files. + //! + //! The size of small file is determined by Blend2D, however, you should expect it to be 16kB or 64kB depending on + //! host operating system. + MMAP_AVOID_SMALL = 2, + + //! Do not fallback to regular read if memory mapping fails. It's worth noting that memory mapping would fail for + //! files stored on filesystem that is not local (like a mounted network filesystem, etc...). + MMAP_NO_FALLBACK = 8, + FORCE_UINT = 4294967295, +} + +//! A thin abstraction over a native OS file IO [C API]. +FileCore :: struct { + //! A file handle - either a file descriptor used by POSIX or file handle used by Windows. On both platforms the + //! handle is always `intptr_t` to make FFI easier (it's basically the size of a pointer / machine register). + //! + //! \note A handle of value `-1` is considered invalid and/or uninitialized. This value also matches Windows API + //! `INVALID_HANDLE_VALUE`, which is also defined to be -1. + handle: c.intptr_t, +} + +//! File information. +FileInfo :: struct { + //! \name Members + //! \{ + size: u64, + modified_time: i64, + flags: FileInfoFlags, + uid: u32, + gid: u32, + reserved: [5]u32, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \name BLFile C API Functions + //! + //! File read/write functionality is provided by \ref BLFileCore in C API and wrapped by \ref BLFile in C++ API. + //! + //! \{ + file_init :: proc(self: ^FileCore) -> Result --- + file_reset :: proc(self: ^FileCore) -> Result --- + file_open :: proc(self: ^FileCore, file_name: cstring, open_flags: FileOpenFlags) -> Result --- + file_close :: proc(self: ^FileCore) -> Result --- + file_seek :: proc(self: ^FileCore, offset: i64, seek_type: FileSeekType, position_out: ^i64) -> Result --- + file_read :: proc(self: ^FileCore, buffer: rawptr, n: c.size_t, bytes_read_out: ^c.size_t) -> Result --- + file_write :: proc(self: ^FileCore, buffer: rawptr, n: c.size_t, bytes_written_out: ^c.size_t) -> Result --- + file_truncate :: proc(self: ^FileCore, max_size: i64) -> Result --- + file_get_info :: proc(self: ^FileCore, info_out: ^FileInfo) -> Result --- + file_get_size :: proc(self: ^FileCore, file_size_out: ^u64) -> Result --- + + //! \name BLFileSystem C API Functions + //! + //! \{ + file_system_get_info :: proc(file_name: cstring, info_out: ^FileInfo) -> Result --- + file_system_read_file :: proc(file_name: cstring, dst: ^ArrayCore, max_size: c.size_t, read_flags: FileReadFlags) -> Result --- + file_system_write_file :: proc(file_name: cstring, data: rawptr, size: c.size_t, bytes_written_out: ^c.size_t) -> Result --- +} + diff --git a/binding/font.odin b/binding/font.odin @@ -0,0 +1,91 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Font [C API]. +FontCore :: struct { + _d: ObjectDetail, +} + +//! \cond INTERNAL +//! Font [C API Impl]. +FontImpl :: struct { + //! Font face used by this font. + face: FontFaceCore, + + //! Font width (1..1000) [0 if the font is not initialized]. + weight: u16, + + //! Font stretch (1..9) [0 if the font is not initialized]. + stretch: u8, + + //! Font style. + style: u8, + + //! Reserved for future use. + reserved: u32, + + //! Font metrics. + metrics: FontMetrics, + + //! Font matrix. + _matrix: FontMatrix, + + //! Assigned font features (key/value pairs). + feature_settings: FontFeatureSettingsCore, + + //! Assigned font variations (key/value pairs). + variation_settings: FontVariationSettingsCore, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \endcond + font_init :: proc(self: ^FontCore) -> Result --- + font_init_move :: proc(self: ^FontCore, other: ^FontCore) -> Result --- + font_init_weak :: proc(self: ^FontCore, other: ^FontCore) -> Result --- + font_destroy :: proc(self: ^FontCore) -> Result --- + font_reset :: proc(self: ^FontCore) -> Result --- + font_assign_move :: proc(self: ^FontCore, other: ^FontCore) -> Result --- + font_assign_weak :: proc(self: ^FontCore, other: ^FontCore) -> Result --- + font_equals :: proc(a: ^FontCore, b: ^FontCore) -> i32 --- + font_create_from_face :: proc(self: ^FontCore, face: ^FontFaceCore, size: f32) -> Result --- + font_create_from_face_with_settings :: proc(self: ^FontCore, face: ^FontFaceCore, size: f32, feature_settings: ^FontFeatureSettingsCore, variation_settings: ^FontVariationSettingsCore) -> Result --- + font_get_face :: proc(self: ^FontCore, out: ^FontFaceCore) -> Result --- + font_get_size :: proc(self: ^FontCore) -> f32 --- + font_set_size :: proc(self: ^FontCore, size: f32) -> Result --- + font_get_metrics :: proc(self: ^FontCore, out: ^FontMetrics) -> Result --- + font_get_matrix :: proc(self: ^FontCore, out: ^FontMatrix) -> Result --- + font_get_design_metrics :: proc(self: ^FontCore, out: ^FontDesignMetrics) -> Result --- + font_get_feature_settings :: proc(self: ^FontCore, out: ^FontFeatureSettingsCore) -> Result --- + font_set_feature_settings :: proc(self: ^FontCore, feature_settings: ^FontFeatureSettingsCore) -> Result --- + font_reset_feature_settings :: proc(self: ^FontCore) -> Result --- + font_get_variation_settings :: proc(self: ^FontCore, out: ^FontVariationSettingsCore) -> Result --- + font_set_variation_settings :: proc(self: ^FontCore, variation_settings: ^FontVariationSettingsCore) -> Result --- + font_reset_variation_settings :: proc(self: ^FontCore) -> Result --- + font_shape :: proc(self: ^FontCore, gb: ^GlyphBufferCore) -> Result --- + font_map_text_to_glyphs :: proc(self: ^FontCore, gb: ^GlyphBufferCore, state_out: ^GlyphMappingState) -> Result --- + font_position_glyphs :: proc(self: ^FontCore, gb: ^GlyphBufferCore) -> Result --- + font_apply_kerning :: proc(self: ^FontCore, gb: ^GlyphBufferCore) -> Result --- + font_apply_gsub :: proc(self: ^FontCore, gb: ^GlyphBufferCore, lookups: ^BitArrayCore) -> Result --- + font_apply_gpos :: proc(self: ^FontCore, gb: ^GlyphBufferCore, lookups: ^BitArrayCore) -> Result --- + font_get_text_metrics :: proc(self: ^FontCore, gb: ^GlyphBufferCore, out: ^TextMetrics) -> Result --- + font_get_glyph_bounds :: proc(self: ^FontCore, glyph_data: ^u32, glyph_advance: c.intptr_t, out: ^BoxI, count: c.size_t) -> Result --- + font_get_glyph_advances :: proc(self: ^FontCore, glyph_data: ^u32, glyph_advance: c.intptr_t, out: ^GlyphPlacement, count: c.size_t) -> Result --- + font_get_glyph_outlines :: proc(self: ^FontCore, glyph_id: GlyphId, user_transform: ^Matrix2D, out: ^PathCore, sink: PathSinkFunc, user_data: rawptr) -> Result --- + font_get_glyph_run_outlines :: proc(self: ^FontCore, glyph_run: ^GlyphRun, user_transform: ^Matrix2D, out: ^PathCore, sink: PathSinkFunc, user_data: rawptr) -> Result --- +} + diff --git a/binding/fontdata.odin b/binding/fontdata.odin @@ -0,0 +1,88 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Flags used by \ref BLFontData (or \ref BLFontDataCore). +FontDataFlags :: enum u32 { + //! No flags. + NO_FLAGS = 0, + + //!< Font data references a font-collection. + FLAG_COLLECTION = 1, + FLAG_FORCE_UINT = 4294967295, +} + +//! A read only data that represents a font table or its sub-table. +FontTable :: struct { + //! \name Members + //! \{ + + //! Pointer to the beginning of the data interpreted as `uint8_t*`. + data: ^u8, + + //! Size of `data` in bytes. + size: c.size_t, +} + +//! Font data [C API]. +FontDataCore :: struct { + _d: ObjectDetail, +} + +//! \cond INTERNAL +//! Font data [C API Virtual Function Table]. +FontDataVirt :: struct { + base: ObjectVirtBase, + get_table_tags: proc "c" (impl: ^FontDataImpl, face_index: u32, out: ^ArrayCore) -> Result, + get_tables: proc "c" (impl: ^FontDataImpl, face_index: u32, dst: ^FontTable, tags: ^Tag, n: c.size_t) -> c.size_t, +} + +//! Font data [C API Impl]. +FontDataImpl :: struct { + //! Virtual function table. + virt: ^FontDataVirt, + + //! Type of the face that would be created with this font data. + face_type: u8, + + //! Number of font faces stored in this font data instance. + face_count: u32, + + //! Font data flags. + flags: u32, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \endcond + font_data_init :: proc(self: ^FontDataCore) -> Result --- + font_data_init_move :: proc(self: ^FontDataCore, other: ^FontDataCore) -> Result --- + font_data_init_weak :: proc(self: ^FontDataCore, other: ^FontDataCore) -> Result --- + font_data_destroy :: proc(self: ^FontDataCore) -> Result --- + font_data_reset :: proc(self: ^FontDataCore) -> Result --- + font_data_assign_move :: proc(self: ^FontDataCore, other: ^FontDataCore) -> Result --- + font_data_assign_weak :: proc(self: ^FontDataCore, other: ^FontDataCore) -> Result --- + font_data_create_from_file :: proc(self: ^FontDataCore, file_name: cstring, read_flags: FileReadFlags) -> Result --- + font_data_create_from_data_array :: proc(self: ^FontDataCore, data_array: ^ArrayCore) -> Result --- + font_data_create_from_data :: proc(self: ^FontDataCore, data: rawptr, data_size: c.size_t, destroy_func: DestroyExternalDataFunc, user_data: rawptr) -> Result --- + font_data_equals :: proc(a: ^FontDataCore, b: ^FontDataCore) -> i32 --- + font_data_get_face_count :: proc(self: ^FontDataCore) -> u32 --- + font_data_get_face_type :: proc(self: ^FontDataCore) -> FontFaceType --- + font_data_get_flags :: proc(self: ^FontDataCore) -> FontDataFlags --- + font_data_get_table_tags :: proc(self: ^FontDataCore, face_index: u32, dst: ^ArrayCore) -> Result --- + font_data_get_tables :: proc(self: ^FontDataCore, face_index: u32, dst: ^FontTable, tags: ^Tag, count: c.size_t) -> c.size_t --- +} + diff --git a/binding/fontdefs.odin b/binding/fontdefs.odin @@ -0,0 +1,730 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Orientation. +Orientation :: enum u32 { + //! Horizontal orientation. + HORIZONTAL = 0, + + //! Vertical orientation. + VERTICAL = 1, + + //! Maximum value of `BLOrientation`. + MAX_VALUE = 1, + FORCE_UINT = 4294967295, +} + +//! Type of a font or font face, see \ref BLFontFace (or \ref BLFontFaceCore). +FontFaceType :: enum u32 { + //! None or unknown font type. + NONE = 0, + + //! TrueType/OpenType font type (.ttf/.otf files and font collections). + OPENTYPE = 1, + + //! Maximum value of `BLFontFaceType`. + MAX_VALUE = 1, + FORCE_UINT = 4294967295, +} + +//! Font stretch. +FontStretch :: enum u32 { + //! Ultra condensed stretch. + ULTRA_CONDENSED = 1, + + //! Extra condensed stretch. + EXTRA_CONDENSED = 2, + + //! Condensed stretch. + CONDENSED = 3, + + //! Semi condensed stretch. + SEMI_CONDENSED = 4, + + //! Normal stretch. + NORMAL = 5, + + //! Semi expanded stretch. + SEMI_EXPANDED = 6, + + //! Expanded stretch. + EXPANDED = 7, + + //! Extra expanded stretch. + EXTRA_EXPANDED = 8, + + //! Ultra expanded stretch. + ULTRA_EXPANDED = 9, + + //! Maximum value of `BLFontStretch`. + MAX_VALUE = 9, + FORCE_UINT = 4294967295, +} + +//! Font style. +FontStyle :: enum u32 { + //! Normal style. + NORMAL = 0, + + //! Oblique. + OBLIQUE = 1, + + //! Italic. + ITALIC = 2, + + //! Maximum value of `BLFontStyle`. + MAX_VALUE = 2, + FORCE_UINT = 4294967295, +} + +//! Font weight. +FontWeight :: enum u32 { + //! Thin weight (100). + THIN = 100, + + //! Extra light weight (200). + EXTRA_LIGHT = 200, + + //! Light weight (300). + LIGHT = 300, + + //! Semi light weight (350). + SEMI_LIGHT = 350, + + //! Normal weight (400). + NORMAL = 400, + + //! Medium weight (500). + MEDIUM = 500, + + //! Semi bold weight (600). + SEMI_BOLD = 600, + + //! Bold weight (700). + BOLD = 700, + + //! Extra bold weight (800). + EXTRA_BOLD = 800, + + //! Black weight (900). + BLACK = 900, + + //! Extra black weight (950). + EXTRA_BLACK = 950, + FORCE_UINT = 4294967295, +} + +//! Font string identifiers used by OpenType 'name' table. +FontStringId :: enum u32 { + //! Copyright notice. + COPYRIGHT_NOTICE = 0, + + //! Font family name. + FAMILY_NAME = 1, + + //! Font subfamily name. + SUBFAMILY_NAME = 2, + + //! Unique font identifier. + UNIQUE_IDENTIFIER = 3, + + //! Full font name that reflects all family and relevant subfamily descriptors. + FULL_NAME = 4, + + //! Version string. Should begin with the synta `Version <number>.<number>`. + VERSION_STRING = 5, + + //! PostScript name for the font. + POST_SCRIPT_NAME = 6, + + //! Trademark notice/information for this font. + TRADEMARK = 7, + + //! Manufacturer name. + MANUFACTURER_NAME = 8, + + //! Name of the designer of the typeface. + DESIGNER_NAME = 9, + + //! Description of the typeface. + DESCRIPTION = 10, + + //! URL of font vendor. + VENDOR_URL = 11, + + //! URL of typeface designer. + DESIGNER_URL = 12, + + //! Description of how the font may be legally used. + LICENSE_DESCRIPTION = 13, + + //! URL where additional licensing information can be found. + LICENSE_INFO_URL = 14, + + //! Reserved. + RESERVED = 15, + + //! Typographic family name. + TYPOGRAPHIC_FAMILY_NAME = 16, + + //! Typographic subfamily name. + TYPOGRAPHIC_SUBFAMILY_NAME = 17, + + //! Compatible full name (MAC only). + COMPATIBLE_FULL_NAME = 18, + + //! Sample text - font name or any other text from the designer. + SAMPLE_TEXT = 19, + + //! PostScript CID findfont name. + POST_SCRIPT_CID_NAME = 20, + + //! WWS family name. + WWS_FAMILY_NAME = 21, + + //! WWS subfamily name. + WWS_SUBFAMILY_NAME = 22, + + //! Light background palette. + LIGHT_BACKGROUND_PALETTE = 23, + + //! Dark background palette. + DARK_BACKGROUND_PALETTE = 24, + + //! Variations PostScript name prefix. + VARIATIONS_POST_SCRIPT_PREFIX = 25, + + //! Count of common font string ids. + COMMON_MAX_VALUE = 26, + + //! Start of custom font string ids. + CUSTOM_START_INDEX = 255, + FORCE_UINT = 4294967295, +} + +//! Bit positions used by \ref BLFontCoverageInfo structure. +//! +//! Each bit represents a range (or multiple ranges) of unicode characters. +FontCoverageGroup :: enum u32 { + BASIC_LATIN = 0, //!< [000000-00007F] Basic Latin. + LATIN1_SUPPLEMENT = 1, //!< [000080-0000FF] Latin-1 Supplement. + LATIN_EXTENDED_A = 2, //!< [000100-00017F] Latin Extended-A. + LATIN_EXTENDED_B = 3, //!< [000180-00024F] Latin Extended-B. + IPA_EXTENSIONS = 4, //!< [000250-0002AF] IPA Extensions. + + //!< [001D00-001D7F] Phonetic Extensions. + //!< [001D80-001DBF] Phonetic Extensions Supplement. + SPACING_MODIFIER_LETTERS = 5, //!< [0002B0-0002FF] Spacing Modifier Letters. + + //!< [00A700-00A71F] Modifier Tone Letters. + //!< [001DC0-001DFF] Combining Diacritical Marks Supplement. + COMBINING_DIACRITICAL_MARKS = 6, //!< [000300-00036F] Combining Diacritical Marks. + GREEK_AND_COPTIC = 7, //!< [000370-0003FF] Greek and Coptic. + COPTIC = 8, //!< [002C80-002CFF] Coptic. + CYRILLIC = 9, //!< [000400-0004FF] Cyrillic. + + //!< [000500-00052F] Cyrillic Supplement. + //!< [002DE0-002DFF] Cyrillic Extended-A. + //!< [00A640-00A69F] Cyrillic Extended-B. + ARMENIAN = 10, //!< [000530-00058F] Armenian. + HEBREW = 11, //!< [000590-0005FF] Hebrew. + VAI = 12, //!< [00A500-00A63F] Vai. + ARABIC = 13, //!< [000600-0006FF] Arabic. + + //!< [000750-00077F] Arabic Supplement. + NKO = 14, //!< [0007C0-0007FF] NKo. + DEVANAGARI = 15, //!< [000900-00097F] Devanagari. + BENGALI = 16, //!< [000980-0009FF] Bengali. + GURMUKHI = 17, //!< [000A00-000A7F] Gurmukhi. + GUJARATI = 18, //!< [000A80-000AFF] Gujarati. + ORIYA = 19, //!< [000B00-000B7F] Oriya. + TAMIL = 20, //!< [000B80-000BFF] Tamil. + TELUGU = 21, //!< [000C00-000C7F] Telugu. + KANNADA = 22, //!< [000C80-000CFF] Kannada. + MALAYALAM = 23, //!< [000D00-000D7F] Malayalam. + THAI = 24, //!< [000E00-000E7F] Thai. + LAO = 25, //!< [000E80-000EFF] Lao. + GEORGIAN = 26, //!< [0010A0-0010FF] Georgian. + + //!< [002D00-002D2F] Georgian Supplement. + BALINESE = 27, //!< [001B00-001B7F] Balinese. + HANGUL_JAMO = 28, //!< [001100-0011FF] Hangul Jamo. + LATIN_EXTENDED_ADDITIONAL = 29, //!< [001E00-001EFF] Latin Extended Additional. + + //!< [002C60-002C7F] Latin Extended-C. + //!< [00A720-00A7FF] Latin Extended-D. + GREEK_EXTENDED = 30, //!< [001F00-001FFF] Greek Extended. + GENERAL_PUNCTUATION = 31, //!< [002000-00206F] General Punctuation. + + //!< [002E00-002E7F] Supplemental Punctuation. + SUPERSCRIPTS_AND_SUBSCRIPTS = 32, //!< [002070-00209F] Superscripts And Subscripts. + CURRENCY_SYMBOLS = 33, //!< [0020A0-0020CF] Currency Symbols. + COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS = 34, //!< [0020D0-0020FF] Combining Diacritical Marks For Symbols. + LETTERLIKE_SYMBOLS = 35, //!< [002100-00214F] Letterlike Symbols. + NUMBER_FORMS = 36, //!< [002150-00218F] Number Forms. + ARROWS = 37, //!< [002190-0021FF] Arrows. + + //!< [0027F0-0027FF] Supplemental Arrows-A. + //!< [002900-00297F] Supplemental Arrows-B. + //!< [002B00-002BFF] Miscellaneous Symbols and Arrows. + MATHEMATICAL_OPERATORS = 38, //!< [002200-0022FF] Mathematical Operators. + + //!< [002A00-002AFF] Supplemental Mathematical Operators. + //!< [0027C0-0027EF] Miscellaneous Mathematical Symbols-A. + //!< [002980-0029FF] Miscellaneous Mathematical Symbols-B. + MISCELLANEOUS_TECHNICAL = 39, //!< [002300-0023FF] Miscellaneous Technical. + CONTROL_PICTURES = 40, //!< [002400-00243F] Control Pictures. + OPTICAL_CHARACTER_RECOGNITION = 41, //!< [002440-00245F] Optical Character Recognition. + ENCLOSED_ALPHANUMERICS = 42, //!< [002460-0024FF] Enclosed Alphanumerics. + BOX_DRAWING = 43, //!< [002500-00257F] Box Drawing. + BLOCK_ELEMENTS = 44, //!< [002580-00259F] Block Elements. + GEOMETRIC_SHAPES = 45, //!< [0025A0-0025FF] Geometric Shapes. + MISCELLANEOUS_SYMBOLS = 46, //!< [002600-0026FF] Miscellaneous Symbols. + DINGBATS = 47, //!< [002700-0027BF] Dingbats. + CJK_SYMBOLS_AND_PUNCTUATION = 48, //!< [003000-00303F] CJK Symbols And Punctuation. + HIRAGANA = 49, //!< [003040-00309F] Hiragana. + KATAKANA = 50, //!< [0030A0-0030FF] Katakana. + + //!< [0031F0-0031FF] Katakana Phonetic Extensions. + BOPOMOFO = 51, //!< [003100-00312F] Bopomofo. + + //!< [0031A0-0031BF] Bopomofo Extended. + HANGUL_COMPATIBILITY_JAMO = 52, //!< [003130-00318F] Hangul Compatibility Jamo. + PHAGS_PA = 53, //!< [00A840-00A87F] Phags-pa. + ENCLOSED_CJK_LETTERS_AND_MONTHS = 54, //!< [003200-0032FF] Enclosed CJK Letters And Months. + CJK_COMPATIBILITY = 55, //!< [003300-0033FF] CJK Compatibility. + HANGUL_SYLLABLES = 56, //!< [00AC00-00D7AF] Hangul Syllables. + NON_PLANE = 57, //!< [00D800-00DFFF] Non-Plane 0 *. + PHOENICIAN = 58, //!< [010900-01091F] Phoenician. + CJK_UNIFIED_IDEOGRAPHS = 59, //!< [004E00-009FFF] CJK Unified Ideographs. + + //!< [002E80-002EFF] CJK Radicals Supplement. + //!< [002F00-002FDF] Kangxi Radicals. + //!< [002FF0-002FFF] Ideographic Description Characters. + //!< [003400-004DBF] CJK Unified Ideographs Extension A. + //!< [020000-02A6DF] CJK Unified Ideographs Extension B. + //!< [003190-00319F] Kanbun. + PRIVATE_USE_PLANE0 = 60, //!< [00E000-00F8FF] Private Use (Plane 0). + CJK_STROKES = 61, //!< [0031C0-0031EF] CJK Strokes. + + //!< [00F900-00FAFF] CJK Compatibility Ideographs. + //!< [02F800-02FA1F] CJK Compatibility Ideographs Supplement. + ALPHABETIC_PRESENTATION_FORMS = 62, //!< [00FB00-00FB4F] Alphabetic Presentation Forms. + ARABIC_PRESENTATION_FORMS_A = 63, //!< [00FB50-00FDFF] Arabic Presentation Forms-A. + COMBINING_HALF_MARKS = 64, //!< [00FE20-00FE2F] Combining Half Marks. + VERTICAL_FORMS = 65, //!< [00FE10-00FE1F] Vertical Forms. + + //!< [00FE30-00FE4F] CJK Compatibility Forms. + SMALL_FORM_VARIANTS = 66, //!< [00FE50-00FE6F] Small Form Variants. + ARABIC_PRESENTATION_FORMS_B = 67, //!< [00FE70-00FEFF] Arabic Presentation Forms-B. + HALFWIDTH_AND_FULLWIDTH_FORMS = 68, //!< [00FF00-00FFEF] Halfwidth And Fullwidth Forms. + SPECIALS = 69, //!< [00FFF0-00FFFF] Specials. + TIBETAN = 70, //!< [000F00-000FFF] Tibetan. + SYRIAC = 71, //!< [000700-00074F] Syriac. + THAANA = 72, //!< [000780-0007BF] Thaana. + SINHALA = 73, //!< [000D80-000DFF] Sinhala. + MYANMAR = 74, //!< [001000-00109F] Myanmar. + ETHIOPIC = 75, //!< [001200-00137F] Ethiopic. + + //!< [001380-00139F] Ethiopic Supplement. + //!< [002D80-002DDF] Ethiopic Extended. + CHEROKEE = 76, //!< [0013A0-0013FF] Cherokee. + UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS = 77, //!< [001400-00167F] Unified Canadian Aboriginal Syllabics. + OGHAM = 78, //!< [001680-00169F] Ogham. + RUNIC = 79, //!< [0016A0-0016FF] Runic. + KHMER = 80, //!< [001780-0017FF] Khmer. + + //!< [0019E0-0019FF] Khmer Symbols. + MONGOLIAN = 81, //!< [001800-0018AF] Mongolian. + BRAILLE_PATTERNS = 82, //!< [002800-0028FF] Braille Patterns. + YI_SYLLABLES_AND_RADICALS = 83, //!< [00A000-00A48F] Yi Syllables. + + //!< [00A490-00A4CF] Yi Radicals. + TAGALOG_HANUNOO_BUHID_TAGBANWA = 84, //!< [001700-00171F] Tagalog. + + //!< [001720-00173F] Hanunoo. + //!< [001740-00175F] Buhid. + //!< [001760-00177F] Tagbanwa. + OLD_ITALIC = 85, //!< [010300-01032F] Old Italic. + GOTHIC = 86, //!< [010330-01034F] Gothic. + DESERET = 87, //!< [010400-01044F] Deseret. + MUSICAL_SYMBOLS = 88, //!< [01D000-01D0FF] Byzantine Musical Symbols. + + //!< [01D100-01D1FF] Musical Symbols. + //!< [01D200-01D24F] Ancient Greek Musical Notation. + MATHEMATICAL_ALPHANUMERIC_SYMBOLS = 89, //!< [01D400-01D7FF] Mathematical Alphanumeric Symbols. + PRIVATE_USE_PLANE_15_16 = 90, //!< [0F0000-0FFFFD] Private Use (Plane 15). + + //!< [100000-10FFFD] Private Use (Plane 16). + VARIATION_SELECTORS = 91, //!< [00FE00-00FE0F] Variation Selectors. + + //!< [0E0100-0E01EF] Variation Selectors Supplement. + TAGS = 92, //!< [0E0000-0E007F] Tags. + LIMBU = 93, //!< [001900-00194F] Limbu. + TAI_LE = 94, //!< [001950-00197F] Tai Le. + NEW_TAI_LUE = 95, //!< [001980-0019DF] New Tai Lue. + BUGINESE = 96, //!< [001A00-001A1F] Buginese. + GLAGOLITIC = 97, //!< [002C00-002C5F] Glagolitic. + TIFINAGH = 98, //!< [002D30-002D7F] Tifinagh. + YIJING_HEXAGRAM_SYMBOLS = 99, //!< [004DC0-004DFF] Yijing Hexagram Symbols. + SYLOTI_NAGRI = 100, //!< [00A800-00A82F] Syloti Nagri. + LINEAR_B_SYLLABARY_AND_IDEOGRAMS = 101, //!< [010000-01007F] Linear B Syllabary. + + //!< [010080-0100FF] Linear B Ideograms. + //!< [010100-01013F] Aegean Numbers. + ANCIENT_GREEK_NUMBERS = 102, //!< [010140-01018F] Ancient Greek Numbers. + UGARITIC = 103, //!< [010380-01039F] Ugaritic. + OLD_PERSIAN = 104, //!< [0103A0-0103DF] Old Persian. + SHAVIAN = 105, //!< [010450-01047F] Shavian. + OSMANYA = 106, //!< [010480-0104AF] Osmanya. + CYPRIOT_SYLLABARY = 107, //!< [010800-01083F] Cypriot Syllabary. + KHAROSHTHI = 108, //!< [010A00-010A5F] Kharoshthi. + TAI_XUAN_JING_SYMBOLS = 109, //!< [01D300-01D35F] Tai Xuan Jing Symbols. + CUNEIFORM = 110, //!< [012000-0123FF] Cuneiform. + + //!< [012400-01247F] Cuneiform Numbers and Punctuation. + COUNTING_ROD_NUMERALS = 111, //!< [01D360-01D37F] Counting Rod Numerals. + SUNDANESE = 112, //!< [001B80-001BBF] Sundanese. + LEPCHA = 113, //!< [001C00-001C4F] Lepcha. + OL_CHIKI = 114, //!< [001C50-001C7F] Ol Chiki. + SAURASHTRA = 115, //!< [00A880-00A8DF] Saurashtra. + KAYAH_LI = 116, //!< [00A900-00A92F] Kayah Li. + REJANG = 117, //!< [00A930-00A95F] Rejang. + CHAM = 118, //!< [00AA00-00AA5F] Cham. + ANCIENT_SYMBOLS = 119, //!< [010190-0101CF] Ancient Symbols. + PHAISTOS_DISC = 120, //!< [0101D0-0101FF] Phaistos Disc. + CARIAN_LYCIAN_LYDIAN = 121, //!< [0102A0-0102DF] Carian. + + //!< [010280-01029F] Lycian. + //!< [010920-01093F] Lydian. + DOMINO_AND_MAHJONG_TILES = 122, //!< [01F030-01F09F] Domino Tiles. + + //!< [01F000-01F02F] Mahjong Tiles. + INTERNAL_USAGE_123 = 123, //!< Reserved for internal usage (123). + INTERNAL_USAGE_124 = 124, //!< Reserved for internal usage (124). + INTERNAL_USAGE_125 = 125, //!< Reserved for internal usage (125). + INTERNAL_USAGE_126 = 126, //!< Reserved for internal usage (126). + INTERNAL_USAGE_127 = 127, //!< Reserved for internal usage (127). + + //! Maximum value of `BLFontCoverageGroup`. + MAX_VALUE = 127, + FORCE_UINT = 4294967295, +} + +//! Text direction. +TextDirection :: enum u32 { + //! Left-to-right direction. + LTR = 0, + + //! Right-to-left direction. + RTL = 1, + + //! Maximum value of `BLTextDirection`. + MAX_VALUE = 1, + FORCE_UINT = 4294967295, +} + +//! Glyph id - a 32-bit unsigned integer. +GlyphId :: u32 + +//! Contains additional information associated with a glyph used by \ref BLGlyphBuffer. +GlyphInfo :: struct { + //! \name Members + //! \{ + cluster: u32, + reserved: u32, +} + +//! Glyph placement. +//! +//! Provides information about glyph offset (x/y) and advance (x/y). +GlyphPlacement :: struct { + //! \name Members + //! \{ + placement: PointI, + advance: PointI, +} + +//! Character to glyph mapping state. +GlyphMappingState :: struct { + //! \name Members + //! \{ + + //! Number of glyphs or glyph-items on output. + glyph_count: c.size_t, + + //! Index of the first undefined glyph (SIZE_MAX if none). + undefined_first: c.size_t, + + //! Undefined glyph count (chars that have no mapping). + undefined_count: c.size_t, +} + +//! Information passed to a \ref BLPathSinkFunc sink by \ref BLFont::get_glyph_outlines(). +GlyphOutlineSinkInfo :: struct { + glyph_index: c.size_t, + contour_count: c.size_t, +} + +//! Font coverage information struct provides information about ranges of unicode characters supported by a font-face. +//! +//! \remarks The information is stored in "OS/2" table in TTF/OTF font. Blend2D reads this information and populates +//! `BLFontCoverageInfo` struct from such data, however, there is no guarantee that what font describes is actually +//! true. +FontCoverageInfo :: struct { + //! \name Members + //! \{ + + //! Unicode coverage data as a bit array of 4 32-bit unsigned integers. + data: [4]u32, +} + +//! Font PANOSE classification. +FontPanoseInfo :: struct { + using _: struct #raw_union { + data: [10]u8, + family_kind: u8, + + text: struct { + family_kind: u8, + serif_style: u8, + weight: u8, + proportion: u8, + contrast: u8, + stroke_variation: u8, + arm_style: u8, + letterform: u8, + midline: u8, + x_height: u8, + }, + + script: struct { + family_kind: u8, + tool_kind: u8, + weight: u8, + spacing: u8, + aspect_ratio: u8, + contrast: u8, + topology: u8, + form: u8, + finials: u8, + x_ascent: u8, + }, + + decorative: struct { + family_kind: u8, + decorative_class: u8, + weight: u8, + aspect: u8, + contrast: u8, + serif_variant: u8, + treatment: u8, + lining: u8, + topology: u8, + character_range: u8, + }, + + symbol: struct { + family_kind: u8, + symbol_kind: u8, + weight: u8, + spacing: u8, + aspect_ratio_and_contrast: u8, + aspect_ratio_94: u8, + aspect_ratio_119: u8, + aspect_ratio_157: u8, + aspect_ratio_163: u8, + aspect_ratio_211: u8, + }, + }, +} + +//! 2x2 transformation matrix used by \ref BLFont. It's similar to \ref BLMatrix2D, +//! however, it doesn't provide a translation part as it's assumed to be zero. +FontMatrix :: struct { + using _: struct #raw_union { + m: [4]f64, + + using _: struct { + m00: f64, + m01: f64, + m10: f64, + m11: f64, + }, + }, +} + +//! Scaled \ref BLFontDesignMetrics based on font size and other properties. +FontMetrics :: struct { + //! Font size. + size: f32, + + using _: struct #raw_union { + using _: struct { + //! Font ascent (horizontal orientation). + ascent: f32, + + //! Font ascent (vertical orientation). + v_ascent: f32, + + //! Font descent (horizontal orientation). + descent: f32, + + //! Font descent (vertical orientation). + v_descent: f32, + }, + + using _: struct { + ascent_by_orientation: [2]f32, + descent_by_orientation: [2]f32, + }, + }, + + //! Line gap. + line_gap: f32, + + //! Distance between the baseline and the mean line of lower-case letters. + x_height: f32, + + //! Maximum height of a capital letter above the baseline. + cap_height: f32, + + //! Minimum x, reported by the font. + x_min: f32, + + //! Minimum y, reported by the font. + y_min: f32, + + //! Maximum x, reported by the font. + x_max: f32, + + //! Maximum y, reported by the font. + y_max: f32, + + //! Text underline position. + underline_position: f32, + + //! Text underline thickness. + underline_thickness: f32, + + //! Text strikethrough position. + strikethrough_position: f32, + + //! Text strikethrough thickness. + strikethrough_thickness: f32, +} + +//! Design metrics of a font. +//! +//! Design metrics is information that \ref BLFontFace collected directly from the font data. It means that all +//! fields are measured in font design units. +//! +//! When a new \ref BLFont instance is created a scaled metrics \ref BLFontMetrics is automatically calculated +//! from \ref BLFontDesignMetrics including other members like transformation, etc... +FontDesignMetrics :: struct { + //! Units per EM square. + units_per_em: i32, + + //! Lowest readable size in pixels. + lowest_ppem: i32, + + //! Line gap. + line_gap: i32, + + //! Distance between the baseline and the mean line of lower-case letters. + x_height: i32, + + //! Maximum height of a capital letter above the baseline. + cap_height: i32, + + using _: struct #raw_union { + using _: struct { + //! Ascent (horizontal layout). + ascent: i32, + + //! Ascent (vertical layout). + v_ascent: i32, + + //! Descent (horizontal layout). + descent: i32, + + //! Descent (vertical layout). + v_descent: i32, + + //! Minimum leading-side bearing (horizontal layout). + h_min_lsb: i32, + + //! Minimum leading-side bearing (vertical layout). + v_min_lsb: i32, + + //! Minimum trailing-side bearing (horizontal layout). + h_min_tsb: i32, + + //! Minimum trailing-side bearing (vertical layout). + v_min_tsb: i32, + + //! Maximum advance (horizontal layout). + h_max_advance: i32, + + //! Maximum advance (vertical layout). + v_max_advance: i32, + }, + + using _: struct { + //! Horizontal & vertical ascents. + ascent_by_orientation: [2]i32, + + //! Horizontal & vertical descents. + descent_by_orientation: [2]i32, + + //! Minimum leading-side bearing (horizontal and vertical). + min_lsb_by_orientation: [2]i32, + + //! Minimum trailing-side bearing (horizontal and vertical).. + min_tsb_by_orientation: [2]i32, + + //! Maximum advance width (horizontal) and height (vertical). + max_advance_by_orientation: [2]i32, + }, + }, + + //! Aggregated bounding box of all glyphs in the font. + //! + //! \note This value is reported by the font data so it's not granted to be true. + glyph_bounding_box: BoxI, + + //! Text underline position. + underline_position: i32, + + //! Text underline thickness. + underline_thickness: i32, + + //! Text strikethrough position. + strikethrough_position: i32, + + //! Text strikethrough thickness. + strikethrough_thickness: i32, +} + +//! Text metrics. +TextMetrics :: struct { + advance: Point, + leading_bearing: Point, + trailing_bearing: Point, + bounding_box: Box, +} + diff --git a/binding/fontface.odin b/binding/fontface.odin @@ -0,0 +1,234 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Flags used by \ref BLFontFace (or \ref BLFontFaceCore) +FontFaceFlags :: enum u32 { + //! No flags. + NO_FLAGS = 0, + + //! Font uses typographic family and subfamily names. + FLAG_TYPOGRAPHIC_NAMES = 1, + + //! Font uses typographic metrics. + FLAG_TYPOGRAPHIC_METRICS = 2, + + //! Character to glyph mapping is available. + FLAG_CHAR_TO_GLYPH_MAPPING = 4, + + //! Horizontal glyph metrics (advances, side bearings) is available. + FLAG_HORIZONTAL_METRICS = 16, + + //! Vertical glyph metrics (advances, side bearings) is available. + FLAG_VERTICAL_METRICS = 32, + + //! Legacy horizontal kerning feature ('kern' table with horizontal kerning data). + FLAG_HORIZONTAL_KERNING = 64, + + //! Legacy vertical kerning feature ('kern' table with vertical kerning data). + FLAG_VERTICAL_KERNING = 128, + + //! OpenType features (GDEF, GPOS, GSUB) are available. + FLAG_OPENTYPE_FEATURES = 256, + + //! Panose classification is available. + FLAG_PANOSE_INFO = 512, + + //! Unicode coverage information is available. + FLAG_COVERAGE_INFO = 1024, + + //! Baseline for font at `y` equals 0. + FLAG_BASELINE_Y_EQUALS_0 = 4096, + + //! Left sidebearing point at `x == 0` (TT only). + FLAG_LSB_POINT_X_EQUALS_0 = 8192, + + //! Unicode variation sequences feature is available. + FLAG_VARIATION_SEQUENCES = 268435456, + + //! OpenType Font Variations feature is available. + FLAG_OPENTYPE_VARIATIONS = 536870912, + + //! This is a symbol font. + FLAG_SYMBOL_FONT = 1073741824, + + //! This is a last resort font. + FLAG_LAST_RESORT_FONT = 2147483648, + FLAG_FORCE_UINT = 4294967295, +} + +//! Diagnostic flags offered by \ref BLFontFace (or \ref BLFontFaceCore). +FontFaceDiagFlags :: enum u32 { + //! No flags. + NO_FLAGS = 0, + + //! Wrong data in 'name' table. + WRONG_NAME_DATA = 1, + + //! Fixed data read from 'name' table and possibly fixed font family/subfamily name. + FIXED_NAME_DATA = 2, + + //! Wrong data in 'kern' table [kerning disabled]. + WRONG_KERN_DATA = 4, + + //! Fixed data read from 'kern' table so it can be used. + FIXED_KERN_DATA = 8, + + //! Wrong data in 'cmap' table. + WRONG_CMAP_DATA = 16, + + //! Wrong format in 'cmap' (sub)table. + WRONG_CMAP_FORMAT = 32, + FORCE_UINT = 4294967295, +} + +//! Format of an outline stored in a font. +FontOutlineType :: enum u32 { + //! None. + NONE = 0, + + //! Truetype outlines. + TRUETYPE = 1, + + //! OpenType (CFF) outlines. + CFF = 2, + + //! OpenType (CFF2) outlines with font variations support. + CFF2 = 3, + + //! Maximum value of `BLFontOutlineType`. + MAX_VALUE = 3, + FORCE_UINT = 4294967295, +} + +//! Information of \ref BLFontFace. +FontFaceInfo :: struct { + //! \name Members + //! \{ + + //! Font face type, see \ref BLFontFaceType. + face_type: u8, + + //! Type of outlines used by the font face, see \ref BLFontOutlineType. + outline_type: u8, + + //! Reserved fields. + reserved8: [2]u8, + + //! Number of glyphs provided by this font face. + glyph_count: u32, + + //! Revision (read from 'head' table, represented as 16.16 fixed point). + revision: u32, + + //! Face face index in a TTF/OTF collection or zero if not part of a collection. + face_index: u32, + + //! Font face flags, see \ref BLFontFaceFlags + face_flags: u32, + + //! Font face diagnostic flags, see \ref BLFontFaceDiagFlags. + diag_flags: u32, + + //! Reserved for future use, set to zero. + reserved: [2]u32, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \name BLFontFace - C API + //! \{ + font_face_init :: proc(self: ^FontFaceCore) -> Result --- + font_face_init_move :: proc(self: ^FontFaceCore, other: ^FontFaceCore) -> Result --- + font_face_init_weak :: proc(self: ^FontFaceCore, other: ^FontFaceCore) -> Result --- + font_face_destroy :: proc(self: ^FontFaceCore) -> Result --- + font_face_reset :: proc(self: ^FontFaceCore) -> Result --- + font_face_assign_move :: proc(self: ^FontFaceCore, other: ^FontFaceCore) -> Result --- + font_face_assign_weak :: proc(self: ^FontFaceCore, other: ^FontFaceCore) -> Result --- + font_face_equals :: proc(a: ^FontFaceCore, b: ^FontFaceCore) -> i32 --- + font_face_create_from_file :: proc(self: ^FontFaceCore, file_name: cstring, read_flags: FileReadFlags) -> Result --- + font_face_create_from_data :: proc(self: ^FontFaceCore, font_data: ^FontDataCore, face_index: u32) -> Result --- + font_face_get_full_name :: proc(self: ^FontFaceCore, out: ^StringCore) -> Result --- + font_face_get_family_name :: proc(self: ^FontFaceCore, out: ^StringCore) -> Result --- + font_face_get_subfamily_name :: proc(self: ^FontFaceCore, out: ^StringCore) -> Result --- + font_face_get_post_script_name :: proc(self: ^FontFaceCore, out: ^StringCore) -> Result --- + font_face_get_face_info :: proc(self: ^FontFaceCore, out: ^FontFaceInfo) -> Result --- + font_face_get_design_metrics :: proc(self: ^FontFaceCore, out: ^FontDesignMetrics) -> Result --- + font_face_get_coverage_info :: proc(self: ^FontFaceCore, out: ^FontCoverageInfo) -> Result --- + font_face_get_panose_info :: proc(self: ^FontFaceCore, out: ^FontPanoseInfo) -> Result --- + font_face_get_character_coverage :: proc(self: ^FontFaceCore, out: ^BitSetCore) -> Result --- + font_face_has_script_tag :: proc(self: ^FontFaceCore, script_tag: Tag) -> i32 --- + font_face_has_feature_tag :: proc(self: ^FontFaceCore, feature_tag: Tag) -> i32 --- + font_face_has_variation_tag :: proc(self: ^FontFaceCore, variation_tag: Tag) -> i32 --- + font_face_get_script_tags :: proc(self: ^FontFaceCore, out: ^ArrayCore) -> Result --- + font_face_get_feature_tags :: proc(self: ^FontFaceCore, out: ^ArrayCore) -> Result --- + font_face_get_variation_tags :: proc(self: ^FontFaceCore, out: ^ArrayCore) -> Result --- +} + +//! Font face [C API]. +FontFaceCore :: struct { + _d: ObjectDetail, +} + +//! \cond INTERNAL +//! Font face [C API Virtual Function Table]. +FontFaceVirt :: struct { + base: ObjectVirtBase, +} + +//! Font face [C API Impl]. +FontFaceImpl :: struct { + //! Virtual function table. + virt: ^FontFaceVirt, + + //! Font face default weight (1..1000) [0 if font face is not initialized]. + weight: u16, + + //! Font face default stretch (1..9) [0 if font face is not initialized]. + stretch: u8, + + //! Font face default style. + style: u8, + + //! Font face information. + face_info: FontFaceInfo, + + //! Unique identifier assigned by Blend2D that can be used for caching. + unique_id: UniqueId, + + //! Font data. + data: FontDataCore, + + //! Full name. + full_name: StringCore, + + //! Family name. + family_name: StringCore, + + //! Subfamily name. + subfamily_name: StringCore, + + //! PostScript name. + post_script_name: StringCore, + + //! Font face metrics in design units. + design_metrics: FontDesignMetrics, + + //! Font face unicode coverage information as specified in the "OS/2" header. + coverage_info: FontCoverageInfo, + + //! Font face panose classification. + panose_info: FontPanoseInfo, +} + diff --git a/binding/fontfeaturesettings.odin b/binding/fontfeaturesettings.odin @@ -0,0 +1,100 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Font feature settings [C API]. +FontFeatureSettingsCore :: struct { + _d: ObjectDetail, +} + +//! \cond INTERNAL +//! Font feature settings [C API Impl]. +//! +//! \note This Impl's layout is fully compatible with \ref BLArrayImpl. +FontFeatureSettingsImpl :: struct { + //! Pointer to feature items. + data: ^FontFeatureItem, + + //! Number of feature items in `data`. + size: c.size_t, + + //! Capacity of `data`. + capacity: c.size_t, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \endcond + font_feature_settings_init :: proc(self: ^FontFeatureSettingsCore) -> Result --- + font_feature_settings_init_move :: proc(self: ^FontFeatureSettingsCore, other: ^FontFeatureSettingsCore) -> Result --- + font_feature_settings_init_weak :: proc(self: ^FontFeatureSettingsCore, other: ^FontFeatureSettingsCore) -> Result --- + font_feature_settings_destroy :: proc(self: ^FontFeatureSettingsCore) -> Result --- + font_feature_settings_reset :: proc(self: ^FontFeatureSettingsCore) -> Result --- + font_feature_settings_clear :: proc(self: ^FontFeatureSettingsCore) -> Result --- + font_feature_settings_shrink :: proc(self: ^FontFeatureSettingsCore) -> Result --- + font_feature_settings_assign_move :: proc(self: ^FontFeatureSettingsCore, other: ^FontFeatureSettingsCore) -> Result --- + font_feature_settings_assign_weak :: proc(self: ^FontFeatureSettingsCore, other: ^FontFeatureSettingsCore) -> Result --- + font_feature_settings_get_size :: proc(self: ^FontFeatureSettingsCore) -> c.size_t --- + font_feature_settings_get_capacity :: proc(self: ^FontFeatureSettingsCore) -> c.size_t --- + font_feature_settings_get_view :: proc(self: ^FontFeatureSettingsCore, out: ^FontFeatureSettingsView) -> Result --- + font_feature_settings_has_value :: proc(self: ^FontFeatureSettingsCore, feature_tag: Tag) -> i32 --- + font_feature_settings_get_value :: proc(self: ^FontFeatureSettingsCore, feature_tag: Tag) -> u32 --- + font_feature_settings_set_value :: proc(self: ^FontFeatureSettingsCore, feature_tag: Tag, value: u32) -> Result --- + font_feature_settings_remove_value :: proc(self: ^FontFeatureSettingsCore, feature_tag: Tag) -> Result --- + font_feature_settings_equals :: proc(a: ^FontFeatureSettingsCore, b: ^FontFeatureSettingsCore) -> i32 --- +} + +//! Associates a font feature tag with a value. Tag describes the feature (as provided by the font) and `value` +//! describes its value. Some features only allow boolean values 0 and 1 and some allow values up to 65535. +//! Values above 65535 are invalid, however, only \ref BL_FONT_FEATURE_INVALID_VALUE should be used as invalid +//! value in general. +//! +//! Registered OpenType features: +//! - https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags +//! - https://helpx.adobe.com/typekit/using/open-type-syntax.html +FontFeatureItem :: struct { + //! \name Members + //! \{ + + //! Feature tag (32-bit). + tag: Tag, + + //! Feature value. + //! + //! \note values greater than 65535 are invalid. + value: u32, +} + +//! A view unifying the representation of an internal storage used by \ref BLFontFeatureSettings. +FontFeatureSettingsView :: struct { + //! \name Members + //! \{ + + //! Pointer to font feature items, where each item describes a tag and its value. + //! + //! \note If the container is in SSO mode the `data` member will point to `sso_data`. + data: ^FontFeatureItem, + + //! Count of items in `data. + size: c.size_t, + + //! Unpacked SSO items into \ref BLFontFeatureItem array. + //! + //! \note This member won't be initialized or zeroed in case \ref BLFontFeatureSettings is not in SSO mode. And if the + //! container is in SSO mode only the number of items used will be overwritten by \ref BLFontFeatureSettings::get_view(). + sso_data: [36]FontFeatureItem, +} + diff --git a/binding/fontmanager.odin b/binding/fontmanager.odin @@ -0,0 +1,72 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Font manager [C API]. +FontManagerCore :: struct { + _d: ObjectDetail, +} + +//! \cond INTERNAL +//! Font manager [C API Virtual Function Table]. +FontManagerVirt :: struct { + base: ObjectVirtBase, +} + +//! Font manager [C API Impl]. +FontManagerImpl :: struct { + //! Virtual function table. + virt: ^FontManagerVirt, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \endcond + font_manager_init :: proc(self: ^FontManagerCore) -> Result --- + font_manager_init_move :: proc(self: ^FontManagerCore, other: ^FontManagerCore) -> Result --- + font_manager_init_weak :: proc(self: ^FontManagerCore, other: ^FontManagerCore) -> Result --- + font_manager_init_new :: proc(self: ^FontManagerCore) -> Result --- + font_manager_destroy :: proc(self: ^FontManagerCore) -> Result --- + font_manager_reset :: proc(self: ^FontManagerCore) -> Result --- + font_manager_assign_move :: proc(self: ^FontManagerCore, other: ^FontManagerCore) -> Result --- + font_manager_assign_weak :: proc(self: ^FontManagerCore, other: ^FontManagerCore) -> Result --- + font_manager_create :: proc(self: ^FontManagerCore) -> Result --- + font_manager_get_face_count :: proc(self: ^FontManagerCore) -> c.size_t --- + font_manager_get_family_count :: proc(self: ^FontManagerCore) -> c.size_t --- + font_manager_has_face :: proc(self: ^FontManagerCore, face: ^FontFaceCore) -> i32 --- + font_manager_add_face :: proc(self: ^FontManagerCore, face: ^FontFaceCore) -> Result --- + font_manager_query_face :: proc(self: ^FontManagerCore, name: cstring, name_size: c.size_t, properties: ^FontQueryProperties, out: ^FontFaceCore) -> Result --- + font_manager_query_faces_by_family_name :: proc(self: ^FontManagerCore, name: cstring, name_size: c.size_t, out: ^ArrayCore) -> Result --- + font_manager_equals :: proc(a: ^FontManagerCore, b: ^FontManagerCore) -> i32 --- +} + +//! Properties that can be used to query \ref BLFont and \ref BLFontFace. +//! +//! \sa BLFontManager. +FontQueryProperties :: struct { + //! \name Members + //! \{ + + //! Font style. + style: u32, + + //! Font weight. + weight: u32, + + //! Font stretch. + stretch: u32, +} + diff --git a/binding/fontvariationsettings.odin b/binding/fontvariationsettings.odin @@ -0,0 +1,91 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Font variation settings [C API]. +FontVariationSettingsCore :: struct { + _d: ObjectDetail, +} + +//! \cond INTERNAL +//! Font variation settings [C API Impl]. +//! +//! \note This Impl's layout is fully compatible with \ref BLArrayImpl. +FontVariationSettingsImpl :: struct { + //! Pointer to variation items. + data: ^FontVariationItem, + + //! Number of variation items in `data`. + size: c.size_t, + + //! Capacity of `data`. + capacity: c.size_t, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \endcond + font_variation_settings_init :: proc(self: ^FontVariationSettingsCore) -> Result --- + font_variation_settings_init_move :: proc(self: ^FontVariationSettingsCore, other: ^FontVariationSettingsCore) -> Result --- + font_variation_settings_init_weak :: proc(self: ^FontVariationSettingsCore, other: ^FontVariationSettingsCore) -> Result --- + font_variation_settings_destroy :: proc(self: ^FontVariationSettingsCore) -> Result --- + font_variation_settings_reset :: proc(self: ^FontVariationSettingsCore) -> Result --- + font_variation_settings_clear :: proc(self: ^FontVariationSettingsCore) -> Result --- + font_variation_settings_shrink :: proc(self: ^FontVariationSettingsCore) -> Result --- + font_variation_settings_assign_move :: proc(self: ^FontVariationSettingsCore, other: ^FontVariationSettingsCore) -> Result --- + font_variation_settings_assign_weak :: proc(self: ^FontVariationSettingsCore, other: ^FontVariationSettingsCore) -> Result --- + font_variation_settings_get_size :: proc(self: ^FontVariationSettingsCore) -> c.size_t --- + font_variation_settings_get_capacity :: proc(self: ^FontVariationSettingsCore) -> c.size_t --- + font_variation_settings_get_view :: proc(self: ^FontVariationSettingsCore, out: ^FontVariationSettingsView) -> Result --- + font_variation_settings_has_value :: proc(self: ^FontVariationSettingsCore, variation_tag: Tag) -> i32 --- + font_variation_settings_get_value :: proc(self: ^FontVariationSettingsCore, variation_tag: Tag) -> f32 --- + font_variation_settings_set_value :: proc(self: ^FontVariationSettingsCore, variation_tag: Tag, value: f32) -> Result --- + font_variation_settings_remove_value :: proc(self: ^FontVariationSettingsCore, variation_tag: Tag) -> Result --- + font_variation_settings_equals :: proc(a: ^FontVariationSettingsCore, b: ^FontVariationSettingsCore) -> i32 --- +} + +//! Associates a font variation tag with a value. +FontVariationItem :: struct { + //! \name Members + //! \{ + + //! Variation tag (32-bit). + tag: Tag, + + //! Variation value. + //! + //! \note values outside of [0, 1] range are invalid. + value: f32, +} + +//! A view unifying the representation of an internal storage used by \ref BLFontVariationSettings. +FontVariationSettingsView :: struct { + //! Pointer to font variation items, where each item describes a variation tag and its value. + //! + //! \note If the container is in SSO mode the `data` member will point to `sso_data`. + data: ^FontVariationItem, + + //! Count of items in `data. + size: c.size_t, + + //! Unpacked SSO items into \ref BLFontVariationItem array. + //! + //! \note This member won't be initialized or zeroed in case \ref BLFontVariationSettings is not in + //! SSO mode. And if the container is in SSO mode only the number of items used will be overwritten + //! by \ref BLFontVariationSettings::get_view(). + sso_data: [3]FontVariationItem, +} + diff --git a/binding/format.odin b/binding/format.odin @@ -0,0 +1,140 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! 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 | +//! +---------------------+---------------------+-----------------------------+ +//! ``` +Format :: enum u32 { + //! None or invalid pixel format. + NONE = 0, + + //! 32-bit premultiplied ARGB pixel format (8-bit components). + PRGB32 = 1, + + //! 32-bit (X)RGB pixel format (8-bit components, alpha ignored). + XRGB32 = 2, + + //! 8-bit alpha-only pixel format. + A8 = 3, + + // Maximum value of `BLFormat`. + MAX_VALUE = 3, + FORCE_UINT = 4294967295, +} + +//! Pixel format flags. +FormatFlags :: enum u32 { + //! No flags. + NO_FLAGS = 0, + + //! Pixel format provides RGB components. + FLAG_RGB = 1, + + //! Pixel format provides only alpha component. + FLAG_ALPHA = 2, + + //! A combination of `BL_FORMAT_FLAG_RGB | BL_FORMAT_FLAG_ALPHA`. + FLAG_RGBA = 3, + + //! Pixel format provides LUM component (and not RGB components). + FLAG_LUM = 4, + + //! A combination of `BL_FORMAT_FLAG_LUM | BL_FORMAT_FLAG_ALPHA`. + FLAG_LUMA = 6, + + //! Indexed pixel format the requires a palette (I/O only). + FLAG_INDEXED = 16, + + //! RGB components are premultiplied by alpha component. + FLAG_PREMULTIPLIED = 256, + + //! Pixel format doesn't use native byte-order (I/O only). + FLAG_BYTE_SWAP = 512, + + // The following flags are only informative. They are part of `bl_format_info[]`, but don't have to be passed to + // `BLPixelConverter` as they will always be calculated automatically. + + //! Pixel components are byte aligned (all 8bpp). + FLAG_BYTE_ALIGNED = 65536, + + //! 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. + FLAG_UNDEFINED_BITS = 131072, + + //! 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. + FLAG_LE = 0, + + //! 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. + FLAG_BE = 512, + FLAG_FORCE_UINT = 4294967295, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \name BLFormat - C API + //! \{ + format_info_query :: proc(self: ^FormatInfo, format: Format) -> Result --- + format_info_sanitize :: proc(self: ^FormatInfo) -> Result --- +} + +//! Provides a detailed information about a pixel format. Use \ref bl_format_info array to get an information of Blend2D +//! native pixel formats. +FormatInfo :: struct { + depth: u32, + flags: FormatFlags, + + using _: struct #raw_union { + using _: struct { + sizes: [4]u8, + shifts: [4]u8, + }, + + using _: struct { + r_size: u8, + g_size: u8, + b_size: u8, + a_size: u8, + r_shift: u8, + g_shift: u8, + b_shift: u8, + a_shift: u8, + }, + + palette: ^Rgba32, + }, +} + diff --git a/binding/geometry.odin b/binding/geometry.odin @@ -0,0 +1,244 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Direction of a geometry used by geometric primitives and paths. +GeometryDirection :: enum u32 { + //! No direction specified. + NONE = 0, + + //! Clockwise direction. + CW = 1, + + //! Counter-clockwise direction. + CCW = 2, + FORCE_UINT = 4294967295, +} + +//! Geometry type. +//! +//! Geometry describes a shape or path that can be either rendered or added to a BLPath container. Both \ref BLPath +//! and \ref BLContext provide functionality to work with all geometry types. Please note that each type provided +//! here requires to pass a matching struct or class to the function that consumes a `geometry_type` and `geometry_data` +//! arguments. +//! +//! \cond INTERNAL +//! \note Always modify `BL_GEOMETRY_TYPE_SIMPLE_LAST` and related functions when adding a new type to `BLGeometryType` +//! enum. Some functions just pass the geometry type and data to another function, but the rendering context must copy +//! simple types to a render job, which means that it must know which type is simple and also sizes of all simple +//! types, see `geometry_p.h` for more details about handling simple types. +//! \endcond +GeometryType :: enum u32 { + //! No geometry provided. + NONE = 0, + + //! BLBoxI struct. + BOXI = 1, + + //! BLBox struct. + BOXD = 2, + + //! BLRectI struct. + RECTI = 3, + + //! BLRect struct. + RECTD = 4, + + //! BLCircle struct. + CIRCLE = 5, + + //! BLEllipse struct. + ELLIPSE = 6, + + //! BLRoundRect struct. + ROUND_RECT = 7, + + //! BLArc struct. + ARC = 8, + + //! BLArc struct representing chord. + CHORD = 9, + + //! BLArc struct representing pie. + PIE = 10, + + //! BLLine struct. + LINE = 11, + + //! BLTriangle struct. + TRIANGLE = 12, + + //! BLArrayView<BLPointI> representing a polyline. + POLYLINEI = 13, + + //! BLArrayView<BLPoint> representing a polyline. + POLYLINED = 14, + + //! BLArrayView<BLPointI> representing a polygon. + POLYGONI = 15, + + //! BLArrayView<BLPoint> representing a polygon. + POLYGOND = 16, + + //! BLArrayView<BLBoxI> struct. + ARRAY_VIEW_BOXI = 17, + + //! BLArrayView<BLBox> struct. + ARRAY_VIEW_BOXD = 18, + + //! BLArrayView<BLRectI> struct. + ARRAY_VIEW_RECTI = 19, + + //! BLArrayView<BLRect> struct. + ARRAY_VIEW_RECTD = 20, + + //! BLPath (or BLPathCore). + PATH = 21, + + //! Maximum value of `BLGeometryType`. + MAX_VALUE = 21, + + //! \cond INTERNAL + + //! The last simple type. + SIMPLE_LAST = 12, + + //! \endcond + FORCE_UINT = 4294967295, +} + +//! Fill rule. +FillRule :: enum u32 { + //! Non-zero fill-rule. + NON_ZERO = 0, + + //! Even-odd fill-rule. + EVEN_ODD = 1, + + //! Maximum value of `BLFillRule`. + MAX_VALUE = 1, + FORCE_UINT = 4294967295, +} + +//! Hit-test result. +HitTest :: enum u32 { + //! Fully in. + IN = 0, + + //! Partially in/out. + PART = 1, + + //! Fully out. + OUT = 2, + + //! Hit test failed (invalid argument, NaNs, etc). + INVALID = 4294967295, + FORCE_UINT = 4294967295, +} + +//! Point specified as [x, y] using `int` as a storage type. +PointI :: struct { + x: i32, + y: i32, +} + +//! Size specified as [w, h] using `int` as a storage type. +SizeI :: struct { + w: i32, + h: i32, +} + +//! Box specified as [x0, y0, x1, y1] using `int` as a storage type. +BoxI :: struct { + x0: i32, + y0: i32, + x1: i32, + y1: i32, +} + +//! Rectangle specified as [x, y, w, h] using `int` as a storage type. +RectI :: struct { + x: i32, + y: i32, + w: i32, + h: i32, +} + +//! Point specified as [x, y] using `double` as a storage type. +Point :: struct { + x: f64, + y: f64, +} + +//! Size specified as [w, h] using `double` as a storage type. +Size :: struct { + w: f64, + h: f64, +} + +//! Box specified as [x0, y0, x1, y1] using `double` as a storage type. +Box :: struct { + x0: f64, + y0: f64, + x1: f64, + y1: f64, +} + +//! Rectangle specified as [x, y, w, h] using `double` as a storage type. +Rect :: struct { + x: f64, + y: f64, + w: f64, + h: f64, +} + +//! Line specified as [x0, y0, x1, y1] using `double` as a storage type. +Line :: struct { + x0, y0: f64, + x1, y1: f64, +} + +//! Triangle data specified as [x0, y0, x1, y1, x2, y2] using `double` as a storage type. +Triangle :: struct { + x0, y0: f64, + x1, y1: f64, + x2, y2: f64, +} + +//! Rounded rectangle specified as [x, y, w, h, rx, ry] using `double` as a storage type. +RoundRect :: struct { + x, y, w, h: f64, + rx, ry: f64, +} + +//! Circle specified as [cx, cy, r] using `double` as a storage type. +Circle :: struct { + cx, cy: f64, + r: f64, +} + +//! Ellipse specified as [cx, cy, rx, ry] using `double` as a storage type. +Ellipse :: struct { + cx, cy: f64, + rx, ry: f64, +} + +//! Arc specified as [cx, cy, rx, ry, start, sweep] using `double` as a storage type. +Arc :: struct { + cx, cy: f64, + rx, ry: f64, + start: f64, + sweep: f64, +} + diff --git a/binding/glyphbuffer.odin b/binding/glyphbuffer.odin @@ -0,0 +1,77 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Glyph buffer [Impl]. +//! +//! \note This is not a `BLObjectImpl` compatible Impl. +GlyphBufferImpl :: struct { + using _: struct #raw_union { + using _: struct { + //! Text (UCS4 code-points) or glyph content. + content: ^u32, + + //! Glyph placement data. + placement_data: ^GlyphPlacement, + + //! Number of either code points or glyph indexes in the glyph-buffer. + size: c.size_t, + + //! Reserved, used exclusively by BLGlyphRun. + reserved: u32, + + //! Flags shared between BLGlyphRun and BLGlyphBuffer. + flags: u32, + }, + + //! Glyph run data that can be passed directly to the rendering context. + //! + //! Glyph run shares data with other members like `content`, `placement_data`, `size`, and `flags`. When working + //! with data it's better to access these members directly as they are typed, whereas \ref BLGlyphRun stores + //! pointers as `const void*` as it offers more flexibility, which \ref BLGlyphRun doesn't need. + glyph_run: GlyphRun, + }, + + //! Glyph info data - additional information of each code-point or glyph. + info_data: ^GlyphInfo, +} + +//! Glyph buffer [C API]. +GlyphBufferCore :: struct { + impl: ^GlyphBufferImpl, + BL_DEFINE_OBJECT_DCAST: proc "c" () -> i32, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + glyph_buffer_init :: proc(self: ^GlyphBufferCore) -> Result --- + glyph_buffer_init_move :: proc(self: ^GlyphBufferCore, other: ^GlyphBufferCore) -> Result --- + glyph_buffer_destroy :: proc(self: ^GlyphBufferCore) -> Result --- + glyph_buffer_reset :: proc(self: ^GlyphBufferCore) -> Result --- + glyph_buffer_clear :: proc(self: ^GlyphBufferCore) -> Result --- + glyph_buffer_get_size :: proc(self: ^GlyphBufferCore) -> c.size_t --- + glyph_buffer_get_flags :: proc(self: ^GlyphBufferCore) -> u32 --- + glyph_buffer_get_glyph_run :: proc(self: ^GlyphBufferCore) -> ^GlyphRun --- + glyph_buffer_get_content :: proc(self: ^GlyphBufferCore) -> ^u32 --- + glyph_buffer_get_info_data :: proc(self: ^GlyphBufferCore) -> ^GlyphInfo --- + glyph_buffer_get_placement_data :: proc(self: ^GlyphBufferCore) -> ^GlyphPlacement --- + glyph_buffer_set_text :: proc(self: ^GlyphBufferCore, text_data: rawptr, size: c.size_t, encoding: TextEncoding) -> Result --- + glyph_buffer_set_glyphs :: proc(self: ^GlyphBufferCore, glyph_data: ^u32, size: c.size_t) -> Result --- + glyph_buffer_set_glyphs_from_struct :: proc(self: ^GlyphBufferCore, glyph_data: rawptr, size: c.size_t, glyph_id_size: c.size_t, glyph_id_advance: c.intptr_t) -> Result --- + glyph_buffer_set_debug_sink :: proc(self: ^GlyphBufferCore, sink: DebugMessageSinkFunc, user_data: rawptr) -> Result --- + glyph_buffer_reset_debug_sink :: proc(self: ^GlyphBufferCore) -> Result --- +} + diff --git a/binding/glyphrun.odin b/binding/glyphrun.odin @@ -0,0 +1,97 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Flags used by \ref BLGlyphRun. +GlyphRunFlags :: enum u32 { + //! No flags. + NO_FLAGS = 0, + + //! Glyph-run contains UCS-4 string and not glyphs (glyph-buffer only). + FLAG_UCS4_CONTENT = 268435456, + + //! Glyph-run was created from text that was not a valid unicode. + FLAG_INVALID_TEXT = 536870912, + + //! Not the whole text was mapped to glyphs (contains undefined glyphs). + FLAG_UNDEFINED_GLYPHS = 1073741824, + + //! Encountered invalid font data during text / glyph processing. + FLAG_INVALID_FONT_DATA = 2147483648, + FLAG_FORCE_UINT = 4294967295, +} + +//! Placement of glyphs stored in a \ref BLGlyphRun. +GlyphPlacementType :: enum u32 { + //! No placement (custom handling by \ref BLPathSinkFunc). + NONE = 0, + + //! Each glyph has a BLGlyphPlacement (advance + offset). + ADVANCE_OFFSET = 1, + + //! Each glyph has a BLPoint offset in design-space units. + DESIGN_UNITS = 2, + + //! Each glyph has a BLPoint offset in user-space units. + USER_UNITS = 3, + + //! Each glyph has a BLPoint offset in absolute units. + ABSOLUTE_UNITS = 4, + + //! Maximum value of `BLGlyphPlacementType`. + MAX_VALUE = 4, + FORCE_UINT = 4294967295, +} + +//! BLGlyphRun describes a set of consecutive glyphs and their placements. +//! +//! BLGlyphRun should only be used to pass glyph IDs and their placements to the rendering context. The purpose of +//! BLGlyphRun is to allow rendering glyphs, which could be shaped by various shaping engines (Blend2D, Harfbuzz, etc). +//! +//! BLGlyphRun allows to render glyphs that are stored as uint32_t[] array or part of a bigger structure (for example +//! `hb_glyph_info_t` used by HarfBuzz). Glyph placements at the moment use Blend2D's \ref BLGlyphPlacement or \ref +//! BLPoint, but it's possible to extend the data type in the future. +//! +//! See `BLGlyphRunPlacement` for placement modes provided by Blend2D. +GlyphRun :: struct { + //! \name Members + //! \{ + + //! Glyph id data (abstract, incremented by `glyph_advance`). + glyph_data: rawptr, + + //! Glyph placement data (abstract, incremented by `placement_advance`). + placement_data: rawptr, + + //! Size of the glyph-run in glyph units. + size: c.size_t, + + //! Reserved for future use, muse be zero. + reserved: u8, + + //! Type of placement, see \ref BLGlyphPlacementType. + placement_type: u8, + + //! Advance of `glyph_data` array. + glyph_advance: i8, + + //! Advance of `placement_data` array. + placement_advance: i8, + + //! Glyph-run flags. + flags: u32, +} + diff --git a/binding/gradient.odin b/binding/gradient.odin @@ -0,0 +1,188 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Gradient type. +GradientType :: enum u32 { + //! Linear gradient type. + LINEAR = 0, + + //! Radial gradient type. + RADIAL = 1, + + //! Conic gradient type. + CONIC = 2, + + //! Maximum value of `BLGradientType`. + MAX_VALUE = 2, + FORCE_UINT = 4294967295, +} + +//! Gradient data index. +GradientValue :: enum u32 { + //! x0 - start 'x' for a Linear gradient and `x` center for both Radial and Conic gradients. + COMMON_X0 = 0, + + //! y0 - start 'y' for a Linear gradient and `y` center for both Radial and Conic gradients. + COMMON_Y0 = 1, + + //! x1 - end 'x' for a Linear gradient and focal point `x` for a Radial gradient. + COMMON_X1 = 2, + + //! y1 - end 'y' for a Linear/gradient and focal point `y` for a Radial gradient. + COMMON_Y1 = 3, + + //! Radial gradient center radius. + RADIAL_R0 = 4, + + //! Radial gradient focal radius. + RADIAL_R1 = 5, + + //! Conic gradient angle. + CONIC_ANGLE = 2, + + //! Conic gradient angle. + CONIC_REPEAT = 3, + + //! Maximum value of `BLGradientValue`. + MAX_VALUE = 5, + FORCE_UINT = 4294967295, +} + +//! Gradient rendering quality. +GradientQuality :: enum u32 { + //! Nearest neighbor. + NEAREST = 0, + + //! Use smoothing, if available (currently never available). + SMOOTH = 1, + + //! The renderer will use an implementation-specific dithering algorithm to prevent banding. + DITHER = 2, + + //! Maximum value of `BLGradientQuality`. + MAX_VALUE = 2, + FORCE_UINT = 4294967295, +} + +//! Defines an `offset` and `rgba` color that us used by \ref BLGradient to define a linear transition between colors. +GradientStop :: struct { + offset: f64, + rgba: Rgba64, +} + +//! Linear gradient values packed into a structure. +LinearGradientValues :: struct { + x0: f64, + y0: f64, + x1: f64, + y1: f64, +} + +//! Radial gradient values packed into a structure. +RadialGradientValues :: struct { + x0: f64, + y0: f64, + x1: f64, + y1: f64, + r0: f64, + r1: f64, +} + +//! Conic gradient values packed into a structure. +ConicGradientValues :: struct { + x0: f64, + y0: f64, + angle: f64, + repeat: f64, +} + +//! Gradient [C API]. +GradientCore :: struct { + _d: ObjectDetail, +} + +//! \cond INTERNAL +//! Gradient [C API Impl]. +GradientImpl :: struct { + //! Gradient stop data. + stops: ^GradientStop, + + //! Gradient stop count. + size: c.size_t, + + //! Stop capacity. + capacity: c.size_t, + + //! Gradient transformation matrix. + transform: Matrix2D, + + using _: struct #raw_union { + //! Gradient values (coordinates, radius, angle). + values: [6]f64, + + //! Linear parameters. + linear: LinearGradientValues, + + //! Radial parameters. + radial: RadialGradientValues, + + //! Conic parameters. + conic: ConicGradientValues, + }, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \endcond + gradient_init :: proc(self: ^GradientCore) -> Result --- + gradient_init_move :: proc(self: ^GradientCore, other: ^GradientCore) -> Result --- + gradient_init_weak :: proc(self: ^GradientCore, other: ^GradientCore) -> Result --- + gradient_init_as :: proc(self: ^GradientCore, type: GradientType, values: rawptr, extend_mode: ExtendMode, stops: ^GradientStop, n: c.size_t, transform: ^Matrix2D) -> Result --- + gradient_destroy :: proc(self: ^GradientCore) -> Result --- + gradient_reset :: proc(self: ^GradientCore) -> Result --- + gradient_assign_move :: proc(self: ^GradientCore, other: ^GradientCore) -> Result --- + gradient_assign_weak :: proc(self: ^GradientCore, other: ^GradientCore) -> Result --- + gradient_create :: proc(self: ^GradientCore, type: GradientType, values: rawptr, extend_mode: ExtendMode, stops: ^GradientStop, n: c.size_t, transform: ^Matrix2D) -> Result --- + gradient_shrink :: proc(self: ^GradientCore) -> Result --- + gradient_reserve :: proc(self: ^GradientCore, n: c.size_t) -> Result --- + gradient_get_type :: proc(self: ^GradientCore) -> GradientType --- + gradient_set_type :: proc(self: ^GradientCore, type: GradientType) -> Result --- + gradient_get_extend_mode :: proc(self: ^GradientCore) -> ExtendMode --- + gradient_set_extend_mode :: proc(self: ^GradientCore, extend_mode: ExtendMode) -> Result --- + gradient_get_value :: proc(self: ^GradientCore, index: c.size_t) -> f64 --- + gradient_set_value :: proc(self: ^GradientCore, index: c.size_t, value: f64) -> Result --- + gradient_set_values :: proc(self: ^GradientCore, index: c.size_t, values: ^f64, n: c.size_t) -> Result --- + gradient_get_size :: proc(self: ^GradientCore) -> c.size_t --- + gradient_get_capacity :: proc(self: ^GradientCore) -> c.size_t --- + gradient_get_stops :: proc(self: ^GradientCore) -> ^GradientStop --- + gradient_reset_stops :: proc(self: ^GradientCore) -> Result --- + gradient_assign_stops :: proc(self: ^GradientCore, stops: ^GradientStop, n: c.size_t) -> Result --- + gradient_add_stop_rgba32 :: proc(self: ^GradientCore, offset: f64, argb32: u32) -> Result --- + gradient_add_stop_rgba64 :: proc(self: ^GradientCore, offset: f64, argb64: u64) -> Result --- + gradient_remove_stop :: proc(self: ^GradientCore, index: c.size_t) -> Result --- + gradient_remove_stop_by_offset :: proc(self: ^GradientCore, offset: f64, all: u32) -> Result --- + gradient_remove_stops_by_index :: proc(self: ^GradientCore, r_start: c.size_t, r_end: c.size_t) -> Result --- + gradient_remove_stops_by_offset :: proc(self: ^GradientCore, offset_min: f64, offset_max: f64) -> Result --- + gradient_replace_stop_rgba32 :: proc(self: ^GradientCore, index: c.size_t, offset: f64, rgba32: u32) -> Result --- + gradient_replace_stop_rgba64 :: proc(self: ^GradientCore, index: c.size_t, offset: f64, rgba64: u64) -> Result --- + gradient_index_of_stop :: proc(self: ^GradientCore, offset: f64) -> c.size_t --- + gradient_get_transform :: proc(self: ^GradientCore, transform_out: ^Matrix2D) -> Result --- + gradient_get_transform_type :: proc(self: ^GradientCore) -> TransformType --- + gradient_apply_transform_op :: proc(self: ^GradientCore, op_type: TransformOp, op_data: rawptr) -> Result --- + gradient_equals :: proc(a: ^GradientCore, b: ^GradientCore) -> i32 --- +} + diff --git a/binding/image.odin b/binding/image.odin @@ -0,0 +1,157 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Flags used by `BLImageInfo`. +ImageInfoFlags :: enum u32 { + //! No flags. + NO_FLAGS = 0, + + //! Progressive mode. + PROGRESSIVE = 1, + FORCE_UINT = 4294967295, +} + +//! Filter type used by `BLImage::scale()`. +ImageScaleFilter :: enum u32 { + //! No filter or uninitialized. + NONE = 0, + + //! Nearest neighbor filter (radius 1.0). + NEAREST = 1, + + //! Bilinear filter (radius 1.0). + BILINEAR = 2, + + //! Bicubic filter (radius 2.0). + BICUBIC = 3, + + //! Lanczos filter (radius 2.0). + LANCZOS = 4, + + //! Maximum value of `BLImageScaleFilter`. + MAX_VALUE = 4, + FORCE_UINT = 4294967295, +} + +//! Data that describes a raster image. Used by \ref BLImage. +ImageData :: struct { + //! Pixel data, starting at the top left corner of the image. + //! + //! \note If the stride is negative the image data would start at the bottom. + pixel_data: rawptr, + + //! Stride (in bytes) of image data (positive when image data starts at top-left, negative when it starts at + //! bottom-left). + stride: c.intptr_t, + + //! Size of the image. + size: SizeI, + + //! Pixel format, see \ref BLFormat. + format: u32, + flags: u32, +} + +//! Image information provided by image codecs. +ImageInfo :: struct { + //! Image size. + size: SizeI, + + //! Pixel density per one meter, can contain fractions. + density: Size, + + //! Image flags. + flags: u32, + + //! Image depth. + depth: u16, + + //! Number of planes. + plane_count: u16, + + //! Number of frames (0 = unknown/unspecified). + frame_count: u64, + + //! Number of animation repeats (0 == infinite). + repeat_count: u32, + + //! Reserved for future use. + reserved: [3]u32, + + //! Image format (as understood by codec). + format: [16]i8, + + //! Image compression (as understood by codec). + compression: [16]i8, +} + +//! 2D raster image [C API]. +ImageCore :: struct { + _d: ObjectDetail, +} + +//! \cond INTERNAL +//! 2D raster image [C API Impl]. +ImageImpl :: struct { + //! Pixel data. + pixel_data: rawptr, + + //! Image stride. + stride: c.intptr_t, + + //! Image size. + size: SizeI, + + //! Image format. + format: u8, + + //! Image flags. + flags: u8, + + //! Image depth (in bits). + depth: u16, + + //! Reserved for future use, must be zero. + reserved: [4]u8, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \endcond + image_init :: proc(self: ^ImageCore) -> Result --- + image_init_move :: proc(self: ^ImageCore, other: ^ImageCore) -> Result --- + image_init_weak :: proc(self: ^ImageCore, other: ^ImageCore) -> Result --- + image_init_as :: proc(self: ^ImageCore, w: i32, h: i32, format: Format) -> Result --- + image_init_as_from_data :: proc(self: ^ImageCore, w: i32, h: i32, format: Format, pixel_data: rawptr, stride: c.intptr_t, access_flags: DataAccessFlags, destroy_func: DestroyExternalDataFunc, user_data: rawptr) -> Result --- + image_destroy :: proc(self: ^ImageCore) -> Result --- + image_reset :: proc(self: ^ImageCore) -> Result --- + image_assign_move :: proc(self: ^ImageCore, other: ^ImageCore) -> Result --- + image_assign_weak :: proc(self: ^ImageCore, other: ^ImageCore) -> Result --- + image_assign_deep :: proc(self: ^ImageCore, other: ^ImageCore) -> Result --- + image_create :: proc(self: ^ImageCore, w: i32, h: i32, format: Format) -> Result --- + image_create_from_data :: proc(self: ^ImageCore, w: i32, h: i32, format: Format, pixel_data: rawptr, stride: c.intptr_t, access_flags: DataAccessFlags, destroy_func: DestroyExternalDataFunc, user_data: rawptr) -> Result --- + image_get_data :: proc(self: ^ImageCore, data_out: ^ImageData) -> Result --- + image_make_mutable :: proc(self: ^ImageCore, data_out: ^ImageData) -> Result --- + image_convert :: proc(self: ^ImageCore, format: Format) -> Result --- + image_equals :: proc(a: ^ImageCore, b: ^ImageCore) -> i32 --- + image_scale :: proc(dst: ^ImageCore, src: ^ImageCore, size: ^SizeI, filter: ImageScaleFilter) -> Result --- + image_read_from_file :: proc(self: ^ImageCore, file_name: cstring, codecs: ^ArrayCore) -> Result --- + image_read_from_data :: proc(self: ^ImageCore, data: rawptr, size: c.size_t, codecs: ^ArrayCore) -> Result --- + image_write_to_file :: proc(self: ^ImageCore, file_name: cstring, codec: ^ImageCodecCore) -> Result --- + image_write_to_data :: proc(self: ^ImageCore, dst: ^ArrayCore, codec: ^ImageCodecCore) -> Result --- +} + diff --git a/binding/imagecodec.odin b/binding/imagecodec.odin @@ -0,0 +1,109 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Image codec [C API]. +ImageCodecCore :: struct { + _d: ObjectDetail, +} + +//! \cond +//! Image codec [C API Virtual Function Table]. +ImageCodecVirt :: struct { + base: ObjectVirtBase, + inspect_data: proc "c" (impl: ^ImageCodecImpl, data: ^u8, size: c.size_t) -> u32, + create_decoder: proc "c" (impl: ^ImageCodecImpl, dst: ^ImageDecoderCore) -> Result, + create_encoder: proc "c" (impl: ^ImageCodecImpl, dst: ^ImageEncoderCore) -> Result, +} + +//! Image codec [C API Impl]. +ImageCodecImpl :: struct { + //! \name Members + //! \{ + + //! Virtual function table. + virt: ^ImageCodecVirt, + + //! Image codec name like "PNG", "JPEG", etc... + name: StringCore, + + //! Image codec vendor string, built-in codecs use "Blend2D" as a vendor string. + vendor: StringCore, + + //! Mime types. + mime_type: StringCore, + + //! Known file extensions used by this image codec separated by "|". + extensions: StringCore, + + //! Image codec features. + features: u32, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \endcond + image_codec_init :: proc(self: ^ImageCodecCore) -> Result --- + image_codec_init_move :: proc(self: ^ImageCodecCore, other: ^ImageCodecCore) -> Result --- + image_codec_init_weak :: proc(self: ^ImageCodecCore, other: ^ImageCodecCore) -> Result --- + image_codec_init_by_name :: proc(self: ^ImageCodecCore, name: cstring, size: c.size_t, codecs: ^ArrayCore) -> Result --- + image_codec_destroy :: proc(self: ^ImageCodecCore) -> Result --- + image_codec_reset :: proc(self: ^ImageCodecCore) -> Result --- + image_codec_assign_move :: proc(self: ^ImageCodecCore, other: ^ImageCodecCore) -> Result --- + image_codec_assign_weak :: proc(self: ^ImageCodecCore, other: ^ImageCodecCore) -> Result --- + image_codec_find_by_name :: proc(self: ^ImageCodecCore, name: cstring, size: c.size_t, codecs: ^ArrayCore) -> Result --- + image_codec_find_by_extension :: proc(self: ^ImageCodecCore, name: cstring, size: c.size_t, codecs: ^ArrayCore) -> Result --- + image_codec_find_by_data :: proc(self: ^ImageCodecCore, data: rawptr, size: c.size_t, codecs: ^ArrayCore) -> Result --- + image_codec_inspect_data :: proc(self: ^ImageCodecCore, data: rawptr, size: c.size_t) -> u32 --- + image_codec_create_decoder :: proc(self: ^ImageCodecCore, dst: ^ImageDecoderCore) -> Result --- + image_codec_create_encoder :: proc(self: ^ImageCodecCore, dst: ^ImageEncoderCore) -> Result --- + image_codec_array_init_built_in_codecs :: proc(self: ^ArrayCore) -> Result --- + image_codec_array_assign_built_in_codecs :: proc(self: ^ArrayCore) -> Result --- + image_codec_add_to_built_in :: proc(codec: ^ImageCodecCore) -> Result --- + image_codec_remove_from_built_in :: proc(codec: ^ImageCodecCore) -> Result --- +} + +//! Image codec feature bits. +ImageCodecFeatures :: enum u32 { + //! No features. + NO_FEATURES = 0, + + //! Image codec supports reading images (can create BLImageDecoder). + FEATURE_READ = 1, + + //! Image codec supports writing images (can create BLImageEncoder). + FEATURE_WRITE = 2, + + //! Image codec supports lossless compression. + FEATURE_LOSSLESS = 4, + + //! Image codec supports loosy compression. + FEATURE_LOSSY = 8, + + //! Image codec supports writing multiple frames (GIF). + FEATURE_MULTI_FRAME = 16, + + //! Image codec supports IPTC metadata. + FEATURE_IPTC = 268435456, + + //! Image codec supports EXIF metadata. + FEATURE_EXIF = 536870912, + + //! Image codec supports XMP metadata. + FEATURE_XMP = 1073741824, + FEATURE_FORCE_UINT = 4294967295, +} + diff --git a/binding/imagedecoder.odin b/binding/imagedecoder.odin @@ -0,0 +1,70 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Image decoder [C API] +ImageDecoderCore :: struct { + _d: ObjectDetail, +} + +//! \cond INTERNAL +//! Image decoder [C API Virtual Function Table]. +ImageDecoderVirt :: struct { + base: ObjectVirtBase, + restart: proc "c" (impl: ^ImageDecoderImpl) -> Result, + read_info: proc "c" (impl: ^ImageDecoderImpl, info_out: ^ImageInfo, data: ^u8, size: c.size_t) -> Result, + read_frame: proc "c" (impl: ^ImageDecoderImpl, image_out: ^ImageCore, data: ^u8, size: c.size_t) -> Result, +} + +//! Image decoder [C API Impl]. +ImageDecoderImpl :: struct { + //! \name Members + //! \{ + + //! Virtual function table. + virt: ^ImageDecoderVirt, + + //! Image codec that created this decoder. + codec: ImageCodecCore, + + //! Last faulty result (if failed). + last_result: Result, + + //! Handle in case that this decoder wraps a third-party library. + handle: rawptr, + + //! Current frame index. + frame_index: u64, + + //! Position in source buffer. + buffer_index: c.size_t, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \endcond + image_decoder_init :: proc(self: ^ImageDecoderCore) -> Result --- + image_decoder_init_move :: proc(self: ^ImageDecoderCore, other: ^ImageDecoderCore) -> Result --- + image_decoder_init_weak :: proc(self: ^ImageDecoderCore, other: ^ImageDecoderCore) -> Result --- + image_decoder_destroy :: proc(self: ^ImageDecoderCore) -> Result --- + image_decoder_reset :: proc(self: ^ImageDecoderCore) -> Result --- + image_decoder_assign_move :: proc(self: ^ImageDecoderCore, other: ^ImageDecoderCore) -> Result --- + image_decoder_assign_weak :: proc(self: ^ImageDecoderCore, other: ^ImageDecoderCore) -> Result --- + image_decoder_restart :: proc(self: ^ImageDecoderCore) -> Result --- + image_decoder_read_info :: proc(self: ^ImageDecoderCore, info_out: ^ImageInfo, data: ^u8, size: c.size_t) -> Result --- + image_decoder_read_frame :: proc(self: ^ImageDecoderCore, image_out: ^ImageCore, data: ^u8, size: c.size_t) -> Result --- +} + diff --git a/binding/imageencoder.odin b/binding/imageencoder.odin @@ -0,0 +1,68 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Image encoder [C API]. +ImageEncoderCore :: struct { + _d: ObjectDetail, +} + +//! \cond INTERNAL +//! Image encoder [Virtual Function Table]. +ImageEncoderVirt :: struct { + base: ObjectVirtBase, + restart: proc "c" (impl: ^ImageEncoderImpl) -> Result, + write_frame: proc "c" (impl: ^ImageEncoderImpl, dst: ^ArrayCore, image: ^ImageCore) -> Result, +} + +//! Image encoder [Impl]. +ImageEncoderImpl :: struct { + //! \name Members + //! \{ + + //! Virtual function table. + virt: ^ImageEncoderVirt, + + //! Image codec that created this encoder. + codec: ImageCodecCore, + + //! Last faulty result (if failed). + last_result: Result, + + //! Handle in case that this encoder wraps a third-party library. + handle: rawptr, + + //! Current frame index. + frame_index: u64, + + //! Position in source buffer. + buffer_index: c.size_t, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \endcond + image_encoder_init :: proc(self: ^ImageEncoderCore) -> Result --- + image_encoder_init_move :: proc(self: ^ImageEncoderCore, other: ^ImageEncoderCore) -> Result --- + image_encoder_init_weak :: proc(self: ^ImageEncoderCore, other: ^ImageEncoderCore) -> Result --- + image_encoder_destroy :: proc(self: ^ImageEncoderCore) -> Result --- + image_encoder_reset :: proc(self: ^ImageEncoderCore) -> Result --- + image_encoder_assign_move :: proc(self: ^ImageEncoderCore, other: ^ImageEncoderCore) -> Result --- + image_encoder_assign_weak :: proc(self: ^ImageEncoderCore, other: ^ImageEncoderCore) -> Result --- + image_encoder_restart :: proc(self: ^ImageEncoderCore) -> Result --- + image_encoder_write_frame :: proc(self: ^ImageEncoderCore, dst: ^ArrayCore, image: ^ImageCore) -> Result --- +} + diff --git a/binding/matrix.odin b/binding/matrix.odin @@ -0,0 +1,135 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Transformation matrix type that can be obtained by calling `BLMatrix2D::type()`. +//! +//! ``` +//! Identity Transl. Scale Swap Affine +//! [1 0] [1 0] [. 0] [0 .] [. .] +//! [0 1] [0 1] [0 .] [. 0] [. .] +//! [0 0] [. .] [. .] [. .] [. .] +//! ``` +TransformType :: enum u32 { + //! Identity matrix. + TRANSFORM_TYPE_IDENTITY = 0, + + //! Has translation part (the rest is like identity). + TRANSFORM_TYPE_TRANSLATE = 1, + + //! Has translation and scaling parts. + TRANSFORM_TYPE_SCALE = 2, + + //! Has translation and scaling parts, however scaling swaps X/Y. + TRANSFORM_TYPE_SWAP = 3, + + //! Generic affine matrix. + TRANSFORM_TYPE_AFFINE = 4, + + //! Invalid/degenerate matrix not useful for transformations. + TRANSFORM_TYPE_INVALID = 5, + + //! Maximum value of `BLTransformType`. + TRANSFORM_TYPE_MAX_VALUE = 5, + MATRIX2D_TYPE_FORCE_UINT = 4294967295, +} + +//! Transformation matrix operation type. +TransformOp :: enum u32 { + //! Reset matrix to identity (argument ignored, should be nullptr). + RESET = 0, + + //! Assign (copy) the other matrix. + ASSIGN = 1, + + //! Translate the matrix by [x, y]. + TRANSLATE = 2, + + //! Scale the matrix by [x, y]. + SCALE = 3, + + //! Skew the matrix by [x, y]. + SKEW = 4, + + //! Rotate the matrix by the given angle about [0, 0]. + ROTATE = 5, + + //! Rotate the matrix by the given angle about [x, y]. + ROTATE_PT = 6, + + //! Transform this matrix by other \ref BLMatrix2D. + TRANSFORM = 7, + + //! Post-translate the matrix by [x, y]. + POST_TRANSLATE = 8, + + //! Post-scale the matrix by [x, y]. + POST_SCALE = 9, + + //! Post-skew the matrix by [x, y]. + POST_SKEW = 10, + + //! Post-rotate the matrix about [0, 0]. + POST_ROTATE = 11, + + //! Post-rotate the matrix about a reference BLPoint. + POST_ROTATE_PT = 12, + + //! Post-transform this matrix by other \ref BLMatrix2D. + POST_TRANSFORM = 13, + + //! Maximum value of `BLTransformOp`. + MAX_VALUE = 13, + FORCE_UINT = 4294967295, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \name BLMatrix2D - C API + //! + //! Functions that initialize and manipulate \ref BLMatrix2D content. + //! + //! \{ + matrix2d_set_identity :: proc(self: ^Matrix2D) -> Result --- + matrix2d_set_translation :: proc(self: ^Matrix2D, x: f64, y: f64) -> Result --- + matrix2d_set_scaling :: proc(self: ^Matrix2D, x: f64, y: f64) -> Result --- + matrix2d_set_skewing :: proc(self: ^Matrix2D, x: f64, y: f64) -> Result --- + matrix2d_set_rotation :: proc(self: ^Matrix2D, angle: f64, cx: f64, cy: f64) -> Result --- + matrix2d_apply_op :: proc(self: ^Matrix2D, op_type: TransformOp, op_data: rawptr) -> Result --- + matrix2d_invert :: proc(dst: ^Matrix2D, src: ^Matrix2D) -> Result --- + matrix2d_get_type :: proc(self: ^Matrix2D) -> TransformType --- + matrix2d_map_pointd_array :: proc(self: ^Matrix2D, dst: ^Point, src: ^Point, count: c.size_t) -> Result --- +} + +//! 2D matrix represents an affine transformation matrix that can be used to transform geometry and images. +Matrix2D :: struct { + // TODO: Remove the union, keep only m[] array. + using _: struct #raw_union { + //! Matrix values stored in array. + m: [6]f64, + + //! Matrix values that map `m` to named values that can be used directly. + using _: struct { + m00: f64, + m01: f64, + m10: f64, + m11: f64, + m20: f64, + m21: f64, + }, + }, +} + diff --git a/binding/object.odin b/binding/object.odin @@ -0,0 +1,336 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + +ObjectImpl :: struct {} + +//! \cond INTERNAL +//! Defines a start offset of each field or flag in object info - the shift can be then used to get/set value from/to +//! info bits. +ObjectInfoShift :: enum u32 { + P_SHIFT = 0, + Q_SHIFT = 8, + C_SHIFT = 8, + B_SHIFT = 12, + A_SHIFT = 16, + TYPE_SHIFT = 22, + R_SHIFT = 29, + D_SHIFT = 30, + M_SHIFT = 31, + SHIFT_FORCE_UINT = 4294967295, +} + +//! 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. +ObjectInfoBits :: enum u32 { + //! Mask describing 'P' payload (8 bits). + P_MASK = 255, // [........|........|........|pppppppp] + + //! Mask describing 'Q' payload (8 bits aliased with 'bbbbcccc' bits). + Q_MASK = 65280, // [........|........|qqqqqqqq|........] + + //! Mask describing 'C' payload (4 bits). + C_MASK = 3840, // [........|........|....cccc|........] + + //! Mask describing 'B' payload (4 bits). + B_MASK = 61440, // [........|........|bbbb....|........] + + //! Mask describing 'A' payload (6 bits). + A_MASK = 4128768, // [........|..aaaaaa|........|........] + + //! Mask of all payload fields combined, except 'M', 'T', type identification, and 'R' (RefCounted marker). + FIELDS_MASK = 4194303, + + //! Mask describing object type (8 bits), see \ref BLObjectType. + TYPE_MASK = 532676608, // [...ttttt|tt......|........|........] + + //! 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). + R_FLAG = 536870912, // [..R.....|........|........|........] + + //! Flag describing a dynamic object - if this flag is not set, it means the object is in SSO mode. + D_FLAG = 1073741824, // [.D......|........|........|........] + + //! Flag describing a valid object compatible with \ref BLObjectCore interface (otherwise it's most likely \ref BLRgba). + M_FLAG = 2147483648, // [M.......|........|........|........] + + //! A combination of `BL_OBJECT_INFO_M_FLAG` and `BL_OBJECT_INFO_D_FLAG` flags. + MD_FLAGS = 3221225472, + + //! A combination of `BL_OBJECT_INFO_M_FLAG`, `BL_OBJECT_INFO_D_FLAG`, `BL_OBJECT_INFO_R_FLAG` flags. + MDR_FLAGS = 3758096384, + BITS_FORCE_UINT = 4294967295, +} + +//! Object type identifier. +ObjectType :: enum u32 { + //! Object represents a \ref BLRgba value stored as four 32-bit floating point components (can be used as Style). + RGBA = 0, + + //! Object represents a \ref BLRgba32 value stored as 32-bit integer in `0xAARRGGBB` form. + RGBA32 = 1, + + //! Object represents a \ref BLRgba64 value stored as 64-bit integer in `0xAAAARRRRGGGGBBBB` form. + RGBA64 = 2, + + //! Object is `Null` (can be used as style). + NULL = 3, + + //! Object is \ref BLPattern (can be used as style). + PATTERN = 4, + + //! Object is \ref BLGradient (can be used as style). + GRADIENT = 5, + + //! Object is \ref BLImage. + IMAGE = 9, + + //! Object is \ref BLPath. + PATH = 10, + + //! Object is \ref BLFont. + FONT = 16, + + //! Object is \ref BLFontFeatureSettings. + FONT_FEATURE_SETTINGS = 17, + + //! Object is \ref BLFontVariationSettings. + FONT_VARIATION_SETTINGS = 18, + + //! Object is \ref BLBitArray. + BIT_ARRAY = 25, + + //! Object is \ref BLBitSet. + BIT_SET = 26, + + //! Object represents a boolean value. + BOOL = 28, + + //! Object represents a 64-bit signed integer value. + INT64 = 29, + + //! Object represents a 64-bit unsigned integer value. + UINT64 = 30, + + //! Object represents a 64-bit floating point value. + DOUBLE = 31, + + //! Object is \ref BLString. + STRING = 32, + + //! Object is \ref BLArray<T> where `T` is a `BLObject` compatible type. + ARRAY_OBJECT = 33, + + //! Object is \ref BLArray<T> where `T` matches 8-bit signed integral type. + ARRAY_INT8 = 34, + + //! Object is \ref BLArray<T> where `T` matches 8-bit unsigned integral type. + ARRAY_UINT8 = 35, + + //! Object is \ref BLArray<T> where `T` matches 16-bit signed integral type. + ARRAY_INT16 = 36, + + //! Object is \ref BLArray<T> where `T` matches 16-bit unsigned integral type. + ARRAY_UINT16 = 37, + + //! Object is \ref BLArray<T> where `T` matches 32-bit signed integral type. + ARRAY_INT32 = 38, + + //! Object is \ref BLArray<T> where `T` matches 32-bit unsigned integral type. + ARRAY_UINT32 = 39, + + //! Object is \ref BLArray<T> where `T` matches 64-bit signed integral type. + ARRAY_INT64 = 40, + + //! Object is \ref BLArray<T> where `T` matches 64-bit unsigned integral type. + ARRAY_UINT64 = 41, + + //! Object is \ref BLArray<T> where `T` matches 32-bit floating point type. + ARRAY_FLOAT32 = 42, + + //! Object is \ref BLArray<T> where `T` matches 64-bit floating point type. + ARRAY_FLOAT64 = 43, + + //! Object is \ref BLArray<T> where `T` is a struct of size 1. + ARRAY_STRUCT_1 = 44, + + //! Object is \ref BLArray<T> where `T` is a struct of size 2. + ARRAY_STRUCT_2 = 45, + + //! Object is \ref BLArray<T> where `T` is a struct of size 3. + ARRAY_STRUCT_3 = 46, + + //! Object is \ref BLArray<T> where `T` is a struct of size 4. + ARRAY_STRUCT_4 = 47, + + //! Object is \ref BLArray<T> where `T` is a struct of size 6. + ARRAY_STRUCT_6 = 48, + + //! Object is \ref BLArray<T> where `T` is a struct of size 8. + ARRAY_STRUCT_8 = 49, + + //! Object is \ref BLArray<T> where `T` is a struct of size 10. + ARRAY_STRUCT_10 = 50, + + //! Object is \ref BLArray<T> where `T` is a struct of size 12. + ARRAY_STRUCT_12 = 51, + + //! Object is \ref BLArray<T> where `T` is a struct of size 16. + ARRAY_STRUCT_16 = 52, + + //! Object is \ref BLArray<T> where `T` is a struct of size 20. + ARRAY_STRUCT_20 = 53, + + //! Object is \ref BLArray<T> where `T` is a struct of size 24. + ARRAY_STRUCT_24 = 54, + + //! Object is \ref BLArray<T> where `T` is a struct of size 32. + ARRAY_STRUCT_32 = 55, + + //! Object is \ref BLContext. + CONTEXT = 100, + + //! Object is \ref BLImageCodec. + IMAGE_CODEC = 101, + + //! Object is \ref BLImageDecoder. + IMAGE_DECODER = 102, + + //! Object is \ref BLImageEncoder. + IMAGE_ENCODER = 103, + + //! Object is \ref BLFontFace. + FONT_FACE = 104, + + //! Object is \ref BLFontData. + FONT_DATA = 105, + + //! Object is \ref BLFontManager. + FONT_MANAGER = 106, + + //! Minimum object type of an array object. + MIN_ARRAY = 33, + + //! Maximum object type of an array object. + MAX_ARRAY = 55, + + //! Minimum object type identifier that can be used as a style. + MIN_STYLE = 0, + + //! Maximum object type identifier that can be used as a style. + MAX_STYLE = 5, + + //! Minimum object type of an object with virtual function table. + MIN_VIRTUAL = 100, + + //! Maximum object type of an object with virtual function table. + MAX_VIRTUAL = 127, + + //! Maximum possible value of an object type, including identifiers reserved for the future. + MAX_VALUE = 127, + FORCE_UINT = 4294967295, +} + +//! Information bits used by \ref BLObjectCore and all Blend2D compatible objects inheriting it. +ObjectInfo :: struct { + //! \name Members + //! \{ + + //! Stores all object info bits. + bits: u32, +} + +//! Defines a BLObject layout that all objects must use. +ObjectDetail :: struct #raw_union { + impl: ^ObjectImpl, + char_data: [16]i8, + i8_data: [16]i8, + u8_data: [16]u8, + i16_data: [8]i16, + u16_data: [8]u16, + i32_data: [4]i32, + u32_data: [4]u32, + i64_data: [2]i64, + u64_data: [2]u64, + f32_data: [4]f32, + f64_data: [2]f64, + rgba: Rgba, + rgba32: Rgba32, + rgba64: Rgba64, + + using _: struct { + u32_data_overlap: [2]u32, + impl_payload: u32, + info: ObjectInfo, + }, +} + +//! 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. +DestroyExternalDataFunc :: proc "c" (impl: rawptr, external_data: rawptr, user_data: rawptr) + +//! Base members of \ref BLObjectVirt. +//! +//! The reason for this struct is to make C API the same as C++ API in terms of struct members. In C++ mode we use +//! inheritance so `Virt` structs actually inherit from \ref BLObjectVirt, but in every case all base members are +//! provided by `base`. +ObjectVirtBase :: struct { + destroy: proc "c" (impl: ^ObjectImpl) -> Result, + get_property: proc "c" (impl: ^ObjectImpl, name: cstring, name_size: c.size_t, value_out: ^VarCore) -> Result, + set_property: proc "c" (impl: ^ObjectImpl, name: cstring, name_size: c.size_t, value: ^VarCore) -> Result, +} + +//! BLObject [Virtual Function Table]. +//! +//! Virtual function table is only present when object type is greater than \ref BL_OBJECT_TYPE_MIN_VIRTUAL. +//! Objects can extend the function table, but it has to always start with members defined by `BLObjectVirt`. +ObjectVirt :: struct { + base: ObjectVirtBase, +} + +//! Base class used by all Blend2D objects. +ObjectCore :: struct { + _d: ObjectDetail, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + object_alloc_impl :: proc(self: ^ObjectCore, object_info: u32, impl_size: c.size_t) -> Result --- + object_alloc_impl_aligned :: proc(self: ^ObjectCore, object_info: u32, impl_size: c.size_t, impl_alignment: c.size_t) -> Result --- + object_alloc_impl_external :: proc(self: ^ObjectCore, object_info: u32, impl_size: c.size_t, immutable: i32, destroy_func: DestroyExternalDataFunc, user_data: rawptr) -> Result --- + object_free_impl :: proc(impl: ^ObjectImpl) -> Result --- + object_init_move :: proc(self: ^Unknown, other: ^Unknown) -> Result --- + object_init_weak :: proc(self: ^Unknown, other: ^Unknown) -> Result --- + object_reset :: proc(self: ^Unknown) -> Result --- + object_assign_move :: proc(self: ^Unknown, other: ^Unknown) -> Result --- + object_assign_weak :: proc(self: ^Unknown, other: ^Unknown) -> Result --- + object_get_property :: proc(self: ^Unknown, name: cstring, name_size: c.size_t, value_out: ^VarCore) -> Result --- + object_get_property_bool :: proc(self: ^Unknown, name: cstring, name_size: c.size_t, value_out: ^i32) -> Result --- + object_get_property_int32 :: proc(self: ^Unknown, name: cstring, name_size: c.size_t, value_out: ^i32) -> Result --- + object_get_property_int64 :: proc(self: ^Unknown, name: cstring, name_size: c.size_t, value_out: ^i64) -> Result --- + object_get_property_uint32 :: proc(self: ^Unknown, name: cstring, name_size: c.size_t, value_out: ^u32) -> Result --- + object_get_property_uint64 :: proc(self: ^Unknown, name: cstring, name_size: c.size_t, value_out: ^u64) -> Result --- + object_get_property_double :: proc(self: ^Unknown, name: cstring, name_size: c.size_t, value_out: ^f64) -> Result --- + object_set_property :: proc(self: ^Unknown, name: cstring, name_size: c.size_t, value: ^Unknown) -> Result --- + object_set_property_bool :: proc(self: ^Unknown, name: cstring, name_size: c.size_t, value: i32) -> Result --- + object_set_property_int32 :: proc(self: ^Unknown, name: cstring, name_size: c.size_t, value: i32) -> Result --- + object_set_property_int64 :: proc(self: ^Unknown, name: cstring, name_size: c.size_t, value: i64) -> Result --- + object_set_property_uint32 :: proc(self: ^Unknown, name: cstring, name_size: c.size_t, value: u32) -> Result --- + object_set_property_uint64 :: proc(self: ^Unknown, name: cstring, name_size: c.size_t, value: u64) -> Result --- + object_set_property_double :: proc(self: ^Unknown, name: cstring, name_size: c.size_t, value: f64) -> Result --- +} + diff --git a/binding/path.odin b/binding/path.odin @@ -0,0 +1,369 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Path command. +PathCmd :: enum u32 { + //! Move-to command (starts a new figure). + MOVE = 0, + + //! On-path command (interpreted as line-to or the end of a curve). + ON = 1, + + //! Quad-to control point. + QUAD = 2, + + //! Conic-to control point + CONIC = 3, + + //! Cubic-to control point (always used as a pair of commands). + CUBIC = 4, + + //! Close path. + CLOSE = 5, + + //! Conic weight. + //! + //! \note This is not a point. This is a pair of values from which only the first (x) is used to represent weight + //! as used by conic curve. The other value (y) is always set to NaN by Blend2D, but can be arbitrary as it has + //! no meaning. + WEIGHT = 6, + + //! Maximum value of `BLPathCmd`. + MAX_VALUE = 6, + FORCE_UINT = 4294967295, +} + +//! Path command (never stored in path). +PathCmdExtra :: enum u32 { + //! Used by `BLPath::set_vertex_at` to preserve the current command value. + BL_PATH_CMD_PRESERVE = 4294967295, +} + +//! Path flags. +PathFlags :: enum u32 { + //! No flags. + NO_FLAGS = 0, + + //! Path is empty (no commands or close commands only). + FLAG_EMPTY = 1, + + //! Path contains multiple figures. + FLAG_MULTIPLE = 2, + + //! Path contains one or more quad curves. + FLAG_QUADS = 4, + + //! Path contains one or more conic curves. + FLAG_CONICS = 8, + + //! Path contains one or more cubic curves. + FLAG_CUBICS = 16, + + //! Path is invalid. + FLAG_INVALID = 1073741824, + + //! Flags are dirty (not reflecting the current status). + FLAG_DIRTY = 2147483648, + FLAG_FORCE_UINT = 4294967295, +} + +//! Path reversal mode. +PathReverseMode :: enum u32 { + //! Reverse each figure and their order as well (default). + COMPLETE = 0, + + //! Reverse each figure separately (keeps their order). + SEPARATE = 1, + + //! Maximum value of `BLPathReverseMode`. + MAX_VALUE = 1, + FORCE_UINT = 4294967295, +} + +//! Stroke join type. +StrokeJoin :: enum u32 { + //! Miter-join possibly clipped at `miter_limit` [default]. + MITER_CLIP = 0, + + //! Miter-join or bevel-join depending on miter_limit condition. + MITER_BEVEL = 1, + + //! Miter-join or round-join depending on miter_limit condition. + MITER_ROUND = 2, + + //! Bevel-join. + BEVEL = 3, + + //! Round-join. + ROUND = 4, + + //! Maximum value of `BLStrokeJoin`. + MAX_VALUE = 4, + FORCE_UINT = 4294967295, +} + +//! Position of a stroke-cap. +StrokeCapPosition :: enum u32 { + //! Start of the path. + START = 0, + + //! End of the path. + END = 1, + + //! Maximum value of `BLStrokeCapPosition`. + MAX_VALUE = 1, + FORCE_UINT = 4294967295, +} + +//! A presentation attribute defining the shape to be used at the end of open sub-paths. +StrokeCap :: enum u32 { + //! Butt cap [default]. + BUTT = 0, + + //! Square cap. + SQUARE = 1, + + //! Round cap. + ROUND = 2, + + //! Round cap reversed. + ROUND_REV = 3, + + //! Triangle cap. + TRIANGLE = 4, + + //! Triangle cap reversed. + TRIANGLE_REV = 5, + + //! Maximum value of `BLStrokeCap`. + MAX_VALUE = 5, + FORCE_UINT = 4294967295, +} + +//! Stroke transform order. +StrokeTransformOrder :: enum u32 { + //! Transform after stroke => `Transform(Stroke(Input))` [default]. + AFTER = 0, + + //! Transform before stroke => `Stroke(Transform(Input))`. + BEFORE = 1, + + //! Maximum value of `BLStrokeTransformOrder`. + MAX_VALUE = 1, + FORCE_UINT = 4294967295, +} + +//! Mode that specifies how curves are approximated to line segments. +FlattenMode :: enum u32 { + //! Use default mode (decided by Blend2D). + DEFAULT = 0, + + //! Recursive subdivision flattening. + RECURSIVE = 1, + + //! Maximum value of `BLFlattenMode`. + MAX_VALUE = 1, + FORCE_UINT = 4294967295, +} + +//! Mode that specifies how to construct offset curves. +OffsetMode :: enum u32 { + //! Use default mode (decided by Blend2D). + DEFAULT = 0, + + //! Iterative offset construction. + ITERATIVE = 1, + + //! Maximum value of `BLOffsetMode`. + MAX_VALUE = 1, + FORCE_UINT = 4294967295, +} + +//! Options used to describe how geometry is approximated. +//! +//! This struct cannot be simply zeroed and then passed to functions that accept approximation options. +//! Use `bl_default_approximation_options` to setup defaults and then alter values you want to change. +//! +//! Example of using `BLApproximationOptions`: +//! +//! ``` +//! // Initialize with defaults first. +//! BLApproximationOptions approx = bl_default_approximation_options; +//! +//! // Override values you want to change. +//! approx.simplify_tolerance = 0.02; +//! +//! // ... now safely use approximation options in your code ... +//! ``` +ApproximationOptions :: struct { + //! Specifies how curves are flattened, see \ref BLFlattenMode. + flatten_mode: u8, + + //! Specifies how curves are offsetted (used by stroking), see \ref BLOffsetMode. + offset_mode: u8, + + //! Reserved for future use, must be zero. + reserved_flags: [6]u8, + + //! Tolerance used to flatten curves. + flatten_tolerance: f64, + + //! Tolerance used to approximate cubic curves with quadratic curves. + simplify_tolerance: f64, + + //! Curve offsetting parameter, exact meaning depends on `offset_mode`. + offset_parameter: f64, +} + +//! 2D vector path view provides pointers to vertex and command data along with their size. +PathView :: struct { + command_data: ^u8, + vertex_data: ^Point, + size: c.size_t, +} + +//! Optional callback that can be used to consume a path data. +PathSinkFunc :: proc "c" (path: ^PathCore, info: rawptr, user_data: rawptr) -> Result + +//! This is a sink that is used by path offsetting. This sink consumes both `a` and `b` offsets of the path. The sink +//! will be called for each figure and is responsible for joining these paths. If the paths are not closed then the +//! sink must insert start cap, then join `b`, and then insert end cap. +//! +//! The sink must also clean up the paths as this is not done by the offsetter. The reason is that in case the `a` path +//! is the output path you can just keep it and insert `b` path into it (clearing only `b` path after each call). +PathStrokeSinkFunc :: proc "c" (a: ^PathCore, b: ^PathCore, _c: ^PathCore, input_start: c.size_t, input_end: c.size_t, user_data: rawptr) -> Result + +//! 2D vector path [C API]. +PathCore :: struct { + _d: ObjectDetail, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + path_init :: proc(self: ^PathCore) -> Result --- + path_init_move :: proc(self: ^PathCore, other: ^PathCore) -> Result --- + path_init_weak :: proc(self: ^PathCore, other: ^PathCore) -> Result --- + path_destroy :: proc(self: ^PathCore) -> Result --- + path_reset :: proc(self: ^PathCore) -> Result --- + path_get_size :: proc(self: ^PathCore) -> c.size_t --- + path_get_capacity :: proc(self: ^PathCore) -> c.size_t --- + path_get_command_data :: proc(self: ^PathCore) -> ^u8 --- + path_get_vertex_data :: proc(self: ^PathCore) -> ^Point --- + path_clear :: proc(self: ^PathCore) -> Result --- + path_shrink :: proc(self: ^PathCore) -> Result --- + path_reserve :: proc(self: ^PathCore, n: c.size_t) -> Result --- + path_modify_op :: proc(self: ^PathCore, op: ModifyOp, n: c.size_t, cmd_data_out: ^^u8, vtx_data_out: ^^Point) -> Result --- + path_assign_move :: proc(self: ^PathCore, other: ^PathCore) -> Result --- + path_assign_weak :: proc(self: ^PathCore, other: ^PathCore) -> Result --- + path_assign_deep :: proc(self: ^PathCore, other: ^PathCore) -> Result --- + path_set_vertex_at :: proc(self: ^PathCore, index: c.size_t, cmd: u32, x: f64, y: f64) -> Result --- + path_move_to :: proc(self: ^PathCore, x0: f64, y0: f64) -> Result --- + path_line_to :: proc(self: ^PathCore, x1: f64, y1: f64) -> Result --- + path_poly_to :: proc(self: ^PathCore, poly: ^Point, count: c.size_t) -> Result --- + path_quad_to :: proc(self: ^PathCore, x1: f64, y1: f64, x2: f64, y2: f64) -> Result --- + path_conic_to :: proc(self: ^PathCore, x1: f64, y1: f64, x2: f64, y2: f64, w: f64) -> Result --- + path_cubic_to :: proc(self: ^PathCore, x1: f64, y1: f64, x2: f64, y2: f64, x3: f64, y3: f64) -> Result --- + path_smooth_quad_to :: proc(self: ^PathCore, x2: f64, y2: f64) -> Result --- + path_smooth_cubic_to :: proc(self: ^PathCore, x2: f64, y2: f64, x3: f64, y3: f64) -> Result --- + path_arc_to :: proc(self: ^PathCore, x: f64, y: f64, rx: f64, ry: f64, start: f64, sweep: f64, force_move_to: i32) -> Result --- + path_arc_quadrant_to :: proc(self: ^PathCore, x1: f64, y1: f64, x2: f64, y2: f64) -> Result --- + path_elliptic_arc_to :: proc(self: ^PathCore, rx: f64, ry: f64, xAxisRotation: f64, large_arc_flag: i32, sweep_flag: i32, x1: f64, y1: f64) -> Result --- + path_close :: proc(self: ^PathCore) -> Result --- + path_add_geometry :: proc(self: ^PathCore, geometry_type: GeometryType, geometry_data: rawptr, m: ^Matrix2D, dir: GeometryDirection) -> Result --- + path_add_box_i :: proc(self: ^PathCore, box: ^BoxI, dir: GeometryDirection) -> Result --- + path_add_box_d :: proc(self: ^PathCore, box: ^Box, dir: GeometryDirection) -> Result --- + path_add_rect_i :: proc(self: ^PathCore, rect: ^RectI, dir: GeometryDirection) -> Result --- + path_add_rect_d :: proc(self: ^PathCore, rect: ^Rect, dir: GeometryDirection) -> Result --- + path_add_path :: proc(self: ^PathCore, other: ^PathCore, range: ^Range) -> Result --- + path_add_translated_path :: proc(self: ^PathCore, other: ^PathCore, range: ^Range, p: ^Point) -> Result --- + path_add_transformed_path :: proc(self: ^PathCore, other: ^PathCore, range: ^Range, m: ^Matrix2D) -> Result --- + path_add_reversed_path :: proc(self: ^PathCore, other: ^PathCore, range: ^Range, reverse_mode: PathReverseMode) -> Result --- + path_add_stroked_path :: proc(self: ^PathCore, other: ^PathCore, range: ^Range, options: ^StrokeOptionsCore, approx: ^ApproximationOptions) -> Result --- + path_remove_range :: proc(self: ^PathCore, range: ^Range) -> Result --- + path_translate :: proc(self: ^PathCore, range: ^Range, p: ^Point) -> Result --- + path_transform :: proc(self: ^PathCore, range: ^Range, m: ^Matrix2D) -> Result --- + path_fit_to :: proc(self: ^PathCore, range: ^Range, rect: ^Rect, fit_flags: u32) -> Result --- + path_equals :: proc(a: ^PathCore, b: ^PathCore) -> i32 --- + path_get_info_flags :: proc(self: ^PathCore, flags_out: ^u32) -> Result --- + path_get_control_box :: proc(self: ^PathCore, box_out: ^Box) -> Result --- + path_get_bounding_box :: proc(self: ^PathCore, box_out: ^Box) -> Result --- + path_get_figure_range :: proc(self: ^PathCore, index: c.size_t, range_out: ^Range) -> Result --- + path_get_last_vertex :: proc(self: ^PathCore, vtx_out: ^Point) -> Result --- + path_get_closest_vertex :: proc(self: ^PathCore, p: ^Point, max_distance: f64, index_out: ^c.size_t, distance_out: ^f64) -> Result --- + path_hit_test :: proc(self: ^PathCore, p: ^Point, fill_rule: FillRule) -> HitTest --- +} + +//! Stroke options [C API]. +StrokeOptionsCore :: struct { + using _: struct #raw_union { + using _: struct { + start_cap: u8, + end_cap: u8, + join: u8, + transform_order: u8, + reserved: [4]u8, + }, + + caps: [2]u8, + hints: u64, + }, + + width: f64, + miter_limit: f64, + dash_offset: f64, + dash_array: ArrayCore, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + stroke_options_init :: proc(self: ^StrokeOptionsCore) -> Result --- + stroke_options_init_move :: proc(self: ^StrokeOptionsCore, other: ^StrokeOptionsCore) -> Result --- + stroke_options_init_weak :: proc(self: ^StrokeOptionsCore, other: ^StrokeOptionsCore) -> Result --- + stroke_options_destroy :: proc(self: ^StrokeOptionsCore) -> Result --- + stroke_options_reset :: proc(self: ^StrokeOptionsCore) -> Result --- + stroke_options_equals :: proc(a: ^StrokeOptionsCore, b: ^StrokeOptionsCore) -> i32 --- + stroke_options_assign_move :: proc(self: ^StrokeOptionsCore, other: ^StrokeOptionsCore) -> Result --- + stroke_options_assign_weak :: proc(self: ^StrokeOptionsCore, other: ^StrokeOptionsCore) -> Result --- + path_stroke_to_sink :: proc(self: ^PathCore, range: ^Range, stroke_options: ^StrokeOptionsCore, approximation_options: ^ApproximationOptions, a: ^PathCore, b: ^PathCore, _c: ^PathCore, sink: PathStrokeSinkFunc, user_data: rawptr) -> Result --- +} + +//! 2D vector path [Impl]. +PathImpl :: struct { + //! Union of either raw path-data or their `view`. + using _: struct #raw_union { + using _: struct { + //! Command data + command_data: ^u8, + + //! Vertex data. + vertex_data: ^Point, + + //! Vertex/command count. + size: c.size_t, + }, + + //! Path data as view. + view: PathView, + }, + + //! Path vertex/command capacity. + capacity: c.size_t, + + //! Path flags related to caching. + flags: u32, +} + diff --git a/binding/pattern.odin b/binding/pattern.odin @@ -0,0 +1,78 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Pattern quality. +PatternQuality :: enum u32 { + //! Nearest neighbor interpolation. + NEAREST = 0, + + //! Bilinear interpolation. + BILINEAR = 1, + + //! Maximum value of `BLPatternQuality`. + MAX_VALUE = 1, + FORCE_UINT = 4294967295, +} + +//! Pattern [C API]. +PatternCore :: struct { + _d: ObjectDetail, +} + +//! \cond INTERNAL +//! Pattern [C API Impl]. +//! +//! The following properties are stored in BLObjectInfo: +//! +//! - Pattern extend mode is stored in BLObjectInfo's 'b' field. +//! - Pattern matrix type is stored in BLObjectInfo's 'c' field. +PatternImpl :: struct { + //! Image used by the pattern. + image: ImageCore, + + //! Image area to use. + area: RectI, + + //! Pattern transformation matrix. + transform: Matrix2D, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \endcond + pattern_init :: proc(self: ^PatternCore) -> Result --- + pattern_init_move :: proc(self: ^PatternCore, other: ^PatternCore) -> Result --- + pattern_init_weak :: proc(self: ^PatternCore, other: ^PatternCore) -> Result --- + pattern_init_as :: proc(self: ^PatternCore, image: ^ImageCore, area: ^RectI, extend_mode: ExtendMode, transform: ^Matrix2D) -> Result --- + pattern_destroy :: proc(self: ^PatternCore) -> Result --- + pattern_reset :: proc(self: ^PatternCore) -> Result --- + pattern_assign_move :: proc(self: ^PatternCore, other: ^PatternCore) -> Result --- + pattern_assign_weak :: proc(self: ^PatternCore, other: ^PatternCore) -> Result --- + pattern_assign_deep :: proc(self: ^PatternCore, other: ^PatternCore) -> Result --- + pattern_create :: proc(self: ^PatternCore, image: ^ImageCore, area: ^RectI, extend_mode: ExtendMode, transform: ^Matrix2D) -> Result --- + pattern_get_image :: proc(self: ^PatternCore, image: ^ImageCore) -> Result --- + pattern_set_image :: proc(self: ^PatternCore, image: ^ImageCore, area: ^RectI) -> Result --- + pattern_reset_image :: proc(self: ^PatternCore) -> Result --- + pattern_get_area :: proc(self: ^PatternCore, area_out: ^RectI) -> Result --- + pattern_set_area :: proc(self: ^PatternCore, area: ^RectI) -> Result --- + pattern_reset_area :: proc(self: ^PatternCore) -> Result --- + pattern_get_extend_mode :: proc(self: ^PatternCore) -> ExtendMode --- + pattern_set_extend_mode :: proc(self: ^PatternCore, extend_mode: ExtendMode) -> Result --- + pattern_get_transform :: proc(self: ^PatternCore, transform_out: ^Matrix2D) -> Result --- + pattern_get_transform_type :: proc(self: ^PatternCore) -> TransformType --- + pattern_apply_transform_op :: proc(self: ^PatternCore, op_type: TransformOp, op_data: rawptr) -> Result --- + pattern_equals :: proc(a: ^PatternCore, b: ^PatternCore) -> i32 --- +} + diff --git a/binding/pixelconverter.odin b/binding/pixelconverter.odin @@ -0,0 +1,80 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Pixel converter function. +PixelConverterFunc :: proc "c" (self: ^PixelConverterCore, dst_data: ^u8, dst_stride: c.intptr_t, src_data: ^u8, src_stride: c.intptr_t, w: u32, h: u32, options: ^PixelConverterOptions) -> Result + +//! Flags used by `BLPixelConverter::create()` function. +PixelConverterCreateFlags :: enum u32 { + //! No flags. + NO_FLAGS = 0, + + //! Specifies that the source palette in `BLFormatInfo` doesn't have to by copied by `BLPixelConverter`. The caller + //! must ensure that the palette would stay valid until the pixel converter is destroyed. + FLAG_DONT_COPY_PALETTE = 1, + + //! Specifies that the source palette in `BLFormatInfo` is alterable and the pixel converter can modify it when + //! preparing the conversion. The modification can be irreversible so only use this flag when you are sure that + //! the palette passed to `BLPixelConverter::create()` won't be needed outside of pixel conversion. + //! + //! \note The flag `BL_PIXEL_CONVERTER_CREATE_FLAG_DONT_COPY_PALETTE` must be set as well, otherwise this flag would + //! be ignored. + FLAG_ALTERABLE_PALETTE = 2, + + //! When there is no built-in conversion between the given pixel formats it's possible to use an intermediate format + //! that is used during conversion. In such case the base pixel converter creates two more converters that are then + //! used internally. + //! + //! This option disables such feature - creating a pixel converter would fail with `BL_ERROR_NOT_IMPLEMENTED` error + //! if direct conversion is not possible. + FLAG_NO_MULTI_STEP = 4, + FLAG_FORCE_UINT = 4294967295, +} + +//! Pixel conversion options. +PixelConverterOptions :: struct { + origin: PointI, + gap: c.size_t, +} + +//! Pixel converter [C API]. +PixelConverterCore :: struct { + using _: struct #raw_union { + using _: struct { + //! Converter function. + convert_func: PixelConverterFunc, + + //! Internal flags used by the converter - non-zero value means initialized. + internal_flags: u8, + }, + + //! Internal data not exposed to users, aligned to sizeof(void*). + data: [80]u8, + }, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + pixel_converter_init :: proc(self: ^PixelConverterCore) -> Result --- + pixel_converter_init_weak :: proc(self: ^PixelConverterCore, other: ^PixelConverterCore) -> Result --- + pixel_converter_destroy :: proc(self: ^PixelConverterCore) -> Result --- + pixel_converter_reset :: proc(self: ^PixelConverterCore) -> Result --- + pixel_converter_assign :: proc(self: ^PixelConverterCore, other: ^PixelConverterCore) -> Result --- + pixel_converter_create :: proc(self: ^PixelConverterCore, dst_info: ^FormatInfo, src_info: ^FormatInfo, create_flags: PixelConverterCreateFlags) -> Result --- + pixel_converter_convert :: proc(self: ^PixelConverterCore, dst_data: rawptr, dst_stride: c.intptr_t, src_data: rawptr, src_stride: c.intptr_t, w: u32, h: u32, options: ^PixelConverterOptions) -> Result --- +} + diff --git a/binding/random.odin b/binding/random.odin @@ -0,0 +1,35 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \name BLRandom - C API + //! \{ + random_reset :: proc(self: ^Random, seed: u64) -> Result --- + random_next_uint32 :: proc(self: ^Random) -> u32 --- + random_next_uint64 :: proc(self: ^Random) -> u64 --- + random_next_double :: proc(self: ^Random) -> f64 --- +} + +//! Simple pseudo random number generator based on `XORSHIFT+`, which has 64-bit seed, 128 bits of state, and full +//! period `2^128 - 1`. +//! +//! Based on a paper by Sebastiano Vigna: +//! http://vigna.di.unimi.it/ftp/papers/xorshiftplus.pdf +Random :: struct { + //! PRNG state. + data: [2]u64, +} + diff --git a/binding/rgba.odin b/binding/rgba.odin @@ -0,0 +1,42 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! 32-bit RGBA color (8-bit per component) stored as `0xAARRGGBB`. +Rgba32 :: struct { + //! Packed 32-bit RGBA value. + value: u32, +} + +//! 64-bit RGBA color (16-bit per component) stored as `0xAAAARRRRGGGGBBBB`. +Rgba64 :: struct { + //! Packed 64-bit RGBA value. + value: u64, +} + +//! 128-bit RGBA color stored as 4 32-bit floating point values in [RGBA] order. +Rgba :: struct { + //! Red component. + r: f32, + + //! Green component. + g: f32, + + //! Blur component. + b: f32, + + //! Alpha component. + a: f32, +} + diff --git a/binding/runtime.odin b/binding/runtime.odin @@ -0,0 +1,230 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Blend2D runtime limits. +//! +//! \note These constants are used across Blend2D, but they are not designed to be ABI stable. New versions of Blend2D +//! can increase certain limits without notice. Use runtime to query the limits dynamically, see \ref BLRuntimeBuildInfo. +RuntimeLimits :: enum u32 { + //! Maximum width and height of an image. + IMAGE_SIZE = 65535, + + //! Maximum number of threads for asynchronous operations (including rendering). + THREAD_COUNT = 32, +} + +//! Type of runtime information that can be queried through \ref bl_runtime_query_info(). +RuntimeInfoType :: enum u32 { + //! Blend2D build information. + BUILD = 0, + + //! System information (includes CPU architecture, features, core count, etc...). + SYSTEM = 1, + + //! Resources information (includes Blend2D memory consumption) + RESOURCE = 2, + + //! Count of runtime information types. + MAX_VALUE = 2, + FORCE_UINT = 4294967295, +} + +//! Blend2D runtime build type. +RuntimeBuildType :: enum u32 { + //! Describes a Blend2D debug build. + DEBUG = 0, + + //! Describes a Blend2D release build. + RELEASE = 1, + FORCE_UINT = 4294967295, +} + +//! CPU architecture that can be queried by `BLRuntime::query_system_info()`. +RuntimeCpuArch :: enum u32 { + //! Unknown architecture. + UNKNOWN = 0, + + //! 32-bit or 64-bit X86 architecture. + X86 = 1, + + //! 32-bit or 64-bit ARM architecture. + ARM = 2, + + //! 32-bit or 64-bit MIPS architecture. + MIPS = 3, + FORCE_UINT = 4294967295, +} + +//! CPU features Blend2D supports. +RuntimeCpuFeatures :: enum u32 { + X86_SSE2 = 1, + X86_SSE3 = 2, + X86_SSSE3 = 4, + X86_SSE4_1 = 8, + X86_SSE4_2 = 16, + X86_AVX = 32, + X86_AVX2 = 64, + X86_AVX512 = 128, + ARM_ASIMD = 1, + ARM_CRC32 = 2, + ARM_PMULL = 4, + FORCE_UINT = 4294967295, +} + +//! Runtime cleanup flags that can be used through `BLRuntime::cleanup()`. +RuntimeCleanupFlags :: enum u32 { + //! No flags. + NO_FLAGS = 0, + + //! Cleanup object memory pool. + OBJECT_POOL = 1, + + //! Cleanup zeroed memory pool. + ZEROED_POOL = 2, + + //! Cleanup thread pool (would join unused threads). + THREAD_POOL = 16, + + //! Cleanup everything. + EVERYTHING = 4294967295, + FLAG_FORCE_UINT = 4294967295, +} + +//! Blend2D build information. +RuntimeBuildInfo :: struct { + //! Major version number. + major_version: u32, + + //! Minor version number. + minor_version: u32, + + //! Patch version number. + patch_version: u32, + + //! Blend2D build type, see \ref BLRuntimeBuildType. + build_type: u32, + + //! Baseline CPU features, see \ref BLRuntimeCpuFeatures. + //! + //! These features describe CPU features that were detected at compile-time. Baseline features are used to compile + //! all source files so they represent the minimum feature-set the target CPU must support to run Blend2D. + //! + //! Official Blend2D builds set baseline at SSE2 on X86 target and NEON on ARM target. Custom builds can set use + //! a different baseline, which can be read through `BLRuntimeBuildInfo`. + baseline_cpu_features: u32, + + //! Supported CPU features, see \ref BLRuntimeCpuFeatures. + //! + //! These features do not represent the features that the host CPU must support, instead, they represent all features + //! that Blend2D can take advantage of in C++ code that uses instruction intrinsics. For example if AVX2 is part of + //! `supported_cpu_features` it means that Blend2D can take advantage of it if there is a specialized code-path. + supported_cpu_features: u32, + + //! Maximum size of an image (both width and height). + max_image_size: u32, + + //! Maximum number of threads for asynchronous operations, including rendering. + max_thread_count: u32, + + //! Reserved, must be zero. + reserved: [2]u32, + + //! Identification of the C++ compiler used to build Blend2D. + compiler_info: [32]i8, +} + +//! System information queried by the runtime. +RuntimeSystemInfo :: struct { + //! Host CPU architecture, see \ref BLRuntimeCpuArch. + cpu_arch: u32, + + //! Host CPU features, see \ref BLRuntimeCpuFeatures. + cpu_features: u32, + + //! Number of cores of the host CPU/CPUs. + core_count: u32, + + //! Number of threads of the host CPU/CPUs. + thread_count: u32, + + //! Minimum stack size of a worker thread used by Blend2D. + thread_stack_size: u32, + + //! Removed field. + removed: u32, + + //! Allocation granularity of virtual memory (includes thread's stack). + allocation_granularity: u32, + + //! Reserved for future use. + reserved: [5]u32, + + //! Host CPU vendor string such "AMD", "APPLE", "INTEL", "SAMSUNG", etc... + cpu_vendor: [16]i8, + + //! Host CPU brand string or empty string if not detected properly. + cpu_brand: [64]i8, +} + +//! Provides information about resources allocated by Blend2D. +RuntimeResourceInfo :: struct { + //! Virtual memory used at this time. + vm_used: c.size_t, + + //! Virtual memory reserved (allocated internally). + vm_reserved: c.size_t, + + //! Overhead required to manage virtual memory allocations. + vm_overhead: c.size_t, + + //! Number of blocks of virtual memory allocated. + vm_block_count: c.size_t, + + //! Zeroed memory used at this time. + zm_used: c.size_t, + + //! Zeroed memory reserved (allocated internally). + zm_reserved: c.size_t, + + //! Overhead required to manage zeroed memory allocations. + zm_overhead: c.size_t, + + //! Number of blocks of zeroed memory allocated. + zm_block_count: c.size_t, + + //! Count of dynamic pipelines created and cached. + dynamic_pipeline_count: c.size_t, + + //! Reserved for future use. + reserved: [7]c.size_t, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! Initialized Blend2D runtime + runtime_init :: proc() -> Result --- + + //! Shuts down Blend2D runtime + runtime_shutdown :: proc() -> Result --- + runtime_cleanup :: proc(cleanup_flags: RuntimeCleanupFlags) -> Result --- + runtime_query_info :: proc(info_type: RuntimeInfoType, info_out: rawptr) -> Result --- + runtime_message_out :: proc(msg: cstring) -> Result --- + runtime_message_fmt :: proc(fmt: cstring, #c_vararg _: ..any) -> Result --- + runtime_message_vfmt :: proc(fmt: cstring, ap: i32) -> Result --- + result_from_posix_error :: proc(e: i32) -> Result --- +} + diff --git a/binding/runtimescope.odin b/binding/runtimescope.odin @@ -0,0 +1,27 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Blend2D runtime scope [C API]. +RuntimeScopeCore :: struct { + data: [2]u32, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + runtime_scope_begin :: proc(self: ^RuntimeScopeCore) -> Result --- + runtime_scope_end :: proc(self: ^RuntimeScopeCore) -> Result --- + runtime_scope_is_active :: proc(self: ^RuntimeScopeCore) -> i32 --- +} + diff --git a/binding/string.odin b/binding/string.odin @@ -0,0 +1,71 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Byte string [C API]. +StringCore :: struct { + _d: ObjectDetail, +} + +//! \cond INTERNAL +//! Byte string [Impl]. +StringImpl :: struct { + //! String size [in bytes]. + size: c.size_t, + + //! String data capacity [in bytes]. + capacity: c.size_t, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + //! \endcond + string_init :: proc(self: ^StringCore) -> Result --- + string_init_move :: proc(self: ^StringCore, other: ^StringCore) -> Result --- + string_init_weak :: proc(self: ^StringCore, other: ^StringCore) -> Result --- + string_init_with_data :: proc(self: ^StringCore, str: cstring, size: c.size_t) -> Result --- + string_destroy :: proc(self: ^StringCore) -> Result --- + string_reset :: proc(self: ^StringCore) -> Result --- + string_get_data :: proc(self: ^StringCore) -> cstring --- + string_get_size :: proc(self: ^StringCore) -> c.size_t --- + string_get_capacity :: proc(self: ^StringCore) -> c.size_t --- + string_clear :: proc(self: ^StringCore) -> Result --- + string_shrink :: proc(self: ^StringCore) -> Result --- + string_reserve :: proc(self: ^StringCore, n: c.size_t) -> Result --- + string_resize :: proc(self: ^StringCore, n: c.size_t, fill: i8) -> Result --- + string_make_mutable :: proc(self: ^StringCore, data_out: ^cstring) -> Result --- + string_modify_op :: proc(self: ^StringCore, op: ModifyOp, n: c.size_t, data_out: ^cstring) -> Result --- + string_insert_op :: proc(self: ^StringCore, index: c.size_t, n: c.size_t, data_out: ^cstring) -> Result --- + string_assign_move :: proc(self: ^StringCore, other: ^StringCore) -> Result --- + string_assign_weak :: proc(self: ^StringCore, other: ^StringCore) -> Result --- + string_assign_deep :: proc(self: ^StringCore, other: ^StringCore) -> Result --- + string_assign_data :: proc(self: ^StringCore, str: cstring, n: c.size_t) -> Result --- + string_apply_op_char :: proc(self: ^StringCore, op: ModifyOp, _c: i8, n: c.size_t) -> Result --- + string_apply_op_data :: proc(self: ^StringCore, op: ModifyOp, str: cstring, n: c.size_t) -> Result --- + string_apply_op_string :: proc(self: ^StringCore, op: ModifyOp, other: ^StringCore) -> Result --- + string_apply_op_format :: proc(self: ^StringCore, op: ModifyOp, fmt: cstring, #c_vararg _: ..any) -> Result --- + string_apply_op_format_v :: proc(self: ^StringCore, op: ModifyOp, fmt: cstring, ap: i32) -> Result --- + string_insert_char :: proc(self: ^StringCore, index: c.size_t, _c: i8, n: c.size_t) -> Result --- + string_insert_data :: proc(self: ^StringCore, index: c.size_t, str: cstring, n: c.size_t) -> Result --- + string_insert_string :: proc(self: ^StringCore, index: c.size_t, other: ^StringCore) -> Result --- + string_remove_index :: proc(self: ^StringCore, index: c.size_t) -> Result --- + string_remove_range :: proc(self: ^StringCore, r_start: c.size_t, r_end: c.size_t) -> Result --- + string_equals :: proc(a: ^StringCore, b: ^StringCore) -> i32 --- + string_equals_data :: proc(self: ^StringCore, str: cstring, n: c.size_t) -> i32 --- + string_compare :: proc(a: ^StringCore, b: ^StringCore) -> i32 --- + string_compare_data :: proc(self: ^StringCore, str: cstring, n: c.size_t) -> i32 --- +} + diff --git a/binding/var.odin b/binding/var.odin @@ -0,0 +1,71 @@ +// This file is part of Blend2D project <https://blend2d.com> +// +// See blend2d.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib +package blend2d + +when ODIN_OS == .Windows { + foreign import lib "blend2d.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "libblend2d.a" +} else when ODIN_OS == .Linux { + foreign import lib "libblend2d.a" +} + + +//! Variant [C API]. +VarCore :: struct { + _d: ObjectDetail, +} + +@(default_calling_convention="c", link_prefix="bl_") +foreign lib { + var_init_type :: proc(self: ^Unknown, type: ObjectType) -> Result --- + var_init_null :: proc(self: ^Unknown) -> Result --- + var_init_bool :: proc(self: ^Unknown, value: i32) -> Result --- + var_init_int32 :: proc(self: ^Unknown, value: i32) -> Result --- + var_init_int64 :: proc(self: ^Unknown, value: i64) -> Result --- + var_init_uint32 :: proc(self: ^Unknown, value: u32) -> Result --- + var_init_uint64 :: proc(self: ^Unknown, value: u64) -> Result --- + var_init_double :: proc(self: ^Unknown, value: f64) -> Result --- + var_init_rgba :: proc(self: ^Unknown, rgba: ^Rgba) -> Result --- + var_init_rgba32 :: proc(self: ^Unknown, rgba32: u32) -> Result --- + var_init_rgba64 :: proc(self: ^Unknown, rgba64: u64) -> Result --- + var_init_move :: proc(self: ^Unknown, other: ^Unknown) -> Result --- + var_init_weak :: proc(self: ^Unknown, other: ^Unknown) -> Result --- + var_destroy :: proc(self: ^Unknown) -> Result --- + var_reset :: proc(self: ^Unknown) -> Result --- + var_assign_null :: proc(self: ^Unknown) -> Result --- + var_assign_bool :: proc(self: ^Unknown, value: i32) -> Result --- + var_assign_int32 :: proc(self: ^Unknown, value: i32) -> Result --- + var_assign_int64 :: proc(self: ^Unknown, value: i64) -> Result --- + var_assign_uint32 :: proc(self: ^Unknown, value: u32) -> Result --- + var_assign_uint64 :: proc(self: ^Unknown, value: u64) -> Result --- + var_assign_double :: proc(self: ^Unknown, value: f64) -> Result --- + var_assign_rgba :: proc(self: ^Unknown, rgba: ^Rgba) -> Result --- + var_assign_rgba32 :: proc(self: ^Unknown, rgba32: u32) -> Result --- + var_assign_rgba64 :: proc(self: ^Unknown, rgba64: u64) -> Result --- + var_assign_move :: proc(self: ^Unknown, other: ^Unknown) -> Result --- + var_assign_weak :: proc(self: ^Unknown, other: ^Unknown) -> Result --- + var_get_type :: proc(self: ^Unknown) -> ObjectType --- + var_to_bool :: proc(self: ^Unknown, out: ^i32) -> Result --- + var_to_int32 :: proc(self: ^Unknown, out: ^i32) -> Result --- + var_to_int64 :: proc(self: ^Unknown, out: ^i64) -> Result --- + var_to_uint32 :: proc(self: ^Unknown, out: ^u32) -> Result --- + var_to_uint64 :: proc(self: ^Unknown, out: ^u64) -> Result --- + var_to_double :: proc(self: ^Unknown, out: ^f64) -> Result --- + var_to_rgba :: proc(self: ^Unknown, out: ^Rgba) -> Result --- + var_to_rgba32 :: proc(self: ^Unknown, out: ^u32) -> Result --- + var_to_rgba64 :: proc(self: ^Unknown, out: ^u64) -> Result --- + var_equals :: proc(a: ^Unknown, b: ^Unknown) -> i32 --- + var_equals_null :: proc(self: ^Unknown) -> i32 --- + var_equals_bool :: proc(self: ^Unknown, value: i32) -> i32 --- + var_equals_int64 :: proc(self: ^Unknown, value: i64) -> i32 --- + var_equals_uint64 :: proc(self: ^Unknown, value: u64) -> i32 --- + var_equals_double :: proc(self: ^Unknown, value: f64) -> i32 --- + var_equals_rgba :: proc(self: ^Unknown, rgba: ^Rgba) -> i32 --- + var_equals_rgba32 :: proc(self: ^Unknown, rgba32: u32) -> i32 --- + var_equals_rgba64 :: proc(self: ^Unknown, rgba64: u64) -> i32 --- + var_strict_equals :: proc(a: ^Unknown, b: ^Unknown) -> i32 --- +} +