From 60e51ea707dfdcfc3cbf3256c88d3fb47a8594fd Mon Sep 17 00:00:00 2001 From: Jeremie Roy Date: Wed, 22 May 2013 17:15:58 +0200 Subject: [PATCH] make sure pen position always refers to top left + remove measureText + append substring --- examples/common/font/text_buffer_manager.cpp | 196 ++++++------------- examples/common/font/text_buffer_manager.h | 16 +- 2 files changed, 68 insertions(+), 144 deletions(-) diff --git a/examples/common/font/text_buffer_manager.cpp b/examples/common/font/text_buffer_manager.cpp index 5bbdba953..c68102f5b 100644 --- a/examples/common/font/text_buffer_manager.cpp +++ b/examples/common/font/text_buffer_manager.cpp @@ -22,7 +22,7 @@ #include "fs_font_distance_field_subpixel.bin.h" #define MAX_TEXT_BUFFER_COUNT 64 -#define MAX_BUFFERED_CHARACTERS 8192 +#define MAX_BUFFERED_CHARACTERS (8192 - 5) class TextBuffer { @@ -64,15 +64,11 @@ public: m_penX = _x; m_penY = _y; } - /// return the size of the text - //Rectangle measureText(FontHandle _fontHandle, const char * _string); - //Rectangle measureText(FontHandle _fontHandle, const wchar_t * _string); - /// append an ASCII/utf-8 string to the buffer using current pen position and color - void appendText(FontHandle _fontHandle, const char* _string); + void appendText(FontHandle _fontHandle, const char* _string, const char* _end = NULL); /// append a wide char unicode string to the buffer using current pen position and color - void appendText(FontHandle _fontHandle, const wchar_t* _string); + void appendText(FontHandle _fontHandle, const wchar_t* _string, const wchar_t* _end = NULL); /// append a whole face of the atlas cube, mostly used for debugging and visualizing atlas void appendAtlasFace(uint16_t _faceIndex); @@ -215,7 +211,7 @@ TextBuffer::~TextBuffer() delete[] m_indexBuffer; } -void TextBuffer::appendText(FontHandle _fontHandle, const char* _string) +void TextBuffer::appendText(FontHandle _fontHandle, const char* _string, const char* _end) { GlyphInfo glyph; const FontInfo& font = m_fontManager->getFontInfo(_fontHandle); @@ -224,16 +220,17 @@ void TextBuffer::appendText(FontHandle _fontHandle, const char* _string) { m_originX = m_penX; m_originY = m_penY; - m_lineDescender = 0; // font.m_descender; - m_lineAscender = 0; //font.m_ascender; + m_lineDescender = 0; + m_lineAscender = 0; + m_lineGap = 0; } CodePoint codepoint = 0; uint32_t state = 0; - for (; *_string; ++_string) + for (; *_string && _string<_end ; ++_string) { - if (!utf8_decode(&state, (uint32_t*)&codepoint, *_string) ) + if (utf8_decode(&state, (uint32_t*)&codepoint, *_string) == UTF8_ACCEPT ) { if (m_fontManager->getGlyphInfo(_fontHandle, codepoint, glyph) ) { @@ -246,13 +243,10 @@ void TextBuffer::appendText(FontHandle _fontHandle, const char* _string) } } - if (state != UTF8_ACCEPT) - { - BX_CHECK(false, "The string is not well-formed"); - } + BX_CHECK(state == UTF8_ACCEPT, "The string is not well-formed"); } -void TextBuffer::appendText(FontHandle _fontHandle, const wchar_t* _string) +void TextBuffer::appendText(FontHandle _fontHandle, const wchar_t* _string, const wchar_t* _end) { GlyphInfo glyph; const FontInfo& font = m_fontManager->getFontInfo(_fontHandle); @@ -261,14 +255,19 @@ void TextBuffer::appendText(FontHandle _fontHandle, const wchar_t* _string) { m_originX = m_penX; m_originY = m_penY; - m_lineDescender = 0; // font.m_descender; - m_lineAscender = 0; //font.m_ascender; + m_lineDescender = 0; + m_lineAscender = 0; m_lineGap = 0; } - - for (uint32_t ii = 0, end = wcslen(_string); ii < end; ++ii) + if( _end == NULL) { - uint32_t _codePoint = _string[ii]; + _end = _string + wcslen(_string); + } + BX_CHECK(_end >= _string); + + for (const wchar_t* _current = _string; _current < _end; ++_current) + { + uint32_t _codePoint = *_current; if (m_fontManager->getGlyphInfo(_fontHandle, _codePoint, glyph) ) { appendGlyph(_codePoint, font, glyph); @@ -282,6 +281,11 @@ void TextBuffer::appendText(FontHandle _fontHandle, const wchar_t* _string) void TextBuffer::appendAtlasFace(uint16_t _faceIndex) { + if( m_vertexCount/4 >= MAX_BUFFERED_CHARACTERS) + { + return; + } + float x0 = m_penX; float y0 = m_penY; float x1 = x0 + (float)m_fontManager->getAtlas()->getTextureSize(); @@ -306,29 +310,40 @@ void TextBuffer::appendAtlasFace(uint16_t _faceIndex) void TextBuffer::clearTextBuffer() { + m_penX = 0; + m_penY = 0; + m_originX = 0; + m_originY = 0; + m_vertexCount = 0; m_indexCount = 0; m_lineStartIndex = 0; m_lineAscender = 0; m_lineDescender = 0; + m_lineGap = 0; m_rectangle.width = 0; m_rectangle.height = 0; } void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const GlyphInfo& _glyphInfo) -{ - if (_codePoint == L'\n') +{ + if( m_vertexCount/4 >= MAX_BUFFERED_CHARACTERS) { - m_penX = m_originX; - m_penY -= m_lineDescender; - m_penY += m_lineGap; - m_lineDescender = 0; - m_lineAscender = 0; - m_lineStartIndex = m_vertexCount; - return; } + if (_codePoint == L'\n') + { + m_penX = m_originX; + m_penY += m_lineGap + m_lineAscender -m_lineDescender; + m_lineGap = _font.lineGap; + m_lineDescender = _font.descender; + m_lineAscender = _font.ascender; + m_lineStartIndex = m_vertexCount; + return; + } + + //is there a change of font size that require the text on the left to be centered again ? if (_font.ascender > m_lineAscender || (_font.descender < m_lineDescender) ) { @@ -340,14 +355,12 @@ void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const float txtDecals = (_font.ascender - m_lineAscender); m_lineAscender = _font.ascender; - m_lineGap = _font.lineGap; - - m_penY += txtDecals; - verticalCenterLastLine( (txtDecals), (m_penY - m_lineAscender), (m_penY - m_lineDescender + m_lineGap) ); + m_lineGap = _font.lineGap; + verticalCenterLastLine( (txtDecals), (m_penY - m_lineAscender), (m_penY + m_lineAscender - m_lineDescender + m_lineGap) ); } - float kerning = 0; - m_penX += kerning * _font.scale; + float kerning = 0 * _font.scale; + m_penX += kerning; GlyphInfo& blackGlyph = m_fontManager->getBlackGlyph(); @@ -355,9 +368,9 @@ void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const && m_backgroundColor & 0xFF000000) { float x0 = (m_penX - kerning); - float y0 = (m_penY - m_lineAscender); + float y0 = (m_penY); float x1 = ( (float)x0 + (_glyphInfo.advance_x) ); - float y1 = (m_penY - m_lineDescender + m_lineGap); + float y1 = (m_penY + m_lineAscender - m_lineDescender + m_lineGap); m_fontManager->getAtlas()->packUV(blackGlyph.regionIndex, (uint8_t*)m_vertexBuffer, sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u), sizeof(TextVertex) ); @@ -380,7 +393,7 @@ void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const && m_underlineColor & 0xFF000000) { float x0 = (m_penX - kerning); - float y0 = (m_penY - m_lineDescender / 2); + float y0 = (m_penY + m_lineAscender - m_lineDescender * 0.5f); float x1 = ( (float)x0 + (_glyphInfo.advance_x) ); float y1 = y0 + _font.underlineThickness; @@ -405,7 +418,7 @@ void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const && m_overlineColor & 0xFF000000) { float x0 = (m_penX - kerning); - float y0 = (m_penY - _font.ascender); + float y0 = (m_penY); float x1 = ( (float)x0 + (_glyphInfo.advance_x) ); float y1 = y0 + _font.underlineThickness; @@ -430,7 +443,7 @@ void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const && m_strikeThroughColor & 0xFF000000) { float x0 = (m_penX - kerning); - float y0 = (m_penY - _font.ascender / 3); + float y0 = (m_penY + 0.666667f * _font.ascender); float x1 = ( (float)x0 + (_glyphInfo.advance_x) ); float y1 = y0 + _font.underlineThickness; @@ -451,9 +464,8 @@ void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const m_indexCount += 6; } - float x0_precise = m_penX + (_glyphInfo.offset_x); - float x0 = (x0_precise); - float y0 = (m_penY + (_glyphInfo.offset_y) ); + float x0 = m_penX + (_glyphInfo.offset_x); + float y0 = (m_penY + m_lineAscender + (_glyphInfo.offset_y) ); float x1 = (x0 + _glyphInfo.width); float y1 = (y0 + _glyphInfo.height); @@ -479,9 +491,9 @@ void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const m_rectangle.width = m_penX; } - if ( (m_penY - m_lineDescender) > m_rectangle.height) + if ( (m_penY +m_lineAscender - m_lineDescender+m_lineGap) > m_rectangle.height) { - m_rectangle.height = (m_penY - m_lineDescender); + m_rectangle.height = (m_penY +m_lineAscender - m_lineDescender+m_lineGap); } } @@ -813,18 +825,18 @@ void TextBufferManager::setPenPosition(TextBufferHandle _handle, float _x, float bc.textBuffer->setPenPosition(_x, _y); } -void TextBufferManager::appendText(TextBufferHandle _handle, FontHandle _fontHandle, const char* _string) +void TextBufferManager::appendText(TextBufferHandle _handle, FontHandle _fontHandle, const char* _string, const char* _end) { BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used"); BufferCache& bc = m_textBuffers[_handle.idx]; - bc.textBuffer->appendText(_fontHandle, _string); + bc.textBuffer->appendText(_fontHandle, _string, _end); } -void TextBufferManager::appendText(TextBufferHandle _handle, FontHandle _fontHandle, const wchar_t* _string) +void TextBufferManager::appendText(TextBufferHandle _handle, FontHandle _fontHandle, const wchar_t* _string, const wchar_t* _end) { BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used"); BufferCache& bc = m_textBuffers[_handle.idx]; - bc.textBuffer->appendText(_fontHandle, _string); + bc.textBuffer->appendText(_fontHandle, _string, _end); } void TextBufferManager::appendAtlasFace(TextBufferHandle _handle, uint16_t _faceIndex) @@ -841,88 +853,6 @@ void TextBufferManager::clearTextBuffer(TextBufferHandle _handle) bc.textBuffer->clearTextBuffer(); } -TextRectangle TextBufferManager::measureText(FontHandle _fontHandle, const char* _string) const -{ - GlyphInfo glyph; - const FontInfo& font = m_fontManager->getFontInfo(_fontHandle); - TextRectangle rect; - rect.width = 0; - rect.height = font.ascender - font.descender; //should I put lineGap here ? - - CodePoint codepoint = 0; - uint32_t state = 0; - float w = 0; - - for (; *_string; ++_string) - { - if (!utf8_decode(&state, (uint32_t*)&codepoint, *_string) ) - { - if (m_fontManager->getGlyphInfo(_fontHandle, codepoint, glyph) ) - { - if (codepoint == L'\n') - { - rect.height += font.lineGap + font.ascender - font.descender; - w=0; - break; - } - //TODO kerning - - if((w + glyph.advance_x) > rect.width) - { - rect.width = w + glyph.advance_x; - } - } - else - { - BX_CHECK(false, "Glyph not found"); - } - } - } - - if (state != UTF8_ACCEPT) - { - BX_CHECK(false, "The string is not well-formed"); - } - - return rect; -} - -TextRectangle TextBufferManager::measureText(FontHandle _fontHandle, const wchar_t* _string) const -{ - GlyphInfo glyph; - const FontInfo& font = m_fontManager->getFontInfo(_fontHandle); - TextRectangle rect; - rect.width = 0; - rect.height = font.ascender - font.descender; //should I put lineGap here ? - float w = 0; - - for (uint32_t ii = 0, end = wcslen(_string); ii < end; ++ii) - { - uint32_t codepoint = _string[ii]; - if (m_fontManager->getGlyphInfo(_fontHandle, codepoint, glyph) ) - { - if (codepoint == L'\n') - { - rect.height += font.lineGap + font.ascender - font.descender; - w=0; - break; - } - //TODO kerning - - if((w + glyph.advance_x) > rect.width) - { - rect.width = w + glyph.advance_x; - } - } - else - { - BX_CHECK(false, "Glyph not found"); - } - } - - return rect; -} - TextRectangle TextBufferManager::getRectangle(TextBufferHandle _handle) const { BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used"); diff --git a/examples/common/font/text_buffer_manager.h b/examples/common/font/text_buffer_manager.h index 9a00302af..ea9033696 100644 --- a/examples/common/font/text_buffer_manager.h +++ b/examples/common/font/text_buffer_manager.h @@ -55,26 +55,20 @@ public: void setPenPosition(TextBufferHandle _handle, float _x, float _y); /// append an ASCII/utf-8 string to the buffer using current pen position and color - void appendText(TextBufferHandle _handle, FontHandle _fontHandle, const char* _string); + void appendText(TextBufferHandle _handle, FontHandle _fontHandle, const char* _string, const char* _end = NULL); /// append a wide char unicode string to the buffer using current pen position and color - void appendText(TextBufferHandle _handle, FontHandle _fontHandle, const wchar_t* _string); - + void appendText(TextBufferHandle _handle, FontHandle _fontHandle, const wchar_t* _string, const wchar_t* _end = NULL); + /// append a whole face of the atlas cube, mostly used for debugging and visualizing atlas void appendAtlasFace(TextBufferHandle _handle, uint16_t _faceIndex); /// Clear the text buffer and reset its state (pen/color) void clearTextBuffer(TextBufferHandle _handle); - /// Return the rectangular size of the text without adding it to the buffer - TextRectangle measureText(FontHandle _fontHandle, const wchar_t* _string) const; - - /// Return the rectangular size of the text without adding it to the buffer - TextRectangle measureText(FontHandle _fontHandle, const char* _string) const; - /// Return the rectangular size of the current text buffer (including all its content) - TextRectangle getRectangle(TextBufferHandle _handle) const; - + TextRectangle getRectangle(TextBufferHandle _handle) const; + private: struct BufferCache {