bool M_loadFont(const char * filename, void * data, void * arg) { MFont * font = (MFont *)data; int pen_x, pen_y, max_y; unsigned int n, max_code = 4096; unsigned int size = font->getFontSize(); unsigned int space = 2; unsigned int width = 1024; unsigned int height = 0; MImage image; FT_GlyphSlot slot; FT_Library library; FT_Face face; FT_Byte * file_base; FT_Long file_size; // init FT_Error error = FT_Init_FreeType(&library); if(error){ printf("ERROR Load Font : unable to init FreeType\n"); return false; } // open file MFile * file = M_fopen(filename, "rb"); if(! file) { FT_Done_FreeType(library); printf("ERROR Load Font : can't read file %s\n", filename); return false; } M_fseek(file, 0, SEEK_END); file_size = M_ftell(file); M_rewind(file); file_base = new FT_Byte[file_size]; if(file_size != M_fread(file_base, sizeof(FT_Byte), file_size, file)) { M_fclose(file); FT_Done_FreeType(library); delete [] file_base; return false; } // read font error = FT_New_Memory_Face(library, file_base, file_size, 0, &face); M_fclose(file); if(error) { printf("ERROR Load Font : unable to read data %s\n", filename); FT_Done_FreeType(library); delete [] file_base; return false; } // set font size error = FT_Set_Pixel_Sizes(face, 0, size); if(error) { printf("ERROR Load Font : unable to size font\n"); FT_Done_FreeType(library); delete [] file_base; return false; } // parse characters max_y = 0; slot = face->glyph; pen_x = space; pen_y = space; for(n = 0; n<max_code; n++) { // load glyph image into the slot (erase previous one) error = FT_Load_Char(face, n, FT_LOAD_RENDER | FT_LOAD_NO_HINTING); if(error) continue; if(FT_Get_Char_Index(face, n) == 0) continue; // max y max_y = MAX(max_y, slot->bitmap.rows); if((pen_x + slot->bitmap.width + space) > width) { pen_x = space; pen_y += max_y + space; height += max_y + space; max_y = 0; } // increment pen position pen_x += slot->bitmap.width + space; } if(height == 0) { printf("ERROR Load Font : unable to create font texture\n"); FT_Done_FreeType(library); delete [] file_base; return false; } // create image height = getNextPowerOfTwo(height); image.create(M_UBYTE, width, height, 4); memset(image.getData(), 0, image.getSize()*sizeof(char)); // init font font->setTextureWidth(width); font->setTextureHeight(height); // create font texture max_y = 0; slot = face->glyph; pen_x = space; pen_y = space; for(n = 0; n<max_code; n++) { // load glyph image into the slot (erase previous one) error = FT_Load_Char(face, n, FT_LOAD_RENDER | FT_LOAD_NO_HINTING); if(error) continue; if(FT_Get_Char_Index(face, n) == 0) continue; // max y max_y = MAX(max_y, slot->bitmap.rows); if((pen_x + slot->bitmap.width + space) > (int)image.getWidth()){ pen_x = space; pen_y += max_y + space; } // get character properties float xAdvance = (slot->advance.x >> 6) / ((float)size); MVector2 offset = MVector2((float)slot->bitmap_left - 1, - (float)slot->bitmap_top - 1) / ((float)size); MVector2 pos = MVector2((float)(pen_x-1) / (float)width, (float)(pen_y-1) / (float)height); MVector2 scale = MVector2((float)(slot->bitmap.width+2) / (float)width, (float)(slot->bitmap.rows+2) / (float)height); // set character font->setCharacter(n, MCharacter(xAdvance, offset, pos, scale)); // draw to image drawBitmap(&image, &slot->bitmap, pen_x, pen_y); // increment pen position pen_x += slot->bitmap.width + space; } // send texture MEngine * engine = MEngine().getInstance(); MRenderingContext * render = engine->getRenderingContext(); // gen texture id unsigned int textureId = font->getTextureId(); if(textureId == 0) { render->createTexture(&textureId); font->setTextureId(textureId); } // send texture image render->bindTexture(textureId); render->setTextureUWrapMode(M_WRAP_REPEAT); render->setTextureVWrapMode(M_WRAP_REPEAT); render->sendTextureImage(&image, 0, 1, 0); // finish FT_Done_FreeType(library); delete [] file_base; return true; }
bool M_loadBinFont(const char * filename, void * data) { // open file FILE * file = fopen(filename, "rb"); if(! file) { printf("Error : can't read file %s\n", filename); return false; } // bin char header[8]; fread(header, sizeof(char), 8, file); if(strcmp(header, "MFONT") != 0) return false; // version int version; fread(&version, sizeof(int), 1, file); // font size unsigned int fontSize; fread(&fontSize, sizeof(int), 1, file); // init font MFont * font = (MFont *)data; font->setFontSize(fontSize); // create image { unsigned int width, height; fread(&width, sizeof(int), 1, file); fread(&height, sizeof(int), 1, file); font->setTextureWidth(width); font->setTextureHeight(height); MImage image; image.create(M_UBYTE, width, height, 4); unsigned char color[4] = {255, 255, 255, 0}; unsigned int x, y; for(y=0; y<height; y++) { for(x=0; x<width; x++) { fread(&color[3], sizeof(char), 1, file); image.writePixel(x, y, color); } } MEngine * engine = MEngine().getInstance(); MRenderingContext * render = engine->getRenderingContext(); // gen texture id unsigned int textureId = font->getTextureId(); if(textureId == 0) { render->createTexture(&textureId); font->setTextureId(textureId); } // send texture image render->bindTexture(textureId); render->setTextureUWrapMode(M_WRAP_REPEAT); render->setTextureVWrapMode(M_WRAP_REPEAT); render->sendTextureImage(&image, 0, 1, 0); } // read characters infos { // size unsigned int size; fread(&size, sizeof(int), 1, file); // characters unsigned int i; for(i=0; i<size; i++) { unsigned int charCode; MVector2 pos; MVector2 offset; MVector2 scale; float xadvance; fread(&charCode, sizeof(int), 1, file); fread(&pos, sizeof(float), 2, file); fread(&offset, sizeof(float), 2, file); fread(&scale, sizeof(float), 2, file); fread(&xadvance, sizeof(float), 1, file); font->setCharacter(charCode, MCharacter(xadvance, offset, pos, scale)); } } fclose(file); return true; }