Expand description
Raw Rust FFI bindings to the Clipper2 C++ polygon clipping and offsetting library by Angus Johnson — the canonical implementation. The library’s C++ source is vendored into this crate; see the repository README for the rationale and credit details.
§You probably want clipper2 instead
Almost every item here is unsafe, requires manual memory management, and
exposes raw C pointer types. The high-level clipper2
crate wraps these with a safe Rust API and is the recommended way to do
polygon clipping from Rust. Reach for clipper2c-sys directly only when
you need to interop with code that already operates on the C ABI.
§Memory model
All non-trivial types in this crate are opaque handles. The C++ side
owns the storage; Rust code only sees *mut ClipperX pointers and never
reads or writes struct fields directly. The lifecycle of every opaque
object is:
- Ask
clipper_X_size()how many bytes the C++ object needs. - Allocate that many bytes via
clipper_allocate. - Pass the buffer to a constructor like
clipper_X(mem). Internally this is C++ placement-new — no extra allocation occurs. - Use the resulting
*mut ClipperXas a handle to allclipper_X_*operations. - Release with
clipper_delete_X(handle)(runs the C++ destructor and frees theclipper_allocatebuffer) orclipper_destruct_X(handle)(destructor only — caller frees the buffer themselves through the matching allocator).
Memory from clipper_allocate must be released through the matching
clipper_delete_X (or destructed and freed via the same allocator).
Mixing with libc::free or Rust’s allocator is undefined behaviour.
§_64 (i64) vs _D (f64) variants
Every clipping type comes in two flavours that look superficially similar but use different Rust numeric types:
| Suffix | Rust coordinate type | Upstream C++ type | Example |
|---|---|---|---|
_64 | i64 (signed 64-bit integer) | int64_t | ClipperPoint64 (x: i64, y: i64) |
_D | f64 (64-bit IEEE-754 float) | double | ClipperPointD (x: f64, y: f64) |
§Why both exist
The clipping engine is implemented exclusively on int64_t.
Integer arithmetic and comparisons are exact, so the engine’s
handling of coincident edges and shared vertices is deterministic.
Floating-point rounding around bit-different-but-mathematically-equal
values would otherwise produce different topology depending on input
order.
_64types are the engine’s native interface. Youri64coordinates pass through unchanged. No transformation, no rounding._Dtypes are a convenience wrapper forf64data. On input, each coordinate is multiplied by a scale factors = 2^⌈log₂(10^precision)⌉(defaultprecision = 2→s = 128), rounded toi64, fed to the engine. Outputs are divided bysand returned asf64. The round-trip quantises results to a grid of step1/s ≈ 10^-precision.
§Which preserves your data
_64round-trips bit-exactly (samei64values out as in)._Ddoes not — output values are rounded to the integer grid defined by theprecisionsetting. The round-trip is not the identity. This is benign for typical CAD or vector-graphics use, but matters if you depend on invariants like “feeding the same shape back must give bit-identical coordinates”.
§Other tradeoffs
- Precision floor on
_D. Quantisation step is~10^-precision(default~0.01). Max supportedprecisionis 8 decimal digits (CLIPPER2_MAX_DEC_PRECISION). - Range. Integer coordinates must satisfy
|c| ≤ INT64_MAX/4(≈ 2.3 × 10¹⁸). For_D, the same bound applies after scaling, so high-magnitude values at high precision can hit a range error well before the rawf64runs out of bits. - Performance.
_Dadds a multiply on every input coordinate and a divide on every output. For hot-path work, prefer_64and pre-scale once if your data sits on a known integer grid.
Reach for _D when your geometry is already f64 and the
quantisation is acceptable. Reach for _64 when your data fits an
integer grid or when bit-exact preservation matters.
§Cargo features
serde(off by default) — derivesSerialize/DeserializeonClipperPoint64.generate-bindings— regenerate the Rust FFI bindings from the C headers at build time. Off by default; the pre-generatedgenerated/bindings.rsis used otherwise.update-bindings— likegenerate-bindings, but writes the result back intogenerated/bindings.rsso the regen output is committed. Usescripts/regenerate-bindings.shto invoke this with the rightLIBCLANG_PATHhandling.
Structs§
- Clipper
Clipper64 - Clipper
ClipperD - Clipper
Clipper Offset - Clipper
Path64 - Clipper
PathD - Clipper
Paths64 - Clipper
PathsD - Clipper
Point64 - Coordinate pair in the engine’s native integer (i64) space. Each component must satisfy |c| ≤ INT64_MAX/4 (~2.3 × 10¹⁸); values outside this range produce a range error during a clipping operation.
- Clipper
PointD - Coordinate pair in floating-point (f64) space. The clipping engine itself runs on integers; ClipperClipperD multiplies each component by its scale factor (s = 128 at the default precision = 2) and rounds to ClipperPoint64 before feeding the engine, so |x × s| and |y × s| must fit ClipperPoint64’s range. Outputs are divided back and quantised to the scaling grid.
- Clipper
Poly Tree64 - Clipper
Poly TreeD
Constants§
- Clipper
Clip Type_ DIFFERENCE - Clipper
Clip Type_ INTERSECTION - Clipper
Clip Type_ NONE - Clipper
Clip Type_ UNION - Clipper
Clip Type_ XOR - Clipper
EndType_ BUTT_ END - Clipper
EndType_ JOINED_ END - Clipper
EndType_ POLYGON_ END - Clipper
EndType_ ROUND_ END - Clipper
EndType_ SQUARE_ END - Clipper
Fill Rule_ EVEN_ ODD - Clipper
Fill Rule_ NEGATIVE - Clipper
Fill Rule_ NON_ ZERO - Clipper
Fill Rule_ POSITIVE - Clipper
Join Type_ BEVEL_ JOIN - Clipper
Join Type_ MITER_ JOIN - Clipper
Join Type_ ROUND_ JOIN - Clipper
Join Type_ SQUARE_ JOIN - Clipper
Path Type_ CLIP - Clipper
Path Type_ SUBJECT - Clipper
Point InPolygon Result_ IS_ INSIDE - Clipper
Point InPolygon Result_ IS_ ON - Clipper
Point InPolygon Result_ IS_ OUTSIDE
Functions§
- clipper_
allocate ⚠ - Allocator paired with the clipper_delete_X / clipper_destruct_X family. Returns raw bytes that must then be placement-new constructed by a clipper_X(mem, …) call before use.
- clipper_
clipper64 ⚠ - Clipper Contsructors
- clipper_
clipper64_ ⚠add_ clip - clipper_
clipper64_ ⚠add_ open_ subject - clipper_
clipper64_ ⚠add_ subject - Clipper64 Methods
- clipper_
clipper64_ ⚠clear - clipper_
clipper64_ ⚠execute - Run the configured boolean operation. Closed-path output is written
to
closed; if open-path subjects were added via clipper_clipper64_add_open_subject, their offset/intersected portions land inopen. Returns 1 on success, 0 on failure. - clipper_
clipper64_ ⚠execute_ tree_ with_ open - Run the configured boolean operation, writing closed-path output as
a hierarchical ClipperPolyTree64 and open-path output (from
clipper_clipper64_add_open_subject) into the separate ClipperPaths64
open. Use this when you need to know which contours are holes inside which solids — that nesting is lost in the flat output of clipper_clipper64_execute. - clipper_
clipper64_ ⚠get_ preserve_ collinear - clipper_
clipper64_ ⚠get_ reverse_ solution - clipper_
clipper64_ ⚠set_ preserve_ collinear - Clipper64 Setters / Getters
- clipper_
clipper64_ ⚠set_ reverse_ solution - clipper_
clipper64_ ⚠size - clipper_
clipperd ⚠ - clipper_
clipperd_ ⚠add_ clip - clipper_
clipperd_ ⚠add_ open_ subject - clipper_
clipperd_ ⚠add_ subject - ClipperD Methods
- clipper_
clipperd_ ⚠clear - clipper_
clipperd_ ⚠execute - Decimal-coordinate version of clipper_clipper64_execute.
- clipper_
clipperd_ ⚠execute_ tree_ with_ open - Decimal-coordinate version of clipper_clipper64_execute_tree_with_open.
- clipper_
clipperd_ ⚠get_ preserve_ collinear - clipper_
clipperd_ ⚠get_ reverse_ solution - clipper_
clipperd_ ⚠set_ preserve_ collinear - ClipperD Setters / Getters
- clipper_
clipperd_ ⚠set_ reverse_ solution - clipper_
clipperd_ ⚠size - clipper_
clipperoffset ⚠ - ClipperOffset Constructors
- clipper_
clipperoffset_ ⚠add_ path64 - ClipperOffset Methods
- clipper_
clipperoffset_ ⚠add_ paths64 - clipper_
clipperoffset_ ⚠clear - clipper_
clipperoffset_ ⚠error_ code - clipper_
clipperoffset_ ⚠execute - clipper_
clipperoffset_ ⚠get_ arc_ tolerance - clipper_
clipperoffset_ ⚠get_ miter_ limit - clipper_
clipperoffset_ ⚠get_ preserve_ collinear - clipper_
clipperoffset_ ⚠get_ reverse_ solution - clipper_
clipperoffset_ ⚠set_ arc_ tolerance - clipper_
clipperoffset_ ⚠set_ miter_ limit - ClipperOffset Setters / Getters
- clipper_
clipperoffset_ ⚠set_ preserve_ collinear - clipper_
clipperoffset_ ⚠set_ reverse_ solution - clipper_
clipperoffset_ ⚠size - clipper_
delete_ ⚠clipper64 - clipper_
delete_ ⚠clipperd - clipper_
delete_ ⚠clipperoffset - clipper_
delete_ ⚠path64 - clipper_
delete_ ⚠pathd - clipper_
delete_ ⚠paths64 - clipper_
delete_ ⚠pathsd - clipper_
delete_ ⚠polytree64 - clipper_
delete_ ⚠polytreed - clipper_
path64 ⚠ - Path Constructors
- clipper_
path64_ ⚠add_ point - clipper_
path64_ ⚠area - clipper_
path64_ ⚠get_ point - clipper_
path64_ ⚠length - Path Conversions (to C)
- clipper_
path64_ ⚠minkowski_ diff - Minkowski difference: like clipper_path64_minkowski_sum but
translates
patternby -p instead of +p at each vertex ofpath. For a pattern that is symmetric about the origin (e.g. a centred disc or square) sum and difference produce the same result; the distinction matters as soon as the pattern is asymmetric, where difference is the operation you want for “set of points x such that x + pattern is contained in path” intuitions (robot-footprint configuration space, tool-reachability inside a pocket). - clipper_
path64_ ⚠minkowski_ sum - Minkowski sum: sweep the
patternpolygon alongpath, returning the union of all translated copies ofpatternplaced at every vertex ofpath. Geometrically this is { a + b | a in pattern, b in path } — useful when you need to grow a shape by an arbitrary polygonal kernel rather than the radius-only kernel that clipper_paths64_inflate offers. - clipper_
path64_ ⚠of_ points - clipper_
path64_ ⚠simplify - clipper_
path64_ ⚠size - Bytes required for placement-new construction of a ClipperPath64.
- clipper_
path64_ ⚠to_ pathd - Path Conversions
- clipper_
pathd ⚠ - clipper_
pathd_ ⚠add_ point - clipper_
pathd_ ⚠area - clipper_
pathd_ ⚠get_ point - clipper_
pathd_ ⚠length - clipper_
pathd_ ⚠minkowski_ diff - Decimal-coordinate version of clipper_path64_minkowski_diff. See
clipper_pathd_minkowski_sum for the meaning of
precision. - clipper_
pathd_ ⚠minkowski_ sum - Decimal-coordinate version of clipper_path64_minkowski_sum. The
precisionargument selects how many fractional digits are preserved when Clipper2 internally scales to integers, runs the algorithm, and scales back; see the crate-level “_64 (i64) vs _D (f64) variants” documentation for the precision / range / quantisation tradeoffs. Two decimal places is upstream’s default. - clipper_
pathd_ ⚠of_ points - clipper_
pathd_ ⚠simplify - clipper_
pathd_ ⚠size - clipper_
pathd_ ⚠to_ path64 - clipper_
paths64 ⚠ - clipper_
paths64_ ⚠add_ path - clipper_
paths64_ ⚠add_ paths - clipper_
paths64_ ⚠area - clipper_
paths64_ ⚠get_ path - clipper_
paths64_ ⚠get_ point - clipper_
paths64_ ⚠inflate - Path Offsetting
- clipper_
paths64_ ⚠length - clipper_
paths64_ ⚠minkowski_ diff - Multi-path variant of clipper_path64_minkowski_diff; same shape as clipper_paths64_minkowski_sum.
- clipper_
paths64_ ⚠minkowski_ sum - Multi-path variant of clipper_path64_minkowski_sum. The pattern is
a single path applied to every input path in
paths; the per-path results are unioned withfillrule, so this is exactly equivalent to running clipper_path64_minkowski_sum once per input path and unioning the outputs — provided here for the common case of a scene-wide kernel sweep over many polygons. - clipper_
paths64_ ⚠of_ paths - clipper_
paths64_ ⚠path_ length - clipper_
paths64_ ⚠simplify - clipper_
paths64_ ⚠size - clipper_
paths64_ ⚠to_ pathsd - clipper_
pathsd ⚠ - clipper_
pathsd_ ⚠add_ path - clipper_
pathsd_ ⚠add_ paths - clipper_
pathsd_ ⚠area - clipper_
pathsd_ ⚠get_ path - clipper_
pathsd_ ⚠get_ point - clipper_
pathsd_ ⚠inflate - clipper_
pathsd_ ⚠length - clipper_
pathsd_ ⚠minkowski_ diff - Decimal-coordinate version of clipper_paths64_minkowski_diff. See
clipper_pathd_minkowski_sum for the meaning of
precision. - clipper_
pathsd_ ⚠minkowski_ sum - Decimal-coordinate version of clipper_paths64_minkowski_sum. See
clipper_pathd_minkowski_sum for the meaning of
precision. - clipper_
pathsd_ ⚠of_ paths - clipper_
pathsd_ ⚠path_ length - clipper_
pathsd_ ⚠simplify - clipper_
pathsd_ ⚠size - clipper_
pathsd_ ⚠to_ paths64 - clipper_
point_ ⚠in_ path64 - clipper_
point_ ⚠in_ pathd - clipper_
polytree64 ⚠ - PolyTree Constructors
- clipper_
polytree64_ ⚠add_ child - clipper_
polytree64_ ⚠area - clipper_
polytree64_ ⚠count - clipper_
polytree64_ ⚠get_ child - clipper_
polytree64_ ⚠is_ hole - clipper_
polytree64_ ⚠parent - PolyTree64 Methods
- clipper_
polytree64_ ⚠polygon - clipper_
polytree64_ ⚠size - clipper_
polytree64_ ⚠to_ paths - clipper_
polytreed ⚠ - clipper_
polytreed_ ⚠add_ child - clipper_
polytreed_ ⚠area - clipper_
polytreed_ ⚠count - clipper_
polytreed_ ⚠get_ child - clipper_
polytreed_ ⚠inv_ scale - clipper_
polytreed_ ⚠is_ hole - clipper_
polytreed_ ⚠parent - PolyTreeD Methods
- clipper_
polytreed_ ⚠polygon - clipper_
polytreed_ ⚠set_ inv_ scale - clipper_
polytreed_ ⚠size - clipper_
polytreed_ ⚠to_ paths
Type Aliases§
- Clipper
Clip Type - Boolean operation kind. NONE is the sentinel default for an unconfigured engine — passing it to clipper_*_execute is undefined. Use INTERSECTION / UNION / DIFFERENCE / XOR for the standard four set operations.
- Clipper
EndType - Open-path endpoint handling for ClipperOffset. POLYGON_END is the closed-polygon case — no endpoints to inflate. The other variants decide how the start and end of a polyline are extended (listed in enum order): JOINED keeps polylines connected to neighbouring segments, BUTT keeps the line flat at the original endpoint, SQUARE extends one delta past it, ROUND adds a half-circle cap.
- Clipper
Fill Rule - Determines which subregions are ‘inside’ when paths self-intersect or overlap. EVEN_ODD toggles inside/outside on every edge crossing. NON_ZERO uses the winding-number sign — the conventional rule for polygons-with-holes data where holes wind opposite to their outer contour. POSITIVE and NEGATIVE only count windings of the matching sign, useful when direction has been baked into the input.
- Clipper
Join Type - Corner-handling style for ClipperOffset; same shapes as SVG and Cairo stroke joins. SQUARE squares off perpendicular to the corner. BEVEL flattens the corner with a straight cut. ROUND replaces it with a circular arc. MITER extends the offset edges to their intersection, clipped at the configured miter limit.
- Clipper
Path Type - Subject paths are the input geometry being clipped. Clip paths are the mask. The clipping engine combines the two sets according to the chosen ClipperClipType and ClipperFillRule.
- Clipper
Point InPolygon Result