Explorar el Código

make sure pen position always refers to top left + remove measureText + append substring

Jeremie Roy hace 12 años
padre
commit
60e51ea707

+ 59 - 129
examples/common/font/text_buffer_manager.cpp

@@ -22,7 +22,7 @@
 #include "fs_font_distance_field_subpixel.bin.h"
 #include "fs_font_distance_field_subpixel.bin.h"
 
 
 #define MAX_TEXT_BUFFER_COUNT   64
 #define MAX_TEXT_BUFFER_COUNT   64
-#define MAX_BUFFERED_CHARACTERS 8192
+#define MAX_BUFFERED_CHARACTERS (8192 - 5)
 
 
 class TextBuffer
 class TextBuffer
 {
 {
@@ -64,15 +64,11 @@ public:
 		m_penX = _x; m_penY = _y;
 		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
 	/// 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
 	/// 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
 	/// append a whole face of the atlas cube, mostly used for debugging and visualizing atlas
 	void appendAtlasFace(uint16_t _faceIndex);
 	void appendAtlasFace(uint16_t _faceIndex);
@@ -215,7 +211,7 @@ TextBuffer::~TextBuffer()
 	delete[] m_indexBuffer;
 	delete[] m_indexBuffer;
 }
 }
 
 
-void TextBuffer::appendText(FontHandle _fontHandle, const char* _string)
+void TextBuffer::appendText(FontHandle _fontHandle, const char* _string, const char* _end)
 {
 {
 	GlyphInfo glyph;
 	GlyphInfo glyph;
 	const FontInfo& font = m_fontManager->getFontInfo(_fontHandle);
 	const FontInfo& font = m_fontManager->getFontInfo(_fontHandle);
@@ -224,16 +220,17 @@ void TextBuffer::appendText(FontHandle _fontHandle, const char* _string)
 	{
 	{
 		m_originX = m_penX;
 		m_originX = m_penX;
 		m_originY = m_penY;
 		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;
 	CodePoint codepoint = 0;
 	uint32_t state = 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) )
 			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;
 	GlyphInfo glyph;
 	const FontInfo& font = m_fontManager->getFontInfo(_fontHandle);
 	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_originX = m_penX;
 		m_originY = m_penY;
 		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;
 		m_lineGap = 0;
 	}
 	}
