- Actor GenerateShadow( MeshRecord& meshRecord,
- const Vector2& shadowOffset,
- const Vector4& shadowColor )
- {
- // Scan vertex buffer to determine width and height of effect buffer needed
- 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 )
- {
- if ( verts[ i ].mPosition.x < tlx )
- {
- tlx = verts[ i ].mPosition.x;
- }
- if ( verts[ i ].mPosition.y < tly )
- {
- tly = verts[ i ].mPosition.y;
- }
- if ( verts[ i ].mPosition.x > brx )
- {
- brx = verts[ i ].mPosition.x;
- }
- if ( verts[ i ].mPosition.y > bry )
- {
- bry = verts[ i ].mPosition.y;
- }
- }
-
- float width = brx - tlx;
- float height = bry - tly;
- float divWidth = TWO / width;
- float divHeight = TWO / height;
-
- // Create a buffer to render to
- meshRecord.mBuffer = FrameBufferImage::New( width, height );
-
- // 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( mGlyphManager.GetEffectBufferShader() );
- material.AddSampler( sampler );
-
- Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, material );
-
- // Ensure shadow is behind the text...
- renderer.SetDepthIndex( CONTENT_DEPTH_INDEX + mDepth - 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 )
- {
- 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 );
- }
-
- 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( mGlyphManager.GetGlyphShadowShader() );
- 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 );
-
- // Create a render task to render the effect
- RenderTask task = Stage::GetCurrent().GetRenderTaskList().CreateTask();
- task.SetTargetFrameBuffer( meshRecord.mBuffer );
- task.SetSourceActor( subActor );
- task.SetClearEnabled( true );
- task.SetClearColor( Vector4::ZERO );
- task.SetExclusive( true );
- task.SetRefreshRate( RenderTask::REFRESH_ONCE );
- task.FinishedSignal().Connect( this, &AtlasRenderer::Impl::RenderComplete );
- actor.Add( subActor );
-
- return actor;
- }
-
- void RenderComplete( RenderTask& renderTask )
- {
- // Disconnect and remove this single shot render task
- renderTask.FinishedSignal().Disconnect( this, &AtlasRenderer::Impl::RenderComplete );
- Stage::GetCurrent().GetRenderTaskList().RemoveTask( renderTask );
-
- // Get the actor used for render to buffer and remove it from the parent
- Actor renderActor = renderTask.GetSourceActor();
- if ( renderActor )
- {
- Actor parent = renderActor.GetParent();
- if ( parent )
- {
- parent.Remove( renderActor );
- }
- }
- }
-
- Actor mActor; ///< The actor parent which renders the text
- AtlasGlyphManager mGlyphManager; ///< Glyph Manager to handle upload and caching
- TextAbstraction::FontClient mFontClient; ///> The font client used to supply glyph information
- std::vector< MaxBlockSize > mBlockSizes; ///> Maximum size needed to contain a glyph in a block within a new atlas
- std::vector< uint32_t > mFace; ///> Face indices for a quad
- Vector< TextCacheEntry > mTextCache;
- Property::Map mQuadVertexFormat;
- Property::Map mQuadIndexFormat;
- int mDepth;