Browse Source

add TTF font support.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@758 bbd45198-f89e-11dd-88c7-29a3b14d5316
bernard.xiong 15 years ago
parent
commit
490767223e
1 changed files with 201 additions and 0 deletions
  1. 201 0
      components/rtgui/common/font_freetype.c

+ 201 - 0
components/rtgui/common/font_freetype.c

@@ -0,0 +1,201 @@
+#include <rtgui/dc.h>
+#include <rtgui/font.h>
+#include <rtgui/tree.h>
+#include <rtgui/rtgui_system.h>
+
+#include <ft2build.h>
+#include <freetype/freetype.h>
+#include <freetype/ftglyph.h>
+
+static void rtgui_freetype_font_draw_text(struct rtgui_font* font, struct rtgui_dc* dc, const char* text, rt_ubase_t len, struct rtgui_rect* rect);
+static void rtgui_freetype_font_get_metrics(struct rtgui_font* font, const char* text, rtgui_rect_t* rect);
+
+struct rtgui_font_engine freetype_font_engine =
+{
+	RT_NULL,
+	RT_NULL,
+	rtgui_freetype_font_draw_text,
+	rtgui_freetype_font_get_metrics
+};
+
+struct rtgui_freetype_font
+{
+	int bold;
+	int italic;
+
+	FT_Face     face;
+	FT_Library  library;
+};
+
+static rt_uint16_t *LATIN1_to_UNICODE(rt_uint16_t *unicode, const char *text, int len)
+{
+	int i;
+
+	for ( i=0; i < len; ++i ) {
+		unicode[i] = ((const unsigned char *)text)[i];
+	}
+	unicode[i] = 0;
+
+	return unicode;
+}
+
+static void rtgui_freetype_font_draw_text(struct rtgui_font* font, struct rtgui_dc* dc, const char* text, rt_ubase_t len, struct rtgui_rect* rect)
+{
+	int index = 0;
+	FT_Error err = 0;
+	rt_uint16_t text_short[32], *text_ptr;
+	struct rtgui_freetype_font* freetype;
+
+	RT_ASSERT(font != RT_NULL);
+	freetype = (struct rtgui_freetype_font*) font->data;
+	RT_ASSERT(freetype != RT_NULL);
+
+	LATIN1_to_UNICODE(text_short, text, len);
+	text_ptr = &text_short[0];
+
+	while (*text_ptr)
+	{
+		index = FT_Get_Char_Index(freetype->face, *text_ptr);
+		err = FT_Load_Glyph(freetype->face, index, FT_LOAD_DEFAULT|FT_LOAD_RENDER);
+		if (err == 0)
+		{
+			int rows, x;
+			rt_uint8_t* ptr;
+
+			/* render font */
+			ptr = (rt_uint8_t*)freetype->face->glyph->bitmap.buffer;
+			
+			for (rows = 0; rows < freetype->face->glyph->bitmap.rows; rows ++)
+				for (x = 0; x < freetype->face->glyph->bitmap.width; x++)
+				{
+					if (*ptr > 0)
+						rtgui_dc_draw_color_point(dc, rect->x1 + x, rect->y1 + rows, RTGUI_RGB(0xff - *ptr, 0xff - *ptr, 0xff - *ptr));
+						// rtgui_dc_draw_point(dc, rect->x1 + x, rect->y1 + rows);
+					
+					ptr ++;
+				}
+		}
+
+		text_ptr ++;
+		rect->x1 += freetype->face->glyph->bitmap.width;
+	}
+}
+
+static void rtgui_freetype_font_get_metrics(struct rtgui_font* font, const char* text, rtgui_rect_t* rect)
+{
+	int index = 0;
+	FT_Error err = 0;
+	rt_uint16_t w = 0, h = 0;
+	const rt_uint16_t *text_short;
+	struct rtgui_freetype_font* freetype;
+	
+	RT_ASSERT(font != RT_NULL);
+	freetype = (struct rtgui_freetype_font*) font->data;
+	RT_ASSERT(freetype != RT_NULL);
+
+	text_short = (const rt_uint16_t*) text;
+	while (*text_short)
+	{
+		index = FT_Get_Char_Index(freetype->face, *text_short);
+		err = FT_Load_Glyph(freetype->face, index, FT_LOAD_DEFAULT);
+
+		if (err == 0)
+		{
+			w += freetype->face->glyph->bitmap.width;
+			if (freetype->face->glyph->bitmap.rows > h)
+			{
+				h = freetype->face->glyph->bitmap.rows;
+			}
+		}
+
+		text_short ++;
+	}
+
+	rect->x1 = 0; rect->y1 = 0;
+	rect->x2 = w; rect->y2 = h;
+}
+
+rtgui_font_t* rtgui_freetype_font_create(const char* filename, int bold, int italic, rt_size_t size)
+{
+	FT_Error err = 0;
+	struct rtgui_font* font;
+
+	font = (struct rtgui_font*) rtgui_malloc (sizeof(struct rtgui_font));
+	if (font != RT_NULL)
+	{
+		struct rtgui_freetype_font* freetype;
+
+		freetype = (struct rtgui_freetype_font*) rtgui_malloc (sizeof(struct rtgui_freetype_font));
+		if (freetype == RT_NULL)
+		{
+			rt_free(font);
+			font = RT_NULL;
+		}
+		else
+		{
+			err = FT_Init_FreeType(&freetype->library);
+			if((err = FT_New_Face(freetype->library, filename, 0, &freetype->face)))
+			{
+				FT_Done_FreeType(freetype->library);
+
+				rt_free(font);
+				font = RT_NULL;
+			}
+			else
+			{
+				err = FT_Select_Charmap(freetype->face, ft_encoding_unicode);
+				if(err)
+				{
+					err = FT_Select_Charmap(freetype->face, ft_encoding_latin_1 );
+				}
+
+				err = FT_Set_Pixel_Sizes(freetype->face, 0, size);
+				if (err != 0)
+				{
+					rtgui_free(font);
+					font = RT_NULL;
+
+					FT_Done_FreeType(freetype->library);
+					rtgui_free(freetype);
+
+					return RT_NULL;
+				}
+
+				freetype->bold = bold;
+				freetype->italic = italic;
+
+				rt_kprintf("fonfile:%s\n", filename);
+				rt_kprintf("font family_name:%s\n", freetype->face->family_name);
+				rt_kprintf("font style_name:%s\n", freetype->face->style_name);
+
+				/* set user data */
+				font->data = freetype;
+				font->family = rt_strdup(freetype->face->family_name);
+				font->height = (rt_uint16_t)size;
+				font->refer_count = 0;
+				font->engine = &freetype_font_engine;
+
+				/* add to system */
+				rtgui_font_system_add_font(font);
+			}
+		}
+	}
+
+	return font;
+}
+
+void rtgui_freetype_font_destroy(rtgui_font_t* font)
+{
+	struct rtgui_freetype_font* freetype;
+	
+	RT_ASSERT(font != RT_NULL);
+	freetype = (struct rtgui_freetype_font*) font->data;
+	RT_ASSERT(freetype != RT_NULL);
+
+	rtgui_font_system_remove_font(font);
+
+	FT_Done_Face    (freetype->face);
+	FT_Done_FreeType(freetype->library);
+	rtgui_free(freetype);
+	rtgui_free(font);
+}