+Actor Controller::Impl::CreateBackgroundActor()
+{
+ // NOTE: Currently we only support background color for one line left-to-right text,
+ // so the following calculation is based on one line left-to-right text only!
+
+ Actor actor;
+
+ Length numberOfGlyphs = mView.GetNumberOfGlyphs();
+ if( numberOfGlyphs > 0u )
+ {
+ Vector<GlyphInfo> glyphs;
+ glyphs.Resize( numberOfGlyphs );
+
+ Vector<Vector2> positions;
+ positions.Resize( numberOfGlyphs );
+
+ // Get the line where the glyphs are laid-out.
+ const LineRun* lineRun = mModel->mVisualModel->mLines.Begin();
+ float alignmentOffset = lineRun->alignmentOffset;
+ numberOfGlyphs = mView.GetGlyphs( glyphs.Begin(),
+ positions.Begin(),
+ alignmentOffset,
+ 0u,
+ numberOfGlyphs );
+
+ glyphs.Resize( numberOfGlyphs );
+ positions.Resize( numberOfGlyphs );
+
+ const GlyphInfo* const glyphsBuffer = glyphs.Begin();
+ const Vector2* const positionsBuffer = positions.Begin();
+
+ BackgroundMesh mesh;
+ mesh.mVertices.Reserve( 4u * glyphs.Size() );
+ mesh.mIndices.Reserve( 6u * glyphs.Size() );
+
+ const Vector2 textSize = mView.GetLayoutSize();
+
+ const float offsetX = textSize.width * 0.5f;
+ const float offsetY = textSize.height * 0.5f;
+
+ const Vector4* const backgroundColorsBuffer = mView.GetBackgroundColors();
+ const ColorIndex* const backgroundColorIndicesBuffer = mView.GetBackgroundColorIndices();
+ const Vector4& defaultBackgroundColor = mModel->mVisualModel->IsBackgroundEnabled() ? mModel->mVisualModel->GetBackgroundColor() : Color::TRANSPARENT;
+
+ Vector4 quad;
+ uint32_t numberOfQuads = 0u;
+
+ for( uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i )
+ {
+ const GlyphInfo& glyph = *( glyphsBuffer + i );
+
+ // Get the background color of the character.
+ // The color index zero is reserved for the default background color (i.e. Color::TRANSPARENT)
+ const ColorIndex backgroundColorIndex = ( nullptr == backgroundColorsBuffer ) ? 0u : *( backgroundColorIndicesBuffer + i );
+ const Vector4& backgroundColor = ( 0u == backgroundColorIndex ) ? defaultBackgroundColor : *( backgroundColorsBuffer + backgroundColorIndex - 1u );
+
+ // Only create quads for glyphs with a background color
+ if ( backgroundColor != Color::TRANSPARENT )
+ {
+ const Vector2 position = *( positionsBuffer + i );
+
+ if ( i == 0u && glyphSize == 1u ) // Only one glyph in the whole text
+ {
+ quad.x = position.x;
+ quad.y = 0.0f;
+ quad.z = quad.x + std::max( glyph.advance, glyph.xBearing + glyph.width );
+ quad.w = textSize.height;
+ }
+ else if ( i == 0u ) // The first glyph in the whole text
+ {
+ quad.x = position.x;
+ quad.y = 0.0f;
+ quad.z = quad.x - glyph.xBearing + glyph.advance;
+ quad.w = textSize.height;
+ }
+ else if ( i == glyphSize - 1u ) // The last glyph in the whole text
+ {
+ quad.x = position.x - glyph.xBearing;
+ quad.y = 0.0f;
+ quad.z = quad.x + std::max( glyph.advance, glyph.xBearing + glyph.width );
+ quad.w = textSize.height;
+ }
+ else // The glyph in the middle of the text
+ {
+ quad.x = position.x - glyph.xBearing;
+ quad.y = 0.0f;
+ quad.z = quad.x + glyph.advance;
+ quad.w = textSize.height;
+ }
+
+ BackgroundVertex vertex;
+
+ // Top left
+ vertex.mPosition.x = quad.x - offsetX;
+ vertex.mPosition.y = quad.y - offsetY;
+ vertex.mColor = backgroundColor;
+ mesh.mVertices.PushBack( vertex );
+
+ // Top right
+ vertex.mPosition.x = quad.z - offsetX;
+ vertex.mPosition.y = quad.y - offsetY;
+ vertex.mColor = backgroundColor;
+ mesh.mVertices.PushBack( vertex );
+
+ // Bottom left
+ vertex.mPosition.x = quad.x - offsetX;
+ vertex.mPosition.y = quad.w - offsetY;
+ vertex.mColor = backgroundColor;
+ mesh.mVertices.PushBack( vertex );
+
+ // Bottom right
+ vertex.mPosition.x = quad.z - offsetX;
+ vertex.mPosition.y = quad.w - offsetY;
+ vertex.mColor = backgroundColor;
+ mesh.mVertices.PushBack( vertex );
+
+ // Six indices in counter clockwise winding
+ mesh.mIndices.PushBack( 1u + 4 * numberOfQuads );
+ mesh.mIndices.PushBack( 0u + 4 * numberOfQuads );
+ mesh.mIndices.PushBack( 2u + 4 * numberOfQuads );
+ mesh.mIndices.PushBack( 2u + 4 * numberOfQuads );
+ mesh.mIndices.PushBack( 3u + 4 * numberOfQuads );
+ mesh.mIndices.PushBack( 1u + 4 * numberOfQuads );
+
+ numberOfQuads++;
+ }
+ }
+
+ // Only create the background actor if there are glyphs with background color
+ if ( mesh.mVertices.Count() > 0u )
+ {
+ Property::Map quadVertexFormat;
+ quadVertexFormat[ "aPosition" ] = Property::VECTOR2;
+ quadVertexFormat[ "aColor" ] = Property::VECTOR4;
+
+ VertexBuffer quadVertices = VertexBuffer::New( quadVertexFormat );
+ quadVertices.SetData( &mesh.mVertices[ 0 ], mesh.mVertices.Size() );
+
+ Geometry quadGeometry = Geometry::New();
+ quadGeometry.AddVertexBuffer( quadVertices );
+ quadGeometry.SetIndexBuffer( &mesh.mIndices[ 0 ], mesh.mIndices.Size() );
+
+ if( !mShaderBackground )
+ {
+ mShaderBackground = Shader::New( VERTEX_SHADER_BACKGROUND, FRAGMENT_SHADER_BACKGROUND );
+ }
+
+ Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, mShaderBackground );
+ renderer.SetProperty( Dali::Renderer::Property::BLEND_MODE, BlendMode::ON );
+ renderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT );
+
+ actor = Actor::New();
+ actor.SetProperty( Dali::Actor::Property::NAME, "TextBackgroundColorActor" );
+ actor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+ actor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+ actor.SetProperty( Actor::Property::SIZE, textSize );
+ actor.SetProperty( Actor::Property::COLOR_MODE, USE_OWN_MULTIPLY_PARENT_COLOR );
+ actor.AddRenderer( renderer );
+ }
+ }
+
+ return actor;
+}
+