void GlFont::InitialiseFont(const unsigned char* ttf_buffer, float pixel_height, int tex_w, int tex_h) { font_height_px = pixel_height; this->tex_w = tex_w; this->tex_h = tex_h; font_bitmap = new unsigned char[tex_w*tex_h]; const int offset = 0; stbtt_fontinfo f; if (!stbtt_InitFont(&f, ttf_buffer, offset)) { throw std::runtime_error("Unable to initialise font"); } float scale = stbtt_ScaleForPixelHeight(&f, pixel_height); STBTT_memset(font_bitmap, 0, tex_w*tex_h); int x = 1; int y = 1; int bottom_y = 1; // Generate bitmap and char indices for (int i=0; i < NUM_CHARS; ++i) { int advance, lsb, x0,y0,x1,y1,gw,gh; int g = stbtt_FindGlyphIndex(&f, FIRST_CHAR + i); stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); gw = x1-x0; gh = y1-y0; if (x + gw + 1 >= tex_w) y = bottom_y, x = 1; // advance to next row if (y + gh + 1 >= tex_h) // check if it fits vertically AFTER potentially moving to next row throw std::runtime_error("Unable to initialise font"); STBTT_assert(x+gw < tex_w); STBTT_assert(y+gh < tex_h); stbtt_MakeGlyphBitmap(&f, font_bitmap+x+y*tex_w, gw,gh,tex_w, scale,scale, g); // Adjust offset for edges of pixels chardata[i] = GlChar(tex_w,tex_h, x, y, gw, gh, scale*advance, x0 -0.5, -y0 -0.5); x = x + gw + 1; if (y+gh+1 > bottom_y) bottom_y = y+gh+1; } // Generate kern table for (int i=0; i < NUM_CHARS; ++i) { for (int j=0; j < NUM_CHARS; ++j) { kern_table[i*NUM_CHARS+j] = scale * stbtt_GetCodepointKernAdvance(&f,i,j); } } }
bool GlFont::LoadFontFromText(char* xml_text) { rapidxml::xml_document<> doc; doc.parse<0>(xml_text); rapidxml::xml_node<>* node_font = doc.first_node("font"); if(node_font) { rapidxml::xml_node<>* node_info = node_font->first_node("info"); rapidxml::xml_node<>* node_common = node_font->first_node("common"); rapidxml::xml_node<>* node_pages = node_font->first_node("pages"); rapidxml::xml_node<>* node_chars = node_font->first_node("chars"); rapidxml::xml_node<>* node_kerns = node_font->first_node("kernings"); if(node_info && node_common && node_chars) { sName = node_info->first_attribute_value<std::string>("face"); sCharset = node_info->first_attribute_value<std::string>("charset"); nSize = node_info->first_attribute_value<int>("size"); nStretchHeight = node_info->first_attribute_value<int>("stretchH"); nOutline = node_info->first_attribute_value<int>("outline"); bBold = node_info->first_attribute_value<bool>("bold"); bItalic = node_info->first_attribute_value<bool>("italic"); bUnicode = node_info->first_attribute_value<bool>("unicode"); bSmooth = node_info->first_attribute_value<bool>("smooth"); bAntiAliasing = node_info->first_attribute_value<bool>("aa"); nBase = node_common->first_attribute_value<int>("base"); nScaleWidth = node_common->first_attribute_value<int>("scaleW"); nScaleHeight = node_common->first_attribute_value<int>("scaleH"); nLineHeight = node_common->first_attribute_value<int>("lineHeight"); nPages = node_common->first_attribute_value<int>("pages"); if(node_pages) { for( rapidxml::xml_node<>* xml_page = node_pages->first_node(); xml_page; xml_page = xml_page->next_sibling() ) { const std::string filename = xml_page->first_attribute_value<std::string>( "file" ); LoadGlImage(mTex, filename, false ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); } }else{ mTex.Reinitialise(nScaleWidth, nScaleHeight, GL_ALPHA,false,0,GL_ALPHA,GL_UNSIGNED_BYTE,font_image_data ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); } if( nPages < 1) { std::cerr << "Incorrect number of font pages loaded." << std::endl; } for( rapidxml::xml_node<>* xml_char = node_chars->first_node(); xml_char; xml_char = xml_char->next_sibling() ) { char id = xml_char->first_attribute_value<int>("id"); int x = xml_char->first_attribute_value<int>("x"); int y = xml_char->first_attribute_value<int>("y"); int width = xml_char->first_attribute_value<int>("width"); int height = xml_char->first_attribute_value<int>("height"); int xOffset = xml_char->first_attribute_value<int>("xoffset"); int yOffset = xml_char->first_attribute_value<int>("yoffset"); int xAdvance = xml_char->first_attribute_value<int>("xadvance"); int page = xml_char->first_attribute_value<int>("page"); if(page != 0) { std::cerr << "Multi-page font not supported" << std::endl; page = 0; } mmCharacters[id] = GlChar(nScaleWidth, nScaleHeight, x,y,width, height,xAdvance, xOffset,nBase - yOffset); } if(node_kerns) { for( rapidxml::xml_node<>* xml_kern = node_kerns->first_node(); xml_kern; xml_kern = xml_kern->next_sibling() ) { char first = xml_kern->first_attribute_value<char>("first"); char second = xml_kern->first_attribute_value<char>("second"); int amount = xml_kern->first_attribute_value<int>("amount"); mmCharacters[second].SetKern(first,amount); } } } } return false; }