Graphics-Potrace
view release on metacpan or search on metacpan
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "potracelib.h"
#define ASSERT_SCALAR(sv,message) \
if (sv == NULL) { \
warn(message, __LINE__); \
goto CLEAN_AND_LEAVE; \
}
SV *_make_point(const potrace_dpoint_t *p) {
AV *point = newAV();
av_push(point, newSVnv(p->x));
av_push(point, newSVnv(p->y));
return newRV_noinc((SV *)point);
}
SV *_make_pathnode(potrace_path_t *node) {
HV *retval = newHV();
AV *curve = newAV();
unsigned int i;
int tag;
potrace_dpoint_t *c = NULL;
HV *segment = NULL;
HV *first_segment = NULL;
SV *last_endpoint = NULL;
hv_store(retval, "area", 4, newSViv(node->area), FALSE);
hv_store(retval, "sign", 4, newSVpvn((node->sign == '-' ? "-" : "+"), 1), FALSE);
hv_store(retval, "curve", 5, newRV_noinc((SV *)curve), FALSE);
for (i = 0; i < (node->curve).n; ++i) {
tag = (node->curve).tag[i];
c = (node->curve).c[i];
segment = newHV();
if (first_segment == NULL)
first_segment = segment;
if (last_endpoint) {
hv_store(segment, "begin", 5, last_endpoint, FALSE);
last_endpoint = NULL;
}
hv_store(segment, "end", 3, _make_point(c+2), FALSE);
last_endpoint = _make_point(c+2); /* "begin" of the next segment */
if (tag == POTRACE_CORNER) {
hv_store(segment, "type", 4, newSVpvn("corner", 6), FALSE);
hv_store(segment, "corner", 6, _make_point(c+1), FALSE);
}
else if (tag == POTRACE_CURVETO) {
hv_store(segment, "type", 4, newSVpvn("bezier", 6), FALSE);
hv_store(segment, "u", 1, _make_point(c), FALSE);
hv_store(segment, "w", 1, _make_point(c+1), FALSE);
}
else {
warn("Unknown tag: %d", tag);
hv_store(segment, "type", 4, newSVpvn("unknown", 7), FALSE);
hv_store(segment, "tag", 3, newSViv(tag), FALSE);
hv_store(segment, "p1", 2, _make_point(c), FALSE);
hv_store(segment, "p2", 2, _make_point(c+1), FALSE);
}
av_push(curve, newRV_noinc((SV *)segment));
}
if (last_endpoint)
hv_store(first_segment, "begin", 5, last_endpoint, FALSE);
return newRV_noinc((SV *)retval);
}
SV *_make_listpath(potrace_path_t *plist) {
AV *retval = newAV();
SV *node = NULL;
unsigned int n = 0;
while (plist != NULL) {
node = _make_pathnode(plist);
av_push(retval, node);
plist = plist->next;
}
return newRV_noinc((SV *)retval);
}
SV *_make_treepath(potrace_path_t *plist) {
AV *retval = newAV();
SV *node = NULL;
unsigned int n = 0;
while (plist != NULL) {
node = _make_pathnode(plist);
hv_store((HV*)SvRV(node), "children", 8, _make_treepath(plist->childlist), FALSE);
av_push(retval, node);
plist = plist->sibling;
}
return newRV_noinc((SV *)retval);
}
void _progress_callback (double progress, void *data) {
dSP;
HV *handler = (HV *) SvRV((SV*) data);
ENTER;
SAVETMPS;
PUSHMARK(SP);
if (hv_exists(handler, "data", 4))
XPUSHs(*hv_fetch(handler, "data", 4, FALSE));
PUTBACK;
call_sv(*hv_fetch(handler, "callback", 8, FALSE), G_DISCARD);
FREETMPS;
LEAVE;
}
int _set_progress (potrace_progress_t *target, SV *input) {
SV *callback = input;
HV *hash = NULL;
SV *data = NULL;
HV *handler = newHV();
target->callback = _progress_callback;
target->data = (void *) handler;
( run in 2.463 seconds using v1.01-cache-2.11-cpan-0bb4e1dffa6 )