diff --git a/components/rtgui/common/font_freetype.c b/components/rtgui/common/font_freetype.c new file mode 100644 index 0000000000..906e986227 --- /dev/null +++ b/components/rtgui/common/font_freetype.c @@ -0,0 +1,201 @@ +#include +#include +#include +#include + +#include +#include +#include + +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); +}