OpenSceneGraph:如何检测osgText::Font是否支持指定字符
问题原因说明
你之前的两种检测方法无效的核心原因如下:
getTextureInfo返回nullptr:该接口返回的是已经上传到GPU的纹理资源,只有对应字形被渲染过至少一次,OSG才会完成字形纹理上传,未触发渲染前调用该接口必然返回空值。getTotalDataSize无法区分占位字形:占位的.notdef字形本身就是合法的矢量/位图字形,本身存在有效数据,所以返回值肯定不为0,无法作为判断依据。
可行解决方案
方案1:调用FreeType底层接口判断(全版本兼容,准确率最高)
OSG底层依赖FreeType加载字体,直接调用FreeType原生接口判断字符的字形索引是最准确的方案。由于osgText::Font的FreeType face指针是protected属性,我们可以通过简单的子类访问:
#include <osgText/Font> #include <ft2build.h> #include FT_FREETYPE_H // 访问器子类,用于获取Font内部的FreeType face指针 class FontAccessor : public osgText::Font { public: FT_Face getFreeTypeFace() const { return _face; } }; bool hasValidGlyph(osgText::Font* font, unsigned int charcode) { if (!font) return false; FontAccessor* accessor = static_cast<FontAccessor*>(font); FT_Face face = accessor->getFreeTypeFace(); if (!face) return false; // FT_Get_Char_Index返回0表示无对应字形,会使用缺省占位符 return FT_Get_Char_Index(face, charcode) != 0; }
方案2:对比缺省占位字形属性(无额外依赖,兼容性好)
如果不想引入FreeType的显式依赖,可以先获取字体的缺省占位字形,再和目标字符的字形做属性对比判断:
bool hasValidGlyph(osgText::Font* font, unsigned int charcode, float fontSize = 32.0f) { if (!font) return false; // 获取缺省占位字形:U+FFFF是Unicode永久保留的非字符,所有字体都不会有对应字形 osgText::Glyph* defaultGlyph = font->getGlyph(std::make_pair(fontSize, fontSize), 0xFFFF); // 获取目标字符的字形 osgText::Glyph* targetGlyph = font->getGlyph(std::make_pair(fontSize, fontSize), charcode); // 对比宽、高、水平步进、数据长度四个参数,完全一致则判定为占位字形 if (targetGlyph->getWidth() == defaultGlyph->getWidth() && targetGlyph->getHeight() == defaultGlyph->getHeight() && targetGlyph->getHorizontalAdvance() == defaultGlyph->getHorizontalAdvance() && targetGlyph->getTotalDataSize() == defaultGlyph->getTotalDataSize()) { return false; } return true; }
该方案仅在极端场景(目标字符的字形和占位符参数完全一致)下会出现误判,绝大多数业务场景可用。
内容的提问来源于stack exchange,提问作者helga-helga
相关产品推荐
相关产品推荐

