Last active
January 2, 2016 00:59
-
-
Save ColonelThirtyTwo/8227727 to your computer and use it in GitHub Desktop.
Updated C/LuaJIT bindings for Clipper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "clipper.cpp" | |
using namespace ClipperLib; | |
#ifdef __MINGW32__ | |
#define export extern "C" __declspec (dllexport) | |
#else | |
#define export extern "C" | |
#endif | |
// clipper_path class | |
export Path* clipper_path_create(int n) { | |
try { | |
return new Path(n); | |
} catch(...) { | |
return 0; | |
} | |
} | |
export void clipper_path_free(Path* poly) { | |
delete poly; | |
} | |
export int clipper_path_size(Path* poly) { | |
return poly->size(); | |
} | |
export IntPoint* clipper_path_get(Path* poly, int i) { | |
return &((*poly)[i]); | |
} | |
export void clipper_path_set(Path* poly, int i, cInt x, cInt y) | |
{ | |
(*poly)[i] = IntPoint(x,y); | |
} | |
export int clipper_path_add(Path* poly, cInt x, cInt y) { | |
try { | |
poly->push_back(IntPoint(x, y)); | |
return 0; | |
} catch(...) { | |
return 1; | |
} | |
} | |
export Paths* clipper_path_simplify(Path* poly, PolyFillType fill_type) { | |
try { | |
Paths* in = new Paths(); | |
in->push_back(*poly); | |
Paths* out = new Paths(); | |
SimplifyPolygons(*in, *out, PolyFillType(fill_type)); | |
return out; | |
} catch(...) { | |
return 0; | |
} | |
} | |
export Path* clipper_path_clean(Path* poly, double distance) { | |
try { | |
Path* out = new Path(); | |
CleanPolygon(*poly, *out, distance); | |
return out; | |
} catch(...) { | |
return 0; | |
} | |
} | |
export void clipper_path_reverse(Path* poly) { | |
ReversePath(*poly); | |
} | |
export int clipper_path_orientation(Path* poly) { | |
return Orientation(*poly); | |
} | |
export double clipper_path_area(Path* poly) { | |
return Area(*poly); | |
} | |
// clipper_paths class | |
export Paths* clipper_paths_create(int n) { | |
try { | |
return new Paths(n); | |
} catch(...) { | |
return 0; | |
} | |
} | |
export void clipper_paths_free(Paths* poly) { | |
delete poly; | |
} | |
export int clipper_paths_size(Paths* poly) { | |
return poly->size(); | |
} | |
export Path* clipper_paths_get(Paths* poly, int i) { | |
return &((*poly)[i]); | |
} | |
export void clipper_paths_set(Paths* poly, int i, Path* e) { | |
(*poly)[i] = *e; | |
} | |
export int clipper_paths_add(Paths* poly, Path* e) { | |
try { | |
poly->push_back(*e); | |
return 0; | |
} catch(...) { | |
return 1; | |
} | |
} | |
export Paths* clipper_paths_simplify(Paths* poly, PolyFillType fill_type) { | |
try { | |
Paths* out = new Paths(); | |
SimplifyPolygons(*poly, *out, PolyFillType(fill_type)); | |
return out; | |
} catch(...) { | |
return 0; | |
} | |
} | |
export Paths* clipper_paths_clean(Paths* poly, double distance) { | |
try { | |
Paths* out = new Paths(poly->size()); | |
CleanPolygons(*poly, *out, distance); | |
return out; | |
} catch(...) { | |
return 0; | |
} | |
} | |
export void clipper_paths_reverse(Paths* poly) { | |
ReversePaths(*poly); | |
} | |
/* | |
export Paths* clipper_paths_offset(Paths* poly, double delta, JoinType jointype, double miter_limit) { | |
try { | |
Paths* out = new Paths(); | |
OffsetPaths(*poly, *out, delta, JoinType(jointype), miter_limit, false); | |
return out; | |
} catch(...) { | |
return 0; | |
} | |
} | |
*/ | |
// clipper class | |
export Clipper* clipper_create() { | |
try { | |
return new Clipper(); | |
} catch(...) { | |
return 0; | |
} | |
} | |
export void clipper_free(Clipper* clipper) { | |
delete clipper; | |
} | |
export int clipper_add_path(Clipper* clipper, Path* poly, PolyType poly_type) { | |
clipper->AddPath(*poly, PolyType(poly_type), true); | |
return 0; | |
} | |
export int clipper_add_paths(Clipper* clipper, Paths* poly, PolyType poly_type) { | |
clipper->AddPaths(*poly, PolyType(poly_type), true); | |
return 0; | |
} | |
export void clipper_get_bounds(Clipper* clipper, IntRect* out) { | |
*out = clipper->GetBounds(); | |
} | |
export Paths* clipper_execute(Clipper* clipper, ClipType clipType, | |
PolyFillType subjFillType, | |
PolyFillType clipFillType) { | |
try { | |
Paths* solution = new Paths(); | |
clipper->Execute(ClipType(clipType), *solution, | |
PolyFillType(subjFillType), | |
PolyFillType(clipFillType)); | |
return solution; | |
} catch(...) { | |
return 0; | |
} | |
} | |
export void clipper_clear(Clipper* clipper) { | |
clipper->Clear(); | |
} | |
export int clipper_get_reverse_solution(Clipper* clipper) { | |
return clipper->ReverseSolution(); | |
} | |
export void clipper_set_reverse_solution(Clipper* clipper, int reverse) { | |
clipper->ReverseSolution(reverse); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local ffi = require'ffi' | |
local C = ffi.load'clipper-c' | |
ffi.cdef[[ | |
typedef signed long long cInt; | |
typedef unsigned long long cUInt; | |
typedef struct clipper_point_st { cInt x, y; } clipper_point; | |
typedef struct clipper_rect_st { cInt x1, y1, x2, y2; } clipper_rect; | |
typedef enum { | |
clipper_ctIntersection, | |
clipper_ctUnion, | |
clipper_ctDifference, | |
clipper_ctXor | |
} clipper_ClipType; | |
typedef enum { | |
clipper_ptSubject, | |
clipper_ptClip | |
} clipper_PolyType; | |
typedef enum { | |
clipper_pftEvenOdd, | |
clipper_pftNonZero, | |
clipper_pftPositive, | |
clipper_pftNegative | |
} clipper_PolyFillType; | |
typedef enum { | |
clipper_jtSquare, | |
clipper_jtRound, | |
clipper_jtMiter | |
} clipper_JoinType; | |
typedef struct clipper_Path clipper_path; | |
typedef struct clipper_Paths clipper_paths; | |
typedef struct clipper_Clipper clipper; | |
clipper_path* clipper_path_create(int); | |
void clipper_path_free (clipper_path*); | |
int clipper_path_size (clipper_path*); | |
clipper_point* clipper_path_get (clipper_path*, int); | |
int clipper_path_set (clipper_path*, int, cInt x, cInt y); | |
int clipper_path_add (clipper_path*, cInt x, cInt y); | |
clipper_paths* clipper_path_simplify (clipper_path*, clipper_PolyFillType); | |
clipper_path* clipper_path_clean (clipper_path*, double); | |
void clipper_path_reverse (clipper_path*); | |
int clipper_path_orientation (clipper_path*); | |
double clipper_path_area (clipper_path*); | |
clipper_paths* clipper_paths_create(int n); | |
void clipper_paths_free (clipper_paths*); | |
int clipper_paths_size (clipper_paths*); | |
clipper_path* clipper_paths_get (clipper_paths*, int); | |
void clipper_paths_set (clipper_paths*, int, clipper_path*); | |
int clipper_paths_add (clipper_paths*, clipper_path*); | |
clipper_paths* clipper_paths_simplify (clipper_paths*, clipper_PolyFillType); | |
clipper_paths* clipper_paths_clean (clipper_paths*, double); | |
void clipper_paths_reverse (clipper_paths*); | |
clipper_paths* clipper_paths_offset (clipper_paths*, double, clipper_JoinType, double); | |
clipper* clipper_create(); | |
void clipper_free (clipper*); | |
int clipper_add_path (clipper*, clipper_path*, clipper_PolyType); | |
int clipper_add_paths (clipper*, clipper_paths*, clipper_PolyType); | |
void clipper_get_bounds (clipper*, clipper_rect*); | |
clipper_paths* clipper_execute (clipper*, clipper_ClipType, | |
clipper_PolyFillType, | |
clipper_PolyFillType); | |
void clipper_clear (clipper*); | |
int clipper_get_reverse_solution (clipper*); | |
void clipper_set_reverse_solution (clipper*, int); | |
]] | |
local fill_types = { | |
even_odd = C.clipper_pftEvenOdd, | |
non_zero = C.clipper_pftNonZero, | |
positive = C.clipper_pftPositive, | |
negative = C.clipper_pftNegative, | |
} | |
local join_types = { | |
square = C.clipper_jtSquare, | |
round = C.clipper_jtRound, | |
miter = C.clipper_jtMiter, | |
} | |
local clip_types = { | |
intersection = C.clipper_ctIntersection, | |
union = C.clipper_ctUnion, | |
difference = C.clipper_ctDifference, | |
xor = C.clipper_ctXor | |
} | |
local clipper_type = ffi.typeof 'clipper' | |
local path_type = ffi.typeof'clipper_path' | |
local paths_type = ffi.typeof 'clipper_paths' | |
local function is_path(poly) | |
return ffi.istype(path_type, poly) | |
end | |
local Path = {} --path methods | |
Path.__index = Path | |
function Path:__new(n) | |
return C.clipper_path_create(n or 0) | |
end | |
Path.__gc = C.clipper_path_free | |
function Path:free() | |
C.clipper_path_free(self) | |
ffi.gc(self, nil) | |
end | |
function Path:size() | |
-- Lua passes two arguments to __len: self and nil, which causes an error when directly using the C function | |
return C.clipper_path_size(self) | |
end | |
Path.__len = Path.size | |
function Path:get(i) | |
return C.clipper_path_get(self, i-1) | |
end | |
function Path:set(i, x, y) | |
C.clipper_path_set(self, i, x, y) | |
end | |
function Path:add(x, y) | |
assert(C.clipper_path_add(self, x, y) == 0, 'out of memory') | |
end | |
function Path:simplify(fill_type) | |
local out = C.clipper_path_simplify(self, fill_types[fill_type or 'even_odd']) | |
return ffi.gc(out, C.clipper_paths_free) | |
end | |
function Path:clean(d) | |
local out = C.clipper_path_clean(self, d or 1.415) | |
return ffi.gc(out, C.clipper_path_free) | |
end | |
Path.reverse = C.clipper_path_reverse | |
function Path:orientation() | |
return C.clipper_path_orientation(self) == 1 | |
end | |
Path.area = C.clipper_path_area | |
local Paths = {} --paths methods | |
Paths.__index = Paths | |
function Paths:__new(...) | |
if is_path(...) then | |
local n = select('#',...) | |
local out = C.clipper_paths_create(n) | |
for i=1,n do | |
out:set(i, select(i,...)) | |
end | |
return out | |
else | |
return C.clipper_paths_create(... or 0) | |
end | |
end | |
Paths.__gc = C.clipper_paths_free | |
function Paths:free() | |
C.clipper_paths_free(self) | |
ffi.gc(self, nil) | |
end | |
Paths.size = C.clipper_paths_size | |
function Paths:get(i) | |
return C.clipper_paths_get(self, i-1) | |
end | |
function Paths:set(i, poly) | |
return C.clipper_paths_set(self, i-1, poly) | |
end | |
function Paths:add(poly) | |
assert(C.clipper_paths_add(self, poly) == 0, 'out of memory') | |
end | |
function Paths:simplify(fill_type) | |
local out = C.clipper_paths_simplify(self, fill_types[fill_type or 'even_odd']) | |
return ffi.gc(out, C.clipper_paths_free) | |
end | |
function Paths:clean(d) | |
local out = C.clipper_paths_clean(self, d or 1.415) | |
return ffi.gc(out, C.clipper_paths_free) | |
end | |
Paths.reverse = C.clipper_paths_reverse | |
function Paths:offset(delta, join_type, limit) | |
local out = C.clipper_paths_offset(self, delta, join_types[join_type or 'square'], limit or 0) | |
return ffi.gc(out, C.clipper_paths_free) | |
end | |
local Clipper = {} --clipper methods | |
Clipper.__index = Clipper | |
function Clipper:__new() | |
return C.clipper_create() | |
end | |
Clipper.__gc = C.clipper_free | |
function Clipper:free() | |
C.clipper_free(self) | |
ffi.gc(self, nil) | |
end | |
local function Clipper_add(self, poly, where_flag) | |
if is_path(poly) then | |
C.clipper_add_path(self, poly, where_flag) | |
else | |
C.clipper_add_paths(self, poly, where_flag) | |
end | |
end | |
function Clipper:add_subject(poly) clipper_add(self, poly, C.clipper_ptSubject) end | |
function Clipper:add_clip(poly) clipper_add(self, poly, C.clipper_ptClip) end | |
function Clipper:get_bounds(r) | |
local r = r or ffi.new'clipper_rect' | |
C.clipper_get_bounds(self, r) | |
return r.x1, r.y1, r.x2, r.y2 | |
end | |
function Clipper:execute(clip_type, subj_fill_type, clip_fill_type, reverse) | |
C.clipper_set_reverse_solution(self, reverse and 1 or 0) | |
local out = C.clipper_execute(self, | |
clip_types[clip_type], | |
fill_types[subj_fill_type or 'even_odd'], | |
fill_types[clip_fill_type or 'even_odd']) | |
return ffi.gc(out, C.clipper_paths_free) | |
end | |
Clipper.clear = C.clipper_clear | |
ffi.metatype(clipper_type, Clipper) | |
ffi.metatype(path_type, Path) | |
ffi.metatype(paths_type, Paths) | |
return { | |
Clipper = clipper_type, | |
Path = path_type, | |
Paths = paths_type, | |
lib = C, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment