#include #include #include #include #include #include FT_FREETYPE_H #include FT_GLYPH_H #include typedef struct { int l; int t; int r; int b; }rect_t; typedef struct { FT_Face face; int height; int base; FT_Glyph glyph[256]; }font_t; static FT_Face def_face; typedef unsigned int color_t; unsigned int ansi2utf32(unsigned char ch); font_t *create_font(FT_Face face, int size); void my_draw_bitmap(bitmap_t *win, FT_Bitmap *bitmap, int dstx, int dsty, int col) { uint8_t *dst; uint8_t *src, *tmpsrc; uint32_t *tmpdst; int i, j; dst = win->data + dsty * win->pitch + dstx*4; src = bitmap->buffer; // printf("buffer %x width %d rows %d\n", // bitmap->buffer, bitmap->width, bitmap->rows); for( i = 0; i < bitmap->rows; i++ ) { tmpdst = (uint32_t*)dst; tmpsrc = src; dst+= win->pitch; src+= bitmap->pitch; for( j = 0; j < bitmap->width; j++) { int a = *tmpsrc++; int sr, sg, sb; int dr, dg, db; if( a != 0) a++; db = *tmpdst & 0xFF; dg = (*tmpdst >> 8) & 0xFF; dr = (*tmpdst >> 16) & 0xFF; sb = col & 0xFF; sg = (col >> 8) & 0xFF; sr = (col >> 16) &0xFF; db = (a*sb + db*(256-a))/256; dg = (a*sg + dg*(256-a))/256; dr = (a*sr + dr*(256-a))/256; *tmpdst++ = 0xFF000000|(dr<<16)|(dg<<8)|db; }; } }; int draw_text_ext(bitmap_t *winbitmap, font_t *font, char *text, int len, rect_t *rc, int color) { FT_UInt glyph_index; FT_Bool use_kerning = 0; FT_BitmapGlyph glyph; FT_UInt previous; int x, y, w; int col, ncol; unsigned char ch; int err = 0; use_kerning = FT_HAS_KERNING( font->face ); previous = 0; col = 0; x = rc->l << 6; y = rc->b; w = (rc->r - rc->l) << 6; while( len-- ) { ch = *text++; if(ch == '\n' || ch == '\r') continue; if(ch == '\t') { ncol = (col+4) & ~3; if( col < ncol) { glyph_index = FT_Get_Char_Index( font->face, ansi2utf32(' ') ); while( col < ncol) { if ( use_kerning && previous && glyph_index ) { FT_Vector delta; FT_Get_Kerning( font->face, previous, glyph_index, FT_KERNING_DEFAULT, &delta ); x += delta.x ; } if( x + (font->glyph[ch]->advance.x >> 10) > w) break; x += font->glyph[ch]->advance.x >> 10; previous = glyph_index; col ++; }; }; continue; }; glyph_index = FT_Get_Char_Index( font->face, ansi2utf32(ch) ); if ( use_kerning && previous && glyph_index ) { FT_Vector delta; FT_Get_Kerning( font->face, previous, glyph_index, FT_KERNING_DEFAULT, &delta ); x += delta.x ; } if( x + (font->glyph[ch]->advance.x >> 10) > w) break; glyph = (FT_BitmapGlyph)font->glyph[ch]; my_draw_bitmap(winbitmap, &glyph->bitmap, (x >> 6) + glyph->left, y - glyph->top, color); x += font->glyph[ch]->advance.x >> 10; previous = glyph_index; }; return err; }; int init_fontlib() { static FT_Library library; FT_Face face = NULL; int err; err = FT_Init_FreeType( &library ); if ( err ) { printf("an error occurred during FreeType initialization\n"); goto done; } // err = FT_New_Face( library, "/kolibrios/Fonts/IstokWeb.ttf", 0, &face ); // err = FT_New_Face( library, "/kolibrios/Fonts/lucon.ttf", 0, &face ); err = FT_New_Face( library, "/kolibrios/Fonts/DroidSansMono.ttf", 0, &face ); if ( err == FT_Err_Unknown_File_Format ) { printf("font format is unsupported\n"); goto done; } else if ( err ) { printf("font file could not be read or broken\n"); goto done; } def_face = face; done: return err; }; unsigned int ansi2utf32(unsigned char ch) { if(ch < 0x80) return ch; if(ch < 0xB0) return 0x410-0x80 + ch; if(ch < 0xE0) return 0; if(ch < 0xF0) return 0x440-0xE0 + ch; if(ch == 0xF0) return 0x401; else if(ch==0xF1) return 0x451; else return 0; } font_t *create_font(FT_Face xface, int size) { font_t *font; int i, err; font = malloc(sizeof(*font)); if(font == NULL) return font; memset(font, 0, sizeof(*font)); font->face = (xface == NULL) ? def_face : xface; font->height = size+1; err = FT_Set_Pixel_Sizes( font->face, 0, size ); for(i = 0; i < 256; i++) { FT_UInt glyph_index; FT_BitmapGlyph glyph_bitmap; glyph_index = FT_Get_Char_Index( font->face, ansi2utf32(i) ); err = FT_Load_Glyph( font->face, glyph_index, FT_LOAD_DEFAULT ); if ( err ) { font->glyph[i] = font->glyph[0] ; continue; }; err = FT_Get_Glyph( font->face->glyph, &font->glyph[i] ); if (err) { font->glyph[i] = font->glyph[0] ; continue; }; if ( font->glyph[i]->format != FT_GLYPH_FORMAT_BITMAP ) { err = FT_Glyph_To_Bitmap( &font->glyph[i], FT_RENDER_MODE_NORMAL, 0, 1 ); if ( err ) continue; glyph_bitmap = (FT_BitmapGlyph)font->glyph[i]; if(glyph_bitmap->top > font->base) font->base = glyph_bitmap->top; } } return font; }