summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/examples/common/font/font_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/bgfx/examples/common/font/font_manager.cpp')
-rw-r--r--3rdparty/bgfx/examples/common/font/font_manager.cpp404
1 files changed, 169 insertions, 235 deletions
diff --git a/3rdparty/bgfx/examples/common/font/font_manager.cpp b/3rdparty/bgfx/examples/common/font/font_manager.cpp
index 0da5c17a0ba..5416fc55798 100644
--- a/3rdparty/bgfx/examples/common/font/font_manager.cpp
+++ b/3rdparty/bgfx/examples/common/font/font_manager.cpp
@@ -1,33 +1,19 @@
/*
* Copyright 2013 Jeremie Roy. All rights reserved.
- * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
+ * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
*/
-#include <bx/macros.h>
-
-#if BX_COMPILER_MSVC
-# define generic GenericFromFreeType // WinRT language extensions see "generic" as a keyword... this is stupid
-#endif // BX_COMPILER_MSVC
-
-BX_PRAGMA_DIAGNOSTIC_PUSH();
-BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4245) // error C4245: '=' : conversion from 'int' to 'FT_UInt', signed/unsigned mismatch
-BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4611) // warning C4611 : interaction between '_setjmp' and C++ object destruction is non - portable
-#if BX_COMPILER_MSVC || BX_COMPILER_GCC >= 40300
-#pragma push_macro("interface")
-#endif
-#undef interface
-#include <freetype/freetype.h>
-#if BX_COMPILER_MSVC || BX_COMPILER_GCC >= 40300
-#pragma pop_macro("interface")
-#endif
-BX_PRAGMA_DIAGNOSTIC_POP();
-
+#include <bx/bx.h>
+#include <stb/stb_truetype.h>
#include "../common.h"
-
#include <bgfx/bgfx.h>
+BX_PRAGMA_DIAGNOSTIC_PUSH()
+BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4244) // warning C4244: '=': conversion from 'double' to 'float', possible loss of data
+BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4701) // warning C4701: potentially uninitialized local variable 'pt' used
#define SDF_IMPLEMENTATION
#include <sdf/sdf.h>
+BX_PRAGMA_DIAGNOSTIC_POP()
#include <wchar.h> // wcslen
@@ -38,11 +24,6 @@ namespace stl = tinystl;
#include "font_manager.h"
#include "../cube_atlas.h"
-struct FTHolder
-{
- FT_Library library;
- FT_Face face;
-};
class TrueTypeFont
{
@@ -53,7 +34,7 @@ public:
/// Initialize from an external buffer
/// @remark The ownership of the buffer is external, and you must ensure it stays valid up to this object lifetime
/// @return true if the initialization succeed
- bool init(const uint8_t* _buffer, uint32_t _bufferSize, int32_t _fontIndex, uint32_t _pixelHeight);
+ bool init(const uint8_t* _buffer, uint32_t _bufferSize, int32_t _fontIndex, uint32_t _pixelHeight, int16_t _widthPadding, int16_t _heightPadding);
/// return the font descriptor of the current font
FontInfo getFontInfo();
@@ -63,255 +44,137 @@ public:
/// @ remark buffer min size: glyphInfo.m_width * glyphInfo * height * sizeof(char)
bool bakeGlyphAlpha(CodePoint _codePoint, GlyphInfo& _outGlyphInfo, uint8_t* _outBuffer);
- /// raster a glyph as 32bit subpixel rgba to a memory buffer
- /// update the GlyphInfo according to the raster strategy
- /// @ remark buffer min size: glyphInfo.m_width * glyphInfo * height * sizeof(uint32_t)
- bool bakeGlyphSubpixel(CodePoint _codePoint, GlyphInfo& _outGlyphInfo, uint8_t* _outBuffer);
-
/// raster a glyph as 8bit signed distance to a memory buffer
/// update the GlyphInfo according to the raster strategy
/// @ remark buffer min size: glyphInfo.m_width * glyphInfo * height * sizeof(char)
bool bakeGlyphDistance(CodePoint _codePoint, GlyphInfo& _outGlyphInfo, uint8_t* _outBuffer);
private:
- FTHolder* m_font;
+ friend class FontManager;
+
+ stbtt_fontinfo m_font;
+ float m_scale;
+
+ int16_t m_widthPadding;
+ int16_t m_heightPadding;
};
-TrueTypeFont::TrueTypeFont() : m_font(NULL)
+TrueTypeFont::TrueTypeFont() : m_font()
+ , m_widthPadding(6)
+ , m_heightPadding(6)
{
}
TrueTypeFont::~TrueTypeFont()
{
- if (NULL != m_font)
- {
- FT_Done_Face(m_font->face);
- FT_Done_FreeType(m_font->library);
- delete m_font;
- m_font = NULL;
- }
}
-bool TrueTypeFont::init(const uint8_t* _buffer, uint32_t _bufferSize, int32_t _fontIndex, uint32_t _pixelHeight)
+bool TrueTypeFont::init(const uint8_t* _buffer, uint32_t _bufferSize, int32_t _fontIndex, uint32_t _pixelHeight, int16_t _widthPadding, int16_t _heightPadding)
{
- BX_CHECK(m_font == NULL, "TrueTypeFont already initialized");
- BX_CHECK( (_bufferSize > 256 && _bufferSize < 100000000), "TrueType buffer size is suspicious");
- BX_CHECK( (_pixelHeight > 4 && _pixelHeight < 128), "TrueType buffer size is suspicious");
-
- FTHolder* holder = new FTHolder;
-
- FT_Error error = FT_Init_FreeType(&holder->library);
- BX_WARN(!error, "FT_Init_FreeType failed.");
-
- if (error)
- {
- goto err0;
- }
+ BX_WARN( (_bufferSize > 256 && _bufferSize < 100000000), "(FontIndex %d) TrueType buffer size is suspicious (%d)", _fontIndex, _bufferSize);
+ BX_WARN( (_pixelHeight > 4 && _pixelHeight < 128), "(FontIndex %d) TrueType pixel height is suspicious (%d)", _fontIndex, _pixelHeight);
+ BX_UNUSED(_bufferSize);
- error = FT_New_Memory_Face(holder->library, _buffer, _bufferSize, _fontIndex, &holder->face);
- BX_WARN(!error, "FT_Init_FreeType failed.");
+ int offset = stbtt_GetFontOffsetForIndex(_buffer, _fontIndex);
- if (error)
- {
- if (FT_Err_Unknown_File_Format == error)
- {
- goto err0;
- }
-
- goto err1;
- }
-
- error = FT_Select_Charmap(holder->face, FT_ENCODING_UNICODE);
- BX_WARN(!error, "FT_Init_FreeType failed.");
+ stbtt_InitFont(&m_font, _buffer, offset);
- if (error)
- {
- goto err2;
- }
+ m_scale = stbtt_ScaleForMappingEmToPixels(&m_font, (float)_pixelHeight);
- error = FT_Set_Pixel_Sizes(holder->face, 0, _pixelHeight);
- BX_WARN(!error, "FT_Init_FreeType failed.");
-
- if (error)
- {
- goto err2;
- }
-
- m_font = holder;
+ m_widthPadding = _widthPadding;
+ m_heightPadding = _heightPadding;
return true;
-
-err2:
- FT_Done_Face(holder->face);
-
-err1:
- FT_Done_FreeType(holder->library);
-
-err0:
- delete holder;
- return false;
}
FontInfo TrueTypeFont::getFontInfo()
{
- BX_CHECK(m_font != NULL, "TrueTypeFont not initialized");
- BX_CHECK(FT_IS_SCALABLE(m_font->face), "Font is unscalable");
+ int ascent;
+ int descent;
+ int lineGap;
+ stbtt_GetFontVMetrics(&m_font, &ascent, &descent, &lineGap);
+
+ float scale = m_scale;
- FT_Size_Metrics metrics = m_font->face->size->metrics;
+ int x0, y0, x1, y1;
+ stbtt_GetFontBoundingBox(&m_font, &x0, &y0, &x1, &y1);
FontInfo outFontInfo;
outFontInfo.scale = 1.0f;
- outFontInfo.ascender = metrics.ascender / 64.0f;
- outFontInfo.descender = metrics.descender / 64.0f;
- outFontInfo.lineGap = (metrics.height - metrics.ascender + metrics.descender) / 64.0f;
- outFontInfo.maxAdvanceWidth = metrics.max_advance/ 64.0f;
+ outFontInfo.ascender = bx::round(ascent * scale);
+ outFontInfo.descender = bx::round(descent * scale);
+ outFontInfo.lineGap = bx::round(lineGap * scale);
+ outFontInfo.maxAdvanceWidth = bx::round((y1 - y0) * scale);
- outFontInfo.underlinePosition = FT_MulFix(m_font->face->underline_position, metrics.y_scale) / 64.0f;
- outFontInfo.underlineThickness = FT_MulFix(m_font->face->underline_thickness, metrics.y_scale) / 64.0f;
+ outFontInfo.underlinePosition = (x1 - x0) * scale - ascent;
+ outFontInfo.underlineThickness = (x1 - x0) * scale / 24.f;
return outFontInfo;
}
-static void glyphInfoInit(GlyphInfo& _glyphInfo, FT_BitmapGlyph _bitmap, FT_GlyphSlot _slot, uint8_t* _dst, uint32_t _bpp)
-{
- int32_t xx = _bitmap->left;
- int32_t yy = -_bitmap->top;
- int32_t ww = _bitmap->bitmap.width;
- int32_t hh = _bitmap->bitmap.rows;
-
- _glyphInfo.offset_x = (float)xx;
- _glyphInfo.offset_y = (float)yy;
- _glyphInfo.width = (float)ww;
- _glyphInfo.height = (float)hh;
- _glyphInfo.advance_x = (float)_slot->advance.x / 64.0f;
- _glyphInfo.advance_y = (float)_slot->advance.y / 64.0f;
-
- uint32_t dstPitch = ww * _bpp;
-
- uint8_t* src = _bitmap->bitmap.buffer;
- uint32_t srcPitch = _bitmap->bitmap.pitch;
-
- for (int32_t ii = 0; ii < hh; ++ii)
- {
- bx::memCopy(_dst, src, dstPitch);
-
- _dst += dstPitch;
- src += srcPitch;
- }
-}
-
bool TrueTypeFont::bakeGlyphAlpha(CodePoint _codePoint, GlyphInfo& _glyphInfo, uint8_t* _outBuffer)
{
- BX_CHECK(m_font != NULL, "TrueTypeFont not initialized");
+ int32_t ascent, descent, lineGap;
+ stbtt_GetFontVMetrics(&m_font, &ascent, &descent, &lineGap);
- _glyphInfo.glyphIndex = FT_Get_Char_Index(m_font->face, _codePoint);
+ int32_t advance, lsb;
+ stbtt_GetCodepointHMetrics(&m_font, _codePoint, &advance, &lsb);
- FT_GlyphSlot slot = m_font->face->glyph;
- FT_Error error = FT_Load_Glyph(m_font->face, _glyphInfo.glyphIndex, FT_LOAD_DEFAULT);
- if (error)
- {
- return false;
- }
+ const float scale = m_scale;
+ int32_t x0, y0, x1, y1;
+ stbtt_GetCodepointBitmapBox(&m_font, _codePoint, scale, scale, &x0, &y0, &x1, &y1);
- FT_Glyph glyph;
- error = FT_Get_Glyph(slot, &glyph);
- if (error)
- {
- return false;
- }
+ const int32_t ww = x1-x0;
+ const int32_t hh = y1-y0;
- error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
- if (error)
- {
- return false;
- }
+ _glyphInfo.offset_x = (float)x0;
+ _glyphInfo.offset_y = (float)y0;
+ _glyphInfo.width = (float)ww;
+ _glyphInfo.height = (float)hh;
+ _glyphInfo.advance_x = bx::round(((float)advance) * scale);
+ _glyphInfo.advance_y = bx::round(((float)(ascent + descent + lineGap)) * scale);
- FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
+ uint32_t bpp = 1;
+ uint32_t dstPitch = ww * bpp;
- glyphInfoInit(_glyphInfo, bitmap, slot, _outBuffer, 1);
-
- FT_Done_Glyph(glyph);
- return true;
-}
-
-bool TrueTypeFont::bakeGlyphSubpixel(CodePoint _codePoint, GlyphInfo& _glyphInfo, uint8_t* _outBuffer)
-{
- BX_CHECK(m_font != NULL, "TrueTypeFont not initialized");
-
- _glyphInfo.glyphIndex = FT_Get_Char_Index(m_font->face, _codePoint);
-
- FT_GlyphSlot slot = m_font->face->glyph;
- FT_Error error = FT_Load_Glyph(m_font->face, _glyphInfo.glyphIndex, FT_LOAD_DEFAULT);
- if (error)
- {
- return false;
- }
-
- FT_Glyph glyph;
- error = FT_Get_Glyph(slot, &glyph);
- if (error)
- {
- return false;
- }
-
- error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_LCD, 0, 1);
- if (error)
- {
- return false;
- }
-
- FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
-
- glyphInfoInit(_glyphInfo, bitmap, slot, _outBuffer, 3);
- FT_Done_Glyph(glyph);
+ stbtt_MakeCodepointBitmap(&m_font, _outBuffer, ww, hh, dstPitch, scale, scale, _codePoint);
return true;
}
bool TrueTypeFont::bakeGlyphDistance(CodePoint _codePoint, GlyphInfo& _glyphInfo, uint8_t* _outBuffer)
{
- BX_CHECK(m_font != NULL, "TrueTypeFont not initialized");
+ int32_t ascent, descent, lineGap;
+ stbtt_GetFontVMetrics(&m_font, &ascent, &descent, &lineGap);
- _glyphInfo.glyphIndex = FT_Get_Char_Index(m_font->face, _codePoint);
+ int32_t advance, lsb;
+ stbtt_GetCodepointHMetrics(&m_font, _codePoint, &advance, &lsb);
- FT_Int32 loadMode = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
- FT_Render_Mode renderMode = FT_RENDER_MODE_NORMAL;
+ const float scale = m_scale;
+ int32_t x0, y0, x1, y1;
+ stbtt_GetCodepointBitmapBox(&m_font, _codePoint, scale, scale, &x0, &y0, &x1, &y1);
- FT_GlyphSlot slot = m_font->face->glyph;
- FT_Error error = FT_Load_Glyph(m_font->face, _glyphInfo.glyphIndex, loadMode);
- if (error)
- {
- return false;
- }
-
- FT_Glyph glyph;
- error = FT_Get_Glyph(slot, &glyph);
- if (error)
- {
- return false;
- }
-
- error = FT_Glyph_To_Bitmap(&glyph, renderMode, 0, 1);
- if (error)
- {
- return false;
- }
+ const int32_t ww = x1-x0;
+ const int32_t hh = y1-y0;
- FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
+ _glyphInfo.offset_x = (float)x0;
+ _glyphInfo.offset_y = (float)y0;
+ _glyphInfo.width = (float)ww;
+ _glyphInfo.height = (float)hh;
+ _glyphInfo.advance_x = bx::round(((float)advance) * scale);
+ _glyphInfo.advance_y = bx::round(((float)(ascent + descent + lineGap)) * scale);
- int32_t ww = bitmap->bitmap.width;
- int32_t hh = bitmap->bitmap.rows;
+ uint32_t bpp = 1;
+ uint32_t dstPitch = ww * bpp;
- glyphInfoInit(_glyphInfo, bitmap, slot, _outBuffer, 1);
-
- FT_Done_Glyph(glyph);
+ stbtt_MakeCodepointBitmap(&m_font, _outBuffer, ww, hh, dstPitch, scale, scale, _codePoint);
if (ww * hh > 0)
{
- uint32_t dw = 6;
- uint32_t dh = 6;
+ uint32_t dw = m_widthPadding;
+ uint32_t dh = m_heightPadding;
uint32_t nw = ww + dw * 2;
uint32_t nh = hh + dh * 2;
- BX_CHECK(nw * nh < 128 * 128, "Buffer overflow (size %d)", nw * nh);
+ BX_ASSERT(nw * nh < 128 * 128, "Buffer overflow (size %d)", nw * nh);
uint32_t buffSize = nw * nh * sizeof(uint8_t);
@@ -324,7 +187,8 @@ bool TrueTypeFont::bakeGlyphDistance(CodePoint _codePoint, GlyphInfo& _glyphInfo
bx::memCopy(alphaImg + ii * nw + dw, _outBuffer + (ii - dh) * ww, ww);
}
- sdfBuild(_outBuffer, nw, 8.0f, alphaImg, nw, nh, nw);
+ // stb_truetype has some builtin sdf functionality, we can investigate using that too
+ sdfBuildDistanceField(_outBuffer, nw, 8.0f, alphaImg, nw, nh, nw);
free(alphaImg);
_glyphInfo.offset_x -= (float)dw;
@@ -391,10 +255,10 @@ void FontManager::init()
FontManager::~FontManager()
{
- BX_CHECK(m_fontHandles.getNumHandles() == 0, "All the fonts must be destroyed before destroying the manager");
+ BX_ASSERT(m_fontHandles.getNumHandles() == 0, "All the fonts must be destroyed before destroying the manager");
delete [] m_cachedFonts;
- BX_CHECK(m_filesHandles.getNumHandles() == 0, "All the font files must be destroyed before destroying the manager");
+ BX_ASSERT(m_filesHandles.getNumHandles() == 0, "All the font files must be destroyed before destroying the manager");
delete [] m_cachedFiles;
delete [] m_buffer;
@@ -408,7 +272,7 @@ FontManager::~FontManager()
TrueTypeHandle FontManager::createTtf(const uint8_t* _buffer, uint32_t _size)
{
uint16_t id = m_filesHandles.alloc();
- BX_CHECK(id != bx::kInvalidHandle, "Invalid handle used");
+ BX_ASSERT(id != bx::kInvalidHandle, "Invalid handle used");
m_cachedFiles[id].buffer = new uint8_t[_size];
m_cachedFiles[id].bufferSize = _size;
bx::memCopy(m_cachedFiles[id].buffer, _buffer, _size);
@@ -419,19 +283,20 @@ TrueTypeHandle FontManager::createTtf(const uint8_t* _buffer, uint32_t _size)
void FontManager::destroyTtf(TrueTypeHandle _handle)
{
- BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
- delete m_cachedFiles[_handle.idx].buffer;
+ BX_ASSERT(isValid(_handle), "Invalid handle used");
+ delete[] m_cachedFiles[_handle.idx].buffer;
m_cachedFiles[_handle.idx].bufferSize = 0;
m_cachedFiles[_handle.idx].buffer = NULL;
m_filesHandles.free(_handle.idx);
}
-FontHandle FontManager::createFontByPixelSize(TrueTypeHandle _ttfHandle, uint32_t _typefaceIndex, uint32_t _pixelSize, uint32_t _fontType)
+FontHandle FontManager::createFontByPixelSize(TrueTypeHandle _ttfHandle, uint32_t _typefaceIndex, uint32_t _pixelSize, uint32_t _fontType,
+ uint16_t _glyphWidthPadding, uint16_t _glyphHeightPadding)
{
- BX_CHECK(bgfx::isValid(_ttfHandle), "Invalid handle used");
+ BX_ASSERT(isValid(_ttfHandle), "Invalid handle used");
TrueTypeFont* ttf = new TrueTypeFont();
- if (!ttf->init(m_cachedFiles[_ttfHandle.idx].buffer, m_cachedFiles[_ttfHandle.idx].bufferSize, _typefaceIndex, _pixelSize) )
+ if (!ttf->init(m_cachedFiles[_ttfHandle.idx].buffer, m_cachedFiles[_ttfHandle.idx].bufferSize, _typefaceIndex, _pixelSize, _glyphWidthPadding, _glyphHeightPadding) )
{
delete ttf;
FontHandle invalid = { bx::kInvalidHandle };
@@ -439,7 +304,7 @@ FontHandle FontManager::createFontByPixelSize(TrueTypeHandle _ttfHandle, uint32_
}
uint16_t fontIdx = m_fontHandles.alloc();
- BX_CHECK(fontIdx != bx::kInvalidHandle, "Invalid handle used");
+ BX_ASSERT(fontIdx != bx::kInvalidHandle, "Invalid handle used");
CachedFont& font = m_cachedFonts[fontIdx];
font.trueTypeFont = ttf;
@@ -455,7 +320,7 @@ FontHandle FontManager::createFontByPixelSize(TrueTypeHandle _ttfHandle, uint32_
FontHandle FontManager::createScaledFontToPixelSize(FontHandle _baseFontHandle, uint32_t _pixelSize)
{
- BX_CHECK(bgfx::isValid(_baseFontHandle), "Invalid handle used");
+ BX_ASSERT(isValid(_baseFontHandle), "Invalid handle used");
CachedFont& baseFont = m_cachedFonts[_baseFontHandle.idx];
FontInfo& fontInfo = baseFont.fontInfo;
@@ -470,7 +335,7 @@ FontHandle FontManager::createScaledFontToPixelSize(FontHandle _baseFontHandle,
newFontInfo.underlinePosition = (newFontInfo.underlinePosition * newFontInfo.scale);
uint16_t fontIdx = m_fontHandles.alloc();
- BX_CHECK(fontIdx != bx::kInvalidHandle, "Invalid handle used");
+ BX_ASSERT(fontIdx != bx::kInvalidHandle, "Invalid handle used");
CachedFont& font = m_cachedFonts[fontIdx];
font.cachedGlyphs.clear();
@@ -484,7 +349,7 @@ FontHandle FontManager::createScaledFontToPixelSize(FontHandle _baseFontHandle,
void FontManager::destroyFont(FontHandle _handle)
{
- BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
+ BX_ASSERT(isValid(_handle), "Invalid handle used");
CachedFont& font = m_cachedFonts[_handle.idx];
@@ -500,7 +365,7 @@ void FontManager::destroyFont(FontHandle _handle)
bool FontManager::preloadGlyph(FontHandle _handle, const wchar_t* _string)
{
- BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
+ BX_ASSERT(isValid(_handle), "Invalid handle used");
CachedFont& font = m_cachedFonts[_handle.idx];
if (NULL == font.trueTypeFont)
@@ -522,7 +387,7 @@ bool FontManager::preloadGlyph(FontHandle _handle, const wchar_t* _string)
bool FontManager::preloadGlyph(FontHandle _handle, CodePoint _codePoint)
{
- BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
+ BX_ASSERT(isValid(_handle), "Invalid handle used");
CachedFont& font = m_cachedFonts[_handle.idx];
FontInfo& fontInfo = font.fontInfo;
@@ -550,8 +415,16 @@ bool FontManager::preloadGlyph(FontHandle _handle, CodePoint _codePoint)
font.trueTypeFont->bakeGlyphDistance(_codePoint, glyphInfo, m_buffer);
break;
+ case FONT_TYPE_DISTANCE_OUTLINE:
+ case FONT_TYPE_DISTANCE_OUTLINE_IMAGE:
+ case FONT_TYPE_DISTANCE_DROP_SHADOW:
+ case FONT_TYPE_DISTANCE_DROP_SHADOW_IMAGE:
+ case FONT_TYPE_DISTANCE_OUTLINE_DROP_SHADOW_IMAGE:
+ font.trueTypeFont->bakeGlyphDistance(_codePoint, glyphInfo, m_buffer);
+ break;
+
default:
- BX_CHECK(false, "TextureType not supported yet");
+ BX_ASSERT(false, "TextureType not supported yet");
}
if (!addBitmap(glyphInfo, m_buffer) )
@@ -590,12 +463,73 @@ bool FontManager::preloadGlyph(FontHandle _handle, CodePoint _codePoint)
return false;
}
+bool FontManager::addGlyphBitmap(FontHandle _handle, CodePoint _codePoint, uint16_t _width, uint16_t _height, uint16_t _pitch, float extraScale, const uint8_t* _bitmapBuffer, float glyphOffsetX, float glyphOffsetY)
+{
+ BX_ASSERT(isValid(_handle), "Invalid handle used");
+ CachedFont& font = m_cachedFonts[_handle.idx];
+
+ GlyphHashMap::iterator iter = font.cachedGlyphs.find(_codePoint);
+ if (iter != font.cachedGlyphs.end() )
+ {
+ return true;
+ }
+
+ GlyphInfo glyphInfo;
+
+ float glyphScale = extraScale;
+ glyphInfo.offset_x = glyphOffsetX * glyphScale;
+ glyphInfo.offset_y = glyphOffsetY * glyphScale;
+ glyphInfo.width = (float)_width;
+ glyphInfo.height = (float)_height;
+ glyphInfo.advance_x = (float)_width * glyphScale;
+ glyphInfo.advance_y = (float)_height * glyphScale;
+ glyphInfo.bitmapScale = glyphScale;
+
+ uint32_t dstPitch = _width * 4;
+
+ uint8_t* dst = m_buffer;
+ const uint8_t* src = _bitmapBuffer;
+ uint32_t srcPitch = _pitch;
+
+ for (int32_t ii = 0; ii < _height; ++ii)
+ {
+ bx::memCopy(dst, src, dstPitch);
+
+ dst += dstPitch;
+ src += srcPitch;
+ }
+
+ glyphInfo.regionIndex = m_atlas->addRegion(
+ (uint16_t)bx::ceil(glyphInfo.width)
+ , (uint16_t)bx::ceil(glyphInfo.height)
+ , m_buffer
+ , AtlasRegion::TYPE_BGRA8
+ );
+
+ font.cachedGlyphs[_codePoint] = glyphInfo;
+ return true;
+}
+
const FontInfo& FontManager::getFontInfo(FontHandle _handle) const
{
- BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
+ BX_ASSERT(isValid(_handle), "Invalid handle used");
return m_cachedFonts[_handle.idx].fontInfo;
}
+float FontManager::getKerning(FontHandle _handle, CodePoint _prevCodePoint, CodePoint _codePoint)
+{
+ const CachedFont& cachedFont = m_cachedFonts[_handle.idx];
+ if (isValid(cachedFont.masterFontHandle))
+ {
+ CachedFont& baseFont = m_cachedFonts[cachedFont.masterFontHandle.idx];
+ return baseFont.trueTypeFont->m_scale * stbtt_GetCodepointKernAdvance(&baseFont.trueTypeFont->m_font, _prevCodePoint, _codePoint);
+ }
+ else
+ {
+ return cachedFont.trueTypeFont->m_scale * stbtt_GetCodepointKernAdvance(&cachedFont.trueTypeFont->m_font, _prevCodePoint, _codePoint);
+ }
+}
+
const GlyphInfo* FontManager::getGlyphInfo(FontHandle _handle, CodePoint _codePoint)
{
const GlyphHashMap& cachedGlyphs = m_cachedFonts[_handle.idx].cachedGlyphs;
@@ -611,7 +545,7 @@ const GlyphInfo* FontManager::getGlyphInfo(FontHandle _handle, CodePoint _codePo
it = cachedGlyphs.find(_codePoint);
}
- BX_CHECK(it != cachedGlyphs.end(), "Failed to preload glyph.");
+ BX_ASSERT(it != cachedGlyphs.end(), "Failed to preload glyph.");
return &it->second;
}