From 35418f7ea9e356d49750cdc0bdff5c31b7d86539 Mon Sep 17 00:00:00 2001
From: Paul Wisbey
Date: Tue, 10 Mar 2015 09:26:05 +0000
Subject: [PATCH] BasicRenderer reworked for RGBA8888
Change-Id: I39ea80c1c862adf8d5b5e715bc97f425c66da386
---
.../text/rendering/basic/text-basic-renderer.cpp | 289 +++++++++++++--------
1 file changed, 187 insertions(+), 102 deletions(-)
diff --git a/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.cpp b/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.cpp
index 4521d94..ac95892 100644
--- a/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.cpp
+++ b/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.cpp
@@ -20,6 +20,7 @@
// INTERNAL INCLUDES
#include
+#include
#include
#include
#include
@@ -50,9 +51,9 @@ struct TextureCoordinates
Vector2 bottomRight;
};
-struct AtlasHelperGlyph
+struct AtlasGlyph
{
- AtlasHelperGlyph()
+ AtlasGlyph()
: fontId( 0 ),
index( 0 ),
xOffset( 0 ),
@@ -61,16 +62,18 @@ struct AtlasHelperGlyph
{
}
- AtlasHelperGlyph( FontId id,
- GlyphIndex glyphIndex,
- std::size_t offset,
- std::size_t widthPixels,
- std::size_t heightPixels )
+ AtlasGlyph( FontId id,
+ GlyphIndex glyphIndex,
+ std::size_t offset,
+ std::size_t widthPixels,
+ std::size_t heightPixels,
+ BufferImage bitmap )
: fontId( id ),
index( glyphIndex ),
xOffset( offset ),
width( widthPixels ),
- height( heightPixels )
+ height( heightPixels ),
+ mBitmap( bitmap )
{
}
@@ -79,140 +82,179 @@ struct AtlasHelperGlyph
std::size_t xOffset;
std::size_t width;
std::size_t height;
+ BufferImage mBitmap;
TextureCoordinates coords;
};
-struct AtlasHelper
+} // unnamed namespace
+
+struct BasicRenderer::Impl
{
- AtlasHelper()
- : mWidth( 0.0f ),
- mHeight( 0.0f )
+ /**
+ * @brief Create the renderer implementation.
+ */
+ Impl()
+ : mWidthL8( 0.0f ),
+ mHeightL8( 0.0f ),
+ mWidthBGRA8888( 0.0f ),
+ mHeightBGRA8888( 0.0f )
{
mFontClient = TextAbstraction::FontClient::Get();
}
- void Reset()
+ /**
+ * @brief Reset the previous glyph calculations.
+ *
+ * @param[in] size The glyph space to reserve.
+ */
+ void Reset( std::size_t size )
{
- mWidth = 0.0f;
- mHeight = 0.0f;
+ mWidthL8 = 0.0f;
+ mHeightL8 = 0.0f;
+ mWidthBGRA8888 = 0.0f;
+ mHeightBGRA8888 = 0.0f;
mGlyphs.clear();
- }
-
- void Reserve( std::size_t size )
- {
mGlyphs.reserve( size );
+ mAtlasL8.Reset();
+ mAtlasBGRA8888.Reset();
}
- bool GlyphFound( FontId fontId, GlyphIndex index ) const
+ /**
+ * @brief Ccreate an Atlas, uploading the necessary glyph bitmaps
+ *
+ * @param[in] glyphs The glyphs to upload.
+ */
+ void CreateAtlases( const Vector& glyphs )
{
- for( unsigned int i=0; i 0 &&
+ height > 0 ) // skip whitespace
{
- return true;
+ if( !GlyphFound( glyphs[i].fontId, glyphs[i].index ) )
+ {
+ AddGlyph( glyphs[i] );
+ }
}
}
- return false;
+ mAtlasL8 = CreateAtlas( mWidthL8, mHeightL8, Pixel::L8 );
+ mAtlasBGRA8888 = CreateAtlas( mWidthBGRA8888, mHeightBGRA8888, Pixel::BGRA8888 );
}
- void AddGlyph( const GlyphInfo& glyphInfo )
+ Atlas CreateAtlas( unsigned int width, unsigned int height, Pixel::Format format )
{
- mGlyphs.push_back( AtlasHelperGlyph( glyphInfo.fontId, glyphInfo.index, mWidth, glyphInfo.width, glyphInfo.height ) );
+ Atlas atlas;
- mWidth += glyphInfo.width + PADDING;
- if( mHeight < glyphInfo.height + PADDING )
+ if( width > 0 && height > 0 )
{
- mHeight = glyphInfo.height + PADDING;
- }
- }
+ atlas = Atlas::New( width, height, format );
- Atlas CreateAtlas()
- {
- Atlas atlas = Atlas::New( mWidth, mHeight, Pixel::L8 );
+ for( unsigned int i=0; i(glyph.xOffset) / static_cast(mWidth);
- coords.topLeft.y = 0.0f;
- coords.topRight.x = static_cast(glyph.xOffset + glyph.width) / static_cast(mWidth);
- coords.topRight.y = 0.0f;
- coords.bottomLeft.x = static_cast(glyph.xOffset) / static_cast(mWidth);
- coords.bottomLeft.y = static_cast(glyph.height) / static_cast(mHeight);
- coords.bottomRight.x = static_cast(glyph.xOffset + glyph.width) / static_cast(mWidth);
- coords.bottomRight.y = static_cast(glyph.height) / static_cast(mHeight);
+ const Pixel::Format glyphFormat = glyph.mBitmap.GetPixelFormat();
+
+ if( format == glyphFormat )
+ {
+ atlas.Upload( glyph.mBitmap, glyph.xOffset, 0 );
+
+ TextureCoordinates& coords = glyph.coords;
+ coords.topLeft.x = static_cast(glyph.xOffset) / static_cast(width);
+ coords.topLeft.y = 0.0f;
+ coords.topRight.x = static_cast(glyph.xOffset + glyph.width) / static_cast(width);
+ coords.topRight.y = 0.0f;
+ coords.bottomLeft.x = static_cast(glyph.xOffset) / static_cast(width);
+ coords.bottomLeft.y = static_cast(glyph.height) / static_cast(height);
+ coords.bottomRight.x = static_cast(glyph.xOffset + glyph.width) / static_cast(width);
+ coords.bottomRight.y = static_cast(glyph.height) / static_cast(height);
+ }
+ }
}
return atlas;
}
- void GetTextureCoordinates( FontId fontId, GlyphIndex index, TextureCoordinates& coords )
+ /**
+ * @brief Check whether we already have the glyph.
+ */
+ bool GlyphFound( FontId fontId, GlyphIndex index ) const
{
for( unsigned int i=0; i mGlyphs;
+ if( Pixel::L8 == format )
+ {
+ mGlyphs.push_back( AtlasGlyph( glyphInfo.fontId, glyphInfo.index, mWidthL8, glyphInfo.width, glyphInfo.height, bitmap ) );
- TextAbstraction::FontClient mFontClient;
-};
+ // Increase the Atlas width/height
+ mWidthL8 += glyphInfo.width + PADDING;
+ if( mHeightL8 < glyphInfo.height + PADDING )
+ {
+ mHeightL8 = glyphInfo.height + PADDING;
+ }
+ }
+ else if ( Pixel::BGRA8888 == format )
+ {
+ mGlyphs.push_back( AtlasGlyph( glyphInfo.fontId, glyphInfo.index, mWidthBGRA8888, glyphInfo.width, glyphInfo.height, bitmap ) );
-} // unnamed namespace
+ // A separate Atlas is used for color Emojis
+ mWidthBGRA8888 += glyphInfo.width + PADDING;
+ if( mHeightBGRA8888 < glyphInfo.height + PADDING )
+ {
+ mHeightBGRA8888 = glyphInfo.height + PADDING;
+ }
+ }
+ }
-struct BasicRenderer::Impl
-{
/**
- * @brief Ccreate an Atlas, uploading the necessary glyph bitmaps
- *
- * @param[in] glyphs The glyphs to upload.
+ * @brief Get the texture coordinates for a glyph.
*/
- Atlas CreateAtlas( const Vector& glyphs )
+ bool GetTextureCoordinates( Pixel::Format format, FontId fontId, GlyphIndex index, TextureCoordinates& coords )
{
- AtlasHelper& helper = mAtlasHelper;
-
- // Clear previous atlas
- helper.Reset();
- helper.Reserve( glyphs.Count() );
-
- for( unsigned int i=0; i 0 &&
- height > 0 ) // skip whitespace
+ const Pixel::Format glyphFormat = glyph.mBitmap.GetPixelFormat();
+
+ if( format == glyphFormat &&
+ fontId == glyph.fontId &&
+ index == glyph.index )
{
- if( !helper.GlyphFound( glyphs[i].fontId, glyphs[i].index ) )
- {
- helper.AddGlyph( glyphs[i] );
- }
+ coords = glyph.coords;
+ return true;
}
}
- // Uploads the bitmaps to Dali
- return helper.CreateAtlas();
+ return false;
}
/**
@@ -222,7 +264,7 @@ struct BasicRenderer::Impl
* @param[in] positions The 2D positions of the glyphs.
* @param[in] image The material uses this as a diffuse texture.
*/
- Mesh CreateMesh( const Vector& glyphs, const std::vector& positions, Image image )
+ Mesh CreateMesh( const Vector& glyphs, const std::vector& positions, Pixel::Format format, Image image )
{
MeshData::VertexContainer vertices( 4 * glyphs.Count() ); // 1 quad per glyph
@@ -240,15 +282,16 @@ struct BasicRenderer::Impl
const Vector2& position = positions[i];
TextureCoordinates coords;
- mAtlasHelper.GetTextureCoordinates( glyphs[i].fontId, glyphs[i].index, coords );
-
- vertices[ i*4 + 0 ] = MeshData::Vertex( Vector3( position.x + 0.0f*width, position.y + 0.0f*height, 0.0f ), coords.topLeft, Vector3( 1.0f, 0.0f, 0.0f ) );
- vertices[ i*4 + 1 ] = MeshData::Vertex( Vector3( position.x + 1.0f*width, position.y + 0.0f*height, 0.0f ), coords.topRight, Vector3( 1.0f, 1.0f, 0.0f ) );
- vertices[ i*4 + 2 ] = MeshData::Vertex( Vector3( position.x + 0.0f*width, position.y + 1.0f*height, 0.0f ), coords.bottomLeft, Vector3( 0.0f, 1.0f, 0.0f ) );
- vertices[ i*4 + 3 ] = MeshData::Vertex( Vector3( position.x + 1.0f*width, position.y + 1.0f*height, 0.0f ), coords.bottomRight, Vector3( 0.0f, 0.0f, 1.0f ) );
+ if( GetTextureCoordinates( format, glyphs[i].fontId, glyphs[i].index, coords ) )
+ {
+ vertices[ i*4 + 0 ] = MeshData::Vertex( Vector3( position.x + 0.0f*width, position.y + 0.0f*height, 0.0f ), coords.topLeft, Vector3( 1.0f, 0.0f, 0.0f ) );
+ vertices[ i*4 + 1 ] = MeshData::Vertex( Vector3( position.x + 1.0f*width, position.y + 0.0f*height, 0.0f ), coords.topRight, Vector3( 1.0f, 1.0f, 0.0f ) );
+ vertices[ i*4 + 2 ] = MeshData::Vertex( Vector3( position.x + 0.0f*width, position.y + 1.0f*height, 0.0f ), coords.bottomLeft, Vector3( 0.0f, 1.0f, 0.0f ) );
+ vertices[ i*4 + 3 ] = MeshData::Vertex( Vector3( position.x + 1.0f*width, position.y + 1.0f*height, 0.0f ), coords.bottomRight, Vector3( 0.0f, 0.0f, 1.0f ) );
- faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 3 ); faces.push_back( i*4 + 1 );
- faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 2 ); faces.push_back( i*4 + 3 );
+ faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 3 ); faces.push_back( i*4 + 1 );
+ faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 2 ); faces.push_back( i*4 + 3 );
+ }
}
}
@@ -269,7 +312,18 @@ struct BasicRenderer::Impl
RenderableActor mActor; ///< The actor which renders the text
- AtlasHelper mAtlasHelper; ///< A helper class for storing atlas positions etc.
+ Atlas mAtlasL8;
+ unsigned int mWidthL8;
+ unsigned int mHeightL8;
+
+ // A separate Atlas is used for color Emojis
+ Atlas mAtlasBGRA8888;
+ unsigned int mWidthBGRA8888;
+ unsigned int mHeightBGRA8888;
+
+ std::vector mGlyphs;
+
+ TextAbstraction::FontClient mFontClient;
};
Text::RendererPtr BasicRenderer::New()
@@ -279,6 +333,7 @@ Text::RendererPtr BasicRenderer::New()
RenderableActor BasicRenderer::Render( Text::ViewInterface& view )
{
+ // Remove the previous text
UnparentAndReset( mImpl->mActor );
Text::Length numberOfGlyphs = view.GetNumberOfGlyphs();
@@ -294,16 +349,46 @@ RenderableActor BasicRenderer::Render( Text::ViewInterface& view )
positions.resize( numberOfGlyphs );
view.GetGlyphPositions( &positions[0], 0, numberOfGlyphs );
- Atlas atlas = mImpl->CreateAtlas( glyphs );
+ mImpl->CreateAtlases( glyphs );
+
+ MeshActor actorL8;
+ if( mImpl->mAtlasL8 )
+ {
+ actorL8 = MeshActor::New( mImpl->CreateMesh( glyphs, positions, Pixel::L8, mImpl->mAtlasL8 ) );
+ actorL8.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
- MeshActor actor = MeshActor::New( mImpl->CreateMesh( glyphs, positions, atlas ) );
- actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
- actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
+ ShaderEffect shader = BasicShader::New();
+ actorL8.SetShaderEffect( shader );
+ }
- ShaderEffect shader = BasicShader::New();
- actor.SetShaderEffect( shader );
+ MeshActor actorBGRA8888;
+ if( mImpl->mAtlasBGRA8888 )
+ {
+ actorBGRA8888 = MeshActor::New( mImpl->CreateMesh( glyphs, positions, Pixel::BGRA8888, mImpl->mAtlasBGRA8888 ) );
+ actorBGRA8888.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
- mImpl->mActor = actor;
+ ShaderEffect shader = BasicShader::New();
+ actorBGRA8888.SetShaderEffect( shader );
+ }
+
+ // If we have both monochrome & color glyphs, two mesh actors are returned in a container
+ if( actorL8 && actorBGRA8888 )
+ {
+ mImpl->mActor = ImageActor::New();
+ mImpl->mActor.Add( actorL8 );
+ mImpl->mActor.Add( actorBGRA8888 );
+ }
+ else
+ {
+ if( actorL8 )
+ {
+ mImpl->mActor = actorL8;
+ }
+ else if( actorBGRA8888 )
+ {
+ mImpl->mActor = actorBGRA8888;
+ }
+ }
}
return mImpl->mActor;
--
2.7.4