view_t view() { FT_BitmapGlyph bmg = bitmap_glyph(); return boost::gil::interleaved_view ( bmg->bitmap.width, bmg->bitmap.rows, (pixel_t*)bmg->bitmap.buffer, sizeof(pixel_t) * bmg->bitmap.width ); }
void gep::Font::buildChar(void* pFace, wchar_t c, size_t num){ FT_Face face = (FT_Face)pFace; // Load the glyph if(FT_Load_Glyph( face, FT_Get_Char_Index( face, c ), FT_LOAD_DEFAULT ) != 0) { std::ostringstream msg; msg << "Error loading character " << (uint32)c; throw Exception(msg.str()); } FT_Glyph glyph; FT_Get_Glyph( face->glyph, &glyph); // Convert it to a bitmap FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, nullptr, 1 ); FT_BitmapGlyph bitmap_glyph((FT_BitmapGlyph)glyph); FT_Bitmap* bitmap = &bitmap_glyph->bitmap; // Allocate the bitmap ImageData2D::image_data_t buffer; if(bitmap->width > 0 || bitmap->rows > 0) { buffer = GEP_NEW_ARRAY(g_stdAllocator, ImageData2D::mipmap_data_t, 1); buffer[0] = GEP_NEW_ARRAY(g_stdAllocator, ImageData2D::channel_data_t, bitmap->rows * bitmap->width); auto& mipmap = buffer[0]; for(int i=0; i<bitmap->rows * bitmap->width; i++){ mipmap[i] = bitmap->buffer[i]; } } auto& g = m_glyphs[num]; if(bitmap->width > 0 || bitmap->rows > 0) { g.m_data = GEP_NEW(g_stdAllocator, ImageData2D); g.m_data->setData(&g_stdAllocator, buffer, bitmap->width, bitmap->rows, ImageFormat::R8, ImageCompression::NONE); } else { g.m_data = nullptr; } g.m_width = bitmap->width; g.m_height = bitmap->rows; g.m_top = bitmap_glyph->top; g.m_left = bitmap_glyph->left; g.m_right = (face->glyph->advance.x >> 6) - bitmap_glyph->left - bitmap->width; }
void font_data::createGlyph(CharacterCode charCode) const { if (FT_Load_Glyph(_face, FT_Get_Char_Index(_face, charCode), FT_LOAD_DEFAULT)) { LogError << "FT_Load_Glyph failed" << std::endl; throw std::runtime_error("FT_Load_Glyph failed"); } FT_Glyph glyph; if (FT_Get_Glyph(_face->glyph, &glyph)) { LogError << "FT_Get_Glyph failed" << std::endl; throw std::runtime_error("FT_Get_Glyph failed"); } FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1); FT_BitmapGlyph bitmap_glyph(reinterpret_cast<FT_BitmapGlyph>(glyph)); const FT_Bitmap& bitmap = bitmap_glyph->bitmap; const int width(next_p2(bitmap.width + 1)); const int height(next_p2(bitmap.rows + 1)); const size_t expanded_size(width * height * 2); GLubyte* expanded_data = new GLubyte[expanded_size]; memset(expanded_data, 0, expanded_size); for (int j(0); j < height; ++j) { for (int i(0); i < width; ++i) { expanded_data[2 * (i + j * width)] = expanded_data[2 * (i + j * width) + 1] = (i >= bitmap.width || j >= bitmap.rows) ? 0 : static_cast<GLubyte>(std::min(static_cast<float>(bitmap.buffer[i + bitmap.width * j]) * 1.5f, 255.0f)); } } GlyphData glyphData; glyphData._width = _face->glyph->advance.x >> 6; glyphData._texture = new OpenGL::Texture(); glyphData._texture->bind(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data); delete[] expanded_data; expanded_data = NULL; glyphData._callList = new OpenGL::CallList(); glyphData._callList->startRecording(); glyphData._texture->bind(); const float xl((const float)bitmap_glyph->left); const float xh(xl + width); const float yl((const float)h - bitmap_glyph->top); const float yh(yl + height); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.0f, 0.0f); glVertex2f(xl, yl); glTexCoord2f(0.0f, 1.0f); glVertex2f(xl, yh); glTexCoord2f(1.0f, 0.0f); glVertex2f(xh, yl); glTexCoord2f(1.0f, 1.0f); glVertex2f(xh, yh); glEnd(); glTranslatef(static_cast<float>(glyphData._width), 0.0f, 0.0f); glyphData._callList->endRecording(); _cachedGlyphs[charCode] = glyphData; }