|
@@ -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);
|
|
|
+}
|