X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Frendering%2Fatlas%2Ftext-atlas-renderer.cpp;h=b1724d07b89f579fa2573d89f74d7a715d030099;hp=016284aac8a29a0399bff82cb8b879f8bc38e01e;hb=3799c74b38bf0e5d0c375d5666d30961ac07acde;hpb=0a2f5e1551be90466c7b64173bd750c4009c744e diff --git a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp index 016284a..b1724d0 100644 --- a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp @@ -19,19 +19,18 @@ #include // EXTERNAL INCLUDES -#include #include #include +#include + // INTERNAL INCLUDES #include +#include #include #include #include -#include -#if defined(DEBUG_ENABLED) -Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_ATLAS_RENDERER"); -#endif +//#include using namespace Dali; using namespace Dali::Toolkit; @@ -39,13 +38,72 @@ using namespace Dali::Toolkit::Text; namespace { +#if defined(DEBUG_ENABLED) + Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_RENDERING"); +#endif + const float ZERO( 0.0f ); const float HALF( 0.5f ); const float ONE( 1.0f ); const float TWO( 2.0f ); - const Vector2 DEFAULT_ATLAS_SIZE( 512.0f, 512.0f ); - const Vector2 DEFAULT_BLOCK_SIZE( 16.0f, 16.0f ); - const Vector2 PADDING( 4.0f, 4.0f ); // Allow for variation in font glyphs + const uint32_t DEFAULT_ATLAS_WIDTH = 512u; + const uint32_t DEFAULT_ATLAS_HEIGHT = 512u; + + #define MAKE_SHADER(A)#A + + const char* VERTEX_SHADER = MAKE_SHADER( + attribute mediump vec2 aPosition; + attribute mediump vec2 aTexCoord; + uniform mediump mat4 uMvpMatrix; + uniform mediump vec3 uSize; + varying mediump vec2 vTexCoord; + + void main() + { + mediump vec4 position = vec4( aPosition, 0.0, 1.0 ); + position.xyz *= uSize; + gl_Position = uMvpMatrix * position; + vTexCoord = aTexCoord; + } + ); + + const char* FRAGMENT_SHADER = MAKE_SHADER( + uniform sampler2D sTexture; + varying mediump vec2 vTexCoord; + + void main() + { + //gl_FragColor = vec4( 1.0 ); + gl_FragColor = texture2D( sTexture, vTexCoord ); + } + ); + + const char* VERTEX_SHADER_SHADOW = MAKE_SHADER( + attribute mediump vec2 aPosition; + attribute mediump vec2 aTexCoord; + uniform mediump vec3 uSize; + varying mediump vec2 vTexCoord; + + void main() + { + mediump vec4 position = vec4( aPosition, 0.0, 1.0 ); + position.xyz *= uSize; + gl_Position = position; + vTexCoord = aTexCoord; + } + ); + + const char* FRAGMENT_SHADER_SHADOW = MAKE_SHADER( + uniform sampler2D sTexture; + uniform lowp vec4 uColor; + varying mediump vec2 vTexCoord; + + void main() + { + mediump vec4 color = texture2D( sTexture, vTexCoord ); + gl_FragColor = vec4(uColor.rgb, uColor.a*color.r); + } + ); } struct AtlasRenderer::Impl : public ConnectionTracker @@ -61,7 +119,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker { Vector4 mColor; uint32_t mAtlasId; - MeshData mMeshData; + AtlasManager::Mesh2D mMesh; FrameBufferImage mBuffer; bool mIsUnderline; }; @@ -85,21 +143,21 @@ struct AtlasRenderer::Impl : public ConnectionTracker struct MaxBlockSize { FontId mFontId; - Vector2 mNeededBlockSize; + uint32_t mNeededBlockWidth; + uint32_t mNeededBlockHeight; }; Impl() { mGlyphManager = AtlasGlyphManager::Get(); mFontClient = TextAbstraction::FontClient::Get(); - mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_SIZE, DEFAULT_BLOCK_SIZE ); - mBasicShader = BasicShader::New(); - mBgraShader = BgraShader::New(); - mBasicShadowShader = BasicShadowShader::New(); - - mFace.reserve( 6u ); - mFace.push_back( 0 ); mFace.push_back( 2u ); mFace.push_back( 1u ); - mFace.push_back( 1u ); mFace.push_back( 2u ); mFace.push_back( 3u ); + + mQuadVertexFormat[ "aPosition" ] = Property::VECTOR2; + mQuadVertexFormat[ "aTexCoord" ] = Property::VECTOR2; + mQuadIndexFormat[ "indices" ] = Property::UNSIGNED_INTEGER; + + mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ); + mShadowShader = Shader::New( VERTEX_SHADER_SHADOW, FRAGMENT_SHADER_SHADOW, Dali::Shader::HINT_MODIFIES_GEOMETRY ); } void AddGlyphs( const std::vector& positions, @@ -117,7 +175,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker float currentUnderlinePosition = ZERO; float currentUnderlineThickness = underlineHeight; - + uint32_t currentBlockSize = 0; FontId lastFontId = 0; Style style = STYLE_NORMAL; @@ -134,9 +192,9 @@ struct AtlasRenderer::Impl : public ConnectionTracker CalculateBlocksSize( glyphs ); - for ( uint32_t i = 0; i < glyphs.Size(); ++i ) + for( uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i ) { - GlyphInfo glyph = glyphs[ i ]; + const GlyphInfo& glyph = glyphs[ i ]; // No operation for white space if ( glyph.width && glyph.height ) @@ -147,8 +205,8 @@ struct AtlasRenderer::Impl : public ConnectionTracker // We need to fetch fresh font underline metrics FontMetrics fontMetrics; mFontClient.GetFontMetrics( glyph.fontId, fontMetrics ); - currentUnderlinePosition = FontMetricsRoundUp( fabsf( fontMetrics.underlinePosition ) ); - float descender = FontMetricsRoundUp( fabsf( fontMetrics.descender ) ); + currentUnderlinePosition = ceil( fabsf( fontMetrics.underlinePosition ) ); + float descender = ceil( fabsf( fontMetrics.descender ) ); if ( underlineHeight == ZERO ) { @@ -161,7 +219,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker } else { - currentUnderlineThickness = FontMetricsRoundUp( currentUnderlineThickness ); + currentUnderlineThickness = ceil( currentUnderlineThickness ); } } @@ -177,14 +235,14 @@ struct AtlasRenderer::Impl : public ConnectionTracker } } - Vector2 position = positions[ i ]; - MeshData newMeshData; + const Vector2& position = positions[ i ]; + AtlasManager::Mesh2D newMesh; mGlyphManager.Cached( glyph.fontId, glyph.index, slot ); if ( slot.mImageId ) { // This glyph already exists so generate mesh data plugging in our supplied position - mGlyphManager.GenerateMeshData( slot.mImageId, position, newMeshData ); + mGlyphManager.GenerateMeshData( slot.mImageId, position, newMesh ); mImageIds.PushBack( slot.mImageId ); } else @@ -197,35 +255,62 @@ struct AtlasRenderer::Impl : public ConnectionTracker { if ( mBlockSizes[ j ].mFontId == glyph.fontId ) { - mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_SIZE, mBlockSizes[ j ].mNeededBlockSize ); + currentBlockSize = j; + mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_WIDTH, + DEFAULT_ATLAS_HEIGHT, + mBlockSizes[ j ].mNeededBlockWidth, + mBlockSizes[ j ].mNeededBlockHeight ); } } } - // Glyph doesn't currently exist in atlas so upload + // Create a new image for the glyph BufferImage bitmap = mFontClient.CreateBitmap( glyph.fontId, glyph.index ); + if ( bitmap ) + { + // Ensure that the next image will fit into the current block size + bool setSize = false; + if ( bitmap.GetWidth() > mBlockSizes[ currentBlockSize ].mNeededBlockWidth ) + { + setSize = true; + mBlockSizes[ currentBlockSize ].mNeededBlockWidth = bitmap.GetWidth(); + } + if ( bitmap.GetHeight() > mBlockSizes[ currentBlockSize ].mNeededBlockHeight ) + { + setSize = true; + mBlockSizes[ currentBlockSize ].mNeededBlockHeight = bitmap.GetHeight(); + } + + if ( setSize ) + { + mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_WIDTH, + DEFAULT_ATLAS_HEIGHT, + mBlockSizes[ currentBlockSize ].mNeededBlockWidth, + mBlockSizes[ currentBlockSize ].mNeededBlockHeight ); + } - // Locate a new slot for our glyph - mGlyphManager.Add( glyph, bitmap, slot ); + // Locate a new slot for our glyph + mGlyphManager.Add( glyph, bitmap, slot ); - // Generate mesh data for this quad, plugging in our supplied position - if ( slot.mImageId ) - { - mGlyphManager.GenerateMeshData( slot.mImageId, position, newMeshData ); - mImageIds.PushBack( slot.mImageId ); + // Generate mesh data for this quad, plugging in our supplied position + if ( slot.mImageId ) + { + mGlyphManager.GenerateMeshData( slot.mImageId, position, newMesh ); + mImageIds.PushBack( slot.mImageId ); + } } } // Find an existing mesh data object to attach to ( or create a new one, if we can't find one using the same atlas) StitchTextMesh( meshContainer, - newMeshData, + newMesh, extents, textColor, position.y + glyph.yBearing, currentUnderlinePosition, currentUnderlineThickness, slot ); + lastFontId = glyph.fontId; } - lastFontId = glyph.fontId; } if ( underlineEnabled ) @@ -239,30 +324,12 @@ struct AtlasRenderer::Impl : public ConnectionTracker { for ( std::vector< MeshRecord >::iterator mIt = meshContainer.begin(); mIt != meshContainer.end(); ++mIt ) { - MeshActor actor = MeshActor::New( Mesh::New( mIt->mMeshData ) ); - actor.SetColor( mIt->mColor ); - if ( mIt->mIsUnderline ) - { - actor.SetColorMode( USE_OWN_COLOR ); - } - else - { - actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); - } + Actor actor = CreateMeshActor( *mIt ); - // Check to see what pixel format the shader should be - if ( mGlyphManager.GetPixelFormat( mIt->mAtlasId ) == Pixel::L8 ) + // Create an effect if necessary + if ( style == STYLE_DROP_SHADOW ) { - // Create an effect if necessary - if ( style == STYLE_DROP_SHADOW ) - { - actor.Add( GenerateShadow( *mIt, shadowOffset, shadowColor ) ); - } - actor.SetShaderEffect( mBasicShader ); - } - else - { - actor.SetShaderEffect( mBgraShader ); + actor.Add( GenerateShadow( *mIt, shadowOffset, shadowColor ) ); } if ( mActor ) @@ -278,7 +345,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker } #if defined(DEBUG_ENABLED) Toolkit::AtlasGlyphManager::Metrics metrics = mGlyphManager.GetMetrics(); - DALI_LOG_INFO( gLogFilter, Debug::Concise, "TextAtlasRenderer::GlyphManager::GlyphCount: %i, AtlasCount: %i, TextureMemoryUse: %iK\n", + DALI_LOG_INFO( gLogFilter, Debug::General, "TextAtlasRenderer::GlyphManager::GlyphCount: %i, AtlasCount: %i, TextureMemoryUse: %iK\n", metrics.mGlyphCount, metrics.mAtlasMetrics.mAtlasCount, metrics.mAtlasMetrics.mTextureMemoryUsed / 1024 ); @@ -287,18 +354,48 @@ struct AtlasRenderer::Impl : public ConnectionTracker DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Atlas [%i] %sPixels: %s Size: %ix%i, BlockSize: %ix%i, BlocksUsed: %i/%i\n", i + 1, i > 8 ? "" : " ", metrics.mAtlasMetrics.mAtlasMetrics[ i ].mPixelFormat == Pixel::L8 ? "L8 " : "BGRA", - metrics.mAtlasMetrics.mAtlasMetrics[ i ].mWidth, - metrics.mAtlasMetrics.mAtlasMetrics[ i ].mHeight, - metrics.mAtlasMetrics.mAtlasMetrics[ i ].mBlockWidth, - metrics.mAtlasMetrics.mAtlasMetrics[ i ].mBlockHeight, + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mSize.mWidth, + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mSize.mHeight, + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mSize.mBlockWidth, + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mSize.mBlockHeight, metrics.mAtlasMetrics.mAtlasMetrics[ i ].mBlocksUsed, metrics.mAtlasMetrics.mAtlasMetrics[ i ].mTotalBlocks ); } #endif } + Actor CreateMeshActor( const MeshRecord& meshRecord ) + { + PropertyBuffer quadVertices = PropertyBuffer::New( mQuadVertexFormat, meshRecord.mMesh.mVertices.Size() ); + PropertyBuffer quadIndices = PropertyBuffer::New( mQuadIndexFormat, meshRecord.mMesh.mIndices.Size() ); + quadVertices.SetData( const_cast< AtlasManager::Vertex2D* >( &meshRecord.mMesh.mVertices[ 0 ] ) ); + quadIndices.SetData( const_cast< unsigned int* >( &meshRecord.mMesh.mIndices[ 0 ] ) ); + + Geometry quadGeometry = Geometry::New(); + quadGeometry.AddVertexBuffer( quadVertices ); + quadGeometry.SetIndexBuffer( quadIndices ); + + Material material = mGlyphManager.GetMaterial( meshRecord.mAtlasId ); + Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, material ); + renderer.SetDepthIndex( 0 ); + Actor actor = Actor::New(); + actor.AddRenderer( renderer ); + actor.SetSize( 1.0f, 1.0f ); + actor.SetColor( meshRecord.mColor ); + + if ( meshRecord.mIsUnderline ) + { + actor.SetColorMode( USE_OWN_COLOR ); + } + else + { + actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + } + return actor; + } + void StitchTextMesh( std::vector< MeshRecord >& meshContainer, - MeshData& newMeshData, + AtlasManager::Mesh2D& newMesh, Vector< Extent >& extents, const Vector4& color, float baseLine, @@ -308,9 +405,8 @@ struct AtlasRenderer::Impl : public ConnectionTracker { if ( slot.mImageId ) { - MeshData::VertexContainer verts = newMeshData.GetVertices(); - float left = verts[ 0 ].x; - float right = verts[ 1 ].x; + float left = newMesh.mVertices[ 0 ].mPosition.x; + float right = newMesh.mVertices[ 1 ].mPosition.x; // Check to see if there's a mesh data object that references the same atlas ? uint32_t index = 0; @@ -319,7 +415,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker if ( slot.mAtlasId == mIt->mAtlasId && color == mIt->mColor ) { // Stitch the mesh to the existing mesh and adjust any extents - mGlyphManager.StitchMesh( mIt->mMeshData, newMeshData ); + mGlyphManager.StitchMesh( mIt->mMesh, newMesh ); AdjustExtents( extents, meshContainer, index, @@ -335,7 +431,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker // No mesh data object currently exists that references this atlas, so create a new one MeshRecord meshRecord; meshRecord.mAtlasId = slot.mAtlasId; - meshRecord.mMeshData = newMeshData; + meshRecord.mMesh = newMesh; meshRecord.mColor = color; meshRecord.mIsUnderline = false; meshContainer.push_back( meshRecord ); @@ -420,60 +516,37 @@ struct AtlasRenderer::Impl : public ConnectionTracker MaxBlockSize maxBlockSize; for ( uint32_t i = 0; i < glyphs.Size(); ++i ) { - // Get the fontId of this glyph and check to see if a max size exists? FontId fontId = glyphs[ i ].fontId; - float paddedWidth = glyphs[ i ].width + PADDING.x; - float paddedHeight = glyphs[ i ].height + PADDING.y; bool foundFont = false; - for ( uint32_t j = 0; j < mBlockSizes.size(); ++j ) { if ( mBlockSizes[ j ].mFontId == fontId ) { foundFont = true; - if ( mBlockSizes[ j ].mNeededBlockSize.x < paddedWidth ) - { - mBlockSizes[ j ].mNeededBlockSize.x = paddedWidth; - } - if ( mBlockSizes[ j ].mNeededBlockSize.y < paddedHeight ) - { - mBlockSizes[ j ].mNeededBlockSize.y = paddedHeight; - } } } - if ( !foundFont ) { - maxBlockSize.mNeededBlockSize = Vector2( paddedWidth, paddedHeight ); + FontMetrics fontMetrics; + mFontClient.GetFontMetrics( fontId, fontMetrics ); + maxBlockSize.mNeededBlockWidth = static_cast< uint32_t >( fontMetrics.height ); + maxBlockSize.mNeededBlockHeight = static_cast< uint32_t >( fontMetrics.height ); maxBlockSize.mFontId = fontId; mBlockSizes.push_back( maxBlockSize ); } } } - float FontMetricsRoundUp( float value ) - { - double integral_part; - if ( modf( value, &integral_part ) ) - { - return ( static_cast< float >( integral_part ) + 1.0f ); - } - else - { - return static_cast< float >( integral_part ); - } - } - void GenerateUnderlines( std::vector< MeshRecord>& meshRecords, Vector< Extent >& extents, const Vector4& underlineColor, const Vector4& textColor ) { - MeshData newMeshData; + AtlasManager::Mesh2D newMesh; + unsigned short faceIndex = 0; for ( Vector< Extent >::ConstIterator eIt = extents.Begin(); eIt != extents.End(); ++eIt ) { - MeshData::VertexContainer newVerts; - newVerts.reserve( 4u ); + AtlasManager::Vertex2D vert; uint32_t index = eIt->mMeshRecordIndex; Vector2 uv = mGlyphManager.GetAtlasSize( meshRecords[ index ].mAtlasId ); @@ -485,37 +558,45 @@ struct AtlasRenderer::Impl : public ConnectionTracker float tlx = eIt->mLeft; float brx = eIt->mRight; - newVerts.push_back( MeshData::Vertex( Vector3( tlx, baseLine, ZERO ), - Vector2::ZERO, - Vector3::ZERO ) ); - - newVerts.push_back( MeshData::Vertex( Vector3( brx, baseLine, ZERO ), - Vector2( u, ZERO ), - Vector3::ZERO ) ); - - newVerts.push_back( MeshData::Vertex( Vector3( tlx, baseLine + thickness, ZERO ), - Vector2( ZERO, v ), - Vector3::ZERO ) ); - - newVerts.push_back( MeshData::Vertex( Vector3( brx, baseLine + thickness, ZERO ), - Vector2( u, v ), - Vector3::ZERO ) ); - - newMeshData.SetVertices( newVerts ); - newMeshData.SetFaceIndices( mFace ); + vert.mPosition.x = tlx; + vert.mPosition.y = baseLine; + vert.mTexCoords.x = ZERO; + vert.mTexCoords.y = ZERO; + newMesh.mVertices.PushBack( vert ); + + vert.mPosition.x = brx; + vert.mPosition.y = baseLine; + vert.mTexCoords.x = u; + newMesh.mVertices.PushBack( vert ); + + vert.mPosition.x = tlx; + vert.mPosition.y = baseLine + thickness; + vert.mTexCoords.x = ZERO; + vert.mTexCoords.y = v; + newMesh.mVertices.PushBack( vert ); + + vert.mPosition.x = brx; + vert.mPosition.y = baseLine + thickness; + vert.mTexCoords.x = u; + newMesh.mVertices.PushBack( vert ); + + // Six indices in counter clockwise winding + newMesh.mIndices.PushBack( faceIndex + 1u ); + newMesh.mIndices.PushBack( faceIndex ); + newMesh.mIndices.PushBack( faceIndex + 2u ); + newMesh.mIndices.PushBack( faceIndex + 2u ); + newMesh.mIndices.PushBack( faceIndex + 3u ); + newMesh.mIndices.PushBack( faceIndex + 1u ); + faceIndex += 4; if ( underlineColor == textColor ) { - mGlyphManager.StitchMesh( meshRecords[ index ].mMeshData, newMeshData ); + mGlyphManager.StitchMesh( meshRecords[ index ].mMesh, newMesh ); } else { MeshRecord record; - newMeshData.SetMaterial( meshRecords[ index ].mMeshData.GetMaterial() ); - newMeshData.SetHasNormals( true ); - newMeshData.SetHasColor( false ); - newMeshData.SetHasTextureCoords( true ); - record.mMeshData = newMeshData; + record.mMesh = newMesh; record.mAtlasId = meshRecords[ index ].mAtlasId; record.mColor = underlineColor; record.mIsUnderline = true; @@ -524,34 +605,34 @@ struct AtlasRenderer::Impl : public ConnectionTracker } } - MeshActor GenerateShadow( MeshRecord& meshRecord, - const Vector2& shadowOffset, - const Vector4& shadowColor ) + Actor GenerateShadow( MeshRecord& meshRecord, + const Vector2& shadowOffset, + const Vector4& shadowColor ) { // Scan vertex buffer to determine width and height of effect buffer needed - MeshData::VertexContainer verts = meshRecord.mMeshData.GetVertices(); - float tlx = verts[ 0 ].x; - float tly = verts[ 0 ].y; + const Vector< AtlasManager::Vertex2D >& verts = meshRecord.mMesh.mVertices; + float tlx = verts[ 0 ].mPosition.x; + float tly = verts[ 0 ].mPosition.y; float brx = ZERO; float bry = ZERO; - for ( uint32_t i = 0; i < verts.size(); ++i ) + for ( uint32_t i = 0; i < verts.Size(); ++i ) { - if ( verts[ i ].x < tlx ) + if ( verts[ i ].mPosition.x < tlx ) { - tlx = verts[ i ].x; + tlx = verts[ i ].mPosition.x; } - if ( verts[ i ].y < tly ) + if ( verts[ i ].mPosition.y < tly ) { - tly = verts[ i ].y; + tly = verts[ i ].mPosition.y; } - if ( verts[ i ].x > brx ) + if ( verts[ i ].mPosition.x > brx ) { - brx = verts[ i ].x; + brx = verts[ i ].mPosition.x; } - if ( verts[ i ].y > bry ) + if ( verts[ i ].mPosition.y > bry ) { - bry = verts[ i ].y; + bry = verts[ i ].mPosition.y; } } @@ -563,76 +644,62 @@ struct AtlasRenderer::Impl : public ConnectionTracker // Create a buffer to render to meshRecord.mBuffer = FrameBufferImage::New( width, height ); - // Create a mesh actor to contain the post-effect render - MeshData::VertexContainer vertices; - MeshData::FaceIndices face; - - vertices.push_back( MeshData::Vertex( Vector3( tlx + shadowOffset.x, tly + shadowOffset.y, ZERO ), - Vector2::ZERO, - Vector3::ZERO ) ); - - vertices.push_back( MeshData::Vertex( Vector3( brx + shadowOffset.x, tly + shadowOffset.y, ZERO ), - Vector2( ONE, ZERO ), - Vector3::ZERO ) ); - - vertices.push_back( MeshData::Vertex( Vector3( tlx + shadowOffset.x, bry + shadowOffset.y, ZERO ), - Vector2( ZERO, ONE ), - Vector3::ZERO ) ); - - vertices.push_back( MeshData::Vertex( Vector3( brx + shadowOffset.x, bry + shadowOffset.y, ZERO ), - Vector2::ONE, - Vector3::ZERO ) ); - - MeshData meshData; - Material newMaterial = Material::New("effect buffer"); - newMaterial.SetDiffuseTexture( meshRecord.mBuffer ); - meshData.SetMaterial( newMaterial ); - meshData.SetVertices( vertices ); - meshData.SetFaceIndices( mFace ); - meshData.SetHasNormals( true ); - meshData.SetHasColor( false ); - meshData.SetHasTextureCoords( true ); - MeshActor actor = MeshActor::New( Mesh::New( meshData ) ); - actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); - actor.SetShaderEffect( mBgraShader ); - actor.SetFilterMode( FilterMode::LINEAR, FilterMode::LINEAR ); - actor.SetSortModifier( 0.1f ); // force behind main text - - // Create a sub actor to render once with normalized vertex positions - MeshData newMeshData; - MeshData::VertexContainer newVerts; - MeshData::FaceIndices newFaces; - MeshData::FaceIndices faces = meshRecord.mMeshData.GetFaces(); - for ( uint32_t i = 0; i < verts.size(); ++i ) - { - MeshData::Vertex vertex = verts[ i ]; - vertex.x = ( ( vertex.x - tlx ) * divWidth ) - ONE; - vertex.y = ( ( vertex.y - tly ) * divHeight ) - ONE; - newVerts.push_back( vertex ); - } - - // Reverse triangle winding order - uint32_t faceCount = faces.size() / 3; - for ( uint32_t i = 0; i < faceCount; ++i ) + // We will render a quad into this buffer + unsigned int indices[ 6 ] = { 1, 0, 2, 2, 3, 1 }; + PropertyBuffer quadVertices = PropertyBuffer::New( mQuadVertexFormat, 4u ); + PropertyBuffer quadIndices = PropertyBuffer::New( mQuadIndexFormat, sizeof(indices)/sizeof(indices[0]) ); + + AtlasManager::Vertex2D vertices[ 4 ] = { + { Vector2( tlx + shadowOffset.x, tly + shadowOffset.y ), Vector2( ZERO, ZERO ) }, + { Vector2( brx + shadowOffset.x, tly + shadowOffset.y ), Vector2( ONE, ZERO ) }, + { Vector2( tlx + shadowOffset.x, bry + shadowOffset.y ), Vector2( ZERO, ONE ) }, + { Vector2( brx + shadowOffset.x, bry + shadowOffset.y ), Vector2( ONE, ONE ) } }; + + quadVertices.SetData( vertices ); + quadIndices.SetData( indices ); + + Geometry quadGeometry = Geometry::New(); + quadGeometry.AddVertexBuffer( quadVertices ); + quadGeometry.SetIndexBuffer( quadIndices ); + + Sampler sampler = Sampler::New( meshRecord.mBuffer, "sTexture" ); + Material material = Material::New( mShader ); + material.AddSampler( sampler ); + + Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, material ); + renderer.SetDepthIndex( -1 ); + Actor actor = Actor::New(); + actor.AddRenderer( renderer ); + actor.SetSize( 1.0f, 1.0f ); + + // Create a sub actor to render the source with normalized vertex positions + Vector< AtlasManager::Vertex2D > normVertexList; + for ( uint32_t i = 0; i < verts.Size(); ++i ) { - uint32_t index = i * 3; - newFaces.push_back( faces[ index + 2 ] ); - newFaces.push_back( faces[ index + 1 ] ); - newFaces.push_back( faces[ index ] ); + AtlasManager::Vertex2D vertex = verts[ i ]; + vertex.mPosition.x = ( ( vertex.mPosition.x - tlx ) * divWidth ) - ONE; + vertex.mPosition.y = ( ( vertex.mPosition.y - tly ) * divHeight ) - ONE; + normVertexList.PushBack( vertex ); } - newMeshData.SetMaterial( meshRecord.mMeshData.GetMaterial() ); - newMeshData.SetVertices( newVerts ); - newMeshData.SetFaceIndices( newFaces ); - newMeshData.SetHasNormals( true ); - newMeshData.SetHasColor( false ); - newMeshData.SetHasTextureCoords( true ); - - MeshActor subActor = MeshActor::New( Mesh::New( newMeshData ) ); + PropertyBuffer normVertices = PropertyBuffer::New( mQuadVertexFormat, normVertexList.Size() ); + PropertyBuffer normIndices = PropertyBuffer::New( mQuadIndexFormat, meshRecord.mMesh.mIndices.Size() ); + normVertices.SetData( const_cast< AtlasManager::Vertex2D* >( &normVertexList[ 0 ] ) ); + normIndices.SetData( const_cast< unsigned int* >( &meshRecord.mMesh.mIndices[ 0 ] ) ); + + Geometry normGeometry = Geometry::New(); + normGeometry.AddVertexBuffer( normVertices ); + normGeometry.SetIndexBuffer( normIndices ); + + Material normMaterial = Material::New( mShadowShader ); + Sampler normSampler = mGlyphManager.GetSampler( meshRecord.mAtlasId ); + normMaterial.AddSampler( normSampler ); + Dali::Renderer normRenderer = Dali::Renderer::New( normGeometry, normMaterial ); + Actor subActor = Actor::New(); + subActor.AddRenderer( normRenderer ); + subActor.SetSize( 1.0f, 1.0f ); subActor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); subActor.SetColor( shadowColor ); - subActor.SetShaderEffect( mBasicShadowShader ); - subActor.SetFilterMode( FilterMode::NEAREST, FilterMode::NEAREST ); // Create a render task to render the effect RenderTask task = Stage::GetCurrent().GetRenderTaskList().CreateTask(); @@ -644,6 +711,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker task.SetRefreshRate( RenderTask::REFRESH_ONCE ); task.FinishedSignal().Connect( this, &AtlasRenderer::Impl::RenderComplete ); actor.Add( subActor ); + return actor; } @@ -665,39 +733,46 @@ struct AtlasRenderer::Impl : public ConnectionTracker } } - RenderableActor mActor; ///< The actor parent which renders the text + Actor mActor; ///< The actor parent which renders the text AtlasGlyphManager mGlyphManager; ///< Glyph Manager to handle upload and caching Vector< uint32_t > mImageIds; ///< A list of imageIDs used by the renderer TextAbstraction::FontClient mFontClient; ///> The font client used to supply glyph information - ShaderEffect mBasicShader; ///> Shader used to render L8 glyphs - ShaderEffect mBgraShader; ///> Shader used to render BGRA glyphs - ShaderEffect mBasicShadowShader; ///> Shader used to render drop shadow into buffer + Shader mShader; ///> Shader used to render drop shadow buffer textures + Shader mShadowShader; ///> Shader used to render drop shadow into buffer std::vector< MaxBlockSize > mBlockSizes; ///> Maximum size needed to contain a glyph in a block within a new atlas - std::vector< MeshData::FaceIndex > mFace; ///> Face indices for a quad + std::vector< uint32_t > mFace; ///> Face indices for a quad + Property::Map mQuadVertexFormat; + Property::Map mQuadIndexFormat; }; Text::RendererPtr AtlasRenderer::New() { + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Text::AtlasRenderer::New()\n" ); + return Text::RendererPtr( new AtlasRenderer() ); } -RenderableActor AtlasRenderer::Render( Text::ViewInterface& view ) +Actor AtlasRenderer::Render( Text::ViewInterface& view ) { - UnparentAndReset( mImpl->mActor ); - Text::Length numberOfGlyphs = view.GetNumberOfGlyphs(); + Length numberOfGlyphs = view.GetNumberOfGlyphs(); - if( numberOfGlyphs > 0 ) + if( numberOfGlyphs > 0u ) { Vector glyphs; glyphs.Resize( numberOfGlyphs ); - view.GetGlyphs( &glyphs[0], 0, numberOfGlyphs ); - std::vector positions; positions.resize( numberOfGlyphs ); - view.GetGlyphPositions( &positions[0], 0, numberOfGlyphs ); + + numberOfGlyphs = view.GetGlyphs( glyphs.Begin(), + &positions[0], + 0u, + numberOfGlyphs ); + glyphs.Resize( numberOfGlyphs ); + positions.resize( numberOfGlyphs ); + mImpl->AddGlyphs( positions, glyphs, view.GetTextColor(), @@ -707,6 +782,7 @@ RenderableActor AtlasRenderer::Render( Text::ViewInterface& view ) view.GetUnderlineColor(), view.GetUnderlineHeight() ); } + return mImpl->mActor; } @@ -719,4 +795,4 @@ AtlasRenderer::AtlasRenderer() AtlasRenderer::~AtlasRenderer() { delete mImpl; -} \ No newline at end of file +}