2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-toolkit/internal/text/rendering/vector-based/vector-based-renderer.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali/devel-api/rendering/renderer.h>
24 #include <dali/devel-api/rendering/geometry.h>
25 #include <dali/devel-api/text-abstraction/font-client.h>
28 #include <dali-toolkit/internal/text/glyph-run.h>
29 #include <dali-toolkit/internal/text/text-view.h>
30 #include <dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.h>
31 #include <dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas.h>
32 #include <dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas-share.h>
35 using namespace Dali::Toolkit;
36 using namespace Dali::Toolkit::Text;
41 #if defined(DEBUG_ENABLED)
42 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_RENDERING");
45 const float DEFAULT_POINT_SIZE = 13.f;
56 void AddVertex( Vector<Vertex2D>& vertices, float x, float y, float u, float v, const Vector4& color )
63 meshVertex.color = color;
64 vertices.PushBack( meshVertex );
67 void AddTriangle( Vector<unsigned int>& indices, unsigned int v0, unsigned int v1, unsigned int v2 )
69 indices.PushBack( v0 );
70 indices.PushBack( v1 );
71 indices.PushBack( v2 );
74 bool CreateGeometry( const Vector<GlyphInfo>& glyphs,
75 unsigned int numberOfGlyphs,
76 const Vector<Vector2>& positions,
79 VectorBlobAtlas& atlas,
80 Dali::TextAbstraction::FontClient& fontClient,
81 Vector< Vertex2D >& vertices,
82 Vector< unsigned int >& indices,
83 const Vector4* const colorsBuffer,
84 const ColorIndex* const colorIndicesBuffer,
85 const Vector4& defaultColor )
87 // Whether the default color is used.
88 const bool useDefaultColor = ( NULL == colorsBuffer );
90 bool atlasFull( false );
92 for( unsigned int i=0, idx=0; i<numberOfGlyphs && !atlasFull; ++i )
94 if( glyphs[i].width > 0 &&
95 glyphs[i].height > 0 )
97 bool foundBlob( true );
99 BlobCoordinate blobCoords[4];
101 if( ! atlas.FindGlyph( glyphs[i].fontId, glyphs[i].index, blobCoords ) )
104 VectorBlob* blob( NULL );
105 unsigned int blobLength( 0 );
106 unsigned int nominalWidth( 0 );
107 unsigned int nominalHeight( 0 );
108 fontClient.CreateVectorBlob( glyphs[i].fontId, glyphs[i].index, blob, blobLength, nominalWidth, nominalHeight );
110 if( 0 != blobLength )
112 bool glyphAdded = atlas.AddGlyph( glyphs[i].fontId, glyphs[i].index, blob, blobLength, nominalWidth, nominalHeight, blobCoords );
114 foundBlob = glyphAdded;
115 atlasFull = !glyphAdded;
125 // Get the color of the character.
126 const ColorIndex colorIndex = useDefaultColor ? 0u : *( colorIndicesBuffer + i );
127 const Vector4& color = ( useDefaultColor || ( 0u == colorIndex ) ) ? defaultColor : *( colorsBuffer + colorIndex - 1u );
129 const float x1( xOffset + positions[i].x );
130 const float x2( xOffset + positions[i].x + glyphs[i].width );
131 const float y1( yOffset + positions[i].y );
132 const float y2( yOffset + positions[i].y + glyphs[i].height );
134 AddVertex( vertices, x1, y2, blobCoords[0].u, blobCoords[0].v, color );
135 AddVertex( vertices, x1, y1, blobCoords[1].u, blobCoords[1].v, color );
136 AddVertex( vertices, x2, y2, blobCoords[2].u, blobCoords[2].v, color );
137 AddTriangle( indices, idx, idx+1, idx+2 );
140 AddVertex( vertices, x1, y1, blobCoords[1].u, blobCoords[1].v, color );
141 AddVertex( vertices, x2, y2, blobCoords[2].u, blobCoords[2].v, color );
142 AddVertex( vertices, x2, y1, blobCoords[3].u, blobCoords[3].v, color );
143 AddTriangle( indices, idx, idx+1, idx+2 );
149 // If the atlas is still partially empty, all the glyphs were added
153 } // unnamed namespace
155 struct VectorBasedRenderer::Impl
159 mFontClient = TextAbstraction::FontClient::Get();
161 mQuadVertexFormat[ "aPosition" ] = Property::VECTOR2;
162 mQuadVertexFormat[ "aTexCoord" ] = Property::VECTOR2;
163 mQuadVertexFormat[ "aColor" ] = Property::VECTOR4;
164 mQuadIndexFormat[ "indices" ] = Property::INTEGER;
167 Actor mActor; ///< The actor parent which renders the text
169 TextAbstraction::FontClient mFontClient; ///> The font client used to supply glyph information
171 Property::Map mQuadVertexFormat; ///> Describes the vertex format for text
172 Property::Map mQuadIndexFormat; ///> Describes the index format for text
174 Shader mShaderEffect;
176 IntrusivePtr<VectorBlobAtlas> mAtlas;
179 Text::RendererPtr VectorBasedRenderer::New()
181 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Text::VectorBasedRenderer::New()\n" );
183 return Text::RendererPtr( new VectorBasedRenderer() );
186 Actor VectorBasedRenderer::Render( Text::ViewInterface& view, int /*depth*/ )
188 UnparentAndReset( mImpl->mActor );
190 mImpl->mActor = Actor::New();
191 mImpl->mActor.SetParentOrigin( ParentOrigin::CENTER );
192 mImpl->mActor.SetSize( view.GetControlSize() );
193 mImpl->mActor.SetColor( Color::WHITE );
194 #if defined(DEBUG_ENABLED)
195 mImpl->mActor.SetName( "Text renderable actor" );
198 Length numberOfGlyphs = view.GetNumberOfGlyphs();
200 if( numberOfGlyphs > 0u )
202 Vector<GlyphInfo> glyphs;
203 glyphs.Resize( numberOfGlyphs );
205 Vector<Vector2> positions;
206 positions.Resize( numberOfGlyphs );
208 numberOfGlyphs = view.GetGlyphs( glyphs.Begin(),
212 glyphs.Resize( numberOfGlyphs );
213 positions.Resize( numberOfGlyphs );
215 const Vector4* const colorsBuffer = view.GetColors();
216 const ColorIndex* const colorIndicesBuffer = view.GetColorIndices();
217 const Vector4& defaultColor = view.GetTextColor();
219 Vector< Vertex2D > vertices;
220 Vector< unsigned int > indices;
222 const Vector2& controlSize = view.GetControlSize();
223 float xOffset = controlSize.width * -0.5f;
224 float yOffset = controlSize.height * -0.5f;
226 if( ! mImpl->mAtlas ||
227 mImpl->mAtlas->IsFull() )
229 VectorBlobAtlasShare atlasShare = VectorBlobAtlasShare::Get();
230 mImpl->mAtlas = atlasShare.GetCurrentAtlas();
233 // First try adding the glyphs to the previous shared atlas
234 bool allGlyphsAdded = CreateGeometry( glyphs,
247 if( ! allGlyphsAdded )
249 // The current atlas is full, abandon it and use a new one
250 mImpl->mAtlas.Reset();
254 VectorBlobAtlasShare atlasShare = VectorBlobAtlasShare::Get();
255 mImpl->mAtlas = atlasShare.GetNewAtlas();
257 CreateGeometry( glyphs,
269 // Return value ignored; using more than an entire new atlas is not supported
272 if( 0 != vertices.Count() )
274 PropertyBuffer quadVertices = PropertyBuffer::New( mImpl->mQuadVertexFormat );
275 PropertyBuffer quadIndices = PropertyBuffer::New( mImpl->mQuadIndexFormat );
277 quadVertices.SetData( &vertices[ 0 ], vertices.Size() );
278 quadIndices.SetData( &indices[ 0 ], indices.Size() );
280 Geometry quadGeometry = Geometry::New();
281 quadGeometry.AddVertexBuffer( quadVertices );
282 quadGeometry.SetIndexBuffer( quadIndices );
284 TextureSet texture = mImpl->mAtlas->GetTextureSet();
286 const Vector4 atlasInfo = mImpl->mAtlas->GetInfo();
287 mImpl->mShaderEffect = GlyphyShader::New( atlasInfo );
289 Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, mImpl->mShaderEffect );
290 renderer.SetTextures( texture );
291 mImpl->mActor.AddRenderer( renderer );
295 return mImpl->mActor;
298 VectorBasedRenderer::VectorBasedRenderer()
303 VectorBasedRenderer::~VectorBasedRenderer()