From 5cd2e2299f98065fa06c192df4dfb2c014b2b253 Mon Sep 17 00:00:00 2001 From: chai Date: Wed, 3 Nov 2021 13:08:39 +0800 Subject: *font --- Runtime/GUI/Font.cpp | 65 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 14 deletions(-) (limited to 'Runtime/GUI/Font.cpp') diff --git a/Runtime/GUI/Font.cpp b/Runtime/GUI/Font.cpp index 614792a..d669844 100644 --- a/Runtime/GUI/Font.cpp +++ b/Runtime/GUI/Font.cpp @@ -15,6 +15,9 @@ using namespace character; static std::string s_FontError; +static std::vector s_PixelBuffer; +static int s_SizePerPixel = sizeof(unsigned char); + Font::Font(std::string path, TextGeneratingSettings settings) : LuaBind::NativeClass() { @@ -109,8 +112,14 @@ const Character* Font::GetCharacter(character::Codepoint codepoint, int pixelSiz auto iter = m_Characters.find(hash); if (iter == m_Characters.end()) { - RenderCharacter(codepoint, pixelSize); - iter = m_Characters.find(hash); + if (RenderCharacter(codepoint, pixelSize)) + { + iter = m_Characters.find(hash); + } + else + { + return NULL; + } } Assert(iter != m_Characters.end()); return &iter->second; @@ -133,21 +142,48 @@ void Font::RenderCharacters(std::vector& codepoint, int pi } } -void Font::RenderCharacter(character::Codepoint codepoint, int pixelSize) +bool Font::RenderCharacter(character::Codepoint codepoint, int pixelSize) { character::Hash hash = GetHash(codepoint, pixelSize); if (m_Characters.count(hash) != 0) - return; + return true; FT_Set_Pixel_Sizes(m_FTFace, 0, pixelSize); - if (FT_Load_Char(m_FTFace, codepoint, FT_LOAD_RENDER)) - { - return; - } + + // bug: 发现有时候渲染的结果是FT_PIXEL_MODE_MONO(1-bits),试过不同的flags组合还是不对,最后手动转换为8-bits + + //FT_Int32 flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_FORCE_AUTOHINT; + FT_Int32 flags = FT_LOAD_RENDER; + if (FT_Load_Char(m_FTFace, codepoint, flags)) + return false; int w = m_FTFace->glyph->bitmap.width; int h = m_FTFace->glyph->bitmap.rows; - TextHelper::print_glyph(m_FTFace->glyph->bitmap.buffer, w, h); + const unsigned char* pixels = m_FTFace->glyph->bitmap.buffer; + if (pixels == NULL) + return false; + + s_PixelBuffer.resize(w * h); + if (m_FTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) + { + // 1 bit monochrome + int pitch = m_FTFace->glyph->bitmap.pitch; + for (int y = 0; y < h; ++y) + { + for (int x = 0; x < w; ++x) + { + int index = x + y * w; + s_PixelBuffer[index] = ((pixels[pitch * y + x / 8]) & (1 << (7 - x % 8))) ? 255 : 0; + } + } + } + else if (m_FTFace->glyph->bitmap.pixel_mode) + { + // 8 bit grayscale + memcpy(&s_PixelBuffer[0], pixels, s_SizePerPixel * w * h); + } + + //TextHelper::print_glyph(&s_PixelBuffer[0], w, h); GlyphAtals* atlas = RequestAtlas(pixelSize, Internal::Vector2(w, h)); Assert(atlas); @@ -156,15 +192,17 @@ void Font::RenderCharacter(character::Codepoint codepoint, int pixelSize) try { - atlas->altas->UpdateSubImage(rect, EPixelFormat::PixelFormat_R, EPixelElementType::PixelType_UNSIGNED_BYTE, m_FTFace->glyph->bitmap.buffer); + atlas->altas->UpdateSubImage(rect, EPixelFormat::PixelFormat_R, EPixelElementType::PixelType_UNSIGNED_BYTE, &s_PixelBuffer[0]); } catch (TextureException& e) { + s_PixelBuffer.clear(); std::string error = e.what(); error = "Render Character Error: " + error; log_error(e.what()); - return; + return false; } + s_PixelBuffer.clear(); Character character; character.atlas = atlas->index; @@ -173,9 +211,8 @@ void Font::RenderCharacter(character::Codepoint codepoint, int pixelSize) character.advance = m_FTFace->glyph->advance.x * 1/64.f; m_Characters.insert(std::pair(hash, character)); -/* - FT_Done_Face(m_FTFace); - FT_Done_FreeType(m_FTLibrary);*/ + + return true; } const GlyphAtals* Font::GetGlyphAtlas(int index) -- cgit v1.1-26-g67d0