Пример #1
0
SOCKET val_sock(value inValue)
{
   if (!val_is_null(inValue))
   {
      if (val_is_kind(inValue,k_socket) )
         return ((SOCKET)(socket_int)val_data(inValue));
      inValue = val_field(inValue,id___s);
      if (val_is_kind(inValue,k_socket) )
         return ((SOCKET)(socket_int)val_data(inValue));
   }
   val_throw(alloc_string("Invalid socket handle"));
   return 0;
}
Пример #2
0
/**
	Destroy an ENetPeer structure.
**/
static void destroy_enetpeer( value p ) {
#ifdef ENET_DEBUG
	fprintf(stderr, "*** destroy_enetpeer\n");
	exit(0);
#endif
return;
	ENetPeer *peer;
	if(!val_is_abstract(p) || !val_is_kind(p, k_udprpeer))
		return;
	peer = (ENetPeer *)val_data(p);
	if(peer == NULL)
		return;

	// force immediate disconnect, if still connected.
	enet_peer_disconnect_now(peer, 0);

	// if the peer has an event still, destroy it
	//free_peer_event(peer);

	// clear the peer structure
	enet_peer_reset(peer);

	// peers never need be deallocated, they are part of an ENetHost
#ifdef ENET_DEBUG
	fprintf(stderr, "*** destroy_enetpeer done.\n");
#endif
	return;
}
Пример #3
0
/**
	Destroy an allocated ENetHost pointer. Must be used with val_gc() for every ENetHost created.
*/
static void destroy_enethost( value h ) {
#ifdef ENET_DEBUG
	fprintf(stderr, "*** destroy_enethost\n");
	//exit(0);
#endif
//return;
	if(!val_is_kind(h, k_udprhost))
		return;
	ENetHost *host = (ENetHost *)val_data(h);
	ENetPeer *peer;
	//int x, count;
	if(host == NULL)
		return;
	enet_host_flush( host );
	for (peer = host->peers;
         peer < &host->peers[host->peerCount];
         ++peer)
    {
    	if (peer->state == ENET_PEER_STATE_CONNECTED) {
    		enet_peer_disconnect_now(peer, 0);
    	}
    }

#ifdef ENET_DEBUG
	fprintf(stderr, "*** destroy_enethost\n");
#endif
	enet_host_destroy( host );
	//val_kind(v) = NULL;
#ifdef ENET_DEBUG
	fprintf(stderr, "*** destroy_enethost done.\n");
#endif
	return;
}
Пример #4
0
/**
	Set the in and out speeds of a host in Bytes per second.
**/
static value udpr_setrate(value o, value in, value out)
{
    if( !val_is_abstract(o) || !val_is_kind(o,k_udprhost) )
		neko_error();
	enet_host_bandwidth_limit((ENetHost *)val_data(o), (enet_uint32)val_int32(in), (enet_uint32)val_int32(out));
	return val_true;
}
Пример #5
0
/**
	Destroy an allocated ENetEvent struct
**/
static void destroy_enetevent( value e ) {
	ENetEvent *event;
	if( !val_is_abstract(e) || !val_is_kind(e,k_udprevent) )
		return;
	event = (ENetEvent *)val_data(e);
	if(e == NULL)
		return;

	// enet_packet_destroy frees the packet itself.
#ifdef ENET_DEBUG
printf("*** destroy_enetevent freeing packet\n");
#endif
	if(event->packet != NULL)
		enet_packet_destroy (event->packet);
	//if(event->type == ENET_EVENT_TYPE_DISCONNECT
		//&& event->peer->data != NULL)
			//enet_free(event->peer -> data);
#ifdef ENET_DEBUG
//printf("*** destroy_enetevent freeing event\n");
#endif
	enet_free(event);
#ifdef ENET_DEBUG
//printf("*** destroy_enetevent done.\n");
#endif
	return;
}
Пример #6
0
static void dump_module( value v, field f, void *p ) {
	value vname;
	const char *name;
	if( !val_is_kind(v,neko_kind_module) )
		return;
	vname = val_field_name(f);
	name = val_is_null(vname)?"???":val_string(vname);
	((dump_param*)p)->callb( name, (neko_module*)val_data(v), &((dump_param*)p)->tot );
}
Пример #7
0
/**
	Returns an ENetPeer *, or throw if connection fails.
**/
static value udpr_connect(value h, value ip, value port, value channels, value timeout) {
    ENetAddress address;
    ENetEvent event;
    ENetHost *host;
    ENetPeer *peer;
    int to;

	if( !val_is_abstract(h) || !val_is_kind(h,k_udprhost) )
		neko_error();

	// checked in address population
	//val_check(ip,int);
	//val_check(port,int);
	val_check(channels,int);
	val_check(timeout,int);
	to = val_int(timeout);
	if(to < 0)
		to = 5000;

	host = (ENetHost *)val_data(h);
	if(populate_address(&address, ip, port) != val_true)
		neko_error();

    // Initiate the connection with channels 0..channels-1
    peer = enet_host_connect (host, &address, (size_t)val_int(channels));
    if (peer == NULL)
    	neko_error();

#ifdef ENET_DEBUG
		fprintf(stderr, "udpr_connect: waiting %d\n", to);
#endif
    /* Wait up to 5 seconds for the connection attempt to succeed. */
    if (enet_host_service (host, & event, to) > 0 &&
        event.type == ENET_EVENT_TYPE_CONNECT)
    {
    	// success
#ifdef ENET_DEBUG
		fprintf(stderr, "udpr_connect: returning peer %x\n", peer);
#endif
		value v = alloc_abstract(k_udprpeer,peer);
		//val_gc(v, destroy_enetpeer);
		return v;
    }

	// timeout has occurred or disconnect received.
#ifdef ENET_DEBUG
	fprintf(stderr, "udpr_connect: *** enet_peer_reset\n");
#endif
    enet_peer_reset (peer);
    neko_error();
}
Пример #8
0
/**
	Returns the ENetPeer that generated an event, with the Event
	allocated pointer in Peer->data. The returned ENetPeer must not
	be destroyed, since it's a copy of an existing peer pointer.
	Timeout is float number of seconds (0.001 == 1 ms)
**/
static value udpr_poll(value h, value timeout)
{
	//ENetPeerHandle hndPeer = enet_host_peer_to_handle(host, event->peer);
    ENetEvent *event;
    int res;

	if( !val_is_abstract(h) || !val_is_kind(h,k_udprhost) )
		neko_error();

	val_check(timeout,number);
	enet_uint32 tout = (enet_uint32)(val_number(timeout)*1000);

	event = (ENetEvent *) enet_malloc (sizeof (ENetEvent));

    // Wait up to timeout milliseconds for an event.

    res = enet_host_service ((ENetHost *)val_data(h), event, tout);
    if(res <= 0) {
    	if(res == 0)
    		return val_null;
    	neko_error();
    }

	switch (event->type)
	{
	case ENET_EVENT_TYPE_NONE:
		//if(event->peer != NULL)
			//free_peer_event(event->peer);
		enet_free(event);
		return val_null;
		break;
	default:
		// auto frees any existing unhandled event, add this event.
#ifdef ENET_DEBUG_FULL
		if(event->type == ENET_EVENT_TYPE_RECEIVE)
			fprintf(stderr, "udpr_poll: event type %s %0.*s\n", event_to_string(event->type), event->packet->dataLength, event->packet->data);
		else
			fprintf(stderr, "udpr_poll: event type %s\n", event_to_string(event->type));
#endif
		break;
	}

	value v = alloc_abstract(k_udprevent,event);
	val_gc(v, destroy_enetevent);
	return v;
#ifdef ENET_DEBUG
	//fprintf(stderr, "udpr_poll: returning peer %x\n", event->peer);
#endif
	//value v = alloc_abstract(k_udprpeer, event->peer);
	//return v;
}
Пример #9
0
value ftRenderGlyph( value font, value _index, value _size, value _hint ) {
    if( !val_is_object(font) ) {
        ft_failure_v("not a freetype font face: ", font );
    }
    value __f = val_field( font, val_id("__f") );
    if( __f == NULL || !val_is_abstract( __f ) || !val_is_kind( __f, k_ft_face ) ) {
        ft_failure_v("not a freetype font face: ", font );
    }
    FT_Face *face = val_data( __f );

    val_check( _size, number );
    int size = val_number(_size);
    FT_Set_Char_Size( *face, size, size, 72, 72 );
    
    val_check( _hint, bool );
    int hint = val_bool(_hint);
    
    val_check(_index,number);
    /*
    int index = FT_Get_Char_Index( *face, (FT_UInt) val_number(_index) );
    fprintf( stderr, "char %i is glyph %i\n", (int)val_number(_index), (int)index );
    int err = FT_Load_Glyph( *face, index, FT_LOAD_RENDER | FT_LOAD_NO_HINTING );
        fprintf( stderr, "Load Glyph idx %i->%i/%i, sz %i, face %p: err 0x%x\n",
                (int)val_number(_index), index, 
                (int)((*face)->num_glyphs), size>>6, face, err );
    */
    int err = FT_Load_Char( *face, (FT_ULong)val_number(_index), FT_LOAD_RENDER | (hint?0:FT_LOAD_NO_HINTING) );
    if( err ) { 
        
        fprintf( stderr, "Load_Char failed: %x char index %i\n", err, FT_Get_Char_Index( *face, (FT_UInt) val_number(_index) ) );
        val_throw(alloc_string("Could not load requested Glyph"));
   //     return( val_null );
    }
    FT_GlyphSlot glyph = (*face)->glyph;
    /*
    err = FT_Render_Glyph( glyph, FT_RENDER_MODE_NORMAL );
    if( err || glyph->format != ft_glyph_format_bitmap ) {
        val_throw(alloc_string("Could not render requested Glyph"));
    }
    */
    FT_Bitmap bitmap = glyph->bitmap;

    value ret = alloc_object(NULL);
    alloc_field( ret, val_id("width"), alloc_int(bitmap.width) );
    alloc_field( ret, val_id("height"), alloc_int(bitmap.rows) );
    alloc_field( ret, val_id("bitmap"), copy_string( (char*)bitmap.buffer, bitmap.width*bitmap.rows ) );
    alloc_field( ret, val_id("x"), alloc_int( glyph->metrics.horiBearingX ) );
    alloc_field( ret, val_id("y"), alloc_int( glyph->metrics.horiBearingY ) );
    alloc_field( ret, val_id("advance"), alloc_float( glyph->advance.x ));
    return ret;
}
Пример #10
0
	bool AbstractToObject (value inValue, OBJ *&outObj) {
		
		outObj = 0;
		
		if (!val_is_kind (inValue, gObjectKind)) {
			
			return false;
			
		}
		
		Object* obj = (Object*)val_to_kind (inValue, gObjectKind);
		outObj = dynamic_cast<OBJ*> (obj);
		return outObj;
		
	}
