Skip to content

Instantly share code, notes, and snippets.

@esnya
Last active December 30, 2015 06:53
Show Gist options
  • Select an option

  • Save esnya/43ac84364c94482cf80c to your computer and use it in GitHub Desktop.

Select an option

Save esnya/43ac84364c94482cf80c to your computer and use it in GitHub Desktop.
Minimal wrapper for DererictFI
public import derelict.freeimage.freeimage;
import std.traits;
static this() {
DerelictFI.load();
}
auto camelize(T)(T str) {
import std.ascii : toUpper;
return str[0].toUpper() ~ str[1 .. $];
}
class Bitmap {
this(FIBITMAP* handle) in {
assert(handle);
} body {
this.handle = handle;
}
~this() {
this.unload();
}
private FIBITMAP* _handle;
@property FIBITMAP* handle() { return _handle; }
protected @property void handle(FIBITMAP* handle) { _handle = handle; }
auto opDispatch(string op, T...)(T args) if (isCallable!(FreeImage.FreeImageOf!op)) {
return FreeImage.opDispatch!(op)(this, args);
}
auto opDispatch(string op, T...)(T args) if (T.length == 0 && !isCallable!(FreeImage.FreeImageOf!op) && isCallable!(FreeImage.FreeImageOf!("Get" ~ op.camelize))) {
return this.opDispatch!("Get" ~ op.camelize)(args);
}
}
struct FreeImage {
template FreeImageOf(string name) {
enum Name = "FreeImage_" ~ name.camelize;
static if (is(typeof(mixin(Name)))) {
mixin("alias FreeImageOf = " ~ Name ~ ";");
} else {
alias FreeImageOf = void;
}
}
alias ParameterTypeTupleOf(string name) = ParameterTypeTuple!(FreeImageOf!name);
alias ParameterDefaultsOf(string name) = ParameterDefaults!(FreeImageOf!name);
static auto opDispatch(string op, T...)(T args) if (isCallable!(FreeImageOf!op) && (T.length == ParameterTypeTupleOf!op.length || T.length < ParameterTypeTupleOf!op.length && !is(ParameterDefaultsOf!op[T.length] == void))) {
alias Func = FreeImageOf!op;
ParameterTypeTupleOf!op _args;
foreach (i, D; ParameterTypeTupleOf!op) {
static if (i >= T.length) {
_args[i] = ParameterDefaultsOf!op[i];
} else {
alias S = typeof(args[i]);
static if (isAssignable!(D, S)) {
_args[i] = args[i];
} else static if (hasMember!(S, "handle") && isAssignable!(D, typeof(mixin("args[i].handle")))) {
_args[i] = args[i].handle;
} else static if (isPointer!D && is(Unqual!(PointerTarget!D) == char)) {
version(Windows) {
import std.windows.charset;
_args[i] = args[i].toMBSz(1);
} else {
import std.string;
_args[i] = args[i].toStringz();
}
} else static if (isPointer!D && is(Unqual!(PointerTarget!D) == wchar)) {
import std.utf;
_args[i] = args[i].toUTF16z();
} else {
static assert("Can't convert " ~ S.stringof ~ " to " ~ D.stringof);
}
}
}
static if (is(ReturnType!Func == void)) {
Func(_args);
} else {
auto result = Func(_args);
static if (isPointer!(ReturnType!Func) || is(ReturnType!Func == BOOL)) {
import std.exception : enforce;
enforce(result, (() {
char[] msg;
msg ~= "Error occoured on FreeImage.";
msg ~= op;
msg ~= '(';
foreach (i, arg; args) {
import std.conv : to;
if (i > 0) msg ~= ", ";
msg ~= arg.to!string();
}
msg ~= ')';
return msg.idup;
})());
}
static if (is(PointerTarget!(ReturnType!Func) == FIBITMAP)) {
return new Bitmap(result);
} else {
return result;
}
}
}
}
unittest {
auto img = FreeImage.Allocate(320, 240, 32);
assert(img.width == 320);
assert(img.height == 240);
delete img;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment