Font::Font(const res::path & fontFile, unsigned int fontSize, FT_Face face) : info(fontFile, fontSize) , referenceCount(0) , face(face) , textures(0) { // TODO-font: Compute optimal size using m_FTFace->bbox const unsigned int TEXTURE_SIZE = 512; // Insert all the glyphs into texture pages textures = new PackedTexture(TEXTURE_SIZE, Image::Format_A8); // Insert the replacement characters first as they may be needed if others are missing insertGlyph('?'); insertGlyph(util::REPLACEMENT_CHAR); // Pre-load glyphs for displayable ASCII characters for(Char chr = 32; chr < FONT_PRELOAD_LIMIT; ++chr) { if(chr != '?') { insertGlyph(chr); } } textures->upload(); }
Font::Font(const res::path & file, unsigned size, unsigned weight, FT_Face face) : m_info(file, size, weight) , m_referenceCount(0) , m_size(NULL) , m_textures(NULL) { FT_New_Size(face, &m_size); FT_Activate_Size(m_size); // Windows default is 96dpi // FreeType default is 72dpi FT_Set_Char_Size(m_size->face, 0, m_info.size * 64, 64, 64); // TODO Compute optimal size using m_FTFace->bbox const unsigned int TEXTURE_SIZE = 512; // Insert all the glyphs into texture pages m_textures = new PackedTexture(TEXTURE_SIZE, Image::Format_A8); // Insert the replacement characters first as they may be needed if others are missing insertGlyph('?'); insertGlyph(util::REPLACEMENT_CHAR); // Pre-load glyphs for displayable ASCII characters for(Char chr = 32; chr < FONT_PRELOAD_LIMIT; ++chr) { if(chr != '?') { insertGlyph(chr); } } m_textures->upload(); }
Font::glyph_iterator Font::getNextGlyph(text_iterator & it, text_iterator end) { Char chr = util::UTF8::read(it, end); if(chr == util::INVALID_CHAR) { return glyphs.end(); } glyph_iterator glyph = glyphs.find(chr); if(glyph != glyphs.end()) { return glyph; // an existing glyph } if(chr < FONT_PRELOAD_LIMIT) { // We pre-load all glyphs for ASCII characters, so there is no point in checking again return glyphs.end(); } if(!insertGlyph(chr)) { // No new glyph was inserted but the character was mapped to an existing one return glyphs.find(chr); } arx_assert(glyphs.find(chr) != glyphs.end()); // As we need to re-upload the textures now, first check for more missing glyphs insertMissingGlyphs(it, end); // Re-upload the changed textures textures->upload(); return glyphs.find(chr); // the newly inserted glyph }
/** Update the supported characters for this font if required. */ void FontWithFace::updateCharactersList() { if (m_fallback_font != NULL) m_fallback_font->updateCharactersList(); if (m_new_char_holder.empty()) return; for (const wchar_t& c : m_new_char_holder) { const GlyphInfo& gi = getGlyphInfo(c); insertGlyph(c, gi); } m_new_char_holder.clear(); } // updateCharactersList
bool Font::insertMissingGlyphs(text_iterator begin, text_iterator end) { Char chr; bool changed = false; for(text_iterator it = begin; (chr = util::UTF8::read(it, end)) != util::INVALID_CHAR; ) { if(glyphs.find(chr) == glyphs.end()) { if(chr >= FONT_PRELOAD_LIMIT && insertGlyph(chr)) { changed = true; } } } return changed; }
// ---------------------------------------------------------------------------- void FontWithFace::updateCharactersList() { if (m_fallback_font != NULL) m_fallback_font->updateCharactersList(); if (m_new_char_holder.empty()) return; for (const wchar_t& c : m_new_char_holder) { const GlyphInfo& gi = getGlyphInfo(c); insertGlyph(c, gi); } m_new_char_holder.clear(); // Update last glyph page video::ITexture* page_texture = irr_driver->getVideoDriver() ->addTexture("Glyph_page", m_page); m_spritebank->setTexture(m_spritebank->getTextureCount() - 1, page_texture); irr_driver->getVideoDriver()->removeTexture(page_texture); assert(page_texture->getReferenceCount() == 1); } // updateCharactersList