odin-blend2d

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

path.odin (13365B)


      1 // This file is part of Blend2D project <https://blend2d.com>
      2 //
      3 // See blend2d.h or LICENSE.md for license and copyright information
      4 // SPDX-License-Identifier: Zlib
      5 package blend2d
      6 
      7 import "core:c"
      8 
      9 when ODIN_OS == .Windows {
     10 	foreign import lib "blend2d.lib"
     11 } else when ODIN_OS == .Darwin {
     12 	foreign import lib "libblend2d.a"
     13 } else when ODIN_OS == .Linux {
     14 	foreign import lib "libblend2d.a"
     15 }
     16 
     17 
     18 //! Path command.
     19 PathCmd :: enum u32 {
     20 	//! Move-to command (starts a new figure).
     21 	MOVE       = 0,
     22 
     23 	//! On-path command (interpreted as line-to or the end of a curve).
     24 	ON         = 1,
     25 
     26 	//! Quad-to control point.
     27 	QUAD       = 2,
     28 
     29 	//! Conic-to control point
     30 	CONIC      = 3,
     31 
     32 	//! Cubic-to control point (always used as a pair of commands).
     33 	CUBIC      = 4,
     34 
     35 	//! Close path.
     36 	CLOSE      = 5,
     37 
     38 	//! Conic weight.
     39 	//!
     40 	//! \note This is not a point. This is a pair of values from which only the first (x) is used to represent weight
     41 	//! as used by conic curve. The other value (y) is always set to NaN by Blend2D, but can be arbitrary as it has
     42 	//! no meaning.
     43 	WEIGHT     = 6,
     44 
     45 	//! Maximum value of `BLPathCmd`.
     46 	MAX_VALUE  = 6,
     47 	FORCE_UINT = 4294967295,
     48 }
     49 
     50 //! Path command (never stored in path).
     51 PathCmdExtra :: enum u32 {
     52 	//! Used by `BLPath::set_vertex_at` to preserve the current command value.
     53 	BL_PATH_CMD_PRESERVE = 4294967295,
     54 }
     55 
     56 //! Path flags.
     57 PathFlags :: enum u32 {
     58 	//! No flags.
     59 	NO_FLAGS        = 0,
     60 
     61 	//! Path is empty (no commands or close commands only).
     62 	FLAG_EMPTY      = 1,
     63 
     64 	//! Path contains multiple figures.
     65 	FLAG_MULTIPLE   = 2,
     66 
     67 	//! Path contains one or more quad curves.
     68 	FLAG_QUADS      = 4,
     69 
     70 	//! Path contains one or more conic curves.
     71 	FLAG_CONICS     = 8,
     72 
     73 	//! Path contains one or more cubic curves.
     74 	FLAG_CUBICS     = 16,
     75 
     76 	//! Path is invalid.
     77 	FLAG_INVALID    = 1073741824,
     78 
     79 	//! Flags are dirty (not reflecting the current status).
     80 	FLAG_DIRTY      = 2147483648,
     81 	FLAG_FORCE_UINT = 4294967295,
     82 }
     83 
     84 //! Path reversal mode.
     85 PathReverseMode :: enum u32 {
     86 	//! Reverse each figure and their order as well (default).
     87 	COMPLETE   = 0,
     88 
     89 	//! Reverse each figure separately (keeps their order).
     90 	SEPARATE   = 1,
     91 
     92 	//! Maximum value of `BLPathReverseMode`.
     93 	MAX_VALUE  = 1,
     94 	FORCE_UINT = 4294967295,
     95 }
     96 
     97 //! Stroke join type.
     98 StrokeJoin :: enum u32 {
     99 	//! Miter-join possibly clipped at `miter_limit` [default].
    100 	MITER_CLIP  = 0,
    101 
    102 	//! Miter-join or bevel-join depending on miter_limit condition.
    103 	MITER_BEVEL = 1,
    104 
    105 	//! Miter-join or round-join depending on miter_limit condition.
    106 	MITER_ROUND = 2,
    107 
    108 	//! Bevel-join.
    109 	BEVEL       = 3,
    110 
    111 	//! Round-join.
    112 	ROUND       = 4,
    113 
    114 	//! Maximum value of `BLStrokeJoin`.
    115 	MAX_VALUE   = 4,
    116 	FORCE_UINT  = 4294967295,
    117 }
    118 
    119 //! Position of a stroke-cap.
    120 StrokeCapPosition :: enum u32 {
    121 	//! Start of the path.
    122 	START      = 0,
    123 
    124 	//! End of the path.
    125 	END        = 1,
    126 
    127 	//! Maximum value of `BLStrokeCapPosition`.
    128 	MAX_VALUE  = 1,
    129 	FORCE_UINT = 4294967295,
    130 }
    131 
    132 //! A presentation attribute defining the shape to be used at the end of open sub-paths.
    133 StrokeCap :: enum u32 {
    134 	//! Butt cap [default].
    135 	BUTT         = 0,
    136 
    137 	//! Square cap.
    138 	SQUARE       = 1,
    139 
    140 	//! Round cap.
    141 	ROUND        = 2,
    142 
    143 	//! Round cap reversed.
    144 	ROUND_REV    = 3,
    145 
    146 	//! Triangle cap.
    147 	TRIANGLE     = 4,
    148 
    149 	//! Triangle cap reversed.
    150 	TRIANGLE_REV = 5,
    151 
    152 	//! Maximum value of `BLStrokeCap`.
    153 	MAX_VALUE    = 5,
    154 	FORCE_UINT   = 4294967295,
    155 }
    156 
    157 //! Stroke transform order.
    158 StrokeTransformOrder :: enum u32 {
    159 	//! Transform after stroke  => `Transform(Stroke(Input))` [default].
    160 	AFTER      = 0,
    161 
    162 	//! Transform before stroke => `Stroke(Transform(Input))`.
    163 	BEFORE     = 1,
    164 
    165 	//! Maximum value of `BLStrokeTransformOrder`.
    166 	MAX_VALUE  = 1,
    167 	FORCE_UINT = 4294967295,
    168 }
    169 
    170 //! Mode that specifies how curves are approximated to line segments.
    171 FlattenMode :: enum u32 {
    172 	//! Use default mode (decided by Blend2D).
    173 	DEFAULT    = 0,
    174 
    175 	//! Recursive subdivision flattening.
    176 	RECURSIVE  = 1,
    177 
    178 	//! Maximum value of `BLFlattenMode`.
    179 	MAX_VALUE  = 1,
    180 	FORCE_UINT = 4294967295,
    181 }
    182 
    183 //! Mode that specifies how to construct offset curves.
    184 OffsetMode :: enum u32 {
    185 	//! Use default mode (decided by Blend2D).
    186 	DEFAULT    = 0,
    187 
    188 	//! Iterative offset construction.
    189 	ITERATIVE  = 1,
    190 
    191 	//! Maximum value of `BLOffsetMode`.
    192 	MAX_VALUE  = 1,
    193 	FORCE_UINT = 4294967295,
    194 }
    195 
    196 //! Options used to describe how geometry is approximated.
    197 //!
    198 //! This struct cannot be simply zeroed and then passed to functions that accept approximation options.
    199 //! Use `bl_default_approximation_options` to setup defaults and then alter values you want to change.
    200 //!
    201 //! Example of using `BLApproximationOptions`:
    202 //!
    203 //! ```
    204 //! // Initialize with defaults first.
    205 //! BLApproximationOptions approx = bl_default_approximation_options;
    206 //!
    207 //! // Override values you want to change.
    208 //! approx.simplify_tolerance = 0.02;
    209 //!
    210 //! // ... now safely use approximation options in your code ...
    211 //! ```
    212 ApproximationOptions :: struct {
    213 	//! Specifies how curves are flattened, see \ref BLFlattenMode.
    214 	flatten_mode: u8,
    215 
    216 	//! Specifies how curves are offsetted (used by stroking), see \ref BLOffsetMode.
    217 	offset_mode: u8,
    218 
    219 	//! Reserved for future use, must be zero.
    220 	reserved_flags: [6]u8,
    221 
    222 	//! Tolerance used to flatten curves.
    223 	flatten_tolerance: f64,
    224 
    225 	//! Tolerance used to approximate cubic curves with quadratic curves.
    226 	simplify_tolerance: f64,
    227 
    228 	//! Curve offsetting parameter, exact meaning depends on `offset_mode`.
    229 	offset_parameter: f64,
    230 }
    231 
    232 //! 2D vector path view provides pointers to vertex and command data along with their size.
    233 PathView :: struct {
    234 	command_data: ^u8,
    235 	vertex_data:  ^Point,
    236 	size:         c.size_t,
    237 }
    238 
    239 //! Optional callback that can be used to consume a path data.
    240 PathSinkFunc :: proc "c" (path: ^PathCore, info: rawptr, user_data: rawptr) -> Result
    241 
    242 //! This is a sink that is used by path offsetting. This sink consumes both `a` and `b` offsets of the path. The sink
    243 //! will be called for each figure and is responsible for joining these paths. If the paths are not closed then the
    244 //! sink must insert start cap, then join `b`, and then insert end cap.
    245 //!
    246 //! 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
    247 //! is the output path you can just keep it and insert `b` path into it (clearing only `b` path after each call).
    248 PathStrokeSinkFunc :: proc "c" (a: ^PathCore, b: ^PathCore, _c: ^PathCore, input_start: c.size_t, input_end: c.size_t, user_data: rawptr) -> Result
    249 
    250 //! 2D vector path [C API].
    251 PathCore :: struct {
    252 	_d: ObjectDetail,
    253 }
    254 
    255 @(default_calling_convention="c", link_prefix="bl_")
    256 foreign lib {
    257 	path_init                 :: proc(self: ^PathCore) -> Result ---
    258 	path_init_move            :: proc(self: ^PathCore, other: ^PathCore) -> Result ---
    259 	path_init_weak            :: proc(self: ^PathCore, other: ^PathCore) -> Result ---
    260 	path_destroy              :: proc(self: ^PathCore) -> Result ---
    261 	path_reset                :: proc(self: ^PathCore) -> Result ---
    262 	path_get_size             :: proc(self: ^PathCore) -> c.size_t ---
    263 	path_get_capacity         :: proc(self: ^PathCore) -> c.size_t ---
    264 	path_get_command_data     :: proc(self: ^PathCore) -> ^u8 ---
    265 	path_get_vertex_data      :: proc(self: ^PathCore) -> ^Point ---
    266 	path_clear                :: proc(self: ^PathCore) -> Result ---
    267 	path_shrink               :: proc(self: ^PathCore) -> Result ---
    268 	path_reserve              :: proc(self: ^PathCore, n: c.size_t) -> Result ---
    269 	path_modify_op            :: proc(self: ^PathCore, op: ModifyOp, n: c.size_t, cmd_data_out: ^^u8, vtx_data_out: ^^Point) -> Result ---
    270 	path_assign_move          :: proc(self: ^PathCore, other: ^PathCore) -> Result ---
    271 	path_assign_weak          :: proc(self: ^PathCore, other: ^PathCore) -> Result ---
    272 	path_assign_deep          :: proc(self: ^PathCore, other: ^PathCore) -> Result ---
    273 	path_set_vertex_at        :: proc(self: ^PathCore, index: c.size_t, cmd: u32, x: f64, y: f64) -> Result ---
    274 	path_move_to              :: proc(self: ^PathCore, x0: f64, y0: f64) -> Result ---
    275 	path_line_to              :: proc(self: ^PathCore, x1: f64, y1: f64) -> Result ---
    276 	path_poly_to              :: proc(self: ^PathCore, poly: ^Point, count: c.size_t) -> Result ---
    277 	path_quad_to              :: proc(self: ^PathCore, x1: f64, y1: f64, x2: f64, y2: f64) -> Result ---
    278 	path_conic_to             :: proc(self: ^PathCore, x1: f64, y1: f64, x2: f64, y2: f64, w: f64) -> Result ---
    279 	path_cubic_to             :: proc(self: ^PathCore, x1: f64, y1: f64, x2: f64, y2: f64, x3: f64, y3: f64) -> Result ---
    280 	path_smooth_quad_to       :: proc(self: ^PathCore, x2: f64, y2: f64) -> Result ---
    281 	path_smooth_cubic_to      :: proc(self: ^PathCore, x2: f64, y2: f64, x3: f64, y3: f64) -> Result ---
    282 	path_arc_to               :: proc(self: ^PathCore, x: f64, y: f64, rx: f64, ry: f64, start: f64, sweep: f64, force_move_to: i32) -> Result ---
    283 	path_arc_quadrant_to      :: proc(self: ^PathCore, x1: f64, y1: f64, x2: f64, y2: f64) -> Result ---
    284 	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 ---
    285 	path_close                :: proc(self: ^PathCore) -> Result ---
    286 	path_add_geometry         :: proc(self: ^PathCore, geometry_type: GeometryType, geometry_data: rawptr, m: ^Matrix2D, dir: GeometryDirection) -> Result ---
    287 	path_add_box_i            :: proc(self: ^PathCore, box: ^BoxI, dir: GeometryDirection) -> Result ---
    288 	path_add_box_d            :: proc(self: ^PathCore, box: ^Box, dir: GeometryDirection) -> Result ---
    289 	path_add_rect_i           :: proc(self: ^PathCore, rect: ^RectI, dir: GeometryDirection) -> Result ---
    290 	path_add_rect_d           :: proc(self: ^PathCore, rect: ^Rect, dir: GeometryDirection) -> Result ---
    291 	path_add_path             :: proc(self: ^PathCore, other: ^PathCore, range: ^Range) -> Result ---
    292 	path_add_translated_path  :: proc(self: ^PathCore, other: ^PathCore, range: ^Range, p: ^Point) -> Result ---
    293 	path_add_transformed_path :: proc(self: ^PathCore, other: ^PathCore, range: ^Range, m: ^Matrix2D) -> Result ---
    294 	path_add_reversed_path    :: proc(self: ^PathCore, other: ^PathCore, range: ^Range, reverse_mode: PathReverseMode) -> Result ---
    295 	path_add_stroked_path     :: proc(self: ^PathCore, other: ^PathCore, range: ^Range, options: ^StrokeOptionsCore, approx: ^ApproximationOptions) -> Result ---
    296 	path_remove_range         :: proc(self: ^PathCore, range: ^Range) -> Result ---
    297 	path_translate            :: proc(self: ^PathCore, range: ^Range, p: ^Point) -> Result ---
    298 	path_transform            :: proc(self: ^PathCore, range: ^Range, m: ^Matrix2D) -> Result ---
    299 	path_fit_to               :: proc(self: ^PathCore, range: ^Range, rect: ^Rect, fit_flags: u32) -> Result ---
    300 	path_equals               :: proc(a: ^PathCore, b: ^PathCore) -> i32 ---
    301 	path_get_info_flags       :: proc(self: ^PathCore, flags_out: ^u32) -> Result ---
    302 	path_get_control_box      :: proc(self: ^PathCore, box_out: ^Box) -> Result ---
    303 	path_get_bounding_box     :: proc(self: ^PathCore, box_out: ^Box) -> Result ---
    304 	path_get_figure_range     :: proc(self: ^PathCore, index: c.size_t, range_out: ^Range) -> Result ---
    305 	path_get_last_vertex      :: proc(self: ^PathCore, vtx_out: ^Point) -> Result ---
    306 	path_get_closest_vertex   :: proc(self: ^PathCore, p: ^Point, max_distance: f64, index_out: ^c.size_t, distance_out: ^f64) -> Result ---
    307 	path_hit_test             :: proc(self: ^PathCore, p: ^Point, fill_rule: FillRule) -> HitTest ---
    308 }
    309 
    310 //! Stroke options [C API].
    311 StrokeOptionsCore :: struct {
    312 	using _: struct #raw_union {
    313 		using _: struct {
    314 			start_cap:       u8,
    315 			end_cap:         u8,
    316 			join:            u8,
    317 			transform_order: u8,
    318 			reserved:        [4]u8,
    319 		},
    320 
    321 		caps:  [2]u8,
    322 		hints: u64,
    323 	},
    324 
    325 	width:       f64,
    326 	miter_limit: f64,
    327 	dash_offset: f64,
    328 	dash_array:  ArrayCore,
    329 }
    330 
    331 @(default_calling_convention="c", link_prefix="bl_")
    332 foreign lib {
    333 	stroke_options_init        :: proc(self: ^StrokeOptionsCore) -> Result ---
    334 	stroke_options_init_move   :: proc(self: ^StrokeOptionsCore, other: ^StrokeOptionsCore) -> Result ---
    335 	stroke_options_init_weak   :: proc(self: ^StrokeOptionsCore, other: ^StrokeOptionsCore) -> Result ---
    336 	stroke_options_destroy     :: proc(self: ^StrokeOptionsCore) -> Result ---
    337 	stroke_options_reset       :: proc(self: ^StrokeOptionsCore) -> Result ---
    338 	stroke_options_equals      :: proc(a: ^StrokeOptionsCore, b: ^StrokeOptionsCore) -> i32 ---
    339 	stroke_options_assign_move :: proc(self: ^StrokeOptionsCore, other: ^StrokeOptionsCore) -> Result ---
    340 	stroke_options_assign_weak :: proc(self: ^StrokeOptionsCore, other: ^StrokeOptionsCore) -> Result ---
    341 	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 ---
    342 }
    343 
    344 //! 2D vector path [Impl].
    345 PathImpl :: struct {
    346 	//! Union of either raw path-data or their `view`.
    347 	using _: struct #raw_union {
    348 		using _: struct {
    349 			//! Command data
    350 			command_data: ^u8,
    351 
    352 			//! Vertex data.
    353 			vertex_data: ^Point,
    354 
    355 			//! Vertex/command count.
    356 			size: c.size_t,
    357 		},
    358 
    359 		//! Path data as view.
    360 		view: PathView,
    361 	},
    362 
    363 	//! Path vertex/command capacity.
    364 	capacity: c.size_t,
    365 
    366 	//! Path flags related to caching.
    367 	flags: u32,
    368 }
    369