Пример #11
0
/**
	set_flush_mode : 'stream -> string -> void
	<doc>Change the flush mode ("NO","SYNC","FULL","FINISH","BLOCK")</doc>
**/
static value set_flush_mode( value s, value flush ) {
	int f;
	if( !val_is_kind(s,k_stream_inf) )
		val_check_kind(s,k_stream_def);
	val_check(flush,string);
	if( strcmp(val_string(flush),"NO") == 0 )
		f = Z_NO_FLUSH;
	else if( strcmp(val_string(flush),"SYNC") == 0 )
		f = Z_SYNC_FLUSH;
	else if( strcmp(val_string(flush),"FULL") == 0 )
		f = Z_FULL_FLUSH;
	else if( strcmp(val_string(flush),"FINISH") == 0 )
		f = Z_FINISH;
	else if( strcmp(val_string(flush),"BLOCK") == 0 )
		f = Z_BLOCK;
	else
		return alloc_null();
	val_flush(val_stream(s)) = f;
	return alloc_null();
}
Пример #12
0
static fd_set *make_socket_array( value a, int len, fd_set *tmp, SOCKET *n ) {
	int i;
	SOCKET sock;
	if( val_is_null(a) )
		return NULL;
	if( !val_is_array(a) )
		return &INVALID;
	if( len > FD_SETSIZE )
		val_throw(alloc_string("Too many sockets in select"));
	FD_ZERO(tmp);
	for(i=0;i<len;i++) {
		value s = val_array_ptr(a)[i];
		if( !val_is_kind(s,k_socket) )
			return &INVALID;
		sock = val_sock(s);
		if( sock > *n )
			*n = sock;
		FD_SET(sock,tmp);
	}
	return tmp;
}
Пример #13
0
value hx_zmq_construct_socket (value context_handle,value type)
{
	val_is_kind(context_handle,k_zmq_context_handle);
	if (!val_is_int(type)) {
		val_throw(alloc_int(EINVAL));
		return alloc_null();
	}
		
	void *s = zmq_socket (val_data(context_handle),val_int(type));
	int err = zmq_errno();
	
	if (s == NULL) {
		val_throw (alloc_int(err));
		return alloc_null();
	}
	
	// See: http://nekovm.org/doc/ffi#abstracts_and_kinds
	value v =  alloc_abstract(k_zmq_socket_handle,s);
	val_gc(v,finalize_socket);		// finalize_socket is called when the abstract value is garbage collected
	return v;
	
}
Пример #14
0
static value loader_loadmodule( value mname, value vthis ) {
	value o = val_this();
	value cache;
	val_check(o,object);
	val_check(mname,string);
	val_check(vthis,object);
	cache = val_field(o,id_cache);
	val_check(cache,object);
	{
		reader r;
		readp p;
		neko_module *m;
		neko_vm *vm = NEKO_VM();
		field mid = val_id(val_string(mname));
		value mv = val_field(cache,mid);
		if( val_is_kind(mv,neko_kind_module) ) {
			m = (neko_module*)val_data(mv);
			return m->exports;
		}
		open_module(val_field(o,id_path),val_string(mname),&r,&p);
		if( vm->fstats ) vm->fstats(vm,"neko_read_module",1);
		m = neko_read_module(r,p,vthis);
		if( vm->fstats ) vm->fstats(vm,"neko_read_module",0);
		close_module(p);
		if( m == NULL ) {
			buffer b = alloc_buffer("Invalid module : ");
			val_buffer(b,mname);
			bfailure(b);
		}
		m->name = alloc_string(val_string(mname));
		mv = alloc_abstract(neko_kind_module,m);
		alloc_field(cache,mid,mv);
		if( vm->fstats ) vm->fstats(vm,val_string(mname),1);
		neko_vm_execute(neko_vm_current(),m);
		if( vm->fstats ) vm->fstats(vm,val_string(mname),0);
		return m->exports;
	}
}
Пример #15
0
value ftIterateKerningPairs( value font, value callback ) {
    if( !val_is_object(font) ) {
        ft_failure_v("not a freetype font face: ", font );
    }
    value __f = val_field( font, val_id("__f") );
    if( __f == NULL || !val_is_abstract( __f ) || !val_is_kind( __f, k_ft_face ) ) {
        ft_failure_v("not a freetype font face: ", font );
    }
    FT_Face *face = val_data( __f );

	if( !FT_HAS_KERNING((*face)) ) {
		return val_null;
	}
	

	FT_UInt left_index, right_index;
	FT_ULong left, right;
	FT_Vector vec;

    left = FT_Get_First_Char( *face, &left_index );
    while( left != 0 ) {

		right = FT_Get_First_Char( *face, &right_index );
		while( right != 0 ) {

			if( !FT_Get_Kerning( *face, left_index, right_index, FT_KERNING_UNFITTED, &vec ) && vec.x ) {
//				printf("KERNING %c_%c: %f\n", left, right, vec.x );
		        val_call3( callback, alloc_int( (int)left ), alloc_int( (int)right ), alloc_float( vec.x ) );
		    }
	        
	        right = FT_Get_Next_Char( *face, right, &right_index );
	    }
            
        left = FT_Get_Next_Char( *face, left, &left_index );
    }
		
    return val_true;
}
Пример #16
0
/**
	get_adler32 : 'stream -> 'int32
	<doc>Returns the adler32 value of the stream</doc>
**/
static value get_adler32( value s ) {
	if( !val_is_kind(s,k_stream_inf) )
		val_check_kind(s,k_stream_def);
	return alloc_int32(val_stream(s)->adler);
}
Пример #17
0
static value unserialize_rec( sbuffer *b, value loader ) {
	switch( read_char(b) ) {
	case 'N':
		return val_null;
	case 'T':
		return val_true;
	case 'F':
		return val_false;
	case 'i':
		return alloc_int(read_int(b));
	case 'I':
		return alloc_int32(read_int(b));
	case 'f':
		{
			tfloat d;
			read_str(b,sizeof(tfloat),&d);
			return alloc_float(d);
		}
	case 's':
		{
			int l = read_int(b);
			value v;
			if( l < 0 || l > max_string_size )
				ERROR();
			v = alloc_empty_string(l);
			add_ref(b,v);
			read_str(b,l,(char*)val_string(v));
			return v;
		}
	case 'o':
		{
			int f;
			value o = alloc_object(NULL);
			add_ref(b,o);
			while( (f = read_int(b)) != 0 ) {
				value fval = unserialize_rec(b,loader);
				alloc_field(o,(field)f,fval);
			}
			switch( read_char(b) ) {
			case 'p':
				{
					value v = unserialize_rec(b,loader);
					if( !val_is_object(v) )
						ERROR();
					((vobject*)o)->proto = (vobject*)v;
				}
				break;
			case 'z':
				break;
			default:
				ERROR();
			}
			return o;
		}
	case 'r':
		{
			int n = read_int(b);
			if( n < 0 || n >= b->nrefs )
				ERROR();
			return b->trefs[b->nrefs - n - 1];
		}
	case 'a':
		{
			int i;
			int n = read_int(b);
			value o;
			value *t;
			if( n < 0 || n > max_array_size )
				ERROR();
			o = alloc_array(n);
			t = val_array_ptr(o);
			add_ref(b,o);
			for(i=0;i<n;i++)
				t[i] = unserialize_rec(b,loader);
			return o;

		}
	case 'p':
		{
			int nargs = read_int(b);
			vfunction *f = (vfunction*)alloc_function((void*)1,nargs,NULL);
			vfunction *f2;
			value name;
			add_ref(b,(value)f);
			name = unserialize_rec(b,loader);
			f2 = (vfunction*)val_ocall2(loader,id_loadprim,name,alloc_int(nargs));
			if( !val_is_function(f2) || val_fun_nargs(f2) != nargs )
				failure("Loader returned not-a-function");
			f->t = f2->t;
			f->addr = f2->addr;
			f->module = f2->module;
			return (value)f;
		}
	case 'L':
		{
			vfunction *f = (vfunction*)alloc_function((void*)1,0,NULL);
			value mname;
			int pos;
			int nargs;
			value env;
			add_ref(b,(value)f);
			mname = unserialize_rec(b,loader);
			pos = read_int(b);
			nargs = read_int(b);
			env = unserialize_rec(b,loader);
			if( !val_is_array(env) )
				ERROR();
			{
				value exp = val_ocall2(loader,id_loadmodule,mname,loader);
				value mval;
				unsigned int i;
				int_val *mpos;
				neko_module *m;
				if( !val_is_object(exp) ) {
					buffer b = alloc_buffer("module ");
					val_buffer(b,mname);
					buffer_append(b," is not an object");
					bfailure(b);
				}
				mval = val_field(exp,id_module);
				if( !val_is_kind(mval,neko_kind_module) ) {
					buffer b = alloc_buffer("module ");
					val_buffer(b,mname);
					buffer_append(b," has invalid type");
					bfailure(b);
				}
				m = (neko_module*)val_data(mval);
				mpos = m->code + pos;
				for(i=0;i<m->nglobals;i++) {
					vfunction *g = (vfunction*)m->globals[i];
					if( val_is_function(g) && g->addr == mpos && g->module == m && g->nargs == nargs ) {
						f->t = VAL_FUNCTION;
						f->env = env;
						f->addr = mpos;
						f->nargs = nargs;
						f->module = m;
						return (value)f;
					}
				}
				{
					buffer b = alloc_buffer("module ");
					val_buffer(b,mname);
					buffer_append(b," has been modified");
					bfailure(b);
				}
			}
			return val_null;
		}
	case 'x':
		{
			value mname = unserialize_rec(b,loader);
			value data = unserialize_rec(b,loader);
			value exports = val_ocall2(loader,id_loadmodule,mname,loader);
			value s;
			if( !val_is_object(exports) ) {
				buffer b = alloc_buffer("module ");
				val_buffer(b,mname);
				buffer_append(b," is not an object");
				bfailure(b);
			}
			s = val_field(exports,id_unserialize);
			if( !val_is_function(s) || (val_fun_nargs(s) != 1 && val_fun_nargs(s) != VAR_ARGS) ) {
				buffer b = alloc_buffer("module ");
				val_buffer(b,mname);
				buffer_append(b," has invalid __unserialize function");
			}
			s = val_call1(s,data);
			add_ref(b,s);
			return s;
		}
	case 'h':
		{
			int i;
			vhash *h = (vhash*)alloc(sizeof(vhash));
			h->ncells = read_int(b);
			h->nitems = read_int(b);
			h->cells = (hcell**)alloc(sizeof(hcell*)*h->ncells);
			for(i=0;i<h->ncells;i++)
				h->cells[i] = NULL;
			for(i=0;i<h->nitems;i++) {
				hcell **p;
				hcell *c = (hcell*)alloc(sizeof(hcell));
				c->hkey = read_int(b);
				c->key = unserialize_rec(b,loader);
				c->val = unserialize_rec(b,loader);
				c->next = NULL;
				p = &h->cells[c->hkey % h->ncells];
				while( *p != NULL )
					p = &(*p)->next;
				*p = c;
			}
			return alloc_abstract(k_hash,h);
		}
	default:
		ERROR();
		return val_null;
	}
}
Пример #18
0
void serialize_rec( sbuffer *b, value o ) {
	b->nrec++;
	if( b->nrec > 350 )
		failure("Serialization stack overflow");
	switch( val_type(o) ) {
	case VAL_NULL:
		write_char(b,'N');
		break;
	case VAL_BOOL:
		if( val_bool(o) )
			write_char(b,'T');
		else
			write_char(b,'F');
		break;
	case VAL_INT:
		write_char(b,'i');
		write_int(b,val_int(o));
		break;
	case VAL_FLOAT:
		write_char(b,'f');
		write_str(b,sizeof(tfloat),&val_float(o));
		break;
	case VAL_STRING:
		if( !write_ref(b,o,NULL) ) {
			write_char(b,'s');
			write_int(b,val_strlen(o));
			write_str(b,val_strlen(o),val_string(o));
		}
		break;
	case VAL_OBJECT:
		{
			value s;
			if( !write_ref(b,o,&s) ) {
				if( s != NULL ) {
					// reference was not written
					if( !val_is_function(s) || (val_fun_nargs(s) != 0 && val_fun_nargs(s) != VAR_ARGS) )
						failure("Invalid __serialize method");
					write_char(b,'x');
					serialize_rec(b,((neko_module*)((vfunction*)s)->module)->name);
					serialize_rec(b,val_ocall0(o,id_serialize));
					// put reference back
					write_ref(b,o,NULL);
					break;
				}
				write_char(b,'o');
				val_iter_fields(o,serialize_fields_rec,b);
				write_int(b,0);
				o = (value)((vobject*)o)->proto;
				if( o == NULL )
					write_char(b,'z');
				else {
					write_char(b,'p');
					serialize_rec(b,o);
				}
			}
		}
		break;
	case VAL_ARRAY:
		if( !write_ref(b,o,NULL) ) {
			int i;
			int n = val_array_size(o);
			write_char(b,'a');
			write_int(b,n);
			for(i=0;i<n;i++)
				serialize_rec(b,val_array_ptr(o)[i]);
		}
		break;
	case VAL_FUNCTION:
		if( !write_ref(b,o,NULL) ) {
			neko_module *m;
			if( val_tag(o) == VAL_PRIMITIVE ) {
				// assume that alloc_array(0) return a constant array ptr
				// we don't want to access custom memory (maybe not a ptr)
				if( ((vfunction*)o)->env != alloc_array(0) )
					failure("Cannot Serialize Primitive with environment");
				write_char(b,'p');
				write_int(b,((vfunction*)o)->nargs);
				serialize_rec(b,((vfunction*)o)->module);
				break;
			}
			if( val_tag(o) == VAL_JITFUN )
				failure("Cannot Serialize JIT method");
			write_char(b,'L');
			m = (neko_module*)((vfunction*)o)->module;
			serialize_rec(b,m->name);
			write_int(b,(int)((int_val*)((vfunction*)o)->addr - m->code));
			write_int(b,((vfunction*)o)->nargs);
			serialize_rec(b,((vfunction*)o)->env);
		}
		break;
	case VAL_INT32:
		write_char(b,'I');
		write_int(b,val_int32(o));
		break;
	case VAL_ABSTRACT:
		if( val_is_kind(o,k_hash) ) {
			int i;
			vhash *h = val_hdata(o);
			write_char(b,'h');
			write_int(b,h->ncells);
			write_int(b,h->nitems);
			for(i=0;i<h->ncells;i++) {
				hcell *c = h->cells[i];
				while( c != NULL ) {
					write_int(b,c->hkey);
					serialize_rec(b,c->key);
					serialize_rec(b,c->val);
					c = c->next;
				}
			}
			break;
		}
	default:
		failure("Cannot Serialize Abstract");
		break;
	}
	b->nrec--;
}
Пример #19
0
value ftIterateGlyphs( value font, value callbacks ) {
    if( !val_is_object(callbacks) ) {
        ft_failure_v("not a callback function object: ", callbacks );
    }
// printf("A\n");
    field endGlyph = val_id("endGlyph");
    field startContour = val_id("startContour");
    field endContour = val_id("endContour");
    field lineTo = val_id("lineTo");
    field curveTo = val_id("curveTo");
// printf("B\n");
    
    if( !val_is_object(font) ) {
        ft_failure_v("not a freetype font face: ", font );
    }
    value __f = val_field( font, val_id("__f") );
    if( __f == NULL || !val_is_abstract( __f ) || !val_is_kind( __f, k_ft_face ) ) {
        ft_failure_v("not a freetype font face: ", font );
    }
    FT_Face *face = val_data( __f );
// printf("C\n");

	FT_UInt glyph_index;
	FT_ULong character;
	FT_Outline *outline;

    field f_character = val_id("character");
    field f_advance = val_id("advance");
    
    character = FT_Get_First_Char( *face, &glyph_index );

// printf("D\n");
    while( character != 0 ) {
        if( FT_Load_Glyph( *face, glyph_index, FT_LOAD_NO_BITMAP ) ) {
            // ignore (TODO report?)
        } else if( (*face)->glyph->format != FT_GLYPH_FORMAT_OUTLINE ) {
            // ignore (TODO)
        } else {
            outline = &((*face)->glyph->outline);
		    int start = 0, end, contour, p;
		    char control, cubic;
		    int n,i;
// printf("  1\n");
		    for( contour = 0; contour < outline->n_contours; contour++ ) {
			    end = outline->contours[contour];
			    n=0;

    
			    for( p = start; p<=end; p++ ) {
				    control = !(outline->tags[p] & 0x01);
				    cubic = outline->tags[p] & 0x02;

				    if( p==start ) {
                        val_ocall2( callbacks, startContour, 
                                    alloc_int( outline->points[p-n].x ),
                                    alloc_int( outline->points[p-n].y ) );
				    }

				    if( !control && n > 0 ) {
					    importGlyphPoints( &(outline->points[(p-n)+1]), n-1, callbacks, lineTo, curveTo, cubic );
					    n=1;
				    } else {
					    n++;
				    }
			    }

			    if( n ) {
				    // special case: repeat first point
				    FT_Vector points[n+1];
				    int s=(end-n)+2;
				    for( i=0; i<n-1; i++ ) {
					    points[i].x = outline->points[s+i].x;
					    points[i].y = outline->points[s+i].y;
				    }
				    points[n-1].x = outline->points[start].x;
				    points[n-1].y = outline->points[start].y;

				    importGlyphPoints( points, n-1, callbacks, lineTo, curveTo, false );
			    }

			    start = end+1;
                val_ocall0( callbacks, endContour );
		    }

// printf("  2\n");
            val_ocall2( callbacks, endGlyph, alloc_int( character ), alloc_int( (*face)->glyph->advance.x ) );
// printf("  3\n");
        }
// printf("  E\n");
        character = FT_Get_Next_Char( *face, character, &glyph_index );
// printf("  F\n");
    }
    
// printf("  Goo\n");
    return val_true;
}