#include <ft2build.h>
#include <ctype.h>

#include FT_FREETYPE_H

FT_Library      library;
FT_Face         face;
FT_CharMap      charmap;

int				gray[255];
char			map[255];

/**
 * 取得某個灰階值對應的 char
 */
char mosaic( int x )
{
	char result;
	int i, min, diff;

	min = 255;

	for( i = 0; i < 255; i++) {
		if( isprint( i ) ) {
			diff = abs( x - gray[i] );
			if( diff < min ) {
				result = i;
				min = diff;
			}
		}
	}

	return result;
}

/**
 * 顯示出 bitmap
 *
 * reverse - 是否反著印
 */
void showfont( FT_Bitmap bitmap, int reverse )
{
	unsigned char *buf = bitmap.buffer;
	int rows = bitmap.rows;
	int width = bitmap.width;
	int r, w;

	if(reverse == 0) {
		for (r = 0; r < rows; r++) {
			for (w = 0; w < width; w++) {
				printf("%c", mosaic(*(buf + r * width + w)));
			}
			printf("\n");
		}
	} else {
		for (r = rows - 1; r >= 0; r--) {
			for (w = width - 1; w >= 0; w--) {
				printf("%c", mosaic(*(buf + r * width + w)));
			}
			printf("\n");
		}
	}
}

/**
 * 傳回 buf 中第一個 utf-8 char 的 index
 */
int utf8CharsToCharcode( char* buf )
{
	int c;
	int limit;

	for( limit = 0; buf[limit] != '\0' && buf[limit] != '\n'; limit++ );

	if( limit == 1 ) {
		c = buf[0];
	} else if( limit == 2 ) {
		c = buf[0] & 0x1f;
		c <<= 6;
		c |= buf[1] & 0x3f;
	} else if( limit == 3 ) {
		c = buf[0] & 0xf;
		c <<= 6;
		c |= buf[1] & 0x3f;
		c <<= 6;
		c |= buf[2] & 0x3f;
	} else {
		c = buf[0] & 0x7;
		c <<= 6;
		c |= buf[1] & 0x3f;
		c <<= 6;
		c |= buf[2] & 0x3f;
		c <<= 6;
		c |= buf[3] & 0x3f;
	}

	return c;
}

/**
 * 從 utf-8 index 取得 bitmap
 */
FT_Bitmap get_bitmap( int c )
{
	FT_UInt glyph_index;
	FT_Bitmap bitmap;
	int errno;

	glyph_index = FT_Get_Char_Index( face, c );

#ifdef DEBUG
	printf("char = %c\n", c);
	printf("glyph_index = %d\n", glyph_index);
#endif

	if(glyph_index == 0) {
		printf("Get char index error!\n");
	}

	errno = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
	if ( errno ) {
		printf("FT_Load_Glyph error!\n");
	}

	errno = FT_Render_Glyph(face->glyph, ft_render_mode_normal);
	if (errno) {
		printf("FT_Render_Glyph error!\n");
	}

	bitmap = face->glyph->bitmap;

#ifdef DEBUG
	printf("rows: %d, width: %d, pitch: %d\n", bitmap.rows, bitmap.width, bitmap.pitch);
#endif

	return bitmap;
}

/**
 * 記算每個 printable ASCII 的灰階值
 */
int gray_value( int c )
{
	int r, w, count = 0;
	FT_Bitmap bitmap;

	bitmap = get_bitmap( c );

	for (r = 0; r < bitmap.rows; r++) {
		for (w = 0; w < bitmap.width; w++) {
			if( *(bitmap.buffer + r * bitmap.width + w) > 32 ) {
				count++;
			}
		}
	}

	return count;
}

/**
 * 建構從灰階查 ASCII 的表
 */
void build_gray_table()
{
	int i, max;

	max = 0;
	for( i = 0; i < 255; i++ ) {
		if( isprint( i ) ) {
			gray[i] = gray_value( i );
		} else {
			gray[i] = 0;
		}

		if( gray[i] > max )
			max = gray[i];
	}

	for( i = 0; i < 255; i++ ) {
		gray[i] = 255 * gray[i] / max;
	}

#ifdef DEBUG
	for( i = 0; i < 255; i++) {
		if( isprint( i ) )
			printf("%c %d\n", i, gray[i] );
	}
#endif

}

/**
 * 初始化 freetype
 */
void init()
{
	int errno;
	int fontrows = 24, fontwidth = 40;

	errno = FT_Init_FreeType(&library);
	if (errno) {
		printf("FT_Init_FreeType error!\n");
	}

	errno = FT_New_Face(library, "/home/zhouer/.fonts/mingliu.ttc", 0, &face);

	if (errno == FT_Err_Unknown_File_Format) {
		printf("FT_New_Face FT_Err_Unknown_File_Format error!\n");
	} else if (errno) {
		printf("FT_New_Face others error!\n");
	}

#ifdef DEBUG
	printf("face->num_charmaps = %d\n", face->num_charmaps);

	printf("support:\n");
	for ( n = 0; n < face->num_charmaps; n++ )
	{
		printf("platform_id: %u, encoding_id: %u\n", charmap->platform_id, charmap->encoding_id);
	}
#endif

	errno = FT_Select_Charmap( face, ft_encoding_unicode );
	if (errno) {
		printf("FT_Select_Charmap error!\n");
	}

#ifdef DEBUG
	printf("selected charmap: platform_id: %u, encoding_id: %u\n", face->charmap->platform_id, face->charmap->encoding_id);
#endif

	errno = FT_Set_Pixel_Sizes(face, fontwidth, fontrows);
	if (errno) {
		printf("FT_Set_Pixel_Sizes error!\n");
	}

}

int main()
{
	char buf[256];
	int index;

	init();
	build_gray_table();

	fgets( buf, 256, stdin );
	index = utf8CharsToCharcode( buf );
	showfont( get_bitmap(index), 0 );

	return 0;
}

