bool Font::insertGlyph(Char character) { FT_Error error; FT_UInt glyphIndex = FT_Get_Char_Index(face, character); if(!glyphIndex) { insertPlaceholderGlyph(character); return false; } error = FT_Load_Glyph(face, glyphIndex, FT_LOAD_FORCE_AUTOHINT); if(error) { insertPlaceholderGlyph(character); return false; } error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); if(error) { insertPlaceholderGlyph(character); return false; } // Fill in info for this glyph. Glyph & glyph = glyphs[character]; glyph.index = glyphIndex; glyph.size.x = face->glyph->bitmap.width; glyph.size.y = face->glyph->bitmap.rows; glyph.advance.x = face->glyph->linearHoriAdvance / 65536.0f; glyph.advance.y = face->glyph->linearVertAdvance / 65536.0f; glyph.lsb_delta = face->glyph->lsb_delta; glyph.rsb_delta = face->glyph->rsb_delta; glyph.draw_offset.x = face->glyph->bitmap_left; glyph.draw_offset.y = face->glyph->bitmap_top - face->glyph->bitmap.rows; glyph.uv_start = Vec2f_ZERO; glyph.uv_end = Vec2f_ZERO; glyph.texture = 0; // Some glyphs like spaces have a size of 0... if(glyph.size.x != 0 && glyph.size.y != 0) { Image imgGlyph; imgGlyph.Create(glyph.size.x, glyph.size.y, Image::Format_A8); FT_Bitmap * srcBitmap = &face->glyph->bitmap; arx_assert(srcBitmap->pitch >= 0); arx_assert(unsigned(srcBitmap->pitch) == unsigned(srcBitmap->width)); // Copy pixels unsigned char * src = srcBitmap->buffer; unsigned char * dst = imgGlyph.GetData(); memcpy(dst, src, glyph.size.x * glyph.size.y); Vec2i offset; if(!textures->insertImage(imgGlyph, glyph.texture, offset)) { LogWarning << "Could not upload glyph for character U+" << std::hex << character << " (" << util::encode<util::UTF8>(character) << ") in font " << info.name; insertPlaceholderGlyph(character); return false; } // Compute UV mapping for each glyph. const float textureSize = textures->getTextureSize(); glyph.uv_start = Vec2f(offset) / Vec2f(textureSize); glyph.uv_end = Vec2f(offset + glyph.size) / Vec2f(textureSize); } return true; }
bool Font::insertGlyph(Char character) { if(!m_size) { insertPlaceholderGlyph(character); return false; } FT_UInt glyphIndex = FT_Get_Char_Index(m_size->face, character); if(!glyphIndex) { insertPlaceholderGlyph(character); return false; } FT_Int32 flags = FT_LOAD_TARGET_LIGHT; if(m_info.weight != 0) { flags |= FT_LOAD_FORCE_AUTOHINT; } if(FT_Load_Glyph(m_size->face, glyphIndex, flags)) { insertPlaceholderGlyph(character); return false; } FT_GlyphSlot ftGlyph = m_size->face->glyph; if(m_info.weight != 0 && ftGlyph->format == FT_GLYPH_FORMAT_OUTLINE) { FT_Pos strength = FT_MulFix(m_size->face->units_per_EM, m_size->metrics.y_scale) / 24 * m_info.weight / 4; FT_Outline_Embolden(&ftGlyph->outline, strength); } if(FT_Render_Glyph(ftGlyph, FT_RENDER_MODE_NORMAL)) { insertPlaceholderGlyph(character); return false; } // Fill in info for this glyph. Glyph & glyph = m_glyphs[character]; glyph.index = glyphIndex; glyph.size.x = ftGlyph->bitmap.width; glyph.size.y = ftGlyph->bitmap.rows; glyph.advance.x = float(ftGlyph->linearHoriAdvance) / 65536.f; glyph.advance.y = float(ftGlyph->linearVertAdvance) / 65536.f; glyph.lsb_delta = ftGlyph->lsb_delta; glyph.rsb_delta = ftGlyph->rsb_delta; glyph.draw_offset.x = ftGlyph->bitmap_left; glyph.draw_offset.y = ftGlyph->bitmap_top - ftGlyph->bitmap.rows; glyph.uv_start = Vec2f(0.f); glyph.uv_end = Vec2f(0.f); glyph.texture = 0; // Some glyphs like spaces have a size of 0... if(glyph.size.x != 0 && glyph.size.y != 0) { Image imgGlyph; imgGlyph.create(size_t(glyph.size.x), size_t(glyph.size.y), Image::Format_A8); FT_Bitmap & srcBitmap = ftGlyph->bitmap; arx_assert(srcBitmap.pitch >= 0); arx_assert(unsigned(srcBitmap.pitch) == unsigned(srcBitmap.width)); // Copy pixels unsigned char * src = srcBitmap.buffer; unsigned char * dst = imgGlyph.getData(); memcpy(dst, src, glyph.size.x * glyph.size.y); Vec2i offset; if(!m_textures->insertImage(imgGlyph, glyph.texture, offset)) { LogWarning << "Could not upload glyph for character U+" << std::hex << character << " (" << util::encode<util::UTF8>(character) << ") in font " << m_info.name; insertPlaceholderGlyph(character); return false; } // Compute UV mapping for each glyph. const float textureSize = float(m_textures->getTextureSize()); glyph.uv_start = Vec2f(offset) / Vec2f(textureSize); glyph.uv_end = Vec2f(offset + glyph.size) / Vec2f(textureSize); } return true; }