예제 #1
0
void text_renderer_font_destroy(text_renderer_p renderer, int32_t font_handle) {
	text_renderer_font_p font = hash_get_ptr(renderer->fonts, font_handle);
	if (!font)
		return;
	
	// TODO: mark all cells of this font as free
	
	FT_Done_Face(font->face);
	hash_destroy(font->cell_refs);
	hash_remove(renderer->fonts, font_handle);
}
예제 #2
0
파일: wpa_ctrl.c 프로젝트: iasoon/netman
/* TODO: eww. */
void
wpa_connect_to_network(STATE *state, char *interface, KEYVALUE *options)
{
	WPA_INTERFACE iface;
	WPA_NETWORK *net;
	wpa_interface_init(&iface, interface);
	net = hash_get_ptr(iface.networks, get_element("ssid", options).str);
	if (net == 0) {
		net = wpa_add_network(&iface, options);
	} else {
		/* TODO: merge options instead of overwriting? */
		net->options = options;
		wpa_configure_network(&iface, net);
	}
	if (net != iface.current_network){
		wpa_enable_network(&iface, net);
		wpa_handle_messages(state, &iface);
	}
	wpa_interface_disconnect(&iface);
}
예제 #3
0
void text_renderer_prepare(text_renderer_p renderer, int32_t font_handle, uint32_t range_start, uint32_t range_end) {
	text_renderer_font_p font = hash_get_ptr(renderer->fonts, font_handle);
	if (!font)
		return;
	
	glBindTexture(GL_TEXTURE_RECTANGLE, renderer->texture);
	
	// Lookup the size of our texture (needed by find_free_cell_or_revoke_unused_cell() for some checks)
	GLint texture_width = 0, texture_height = 0;
	glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE, 0, GL_TEXTURE_WIDTH, &texture_width);
	glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE, 0, GL_TEXTURE_HEIGHT, &texture_height);
	
	GLint unpack_alignment = 0;
	glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	
	for(uint32_t code_point = range_start; code_point <= range_end; code_point++) {
		// Handle line break.
		if (code_point == '\n') {
			continue;
		}
		
		// Look if this glyph is present in the texture. If so this font has a cell reference
		// for this code point.
		text_renderer_cell_ref_p cell_ref = hash_get_ptr(font->cell_refs, code_point);
		
		// Glyph not rendered yet, try to render it
		if (!cell_ref) {
			uint32_t glyph_index = FT_Get_Char_Index(font->face, code_point);
			if (glyph_index == 0)
				continue;
			
			FT_Error error = FT_Load_Glyph(font->face, glyph_index, FT_LOAD_RENDER);
			if (error)
				continue;
			
			// Look for a free cell to store the rendered glyph
			uint32_t gw = font->face->glyph->bitmap.width, gh = font->face->glyph->bitmap.rows;
			size_t line_idx = 0, cell_idx = 0;
			text_renderer_cell_p free_cell = find_free_cell_or_revoke_unused_cell(renderer, font, gw, gh, texture_width, texture_height, &line_idx, &cell_idx);
			
			if (free_cell == NULL)
				continue;
			
			free_cell->glyph_index    = glyph_index;
			free_cell->hori_bearing_x = font->face->glyph->metrics.horiBearingX / 64;
			free_cell->hori_bearing_y = font->face->glyph->metrics.horiBearingY / 64;
			free_cell->hori_advance   = font->face->glyph->metrics.horiAdvance  / 64;
			
			/*
			printf("%3u %c: %2ux%2u %3u bytes, pitch %2u, pos %3u/%3u hori_bearing: %2d/%2d, adv: %2d\n",
				code_point, code_point, gw, gh, gw*gh, font->face->glyph->bitmap.pitch,
				free_cell->x, free_cell->y, free_cell->hori_bearing_x, free_cell->hori_bearing_y, free_cell->hori_advance);
			*/
			
			glPixelStorei(GL_UNPACK_ROW_LENGTH, font->face->glyph->bitmap.pitch);
			glTexSubImage2D(GL_TEXTURE_RECTANGLE, 0, free_cell->x, free_cell->y, gw, gh, GL_RED, GL_UNSIGNED_BYTE, font->face->glyph->bitmap.buffer);
			
			cell_ref = hash_put_ptr(font->cell_refs, code_point);
			cell_ref->line_idx = line_idx;
			cell_ref->cell_idx = cell_idx;
		}
	}
	
	glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment);
	glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
	glBindTexture(GL_TEXTURE_RECTANGLE, 0);
}
예제 #4
0
size_t text_renderer_render(text_renderer_p renderer, int32_t font_handle, char* text, size_t x, size_t y, float* buffer_ptr, size_t buffer_size) {
	text_renderer_font_p font = hash_get_ptr(renderer->fonts, font_handle);
	if (!font)
		return 0;
	
	// The current position is the baseline of the text so start one line down
	// from the position. Otherwise we would render above it.
	size_t pos_x = x, pos_y = y + (font->face->size->metrics.height / 64);
	float* p = buffer_ptr;
	FT_UInt glyph_index = 0, prev_glyph_index = 0;
	
	glBindTexture(GL_TEXTURE_RECTANGLE, renderer->texture);
	
	// Lookup the size of our texture (needed by find_free_cell_or_revoke_unused_cell() for some checks)
	GLint texture_width = 0, texture_height = 0;
	glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE, 0, GL_TEXTURE_WIDTH, &texture_width);
	glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE, 0, GL_TEXTURE_HEIGHT, &texture_height);
	
	GLint unpack_alignment = 0;
	glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	
	for(utf8_iterator_t it = utf8_first(text); it.code_point != 0; it = utf8_next(it)) {
		// Handle line break.
		if (it.code_point == '\n') {
			pos_y += font->face->size->metrics.height / 64;
			pos_x = x;
			
			// Don't do kerning at the next character after the line break.
			prev_glyph_index = 0;
			
			continue;
		}
		
		// Look if this glyph is present in the texture. If so this font has a cell reference
		// for this code point.
		text_renderer_cell_ref_p cell_ref = hash_get_ptr(font->cell_refs, it.code_point);
		
		// Glyph not rendered yet, try to render it
		if (!cell_ref) {
			glyph_index = FT_Get_Char_Index(font->face, it.code_point);
			if (glyph_index == 0)
				goto render_error_glyph;
			
			FT_Error error = FT_Load_Glyph(font->face, glyph_index, FT_LOAD_RENDER);
			if (error)
				goto render_error_glyph;
			
			// Look for a free cell to store the rendered glyph
			uint32_t gw = font->face->glyph->bitmap.width, gh = font->face->glyph->bitmap.rows;
			size_t line_idx = 0, cell_idx = 0;
			text_renderer_cell_p free_cell = find_free_cell_or_revoke_unused_cell(renderer, font, gw, gh, texture_width, texture_height, &line_idx, &cell_idx);
			
			if (free_cell == NULL)
				goto render_error_glyph;
			
			free_cell->glyph_index    = glyph_index;
			free_cell->hori_bearing_x = font->face->glyph->metrics.horiBearingX / 64;
			free_cell->hori_bearing_y = font->face->glyph->metrics.horiBearingY / 64;
			free_cell->hori_advance   = font->face->glyph->metrics.horiAdvance  / 64;
			
			/*
			printf("%c: %2ux%2u %2u bytes, pitch %u, x: %u, y: %u hori_bearing: %2u/%2u, adv: %2u\n",
				it.code_point, gw, gh, gw*gh, font->face->glyph->bitmap.pitch,
				free_cell->x, free_cell->y, free_cell->hori_bearing_x, free_cell->hori_bearing_y, free_cell->hori_advance);
			*/

			glPixelStorei(GL_UNPACK_ROW_LENGTH, font->face->glyph->bitmap.pitch);
			glTexSubImage2D(GL_TEXTURE_RECTANGLE, 0, free_cell->x, free_cell->y, gw, gh, GL_RED, GL_UNSIGNED_BYTE, font->face->glyph->bitmap.buffer);
			
			cell_ref = hash_put_ptr(font->cell_refs, it.code_point);
			cell_ref->line_idx = line_idx;
			cell_ref->cell_idx = cell_idx;
		}
		
		// Glyph rendered successfully, do kerning and generate vertices for it
		text_renderer_line_t line = array_elem(renderer->lines, text_renderer_line_t, cell_ref->line_idx);
		text_renderer_cell_t cell = array_elem(line.cells, text_renderer_cell_t, cell_ref->cell_idx);
		
		if (cell.glyph_index && prev_glyph_index) {
			FT_Vector delta;
			FT_Get_Kerning(font->face, prev_glyph_index, glyph_index, FT_KERNING_DEFAULT, &delta);
			pos_x += delta.x / 64;
		}
		
		// We have the texture coordinates of the glyph, generate the vertex buffer
		if ( (p + 6*4 - buffer_ptr) * sizeof(float) < buffer_size ) {
			float w = cell.width, h = line.height;
			
			float cx = pos_x + cell.hori_bearing_x;
			float cy = pos_y - cell.hori_bearing_y;
			
			float tl_x = cx + 0, tl_y = cy + 0,  tl_u = cell.x,     tl_v = cell.y;
			float tr_x = cx + w, tr_y = cy + 0,  tr_u = cell.x + w, tr_v = cell.y;
			float bl_x = cx + 0, bl_y = cy + h,  bl_u = cell.x,     bl_v = cell.y + h;
			float br_x = cx + w, br_y = cy + h,  br_u = cell.x + w, br_v = cell.y + h;
			
			*(p++) = tl_x; *(p++) = tl_y; *(p++) = tl_u; *(p++) = tl_v;
			*(p++) = tr_x; *(p++) = tr_y; *(p++) = tr_u; *(p++) = tr_v;
			*(p++) = bl_x; *(p++) = bl_y; *(p++) = bl_u; *(p++) = bl_v;
			*(p++) = tr_x; *(p++) = tr_y; *(p++) = tr_u; *(p++) = tr_v;
			*(p++) = br_x; *(p++) = br_y; *(p++) = br_u; *(p++) = br_v;
			*(p++) = bl_x; *(p++) = bl_y; *(p++) = bl_u; *(p++) = bl_v;
			
			pos_x += cell.hori_advance;
		}
		
		prev_glyph_index = glyph_index;
		continue;
		
		render_error_glyph:
			// For now just output nothing when we fail to render a glyph.
			// TODO: Figure out how to render a kind of error glyph.
			prev_glyph_index = glyph_index;
			continue;
	}
	
	glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment);
	glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
	glBindTexture(GL_TEXTURE_RECTANGLE, 0);
	
	return (p - buffer_ptr) * sizeof(float);
}