X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Frendering%2Fbasic%2Ftext-basic-renderer.cpp;h=ac958924c5ce2405a456cd2b23d81788082b6154;hp=4521d942786789c57f1c1b6934d0733d02c2dd65;hb=35418f7ea9e356d49750cdc0bdff5c31b7d86539;hpb=eea53605c5acb244aebb72d75bdd9b3a68a9678a 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;