+	if( _end == NULL)
+	{
+		_end = _string + wcslen(_string);
+	}
+	BX_CHECK(_end >= _string);
 
 
-	for (uint32_t ii = 0, end = wcslen(_string); ii < end; ++ii)
+	for (const wchar_t* _current = _string; _current < _end; ++_current)
 	{
 	{
-		uint32_t _codePoint = _string[ii];
+		uint32_t _codePoint = *_current;
 		if (m_fontManager->getGlyphInfo(_fontHandle, _codePoint, glyph) )
 		if (m_fontManager->getGlyphInfo(_fontHandle, _codePoint, glyph) )
 		{
 		{
 			appendGlyph(_codePoint, font, glyph);
 			appendGlyph(_codePoint, font, glyph);
@@ -282,6 +281,11 @@ void TextBuffer::appendText(FontHandle _fontHandle, const wchar_t* _string)
 
 
 void TextBuffer::appendAtlasFace(uint16_t _faceIndex)
 void TextBuffer::appendAtlasFace(uint16_t _faceIndex)
 {
 {
+	if( m_vertexCount/4 >= MAX_BUFFERED_CHARACTERS)
+	{
+		return;
+	}
+
 	float x0 = m_penX;
 	float x0 = m_penX;
 	float y0 = m_penY;
 	float y0 = m_penY;
 	float x1 = x0 + (float)m_fontManager->getAtlas()->getTextureSize();
 	float x1 = x0 + (float)m_fontManager->getAtlas()->getTextureSize();
@@ -306,29 +310,40 @@ void TextBuffer::appendAtlasFace(uint16_t _faceIndex)
 
 
 void TextBuffer::clearTextBuffer()
 void TextBuffer::clearTextBuffer()
 {
 {
+	m_penX = 0;
+	m_penY = 0;
+	m_originX = 0;
+	m_originY = 0;
+
 	m_vertexCount = 0;
 	m_vertexCount = 0;
 	m_indexCount = 0;
 	m_indexCount = 0;
 	m_lineStartIndex = 0;
 	m_lineStartIndex = 0;
 	m_lineAscender = 0;
 	m_lineAscender = 0;
 	m_lineDescender = 0;
 	m_lineDescender = 0;
+	m_lineGap = 0;
 	m_rectangle.width = 0;
 	m_rectangle.width = 0;
 	m_rectangle.height = 0;
 	m_rectangle.height = 0;
 }
 }
 
 
 void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const GlyphInfo& _glyphInfo)
 void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const GlyphInfo& _glyphInfo)
-{
+{	
+	if( m_vertexCount/4 >= MAX_BUFFERED_CHARACTERS)
+	{
+		return;
+	}
+
 	if (_codePoint == L'\n')
 	if (_codePoint == L'\n')
 	{
 	{
 		m_penX = m_originX;
 		m_penX = m_originX;
-		m_penY -= m_lineDescender;
-		m_penY += m_lineGap;
-		m_lineDescender = 0;
-		m_lineAscender = 0;
+		m_penY += m_lineGap + m_lineAscender -m_lineDescender;
+		m_lineGap = _font.lineGap;
+		m_lineDescender = _font.descender;
+		m_lineAscender = _font.ascender;
 		m_lineStartIndex = m_vertexCount;
 		m_lineStartIndex = m_vertexCount;
-
 		return;
 		return;
 	}
 	}
 
 
+	//is there a change of font size that require the text on the left to be centered again ?
 	if (_font.ascender > m_lineAscender
 	if (_font.ascender > m_lineAscender
 		|| (_font.descender < m_lineDescender) )
 		|| (_font.descender < m_lineDescender) )
 	{
 	{
@@ -340,14 +355,12 @@ void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const
 
 
 		float txtDecals = (_font.ascender - m_lineAscender);
 		float txtDecals = (_font.ascender - m_lineAscender);
 		m_lineAscender = _font.ascender;
 		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();
 	GlyphInfo& blackGlyph = m_fontManager->getBlackGlyph();
 
 
@@ -355,9 +368,9 @@ void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const
 	&&  m_backgroundColor & 0xFF000000)
 	&&  m_backgroundColor & 0xFF000000)
 	{
 	{
 		float x0 = (m_penX - kerning);
 		float x0 = (m_penX - kerning);
-		float y0 = (m_penY - m_lineAscender);
+		float y0 = (m_penY);
 		float x1 = ( (float)x0 + (_glyphInfo.advance_x) );
 		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) );
 		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)
 	&&  m_underlineColor & 0xFF000000)
 	{
 	{
 		float x0 = (m_penX - kerning);
 		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 x1 = ( (float)x0 + (_glyphInfo.advance_x) );
 		float y1 = y0 + _font.underlineThickness;
 		float y1 = y0 + _font.underlineThickness;
 
 
@@ -405,7 +418,7 @@ void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const
 	&&  m_overlineColor & 0xFF000000)
 	&&  m_overlineColor & 0xFF000000)
 	{
 	{
 		float x0 = (m_penX - kerning);
 		float x0 = (m_penX - kerning);
-		float y0 = (m_penY - _font.ascender);
+		float y0 = (m_penY);
 		float x1 = ( (float)x0 + (_glyphInfo.advance_x) );
 		float x1 = ( (float)x0 + (_glyphInfo.advance_x) );
 		float y1 = y0 + _font.underlineThickness;
 		float y1 = y0 + _font.underlineThickness;
 
 
@@ -430,7 +443,7 @@ void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const
 	&&  m_strikeThroughColor & 0xFF000000)
 	&&  m_strikeThroughColor & 0xFF000000)
 	{
 	{
 		float x0 = (m_penX - kerning);
 		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 x1 = ( (float)x0 + (_glyphInfo.advance_x) );
 		float y1 = y0 + _font.underlineThickness;
 		float y1 = y0 + _font.underlineThickness;
 
 
@@ -451,9 +464,8 @@ void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const
 		m_indexCount += 6;
 		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 x1 = (x0 + _glyphInfo.width);
 	float y1 = (y0 + _glyphInfo.height);
 	float y1 = (y0 + _glyphInfo.height);
 
 
@@ -479,9 +491,9 @@ void TextBuffer::appendGlyph(CodePoint _codePoint, const FontInfo& _font, const
 		m_rectangle.width = m_penX;
 		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);
 	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");
 	BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
 	BufferCache& bc = m_textBuffers[_handle.idx];
 	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");
 	BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
 	BufferCache& bc = m_textBuffers[_handle.idx];
 	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)
 void TextBufferManager::appendAtlasFace(TextBufferHandle _handle, uint16_t _faceIndex)
@@ -841,88 +853,6 @@ void TextBufferManager::clearTextBuffer(TextBufferHandle _handle)
 	bc.textBuffer->clearTextBuffer();
 	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
 TextRectangle TextBufferManager::getRectangle(TextBufferHandle _handle) const
 {
 {
 	BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
 	BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");

+ 5 - 11
examples/common/font/text_buffer_manager.h

@@ -55,26 +55,20 @@ public:
 	void setPenPosition(TextBufferHandle _handle, float _x, float _y);
 	void setPenPosition(TextBufferHandle _handle, float _x, float _y);
 
 
 	/// append an ASCII/utf-8 string to the buffer using current pen position and color
 	/// 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
 	/// 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
 	/// append a whole face of the atlas cube, mostly used for debugging and visualizing atlas
 	void appendAtlasFace(TextBufferHandle _handle, uint16_t _faceIndex);
 	void appendAtlasFace(TextBufferHandle _handle, uint16_t _faceIndex);
 
 
 	/// Clear the text buffer and reset its state (pen/color)
 	/// Clear the text buffer and reset its state (pen/color)
 	void clearTextBuffer(TextBufferHandle _handle);
 	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)
 	/// Return the rectangular size of the current text buffer (including all its content)
-	TextRectangle getRectangle(TextBufferHandle _handle) const;
-
+	TextRectangle getRectangle(TextBufferHandle _handle) const;	
+	
 private:
 private:
 	struct BufferCache
 	struct BufferCache
 	{
 	{